← all branches

feat/one-api

needs attentionviewing older commit
45699ca · incrementalpre-PRreviewed 2026-08-09 17:44 UTC0H · 7M · 11L · 12I
The branch
Purpose
Harden the public API's security posture and clean up a zero-user webhook surface before the branch promotes to a PR
Goal
Remove webhook-endpoint entirely (zero users, sealing-key dependency); close the OAuth /v1/auth/oauth/token gaps (rate limiting, telemetry); fix session-actor principal leak; make security-critical test assertions non-vacuous
Sub-goals
  • SG-1: Remove webhook-endpoint domain entity, API contract/handler/mapper, DB migration, EventBridge dispatcher, MCP tool
  • SG-2: Add rate limiting + telemetry to standalone OAuth route (was bypassing withMetaGate)
  • SG-3: Fix session-actor principal to not persist Supabase uid; fix telemetry gate to actor===anonymous
  • SG-4: Fix IDOR probe bodies to reach org gate (not die at body validation); fix RLS test to be non-vacuous; fix profile race retry
The changes (whole branch)
What
60 files in this incremental window: domain code + API surface for webhooks fully deleted; OAuth route now has rate limit + telemetry; meta-gate principal and telemetry gate logic fixed; wizard error mapping fixed; IDOR/RLS integration tests hardened
Why
PR #389 review panel surfaced these as unresolved issues before the branch can promote; this commit acts on all of them
Areas
apps/platform+34213928domains/core+13813293packages/api+6611347packages/database+121916342domains/utility+132303packages/event-bus+1168packages/mcp-server+851infra/cdk+952.claude/rules+55321
Blast
60 files in this window, +13k/-2.8k; cumulative branch: 221 files. Core removal areas: domains/core (-3.3k), packages/database (+122k bulk from migration snapshot), apps/platform net -507 (deletions exceed additions).
security-surface-removal standalone-route-outside-meta-gate rate-limit-scope-question
ci· pre-PR branch — no CI rollup availablecoderabbit· no .coderabbit.yaml

Findings · 24

correctness5

medium

OAuth route emits no telemetry on 429 rate-limit rejection

apps/platform/src/app/api/v1/auth/oauth/token/route.ts:87

When the rate limiter fires, emit() is never called. Rate-limit hits on sk_ probing are invisible to api_request_events.

medium

WizardDecisionError 403/404 statusCodes silently flatten to 422

apps/platform/src/api/handlers/utility-contracts.handler.ts:742

The new branch maps statusCode===409→conflict(), everything else→422. Wizard can emit 404/403 wrapped in WizardDecisionError; these surface as 422 — semantically wrong.

low

IDOR afterAll cleanup deletes metric_type by variable, not public_id

apps/platform/src/__tests__/integration/public-v1-idor.test.ts:253

More aggressive than needed; prefer DELETE WHERE public_id = IDOR_METRIC_TYPE_ID.

low

Profile retry: second-attempt error tag misclassified on username collision

domains/core/src/profile/profile.shells.ts:167

Cosmetic misclassification; no behavioral regression.

info

Session actor principal=null rows now persist to api_request_events

apps/platform/src/api/utils/public-v1-meta-gate.ts:149

Intentional. Queries joining principal→api_keys.public_id implicitly exclude session-actor rows. Fine for W2; revisit at W3.

security5

medium

OAuth rate-limit bucket is independent of the sibling /v1/auth/token bucket

apps/platform/src/app/api/v1/auth/oauth/token/route.ts:86

Two independent 10/min windows rather than a shared auth-family budget. Doc comment claims parity but it is not true.

medium

x-forwarded-for is client-spoofable — no credential-hash fallback on OAuth route

apps/platform/src/app/api/v1/auth/oauth/token/route.ts:83

Safe on Vercel CDK topology but not enforced by code. Main ts-rest route has token-hash fallback; OAuth route has none.

low

Multi-membership session actors land in memberships[0] org — unreliable for attribution

apps/platform/src/api/utils/public-v1-meta-gate.ts:149

Data-quality concern, not a security boundary issue.

info

Sealed-secret exports removed cleanly — no dangling consumers

domains/core/src/index.ts:1

Grep confirms no remaining production references. Reduces attack surface.

info

IDOR harness: webhook probes correctly removed, metric_type probe reaches org gate

apps/platform/src/__tests__/integration/public-v1-idor.test.ts:175

Real metric_type needed because handler resolves it before site check.

conventions5

medium

unauthorized.ts placed in mappers/public-v1/ but is a shared constant, not a mapper

apps/platform/src/api/mappers/public-v1/unauthorized.ts:1

Per canonical-form.md, mappers/ owns domain→response mapping. Constant belongs in utils/. Also defines a subtly different 401 message from withMetaGate's own UNAUTHORIZED constant.

medium

OAuth route rate-limit bucket is a free-form string, not a registry-derived key

apps/platform/src/app/api/v1/auth/oauth/token/route.ts:86

Route correctly outside withMetaGate (per BAT-294), but the rate-limit bucket '/v1/auth/oauth/token' is not the canonical route key derived from the registry.

low

MCP server README not updated in same change (mcp-server.md rule step 4)

packages/mcp-server/README.md:1

May be stale if it previously listed webhook tools.

info

route-inventory.json and guard test count updated consistently

scripts/one-api/route-inventory.json:1

3 webhook routes removed; inventory and guard test (≥48→≥45) are consistent.

info

Migration 0073 drops webhook_endpoints — schema file and Drizzle export also removed

packages/database/drizzle/0073_light_ted_forrester.sql:1

Migration, schema, and domain code consistently removed.

tests5

medium

Session-actor telemetry gate change has no regression test

apps/platform/src/api/utils/__tests__/public-v1-meta-gate.test.ts:191

Reverting the gate from actor==='anonymous' back to principal===null would silently drop session-actor rows again with all tests green.

low

IDOR_METRIC_TYPE_ID uses 24-char ULID part (canonical is 26)

apps/platform/src/__tests__/integration/public-v1-idor.test.ts:67

Functionally harmless; cosmetically inconsistent with convention.

low

KEY_A constant uses 24-char ULID part (canonical is 26)

apps/platform/src/__tests__/integration/rls-machine-claim.test.ts:40

Functionally harmless; cosmetically inconsistent with convention.

info

OAuth rate-limit test correctly asserts DB lookup skipped on 429

apps/platform/src/app/api/v1/auth/oauth/token/__tests__/route.test.ts:170

findActiveByPrefix not-called assert confirms guard fires before DB lookup.

info

RLS machine-claim non-vacuous guard: pre-assertion proves row exists before checking machine cannot see it

apps/platform/src/__tests__/integration/rls-machine-claim.test.ts:170

Textbook non-vacuous pattern. Correctly eliminates empty-table false-pass.

improvement4

low

MCP server JSDoc header still lists 'webhooks' as an exposed capability

packages/mcp-server/src/index.ts:6

Webhook tools correctly tombstoned at line 315 but module-level description not updated.

low

x-forwarded-for IP extraction duplicated in 3 places without shared utility

apps/platform/src/app/api/v1/auth/oauth/token/route.ts:83

Also in ts-rest mount route and auth.handler.ts (which has richer x-real-ip/cf-connecting-ip fallback).

low

Inline emit() actor mapping diverges from withMetaGate's actorType map

apps/platform/src/app/api/v1/auth/oauth/token/route.ts:96

Correct today (service keys only); won't track future credential classes added to withMetaGate automatically.

info

unauthorized.ts comment references its webhook provenance — can be trimmed

apps/platform/src/api/mappers/public-v1/unauthorized.ts:3

Accurate history but noisy. Minor.

History · 47 commits

  1. 82bb5b9blockedincremental5H · 5M · 4L2026-08-12 01:48
  2. 90aa3d5needs attentionincremental1H · 5M · 3L2026-08-11 19:37
  3. 29d19a0needs attentionincremental1H · 5M · 9L2026-08-11 17:41
  4. 9bd8a0cneeds attentionfull0H · 5M · 9L2026-08-11 02:14
  5. 62ec3f7needs attentionincremental2H · 5M · 6L2026-08-10 22:51
  6. f93bca9needs attentionincremental2H · 5M · 8L2026-08-10 17:51
  7. 052db6fneeds attentionincremental1H · 3M · 4L2026-08-09 21:13
  8. 45699caneeds attentionincremental0H · 7M · 11L2026-08-09 17:44current
  9. b843d8aneeds attentionincremental1H · 7M · 9L2026-08-09 04:05
  10. e1757b8needs attentionincremental0H · 3M · 6L2026-08-05 02:11
  11. 7a762faneeds attentionincremental2H · 5M · 5L2026-08-05 01:25
  12. 3300a60needs attentionincremental2H · 4M · 7L2026-08-04 19:06
  13. 0c8a7f5needs attentionincremental0H · 4M · 9L2026-08-04 18:15
  14. 345f42eneeds attentionincremental2H · 6M · 9L2026-08-04 17:28
  15. 8338a9aneeds attentionincremental5H · 14M · 14L2026-08-04 00:33
  16. 41be4c3needs attentionincremental0H · 5M · 7L2026-08-03 23:49
  17. 5ed593dneeds attentionincremental1H · 6M · 6L2026-08-03 21:32
  18. b333e25needs attentionincremental4H · 9M · 8L2026-08-03 21:00
  19. 5642cccneeds attentionincremental2H · 3M · 2L2026-08-03 20:17
  20. 73b0b39needs attentionincremental3H · 10M · 13L2026-07-31 18:29
  21. b19852eneeds attentionincremental0H · 1M · 5L2026-07-29 05:04
  22. 3845205needs attentionincremental3H · 6M · 4L2026-07-29 04:47
  23. eb8eb50needs attentionincremental0H · 1M · 2L2026-07-29 03:03
  24. f4720a3needs attentionincremental6H · 8M · 7L2026-07-29 02:54
  25. f8d341ablockedincremental2H · 2M · 5L2026-07-29 00:00
  26. a7f1a64needs attentionincremental2H · 8M · 8L2026-07-28 18:41
  27. 738b60bblockedincremental3H · 6M · 5L2026-07-28 00:46
  28. 2c248b6needs attentionincremental8H · 12M · 8L2026-07-27 23:23
  29. 1346cc0needs attentionincremental2H · 8M · 6L2026-07-27 20:15
  30. 0716018needs attentionincremental2H · 11M · 12L2026-07-27 19:22
  31. 215cd2dneeds attentionincremental3H · 6M · 5L2026-07-27 17:04
  32. ec46958needs attentionincremental0H · 3M · 5L2026-07-27 16:51
  33. de7b337blockedincremental4H · 9M · 14L2026-07-27 06:36
  34. b1bb9c0needs attentionincremental1H · 2M · 4L2026-07-27 05:09
  35. 4701d11needs attentionincremental0H · 4M · 3L2026-07-27 04:44
  36. e1626c4needs attentionincremental3H · 9M · 10L2026-07-27 03:21
  37. 195f198needs attentionincremental3H · 3M · 3L2026-07-25 01:22
  38. 42c7358safeincremental0H · 0M · 0L2026-07-22 20:46
  39. 85b9018needs attentionincremental0H · 1M · 6L2026-07-21 23:51
  40. a7b2a9aneeds attentionincremental0H · 9M · 12L2026-07-21 18:49
  41. c2ee0daneeds attentionincremental4H · 7M · 7L2026-07-21 02:17
  42. e8ffa5eneeds attentionincremental4H · 7M · 5L2026-07-21 01:33
  43. a2d2a54needs attentionincremental2H · 7M · 3L2026-07-21 00:51
  44. 576fbd6needs attentionfull1H · 6M · 7L2026-07-21 00:35
  45. d3465e8needs attentionincremental1H · 7M · 10L2026-07-21 00:23
  46. dc794a7needs attentionincremental0H · 5M · 5L2026-07-20 23:46
  47. 9082773needs attentionfull1H · 3M · 3L2026-07-20 23:13