Addresses CPS-PRD-REV1-REVIEW-Q90 findings F1 and F3 on PR #1491: F1 (format gate): `prettier --write` on the 18 rev1 bundle documents. Whitespace, table padding, list markers and emphasis delimiters only — a normalized token comparison of every file before/after shows zero content difference, so the ratified text is unchanged and no re-ratification applies. F3 (rev0 relative links): the archived rev0 PRD stays byte-identical (sha256 60cc2f98...36afdf verified) per GOV.1 archive-never-edit. A sibling docs/PRDs/2026-08-26_PRD_rev0/README.md records the digest, the original location, the owner disposition that the in-file links are intentionally historical, and a resolution table for all 9 targets (11 occurrences), each verified to exist. Future relocated archives ship the same README instead of edited bytes. F2 (test step) is investigated separately against the CI log.
5.0 KiB
id, status, ratified
| id | status | ratified |
|---|---|---|
| AUTHN.1 | ratified | 2026-09-01 (Jason Woltje; PRD rev1 ratification PR) |
AUTHN.1 — Authentication accounts
Agent-side provider credentials: the accounts seats use to reach providers. (Human login identity is D10 territory — better-auth as system of record — and is out of this section's scope.)
Authentication configuration surface (WebUI page + CLI)
| Control | Notes |
|---|---|
| in-browser OAuth establishment | the OAuth flow runs in-browser; whether the backing terminal flow is tmux-bridged is open: GOV.5-open-questions Q-N1 |
| configured accounts list | provider, mode (OAuth/API), status, holder |
| force renew | |
| deactivate | deactivated accounts drop out of every seat/harness selector |
| allowed harnesses | which harnesses may use this account |
Custody rules
- Secrets live with the credential broker (OpenBao/Vault or flat files per
deployment mode — D3), never in the brain tree, never in manifests, never in
Postgres records. Enforced role manifests declare
credentials: {store: none, providerTokens: denied}— the enforced roles hold no credentials at all; accounts are a launcher/broker concern. - Multi-account per provider is a requirement (onboarding D4 already captures multi-account enrollment).
- Account shape in the seat record (single account vs per-provider map) is open: GOV.5-open-questions Q-D2.
Credential-broker custody rules (pulled 2026-08-31, generalized from the vault draft)
- Reads require a token scoped to the needed paths; provisioning and writes go through a declared channel with documented purpose. An ordinary role never mints credentials or creates production paths.
- Canonical secret path:
environment / service / component / secret-name, lowercase kebab-case, nothing sensitive encoded in the path; environments never cross-reference each other's mounts. Standard field names (username/password,token,host/port/url). - Only the needed field is extracted into the consuming process; values are never echoed to logs or transcripts — read success is proven by field presence and digest, never by printing the value.
- Least privilege, short-lived tokens, no local copies, immediate rotation on compromise; every access audited by the broker.
E2 inputs (triage 2026-08-31; see GOV.2-docs-inventory)
Canonical ground truth: ADMIN-GUIDE/security/sso-providers.md (D10 ground
truth: better-auth + Authentik/WorkOS/Keycloak OIDC).
Pending pulls: DRAFT S2 identity-lifecycle.md (D10 + the #1430 bootstrap
fix) and custody-schema.md; brain docs/guides/proposed/operations/vault.md
(credential-broker custody rules this section states without operational detail).
S2 contract feed (extraction 2026-08-31)
Full extraction record: lane S2-EXTRACTION-2026-08-31.md (per-contract cores, dependency edges, ruling cross-checks). Pulls binding on this section (identity-lifecycle, contract 4, plus
wizard AUTHN clauses):
- better-auth tables are the only account system of record (D10); IdPs are login methods only; account creation grants nothing.
registration_modeopen/invite/closed, defaults closed post-bootstrap, forced closed during the epoch, enforced at a better-auth hook.- Bootstrap/first-admin invariant (#1430): zero-to-one-admin exactly once per
epoch, one atomic transaction, durable fail-closed
bootstrap_state, re-runnable; first-admin-via-SSO runs as a bootstrap-writer transaction, never JIT. v1 first admin is password-only — a disclosed PRD deviation. - JIT defaults OFF per-provider always; JIT users get
member, never elevated; role/authorization attributes are never mapped from IdP claims. Linking keyed(issuer, subject); explicit linking = step-up reauth ≤10 min; automatic linking gated by off-by-defaulttrusted_for_linking+ verified email. - Deactivation (ban) must bound all entry paths — live defect: the
admin-bearer-token path does not check banned status. Deletion deferred;
the existing hard-delete endpoint and
mosaic auth users deleteare mandated for removal.
Seat auth shape ruling (Q-D2, Jason 2026-09-01)
Per-provider map in profile.json, values are credential-broker references —
never secret material. The broker custody rules above govern resolution;
extraction stays field-scoped and digest-proven.