FED-M4: search verb + audit log + rate limit #463

Open
opened 2026-04-19 22:02:07 +00:00 by jason.woltje · 0 comments
Owner

Epic: Federation v1 — see docs/federation/PRD.md and docs/federation/MILESTONES.md.

Goal

Keyword search over allowed resources with full audit and per-grant rate limiting.

Scope

  • search verb across resources allowlist (intersection of scope + native RBAC)
  • Keyword search only (pgvector search deferred to post-v1)
  • Every federated request writes to federation_audit_log: grant_id, verb, resource, query_hash, outcome, bytes_out, latency_ms
  • No request body captured; query_hash = SHA-256 of normalized query
  • Token-bucket rate limit per grant (default 60/min, override per grant)
  • 429 response with Retry-After and structured body
  • 90-day hot retention; cold rollover deferred to FED-M7

Deliverables

  • apps/gateway/src/federation/server/verbs/search.controller.ts
  • apps/gateway/src/federation/server/audit.service.ts (async, non-blocking)
  • apps/gateway/src/federation/server/rate-limit.guard.ts

Acceptance Tests

  • search returns ranked hits only from allowed resources
  • search excluding credentials returns no credential hits even when keyword matches
  • Every successful request appears in federation_audit_log within 1s
  • Denied request (403) also audited with outcome='denied'
  • Audit row stores query hash, NOT query body
  • 61st request in 60s window returns 429 with Retry-After
  • Per-grant override (e.g., 600/min) takes effect without restart
  • Audit writes are async: request latency unchanged when audit write slow

Dependencies

Blocked by FED-M3.

Estimated budget

~20K tokens

Risk notes

Audit writes must not block request path. Use bounded queue with drop-with-counter pattern, not in-line writes.

**Epic:** Federation v1 — see `docs/federation/PRD.md` and `docs/federation/MILESTONES.md`. ## Goal Keyword search over allowed resources with full audit and per-grant rate limiting. ## Scope - `search` verb across `resources` allowlist (intersection of scope + native RBAC) - Keyword search only (pgvector search deferred to post-v1) - Every federated request writes to `federation_audit_log`: `grant_id`, `verb`, `resource`, `query_hash`, `outcome`, `bytes_out`, `latency_ms` - No request body captured; `query_hash` = SHA-256 of normalized query - Token-bucket rate limit per grant (default 60/min, override per grant) - 429 response with `Retry-After` and structured body - 90-day hot retention; cold rollover deferred to FED-M7 ## Deliverables - `apps/gateway/src/federation/server/verbs/search.controller.ts` - `apps/gateway/src/federation/server/audit.service.ts` (async, non-blocking) - `apps/gateway/src/federation/server/rate-limit.guard.ts` ## Acceptance Tests - [ ] `search` returns ranked hits only from allowed resources - [ ] `search` excluding `credentials` returns no credential hits even when keyword matches - [ ] Every successful request appears in `federation_audit_log` within 1s - [ ] Denied request (403) also audited with `outcome='denied'` - [ ] Audit row stores query hash, NOT query body - [ ] 61st request in 60s window returns 429 with `Retry-After` - [ ] Per-grant override (e.g., 600/min) takes effect without restart - [ ] Audit writes are async: request latency unchanged when audit write slow ## Dependencies Blocked by **FED-M3**. ## Estimated budget ~20K tokens ## Risk notes Audit writes must not block request path. Use bounded queue with drop-with-counter pattern, not in-line writes.
jason.woltje added this to the Federation v1 milestone 2026-04-19 22:02:07 +00:00
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#463