Skip to content

feat(policy): add the analyst role below member - #2543

Merged
Makisuo merged 2 commits into
mainfrom
observer/policy
Nov 13, 2026
Merged

Makisuo merged 2 commits into
mainfrom
observer/policy

Conversation

@Makisuo

@Makisuo Makisuo commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

First layer of the Analyst role: an org role for people who follow the product and build dashboards without operating it (product, support, finance, founders).

What changed

  • analyst joins the role ladder below member, with the key org:analyst.
  • A role string the code does not know now reads as analyst, the least a session can hold. It read as member, which was the lowest role until now.
  • A tenant with no roles at all still reads as member. Only Maple's own agents (PR review, investigations, chat) arrive without one, and they need to keep writing.
  • Denials for a member-level permission now say "Only org admins, engineers and members can ...".

Nothing assigns the role yet and the Members page does not offer it, so this layer changes no behaviour for existing sessions. One edge: a membership moved to a role key the code does not know now retires that person's member-pinned credentials, where it kept them before.

The role started out as a read-only "Observer". It was renamed and given dashboards before anything merged, so the branch names still say observer/.

Verified

  • packages/domain: vitest run src/policy/policy.test.ts, 16 passed. Cases: an analyst holds no named grants, stays an analyst next to an unknown role, takes the higher of two roles, and a member-pinned credential outranks an analyst.
  • @maple/domain typecheck and the CI lint config on packages/domain/src/policy: clean.

Next layers

  1. Enforcement: one gate on both APIs that lets an analyst read and build dashboards, with a contract test; then the same for MCP and chat.
  2. Members page: invite and role picker.
  3. Analyst shell: sidebar and palette.
  4. The pages an analyst reaches hide what the API refuses.
  5. Analyst Overview page.

Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.

Summary by CodeRabbit

  • Access and Roles
    • Added the analyst role as the lowest level in the role hierarchy. Unrecognized roles now receive analyst-level access rather than member-level access.
    • Accounts with multiple roles use the highest role assigned; accounts with no listed roles are treated as members.
    • Updated role descriptions to clarify which roles are included in member-level access.

Observer is a read-only org role for people who follow the product without operating it. It ranks below member, so every permission in the table already excludes it.

A role string this code does not know now reads as observer, the least a session can hold, where it read as member. A tenant with no roles still reads as member: only Maple's own agents arrive without one.

Nothing assigns the role yet, and the Members page does not offer it.
@maple-review-bot

This comment has been minimized.

@coderabbitai

coderabbitai Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

Explain Change →

Warning

Review limit reached

You'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.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

Learn how review limits work.

Review configuration:

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1e21fdc1-51d6-4bf6-a313-2df8ed5592c9
Commits

Reviewing files that changed from the base of the PR and between 6fab3c2 and 6fab3c2.

Files selected for processing: 2

  • packages/domain/src/policy/policy.test.ts
  • packages/domain/src/policy/roles.ts

No actionable comments were generated in the recent review.

Walkthrough

The policy roles module adds an internal analyst role below member, maps unknown role names to analyst, and updates role ranking and holder wording. Policy tests cover analyst permissions, role mapping, precedence, and highest-role selection.

Changes: Analyst role policy

Layer / File(s) Summary
Role mapping and policy expectations
packages/domain/src/policy/roles.ts, packages/domain/src/policy/policy.test.ts
The role module adds analyst as the lowest role, maps unknown role names to analyst, selects the highest role by rank, and updates holder phrases. Tests cover permission grants and denials, role mapping, precedence, and empty role lists.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Feature

Merge Risk: Minimal · up to 6fab3

This change adds a lowest-privilege internal role and makes unknown role names fall back to it. No role assignment is exposed yet, so existing sessions are unaffected. No actionable merge-blocking risk remains.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title "feat(policy): add the analyst role below member" matches the main change. The raw summary shows roles.ts adds analyst as the lowest role, roleOf maps unknown names to analyst, and policy te…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Full details: Title check

Explanation

The title "feat(policy): add the analyst role below member" matches the main change. The raw summary shows roles.ts adds analyst as the lowest role, roleOf maps unknown names to analyst, and policy tests cover analyst mapping and precedence. The PR objectives confirm a new role below member. The title is specific and concise. The objectives note the role was first named observer and later renamed analyst, and the PR description still uses observer. That mismatch affects the description, not the title, because the title uses the final name.

Finishing Touches

Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

Share

Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ac5f5c97-16f3-4119-92a3-a9754f095075
Commits

Reviewing files that changed from the base of the PR and between 61dc8b6 and 6fab3c2.

Files selected for processing: 2

  • packages/domain/src/policy/policy.test.ts
  • packages/domain/src/policy/roles.ts

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.

@maple-review-bot maple-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 inline note from Maple's review. The score and summary are in the review comment above.

Comment thread packages/domain/src/policy/roles.ts Resolved
The role also builds dashboards, so observer undersold it. Key org:analyst.
@Makisuo Makisuo changed the title feat(policy): add the observer role below member feat(policy): add the analyst role below member Nov 13, 2026
@maple-review-bot

maple-review-bot Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 6/10 · needs attention. Held at 6 because a correctness warning is open.
1 warning −1 · tests covered · risk high −1

Adds an analyst role below member and makes an unknown Clerk role read as analyst instead of member, with an empty role list still reading as member. The ladder change is sound and well tested; the Members page still mislabels the role until #2549.

  • Role gains analyst at rank 0, below member
  • roleOf reads an unknown Clerk role as analyst, not member
  • highestRole takes Arr.max(byRank); an empty role list still reads as member
  • holdersPhrase("member") now names admins, engineers and members

Before merge

Still open from earlier reviews

6fab3c2 · What was checked, coverage and telemetry details are on the Maple / review check. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@Makisuo
Makisuo added this pull request to stack #2556 November 13, 2026 12:45
@Makisuo
Makisuo merged commit 04e554d into main Nov 13, 2026
43 checks passed
@maple-review-bot

Copy link
Copy Markdown

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.

@Makisuo
Makisuo deleted the observer/policy branch November 13, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant