Files
stack/docs/scratchpads/FED-M3-05-list-verb.md
jason.woltje 86e106fcc9
All checks were successful
ci/woodpecker/push/publish Pipeline was successful
ci/woodpecker/push/ci Pipeline was successful
feat(#462): add federation list verb (#682)
2026-06-25 02:15:17 +00:00

3.3 KiB

FED-M3-05 — Federation List Verb Scratchpad

Objective

Implement POST /api/federation/v1/list/:resource.

Scope

  • Wire FederationAuthGuardFederationScopeService → read-only list query layer.
  • Apply max_rows_per_query row cap and return pagination metadata when truncated.
  • Tag returned rows with _source: "local".
  • Keep audit writes deferred to M4.
  • No request/response body persistence.

Base / branch

  • Branch: feat/federation-m3-verb-list
  • Base: main after M3-04 scope service merged via PR #672 (c739256a).

Implementation notes

  • Added ListController under apps/gateway/src/federation/server/verbs/.
  • Added FederationListQueryService as the read-only query layer and native RBAC evaluator.
  • Query resources supported in M3 list path:
    • tasks: project/mission scoped tasks visible through personal/team project access.
    • notes: non-empty mission_tasks.notes rows visible through personal/team mission access.
    • memory: user-owned insights and preferences rows.
    • credentials / api_keys: denied by native RBAC in M3 even if present in scope; sensitive-resource implementation is not part of FED-M3-05.
  • Cursor pagination uses an opaque base64url keyset cursor over (createdAt, id); DB reads fetch at most limit + 1 rows per resource query.
  • Reviewer isolation fix: mission_tasks.notes rows are always constrained by missionTasks.userId = subjectUserId and accessible mission IDs; team scope narrows missions but never widens to other users' mission task notes.
  • Follow-up review fix: memory listing now uses deterministic table-block pagination (insights first, then preferences) with cursor source metadata, so one table's cursor is never applied to the other.
  • Follow-up hardening: missing auth-guard context returns a structured federation unauthorized envelope; unsupported resources and non-encodable truncated cursors throw instead of silently crashing/truncating.

Tests

  • pnpm --filter @mosaicstack/gateway test -- list.controller.spec.ts list-query.service.spec.ts — PASS (16 tests, including PGlite regression coverage for team-scoped notes isolation, unauthorized mission notes exclusion, includePersonal: false, deterministic memory pagination, missing context envelope, unsupported resource, and cursor encode failure).
  • pnpm --filter @mosaicstack/gateway typecheck — PASS.
  • pnpm --filter @mosaicstack/gateway lint — PASS.
  • pnpm format:check — PASS.
  • pnpm typecheck — PASS (41/41 turbo tasks).
  • pnpm lint — PASS (23/23 turbo tasks).
  • pnpm --filter @mosaicstack/gateway test — FAIL in pre-existing/live-DB integration suite: apps/gateway/src/__tests__/cross-user-isolation.test.ts cleanup cannot connect to local PostgreSQL on localhost:5433. New list tests pass; failure is outside FED-M3-05.

Review evidence

  • ~/.config/mosaic/tools/codex/codex-code-review.sh --uncommitted — PASS after follow-up remediation; approve, no findings.
  • ~/.config/mosaic/tools/codex/codex-security-review.sh --uncommitted — PASS after follow-up remediation; risk level none, no findings.
  • Security-review note: read-path audit logging remains intentionally deferred to M4 per orchestrator clarification and FED-M3-05 scope.

Risks / follow-up

  • Read-path audit logging remains intentionally deferred to M4.