fix: move read-only lookup routes (regions, brand-presence stats) to capability-gated access#2819
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Hey @ravverma,
⚠ Degraded review - no spec document was found for this change (searched the PR links, the touched repos' docs, the architecture/guidelines docs, and linked Jira). This review covers code-level quality but could not validate the change against an agreed design, so confidence is reduced. Add a spec link (PR template section 4) and re-request review for a full-confidence pass.
Verdict: Request changes - the carried-over comment contradicts the route's new access model.
Complexity: LOW - trivial diff; API surface signal.
Changes: Moves GET /v2/regions from INTERNAL_ROUTES to routeRequiredCapabilities with organization:read capability (1 file).
Note: Recommend a human read before merge - possible divergence from the documented design (heuristic, flagged by the conventions reviewer). The bot review is a complement to, not a replacement for, a human read here.
Must fix before merge
- [Important] Stale comment contradicts new access model -
src/routes/required-capabilities.js:~256(details inline)
Non-blocking (1): minor issues and suggestions
- nit: PR title says "region" (singular) but the actual route is
GET /v2/regions(plural) - may affect commit-history searchability.
Skill: pr-review | Model: us.anthropic.claude-opus-4-6-v1[1m] | Duration: 1m 51s | Cost: $2.69 | Commit: 355740ee8c824eac72e452ca7f11d02e9e18695a
If this code review was useful, please react with 👍. Otherwise, react with 👎.
The route now lives in routeRequiredCapabilities, which the S2S wrapper also consumes, so it is reachable by any consumer holding organization:read. The carried-over 'not for S2S consumers' note was stale and misleading.
|
This PR will trigger a patch release when merged. |
There was a problem hiding this comment.
Hey @ravverma,
⚠ Degraded review - no spec document was found for this change (searched the PR links, the touched repos' docs, the architecture/guidelines docs, and linked Jira). This review covers code-level quality but could not validate the change against an agreed design, so confidence is reduced. Add a spec link (PR template section 4) and re-request review for a full-confidence pass.
Verdict: Approve - prior finding addressed, change is clean and correctly scoped.
Complexity: LOW - trivial diff; API surface signal.
Changes: Moves GET /v2/regions from INTERNAL_ROUTES to routeRequiredCapabilities with organization:read capability (1 file).
Previously flagged, now resolved
- Stale comment ("session-token authenticated, not for S2S consumers") now correctly describes the new access model.
- PR title alignment with route path.
Skill: pr-review | Model: us.anthropic.claude-opus-4-6-v1[1m] | Duration: 0m 59s | Cost: $2.19 | Commit: 15455c85a9974d7736e1a2207aba460675f7d5a8
If this code review was useful, please react with 👍. Otherwise, react with 👎.
Move 'GET /org/:spaceCatId/brands/all/brand-presence/stats' and 'GET /org/:spaceCatId/brands/:brandId/brand-presence/stats' out of INTERNAL_ROUTES into routeRequiredCapabilities with brand:read, matching the sibling brand-presence routes (filter-dimensions, weeks, etc.).
# [1.653.0](v1.652.1...v1.653.0) (2026-07-15) ### Bug Fixes * move read-only lookup routes (regions, brand-presence stats) to capability-gated access ([#2819](#2819)) ([312180b](312180b)) ### Features * **prompts:** source-aware upsertPrompts + reject unregistered sources ([#2810](#2810)) ([04e9fc8](04e9fc8)), closes [#793](#793) [#793](#793) [#793](#793) [#793](#793) [#2692](#2692)
|
🎉 This PR is included in version 1.653.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
fix: move read-only lookup routes from INTERNAL_ROUTES to capability-gated access
Problem
Several read-only lookup endpoints were listed in
INTERNAL_ROUTES, so they were only reachable through the internal/session-token path and did not go through the standard required-capability check. As a result, callers on the read-only admin org charter (RO-admin), who are granted the relevant read capabilities, could not reach these harmless reads.Change
Move the following routes out of
INTERNAL_ROUTESand intorouteRequiredCapabilities(src/routes/required-capabilities.js), each gated behind the lowest read capability that fits:GET /v2/regionsorganization:readGET /org/:spaceCatId/brands/all/brand-presence/statsbrand:readGET /org/:spaceCatId/brands/:brandId/brand-presence/statsbrand:readThe two brand-presence stats routes join their sibling brand-presence routes (
filter-dimensions,weeks,sentiment-overview, etc.), which are alreadybrand:read.GET /v2/regionsis a global lookup table with no org scope, soorganization:readis the appropriate least-privilege gate.Why this is safe / low-risk
GETs on lookup/stats data. No writes, no new endpoints, no response-shape change.organization:read/brand:read) rather than left internal-only./v2/regionsuses the sameorganization:readpattern as other global reads.Note on access model
routeRequiredCapabilitiesis the shared map the S2S wrapper also consumes, so once a route has a capability, any consumer (session-token or S2S) holding that capability can call it. This is intended for these non-sensitive reads. The comments carried over fromINTERNAL_ROUTESare updated/removed so they no longer claim "not for S2S consumers."Testing
eslintpasses.