Files
stack/docs/architecture/mos-runtime-portability-m1.md
Jarvis dff8ce4f79
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
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 13:17:02 -05:00

3.4 KiB

Mos Runtime Portability M1 — Logical Identity and Fencing

Boundary

M1 separates the logical Mosaic agent from any Claude, Pi, Codex, tmux, Matrix, or provider-native session. The normalized identity is:

(tenant_id, logical_agent_id, binding_id)

logical_agent_id is a server-owned stable identifier. A connector is a replaceable holder of a lease for one binding; it is not the agent identity.

Durable lease model

PostgreSQL table logical_agent_connector_leases has one unique row per identity/binding tuple. The current row records:

  • an opaque lease UUID;
  • connector ID and normalized allowed scopes;
  • a positive decimal fencing epoch stored as PostgreSQL bigint;
  • acquired, heartbeat, expiry, release, and update timestamps.

Initial acquisition is insert-only. An existing active row causes lease_held. An expired or released row causes takeover_required; ordinary acquisition cannot recover it. Authorized takeover uses compare-and-swap against the expected epoch, rotates the lease UUID, and increments the epoch atomically. Heartbeat and release match the full identity, binding, connector, lease UUID, and epoch.

The companion connector_lease_audit_log is append-only metadata. It stores lifecycle event, outcome/reason, identity/binding/connector, epoch, correlation ID, and timestamp. It deliberately excludes scopes, grant objects, payloads, approval references, tokens, and credentials.

Execution grants

ConnectorLeaseCoordinator issues a short-lived internal grant only after rereading the durable current lease. Defense-in-depth caps leases at 5 minutes and grants at 30 seconds by default; constructor options may tighten these limits. A grant is bound to tenant, logical agent, binding, connector, lease UUID, scope subset, expiry, and epoch.

Validation occurs immediately before adapter invocation and rereads PostgreSQL. The adapter receives only ConnectorExecutionContext; harness-native schemas remain behind the adapter. Validation denies:

  • grants not minted by the current gateway process (including cloned/forged objects);
  • expired grants or leases;
  • released leases;
  • stale epochs or replaced connector/lease UUIDs;
  • missing/cross-tenant/cross-agent/cross-binding leases;
  • scopes not authorized by both grant and current lease.

A gateway restart intentionally invalidates process-local grants. The durable lease and epoch survive, and a fresh grant may be issued only after current-lease and gateway-policy validation.

Concurrency and side-effect rule

The database CAS determines the sole current holder. A successful takeover makes every old-epoch validation fail. Connector adapters must consume and propagate the normalized lease epoch/context so downstream effect boundaries can also fence races that occur after gateway validation.

M1 does not provide exactly-once receipts or a side-effect journal. Those remain later #754 work; callers must not infer exactly-once delivery from lease fencing.

Extension boundary

ConnectorLeaseService is the gateway-owned policy surface. Every policy decision receives the normalized requested scopes and TTL (or explicit null where no TTL applies), so a concrete policy can enforce least privilege and duration limits. Its production default policy denies every lease/grant operation until a server-configured connector policy is supplied. No M1 HTTP endpoint accepts caller-controlled tenant or logical identity, and no concrete Claude/Pi/Codex adapter or channel cutover is included.