TenantAtlas/specs/067-rbac-troubleshooting/spec.md
ahmido 3490fb9e2c feat: RBAC troubleshooting & tenant UI bugfix pack (spec 067) (#84)
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
2026-01-31 20:09:25 +00:00

9.0 KiB

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.