# Implementation Plan: 076-permissions-enterprise-ui

**Branch**: `076-permissions-enterprise-ui` | **Date**: 2026-02-05

**Spec**: specs/076-permissions-enterprise-ui/spec.md

**Input**: specs/076-permissions-enterprise-ui/spec.md

## Summary

Implement the “Tenant Required Permissions (Enterprise Remediation UX)” plus the Verify-step clustering:

- Tenant-scoped Filament Page for required permissions with an overview section + details matrix.
- Copy-to-clipboard for missing permissions split by type (application vs delegated), with clarified semantics.
- Verification report updates to emit 5–7 clustered checks and onboarding Verify step rendering updates (issues-first), deep-linking to the Required Permissions page.

## Technical Context

**Language/Version**: PHP 8.4.15 (Laravel 12)

**Primary Dependencies**: Filament v5 + Livewire v4.0+

**Storage**: PostgreSQL (Sail)

**Testing**: Pest v4

**Target Platform**: Filament admin panel with tenancy routing (`/admin/t/{tenant}/...`)

**Project Type**: Laravel monolith

**Performance Goals**: DB-only render; in-memory filtering on config-sized datasets (<~200 rows)

**Constraints**:

- Required Permissions page is DB-only at render (no Graph/HTTP).
- Tenant isolation / RBAC-UX:
  - non-member tenant access is 404 via existing middleware
  - member without `Capabilities::TENANT_VIEW` is 403
- Badge semantics (BADGE-001): use centralized `BadgeDomain` mappings only.
- Copy semantics: respects Feature filter only; ignores Search; always copies Missing only; Type fixed by clicked button.
- Enterprise correctness: verification runs refresh Observed permissions inventory (Graph) and persist it; viewer surfaces remain DB-only.

## Constitution Check

*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*

- Read/write separation: PASS (page is read-only; copy is client-side)
- Graph contract path: PASS (no Graph calls on render)
- RBAC-UX: PASS (404 for non-members; 403 for missing capability)
- Badge semantics: PASS (explicit badge domains are fixed in spec)

## Project Structure

### Documentation (this feature)

- specs/076-permissions-enterprise-ui/spec.md
- specs/076-permissions-enterprise-ui/plan.md (this file)
- specs/076-permissions-enterprise-ui/research.md
- specs/076-permissions-enterprise-ui/data-model.md
- specs/076-permissions-enterprise-ui/contracts/*
- specs/076-permissions-enterprise-ui/quickstart.md
- specs/076-permissions-enterprise-ui/tasks.md (generated next via speckit)

### Code (planned)

- app/Filament/Pages/TenantRequiredPermissions.php (new)
- resources/views/filament/pages/tenant-required-permissions.blade.php (new)
- app/Jobs/ProviderConnectionHealthCheckJob.php (extend verification report)
- app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php (render check clusters)
- resources/views/filament/forms/components/managed-tenant-onboarding-verification-report.blade.php (render checks)
- tests/Feature/* (Pest)

## Phase 0 — Outline & Research (COMPLETE)

Output: specs/076-permissions-enterprise-ui/research.md

Key decisions:

- Dedicated tenant-scoped Filament Page for Required Permissions.
- Use DB-only permission status (`tenant_permissions`) + `config/intune_permissions.php` for required definitions.
- Implement copy actions via existing robust clipboard fallback pattern.
- Compute clustered verification checks when writing the verification report (job/service), not in Blade.
- Refresh Observed permission inventory during the verification run (Operation Run), not in any viewer surface.

## Phase 1 — Design & Contracts (COMPLETE)

Outputs:

- specs/076-permissions-enterprise-ui/data-model.md
- specs/076-permissions-enterprise-ui/contracts/required-permissions.view-model.json
- specs/076-permissions-enterprise-ui/contracts/verification-report.checks.md
- specs/076-permissions-enterprise-ui/quickstart.md

Remaining required step in this phase:

- Run `.specify/scripts/bash/update-agent-context.sh copilot`.

## Phase 2 — Implementation Planning (READY)

### 2.1 Tenant Required Permissions Page

- Route/tenancy: create tenant page at slug `required-permissions` (under `/admin/t/{tenant}/required-permissions`).
- Authorization:
  - non-member 404 is enforced by existing tenancy middleware
  - add `canAccess()` check for `Capabilities::TENANT_VIEW` (403)
- Data:
  - required definitions: `config/intune_permissions.php`
  - tenant status: `tenant_permissions` via `TenantPermissionService` with DB-only semantics
- Overview:
  - overall status mapping: Blocked if any missing application; Needs attention if only delegated missing; Ready if none missing
  - impacted features summary (from permission → features tags), with clickable cards that apply a Feature filter
  - primary next step: Admin consent guide link (prefer existing tenant-specific Admin Consent URL; fall back to external guide)
- Details matrix:
  - missing-first sorting
  - filters: Feature, Type, Status
  - search across key/description
- Badges:
  - per-row uses `BadgeDomain::TenantPermissionStatus`
  - overview uses `BadgeDomain::VerificationReportOverall`
- Copy actions:
  - copy missing application
  - copy missing delegated
  - selection respects Feature filter only; ignores Search; always Missing-only

### 2.2 Verification Check Clustering

- Extend verification report writing to include 5–7 clustered checks derived from required permissions status.
- Follow specs/076-permissions-enterprise-ui/contracts/verification-report.checks.md for keys + status rules.
- Ensure permission clusters only assert “missing” when Observed inventory refresh succeeded during the run; otherwise degrade to warnings with retry guidance.

### 2.3 Verify Step UI

- Update onboarding Verify step to render check clusters from `verification_report` (via `VerificationReportViewer`).
- Issues-first ordering: failures, then warnings, then passes.
- Provide an explicit “Open Required Permissions” next-step link.

### 2.4 Tests (Pest)

- Access:
  - member without `tenant.view` gets 403
  - non-member tenant access remains 404
- Copy semantics:
  - Feature filter affects payload; Search does not
  - type-specific copy returns only missing of that type
- Verification report:
  - cluster keys present
  - cluster status mapping matches missing application vs delegated rules
