4.9 KiB
Research: Verification Checklist Framework V1.5 (075)
Date: 2026-02-05
Phase: Phase 0 (Foundational Research)
Status: Complete
Decisions
D-075-001 — Canonical storage for report + metadata
Decision: Store the verification report (including fingerprint and previous_report_id) inside operation_runs.context.verification_report (JSONB), consistent with 074.
Rationale:
- Viewer surfaces must be DB-only at render time (constitution: Operations / Run Observability Standard).
OperationRunis already the canonical operational record and stable viewer entry point.- Adds supportability metadata without introducing a new top-level report table.
Alternatives considered:
- Dedicated
verification_reportstable: rejected for v1.5 to avoid new query/index surfaces; revisit if we need global querying across reports.
D-075-002 — Report identity + “previous report” resolution
Decision: Resolve previous_report_id by querying the most recent earlier OperationRun whose run identity matches exactly (flow/type, tenant, workspace, provider connection where applicable).
Rationale:
- The existing
OperationRunService::ensureRunWithIdentity()+run_identity_hashalready defines the dedupe boundary. - Matches the spec’s clarified rule:
provider_connection_idmust match exactly;NULLonly matchesNULL.
Alternatives considered:
- Match previous runs by only
tenant_id + workspace_id + typeand then filter in PHP: rejected due to ambiguity and risk of cross-connection mixing.
D-075-003 — Report ID semantics
Decision: Treat the OperationRun ID as the report identifier in UX and contracts (report_id == operation_run_id).
Rationale:
- The report is attached to the run; the run is the stable, tenant-scoped canonical record.
- Avoids a second identifier for the same “verification execution artifact”.
Alternatives considered:
- Generate a separate report UUID inside the JSON: rejected as it adds indirection without benefits in v1.5.
D-075-004 — Fingerprint algorithm
Decision: Use SHA-256 over a deterministic normalization of check outcomes:
- flatten checks
- sort by
check.key - contribute
key|status|blocking|reason_code|severitywhereseverityis always present (missing → empty)
Store as lowercase hex.
Rationale:
- Deterministic across environments.
- Treats severity-only changes as meaningful (per clarified requirement).
Alternatives considered:
- Hash the full report JSON: rejected (unstable ordering, non-semantic fields like timestamps).
D-075-005 — Per-check acknowledgements persistence
Decision: Create a first-class table verification_check_acknowledgements keyed by (operation_run_id, check_key) with a unique constraint.
Rationale:
- Acknowledgements are governance metadata and must be queryable and auditable.
- Unique per report/check is enforced by the DB.
Alternatives considered:
- Store acknowledgements inside
operation_runs.context: rejected as it complicates update semantics and auditability, and risks “report mutation” appearing like a changed verification outcome.
D-075-006 — Capability naming reconciliation
Decision: Introduce a dedicated canonical capability tenant_verification.acknowledge in the capability registry and map it in the role → capability map.
Rationale:
- Keeps the feature spec requirement literal and avoids overloading “findings” semantics.
- Preserves the constitution rule that capabilities are centrally registered (no raw strings).
Alternatives considered:
- Reuse existing
tenant_findings.acknowledge: rejected because this feature is specifically verification-report scoped, and we want the permission surface to remain explicit.
D-075-007 — Audit action identifier + payload minimization
Decision: Add a stable audit action ID for acknowledgements (e.g. verification.check_acknowledged) and emit it on successful acknowledgement. Audit metadata is minimal and MUST NOT include ack_reason.
Rationale:
- Acknowledgement is a write mutation; constitution requires audit logging.
- Spec explicitly excludes
ack_reasonfrom audit payload; it remains only in the acknowledgement record.
Alternatives considered:
- Reuse
verification.completed: rejected because it conflates verification execution with governance mutation.
D-075-008 — Filament UI implementation constraints
Decision: Implement the “Verify step” UX changes in Filament v5 (Livewire v4) using:
- DB-only viewer helper (no external calls)
- centralized badge domains (BADGE-001)
- mutation via Filament
Action::make(...)->action(...)with->requiresConfirmation()
Rationale:
- Aligns with Filament v5 patterns and constitution rules.
Alternatives considered:
- Publish/override Filament internal views: rejected; prefer render hooks + CSS hooks as needed.