Files
stack/docs/scratchpads/755-mos-logical-identity-fencing.md
Jarvis d190732a55 feat(#755): add logical agent connector fencing
Add normalized runtime-neutral identity, durable PostgreSQL CAS leases, monotonic epochs, short-lived server grants, fail-closed adapter validation, credential-safe audit, and concurrency/restart/abuse coverage.\n\nRefs #755
2026-07-14 17:23:06 -05:00

8.4 KiB

Issue #755 — Logical Mos identity and connector lease fencing

  • Task: MOS-PORT-M1-001
  • Branch: feat/mos-logical-identity-fencing
  • Base: origin/main
  • Started: 2026-07-14
  • Working budget: 38K tokens (task ledger estimate); one implementation lane, bounded to M1.

Objective

Implement the first runtime-portability security boundary: normalized logical-agent identity plus a PostgreSQL-durable exclusive connector lease and server-validated fencing grants.

Scope

  • Normalized identity contract independent of harness/provider-native session IDs.
  • DB migration/schema/repository for one lease per tenant/logical-agent/binding.
  • CAS acquire/takeover, monotonic epoch, TTL, heartbeat, release, expiry handling.
  • Server-derived grants bound to tenant, logical agent, binding, connector, scopes, expiry, and lease epoch.
  • Reject and credential-safely audit stale, expired, forged, unauthorized, cross-tenant, and cross-binding grants before adapter side effects.
  • Runtime adapter boundary consumes normalized lease context.
  • Unit, migration, close/reopen, concurrency, abuse, and gateway integration tests.
  • Required developer/operations documentation for schema and security behavior.

Explicit exclusions

No checkpoint/handoff payloads, exactly-once journal/receipts, concrete Claude/Pi/Codex harness adapter, channel cutover, or full cross-harness failover E2E.

Plan (TDD RED → GREEN → REFACTOR)

  1. Map existing contracts, DB/migration conventions, gateway authorization/audit boundaries, and test infrastructure.
  2. Add failing contract/repository/concurrency/restart/abuse/gateway tests and capture RED evidence.
  3. Implement the smallest normalized contracts, schema/migration/repository, grant validator, audit sink, and gateway service/adapter boundary needed to pass.
  4. Refactor for clear invariants and credential-safe observability; rerun focused suites.
  5. Run package/repo typecheck, lint, format, and appropriate tests.
  6. Run independent code + security review, remediate, and re-review.
  7. Inspect the final diff for security/scope drift; commit; queue guard; push; open PR with Refs #755 and exact verification; stop without merge/issue closure.

Constraints and safety notes

  • docs/tess/TASKS.md is orchestrator-only and will not be edited.
  • Existing dirty .mosaic/orchestrator/mission.json and .mosaic/orchestrator/session.lock are launcher/orchestrator state and will not be staged or altered intentionally.
  • No client-supplied identity may confer authority.
  • No credential, token, or raw grant material may be persisted to audit/log output.
  • Existing authorization checks remain intact; fencing is an additional fail-closed layer.

Assumptions resolved from existing architecture

  • ASSUMPTION: M1 exposes no public lease endpoint. The gateway service is an internal policy surface with deny-all default policy because concrete connector activation/cutover is explicitly deferred.
  • ASSUMPTION: Fencing epochs use PostgreSQL bigint and cross-module decimal strings, preserving JSON portability without JavaScript number precision loss.
  • ASSUMPTION: Process-local grant provenance intentionally fails closed across restart; durable lease/epoch state survives and fresh grants require current policy + lease validation.

TDD evidence

RED observed before implementation:

  • corepack pnpm --filter @mosaicstack/types exec vitest run src/agent/connector-lease.dto.spec.ts → failed to load missing connector-lease.dto.js.
  • corepack pnpm --filter @mosaicstack/agent exec vitest run src/connector-lease.test.ts → failed to load missing connector-lease.js.
  • Gateway focused tests failed before implementation because the new repository/service boundaries did not exist (workspace dependencies were then built before behavioral GREEN runs).

GREEN to date:

  • Types contract: 6/6 passed.
  • Agent grant/fencing unit suite: 5/5 passed.
  • Gateway PGlite repository + policy/side-effect integration: 7/7 passed; 1 real-PostgreSQL test skipped when DATABASE_URL absent.
  • Real PostgreSQL focused run with configured DATABASE_URL: 1/1 passed (credential value not emitted in reports).

Documentation checklist

  • docs/PRD.md contains current MOS-PORT M1 scope and acceptance criteria.
  • Developer architecture: docs/architecture/mos-runtime-portability-m1.md.
  • Admin/operations guidance: docs/guides/mos-connector-lease-operations.md.
  • docs/SITEMAP.md links both pages.
  • No user-guide change: M1 exposes no user-facing flow or channel cutover.
  • No OpenAPI/endpoint-index change: M1 adds no HTTP endpoint.
  • Migration/restart/rollback safety and credential-safe audit constraints documented.
  • Canonical source remains in-repo; no external publishing action is in scope.
  • Independent review confirms documentation matches implementation; implementation-specific findings were remediated.

Independent review and remediation

Codex code/security review ran in multiple rounds. Findings and root-cause remediations:

  1. Policy could not inspect requested scope/TTL → policy subject now receives normalized requested scopes and explicit requested TTL.
  2. Unbounded authority lifetime → hard defaults cap leases at 5 minutes and grants at 30 seconds; overrides may only tighten; over-limit tests added.
  3. Cross-tenant denial could audit under submitted tenant → mismatch audit uses authenticated tenant plus sanitized untrusted target metadata; integration assertion added.
  4. Malformed forged grant could break the denial/audit path → runtime-safe shape validation with sanitized fallback audit; malformed-input test added.
  5. Gateway integration test depended on prior test state → denial test now seeds a unique binding itself; isolated -t run passed.
  6. Reviewer repeatedly identified launcher-generated .mosaic/orchestrator/* state; those files remain unstaged and excluded from the implementation commit.

Latest independent security review: no critical/high/medium/low findings. Final commit-level code review remains to run after the intended diff is committed without launcher state.

Verification evidence

  • Focused contracts/fencing: types 6/6; agent 9/9.
  • Gateway focused PGlite repository/policy integration: 7/7; isolated denial test 1/1.
  • Real PostgreSQL close/reopen/CAS test: 1/1 with configured DATABASE_URL.
  • Root corepack pnpm typecheck: 42/42 Turbo tasks passed.
  • Root corepack pnpm lint: 23/23 Turbo tasks passed.
  • Root corepack pnpm format:check: all matched files passed.
  • Root corepack pnpm test: 42/42 Turbo tasks passed; gateway 616 passed / 12 environment-gated skipped; DB 19 passed / 7 environment-gated skipped; Mosaic 650 passed.

Known residual risks

  • Concrete connector policies and Claude/Pi/Codex adapters are intentionally deferred; production policy defaults deny-all.
  • Gateway pre-side-effect validation cannot make an external system exactly-once. Adapters must propagate/enforce the epoch at downstream effect boundaries; receipts/journaling are later #754 scope.
  • Migration rollback is additive-only; dropping lease/audit tables is intentionally manual to avoid destroying authority/audit evidence.

Commit-level review remediation

  • Commit-level Codex code review found one should-fix: heartbeat, release, and grant issuance authorized caller-supplied lease fields before canonical normalization.
  • TDD RED: the isolated gateway policy-boundary test showed mixed-case/padded logical agent, binding, connector, scope, and epoch values reaching policy unchanged.
  • Remediation: exported the coordinator's canonical lease normalizer and applied it at the gateway boundary before tenant/policy checks and coordinator dispatch for heartbeat, release, and grant issuance.
  • GREEN: isolated policy test 1/1; focused types 6/6, agent 9/9, gateway 8/8; root typecheck 42/42, lint 23/23, format check passed, and root tests 42/42 (gateway 617 passed / 12 environment-gated skipped).
  • Commit-level security review remained clean: no critical/high/medium/low findings.

Durable grant-expiry review remediation

  • Final commit review found a second should-fix: grant expiry was capped against submitted lease metadata after current-authority validation, rather than the durable lease row.
  • TDD RED: a crafted same-authority lease with a later submitted expiry produced a grant expiring after the durable row.
  • Remediation: grant authority fields and expiry now derive from the durable current lease; submitted scopes remain an additional narrowing constraint.
  • GREEN: focused agent fencing suite 10/10.