dot-iu-cutter v0.2 — P0-5 decision_backlog_history Design (2026-05-16)
dot-iu-cutter v0.2 — P0-5 decision_backlog_history Design
document_path: knowledge/dev/laws/dieu44-trien-khai/v0.2-design/dot-iu-cutter-v0.2-p0-5-decision-backlog-history-design-2026-05-16.md
revision: r1
date: 2026-05-16
author: Agent (Claude Code CLI, Opus 4.7 1M)
verifier: GPT (PENDING)
phase: v0.2 — P0-5-remainder decision_backlog_history DESIGN (LOGICAL ONLY; no DDL)
master: dot-iu-cutter-v0.2-p0-6-p0-5-remainder-batch-design-master-2026-05-16.md
v0.1_predecessor: migration-design/dot-iu-cutter-v0.1-p0-5-decision-backlog-entry-migration-design-2026-05-15.md §4.2
mutation_performed: false
ddl_written: false
§1 — Purpose
decision_backlog_history is the version trail for decision_backlog_entry
(Đ38 manifest-as-code discipline): every create / status change / field update /
closure / re-open / supersede on a backlog entry produces an immutable history row.
In v0.1 it was specified as a P0-5 companion; in v0.2 its parent
(decision_backlog_entry) is already LIVE & empty as a v0.1 table — so this is a
pure additive empty-table design into cutter_governance.
§2 — Source Design References
- v0.1 P0-5 migration design §4.2 (fields baseline) — schema-placement OPEN item is
now resolved to
cutter_governance(batch master §6). - D5 §4.7 (diffability/versioning); G-2 closure §5.3–§5.5; Đ38 versioning discipline.
§3 — Logical Object / Table Intent
primary_table: cutter_governance.decision_backlog_history
becomes: cutter_governance table #10 (post-create, gated; design only now)
target_schema: cutter_governance # resolved (batch master §6)
target_layer: Lớp KHO (registry trail; co-located with its live parent)
authority_pattern: PG = SSOT; KB mirror only
§4 — Proposed Fields (conceptual — NO DDL)
| Field | Type-class | Nullable | Notes |
|---|---|---|---|
history_id |
uuid | NO | history row identifier |
decision_id |
in-schema FK → decision_backlog_entry | NO | parent entry (LIVE) |
entry_version_before |
text semver | YES | null for create event |
entry_version_after |
text semver | NO | resulting version after change |
change_kind |
enum-ref | NO | create / status_change / field_update / closure / re_open / supersede |
change_diff |
JSONB (intent) | YES | field-level delta for field_update; app-layer shape (no PG json-schema) |
changed_by |
text actor | NO | actor performing change |
changed_at |
timestamptz | NO | when |
rationale |
text | YES | human-readable change rationale |
§5 — Field Ownership / Vocabulary Dependency
| Field | Owner | v0.2 note |
|---|---|---|
change_kind enum |
cutter-local | DBH-2 — Đ24 confirm or accept cutter-local |
change_diff JSONB |
cutter-local intent | app-layer only in v0.2 |
§6 — Lifecycle
Append-only. History rows are never updated or deleted (immutable trail per Đ38).
A create event has entry_version_before = null. Granularity is governed by DBH-1
(lean: status/version changes + critical-field updates — owner_role, risk_class,
next_review_date; fine-grained per-field logging deferred).
§7 — Relationship to Live v0.1 / Phase α / P0-2 Objects
v0.1 decision_backlog_entry (LIVE, empty):
- parent; decision_backlog_history.decision_id → decision_backlog_entry (in-schema FK)
- NO column / trigger added to decision_backlog_entry by this design
- history is written by the application/P1 write path, not by a PG trigger in P0-5
Phase α objects: NONE (no relationship)
P0-2 objects: NONE (no relationship)
public.* : NO FK, no reference
no_existing_live_table_modified: TRUE
§8 — FK Policy (this table)
in_schema_FK:
- decision_id -> decision_backlog_entry (tight parent-child, same family, same schema)
soft_uuid: none
no_cross_schema_FK: TRUE
rationale: parent-child within the SAME registry family + both in cutter_governance →
in-schema FK is the correct integrity guarantee (mirrors P0-2 block→envelope pattern).
§9 — Empty-at-Create & Rollback Posture
empty_at_create: TRUE — 0 rows; NO backfill of historical entry changes (P1/operational)
rollback: DROP TABLE decision_backlog_history (empty) → cutter_governance to its pre-state
data_loss_on_rollback: NONE at create-time
deferred_concern: AFTER P1 backfill, history-preservation-across-rollback becomes
HIGH-severity (v0.1 §10) — flagged for Đ32 attention; NOT a create-time risk
§10 — Đ32 Risk Class (estimate)
STANDARD (estimate). Additive empty table; single in-schema FK; no live-table touch;
append-only; no data mutation. Full surface table: File 6.
§11 — Open Decisions (registration only; Agent does NOT self-close)
- DBH-1 history granularity: status/version + critical fields (lean) vs every-field. Owner GPT.
- DBH-2
change_kindenum ownership: cutter-local v0.2 (lean) vs Đ24. Owner Đ24 + GPT. - BATCH-1 enum implementation strategy (shared). Owner Đ24 + GPT.
All block DDL freeze; NONE block this design review.
§12 — Dependencies
upstream (SATISFIED — LIVE): decision_backlog_entry (v0.1 LIVE, empty); Đ38 versioning
downstream: decision_backlog_sweep_log reads history for re-surface metrics;
KB mirror regenerator (P1) reads history
no_new_parent_table_required: TRUE
§13 — Explicit Confirmation
no_ddl_written: true
no_sql_written: true
no_create_or_alter_table: true
no_column_or_index_or_constraint_ddl: true
no_trigger_or_function_or_rls_policy: true
no_migration_executed: true
no_pg_mutation: true
no_data_writes: true
no_backfill: true
no_existing_file_or_table_modified: true
open_decision_self_closed: false
output_form: logical_design_only
End of P0-5 decision_backlog_history design.