Skip to content

feat(obs): trust-gate at 100% — every /api/* route propagates request IDs#174

Merged
operatoruplift merged 1 commit intomasterfrom
apihelpers-final
Apr 27, 2026
Merged

feat(obs): trust-gate at 100% — every /api/* route propagates request IDs#174
operatoruplift merged 1 commit intomasterfrom
apihelpers-final

Conversation

@operatoruplift
Copy link
Copy Markdown
Owner

Trust-gate hits 100%

The final 3 routes adopt the apiHelpers pattern. After this merges, 44/44 (100%) of /api/* routes import @/lib/apiHelpers and call withRequestMeta.

Route What it does
app/api/tools/tokens/route.ts Tokens API (search, resolve, asset, price, risk, markets)
app/api/subscription/route.ts Subscription GET + POST (create_invoice, dev_simulate, confirm)
app/api/webhooks/photon/route.ts iMessage webhook receiver (signature-verified, idempotent)

Notable

subscription

Already had a hand-rolled requestId + startedAt + X-Request-Id pattern identical in shape to withRequestMeta. Replaced the local newRequestId() function and the manual header construction with the helper. Behavior identical; structured logs now share the canonical route taxonomy.

webhooks/photon

The webhook receiver had no request-id propagation — every response just returned { ok: true, ... }. Adding meta.headers to all 7 response paths (signature-fail, parse-fail, no-supabase, duplicate, insert-error, success, GET health-probe) and including requestId in each body. Spectrum's webhook retry can now correlate to the server log line.

tools/tokens

Tier-1 tokens lookup tool. Already had a clean honest demo-mode 403 guard from earlier session work; this PR standardizes the error envelope (errorClass, requestId, timestamp, nextAction) and adds X-Request-Id to every response.

Trust-gate journey

PR Coverage Δ
baseline 11/44 (25%)
#167 16/44 (36%) +5
#168 21/44 (48%) +5
#169 26/44 (59%) +5
#170 30/44 (68%) +4
#171 33/44 (75%) +3
#172 37/44 (84%) +4
#173 41/44 (93%) +4
this PR 44/44 (100%) +3

8 PRs to take request-id propagation from 25% → 100% of routes.

Verified

pnpm exec tsc --noEmit
# exit 0

pnpm check
trust-gate: clean. 44/44 route files import @/lib/apiHelpers and all call withRequestMeta.
check: 3 passed, 0 failed, 0 skipped

Net diff

3 files changed, 52 insertions(+), 46 deletions(-)

Rollback

Single git revert.

The final 3 routes adopt the apiHelpers pattern. Trust-gate now reports
44/44 route files import @/lib/apiHelpers and all call withRequestMeta.

| Route | What it does |
|---|---|
| app/api/tools/tokens/route.ts | Tokens API (search, resolve, asset, price, risk, markets) |
| app/api/subscription/route.ts | Subscription GET + POST (create_invoice, dev_simulate, confirm) |
| app/api/webhooks/photon/route.ts | iMessage webhook receiver (signature-verified, idempotent) |

## Notable

### subscription
Already had a hand-rolled requestId + startedAt + X-Request-Id pattern
identical in shape to withRequestMeta. Replaced the local newRequestId()
function and the manual header construction with the helper. Behavior
identical; structured logs share a single `route` taxonomy.

### webhooks/photon
The webhook receiver had no request-id propagation, every response
just returned `{ ok: true, ... }`. Adding meta.headers to all 7
response paths (signature-fail, parse-fail, no-supabase, duplicate,
insert-error, success, GET-health-probe) and including requestId in
each body. Spectrum's webhook retry can now correlate to the server
log line.

### tools/tokens
Tier-1 tokens lookup tool. Already had a clean honest demo-mode 403
guard from earlier session work; this PR standardizes the error
envelope (errorClass, requestId, timestamp, nextAction) and adds
X-Request-Id to every response.

## Trust-gate journey

11/44 (25%) -> 16/44 -> 21/44 -> 26/44 -> 30/44 -> 33/44 -> 37/44 ->
41/44 -> 44/44 (100%) across PRs #167-#173 plus this one.

## Verified

- pnpm exec tsc --noEmit: clean
- pnpm check: 3 passed, 0 failed
- trust-gate: 44/44 route files (100%)

## Rollback

Single git revert. 3 files.
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
website Ready Ready Preview, Comment Apr 27, 2026 3:07pm

@operatoruplift operatoruplift merged commit fc4683c into master Apr 27, 2026
4 checks passed
operatoruplift added a commit that referenced this pull request Apr 27, 2026
#183)

The middleware was a hidden gap in the trust-gate contract. Source
trust-gate (#167-#174) confirmed every route file imports
withRequestMeta. But the middleware in middleware.ts intercepts every
/api/* request first, and its 401 "Authentication required" response
went out without an X-Request-Id header.

Two changes:

## middleware.ts
- Mints `req_<uuid>` if the incoming request doesn't already carry an
  X-Request-Id, otherwise propagates.
- Attaches the ID to:
  - the 401 unauthorized response (status, body envelope, header)
  - every pass-through (forwarded as a request header so the route
    handler's `withRequestMeta` reads the same value)
- The 401 body now also carries `requestId` and `timestamp` to match
  the canonical envelope shape.

## tests/e2e/request-id-runtime.spec.ts (new)
- 16 probes against representative endpoints, all four response
  shapes (200 success, 401 middleware-block, 400/410/403 handler
  envelopes).
- Each asserts `X-Request-Id` is present and matches `^req_[0-9a-f-]+`.
- Picked endpoints to cover: public (capabilities, providers,
  sns.resolve, health.adapters, health.llm, waitlist, auth.login),
  auth-gated (whoami, dashboard.stats, receipts.public-key,
  subscription, x402, tools.web, tools.notes, access.check, risk).

## .github/workflows/ci.yml
- request-id-runtime.spec.ts joins the hermetic spec list, so a
  middleware regression that drops the header fails CI before merge.

Trust-gate is now enforced at BOTH layers: source (every route file
imports the helper) and runtime (every response carries the header).

## Verified

- pnpm exec tsc --noEmit: clean
- pnpm check: 3 passed, 0 failed
- pnpm exec playwright test request-id-runtime.spec.ts: 16/16 pass

## Rollback

Single git revert. Three files.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant