Summary
Implements Spec 067 “RBAC Troubleshooting & Tenant UI Bugfix Pack v1” for the tenant admin plane (/admin) with strict RBAC UX semantics:
Non-member tenant scope ⇒ 404 (deny-as-not-found)
Member lacking capability ⇒ 403 server-side, while the UI stays visible-but-disabled with standardized tooltips
What changed
Tenant view header actions now use centralized UI enforcement (no “normal click → error page” for readonly members).
Archived tenants remain resolvable in tenant-scoped routes for entitled members; an “Archived” banner is shown.
Adds tenant-scoped diagnostics page (/admin/t/{tenant}/diagnostics) with safe repair actions (confirmation + authorization + audit log).
Adds/updates targeted Pest tests to lock the 404 vs 403 semantics and action UX.
Implementation notes
Livewire v4.0+ compliance: Uses Filament v5 + Livewire v4 conventions; widget Blade views render a single root element.
Provider registration: Laravel 11+ providers stay in providers.php (no changes required).
Global search: No global search behavior/resources changed in this PR.
Destructive actions:
Tenant archive/restore/force delete and diagnostics repairs execute via ->action(...) and include ->requiresConfirmation().
Server-side authorization is enforced (non-members 404, insufficient capability 403).
Assets: No new assets. No change to php artisan filament:assets expectations.
Tests
Ran:
vendor/bin/sail bin pint --dirty
vendor/bin/sail artisan test --compact (focused files for Spec 067)
Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box>
Reviewed-on: #84
131 lines
9.0 KiB
Markdown
131 lines
9.0 KiB
Markdown
# Feature Specification: RBAC Troubleshooting & Tenant UI Bugfix Pack v1
|
|
|
|
**Feature Branch**: `067-rbac-troubleshooting`
|
|
**Created**: 2026-01-31
|
|
**Status**: Draft
|
|
**Input**: RBAC troubleshooting + tenant admin UI bugfix pack focused on the tenant-plane admin experience (`/admin`).
|
|
|
|
## User Scenarios & Testing *(mandatory)*
|
|
|
|
### User Story 1 - Permission-safe tenant UI interactions (Priority: P1)
|
|
|
|
A tenant member with read-only permissions can browse tenant pages and menus without being sent to error pages for normal UI clicks.
|
|
|
|
**Why this priority**: Eliminates confusing UX and reduces support load; also prevents “permission leak” regressions in high-risk actions.
|
|
|
|
**Independent Test**: As a read-only member, verify restricted actions are visible-but-disabled with an explanatory tooltip and cannot be executed.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** a user is a member of a tenant but lacks tenant management capability, **When** they view tenant lists and pages, **Then** management actions (e.g. Edit, Deactivate) are disabled and show an explanatory tooltip.
|
|
2. **Given** a user is a member but lacks tenant management capability, **When** they attempt to execute a blocked mutation (direct request / forced execution), **Then** the server denies it.
|
|
|
|
---
|
|
|
|
### User Story 2 - Archived tenant remains viewable for entitled members (Priority: P1)
|
|
|
|
A tenant member who is entitled to view a tenant can still access the tenant view even if the tenant is archived, and the UI clearly indicates status.
|
|
|
|
**Why this priority**: Prevents accidental “false 404” for legitimate members; enables safe lifecycle operations like restore.
|
|
|
|
**Independent Test**: Mark a tenant archived, ensure a viewing member can load it and sees an “Archived” banner; ensure non-members still receive 404.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** a tenant is archived and a user is a member with tenant view capability, **When** they navigate to the tenant view, **Then** the page loads and shows an “Archived” status banner.
|
|
2. **Given** a tenant is archived and a user is not a member, **When** they navigate to the tenant scope URL, **Then** they receive a 404 (deny-as-not-found).
|
|
|
|
---
|
|
|
|
### User Story 3 - Diagnose & repair tenant membership invariants (Priority: P2)
|
|
|
|
An authorized tenant owner/manager can identify and fix membership integrity issues (missing owner, duplicates) via a dedicated troubleshooting screen.
|
|
|
|
**Why this priority**: Provides a recovery path for real-world “sharp edges” without requiring direct database intervention.
|
|
|
|
**Independent Test**: Seed broken states (0 owners, duplicate memberships), confirm diagnostics flag them and repair actions resolve them.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** a tenant has no owners, **When** an authorized user opens diagnostics, **Then** the issue is surfaced and a repair action can promote a member to owner.
|
|
2. **Given** a tenant has duplicate memberships for the same user, **When** an authorized user runs “merge duplicates”, **Then** duplicates are removed and exactly one membership remains.
|
|
|
|
### Edge Cases
|
|
|
|
- A tenant member without management capability attempts to execute a blocked action via a forged request.
|
|
- A non-member attempts to access a tenant-scoped page (must be deny-as-not-found).
|
|
- Tenant is archived: view allowed for entitled members; lifecycle actions are status-appropriate.
|
|
- Tenant has 0 owners; tenant has 1 owner and an action would demote/remove the last owner.
|
|
- Membership duplicates exist and are resolved; ensure resulting owner count remains valid.
|
|
- A tenant has an external GUID identifier; ensure no internal lookups treat that GUID as the internal tenant primary key.
|
|
|
|
## Requirements *(mandatory)*
|
|
|
|
**Constitution alignment (required):** If this feature introduces any Microsoft Graph calls, any write/change behavior,
|
|
or any long-running/queued/scheduled work, the spec MUST describe contract registry updates, safety gates
|
|
(preview/confirmation/audit), tenant isolation, run observability (operation run record: type/identity/visibility), and tests.
|
|
If security-relevant DB-only actions intentionally skip an operation run record, the spec MUST describe audit log entries.
|
|
|
|
**Constitution alignment (RBAC-UX):** If this feature introduces or changes authorization behavior, the spec MUST:
|
|
- state which authorization plane(s) are involved (tenant `/admin/t/{tenant}` vs platform `/system`),
|
|
- ensure any cross-plane access is deny-as-not-found (404),
|
|
- explicitly define 404 vs 403 semantics:
|
|
- non-member / not entitled to tenant scope → 404 (deny-as-not-found)
|
|
- member but missing capability → 403
|
|
- describe how authorization is enforced server-side (Gates/Policies) for every mutation/operation-start/credential change,
|
|
- reference the canonical capability registry (no raw capability strings; no role-string checks in feature code),
|
|
- ensure global search is tenant-scoped and non-member-safe (no hints; inaccessible results treated as 404 semantics),
|
|
- ensure destructive-like actions require an explicit confirmation step,
|
|
- include at least one positive and one negative authorization test, and note any RBAC regression tests added/updated.
|
|
|
|
**Constitution alignment (OPS-EX-AUTH-001):** OIDC/SAML login handshakes may perform synchronous outbound HTTP (e.g., token exchange)
|
|
on `/auth/*` endpoints without an operation run record. This MUST NOT be used for Monitoring/Operations pages.
|
|
|
|
**Constitution alignment (BADGE-001):** If this feature changes status-like badges (status/outcome/severity/risk/availability/boolean),
|
|
the spec MUST describe how badge semantics stay centralized (no ad-hoc mappings) and which tests cover any new/changed values.
|
|
|
|
### Functional Requirements
|
|
|
|
- **FR-001 (Restore action icon)**: The tenant list row menu MUST display a consistent icon for the Restore action.
|
|
- **FR-002 (Readonly edit UX)**: For a tenant member lacking tenant management capability, the UI MUST present Edit as disabled with an explanatory tooltip and MUST avoid normal-click navigation leading to an error page.
|
|
- **FR-003 (Readonly cannot deactivate)**: Deactivate MUST be treated as a protected mutation and MUST NOT be executable by a tenant member lacking tenant management capability.
|
|
- **FR-004 (Archived tenant access)**: An entitled tenant member (tenant view capability) MUST be able to open archived tenants. A non-member MUST receive a 404 for tenant scope URLs.
|
|
- **FR-005 (Owner invariant)**: The system MUST prevent removing/demoting the last remaining tenant owner and MUST surface “missing owner” situations in diagnostics.
|
|
- **FR-006 (Membership integrity)**: The system MUST prevent duplicate memberships per (tenant, user). Diagnostics MUST identify duplicates and provide a safe repair flow for authorized users.
|
|
- **FR-007 (GUID vs internal ID)**: The system MUST treat external tenant identifiers (GUIDs) as external-only identifiers and MUST NOT use them where an internal tenant primary key is required.
|
|
- **FR-008 (Diagnostics access + safety)**: Diagnostics MUST not expose cross-tenant data to non-members. Repair actions MUST be permission-gated and MUST record an auditable trail.
|
|
|
|
#### Authorization & Error Semantics (explicit)
|
|
|
|
- Tenant-scope URLs: non-member / not entitled MUST be deny-as-not-found (404).
|
|
- Member but missing capability: server-side MUST deny execution (403).
|
|
- UI behavior: member-without-capability SHOULD see actions visible-but-disabled with tooltip to prevent normal-click 403 pages.
|
|
|
|
#### Out of Scope
|
|
|
|
- No new “Workspace” model in this spec.
|
|
- No platform-plane (`/system`) expansion.
|
|
- No outbound integration calls are introduced as part of diagnostics/repairs.
|
|
|
|
#### Assumptions
|
|
|
|
- “Archived” is treated as an archived/lifecycle state that remains viewable to entitled members.
|
|
- Deactivate (archive) uses the existing tenant lifecycle capability `Capabilities::TENANT_DELETE`.
|
|
|
|
### Key Entities *(include if feature involves data)*
|
|
|
|
- **Tenant**: The internal customer/workspace entity users are members of; has an internal primary key and an external identifier.
|
|
- **Tenant Membership**: Links a user to a tenant with one or more capability grants or derived entitlements.
|
|
- **Capability / Entitlement**: A named permission used to determine visibility/execution of actions within a tenant scope.
|
|
- **Diagnostics Finding**: A detected issue such as “missing owner”, “duplicate membership”, or “identifier misuse risk”.
|
|
- **Repair Action**: A controlled, permission-gated remediation step that fixes a finding and records an audit entry.
|
|
|
|
## Success Criteria *(mandatory)*
|
|
|
|
### Measurable Outcomes
|
|
|
|
- **SC-001**: Read-only members can navigate all tenant UI flows covered by automated tests without encountering an error page during normal click paths.
|
|
- **SC-002**: Protected tenant mutations (e.g., deactivate) have 0 successful executions by users lacking the required capability across automated tests.
|
|
- **SC-003**: Archived tenant access works as defined: entitled members can view; non-members get 404, verified by automated tests.
|
|
- **SC-004**: Membership integrity can be restored via UI-only repair actions for seeded broken states, verified by automated tests.
|