Repository navigation
feat(auth): let analysts read and build dashboards, and refuse every other change - #2546
Conversation
…tion The auth middlewares now refuse a session or credential whose highest role is observer any request that is not a read or a change to the caller's own state. It is refused by default: an endpoint passes only as a GET, when it is marked ObserverAccess, or on /v2 when the scope registry already names it a read. Marked read: the dashboard query groups and the previews that sit beside writes. Marked personal: the caller's digest, devices, MCP connection and CLI and MCP sign-in approvals, which pin the caller's role. Internal routes answer with ReadOnlyRoleError, /v2 with insufficient_permissions, and API key denials are audited.
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 17 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
This comment has been minimized.
This comment has been minimized.
# Conflicts: # packages/domain/src/policy/roles.ts
Dashboard writes are marked AnalystAccess author, so the auth middlewares let an analyst through them and still refuse every other change. The refusal is now LimitedRoleError (limited_role), since the role is no longer read-only.
Maple review🟢 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. Refuses an analyst-role session or credential every non-GET endpoint on the internal and
Before merge
|
|
Merged with 1 step from "Before merge" still open. If it is done, tick it on the review comment; if not, now is the time.
|
Maple: after this shippedDeployed to New errors since the deploy:
Maple looks once, an hour after the first deploy that carries the merge. |
Second layer of the Analyst role, on top of #2543. An analyst reads everything and builds dashboards; every other HTTP endpoint that changes the organization is refused.
What changed
/v2) refuse a session or credential whose highest role is analyst unless the request reads, changes the caller's own state, or builds a dashboard.AnalystAccess, or on/v2when the scope registry already names it a read. A new endpoint is refused until someone marks it.author: the twelve dashboard writes on/v2/dashboards(create, import, create from a template, update, delete, restore a version, and the share links for a dashboard and for a widget: create, rotate, revoke). They are marked one by one, so a write added to that group later is refused until it is marked.read: the dashboard query groups (query engine, users, AI sessions, MCP servers, AI models, session replays) and the previews that sit beside writes (digest previews, escalation policy dry run, billing price preview, two integration reads).personal: the caller's digest subscription, mobile and widget devices, device credentials, their own MCP connection, agent feedback, and the CLI and MCP sign-in approvals. Those approvals pin the caller's role, so the credential they mint is an analyst's too.LimitedRoleError,/v2answers403 insufficient_permissions, both with "Analysts can read Maple and build dashboards, but not change anything else. Ask an org admin for the Member role to do more." API key denials are audited like the other denials./v2endpoints now listinsufficient_permissionsas a possible 403, so the iOS OpenAPI document is regenerated.Verified
packages/domain:analyst-access.test.tsand the policy tests, 22 passed. Cases: every dashboard write is open to an analyst; issue triage, a new SLO and a new alert rule are not.packages/backend:analyst-gate.test.ts, 6 passed.apps/api: the dashboards, phase 1 resources, telemetry and mobile device HTTP tests, 115 passed. They run the real/v2middleware with an analyst-pinned key: it creates, renames, publishes a share link for and deletes a dashboard; reads an issue and is refused a transition (403, nothing recorded); searches traces by POST; registers and removes its own device.@maple/domainand@maple/backend; the CI lint config on every changed file; the generated error list and iOS OpenAPI document are up to date.author, with handlers that touch dashboards, versions, shares and audit rows only.Known gaps, handled in later layers or follow-ups
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.