TenantAtlas/specs/074-verification-checklist/tasks.md
ahmido 439248ba15 feat: verification report framework (074) (#89)
Implements the 074 verification checklist framework.

Highlights:
- Versioned verification report contract stored in operation_runs.context.verification_report (DB-only viewer).
- Strict sanitizer/redaction (evidence pointers only; no tokens/headers/payloads) + schema validation.
- Centralized BADGE-001 semantics for check status, severity, and overall report outcome.
- Deterministic start (dedupe while active) via shared StartVerification service; capability-first authorization (non-member 404, member missing capability 403).
- Completion audit event (verification.completed) with redacted metadata.
- Integrations: OperationRun detail viewer, onboarding wizard verification step, provider connection start surfaces.

Tests:
- vendor/bin/sail artisan test --compact tests/Feature/Verification tests/Unit/Badges/VerificationBadgesTest.php
- vendor/bin/sail bin pint --dirty

Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box>
Reviewed-on: #89
2026-02-03 23:58:17 +00:00

121 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Tasks: 074 Verification Checklist Framework
**Input**: Design documents from `/specs/074-verification-checklist/`
**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/
**Tests**: Required (Pest).
---
## Phase 1: Foundational (Blocking Prerequisites)
- [x] T001 [US1] Add example reports under specs: `specs/074-verification-checklist/contracts/examples/*.json` (pass/fail/warn/running) aligned to `contracts/verification-report.schema.json`.
- [x] T002 [P] [US1] Add a small schema validation helper for reports (pure PHP, no external deps) in `app/Support/Verification/VerificationReportSchema.php` (version parsing + shape validation + graceful fallback).
- [x] T003 [P] [US1] Add report redaction/sanitization utility in `app/Support/Verification/VerificationReportSanitizer.php` (denylist keys/values; enforce evidence pointers only).
- [x] T004 [US1] Add value objects (or typed arrays) for report/check concepts in `app/Support/Verification/*` (status/severity enums or constants) to avoid ad-hoc strings throughout UI.
**RBAC & UX prereqs**
- [x] T005 [US3] Decide and document the start capability used per verification flow (v1: use `Capabilities::PROVIDER_RUN` for `provider.connection.check`; prefer existing constants in `app/Support/Auth/Capabilities.php`).
- [x] T006 [US3] Add/confirm central UI enforcement helper usage for “visible-but-disabled with tooltip” in verification start UI (use tenant-scoped `app/Support/Rbac/UiEnforcement.php` with a resolved `Tenant` record).
**Badges (BADGE-001)**
- [x] T007 [P] [US1] Add badge domains for verification status/severity in `app/Support/Badges/BadgeDomain.php`.
- [x] T008 [P] [US1] Add domain mappers in `app/Support/Badges/Domains/*` (e.g., `VerificationCheckStatusBadge`, `VerificationCheckSeverityBadge`).
- [x] T009 [US1] Register domains in `app/Support/Badges/BadgeCatalog.php`.
- [x] T010 [US1] Add mapping tests for new badge domains in `tests/Unit/Badges/*`.
**Checkpoint**: Report contract + sanitizer + badge domains exist; UI work can start.
---
## Phase 2: User Story 1 — Operator sees whats wrong (Priority: P1)
**Goal**: Render a structured, DB-only verification report viewer for a run.
**Independent Test**: Seed an `OperationRun` with `context.verification_report` and assert the viewer renders the correct summary + per-check details, with no outbound HTTP.
### Tests (write first)
- [x] T011 [US1] Add a viewer DB-only test (no outbound HTTP, no job dispatch) in `tests/Feature/Verification/VerificationReportViewerDbOnlyTest.php` using `Http::fake()` + `Bus::fake()` and asserting no requests / no dispatch during page render (including a second render to cover Livewire refresh/poll paths).
- [x] T012 [US1] Add a redaction test in `tests/Feature/Verification/VerificationReportRedactionTest.php` to ensure forbidden keys/values never appear in stored/rendered evidence.
- [x] T013 [US1] Add a “malformed/missing report” viewer test in `tests/Feature/Verification/VerificationReportMissingOrMalformedTest.php` (safe empty state).
### Implementation
- [x] T014 [US1] Create a reusable viewer Blade partial in `resources/views/filament/components/verification-report-viewer.blade.php` (summary banner + counts + collapsible checks + next steps links-only).
- [x] T015 [US1] Create a Filament view entry/helper to render the viewer from an `OperationRun` in `app/Filament/Support/VerificationReportViewer.php` (or existing Filament helpers location), using only DB values.
- [x] T016 [US1] Integrate viewer into Monitoring → Operations run view page: update `app/Filament/Resources/OperationRunResource.php` (infolist) to show the verification report section when `context.verification_report` exists.
**Checkpoint**: A seeded report is readable in Monitoring; viewer is DB-only.
---
## Phase 3: User Story 2 — Deterministic starts (Priority: P2)
**Goal**: Starting verification is idempotent while active (dedupe) and guides users to the active run.
**Independent Test**: Start verification twice for the same identity and assert a single active run is used.
### Tests
- [x] T017 [US2] Add a dedupe regression test in `tests/Feature/Verification/VerificationStartDedupeTest.php` asserting repeated starts reuse the same active run (leveraging the existing `OperationRunService::ensureRunWithIdentity()` behavior).
- [x] T018 [US2] Add a “new run after completion” test in `tests/Feature/Verification/VerificationStartAfterCompletionTest.php`.
### Implementation
- [x] T019 [US2] Add (or adapt) a small “start verification” service wrapper in `app/Services/Verification/StartVerification.php` that: authorizes, creates/reuses a run identity, enqueues a verifier job, and returns the run.
- [x] T020 [US2] Update the managed tenant onboarding verification step to route through the shared starter and replace the binary status UI with the shared verification report viewer (or a safe empty state) in `app/Filament/Pages/Workspaces/ManagedTenantOnboardingWizard.php`.
- [x] T021 [US2] Update provider connection verification start surface(s) (where present) to route through the same shared starter.
**Checkpoint**: Starts are deterministic and route users to the active run.
---
## Phase 4: User Story 3 — Least-privilege and safe disclosure (Priority: P3)
**Goal**: View vs start capability split; non-members get 404; members lacking start capability get 403 on execution.
**Independent Test**: Readonly member can view report but cannot start; non-member cannot discover tenant/run.
### Tests
- [x] T022 [US3] Add authorization tests for view vs start in `tests/Feature/Verification/VerificationAuthorizationTest.php` covering:
- tenant non-member → 404 on view + start
- tenant member without start capability → can view, start returns forbidden (403)
- tenant member with start capability → can start
### Implementation
- [x] T023 [US3] Ensure start actions enforce server-side authorization via Gate/Policy (no UI-only enforcement) and use capability constants from `app/Support/Auth/Capabilities.php`.
- [x] T024 [US3] Ensure tenant-scope non-membership yields deny-as-not-found behavior for verification routes/actions (align with existing tenant routing patterns and helpers).
**Checkpoint**: Authorization behavior matches RBAC-UX contract.
---
## Phase 5: Audit & Completion Events (Cross-cutting)
- [x] T025 [US1] Add a stable audit action ID for verification completion in `app/Support/Audit/AuditActionId.php`.
- [x] T026 [US1] Emit a completion audit event when a verification run finalizes (where run completion is set) using `app/Services/Audit/WorkspaceAuditLogger.php` with redacted metadata (run id + counts only).
- [x] T030 [US1] Add a report writer in `app/Support/Verification/VerificationReportWriter.php` that builds `context.verification_report`, derives `summary.overall` deterministically, enforces reason codes + evidence pointer-only policy, and runs sanitizer before persistence.
- [x] T031 [US1] Integrate the report writer into `app/Jobs/ProviderConnectionHealthCheckJob.php` so `provider.connection.check` writes a compliant `verification_report` to the run (both success and failure paths) before marking the run completed.
- [x] T032 [US1] Add a report-writing integration test in `tests/Feature/Verification/ProviderConnectionHealthCheckWritesReportTest.php` ensuring the run ends with a valid, sanitized `context.verification_report` (and no forbidden evidence fields).
---
## Phase 6: Polish & Regression Guards
- [x] T027 [P] Add UI polish for empty/missing report state in the viewer (no leaks of internal details).
- [x] T028 Run formatting: `vendor/bin/sail bin pint --dirty`.
- [x] T029 Run targeted tests: `vendor/bin/sail artisan test --compact tests/Feature/Verification`.
---
## Dependencies & Execution Order
- Phase 1 (Foundational) blocks all other phases.
- US1 can start after Phase 1; US2/US3 can proceed after Phase 1 but should reuse US1 primitives (viewer + sanitizer + badges).
- Audit completion (Phase 5) depends on the shared verification job/service that finalizes runs.