Files
stack/docs/PRDs/2026-08-31_PRD_rev1/SEAT.1-seat-profile.md
T
jason.woltje 13968e9a8b
ci/woodpecker/pr/ci Pipeline failed
docs: PRD rev1 review Q90 — Prettier-format the bundle, add rev0 archive README
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.
2026-09-02 09:40:46 -05:00

88 lines
5.2 KiB
Markdown

---
id: SEAT.1
status: ratified
ratified: 2026-09-01 (Jason Woltje; PRD rev1 ratification PR)
---
# SEAT.1 — Seat identity, profile, and configuration
## Instance contract (register OD-48)
| File | Carries |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `profile.json` | structured identity — and, post-consolidation, the full seat record ([[DATA.1-record-authority]] §consolidation) |
| `overlay.json` | generated composition |
| seat-local `AGENTS.md` | narrative specialization |
| `SOUL.md` | persona |
## Seat configuration surface (WebUI page + CLI)
| Control | Notes |
| ---------------------- | ------------------------------------------------------------------------------------- |
| harness | from **enabled** harnesses only ([[HARN.1-harness-config]]) |
| model | constrained by the harness's available-models allowlist |
| reasoning level | |
| work dir | |
| authentication account | from configured, active accounts allowed for that harness ([[AUTHN.1-auth-accounts]]) |
| overlay | per-seat overlay only — never the role file (ROLE separation rule) |
| role binding | **separated section — see below** |
## The role-binding control (gap G5)
Role Binding is the single highest-authority action in the system,
principal-only under L2-D13. `model` is a preference. They must not share one
undifferentiated form — a privilege grant must not inherit the ceremony of a
dropdown. Requirements:
- Visually and structurally separate section on the page.
- Distinct confirmation step; re-authentication of the principal is under
consideration ([[GOV.5-open-questions]] Q-S2).
- Register OD-02/OD-03 bind the semantics: a seat has exactly one role; an
**active session never switches roles**. A role change reconfigures the
existing seat, preserves identity and history, **discards ephemeral context,
and starts a clean session**. The surface must say so before confirming.
- Role-transition history is recorded: old role, new role, reason, authorizer,
checkpoint, activation time (register OD-04).
Role changes are therefore a _different operation_ from harness/model/provider
changes ([[SESS.1-session-continuity]]) and must not share a code path.
## Seat identity and credential rules (pulled 2026-08-31 from seat-identity draft)
- **One seat = one identity = one token slot.** A second copy of a token
anywhere is drift and is removed without reading it.
- Agents never mint their own tokens; provisioning, rotation, and scope changes
are operator authority. Credential refusal is _correct behavior_ — the fix is
the seat's identity, never another seat's or a shared credential.
- Fail-closed everywhere: an empty/unreadable slot is a designed state reported
at launch; the credential helper refuses, records, notifies — never falls
back to a shared or owner credential.
- Git identity resolution order: explicit environment identity → configured
identity → git's own answer. Identity is named on every invocation and never
persisted inside a shared clone/worktree config (silent attribution rewrite).
Commit author must identify the seat that did the work.
- Tokens are compared by digest, never by value; scopes are verified from the
authority's own report, never transcription.
## E2 inputs (triage 2026-08-31; see [[GOV.2-docs-inventory]])
**Canonical ground truth**: `fleet/reference/agent-mutations.md`,
`fleet/reference/lifecycle-transitions.md` (`enabled`/`desired_state` authority),
`fleet/how-to/create-update-delete-agent.md`, `guides/fleet-local-canary.md`.
**Pending pulls**: brain `docs/guides/proposed/operations/seat-identity.md`
(credential-resolution mechanics under the OD-48 instance contract).
## Role-binding step-up ruling (Q-S2, Jason 2026-09-01)
Confirming a role-binding change requires fresh principal re-authentication no
older than 10 minutes — the same step-up bar the S2 identity-lifecycle
contract sets for account linking. An active session alone is insufficient;
this closes the stolen-session → privilege-misdirection path through the seat
surface.
## Seat record consolidation ruling (Q-D1, Jason 2026-09-01)
`launch.env` consolidates into `profile.json`: one seat record. Verified:
`mosaic-core/lib/loader.ts seatRole()` reads only the `role` key from a
generically-parsed record, so widened files are tolerated by construction.