Org RBAC Surface Behavior
Cross-app contract
Every protected organization surface must satisfy both:
- the viewer has the capability required for the action; and
- the target record belongs to a client in the viewer's resolved client scope.
Owners have all-client scope. Other members use All clients or Selected clients from Settings → Team. Missing or empty selected scope fails closed.
Navigation and action visibility should mirror backend authorization, but hiding a control is never the security boundary.
Settings information architecture
Access stays inside Settings under a dedicated Access group. Team owns people, invitations, roles, and per-person client scope. Role permissions owns the reusable defaults behind each non-owner role. Keeping them adjacent avoids a second administration area while preserving a simple distinction between “who has access” and “what a role can do.”
- Settings navigation omits destinations for which the viewer has no relevant capability.
- The Settings root redirects to the viewer's first accessible destination rather than assuming organization settings access.
- A direct URL to a restricted destination renders a standard access-denied state and does not start its protected data query.
- Personal settings remain available even when the viewer has no organization-management capabilities.
Settings → Team
Team is the only V1 staff-access management surface.
- A member row presents identity, role, status, and join date first. Authorized managers open Edit access when they need role or client-scope controls.
- Selected clients reveals a client checklist and count.
- Owners are visibly fixed to All clients.
- Invitations capture role and client access before sending. Global managers default to All clients; Selected clients delegated managers default to Selected clients and can grant only their own subset.
- Raw capability keys and per-person custom permission editing are not exposed in the normal Team flow.
- The Roles page owns role-default permission configuration.
- A viewer lacking team-read capabilities sees an access-denied state.
- Invite, resend, revoke, role, access, removal, and ownership actions appear only when permitted.
- Delegated managers cannot edit themselves, peers, higher roles, or promote to their own level or above.
- Read-only viewers receive only the directory sections they can view. Client names, selected-client scope, and capability details are redacted unless they can manage staff access. Delegated managers never receive or grant target scope outside their own scope.
Clients
- Lists and detail pages contain only clients in scope.
- Client creation and editing require their respective capabilities.
- There is no Assigned column, staff assignment dialog, or staff-access section on a client page.
- Client people/contact management refers to people at the client company and their portal access, not agency staff authorization.
Projects and delivery work
- Project, task, update, time, note, file, and request reads must remain inside client scope.
- Their create, edit, publish, approve, archive, or delete actions also require the relevant capability.
- Project owners and assignees are delivery metadata. They do not grant client access.
- A project UI may only offer staff who already have access to the project's client when choosing owners or assignees.
Billing and commercial records
- Client scope filters billing profiles, invoices, subscriptions, contracts, and quotes.
- Billing visibility and write operations separately require billing capabilities.
- Access to a client never implies access to its finances.
Search, summaries, and indirect references
Client scope must also apply to indirect and aggregate surfaces, including global search, dashboard summaries, activity feeds, calendar/workspace projections, saved workspace pins, reports, and relationship pickers. Persisted pins are re-authorized on read and write so revoked client or capability access cannot leave stale names or shortcuts in the shell. A hidden direct route is insufficient if names, totals, files, or activity can leak through another query.
State changes and edge cases
- Switching from Selected clients to All clients takes effect immediately and clears active selections.
- Removing a client from Selected clients removes access to that client and client-owned records immediately.
- A member with Selected clients and no selections sees no client-scoped data.
- Client-scoped workspaces replace misleading empty collections with an explanatory no-client-access state when Selected clients has no active selections.
- Client-work navigation remains visible for orientation in that state, while client-dependent create actions disappear until the member has a usable client scope.
- Missing and out-of-scope client-owned detail URLs share a neutral unavailable state and return path; they do not disclose whether the record exists.
- Archiving a client does not change the member's authorization model; normal archived-record visibility rules still apply.
- Removing or disabling a membership blocks organization access regardless of retained historical audit data.
- Revoked and expired pre-acceptance invitations cannot grant effective selected-client access; revocation and expired-token consumption clean up provisional rows.
- Ownership transfer uses its dedicated flow and leaves exactly one protected owner outcome according to the existing ownership contract.
UX language
Use Role, Client access, All clients, and Selected clients consistently. Avoid using “assigned” for authorization in user-facing copy because assignment is already meaningful in project and task workflows.