--- kind: task slug: audit-instrument-rate-limit-trips title: Write audit-log rows on every rate-limit trip plan_slug: multitenant-saas-hardening epic_slug: tenant-lifecycle status: draft priority: P2 tenant_id: global owner: unassigned cursor_todo_id: null updated_at: "2026-06-02" --- # Task summary Rate-limit trips currently only go to stdout (`console.warn`). The parent task spec called for an `audit_log` row on every trip so we can: 1. See in the audit view whether anyone's actually hitting the limits in practice. 2. Build abuse-signal dashboards on top of `audit_log` instead of scraping logs. This is a small follow-up because we kept `Task-rate-limit-and-abuse-guardrails` scoped to "the wire-ins ship cleanly" and didn't want to churn `auth.ts` and `invites.ts` a second time inside the same task. ## Subtasks - [ ] At every `if (!rl.allowed) { ... }` site, call `recordAudit(...)` before the rejection. For the Credentials path, the workspace context isn't known (the user isn't even authenticated yet), so we need a different write path: - Option A: skip audit for sign-in trips and only log to stdout (current behavior). - Option B: add a `system_audit_log` table for non-workspace events (sign-in attempts, rate-limit trips on unauthenticated routes). - Option C: stamp `workspace_id = '00000000-0000-0000-0000-000000000000'` as a sentinel "system" workspace. - Recommended: **A for v1** (no schema change), revisit when we have a real need for cross-workspace audit. For workspace-scoped trips (invite-create), use the regular `recordAudit()` flow. - [ ] Wire `recordAudit` into the `invites.create` rate-limit branch. Action: `rate_limit.tripped`. Metadata: `{ key, retry_after_ms, limit, window_ms }`. - [ ] Add the `rate_limit.tripped` action to the audit page's `ACTION_LABELS` map. ## Acceptance criteria - [ ] Triggering the `invites.create` rate-limit produces a `rate_limit.tripped` row in the audit view. - [ ] Sign-in trips remain logged to stdout (decision A above) until a `system_audit_log` table is justified. ## Links - Parent: `./Task-rate-limit-and-abuse-guardrails.md` - Epic: `./Epic-tenant-lifecycle.md`