Skip to content

[comp] Production Deploy#2615

Merged
Marfuen merged 15 commits intoreleasefrom
main
Apr 20, 2026
Merged

[comp] Production Deploy#2615
Marfuen merged 15 commits intoreleasefrom
main

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot commented Apr 20, 2026

This is an automated pull request to release the candidate branch into production, which will trigger a deployment.
It was created by the [Production PR] action.


Summary by cubic

Deploy the release to production. Includes CS-189 RBAC updates to gate the Auditor View and a fix for an API build error.

  • Bug Fixes
    • CS-189: Show the Auditor View only for users with the built-in auditor role or a custom role that grants audit:read; added a server-side guard and tests, and updated sidebar, search, and menu to use this flag.
    • Removed a stray brace in apps/api/src/policies/policies.service.ts that broke the build.

Written for commit fa16795. Summary will update on new commits.

tofikwest and others added 13 commits April 16, 2026 17:40
… (CS-189)

The Auditor View tab was gated on roles.includes(Role.auditor) — a
literal string match against the built-in "auditor" role. That made the
tab invisible to any custom organization role (e.g. a "Comp AI" custom
role a customer set up for our support team) even when that role was
granted audit:read, and also hid it from owners/admins who implicitly
have the permission. The route layout already enforces audit:read via
requireRoutePermission, so the literal-role gate was both redundant and
wrong.

Switched to canAccessRoute(permissions, 'auditor') in:
- AppSidebar nav item (design-system sidebar)
- MainMenu item (legacy sidebar + mobile menu) — reads permissions via
  usePermissions() so callers no longer need to pass hasAuditorRole
- app-shell-search-groups command palette entry

Also removed the redundant roles.includes(Role.auditor) page-level
check in auditor/(overview)/page.tsx; auditor/layout.tsx's existing
requireRoutePermission('auditor', orgId) still enforces audit:read
server-side.

Aligns with CLAUDE.md RBAC guidance: "No manual role string parsing —
always use permission checks."

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…w-up)

Follow-up after CTO review: owner/admin should NOT see the Auditor View
tab or access the page, even though their implicit all-permissions
include audit:read. The tab is scoped to audit work; it should only
appear for users whose role explicitly grants audit access.

New rule:
  Show Auditor View iff
    - user has the built-in `auditor` role, OR
    - user has a custom org role that explicitly grants `audit:read`.

Implementation:
  - New pure helper `canAccessAuditorView(roleString, customRolePermissions)`
    in lib/permissions.ts. Separates "permission came from built-in role"
    (owner/admin/everyone) from "permission came from custom role".
  - Server-side helpers in lib/permissions.server.ts:
    - `resolveCustomRolePermissions` fetches only the user's custom-role
      permissions (built-in roles excluded).
    - `resolveAuditorViewAccess` runs the check for the current user.
    - `requireAuditorViewAccess` is the route guard — replaces
      `requireRoutePermission('auditor', orgId)` on the auditor layout.
  - usePermissions() now returns `canAccessAuditorView` + `customPermissions`
    so client components don't have to replicate the rule.
  - Org layout computes the flag server-side and forwards it through
    AppShellWrapper → AppSidebar + getAppShellSearchGroups.
  - main-menu reads the flag directly from usePermissions().

Behavior matrix:
  - auditor → visible ✅
  - owner,auditor / admin,auditor → visible ✅
  - CompAI custom role with audit:read → visible ✅
  - owner alone / admin alone → hidden (implicit audit:read doesn't count)
  - owner,ReadOnlyCustomRole (no audit) → hidden
  - employee / contractor → hidden ✅

Adds 9 unit tests locking in every row of that matrix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Tofik Hasanov <72318342+tofikwest@users.noreply.github.com>
…ew gating

Per CS-189 product decision: owners/admins should not see the Auditor View
tab unless they explicitly opt in via a custom role granting audit:read.
Removing audit:read from the built-in owner/admin roles lets the standard
canAccessRoute('auditor') check do the work — the merged permissions
naturally cover owner,auditor / admin,auditor and custom roles with
audit:read, while hiding owner/admin alone.

audit:read is not referenced anywhere in the codebase outside
ROUTE_PERMISSIONS.auditor, so dropping it is safe. Owner/admin still
retain audit:create and audit:update for SOA management.

Deletes ~100 lines of special-case code that was previously needed to
distinguish implicit vs explicit audit:read:
- canAccessAuditorView
- resolveCustomRolePermissions
- resolveAuditorViewAccess
- requireAuditorViewAccess
- customPermissions plumbing through AppShellWrapper / AppSidebar /
  search groups / MainMenu / usePermissions

Tests updated to exercise the full resolution path
(resolveBuiltInPermissions + canAccessRoute).
…rization

fix(policies): remove stray brace breaking nest build
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
app (staging) Ready Ready Preview, Comment Apr 20, 2026 7:55pm
comp-framework-editor Ready Ready Preview, Comment Apr 20, 2026 7:55pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
portal (staging) Skipped Skipped Apr 20, 2026 7:55pm

Request Review

…mission-gating

fix(rbac): gate Auditor View on audit:read instead of role string (CS-189)
@claudfuen
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.26.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants