Third PR of the M4-4 lane (after #1481 design, #1482 schema). Implements the enrollment command module per docs/plans/2026-08-29-agent-enrollment-command-design.md.
Scope
EnrollmentModule (apps/gateway/src/enrollment/): agent.enroll (POST /api/enrollment/agents) and agent.enrollment.get (GET /api/enrollment/agents/:id). Closed error enum (§3.3), correlation envelope on every result and refusal, DTOs registered in the boot-time pipe check.
EnrollmentRepository is the family's sole writer: fence-check → mutate → audit + outbox in one transaction. Actor-bound idempotency replay re-authorizes fresh (mode/scope/digest/actor equality, then owner-or-admin on the recorded outcome); every mismatch folds to the constant conflict. Concurrent same-key submissions serialize via the fence's unique index — the loser retries once and resolves as a replay, never an unhandled 500.
Credentials: intake values sealed (AES-256-GCM via @mosaicstack/auth seal) into provider_credentials — single copy, excluded from the payload digest by construction, never present in results, audit rows, outbox rows, fence rows, or logs. Reference mode resolves the actor's stored (actor, provider) credential or refuses precondition_failed.
Harness: validated against the live HarnessRegistry. The registry is empty in prod until adapters register, so prod enrollment refuses precondition_failed — intended fail-closed, witnessed with FakeHarnessAdapter.
CLI parity (contract 5 §4.5, witness 10): mosaic agent enroll / mosaic agent enrollment <id> in packages/mosaic call the same routes with the same request/result/error contracts; intake API key is read from stdin, never argv (ps leakage).
Witnesses
19 integration witnesses (enrollment-commands.integration.test.ts) cover design §5 items 1–9 and 11: never-echo (HTTP result + all four family tables + captured logs), sealed single-copy with unseal round-trip and an information_schema probe of agents, reference resolution both ways, harness refusal both codes, the §4.3 idempotency set (replay, digest/replay-mode/scope/actor mismatches, revoked-authority replay, shared refusal with zero fence rows, concurrent same-key), five-point fault-injection atomicity (no orphan sealed credential), wizard zero-mutation, is_system closure at the pipe, correlation propagation + no-existence-oracle, fail-closed store outage. Item 10 is the 8-test CLI parity spec (agent-enrollment-command.spec.ts).
Documented deviations
Pipe-level 400s carry no correlationId — class-validator refusals precede envelope construction (defensible under §4.3's envelope binding to executed/replayed/refused commands); every repository-level refusal carries it.
CLI parity composition: the mosaic-side spec asserts registration + request/result/error shapes against a stubbed transport, and the gateway e2e asserts the same routes/shapes over real HTTP. A cross-package dep inversion for one spec was rejected.
fleet.spec.ts inventory updated to include the two new subcommands (the spec keeps an exhaustive list of mosaic agent subcommands).
Mosaic: full package suite 1700/1700 green, tsc clean, eslint clean.
No self-merge without review (gate 16); merge on coordinator go-ahead after review + green CI.
Third PR of the M4-4 lane (after #1481 design, #1482 schema). Implements the enrollment command module per docs/plans/2026-08-29-agent-enrollment-command-design.md.
## Scope
- **EnrollmentModule** (apps/gateway/src/enrollment/): `agent.enroll` (POST /api/enrollment/agents) and `agent.enrollment.get` (GET /api/enrollment/agents/:id). Closed error enum (§3.3), correlation envelope on every result and refusal, DTOs registered in the boot-time pipe check.
- **EnrollmentRepository** is the family's sole writer: fence-check → mutate → audit + outbox in one transaction. Actor-bound idempotency replay re-authorizes fresh (mode/scope/digest/actor equality, then owner-or-admin on the recorded outcome); every mismatch folds to the constant `conflict`. Concurrent same-key submissions serialize via the fence's unique index — the loser retries once and resolves as a replay, never an unhandled 500.
- **Credentials**: intake values sealed (AES-256-GCM via @mosaicstack/auth seal) into provider_credentials — single copy, excluded from the payload digest by construction, never present in results, audit rows, outbox rows, fence rows, or logs. Reference mode resolves the actor's stored (actor, provider) credential or refuses precondition_failed.
- **Harness**: validated against the live HarnessRegistry. The registry is empty in prod until adapters register, so prod enrollment refuses precondition_failed — intended fail-closed, witnessed with FakeHarnessAdapter.
- **CLI parity** (contract 5 §4.5, witness 10): `mosaic agent enroll` / `mosaic agent enrollment <id>` in packages/mosaic call the same routes with the same request/result/error contracts; intake API key is read from stdin, never argv (ps leakage).
## Witnesses
19 integration witnesses (enrollment-commands.integration.test.ts) cover design §5 items 1–9 and 11: never-echo (HTTP result + all four family tables + captured logs), sealed single-copy with unseal round-trip and an information_schema probe of `agents`, reference resolution both ways, harness refusal both codes, the §4.3 idempotency set (replay, digest/replay-mode/scope/actor mismatches, revoked-authority replay, shared refusal with zero fence rows, concurrent same-key), five-point fault-injection atomicity (no orphan sealed credential), wizard zero-mutation, is_system closure at the pipe, correlation propagation + no-existence-oracle, fail-closed store outage. Item 10 is the 8-test CLI parity spec (agent-enrollment-command.spec.ts).
## Documented deviations
1. **Pipe-level 400s carry no correlationId** — class-validator refusals precede envelope construction (defensible under §4.3's envelope binding to executed/replayed/refused *commands*); every repository-level refusal carries it.
2. **CLI parity composition**: the mosaic-side spec asserts registration + request/result/error shapes against a stubbed transport, and the gateway e2e asserts the same routes/shapes over real HTTP. A cross-package dep inversion for one spec was rejected.
3. **fleet.spec.ts inventory** updated to include the two new subcommands (the spec keeps an exhaustive list of `mosaic agent` subcommands).
## Evidence
- Gateway: 19/19 witnesses green, validation-pipe-check spec green, tsc clean, eslint clean.
- Mosaic: full package suite 1700/1700 green, tsc clean, eslint clean.
No self-merge without review (gate 16); merge on coordinator go-ahead after review + green CI.
Implements the command module for the M4-4-0 design
(docs/plans/2026-08-29-agent-enrollment-command-design.md) over the
M4-4a schema (migration 0021):
- EnrollmentModule: agent.enroll (POST /api/enrollment/agents) and
agent.enrollment.get (GET /api/enrollment/agents/:id), closed error
enum, correlation envelope on every result and refusal.
- EnrollmentRepository as the family's sole writer: fence-check ->
mutate -> audit + outbox in one transaction; actor-bound idempotency
replay with fresh authorization; intake credentials sealed
(AES-256-GCM) into provider_credentials, never echoed anywhere;
reference mode resolves the actor's stored credential; harness
validated against the live registry (fail-closed in prod until
adapters register).
- CLI parity (contract 5 s4.5): mosaic agent enroll / enrollment
subcommands; intake API key read from stdin, never argv.
- 19 integration witnesses covering design s5 items 1-9 and 11
(never-echo, sealed single-copy, reference resolution, harness
refusal codes, the s4.3 idempotency set incl. concurrent same-key,
five-point fault-injection atomicity, zero-mutation, is_system
closure, correlation + no-existence-oracle, fail-closed) plus an
8-test CLI parity spec (item 10).
rev-code-02
approved these changes 2026-08-30 02:22:39 +00:00
Independent review by rev-code-02 (gate 16; author fred). Head reviewed: 34f4b34702 (verified current PR head == fetched ref == reviewed tree; base 143ba0f5 contains the merged M4-4a schema; one additive commit, no rewrite). Detached GLM APPROVE was context; everything below is measured by me. I reviewed the governing design as review 383 and its schema as review 384, so this checks the implementation against the same texts.
Design §3 conformance, verified by reading the repository, controller, DTOs, and service:
Surface is exactly one command and one query (POST/GET under api/enrollment), AuthGuard-gated, ParseUUIDPipe on the id, correlation envelope on request, result, and refusal.
Never-echo holds by construction: the credential value's only sink is the sealed-store write; the result view exposes only persisted agent fields (the table carries no credential column); the audit payload is harness/provider/name/credentialMode; log lines carry correlation ids and error names only. The CLI side reads intake values from stdin, never argv, with the process-listing rationale stated in code.
Intake writes the sealed store inside the enrollment transaction (upsert per (userId, provider), mirroring ProviderCredentialsService.store semantics); reference mode resolves (actor, provider) before any write and refuses precondition_failed with nothing created.
The fence implements §3.1 rule 5 in full: recorded operation/key/actor/scope(constant platform-user)/digest(value excluded by construction)/replay-mode; UNIQUE(operation, key) via onConflictDoNothing with a bounded retry so a fence-race loser resolves through the replay path rather than an unhandled unique-violation; replay re-checks mode, scope, digest, recorded actor, and target-result read authority (owner or admin), appends only the non-mutation access event, and refuses every failure with one constant conflict message. A shared replay-mode declaration is refused at the DTO, at the repository, and records no fence row.
agent.enrollment.get folds unauthorized and missing to one fixed not_found; the closed §3.3 error enum maps onto the designed HTTP statuses; enroll fails closed to internal_fault with the transaction rolled back.
Witnesses (design §5), run by me at this head: the 19-test gateway integration suite covers items 1-9 and 11 (never-echo across result/audit/outbox/fence/logs, sealed single-copy, reference refusal and resolution, both harness codes, the full idempotency set including shared refusal and the concurrent same-key race, per-write-point fault injection including after the credential write, zero-mutation, is_system closure, correlation + no-existence-oracle, fail-closed). Item 10 (CLI parity) is witnessed in packages/mosaic by an 8-test spec asserting the same request shape, typed results, preserved refusal contract, and no argv credential flag — same routes as the gateway suite, contract-level parity. All green: 19/19 and 8/8.
Mutation controls, each restored and the tree verified byte-clean:
Leaking the credential value into the audit payload turns the never-echo witness red.
Deleting the replay digest-equality check turns the digest-mismatch witness red (and the correlation witness catches the altered replay path too).
Regression: full gateway suite in a fresh worktree shows 17 files / 19 tests failing — the identical failing set reproduces at the base commit 143ba0f5 in the same worktree (diff of FAIL sets empty), so the failures are the environmental config-anchoring/env-tier set proven environmental earlier this session, not a regression; the delta at head is exactly the new enrollment file (621 -> 640 passed). CI carries the authoritative suite.
Mechanical: tsc --noEmit clean in gateway and mosaic; eslint clean on all touched files (run from the repo-root pinned binary); Prettier 3.8.1 green on every touched file. CI pipeline 3032 is the PR pipeline at exactly 34f4b347 and was still running at review time — terminal green remains the merge gate's.
Non-blocking observations, agreeing with the detached review's nits: the repository re-validates only name/harness lengths below the DTO boundary (persona/model/provider lengths rely on the pipe, which is closed — a defense-in-depth asymmetry, not a gap); opts.gateway is accepted but unused in runEnroll (cosmetic); the CLI --credential flag defaults to reference, which fails closed (an omitted flag cannot trigger secret intake).
Verdict: APPROVED at 34f4b34702. An amend or rebase voids this approval.
Independent review by rev-code-02 (gate 16; author fred). Head reviewed: 34f4b34702148af69b554cc21472aedce8def0da (verified current PR head == fetched ref == reviewed tree; base 143ba0f5 contains the merged M4-4a schema; one additive commit, no rewrite). Detached GLM APPROVE was context; everything below is measured by me. I reviewed the governing design as review 383 and its schema as review 384, so this checks the implementation against the same texts.
Design §3 conformance, verified by reading the repository, controller, DTOs, and service:
- Surface is exactly one command and one query (POST/GET under api/enrollment), AuthGuard-gated, ParseUUIDPipe on the id, correlation envelope on request, result, and refusal.
- Never-echo holds by construction: the credential value's only sink is the sealed-store write; the result view exposes only persisted agent fields (the table carries no credential column); the audit payload is harness/provider/name/credentialMode; log lines carry correlation ids and error names only. The CLI side reads intake values from stdin, never argv, with the process-listing rationale stated in code.
- Intake writes the sealed store inside the enrollment transaction (upsert per (userId, provider), mirroring ProviderCredentialsService.store semantics); reference mode resolves (actor, provider) before any write and refuses precondition_failed with nothing created.
- The fence implements §3.1 rule 5 in full: recorded operation/key/actor/scope(constant platform-user)/digest(value excluded by construction)/replay-mode; UNIQUE(operation, key) via onConflictDoNothing with a bounded retry so a fence-race loser resolves through the replay path rather than an unhandled unique-violation; replay re-checks mode, scope, digest, recorded actor, and target-result read authority (owner or admin), appends only the non-mutation access event, and refuses every failure with one constant conflict message. A shared replay-mode declaration is refused at the DTO, at the repository, and records no fence row.
- agent.enrollment.get folds unauthorized and missing to one fixed not_found; the closed §3.3 error enum maps onto the designed HTTP statuses; enroll fails closed to internal_fault with the transaction rolled back.
Witnesses (design §5), run by me at this head: the 19-test gateway integration suite covers items 1-9 and 11 (never-echo across result/audit/outbox/fence/logs, sealed single-copy, reference refusal and resolution, both harness codes, the full idempotency set including shared refusal and the concurrent same-key race, per-write-point fault injection including after the credential write, zero-mutation, is_system closure, correlation + no-existence-oracle, fail-closed). Item 10 (CLI parity) is witnessed in packages/mosaic by an 8-test spec asserting the same request shape, typed results, preserved refusal contract, and no argv credential flag — same routes as the gateway suite, contract-level parity. All green: 19/19 and 8/8.
Mutation controls, each restored and the tree verified byte-clean:
- Leaking the credential value into the audit payload turns the never-echo witness red.
- Deleting the replay digest-equality check turns the digest-mismatch witness red (and the correlation witness catches the altered replay path too).
Regression: full gateway suite in a fresh worktree shows 17 files / 19 tests failing — the identical failing set reproduces at the base commit 143ba0f5 in the same worktree (diff of FAIL sets empty), so the failures are the environmental config-anchoring/env-tier set proven environmental earlier this session, not a regression; the delta at head is exactly the new enrollment file (621 -> 640 passed). CI carries the authoritative suite.
Mechanical: tsc --noEmit clean in gateway and mosaic; eslint clean on all touched files (run from the repo-root pinned binary); Prettier 3.8.1 green on every touched file. CI pipeline 3032 is the PR pipeline at exactly 34f4b347 and was still running at review time — terminal green remains the merge gate's.
Non-blocking observations, agreeing with the detached review's nits: the repository re-validates only name/harness lengths below the DTO boundary (persona/model/provider lengths rely on the pipe, which is closed — a defense-in-depth asymmetry, not a gap); opts.gateway is accepted but unused in runEnroll (cosmetic); the CLI --credential flag defaults to reference, which fails closed (an omitted flag cannot trigger secret intake).
Verdict: APPROVED at 34f4b34702148af69b554cc21472aedce8def0da. An amend or rebase voids this approval.
marcie
merged commit 431ead3a18 into next2026-08-30 04:30:06 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Third PR of the M4-4 lane (after #1481 design, #1482 schema). Implements the enrollment command module per docs/plans/2026-08-29-agent-enrollment-command-design.md.
Scope
agent.enroll(POST /api/enrollment/agents) andagent.enrollment.get(GET /api/enrollment/agents/:id). Closed error enum (§3.3), correlation envelope on every result and refusal, DTOs registered in the boot-time pipe check.conflict. Concurrent same-key submissions serialize via the fence's unique index — the loser retries once and resolves as a replay, never an unhandled 500.mosaic agent enroll/mosaic agent enrollment <id>in packages/mosaic call the same routes with the same request/result/error contracts; intake API key is read from stdin, never argv (ps leakage).Witnesses
19 integration witnesses (enrollment-commands.integration.test.ts) cover design §5 items 1–9 and 11: never-echo (HTTP result + all four family tables + captured logs), sealed single-copy with unseal round-trip and an information_schema probe of
agents, reference resolution both ways, harness refusal both codes, the §4.3 idempotency set (replay, digest/replay-mode/scope/actor mismatches, revoked-authority replay, shared refusal with zero fence rows, concurrent same-key), five-point fault-injection atomicity (no orphan sealed credential), wizard zero-mutation, is_system closure at the pipe, correlation propagation + no-existence-oracle, fail-closed store outage. Item 10 is the 8-test CLI parity spec (agent-enrollment-command.spec.ts).Documented deviations
mosaic agentsubcommands).Evidence
No self-merge without review (gate 16); merge on coordinator go-ahead after review + green CI.
Independent review by rev-code-02 (gate 16; author fred). Head reviewed:
34f4b34702(verified current PR head == fetched ref == reviewed tree; base143ba0f5contains the merged M4-4a schema; one additive commit, no rewrite). Detached GLM APPROVE was context; everything below is measured by me. I reviewed the governing design as review 383 and its schema as review 384, so this checks the implementation against the same texts.Design §3 conformance, verified by reading the repository, controller, DTOs, and service:
Witnesses (design §5), run by me at this head: the 19-test gateway integration suite covers items 1-9 and 11 (never-echo across result/audit/outbox/fence/logs, sealed single-copy, reference refusal and resolution, both harness codes, the full idempotency set including shared refusal and the concurrent same-key race, per-write-point fault injection including after the credential write, zero-mutation, is_system closure, correlation + no-existence-oracle, fail-closed). Item 10 (CLI parity) is witnessed in packages/mosaic by an 8-test spec asserting the same request shape, typed results, preserved refusal contract, and no argv credential flag — same routes as the gateway suite, contract-level parity. All green: 19/19 and 8/8.
Mutation controls, each restored and the tree verified byte-clean:
Regression: full gateway suite in a fresh worktree shows 17 files / 19 tests failing — the identical failing set reproduces at the base commit
143ba0f5in the same worktree (diff of FAIL sets empty), so the failures are the environmental config-anchoring/env-tier set proven environmental earlier this session, not a regression; the delta at head is exactly the new enrollment file (621 -> 640 passed). CI carries the authoritative suite.Mechanical: tsc --noEmit clean in gateway and mosaic; eslint clean on all touched files (run from the repo-root pinned binary); Prettier 3.8.1 green on every touched file. CI pipeline 3032 is the PR pipeline at exactly
34f4b347and was still running at review time — terminal green remains the merge gate's.Non-blocking observations, agreeing with the detached review's nits: the repository re-validates only name/harness lengths below the DTO boundary (persona/model/provider lengths rely on the pipe, which is closed — a defense-in-depth asymmetry, not a gap); opts.gateway is accepted but unused in runEnroll (cosmetic); the CLI --credential flag defaults to reference, which fails closed (an omitted flag cannot trigger secret intake).
Verdict: APPROVED at
34f4b34702. An amend or rebase voids this approval.