Implements Spec 084 (verification-surfaces-unification). Highlights - Unifies tenant + onboarding verification start on `provider.connection.check` (OperationRun-based, enqueue-only). - Ensures completed blocked runs persist a schema-valid `context.verification_report` stub (DB-only viewers never show “unavailable”). - Adds tenant embedded verification report widget with DB-only rendering + canonical tenantless “View run” links. - Enforces 404/403 semantics for tenantless run viewing (workspace membership + tenant entitlement required; otherwise 404). - Fixes admin panel widgets to resolve tenant from record context so Owners can start verification and recent operations renders correctly. Tests - Ran: `vendor/bin/sail artisan test --compact tests/Feature/Verification/ tests/Feature/ProviderConnections/ProviderOperationBlockedGuidanceSpec081Test.php tests/Feature/Onboarding/OnboardingVerificationTest.php tests/Feature/RunAuthorizationTenantIsolationTest.php tests/Feature/Filament/TenantVerificationReportWidgetTest.php tests/Feature/Filament/RecentOperationsSummaryWidgetTest.php` Notes - Filament v5 / Livewire v4 compatible. - No new assets; no changes to provider registration. Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box> Reviewed-on: #102
174 lines
14 KiB
Markdown
174 lines
14 KiB
Markdown
# Feature Specification: Verification Surfaces Unification
|
||
|
||
**Feature Branch**: `084-verification-surfaces-unification`
|
||
**Created**: 2026-02-09
|
||
**Status**: Draft
|
||
**Input**: User description: "Unify tenant + onboarding verification so all verification uses the same run-based mechanism with DB-only viewing and always-available reports (including blocked)."
|
||
|
||
## Clarifications
|
||
|
||
### Session 2026-02-09
|
||
|
||
- Q: For tenant members who are in-scope but lack the capability to start verification, how should the “Verify configuration” action behave in the UI? → A: Visible but disabled, with helper text explaining the missing capability (server still enforces 403 if invoked).
|
||
- Q: When rendering the embedded verification viewer on the tenant detail page, which run should be selected as “the last relevant run”? → A: Latest run attempt for that tenant+type (even if queued/running); if active and no report yet, show a DB-only “in progress” state.
|
||
- Q: On the tenant detail page, when no verification run exists yet, what should the embedded verification section do? → A: Show a DB-only empty state with a “Start verification” CTA.
|
||
- Q: For the canonical tenantless run viewer (/admin/operations/{run}), what should be required to view a run that is associated with a tenant? → A: Require both workspace membership AND tenant entitlement; missing either is deny-as-not-found (404).
|
||
|
||
## User Scenarios & Testing *(mandatory)*
|
||
|
||
<!--
|
||
IMPORTANT: User stories should be PRIORITIZED as user journeys ordered by importance.
|
||
Each user story/journey must be INDEPENDENTLY TESTABLE - meaning if you implement just ONE of them,
|
||
you should still have a viable MVP (Minimum Viable Product) that delivers value.
|
||
|
||
Assign priorities (P1, P2, P3, etc.) to each story, where P1 is the most critical.
|
||
Think of each story as a standalone slice of functionality that can be:
|
||
- Developed independently
|
||
- Tested independently
|
||
- Deployed independently
|
||
- Demonstrated to users independently
|
||
-->
|
||
|
||
### User Story 1 - Verify tenant configuration consistently (Priority: P1)
|
||
|
||
As a workspace member with the appropriate permission, I can start a tenant verification from the tenant detail view and immediately see the latest stored verification results, without the page performing external provider calls during rendering.
|
||
|
||
**Why this priority**: This is the primary operational entry-point and must be fast, safe, and predictable.
|
||
|
||
**Independent Test**: Can be fully tested by starting verification from the tenant detail view, asserting a run record exists, and asserting the embedded viewer renders using stored data.
|
||
|
||
**Acceptance Scenarios**:
|
||
|
||
1. **Given** a tenant with an eligible provider connection, **When** I click “Verify configuration”, **Then** a verification run is started or deduped, and the tenant page renders the report viewer using stored data only.
|
||
2. **Given** a tenant where verification cannot proceed (e.g., missing consent/credentials), **When** I click “Verify configuration”, **Then** a completed “blocked” run exists and the embedded viewer shows a stub/preflight report (not an “unavailable” state).
|
||
|
||
|
||
|
||
### User Story 2 - Onboarding verify access behaves identically (Priority: P2)
|
||
|
||
As a workspace member with onboarding verification capability, I can start onboarding verification and receive the same run, dedupe/busy, blocked-report, and canonical link behavior as the tenant verification surfaces.
|
||
|
||
**Why this priority**: Removes confusion and reduces operational variance between onboarding and day-2 operations.
|
||
|
||
**Independent Test**: Can be tested by starting verification in onboarding and asserting identical run outcomes and viewer behavior to the tenant surface.
|
||
|
||
**Acceptance Scenarios**:
|
||
|
||
1. **Given** onboarding verification is started while another verification run is already active for the same target, **When** I start verification again, **Then** I receive a busy/deduped result that points to the existing active run.
|
||
|
||
---
|
||
|
||
### User Story 3 - Use canonical run links everywhere (Priority: P3)
|
||
|
||
As a workspace member, I can open the canonical run viewer link from any verification surface and it consistently resolves to the same “tenantless” run route.
|
||
|
||
**Why this priority**: Improves supportability and prevents broken/ambiguous deep links.
|
||
|
||
**Independent Test**: Can be tested by starting verification, then asserting all “View run” links point to the canonical run route and the page is accessible only to authorized members.
|
||
|
||
**Acceptance Scenarios**:
|
||
|
||
1. **Given** a verification run exists, **When** I click “View run”, **Then** I am taken to the canonical run viewer route for that run.
|
||
|
||
---
|
||
|
||
### Edge Cases
|
||
- Verification is started while an existing run is queued/running for the same target (dedupe/busy behavior must be consistent across surfaces).
|
||
- Verification cannot proceed due to missing consent/credentials (a completed blocked run must still have a schema-valid report).
|
||
- Viewer is opened by a non-member (deny-as-not-found behavior).
|
||
- Stored report data is present but incomplete/invalid (viewer must fail safe with a clear non-leaky message and no external calls).
|
||
|
||
## Non-Functional Requirements
|
||
|
||
- **NFR-001 (DB-only render)**: Tenant detail, onboarding verification display, and canonical run viewer rendering MUST be DB-only, with no external provider or Graph calls during mount/render/poll/refresh interactions.
|
||
- **NFR-002 (start path latency)**: Verification start interactions (`started`, `deduped`, `scope_busy`, `blocked`) SHOULD complete request handling in under 1 second under normal local/staging conditions because they only authorize, create/dedupe run state, enqueue, and notify.
|
||
- **NFR-003 (refresh/polling discipline)**: Verification UI refresh behavior MUST read persisted `OperationRun` state only and MUST NOT trigger inventory refresh or Graph permission reconciliation during display refresh.
|
||
|
||
## 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 (`OperationRun` type/identity/visibility), and tests.
|
||
If security-relevant DB-only actions intentionally skip `OperationRun`, the spec MUST describe `AuditLog` 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 confirmation (`->requiresConfirmation()`),
|
||
- 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 `OperationRun`. 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.
|
||
|
||
**Constitution alignment (Filament Action Surfaces):** If this feature adds or modifies any Filament Resource / RelationManager / Page,
|
||
the spec MUST include a “UI Action Matrix” (see below) and explicitly state whether the Action Surface Contract is satisfied.
|
||
If the contract is not satisfied, the spec MUST include an explicit exemption with rationale.
|
||
|
||
<!--
|
||
ACTION REQUIRED: The content in this section represents placeholders.
|
||
Fill them out with the right functional requirements.
|
||
-->
|
||
|
||
### Functional Requirements
|
||
|
||
- **FR-001**: System MUST provide a single, unified verification start mechanism used by both the tenant detail “Verify configuration” and onboarding “Verify access” surfaces.
|
||
- **FR-002**: Starting verification MUST create (or dedupe to) a single “verification run” record for the target, and surface a stable link to view that run.
|
||
- **FR-003**: When a verification run cannot proceed due to missing prerequisites, the system MUST finalize the run as completed “blocked” and persist a schema-valid stub/preflight verification report.
|
||
- **DB-only render invariant**: Verification viewers are read-only projections of persisted run/report data; they MUST NOT perform provider/Graph calls and MUST NOT persist permission inventory updates.
|
||
- **FR-004**: For any verification run that is completed (including blocked), the embedded/onboarding viewers MUST render the verification report using stored data only.
|
||
- **FR-004a**: The tenant detail embedded viewer MUST select the latest verification run attempt for the tenant and verification type; if that run is active (queued/running) and no report is yet available, the UI MUST render a DB-only “in progress” state.
|
||
- **FR-004b**: If no verification run exists yet for the tenant and verification type, the tenant detail embedded section MUST show a DB-only empty state with a “Start verification” CTA.
|
||
- **FR-005**: UI page rendering (including mount/load/summary components) MUST NOT trigger external provider calls directly or indirectly.
|
||
- **FR-006**: Dedupe rules MUST ensure at most one active run (queued/running) exists per target and verification type; repeated starts during an active run MUST return a busy/deduped outcome.
|
||
- **FR-007**: The system MUST persist any permissions inventory updates only as part of the verification job’s execution, and MUST NOT persist these updates during page rendering.
|
||
- **FR-008**: All “View run” links exposed by verification surfaces MUST use the canonical tenantless run viewer route.
|
||
- **FR-009**: Authorization MUST be enforced server-side:
|
||
- missing workspace membership OR missing tenant entitlement MUST be deny-as-not-found (404) for tenant-scoped routes/actions and tenantless canonical views of tenant-associated records,
|
||
- members lacking the required capability to start verification MUST see the action visible-but-disabled with helper text, and MUST receive a forbidden response (403) if invoked.
|
||
- **FR-010**: The system MUST emit run observability sufficient for operations (run type, outcome, timestamps, target scope) and MUST be test-covered.
|
||
|
||
### Assumptions & Dependencies
|
||
|
||
- This change unifies surfaces and report availability; it does not expand the set of verification checks beyond what is already produced today.
|
||
- For tenant verification surfaces (`ViewTenant` header action, tenant embedded CTA, and tenant list verify action), “eligible provider connection” means the resolved **default** provider connection for provider `microsoft`.
|
||
- Onboarding verification continues to use the session-selected provider connection, and still runs through the same unified operation type and run orchestration.
|
||
- Verification reports are stored with the verification run record and are treated as the sole source for UI rendering.
|
||
- External provider calls are permitted only as part of explicit user-triggered verification runs and their execution (never during page rendering).
|
||
- Existing authorization capabilities and membership rules remain the source of truth; this feature standardizes how they apply across surfaces.
|
||
|
||
## UI Action Matrix *(mandatory when Filament is changed)*
|
||
|
||
If this feature adds/modifies any Filament Resource / RelationManager / Page, fill out the matrix below.
|
||
|
||
For each surface, list the exact action labels, whether they are destructive (confirmation? typed confirmation?),
|
||
RBAC gating (capability + enforcement helper), and whether the mutation writes an audit log.
|
||
|
||
| Surface | Location | Header Actions | Inspect Affordance (List/Table) | Row Actions (max 2 visible) | Bulk Actions (grouped) | Empty-State CTA(s) | View Header Actions | Create/Edit Save+Cancel | Audit log? | Notes / Exemptions |
|
||
|---|---|---|---|---|---|---|---|---|---|---|
|
||
| Tenant detail view | Tenant admin area | Verify configuration | Embedded viewer + View run link | n/a | n/a | Start verification (empty state) | n/a | n/a | Yes | DB-only render; starts/dupes run; if missing capability: visible but disabled with helper |
|
||
| Tenant list (Tenants table) | Tenant admin area | n/a | Clickable row + View action | Verify configuration (grouped action) | grouped | n/a | n/a | n/a | Yes | Uses same unified start path and canonical run links as tenant detail |
|
||
| Onboarding verification step | Onboarding wizard | Start verification | Embedded viewer + View run link | n/a | n/a | n/a | n/a | n/a | Yes | Same semantics as tenant surface |
|
||
| Tenantless run viewer | Operations area | n/a | n/a | n/a | n/a | n/a | n/a | n/a | Yes | Requires workspace membership + tenant entitlement; otherwise 404 |
|
||
|
||
### Key Entities *(include if feature involves data)*
|
||
|
||
- **Verification Run**: An immutable operational record representing one attempt to verify access/configuration for a target scope. It captures status/outcome and a canonical link for viewing.
|
||
- **Verification Report**: A schema-valid, stored report attached to a verification run. It is always present for completed runs, including blocked runs (stub/preflight).
|
||
|
||
## Success Criteria *(mandatory)*
|
||
### Measurable Outcomes
|
||
|
||
- **SC-001**: 100% of completed blocked verification runs display a usable stub report (no "report unavailable" state for completed blocked runs).
|
||
- **SC-002**: Tenant detail pages render without any external provider calls; verification-related external calls occur only after an explicit start action.
|
||
- **SC-003**: When a verification run is already active for the same target and type, repeated starts return a busy/deduped response in under 1 second.
|
||
- **SC-004**: All verification surfaces provide a canonical "View run" link, and support can use that single URL to review outcomes.
|