Operations
Bootstrap from zero
Section titled “Bootstrap from zero”The database itself is the only external prerequisite — iam.svc never creates databases and never issues DDL at serve time.
iam.svc config generate bootstrap-dev > .iam.yaml
iam.svc data bootstrap -f .iam.yaml # tenant plane: schema + tables + ledgeriam.svc data bootstrap -f .iam.yaml --tenant superadmin # control plane: registry, operators, keyring --firstname Admin --lastname Useriam.svc -f .iam.yaml -l info # serve on 127.0.0.1:5030data bootstrapcreates the schema if missing and applies one diff-based plan, lock-less and idempotent — safe to re-run.seedcreates the control-plane superadmin and a tenant admin through the engine (hashing and access rules apply); idempotent. The HTTP alternative for the very first superadmin isPOST /auth/bootstrap, gated bybootstrap.tokenand self-closing.- Reserved planes migrate like tenants:
--tenant <c>:<p>:<e>:superadmin, or--scope shared.
Onboarding a product tenant
Section titled “Onboarding a product tenant”- Add the tenant node to the tenant hive (dbpool with
schema:,meta.url— see Configuration). - Ensure the database exists (IaC — not iam’s job).
- Register + provision, either over HTTP (
POST /superadmin/registry/tenants, then…/provision) or in one CLI step:
iam.svc tenant provision -f .iam.yaml --tenant acme:forge:prod:tenant-a \Register → bootstrap → seed → activate, idempotent. There is no product allow-list to edit — a product registers itself on first request. 4. The tenant admin logs in with the tenant’s own CPET headers.
Schema migrations
Section titled “Schema migrations”Steady-state changes are plan-based, risk-gated, and audited:
iam.svc data plan generate -f .iam.yaml --tenant <cpet> [--allow-drops]iam.svc data plan show <plan-id>iam.svc data plan apply <plan-id> --confirm-risk medium [--dry-run]iam.svc data seed run|listiam.svc data applied list --plan-id <id>All commands take -f <config> --tenant <cpet> --datastore --output table|json and operate on one CPET at a time. Plan apply over HTTP requires a superadmin token (403 v2.requires_superadmin is working as intended).
Session operations
Section titled “Session operations”- Managed tenants: instant revoke (
POST /internal/session/revoke), enumerate / log-out-everywhere (/list), fixation rotation (/rotate). - Stateless tenants: revocation only via refresh-family logout; access tokens live out their 15 minutes.
- Concurrency is enforced atomically per (CPET, principal):
on_limit: reject→ 409-class error;evict_oldestrevokes the oldest session with reasonconcurrent_evict.
Impersonation runbook
Section titled “Impersonation runbook”- Grant the operator
impersonate-readonlyorimpersonate(neither is implied by root) plus a grant row for the target tenant. - The target user must have
allow_impersonation: true(default false). POST /superadmin/impersonatewith a mandatoryreason.- The session is force-managed — the user and tenant admin can see it and kill it.
- Break-glass without user opt-in is deliberately not an API — that path is direct DB access with your own change control.
Audit and hardening
Section titled “Audit and hardening”- Every auth flow emits before/after events on the auth event bus; wire an event logger to persist them (the default is a no-op). Script hooks (pointcuts) can react to auth events.
- Rate limits on login/MFA/reset/magic/token-exchange/API-key issue; constant-cost hashing on the user-not-found path; PKCE + 10-minute OAuth state; single-use TOTP; refresh reuse detection.
Known gaps
Section titled “Known gaps”- No
/health//ready— probe TCP or an auth flow. - Metrics are defined but not yet recorded.
- JWKS caps at 100 keys, WebAuthn credentials at 50, silently.
- Generated-key rotation has no endpoint/schedule yet.
- Refresh-token tombstones lack a retention sweep.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause / action |
|---|---|
500 issue_failed after an upgrade | Stale refresh-token schema — iam.svc data plan generate + apply |
400 invalid tenant | CPET headers match no configured tenant node |
500 engine_unavailable | CPET has no resolvable tenant config, or its database is down |
401 on /rest with “no configured URL for issuer iam” | jwks.issuers.iam missing or nested under hives: — it must be top-level |
403 v2.requires_superadmin on plan apply | By design — use a superadmin token |
Login works but /rest 401s in another service | That service lacks the jwks.issuers.iam entry, or its CPET headers don’t match the token’s tenant claim |