fix(ci): openapi-security-tiers must read ALWAYS_PROTECTED_API_PATTERNS (base-red #12581) - #12652
Merged
Merged
Conversation
Owner
Author
|
The red It fails on one error in This PR changes only |
…cuting gate test (#12581) The ALWAYS_PROTECTED two-arm read itself landed in #12605; what was still missing is a regression guard. This runs the real gate and asserts it exits 0 with no "NOT covered" line, so the LOCAL_ONLY-arm defect (#12350) cannot silently reappear on the ALWAYS_PROTECTED arm. Also fails the parse guard when ALWAYS_PROTECTED_API_PATTERNS comes back empty, instead of reporting every regex-covered route as an annotation mismatch.
diegosouzapw
force-pushed
the
fix/release-basereds-gate
branch
from
September 5, 2026 06:14
d9b70d3 to
514d3c3
Compare
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…cuting gate test (diegosouzapw#12581) (diegosouzapw#12652) Merged as a reduced diff, and worth recording why. The two-arm `ALWAYS_PROTECTED` read this PR proposed had already landed in diegosouzapw#12605 while this branch was open — the tip carries `coveredByAlwaysProtected()` with both arms and the new error wording. I ran the gate on the current tip to be sure: `PASS — all security tier annotations match routeGuard.ts`. Merging the whole branch would have reintroduced the same logic under a different comment. What was genuinely missing, and is what merged: - **`tests/unit/openapi-security-tiers-gate.test.ts`** — executes the real gate and asserts exit 0 with no "NOT covered" line. diegosouzapw#12605 fixed the defect but left no guard, so the LOCAL_ONLY-arm bug (diegosouzapw#12350) could reappear on the ALWAYS_PROTECTED arm exactly as it did the first time. 1/1 green. - **The parse guard** — `ALWAYS_PROTECTED_PATTERNS.length === 0` now fails the constant-parse check with its own count in the message. Without it, a regex array that stops parsing degrades into "every pattern-covered route is an annotation mismatch" instead of saying so. A note for the record: my first read of this PR was wrong. I ran the gate in the main checkout, which was 11 commits behind `origin/release/v3.8.51`, saw the pre-diegosouzapw#12605 failure, and classified this as fixing a live red. It was not — the checkout was stale. Corrected before anything was merged.
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.
The failure
release/v3.8.51is red oncheck:openapi-security-tierswith four routes reported as unprotected:They are not unprotected
isAlwaysProtectedPath()ORs two arrays:All four routes are covered by the pattern that shipped with the credential-export hard-gate:
/^\/api\/providers\/[^/]+\/(claude|codex)-auth\/(export|apply-local)\/?$/A runtime probe over the real
isAlwaysProtectedPath()returns true for all four. The gate parsed onlyALWAYS_PROTECTED_API_PATHSand neverALWAYS_PROTECTED_API_PATTERNS, so it was blind to half of its own input — a false positive, not a security hole.This is the residual half of the defect #12350 fixed for the LOCAL_ONLY tier this cycle; that arm already reads both
LOCAL_ONLY_API_PREFIXESandLOCAL_ONLY_API_PATTERNS.Change
ALWAYS_PROTECTED_API_PATTERNS, and include it in the fatal parse guard so a future formatting change inrouteGuard.tsfails loudly instead of silently degrading back into false positives.coveredByAlwaysProtected()mirroringcoveredByLocalOnly()— both concretize{param}before matching.Validation
Gate on a clean tree:
FAIL — 4 annotation mismatchesbefore,PASS — all security tier annotations match routeGuard.ts(exit 0) after.New
tests/unit/openapi-security-tiers-gate.test.tsruns the gate as a subprocess — deliberately not importingrouteGuard.ts, so the unit suite gains no DB handle (that suite is already hanging on one). Mutation-checked: reverting the gate to its previous version makes the test fail and print all four routes; restoring the fix makes it pass.