# Data Model: Verification Checklist Framework V1.5 (075) **Date**: 2026-02-05 **Phase**: Phase 1 (Design) **Status**: Draft (design-complete for implementation planning) --- ## Existing Entity (reference) ### OperationRun (existing) **Purpose**: Canonical operational record. Verification reports are stored in `operation_runs.context.verification_report` (JSONB). **Key fields (relevant)**: - `id` - `tenant_id` - `workspace_id` - `type` (verification flow identifier) - `run_identity_hash` (identity hash used for active dedupe + identity matching) - `status` - `context` (JSONB) **Verification report storage**: - `context.verification_report` (JSON object) --- ## New Persistent Entity ### VerificationCheckAcknowledgement (new table) **Table name**: `verification_check_acknowledgements` **Purpose**: First-class governance record that a failing/warning check is acknowledged for a specific report (report == operation run). **Fields**: - `id` (primary key) - `tenant_id` (FK or scalar; used for tenant-scoped filtering and isolation checks) - `workspace_id` (FK or scalar) - `operation_run_id` (FK to `operation_runs.id`) — the “report” - `check_key` (string) - `ack_reason` (string, max 160) - `expires_at` (timestamp, nullable) — informational only in v1.5 - `acknowledged_at` (timestamp) - `acknowledged_by_user_id` (FK to `users.id`) - `created_at`, `updated_at` **Uniqueness constraint (required)**: - unique `(operation_run_id, check_key)` **Indexes (recommended)**: - `(tenant_id, workspace_id, operation_run_id)` - `(operation_run_id)` **Validation rules**: - `ack_reason`: required, string, length ≤ 160 - `expires_at`: optional, must be a valid timestamp, should be >= acknowledged_at (implementation may enforce) **State transitions**: - Immutable per report/check in v1.5: create once; no update/delete/unack flows. --- ## Contracted Document (stored in JSON) ### VerificationReport (JSON in `OperationRun.context.verification_report`) **Purpose**: Structured, versioned report of verification results used by the DB-only viewer. **Identity**: - `report_id`: `operation_runs.id` - `previous_report_id`: previous run id for same identity (nullable) **New v1.5 fields**: - `fingerprint` (string; lowercase hex; SHA-256) - `previous_report_id` (nullable integer/uuid depending on `OperationRun` PK type) **Existing core fields (from 074, reference)**: - `schema_version` (SemVer string; major `1`) - `flow` (verification flow identifier; aligns with `OperationRun.type`) - `generated_at` (timestamp) - `summary` (counts + overall outcome) - `checks[]` (flat array) including: - `key` - `title` - `status` (`pass|fail|warn|skip|running`) - `severity` (`info|low|medium|high|critical` or empty string) - `blocking` (boolean) - `reason_code` (string) - safe evidence pointers - `next_steps[]` (navigation-only links) **Fingerprint normalization input** (strict): - Flatten all checks across `checks[]`. - Sort by `check.key`. - Contribute the stable tuple string: - `key|status|blocking|reason_code|severity` - `severity` must always be present (missing normalized to empty string). --- ## Derived/Computed View Data (not persisted) ### Change indicator Computed in the viewer by comparing: - current `verification_report.fingerprint` - previous `verification_report.fingerprint` States: - no previous report → no indicator - fingerprints match → “No changes since previous verification” - fingerprints differ → “Changed since previous verification”