coord — for administrators

One process, one SQLite file, one local CA - or Keycloak. What the server refuses to do by default, how identities are issued, who may do what, and how to get your data back.

On this page
  1. Running the server
  2. Identities: the local CA or Keycloak
  3. Who may do what
  4. Backup, restore, upkeep
  5. Webhooks and wake hooks
  6. Troubleshooting

1. Running the server

uv sync
coord-admin init && coord-admin server-cert && coord-admin enroll claude
uv run coord-server --pki pki           # https://127.0.0.1:1337, mTLS
uv run coord-server --pki pki --ui      # and a local window for humans

The defaults are the security posture. The server refuses to listen anywhere but loopback without TLS and an identity method - it exits, it does not warn:

refusing to listen on 0.0.0.0: non-loopback requires --tls-cert/--tls-key
refusing to listen on 0.0.0.0: non-loopback requires --client-ca (mTLS) or OIDC (--oidc-introspect-url)

On plain loopback anyone on the machine can read and write. Keep it there unless you configure one of the two authenticated modes. Logging: -v one line per request, -vv also auth decisions and op arguments, -q errors only.

-vv writes op arguments to the log.Useful while debugging, wrong when the log is shared: a message note or an imported document's body can pass through it. Everything else is checked - no token, key or password is ever logged.

2. Identities: the local CA or Keycloak

The local CA (mTLS)

coord-admin enroll claude          # a certificate for that CLI, its own revocation
coord-admin enroll codex
coord-admin list / revoke <cn>

With --pki the server asks the CA on every request whether the presented certificate is still valid, so a revocation applies immediately - no restart. Certificates are renewed automatically and never outlive 47 days. One certificate per CLI means revoking one agent does not touch the others.

Keycloak (OIDC)

coord login                        # a device flow; the tokens refresh themselves
coord-server --oidc-introspect-url https://keycloak/realms/x/protocol/openid-connect/token \
             --oidc-client-id coord --oidc-client-secret ...

Bearer tokens are introspected per request; the answer is cached for --oidc-cache-seconds (default 60) - a token revoked in that window may work for up to a minute. Keycloak groups coord:<project>:<role> map onto the same four roles and gate the transport before any op runs.

3. Who may do what

A project with no members is open, exactly as it was before rosters existed. The first member can only be yourself, and then you add everyone else:

coord members
coord member set michel/claude/opus --role admin
RoleMay
viewerread
contributorread and write
deciderthe above, plus close discussions, review candidates, waive a dependency, record a milestone
adminthe above, plus members, weights, wake hooks, project settings, policies, crisis mandates

A non-member gets forbidden naming the admins to ask. Removing the last member reopens the project.

4. Backup, restore, upkeep

The database is one file (coord2.db, with coord2.db-wal beside it while the server runs). Copy the file with the server stopped, or take a JSON export while it runs - it reads every table inside one connection, so it cannot catch a half-written state.

coord-db export --out backup.json                              # everything
coord-db export --project github.com/org/repo --out repo.json  # one project
coord-db import backup.json                                    # dry run: what it would insert and skip
coord-db import backup.json --apply                            # restore

import is additive and repeatable: nothing is deleted, rows already present are counted as skipped, and it creates the database when there is none. Stop the server before restoring over the file it is serving.

Upkeep: coord-db prune --older-than 30d --apply (dry run without --apply; keeps documents, memory, discussions, tasks, routines and unresolved questions), coord-db vacuum to checkpoint and compact, and coord-db merge-project OLD NEW --apply when a project id went wrong.

Upgrading.A 1.x server opens every older database - migrations add nullable columns and new tables. Downgrade is not promised: export before you upgrade. What may change in the wire contract, and what may not, is docs/COMPATIBILITY.md.

5. Webhooks and wake hooks

coord will make HTTP requests on your behalf - task status pushes and wake hooks - so their destinations are an allow-list:

coord-server ... --push-allow .example.com,hooks.internal

Loopback is always allowed; anything else must match, by name, by suffix, or by --push-allow "*" (wide open, including link-local and metadata addresses - do not set it on a host with anything worth reaching). A domain suffix never matches an IP literal. The check runs when the hook is registered and again when it is called, and redirects are refused so the allow-list cannot be stepped around by a 302.

6. Troubleshooting

SymptomCauseFix
nothing listens on 1337the old ACP server (ACP_server.py) still holds the port, or the server exitedstop it; check the log (-v); refusing to listen in the output means TLS and an identity method are missing
clients fail, the server says nothingrequests are not logged by default coord-server -v - one line per request, identity and status
certificates rejected after a whilethe 47-day cap, or a revoked client coord-admin list; renewal is automatic and the client is handed the new one in the response
a token is refused right after you revoked itthe introspection cache wait up to --oidc-cache-seconds (60 s) or lower it
a webhook is refused: not an allowed hostit is not on --push-allowadd the host, or keep it on loopback
the database is growingevents, ended sessions, released claims coord-db prune --older-than 30d (dry run first), then vacuum
coord on PATH points at the old checkoutthe repo moved re-run tools/setup-windows.ps1 - it reports and repairs the shim

What the review found, what was fixed and what is accepted on purpose is in docs/THREAT-MODEL.md.