feat(#462): add federation scope enforcement service #672

Merged
jason.woltje merged 2 commits from feat/federation-m3-scope-service into main 2026-06-24 23:22:47 +00:00
Owner

Summary

Implements FED-M3-04: pure server-side federation scope enforcement service.

  • Adds FederationScopeService with structured allow/deny results for M4 audit.
  • Reuses parseFederationScope and enforces:
    1. resource allowlist + excluded_resources
    2. native RBAC via injected evaluator as subjectUserId
    3. include_teams / include_personal intersection without widening RBAC
    4. max_rows_per_query caps
  • Exports/registers the service for upcoming M3 list/get verb controllers.
  • Adds unit tests for all deny paths and scope/RBAC intersection behavior.

Verification

  • pnpm --filter @mosaicstack/gateway test -- src/federation/server/__tests__/scope.service.spec.ts — pass (10 tests)
  • pnpm build — pass
  • pnpm typecheck — pass
  • pnpm lint — pass
  • pnpm format:check — pass
  • pnpm test — pass after local postgres/valkey + pnpm --filter @mosaicstack/db db:push for DB-backed suites
  • ~/.config/mosaic/tools/codex/codex-code-review.sh --uncommitted — approve, 0 findings
  • ~/.config/mosaic/tools/codex/codex-security-review.sh --uncommitted — risk none, 0 findings

Notes

  • docs/federation/TASKS.md is orchestrator-owned, so this PR does not edit it.
  • Provider issue #462 appears already closed, but this PR references the assigned milestone issue.
  • No self-merge; independent reviewer gate required for this trust-boundary change.

Refs #462

## Summary Implements FED-M3-04: pure server-side federation scope enforcement service. - Adds `FederationScopeService` with structured allow/deny results for M4 audit. - Reuses `parseFederationScope` and enforces: 1. resource allowlist + `excluded_resources` 2. native RBAC via injected evaluator as `subjectUserId` 3. `include_teams` / `include_personal` intersection without widening RBAC 4. `max_rows_per_query` caps - Exports/registers the service for upcoming M3 list/get verb controllers. - Adds unit tests for all deny paths and scope/RBAC intersection behavior. ## Verification - `pnpm --filter @mosaicstack/gateway test -- src/federation/server/__tests__/scope.service.spec.ts` — pass (10 tests) - `pnpm build` — pass - `pnpm typecheck` — pass - `pnpm lint` — pass - `pnpm format:check` — pass - `pnpm test` — pass after local `postgres`/`valkey` + `pnpm --filter @mosaicstack/db db:push` for DB-backed suites - `~/.config/mosaic/tools/codex/codex-code-review.sh --uncommitted` — approve, 0 findings - `~/.config/mosaic/tools/codex/codex-security-review.sh --uncommitted` — risk none, 0 findings ## Notes - `docs/federation/TASKS.md` is orchestrator-owned, so this PR does not edit it. - Provider issue #462 appears already closed, but this PR references the assigned milestone issue. - No self-merge; independent reviewer gate required for this trust-boundary change. Refs #462
jason.woltje added 1 commit 2026-06-24 21:02:59 +00:00
feat(#462): add federation scope enforcement service
All checks were successful
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
95e939f152
jason.woltje added 1 commit 2026-06-24 21:41:52 +00:00
test(#462): cover native RBAC personal scope intersection
Some checks are pending
ci/woodpecker/push/ci Pipeline is pending
ci/woodpecker/pr/ci Pipeline is pending
758d73a6d1
jason.woltje force-pushed feat/federation-m3-scope-service from 758d73a6d1 to a648c8c64d 2026-06-24 21:44:42 +00:00 Compare
Author
Owner

REVIEW-OF-RECORD — APPROVE ON MERITS (FED-M3-04 scope.service). Re-review after commit a648c8c6 confirms the prior blocker is closed: new test covers native RBAC includePersonal=false winning even when federation scope requests include_personal=true. Scope pipeline remains sound: invalid scope/resource/excluded/not-granted/invalid-limit/native-RBAC deny paths return structured { allowed:false, deny:{ code, stage, statusCode, grantId, peerId, subjectUserId, resource } } with no partial data; RBAC evaluation is as subjectUserId via injected evaluator; include_teams intersection cannot widen native RBAC; row limit is capped by max_rows_per_query. Rebase preserved QuerySourceService + CapabilitiesController + FederationScopeService module registration. Reviewer verification: scope.service.spec 11/11 pass; scope-schema.spec 18/18 pass; gateway typecheck pass; gateway lint pass; prettier check pass.

REVIEW-OF-RECORD — APPROVE ON MERITS (FED-M3-04 scope.service). Re-review after commit a648c8c6 confirms the prior blocker is closed: new test covers native RBAC includePersonal=false winning even when federation scope requests include_personal=true. Scope pipeline remains sound: invalid scope/resource/excluded/not-granted/invalid-limit/native-RBAC deny paths return structured { allowed:false, deny:{ code, stage, statusCode, grantId, peerId, subjectUserId, resource } } with no partial data; RBAC evaluation is as subjectUserId via injected evaluator; include_teams intersection cannot widen native RBAC; row limit is capped by max_rows_per_query. Rebase preserved QuerySourceService + CapabilitiesController + FederationScopeService module registration. Reviewer verification: scope.service.spec 11/11 pass; scope-schema.spec 18/18 pass; gateway typecheck pass; gateway lint pass; prettier check pass.
jason.woltje force-pushed feat/federation-m3-scope-service from a648c8c64d to 8bd288a7db 2026-06-24 22:59:16 +00:00 Compare
Author
Owner

REVIEW-OF-RECORD — APPROVE — stands on rebased SHA 8bd288a7db. Prior approval id=15903 remains valid; this was a pure rebase onto main fc2970916f with no content change to the reviewed scope.service diff.

REVIEW-OF-RECORD — APPROVE — stands on rebased SHA 8bd288a7dbe784c0e1d57afcba85802d4197dd4b. Prior approval id=15903 remains valid; this was a pure rebase onto main fc2970916f with no content change to the reviewed scope.service diff.
Author
Owner

REVIEW-OF-RECORD — APPROVE (#672 FED-M3-04 scope.service) — head 8bd288a7db. Re-read the rebased diff and verified the trust-boundary behavior: parseFederationScope is reused before access evaluation; invalid scope/resource/excluded/not-granted/invalid-limit/native-RBAC deny paths return structured { allowed:false, deny:{ code, stage, statusCode, grantId, peerId, subjectUserId, resource } } with no partial data; native RBAC is evaluated as subjectUserId through the injected evaluator; include_teams and include_personal intersect with native RBAC and do not widen access; max_rows_per_query caps requested limits. The previous include_personal blocker is covered by the native-RBAC-personal-deny test. Reviewer verification on rebased SHA: scope.service.spec 11/11 pass; scope-schema.spec 18/18 pass; gateway typecheck pass; gateway lint pass; prettier check pass. APPROVE.

REVIEW-OF-RECORD — APPROVE (#672 FED-M3-04 scope.service) — head 8bd288a7dbe784c0e1d57afcba85802d4197dd4b. Re-read the rebased diff and verified the trust-boundary behavior: parseFederationScope is reused before access evaluation; invalid scope/resource/excluded/not-granted/invalid-limit/native-RBAC deny paths return structured { allowed:false, deny:{ code, stage, statusCode, grantId, peerId, subjectUserId, resource } } with no partial data; native RBAC is evaluated as subjectUserId through the injected evaluator; include_teams and include_personal intersect with native RBAC and do not widen access; max_rows_per_query caps requested limits. The previous include_personal blocker is covered by the native-RBAC-personal-deny test. Reviewer verification on rebased SHA: scope.service.spec 11/11 pass; scope-schema.spec 18/18 pass; gateway typecheck pass; gateway lint pass; prettier check pass. APPROVE.
jason.woltje merged commit c739256a2c into main 2026-06-24 23:22:47 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#672