feat(fleet): add shared role semantics
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
108
docs/scratchpads/758-fcm-m1-002-shared-role-resolution.md
Normal file
108
docs/scratchpads/758-fcm-m1-002-shared-role-resolution.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# FCM-M1-002 — Shared role resolution
|
||||
|
||||
- **Task:** `FCM-M1-002`
|
||||
- **Issue:** `mosaicstack/stack#758`
|
||||
- **Branch:** `feat/758-shared-role-resolution`
|
||||
- **Starting head:** `32e75c67b094de443d37fe7d5ff8d25cdfc8b39d`
|
||||
- **Role:** implementation worker; independent review and merge remain outside this worker
|
||||
|
||||
## Objective
|
||||
|
||||
Reuse the existing baseline-plus-`roles.local` persona resolver as the sole class authority for roster-v2 semantics, profile validation, provisioning, and launch/persona resolution. Add exact approved alias canonicalization, fail-closed semantic validation, immutable canonical-class authority contracts, required baseline roles, and operator documentation without implementing lifecycle, mutation, credentials, certificate workflow, or later FCM cards.
|
||||
|
||||
## Budget
|
||||
|
||||
- Soft budget: **25K tokens**.
|
||||
- Strategy: inspect once, implement in small TDD units, run focused suites before the full package gate, and avoid unrelated refactors or M1-003/M2/M4 scope.
|
||||
|
||||
## Plan
|
||||
|
||||
1. Map the existing persona resolver, roster-v2 compiler, profile/provision consumers, launch resolution, role library, and focused tests.
|
||||
2. Write denial/invariant tests first for aliases, canonicalization-before-override, unreadable roles, authority boundaries, policy mismatch, canonical provision output, and resolver parity.
|
||||
3. Run the focused suites and record the expected red evidence.
|
||||
4. Implement one shared canonical resolution and authority contract in/through `fleet-personas.ts`; delegate roster semantic validation and profile/provision paths to it.
|
||||
5. Add baseline `validator`, `team-leader`, and `interaction` role contracts plus `LIBRARY.md` entries while retaining `operator-interaction` compatibility.
|
||||
6. Add the required role reference, alias migration, customization guide, and roster-v2 semantic handoff documentation.
|
||||
7. Run focused tests, the full `@mosaicstack/mosaic` suite, typecheck, lint, Prettier, `git diff --check`, situational verification, independent code/security review, and remediation.
|
||||
8. Commit with the required co-author trailer, run the CI queue guard, push the existing branch, and create/update exactly one PR to `main` with `Refs #758`.
|
||||
|
||||
## TDD evidence
|
||||
|
||||
### Red
|
||||
|
||||
After installing worktree-local dependencies and building `@mosaicstack/db`, the pre-implementation
|
||||
focused run collected the intended tests and failed as expected:
|
||||
|
||||
```text
|
||||
2 test files failed; 32 tests failed; 32 tests passed
|
||||
```
|
||||
|
||||
Expected failures named the missing `canonicalizeRoleClass`,
|
||||
`authorityForCanonicalClass`, and `validateRosterV2Semantics` APIs, absent requested/canonical typed
|
||||
output, and unresolved required canonical role contracts. An earlier run that failed before test
|
||||
collection on an unresolved `yaml` dependency was treated as environment setup, not TDD evidence.
|
||||
|
||||
### Green
|
||||
|
||||
Focused role-resolution and affected service fixtures:
|
||||
|
||||
```text
|
||||
6 test files passed; 109 tests passed
|
||||
```
|
||||
|
||||
The focused set covers personas, profiles, provision, launch persona contract, roster-v2 semantics,
|
||||
and the operator-interaction service fixture. The final profile tests also cover readable lead/floor
|
||||
compatibility and canonical collision denial.
|
||||
|
||||
## Tests and gates
|
||||
|
||||
- Focused suites: pass, **6 files / 109 tests**.
|
||||
- Full `@mosaicstack/mosaic` suite: pass, **50 files / 713 tests**. Workspace package build outputs
|
||||
were prepared first because a clean worktree has no dependency `dist` entries.
|
||||
- `pnpm --filter @mosaicstack/mosaic typecheck`: pass.
|
||||
- `pnpm --filter @mosaicstack/mosaic lint`: pass.
|
||||
- Prettier check over every changed file: pass.
|
||||
- `git diff --check`: pass.
|
||||
- Runtime/file-boundary evidence: real role library, profile/provision filesystem integration,
|
||||
launch-time synchronous contract injection, v1 roster parser round-trip, roster-v2 semantic
|
||||
filesystem checks, and operator-interaction service fixtures all pass without live mutation.
|
||||
- Independent code review: **APPROVE**, no blocking or non-blocking findings; reviewed complete
|
||||
tracked/untracked delta including the canonical collision guard. Residual: roster-v2 semantic
|
||||
validation is an explicit async handoff with production caller wiring owned by later work.
|
||||
- Independent security review: **APPROVE**, no verified authority/security findings on the final
|
||||
delta.
|
||||
|
||||
|
||||
## Risks and boundaries
|
||||
|
||||
- **Security-sensitive authority:** authority must derive only from canonical class, never role prose, aliases, display names, or tool-policy text.
|
||||
- **Resolver divergence:** no second regex, registry, scanner, or prose parser may be introduced.
|
||||
- **Alias capture:** aliases must canonicalize before baseline/`roles.local` lookup so local files cannot redefine legacy aliases as separate authority.
|
||||
- **Readable persona requirement:** semantic success requires a resolved readable persona, not class-set membership.
|
||||
- **Scope control:** no roster mutation, lifecycle, lease issuance, certificate workflow/storage, credentials, remote reconciliation, provision-v2 conversion, or shipped-example disposition execution.
|
||||
- **Coordination:** `docs/TASKS.md` is read-only and remains orchestrator-owned.
|
||||
|
||||
## Acceptance-evidence mapping
|
||||
|
||||
| Requirement / criterion | Verification evidence |
|
||||
| --- | --- |
|
||||
| `FCM-REQ-02` shared semantic resolver | Async/sync resolver parity; roster-v2 delegates batched scans and resolution; profiles/provision and launch reuse `fleet-personas.ts`; no second scanner or class-marker regex added. |
|
||||
| `FCM-REQ-07` canonical classes and authority boundaries | Exact alias and non-alias tests; immutable authority invariant tests; all required canonical contracts resolve through the real role library. |
|
||||
| `AC-FCM-01` structural + semantic roster validation | Synchronous parser/normalizer tests remain intact; async semantic tests cover aliases, custom roles, unreadable/unresolved roles, `LIBRARY`-only rejection, and bidirectional protected policy mismatch. |
|
||||
| `AC-FCM-07` protected authority invariants | Denial tests prove merge-gate-only merge, validator certificate-only, orchestrator/team-leader/interaction limits, no implicit custom-role authority, and canonical tool-policy matching. |
|
||||
|
||||
## Documentation
|
||||
|
||||
- `docs/fleet/reference/role-classes.md`
|
||||
- `docs/fleet/migration/legacy-class-aliases.md`
|
||||
- `docs/fleet/how-to/customize-roles.md`
|
||||
- `docs/fleet/reference/roster-v2-fields.md` semantic handoff
|
||||
- Baseline role contracts and `LIBRARY.md` rows for `validator`, `team-leader`, and `interaction`
|
||||
|
||||
## Residual risks
|
||||
|
||||
- Provisioning remains intentionally v1 and does not emit `reports_to`; canonical topology is retained
|
||||
in its typed seat/summary path only, matching the existing v1 parser boundary.
|
||||
- Alias support remains for compatibility; new configuration should emit canonical identities.
|
||||
- This card defines authority metadata and validation only. Enforcement workflows for leases,
|
||||
certificates, lifecycle, and mutation remain owned by later FCM cards.
|
||||
Reference in New Issue
Block a user