Skip to content

Operate Vouch with the admin UI and CLI

Everything an operator does goes through the /admin/* API, which requires an account with is_admin. There are two front ends for it: the admin area of the web client (#/admin/…, shown only to admins) and the vouch CLI (server/: uv run vouch …). They expose the same information; use whichever is at hand.

Register with the bootstrap token (VOUCH_ADMIN_BOOTSTRAP_TOKEN; in production it lives in AWS Secrets Manager under vouch/app):

Terminal window
uv run vouch register <name> --admin-token <token> --adult --accept-notice --url https://api.<domain>

Or promote nobody: the token is the only way to mint an admin, on purpose.

vouch login / vouch register store a refresh cookie for one API URL in $XDG_CONFIG_HOME/vouch/cli.json; every command exchanges it for a fresh access token (and a rotated cookie), so revoking that session from the web client’s account tab locks the CLI out too. vouch logout revokes it. --url or VOUCH_URL selects the deployment.

Question Web CLI
Is the service healthy? Counts, matcher, migration, settings #/admin/overview vouch admin overview
Who is this user? #/admin/users → row vouch admin users --q name, vouch admin user <id>
Why is a pair stuck? #/admin/pairs → row vouch admin pairs --state awaiting_one, vouch admin pair <id>
Anything reported? #/admin/reports vouch admin reports
What code was texted (dev only)? #/admin/sms vouch admin sms-outbox
Run a full matcher pass now #/admin/system vouch admin run-matcher
Who did what as an admin #/admin/audit vouch api GET /admin/audit
Anything the UI does not have /docs (Swagger) vouch api GET /admin/…
  1. A user files a report from a match (POST /me/reports). It appears in the reports queue with both usernames.
  2. Decide. vouch admin ban <user-id> "<reason>" (or the button in the user drawer) sets banned_at, revokes every session, and makes each of the user’s requests answer 403 account_banned. unban lifts it. delete-user removes the account and everything attached.
  3. vouch admin resolve <report-id> "<what you did>" closes the report.

Reports survive a ban; deleting either account removes them, and resolved reports are purged after VOUCH_REPORT_RETENTION_DAYS. Every admin write (ban, unban, delete, resolve, run matcher) is recorded in the audit log with the admin’s id and username.

Pairs are created inline when a user publishes or changes preferences (one query against every compatible user). The background loop, every VOUCH_MATCHER_INTERVAL_SECONDS, does the whole-userbase safety-net pass in one replica: the one holding a Postgres advisory lock. The overview shows runs, skipped (this replica lost the election) and the last result or error. “Run matcher” forces a full pass from the request path.

With VOUCH_SMS_BACKEND=log the API keeps the last 50 codes it “sent” in memory (numbers masked to two digits). That is how local development, the test suite, vouch sim demo and scripts/demo_e2e.py complete phone verification. With sns the endpoint answers 404 outbox_unavailable; codes only exist on the recipient’s phone.

  • Access / portability: the user’s account tab → download my data, or vouch api GET /me/export as that user.
  • Erasure: the user deletes their own account, or an admin runs vouch admin delete-user <id>.