Files
stack/docs/scratchpads/1045-mosaic-cred.md
T

8.5 KiB

MC-CRED-01 / stack #1045 scratchpad

Last updated: 2026-08-05

Objective

Deliver the governed mosaic cred identity boundary for issue, scope, validation, rotation, and revocation across explicitly declared estates. The trunk-only ruling superseded the original next checkpoint: the branch is rebased onto origin/main and its PR target is main. Linked issues remain believed-fixed, pending jarvis validation after merge.

Requirements sources

  • Charter: /home/hermes/agent-work/tl-mosaic/CHARTER-MC-CRED-01-be-coder-06.md
  • Stack issues: #1045, #1043, #1044, #1047, #1049, #1013, #1007; promotion #1037; consumer #1051
  • Remote spec: jason.woltje/jarvis-brain origin/main b7687d51f4efe52e43dbcd6dc95b5554b3332957
  • Greenfield PRD v3 addenda: INV-B durable journal, INV-C visible failure diagnostics, INV-D supported fixture
  • Binding doctrine: /src/jarvis-brain/infra/fleet/FLEET-DOCTRINE.md

Plan

  1. Publish grant/validate v1 caller contract for MB-BRAIN-01.
  2. Add repo PRD requirements and preregister acceptance tests.
  3. Implement explicit estate registry, secure current file-store adapter, durable operation journal/audit, provider transport, and terminal result types.
  4. Implement grant and side-effect-free validate; then provision/wire/get/whoami/list/rotate/revoke/audit.
  5. Make git and API resolver refusals identical and fail closed under fleet context.
  6. Reconcile live HOMELAB seats through each subject credential's own /user; #1044 hold is lifted, and its fail-closed change carries the pre-registered mechanism evidence (resolver refusal marker, same-run marker positive control, confirmed-lane negative arm).
  7. Run baseline/situational tests, independent code review and mandatory independent security review, CI on the exact head, then open the PR directly against main without closing issues or claiming Jarvis validation.
  8. C1 merges first. After any base/head move, re-derive merge-base, commit set, diff, CI, reviews, and provider measurements from the replacement SHA.

Budget

No explicit token cap supplied. Working cap: keep implementation in one package plus shipped framework resolver changes and required docs/tests; avoid unrelated wrapper defect fixes and VaultWarden redesign. Escalate only if a charter requirement is technically unsatisfiable.

Decisions

  • VaultWarden is out for the agent tier per the charter verdict; phase 1 governs the existing per-identity file store.
  • Estate is explicit input and must match a configured host mapping; target host is never inferred from machine location.
  • Grant authority and basic-auth provisioning material are delegated control-plane credentials, never caller bearer material and never CLI argument/output.
  • ok, refused, error, and indeterminate are distinct machine outcomes. Security callers fail closed on all but ok, while retaining the semantic distinction.
  • Gitea write-differential resolves the subject once and binds provider identity, repository permission, and receive-pack to the same in-memory credential handle. It adds a distinct provider-confirmed read-only-principal control plus the unauthenticated control, with no ref update. The live HOMELAB negative-control subject is tl-mosaic, verified read-only on mosaicstack/stack; code and contract remain principal-agnostic.

Progress

  • Mode/intake/core guides/skills/doctrine loaded.
  • Spec repository READ confirmed under be-coder-06 from provider object.
  • Target-branch conflict resolved by the trunk-only ruling; the lane was rebased from next onto origin/main.
  • Canonical remote PRD v3 addenda re-read at new head.
  • Required issues read via Mosaic wrapper.
  • Early grant/validate contract v1 published at docs/credentials/GRANT-VALIDATE-CONTRACT.md.
  • Contract v1.1 binds transport to the same resolved principal and adds a provider-confirmed read-only-principal control.
  • Contract v1.2 distinguishes provider outage, absent identity, and rejected credential.
  • Contract v1.3 positive-controlled anonymous visibility; subsequently withdrawn as unsound for private identities.
  • Contract v1.4 implements ruling (b): subject credential's own /user, no admin/inventory authority, no implemented identity-not-found path.
  • PRD update.
  • Red-first principal-bound validate, estate-registry, file-store, provider-transport, and journal tests.
  • Implementation: validate, direct/team grant, protected delegated authority, provision/wire/get/whoami/list/rotate/revoke/audit, reverse registry, and fleet fail-closed resolver paths.
  • Review hardening: rotation returns visible open journals; team evidence records absent objects accurately; team scope is checked before/after under a host-qualified OS advisory lock with verified compensation; wire authenticates the exact seat/path/roster binding and preserves post-rename mutation semantics.
  • Independent code/security approvals on the final exact head (Codex advisory iterations are not independent approval).
  • Final exact-head CI and provider evidence.

Tests and evidence

Baseline after workspace build: package typecheck passed; Vitest 81/81 files and 1,514/1,514 tests passed. The package shell suite reached a pre-existing tracked #973 Bash 5.2 BASH_LINENO incompatibility and exited 97 before wake tests; this is baseline, not introduced by MC-CRED.

Red-first evidence:

  • principal-bound validate module absent → focused suite red;
  • incremental v1.1 run: write-capable, identity-mismatched, and receive-pack-admitted read-only controls each returned ok, causing 3/13 tests to fail for the exact control defect; after the control checks, 13/13 passed;
  • read validation absent → 2 tests failed evaluateGiteaReadValidation is not a function; after implementation, 15/15 validate tests passed;
  • estate registry, secure file resolver, Gitea transport, and audit journal each failed first because the module did not exist, then passed focused behavior suites.

Current focused evidence: 77/77 across 11 credential/command suites; package lint, typecheck, formatting, and build are green. Full package Vitest reached 1,578 passing tests and three unrelated CLI-smoke failures caused solely by the installed-version update banner writing to stderr. Provider bodies are stream-bounded and requests deadline-bounded; delegated fd input is ownership/mode/size/time bounded; token and Tea stores are private and atomic; grant mutation/read-back state is journaled.

Fail-closed resolver evidence: synthetic missing-token API and git paths each emitted stable MOSAIC_CREDENTIAL_REFUSAL with reason=no-token-for-identity and shared_path_entered=false; all 13 live token-bearing identities bypassed the shared path without over-fire in the same run. Evidence: /home/hermes/agent-work/be-coder-06/review-evidence/failclosed-postcondition.jsonl; independent verification remains tl-mosaic's obligation.

Live validation v1.4 (subject credential's own /user, no admin): population 13; CONFIRMED 8; CREDENTIAL-REJECTED 4 (coder-mos1, coder-mos2, f10-coder, merge-gate); MISMATCH 1 (mos-admin token authenticates as Mos); NOT-MEASURED 0. The four false v1.2 identity-not-found sealed journals remain immutable and are explicitly superseded by four sealed correction journals. Evidence: /home/hermes/agent-work/be-coder-06/live-validation-v1.4/.

Write differential for be-coder-06 passed with the configured read-only control and unauthenticated arm. Unit evidence proves the control arm invalidates validation when write-capable, identity-mismatched, or receive-pack-admitted.

Risks/blockers

  • The full CLI surface is broad; protect scope by sharing one provider/registry/journal core rather than per-command scripts.
  • Gitea exact token-scope read-back may require delegated Basic Auth. If a bearer-only validation path cannot obtain an exact provider token object, return indeterminate rather than claim a scope.
  • #1044 hold is LIFTED. The four least-privilege credentials are capability-confirmed and identity-not-measured, not dead. Fleet fail-closed paths now refuse with stable reason markers and never enter shared fallback under MOSAIC_AGENT_NAME; interactive callers retain explicit shared behavior. Runtime mismatch coverage remains limited to tokens holding read:user; future mints close identity binding at creation without widening seat scopes.
  • C1 PR #1054 must first be rebuilt from only its four commits on main; the retargeted head 8b067839 carries 13 unrelated next commits and is not merge-eligible. MC-CRED remains sequenced after the clean C1 merge.