--- 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.