docs(mos): promote runtime portability M1 docs
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# Mos Connector Lease Operations — M1
|
||||
|
||||
> **Status:** Held / non-operative.
|
||||
> **Operational authority:** None. This page is a future runbook outline, not a current command, endpoint, migration, or activation procedure.
|
||||
> **Hold condition:** The gateway's `DenyConnectorLeasePolicy` remains the default policy and rejects every lease and grant operation. No connector is activated by this page.
|
||||
|
||||
## Current state
|
||||
|
||||
M1 provides an implemented lease, fencing, audit, and gateway policy boundary. It does not currently provide an operator-facing lease endpoint, activate a connector, cut over a channel, or connect an existing runtime provider to `ConnectorExecutionContext`. The default gateway module is deny-all, so operators must not treat the schema or internal service as an available lease-control surface.
|
||||
|
||||
There is no current operator command sequence to acquire, renew, take over, release, or grant connector authority. Do not attempt to operate the held procedure through direct database writes or by bypassing the gateway policy. Any future activation requires a separately approved server-side policy, concrete adapter, downstream fencing design, and an updated operational runbook.
|
||||
|
||||
## Held future procedure — not current command authority
|
||||
|
||||
The following records the intended shape of a later runbook. It is deliberately non-operative while deny-all remains:
|
||||
|
||||
### Events and evidence to monitor later
|
||||
|
||||
If an authorized policy and adapter are activated in a future work package, correlation IDs may be used to inspect `connector_lease_audit_log` events:
|
||||
|
||||
| Event | Meaning |
|
||||
| ---------- | ---------------------------------------------------------------------------------- |
|
||||
| `acquire` | First holder inserted for an unused binding |
|
||||
| `renew` | Current holder heartbeat extended the TTL |
|
||||
| `takeover` | Authorized compare-and-swap replaced the holder and incremented epoch |
|
||||
| `release` | Current holder explicitly relinquished authority |
|
||||
| `expiry` | An expired current lease was observed |
|
||||
| `reject` | Policy, compare-and-swap, expiry, scope, or fencing validation denied an operation |
|
||||
|
||||
Audit records are metadata-only. Raw grant objects, connector payloads, scopes, tokens, approval references, and credentials must never be added to audit output. The current schema does not independently enforce append-only storage; database-level protection remains a future hardening requirement.
|
||||
|
||||
### Held incident-review outline
|
||||
|
||||
For a future suspected duplicate or stale connector effect, an approved operator procedure would:
|
||||
|
||||
1. correlate the attempted operation with its `reject`, `takeover`, or `expiry` event;
|
||||
2. compare the durable row's connector ID, lease UUID, epoch, expiry, and release time with the adapter's normalized execution context;
|
||||
3. treat an old epoch, old lease UUID, expired lease, or released lease as non-authoritative rather than retrying it as the old holder;
|
||||
4. use only the authorized takeover path with the observed expected epoch, never ordinary acquire, for an expired or released row; and
|
||||
5. preserve evidence without assuming lease fencing provides exactly-once replay safety if an external effect may already have occurred.
|
||||
|
||||
These are held review requirements, not instructions to bypass the current deny-all policy.
|
||||
|
||||
### Held migration and rollback notes
|
||||
|
||||
The checked-in `0016_salty_morlocks.sql` artifact is additive: it creates the lease and audit tables and indexes without changing existing authorization/session tables. A future database rollout would still require the repository's approved migration, backup, verification, and rollback controls. Application rollback would leave additive lease/audit tables in place; dropping them would destroy evidence and is not an automatic rollback step.
|
||||
|
||||
This page does not authorize running migrations, connecting to PostgreSQL, initializing PGlite, or starting a connector. Those activities remain outside this held procedure and subject to repository/runtime gates.
|
||||
|
||||
### Held security prerequisites
|
||||
|
||||
Before this page could become operative, the activation work would need to demonstrate at least:
|
||||
|
||||
- tenant authority derived from authenticated gateway context, not connector request fields;
|
||||
- authorized policy decisions over normalized identity and scopes, with policy TTL handling based on the requested input and coordinator hard caps still applied;
|
||||
- explicit takeover authorization and expected-epoch compare-and-swap;
|
||||
- application-boundary normalization plus any separately approved database constraints or protections;
|
||||
- validation and rejection audit before adapter side effects;
|
||||
- a concrete adapter that consumes and propagates the normalized epoch/context; and
|
||||
- existing authorization and exact-action approval controls remaining in force.
|
||||
|
||||
M1 currently satisfies the boundary contract and default-deny posture, not these activation prerequisites.
|
||||
|
||||
## Explicit non-goals while held
|
||||
|
||||
This page does not authorize or claim:
|
||||
|
||||
1. lease administration from the dashboard, CLI, HTTP, SQL console, or a connector;
|
||||
2. production connector or channel activation;
|
||||
3. exactly-once delivery, side-effect journaling, checkpoint/handoff recovery, or replay safety;
|
||||
4. automatic failover, rollback, or stale-effect recovery across Claude, Pi, Codex, Matrix, tmux, or provider sessions; or
|
||||
5. database-enforced audit immutability or database-enforced application normalization.
|
||||
|
||||
The page may be promoted to an operative runbook only after deny-all is intentionally replaced, concrete adapters are reviewed, activation evidence exists, and this hold is explicitly removed by the owning work package.
|
||||
|
||||
## Related contract
|
||||
|
||||
- [M1 logical identity and fencing decision](../../DEVELOPER-GUIDE/architecture/decisions/mos-runtime-portability-m1.md)
|
||||
- [MOS-PORT requirements](../../PRD.md#mos-runtime-portability-workstream-mos-port)
|
||||
@@ -0,0 +1,96 @@
|
||||
# Mos Runtime Portability M1 — Logical Identity and Fencing
|
||||
|
||||
> **Decision status:** Current implemented decision (M1).
|
||||
> **Operational status:** The lease/fencing boundary is implemented and test-covered; connector activation remains held.
|
||||
> **Audience:** Mosaic developers, gateway/runtime adapter authors, and security reviewers.
|
||||
> **Authority:** This page records the current M1 boundary. The executable source and tests are authoritative for behavior; [`PRD.md`](../../../PRD.md) remains authoritative for requirements.
|
||||
|
||||
## Decision
|
||||
|
||||
M1 separates the logical Mosaic agent from any Claude, Pi, Codex, tmux, Matrix, or provider-native session. The core identity is:
|
||||
|
||||
```text
|
||||
(tenant_id, logical_agent_id, binding_id)
|
||||
```
|
||||
|
||||
`logical_agent_id` is a Mosaic logical identifier, not a runtime session identifier. The gateway derives the tenant from authenticated actor scope. The current internal service boundary normalizes the supplied logical-agent identifier and binding; a future public boundary must resolve and authorize those values server-side. Runtime-native session IDs are not part of the lease or execution-grant contract.
|
||||
|
||||
A connector is a replaceable holder of authority for one logical binding. It is not the logical agent identity.
|
||||
|
||||
## Durable lease model
|
||||
|
||||
The additive migration creates `logical_agent_connector_leases` with one unique row per tenant/logical-agent/binding tuple. The current row contains:
|
||||
|
||||
- an opaque lease UUID;
|
||||
- connector ID and normalized allowed scopes;
|
||||
- a positive decimal fencing epoch exposed by the application and stored as PostgreSQL `bigint`;
|
||||
- acquisition, heartbeat, expiry, release, and update timestamps.
|
||||
|
||||
Initial acquisition is insert-only. An existing active row yields `lease_held`. An expired or released row yields `takeover_required`; ordinary acquisition does not recover it. An authorized takeover compares and swaps 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.
|
||||
|
||||
### Audit and enforcement precision
|
||||
|
||||
`connector_lease_audit_log` is an **application-level append-only contract**: the repository has an insert-only audit path and writes credential-safe lifecycle/rejection metadata. The checked-in schema and migration add a table and indexes, but do not add database triggers, permissions, or other database-level protection against `UPDATE` or `DELETE`. M1 therefore does not claim database-enforced immutability; an append-only guarantee at the database security boundary is a later hardening requirement.
|
||||
|
||||
Likewise, identifier, scope, and epoch normalization is performed at the application boundary by the shared types/coordinator and gateway service. The database enforces column types, non-null fields, the lease primary key, and the unique tenant/logical-agent/binding index, but it does not independently enforce all application formats or semantics such as positive epochs, canonical scope ordering/deduplication, or constrained identifier patterns. Database shape must not be mistaken for a second normalization layer.
|
||||
|
||||
## Execution grants and TTL boundaries
|
||||
|
||||
`ConnectorLeaseCoordinator` issues a short-lived internal grant only after rereading the durable current lease. It enforces hard defense-in-depth maxima of five minutes for leases and thirty seconds for grants; constructor options may only tighten those limits. A grant is bound to tenant, logical agent, binding, connector, lease UUID, scope subset, expiry, correlation ID, and epoch.
|
||||
|
||||
The gateway policy and coordinator have deliberately separate TTL responsibilities:
|
||||
|
||||
- `ConnectorLeaseService` passes the request's numeric `ttlMs` to policy as `requestedTtlMs` for acquire, takeover, heartbeat, and grant issuance. Identity and scopes are normalized before policy evaluation, but this TTL is a request input, not a coordinator-normalized or effective TTL.
|
||||
- Release and read policy checks use `null` because they do not request a TTL.
|
||||
- After policy authorization, the coordinator validates the TTL as a positive safe integer and rejects values above the applicable hard cap (`300000ms` for leases or `30000ms` for grants). It does not silently clamp an over-cap value.
|
||||
- A policy may impose a stricter duration limit, but it cannot expand the coordinator cap. A policy implementation must validate the requested value itself if its decision depends on a bounded or canonical TTL.
|
||||
|
||||
Grant validation occurs immediately before adapter invocation and rereads the durable current row. Validation denies:
|
||||
|
||||
- grants not minted by the current gateway process, including cloned or forged objects;
|
||||
- expired grants or leases;
|
||||
- released leases;
|
||||
- stale epochs or replaced connectors/lease UUIDs;
|
||||
- missing, cross-tenant, cross-agent, or cross-binding leases; and
|
||||
- scopes not authorized by both the grant and the current lease.
|
||||
|
||||
A gateway restart intentionally invalidates process-local grant provenance. The durable lease and epoch survive, but a fresh grant is required after current-lease and policy validation.
|
||||
|
||||
## Adapter boundary and activation state
|
||||
|
||||
The normalized `ConnectorExecutionContext` and `FencedConnectorAdapter` contract define the future adapter boundary. When a concrete adapter is activated, it must receive the context only after the coordinator's final validation and must propagate the epoch/context to downstream effect boundaries that need to fence races after gateway validation.
|
||||
|
||||
That contract is **not evidence of an activated adapter**. The current production module registers the lease repository, service, and deny-all policy. The coordinator and gateway integration tests use test adapters, but current production runtime providers and channel paths do not consume `ConnectorExecutionContext` or call `executeGrant`. No concrete Claude, Pi, Codex, Matrix, tmux, provider, or channel connector is activated by M1.
|
||||
|
||||
`ConnectorLeaseService` is the gateway-owned policy surface. It derives tenant scope from authenticated context, records policy denials, and is internal: no M1 connector-lease HTTP controller or administration endpoint is registered. The default `DenyConnectorLeasePolicy` rejects every lease and grant operation until a separately authorized server-side policy is supplied.
|
||||
|
||||
## Current implementation evidence
|
||||
|
||||
The current boundary is represented by the following checked-in surfaces:
|
||||
|
||||
- Contract and application normalizers: `packages/types/src/agent/connector-lease.dto.ts` and its unit specification.
|
||||
- Coordinator, TTL caps, grant provenance, reread, and fencing checks: `packages/agent/src/connector-lease.ts` and its unit tests.
|
||||
- Gateway policy, tenant derivation, and default deny wiring: `apps/gateway/src/agent/connector-lease.service.ts` and `agent.module.ts`.
|
||||
- Durable repository and compare-and-swap mutations: `apps/gateway/src/agent/connector-lease.repository.ts`.
|
||||
- Schema and additive migration artifacts: `packages/db/src/schema.ts` and `packages/db/drizzle/0016_salty_morlocks.sql`.
|
||||
- Gateway integration and repository specifications: `apps/gateway/src/agent/connector-lease.integration.test.ts` and `connector-lease.repository.test.ts`.
|
||||
|
||||
These references establish the implemented boundary; they do not imply that a production database, connector policy, or concrete connector is currently active.
|
||||
|
||||
## Explicit non-goals
|
||||
|
||||
M1 does **not** provide or authorize:
|
||||
|
||||
1. Production connector activation, channel cutover, or cross-harness failover/rollback E2E.
|
||||
2. Concrete Claude, Pi, Codex, Matrix, tmux, provider, or channel adapters, or integration of existing runtime providers with this lease context.
|
||||
3. A connector-lease HTTP API or caller-controlled tenant authority.
|
||||
4. Exactly-once connector receipts, a side-effect journal, checkpoint/handoff payloads, replay deduplication, or recovery semantics for an external effect that may already have happened.
|
||||
5. Database-enforced append-only audit rows or database-enforced copies of application identifier/scope/epoch normalization.
|
||||
6. A claim that gateway validation alone fences an effect after an adapter has crossed the boundary; downstream adapters and effect journals remain later work.
|
||||
|
||||
A valid lease or grant is therefore not a claim of exactly-once delivery, production connector readiness, or completed runtime cutover.
|
||||
|
||||
## Related contract
|
||||
|
||||
- [M1 connector lease operations — held/non-operative](../../../ADMIN-GUIDE/operations/mos-connector-lease-operations.md)
|
||||
- [MOS-PORT requirements](../../../PRD.md#mos-runtime-portability-workstream-mos-port)
|
||||
@@ -1,49 +0,0 @@
|
||||
# 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:
|
||||
|
||||
```text
|
||||
(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.
|
||||
@@ -1,43 +0,0 @@
|
||||
# Mos Connector Lease Operations — M1
|
||||
|
||||
## Operational status
|
||||
|
||||
M1 installs the durable schema and gateway policy/adapter boundary. It does **not** activate a connector, expose a lease administration endpoint, or cut over a channel. The default gateway connector-lease policy is deny-all until a later work package supplies an authorized server-side policy and concrete adapter.
|
||||
|
||||
## Events to monitor
|
||||
|
||||
Use correlation IDs to follow `connector_lease_audit_log` events:
|
||||
|
||||
| Event | Meaning |
|
||||
| ---------- | --------------------------------------------------------------------- |
|
||||
| `acquire` | First holder inserted for an unused binding |
|
||||
| `renew` | Current holder heartbeat extended the TTL |
|
||||
| `takeover` | Authorized CAS replaced the holder and incremented epoch |
|
||||
| `release` | Current holder explicitly relinquished authority |
|
||||
| `expiry` | An expired current lease was observed |
|
||||
| `reject` | Policy, CAS, expiry, scope, or fencing validation denied an operation |
|
||||
|
||||
Audit data is metadata-only. Raw grant objects, connector payloads, scopes, tokens, approval references, and credentials must never be added to audit output.
|
||||
|
||||
## Incident checks
|
||||
|
||||
For suspected duplicate/stale connector effects:
|
||||
|
||||
1. Correlate the attempted operation with its `reject`, `takeover`, or `expiry` event.
|
||||
2. Compare the current row's connector ID, lease UUID, epoch, expiry, and release time with the adapter's normalized execution context.
|
||||
3. Treat an old epoch, old lease UUID, expired lease, or released lease as non-authoritative. Do not retry it as the old holder.
|
||||
4. Recovery uses the authorized takeover path with the observed expected epoch. Ordinary acquire is intentionally rejected for expired/released rows.
|
||||
5. If an external effect may already have happened, preserve evidence and do not assume lease fencing provides exactly-once replay safety.
|
||||
|
||||
## Migration and rollback safety
|
||||
|
||||
Migration `0016_salty_morlocks.sql` is additive: it creates two new tables and indexes without modifying existing authorization/session tables. Before rollout, normal database backup and migration verification still apply. Rolling application code back leaves unused additive tables in place; dropping tables is not part of automated rollback because it would destroy lease/audit evidence.
|
||||
|
||||
## Security constraints
|
||||
|
||||
- Tenant comes from authenticated gateway context, never a connector request field.
|
||||
- Logical agent, binding, connector, and scope identifiers use normalized constrained forms.
|
||||
- Takeover requires explicit gateway policy authorization and an expected epoch.
|
||||
- Default defense-in-depth TTL caps are 5 minutes for leases and 30 seconds for grants; policy may enforce stricter limits.
|
||||
- Validation and rejection audit complete before adapter side effects.
|
||||
- Existing authz and exact-action approval controls remain additional required gates; a valid connector lease does not bypass them.
|
||||
Reference in New Issue
Block a user