feat(obs): apiHelpers on 5 more routes + drop fake demo stats from /api/dashboard/stats#167
Merged
operatoruplift merged 1 commit intomasterfrom Apr 27, 2026
Merged
Conversation
Two improvements in one PR. ## (1) Trust-gate coverage 11/44 -> 16/44 Five small routes adopted the @/lib/apiHelpers withRequestMeta pattern that the larger /api/tools/* routes already use (PR #123) and the observability sweep extended to the receipts/memory/agents/ notifications/audit families (PR #130). Now every response from these routes carries `X-Request-Id`, supporting the request-id propagation contract trust-gate enforces. Routes: - app/api/providers/route.ts (6 lines) - app/api/capabilities/route.ts (25 lines) - app/api/receipts/public-key/route.ts (26 lines) - app/api/health/llm/route.ts (27 lines) - app/api/dashboard/stats/route.ts (31 lines) ## (2) Fix the residual fabrication in /api/dashboard/stats While adding apiHelpers I found one more fabrication leftover: when the route's auth check fails, it was returning a hardcoded fallback payload: { activeAgents: 14, chatSessions: 8, memoryNodes: 12400, securityBlocks: 47, } These are the **exact same fake values** PR #164 removed from the rendered dashboard. The dashboard now reads from localStorage directly so it doesn't call this route, but anything else that hits /api/dashboard/stats unauthenticated still got the lie. Now: returns zeros on the unauthenticated path. No fake demo data. ## Trust impact Closes the dashboard fabrication arc started in #164/#165/#166. Adds the request-id contract to 5 more routes. ## Verified - pnpm exec tsc --noEmit: clean - pnpm check: 3 passed, 0 failed - trust-gate: 16/44 route files (was 11/44) ## Rollback Single git revert. 5 files.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
operatoruplift
added a commit
that referenced
this pull request
Apr 27, 2026
) Continuing the broadening from #167 / #168. Five more routes adopt the withRequestMeta / errorResponse / validationError pattern. | Route | Lines | Audience | |---|---|---| | app/api/waitlist/route.ts | 40 | Public signup | | app/api/access/check/route.ts | 52 | Beta access gate | | app/api/access/verify-payment/route.ts | 62 | On-chain payment confirm | | app/api/integrations/google/connect/route.ts | 65 | OAuth start | | app/api/integrations/google/callback/route.ts | 59 | OAuth complete | The two integrations routes are notable because they redirect to `/integrations?error=...` instead of returning JSON. Both now append `&ref=<requestId>` to the redirect URL so support can correlate the oauth-failure URL the user sees with the server log line, and `withRequestMeta` still attaches `X-Request-Id` to the redirect. The Google callback also gets a structured one-line JSON log on the error path (matching the shape `errorResponse()` would produce, but in-line because the response is a redirect, not a JSON envelope). ## Verified - pnpm exec tsc --noEmit: clean - pnpm check: 3 passed, 0 failed - trust-gate: 26/44 route files (was 21/44) ## Rollback Single git revert. 5 files.
operatoruplift
added a commit
that referenced
this pull request
Apr 27, 2026
) Continuing the broadening from #167 / #168 / #169. Four more routes adopt the withRequestMeta / errorResponse / validationError pattern. | Route | What it does | |---|---| | app/api/profile/briefing/route.ts (GET + PUT) | Daily-briefing toggle on Profile | | app/api/tools/notes/route.ts | Tier-1 notes tool (Supabase) | | app/api/tools/tasks/route.ts | Tier-1 tasks tool (Supabase) | | app/api/tools/imessage/route.ts | Photon iMessage send | The four /api/tools/* routes already had a clean honest-status flow (503 + action_required when an adapter is inactive, no fake success on demo callers); this PR adds the X-Request-Id + structured error envelope on top so the diagnostic line in CI logs and the response header agree on the request identifier. The imessage route's adapter-not-configured response now also carries the canonical fields (errorClass: 'provider_unavailable', requestId, timestamp, nextAction) so the chat UI can render it the same way it renders calendar/gmail provider errors. ## Verified - pnpm exec tsc --noEmit: clean - pnpm check: 3 passed, 0 failed - trust-gate: 30/44 route files (was 26/44) ## Rollback Single git revert. 4 files.
operatoruplift
added a commit
that referenced
this pull request
Apr 27, 2026
) Continuing the broadening from #167-#170. Three more routes adopt the withRequestMeta / errorResponse / validationError pattern. | Route | What it does | |---|---| | app/api/tools/web/route.ts | Web search + page fetch (Tier 1 tool) | | app/api/tools/reminders/route.ts | Morning nudges (Tier 1 tool) | | app/api/whoami/route.ts | Admin auth diagnostic (paywall bypass debug) | The whoami route is particularly useful for support, ops can pass ?ref=<requestId> when troubleshooting a paywall-bypass issue and the response carries the matching requestId for log correlation. Web + reminders both already had the honest "demo_mode/simulated:true" guard from the earlier session work, this PR just standardizes the error envelopes (errorClass, requestId, timestamp, nextAction) and attaches X-Request-Id to every response. ## Verified - pnpm exec tsc --noEmit: clean - pnpm check: 3 passed, 0 failed - trust-gate: 33/44 route files (was 30/44) ## Rollback Single git revert. 3 files.
operatoruplift
added a commit
that referenced
this pull request
Apr 27, 2026
…> 37/44) (#172) Continuing the broadening from #167-#171. Four more routes adopt the withRequestMeta / errorResponse / validationError pattern. | Route | What it does | |---|---| | app/api/chat/route.ts | Main chat endpoint (highest-traffic) | | app/api/cron/daily-briefing/route.ts | Cron job: daily agenda pinned message | | app/api/cron/morning-briefing/route.ts | Cron job: 8am self-to-self Gmail summary | | app/api/dev/reliability/timeout/route.ts | Admin-gated 504 simulator for /dev/reliability | The chat route already had a private newRequestId() and a manual {requestId, startedAt} hand-roll. This PR replaces both with the canonical helper. Behavior is identical; the structured logs now share a single `route` taxonomy ("chat" instead of inline string). Both cron routes now log with a real requestId so a Vercel cron failure can be traced from the cron log -> server log without guessing. The unauthenticated-cron 401 also carries the requestId so an attacker who probes the cron endpoint shows up in logs with a correlatable identifier. The reliability timeout harness already had a hand-rolled requestId identical in shape to withRequestMeta's. Replaced. ## Verified - pnpm exec tsc --noEmit: clean - pnpm check: 3 passed, 0 failed - trust-gate: 37/44 route files (was 33/44) ## Rollback Single git revert. 4 files.
operatoruplift
added a commit
that referenced
this pull request
Apr 27, 2026
…on (#173) Trust-gate 37/44 -> 41/44 (~93%). Includes one residual honesty fix. ## Routes adopted | Route | What it does | |---|---| | app/api/debug/subscription/route.ts | Admin paywall diagnostic | | app/api/debug/solana-wallet/route.ts | Admin x402 wallet diagnostic | | app/api/tools/x402/route.ts | x402 fetch proxy + retry-with-proof | | app/api/audit/publish-root/route.ts | Merkle-root publish to Anchor program | ## Honesty fix: x402 "charge" action retired While adopting apiHelpers on app/api/tools/x402/route.ts I caught a residual fabrication in the legacy "charge" action. It was building a chargeRecord with `tx_signature: \`x402-devnet-${Date.now()}\``, a fake transaction signature that mimicked a real on-chain identifier, then logging it as `status: 'approved'`. The same fabrication class as the council UI (#147), the dashboard widget (#164), and the dashboard/stats fallback (#167). Real settlement lives in /api/tools/x402/pay where a genuine ed25519 receipt is produced. Nothing in the codebase calls the legacy charge action (grep'd to confirm). Replaced the action with a 410 Gone + nextAction pointing callers at /api/tools/x402/pay. The "fetch" and "retry_with_proof" actions are unchanged; both are pure proxies that don't fabricate anything. ## Verified - pnpm exec tsc --noEmit: clean - pnpm check: 3 passed, 0 failed - trust-gate: 41/44 (was 37/44) - grep for `x402-devnet-`: zero hits ## Rollback Single git revert. 4 files.
operatoruplift
added a commit
that referenced
this pull request
Apr 27, 2026
…IDs (#174) 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.
This was referenced Apr 27, 2026
operatoruplift
added a commit
that referenced
this pull request
Apr 27, 2026
The legacy "confirm" fall-through path on POST /api/subscription was
a real security gap. Any authenticated user posting:
POST /api/subscription
Authorization: Bearer <valid-privy-jwt>
Content-Type: application/json
{ "tx_signature": "anything-here" }
would be marked tier=pro, status=active without any on-chain
verification. The TODO at line 159 admitted it: "Verify the Solana
tx on-chain before activating. For devnet/demo, we trust the
client-provided signature." Same fabrication class as the council
PRs cleaned up (#147, #155, #156, #164, #167, #173).
No code path calls this fall-through (`grep -rn "tx_signature.*\
subscription"` returns zero in app/, src/). The paywall page uses
action="create_invoice" exclusively, and real settlement runs
through /api/access/verify-payment which DOES call verifyPayment()
against the Solana RPC.
Closed the path with HTTP 410 Gone + a nextAction pointing callers
at /api/access/verify-payment, the route that actually verifies the
on-chain tx.
The two known-good actions ("create_invoice" and "dev_simulate")
are unchanged.
## Verified
- pnpm exec tsc --noEmit: clean
- pnpm check: 3 passed, 0 failed
- grep -rn "tx_signature.*subscription" returns 0 callers
## Rollback
Single git revert. One file.
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two wins, one PR
1. Trust-gate coverage 11/44 → 16/44
Five small routes adopted the
withRequestMeta/X-Request-Idpattern from@/lib/apiHelpersthat the/api/tools/*family adopted in #123 and the observability sweep extended to receipts/memory/agents/notifications/audit in #130. Now these routes propagate request IDs the same way:app/api/providers/route.tsapp/api/capabilities/route.tsapp/api/receipts/public-key/route.tsapp/api/health/llm/route.tsapp/api/dashboard/stats/route.tsEach one is a tight, mechanical add of
withRequestMeta(...)+ spreadingmeta.headersinto the response. No response shape changes, no behavior changes.2. Fix residual fabrication in
/api/dashboard/statsWhile adding apiHelpers I caught one more leftover: when the route's auth check fails, it was returning this hardcoded fallback:
These are the exact same fake values PR #164 removed from the rendered dashboard. The dashboard now reads localStorage directly so it doesn't call this route, but anything else that hits
/api/dashboard/statsunauthenticated still got the lie. Now returns zeros.Trust impact
Verified
Net diff
Rollback
Single
git revert.