# 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 what’s 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.