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

4.9 KiB
Raw Blame History

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).
  • OperationRun is 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_reports table: 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_hash already defines the dedupe boundary.
  • Matches the specs clarified rule: provider_connection_id must match exactly; NULL only matches NULL.

Alternatives considered:

  • Match previous runs by only tenant_id + workspace_id + type and 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|severity where severity is 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_reason from 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.