Repository navigation
(janitor/dedupe): consolidate internal API secret auth - #7192
Conversation
Seventeen /api/internal routes repeated the same INTERNAL_API_SECRET header check (read header, timingSafeEqual against config, 401 on mismatch), with two header spellings (x-internal-api-key and x-internal-secret) and a duplicated secretMatches helper in three files. Centralize it in authorizeInternalApiRequest, which accepts either header, and remove the per-route boilerplate.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryReviewed the consolidation of 17 Notes
Files Reviewed (18 files)
Reviewed by deepseek-v4.1-flash · Input: 52.2K · Output: 9.1K · Cached: 250.2K Review guidance: REVIEW.md from base branch |
eshurakov
left a comment
There was a problem hiding this comment.
Code Review Summary
Status: No Issues Found | Recommendation: Merge
Executive Summary
Independent review of all 18 changed files at 6cd35a91989a5c415d2a274b2cb01cb43aeec71c against cc585e94ce47193f58cf9f1cc6710fe649061f0a, all 17 auth call sites, repository callers, and existing reviews found no major security or correctness regressions.
Missing, empty, and invalid secrets still fail closed with the same 401 JSON, before body parsing or side effects; the existing timing-safe comparator and downstream response/error paths are preserved. Both header spellings require the same secret. x-internal-api-key takes precedence if both are supplied, including an invalid/empty key shadowing a valid x-internal-secret; no traced producer sends that conflicting combination.
Verification: 2,499 isolated auth cases against GitHub-fetched pinned source passed, with base/head non-auth equivalence checked for every migrated route. CI at this head passed typecheck, lint, formatting, build, and 1,145 web/shared test suites (18,718 tests passed); logs confirm the replication-lag, scheduled-action, and security-notification route suites ran. No dedicated helper test was added; isolated checks stubbed NextResponse and did not rerun the DB-backed suites locally. No workspace edits or installs.
Files Reviewed (18 files)
apps/web/src/app/api/internal/auto-fix-status/[ticketId]/route.tsapps/web/src/app/api/internal/auto-fix/comment-reply/route.tsapps/web/src/app/api/internal/auto-fix/config/route.tsapps/web/src/app/api/internal/auto-fix/create-pr/route.tsapps/web/src/app/api/internal/code-review-usage/[reviewId]/route.tsapps/web/src/app/api/internal/db/replication-lag/route.tsapps/web/src/app/api/internal/integrations/dolthub/token/route.tsapps/web/src/app/api/internal/kiloclaw/instance-ready/route.tsapps/web/src/app/api/internal/kiloclaw/scheduled-action-side-effects/route.tsapps/web/src/app/api/internal/security-agent/notifications/route.tsapps/web/src/app/api/internal/triage-status/[ticketId]/route.tsapps/web/src/app/api/internal/triage/add-label/route.tsapps/web/src/app/api/internal/triage/check-duplicates/route.tsapps/web/src/app/api/internal/triage/classify-config/route.tsapps/web/src/app/api/internal/triage/post-comment/route.tsapps/web/src/app/api/internal/usage/record/route.tsapps/web/src/app/api/internal/user-data-exports/ready/route.tsapps/web/src/lib/internal-api-auth.ts
Classification
Shared behavior — the same domain concept ("verify a request carries the internal API secret") was reimplemented per-route.
What changed
Seventeen
/api/internal/*route handlers inapps/webeach repeated the identical auth check:The same secret was transported under two different header spellings (
x-internal-api-keyvsx-internal-secret), and three files carried their own localsecretMatcheshelper. This is the kind of drift that makes a future auth change (new secret, added callback token, constant-time hardening) land inconsistently.Consolidated into one owner,
authorizeInternalApiRequestinapps/web/src/lib/internal-api-auth.ts, which accepts either header and returns the401response (ornull), matching the existingauthorizeSupportRequestpattern. Call sites now read:Intentional duplication left alone
glanceable-agents-snapshot: uses an HMAC-normalizedsecretMatches(deliberate hardening).kiloclaw/billing-side-effects: logs a structured side-effect before rejecting.mcp-catalog/token,auto-routing-benchmark/*): different transport/secret.support/_auth.ts: already centralized underSUPPORT_API_SECRET.Verification
tsgo --noEmit -p apps/web/tsconfig.json— cleanoxlint --config .oxlintrc.jsonon changed files — 0 warnings / 0 errorsoxfmton changed files — no diffs