TenantAtlas/specs/075-verification-v1-5/plan.md

151 lines
7.4 KiB
Markdown

# Implementation Plan: Verification Checklist Framework V1.5 (Governance + Supportability + UI-Complete)
**Branch**: `075-verification-v1_5` | **Date**: 2026-02-05 | **Spec**: [spec.md](./spec.md)
**Input**: Feature specification from `/specs/075-verification-v1-5/spec.md`
**Note**: This file is generated from the plan template and then filled in by `/speckit.plan` workflow steps.
## Summary
- Extend the existing 074 verification report system with deterministic **fingerprints** and a **previous report** link so the viewer can show “Changed / No changes”.
- Introduce per-check **acknowledgements** as first-class records (unique per report + check) with explicit confirmation and audit logging, without changing outcomes (“no greenwashing”).
- Update the Verify step UX to be operator-ready: issues-first tabs, centralized badge semantics (BADGE-001), and exactly one primary CTA depending on state.
## Technical Context
<!--
ACTION REQUIRED: Replace the content in this section with the technical details
for the project. The structure here is presented in advisory capacity to guide
the iteration process.
-->
**Language/Version**: PHP 8.4 (Laravel 12)
**Primary Dependencies**: Laravel 12 + Filament v5 + Livewire v4 (Filament v5 requires Livewire v4.0+)
**Storage**: PostgreSQL (Sail) with JSONB (`operation_runs.context`) + a new acknowledgement table
**Testing**: Pest (PHPUnit)
**Target Platform**: Web application (Sail/Docker locally; container deploy via Dokploy)
**Project Type**: web
**Performance Goals**: DB-only viewer renders quickly from stored JSON; fingerprint computation is linear in number of checks (typical report ≤ 50 checks)
**Constraints**:
- Viewer + Verify step are DB-only at render time (no outbound HTTP / Graph / job dispatch).
- All mutations require server-side authorization (RBAC-UX) and explicit confirmation.
- Status-like UI must use centralized badge semantics (BADGE-001).
**Scale/Scope**: Multiple tenants/workspaces; many runs over time; verification used in onboarding and provider workflows
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
- Inventory-first, snapshots-second: PASS (report/ack UX; no inventory semantics changed).
- Read/write separation: PASS (viewer remains read-only; acknowledgements are explicit mutations with confirmation + audit + tests).
- Graph contract path: PASS (viewer is DB-only; no new Graph calls added by this feature).
- Deterministic capabilities: PASS (capabilities remain centrally registered; no raw strings).
- RBAC-UX: PASS (non-member access is 404; member missing capability is 403; server-side enforcement required).
- Run observability: PASS (verification remains an `OperationRun`; dedupe while active is unchanged).
- Data minimization: PASS (no secrets/tokens; audit payload excludes `ack_reason`).
- Badge semantics (BADGE-001): PASS (no new status values; existing verification badge domains remain canonical).
## Project Structure
### Documentation (this feature)
```text
specs/075-verification-v1-5/
├── plan.md # This file
├── research.md # Phase 0 output
├── data-model.md # Phase 1 output
├── quickstart.md # Phase 1 output
├── contracts/ # Phase 1 output
└── tasks.md # Phase 2 output (/speckit.tasks)
```
### Source Code (repository root)
<!--
ACTION REQUIRED: Replace the placeholder tree below with the concrete layout
for this feature. Delete unused options and expand the chosen structure with
real paths (e.g., apps/admin, packages/something). The delivered plan must
not include Option labels.
-->
```text
app/
├── Filament/
├── Jobs/
├── Models/
├── Policies/
├── Services/
└── Support/
database/
└── migrations/
resources/
routes/
tests/
```
**Structure Decision**: Single Laravel web app with Filament v5 panel. This feature extends verification report writer/viewer, adds an acknowledgement persistence model + migration, and refactors the Verify step UI in Filament.
## Complexity Tracking
> **Fill ONLY if Constitution Check has violations that must be justified**
| Violation | Why Needed | Simpler Alternative Rejected Because |
|-----------|------------|-------------------------------------|
| [e.g., 4th project] | [current need] | [why 3 projects insufficient] |
| [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] |
## Phase 0 — Research (output: `research.md`)
See: [research.md](./research.md)
Goals covered:
- Confirm canonical storage approach for report metadata (keep report in `operation_runs.context`).
- Define deterministic fingerprint algorithm and previous report resolution rules.
- Define acknowledgement persistence strategy and capability naming reconciliation.
## Phase 1 — Design & Contracts (outputs: `data-model.md`, `contracts/`, `quickstart.md`)
See:
- [data-model.md](./data-model.md)
- [contracts/](./contracts/)
- [quickstart.md](./quickstart.md)
Design focus:
- Report metadata: add `fingerprint` and `previous_report_id` inside the report JSON.
- Previous report resolution: match identity exactly (type/flow + tenant + workspace + provider connection), with `NULL` connection matching only `NULL`.
- Acknowledgements: first-class DB table keyed by `(operation_run_id, check_key)`; immutable in v1.5.
- Filament UX: issues-first tabs and “one primary CTA” rule; acknowledgements via `Action::make(...)->action(...)` + `->requiresConfirmation()`.
## Phase 2 — Implementation Outline (tasks created in `/speckit.tasks`)
### Data
- Migration: create `verification_check_acknowledgements` table with unique `(operation_run_id, check_key)`.
- Model: `VerificationCheckAcknowledgement` with tenant/workspace scoping.
### Report writer / viewer
- Extend the report writer to compute and store `fingerprint` and `previous_report_id` (report_id is the run id).
- Extend the DB-only viewer to load previous report (when present) and compute the “changed/no-change” indicator.
- Ensure the viewer consumes acknowledgements (DB lookup) and groups “Acknowledged issues” separately.
### Authorization + audit
- Capability: add `tenant_verification.acknowledge` to the canonical capability registry and map to roles.
- Server-side auth: non-members 404; members without capability 403 for acknowledgement.
- Audit: add a new stable action ID (e.g. `verification.check_acknowledged`) with minimal metadata and no `ack_reason`.
### Filament UX
- Verify step: implement the issues-first layout and strict “exactly one primary CTA” rule.
- Actions: acknowledgement requires confirmation; navigation-only links remain links-only.
- BADGE-001: continue to use centralized badge domains for statuses and summary.
### Tests (Pest)
- Fingerprint determinism: same normalized inputs → same hash; severity-only differences → different hash.
- Previous report linking: identity match includes provider connection (`NULL` only matches `NULL`).
- RBAC-UX: non-member gets 404; member without capability gets 403 on acknowledgement.
- Audit: acknowledgement emits correct action id + minimal metadata (assert `ack_reason` absent).
- Viewer DB-only: no outbound HTTP during render/hydration.
## Constitution Check (Post-Design)
Re-check result: PASS. Design keeps report viewing DB-only, introduces a single tenant-scoped mutation with confirmation + audit, preserves RBAC-UX semantics, and maintains BADGE-001 centralized badge rendering.