CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Test (windows-latest) (push) Canceled after 0s
CI / Storage tests on PostgreSQL (push) Canceled after 0s
CI / Complement (federation off) (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
CI / Smoke test the binary (push) Canceled after 0s
Implements PLAN.md Phase 9. internal/appservice reads registration files (appservice.config_files), matches namespaces the way Synapse does (anchored at the start), and delivers events to each service as transactions read from the roomserver's event stream at a cursor kept in appservice_state. A transaction in flight is recorded, so after a restart it is resent under the same ID; failures back off from 2s to 5m, and a successful ping cuts the backoff short. In the Client-Server API an as_token acts as the service's sender or, with ?user_id=, as any existing user in its namespace. Services register and log in their users with m.login.application_service; exclusive user and alias namespaces are refused to everybody else with M_EXCLUSIVE. Unknown aliases and users in a namespace are asked of the service first. The ping endpoint reports M_URL_NOT_SET, M_BAD_STATUS, M_CONNECTION_FAILED and M_CONNECTION_TIMEOUT. Services' own requests, and their users' when rate_limited is false, skip the rate limiter. Users can change their password (POST /account/password) and deactivate their account (POST /account/deactivate), both behind the password. Deactivation revokes tokens, deletes devices, optionally erases the profile and leaves every room through a new userapi.AccountObserver. The admin API is complete: user detail, the admin flag, deactivation and reactivation, password resets, devices, media quotas (media.max_user_storage_bytes plus per-user overrides), registration tokens with use limits and expiry (registration.require_token), server notices (internal/servernotices, server_notices.*), an editor for the federation allow/deny lists persisted in server_settings, a delivery view of the application services, and an audit log of every change. Migration 0011 adds the registration token, server notice room, media quota, audit log and appservice cursor tables. Policy lists are now returned sorted. The Complement entrypoint loads the registrations Complement mounts in /complement/appservice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
83 lines
3.4 KiB
SQL
83 lines
3.4 KiB
SQL
-- Phase 9: application services, and the parts of the admin API that keep
|
|
-- state of their own — registration tokens, server notice rooms, media
|
|
-- quotas and the audit log.
|
|
|
|
-- Registration tokens made through the admin API. The tokens in the config
|
|
-- file are not here: they have no use count or expiry to keep.
|
|
--
|
|
-- uses_allowed is NULL for a token that may be used any number of times.
|
|
-- completed counts the registrations that spent it; a registration takes
|
|
-- its use when the account is created, not when the stage is passed, so an
|
|
-- abandoned sign-up costs nothing.
|
|
CREATE TABLE IF NOT EXISTS admin_registration_tokens (
|
|
token TEXT NOT NULL PRIMARY KEY,
|
|
uses_allowed BIGINT,
|
|
completed BIGINT NOT NULL DEFAULT 0,
|
|
-- 0 means the token never expires.
|
|
expires_at_ms BIGINT NOT NULL DEFAULT 0,
|
|
created_at_ms BIGINT NOT NULL
|
|
);
|
|
|
|
-- The room each user gets their server notices in. One per user: a second
|
|
-- notice goes into the same room, and a user who left it is invited back.
|
|
CREATE TABLE IF NOT EXISTS admin_server_notice_rooms (
|
|
localpart TEXT NOT NULL PRIMARY KEY,
|
|
room_id TEXT NOT NULL
|
|
);
|
|
|
|
-- A user's media quota, where the admin API set one. Users without a row
|
|
-- get media.max_user_storage_bytes. max_bytes 0 is no limit, the same as
|
|
-- the config value.
|
|
CREATE TABLE IF NOT EXISTS media_quotas (
|
|
user_id TEXT NOT NULL PRIMARY KEY,
|
|
max_bytes BIGINT NOT NULL
|
|
);
|
|
|
|
-- Usage is summed over a user's uploads, so it wants an index that starts
|
|
-- with the uploader.
|
|
CREATE INDEX IF NOT EXISTS media_repository_user_idx
|
|
ON media_repository (user_id, media_origin);
|
|
|
|
-- The audit log: one row per change made through the admin API. id is
|
|
-- handed out by admin_sequences inside the writing transaction, for the
|
|
-- reason the roomserver's stream positions are (0003): no engine-specific
|
|
-- autoincrement, and no gaps.
|
|
CREATE TABLE IF NOT EXISTS admin_sequences (
|
|
name TEXT NOT NULL PRIMARY KEY,
|
|
value BIGINT NOT NULL
|
|
);
|
|
|
|
INSERT INTO admin_sequences (name, value) VALUES ('audit', 0) ON CONFLICT (name) DO NOTHING;
|
|
|
|
CREATE TABLE IF NOT EXISTS admin_audit_log (
|
|
id BIGINT NOT NULL PRIMARY KEY,
|
|
ts_ms BIGINT NOT NULL,
|
|
-- The admin who made the change, as a full user ID.
|
|
actor TEXT NOT NULL,
|
|
-- What was done, e.g. "user.deactivate"; see docs/admin-api.md.
|
|
action TEXT NOT NULL,
|
|
-- What it was done to: a user ID, a room ID, a token. Empty for a
|
|
-- server-wide change.
|
|
target TEXT NOT NULL DEFAULT '',
|
|
details_json TEXT NOT NULL DEFAULT '{}'
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS admin_audit_log_actor_idx ON admin_audit_log (actor, id);
|
|
CREATE INDEX IF NOT EXISTS admin_audit_log_action_idx ON admin_audit_log (action, id);
|
|
|
|
-- Where each application service is in the event stream.
|
|
--
|
|
-- stream_pos is the last stream position whose events have been delivered
|
|
-- (or found to be of no interest). txn_to is non-zero while a transaction
|
|
-- is in flight: it is the top of the events in it, and txn_id its ID, so
|
|
-- that after a restart the same transaction — same ID, same events — is
|
|
-- sent again rather than a new one that overlaps it. An application
|
|
-- service deduplicates by transaction ID, and only a retry that is
|
|
-- identical can be deduplicated.
|
|
CREATE TABLE IF NOT EXISTS appservice_state (
|
|
as_id TEXT NOT NULL PRIMARY KEY,
|
|
stream_pos BIGINT NOT NULL,
|
|
txn_id BIGINT NOT NULL DEFAULT 0,
|
|
txn_to BIGINT NOT NULL DEFAULT 0
|
|
);
|