Repository navigation
feat(auth): let analysts read and build dashboards, and refuse every other change - #2546
Merged
Merged
Maple Review Bot / Maple / review
succeeded
Nov 13, 2026 in 3m 20s
Confidence 10/10 · No issues found
🟢 Confidence 10/10 · safe to merge. The gate is one four-line pure function wired into every auth path, and real middleware tests pin both the refusal and the allowed reads.
no findings · tests covered · risk high · 1/1 new units observable
Refuses an analyst-role session or credential every non-GET endpoint on the internal and /v2 APIs unless the endpoint is annotated AnalystAccess or the /v2 scope registry already calls it a read. The check lives in the auth layers, so an unmarked endpoint fails closed, and it is covered by middleware-level tests.
checkAnalystAccessrefuses analysts by default in all three auth middlewaresAnalystAccessannotation opens reads, own-state writes and dashboard authoring/v2dashboard writes are markedauthor: analysts may create, share and deleteLimitedRoleError(403limited_role) added to the middleware error unions
Before merge
- Manual · Check the Clerk role keys on dev and prd map to a known
clerkKey:roleOffalls back to analyst, which now refuses every write
Production impact
Production traffic of the changed files (last 7 days)
| File | Calls/day | Busiest operations |
|---|---|---|
packages/domain/src/http/analyst-access.ts |
547 | GET 300/day, 0.3% errGET 247/day, 3.1% err |
packages/domain/src/http/digest.ts |
53 | preview 53/day, 1.1% err |
packages/domain/src/http/v2/device-credentials.ts |
49 | POST /v2/device_tokens 49/day, 0.0% err |
packages/domain/src/http/v2/dashboards.ts |
43 | GET /v2/dashboards 43/day, 0.0% err |
What was checked
- Gate reads endpoint then group annotations with the same
Context.getidiom aswithAuditedRead(audit-access.ts:156) requiredScopeForRoutereturning null still fails closed through?.access !== "read"(analyst-gate.ts:31)- Approve handlers pass
tenant.rolesinto the minted CLI/MCP credential, so it cannot outrank the caller
Observability coverage: 1 of 1 changes observable
| Change | Kind | Observable | Evidence |
|---|---|---|---|
| analyst refusal in the internal and /v2 auth middlewares | authorization gate | yes | API-key and device-token denials call recordApiDenial (ApiAuthorizationLive.ts:78, ApiAuthorizationV2Live.ts:305); the 403 carries code: limited_role |
f72b00b · Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.
Loading