TenantAtlas/specs/075-verification-v1-5/data-model.md
ahmido 53dc89e6ef Spec 075: Verification Checklist Framework V1.5 (fingerprint + acknowledgements) (#93)
Implements Spec 075 (V1.5) on top of Spec 074.

Highlights
- Deterministic report fingerprint (sha256) + previous_report_id linkage
- Viewer change indicator: "No changes" vs "Changed" when previous exists
- Check acknowledgements (fail|warn|block) with capability-first auth, confirmation, and audit event
- Verify-step UX polish (issues-first, primary CTA)

Testing
- Focused Pest coverage for fingerprint, previous resolver, change indicator, acknowledgements, badge semantics, DB-only viewer guard.

Notes
- Viewing remains DB-only (no external calls while rendering).

Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box>
Reviewed-on: #93
2026-02-05 21:44:19 +00:00

3.5 KiB

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”