KB-2807
dot-iu-cutter v0.2 — BR-4 Authority Backfill Rule Design (2026-05-15)
18 min read Revision 1
dieu44-trien-khaidot-iu-cutterv0.2br-4authoritybackfilldesignplanning-onlydieu0-g2026-05-15
dot-iu-cutter v0.2 — BR-4 Authority Backfill Rule Design
document_path: knowledge/dev/laws/dieu44-trien-khai/v0.2-planning/dot-iu-cutter-v0.2-br-4-authority-backfill-rule-design-2026-05-15.md
revision: r1
date: 2026-05-15
author: Agent (Claude Code CLI, Opus 4.7 1M)
sovereign: User / anh Huyên
verifier: GPT (Đ32 HIGH-risk path — anticipated)
secondary: Opus
governance_review_required: Đ0-G (authority semantics) + Đ32 (risk class)
phase: v0.2 planning — BR-4 rule design (planning only)
BR_4_status: pending_gpt_review
mutation_performed: false
ddl_written: false
backfill_executed: false
§1 — Purpose
Choose the authority-backfill rule that will populate public.tac_logical_unit.authority for the 86 existing rows when v0.2 Phase α adds the column. This document proposes the rule and recommends one candidate for Đ0-G review; it does NOT execute any backfill, write any DDL, or modify any row.
Authority semantics (per v0.1 P0-1 §7):
authority enum (Đ24 Step 1 ratified): enacted | draft | runtime
authority_precedence_in_retrieval: enacted > draft > runtime
mapping_to_Đ0-G_birth_gate: enacted = official; draft = controlled provisional; runtime = derived/operational
§2 — Source Evidence (verbatim from this session's read-only discovery)
2.1 public.tac_lu_lifecycle_vocab (3 entries)
code | name | description | sort_order
-------------|---------------------|------------------------------------------------------------------|-----------
active | Hoạt động | Logical unit có ≥1 version enacted | 10
draft_only | Chỉ bản nháp | Chưa từng có version enacted | 20
retired | Đã rút | Quyết định retire qua change-set + APR | 30
2.2 Lifecycle distribution on public.tac_logical_unit
lifecycle_status | count
------------------|------
draft_only | 86 ← 100% of rows
2.3 Lifecycle distribution on sandbox_tac.logical_unit
lifecycle_status | count
------------------|------
draft_only | 76 ← 100% of rows
2.4 doc_code distribution on public.tac_logical_unit
doc_code | count
----------|------
DIEU-28 | 27
DIEU-32 | 23
DIEU-35 | 36
2.5 Implication for backfill choice
Because all 86 rows are currently lifecycle_status='draft_only', every rule below produces the same concrete result on existing data: authority='draft' for all 86 rows.
The rules differ only in:
- semantic clarity (what does the rule say about why a row gets that authority?)
- generalization (what happens when lifecycle_status transitions to
activeorretired? what happens for future rows?) - governance coupling (how tightly does authority track lifecycle?)
§3 — Candidate Rules
3.1 Candidate A — Uniform DEFAULT 'draft' for all existing rows
rule:
on_backfill: UPDATE public.tac_logical_unit SET authority='draft' WHERE authority IS NULL
on_new_writes: column DEFAULT 'draft' (DDL-level) until further governance lands
for_existing_86_rows: all 86 → 'draft'
semantics:
- "authority is unknown at column-introduction time; assume the most-conservative non-enacted value"
- decoupled from lifecycle_status
generalization:
- future rows with lifecycle_status='active' would still default to 'draft' unless caller explicitly sets authority
- retired rows behavior: untouched at this rule level
dieu0_g_alignment:
- explicit "draft" floor — Đ0-G can adjudicate up to 'enacted' once enactment occurs
pros:
- simplest rule; trivially reviewable; trivially reversible
- no dependency on lifecycle_status vocabulary stability
- matches v0.1 P0-1 §4.1 "nullable initially → backfill" pattern exactly
cons:
- decouples authority from the existing lifecycle_status semantic (which has an `active = ≥1 version enacted` definition that maps perfectly to authority='enacted')
- if/when a row's lifecycle_status transitions to `active`, the authority column does NOT auto-update — a separate write-side or trigger update is needed
- introduces a latent inconsistency risk: lifecycle='active' AND authority='draft' for a transitioned row
risks:
- lifecycle/authority drift across enactment transitions (medium-term)
- reviewers in Phase β / γ might find rows where lifecycle says one thing and authority says another → forensic effort
required_governance:
Đ0-G review confirming that uniform 'draft' floor is acceptable
Đ32 risk class: standard
dry_run_requirement:
- HB-equivalent dry-run includes a scenario "ADD COLUMN authority text NULL → UPDATE … SET authority='draft' WHERE … → backfill audit": rowcount 86 updated
- rollback: UPDATE SET authority=NULL OR DROP COLUMN
3.2 Candidate B — Derive from lifecycle_status mapping
rule:
mapping_table:
lifecycle_status='draft_only' → authority='draft'
lifecycle_status='active' → authority='enacted'
lifecycle_status='retired' → authority='enacted' (rationale: retired means it WAS enacted; the retirement is tracked separately via lifecycle, not via authority)
on_backfill:
UPDATE public.tac_logical_unit
SET authority = CASE lifecycle_status
WHEN 'draft_only' THEN 'draft'
WHEN 'active' THEN 'enacted'
WHEN 'retired' THEN 'enacted'
END
WHERE authority IS NULL
on_new_writes: column DEFAULT 'draft' (DDL-level) for new rows; application/trigger updates authority on lifecycle transitions (FUTURE Phase β work)
for_existing_86_rows: all 86 are 'draft_only' → 'draft' (same concrete result as Candidate A, but with a derived rule rather than a fiat value)
semantics:
- "authority is derivable from existing governance state"
- keeps a single conceptual model: lifecycle_status is the operational state; authority is the Đ0-G birth-gate classification, derived from operational state until Đ0-G rules expand
generalization:
- future rows where lifecycle transitions to 'active' SHOULD have authority updated to 'enacted' (trigger or application-layer write — out of v0.2 scope; documented as Phase β FUTURE item)
- the rule is forward-compatible if `tac_lu_lifecycle_vocab` adds more entries (each new vocab row needs an authority mapping)
dieu0_g_alignment:
- explicit mapping from existing operational vocabulary → authority enum
- Đ0-G can review the mapping table; future vocabulary additions go through Đ0-G
pros:
- operationally semantically tight; same row content reads consistently across lifecycle_status and authority
- generalizes when production data accumulates active/retired rows
- keeps Đ0-G in the loop for any vocabulary expansion
- matches the discovery finding (F-DISC-3) verbatim ("lifecycle_status serves a different concern" still true at the column level, but Candidate B explicitly bridges them via a documented mapping rather than ignoring the relationship)
cons:
- slightly more design surface than Candidate A (a 3-entry mapping table to maintain)
- retired → enacted mapping is a JUDGMENT CALL (could also map to a new authority value like 'retired'); requires Đ0-G ratification
- couples authority to lifecycle_status vocab stability — if vocab evolves, mapping evolves
risks:
- mis-classification of retired rows: if 'retired' should actually map to a distinct authority (not 'enacted'), every retired row gets the wrong value. Mitigation: defer 'retired'-row backfill; only backfill draft_only + active in v0.2 Phase α; deal with retired explicitly in Phase β.
- lifecycle vocab expansion not handled: new vocab row added but mapping not yet updated → CASE returns NULL → column constraint (NOT NULL after v0.2 Phase α complete) violated. Mitigation: keep column NULL-able through v0.2 Phase α; add CHECK or NOT NULL only after full mapping ratified.
required_governance:
Đ0-G review of the 3-entry mapping table (the retired→enacted mapping in particular)
Đ24 cross-check that authority enum {enacted, draft, runtime} is still the canonical vocabulary
Đ32 risk class: standard
dry_run_requirement:
- HB-equivalent dry-run scenario S-B1: backfill on draft_only rows → all become 'draft'
- HB-equivalent dry-run scenario S-B2: synthetic active row inserted → backfill produces 'enacted'
- HB-equivalent dry-run scenario S-B3: synthetic retired row inserted → backfill produces 'enacted' (with Đ0-G confirmation that this is intended)
- rollback: UPDATE SET authority=NULL OR DROP COLUMN
3.3 Candidate C — Derive from doc_code / canonical_address prefix regex
rule:
on_backfill:
rule_text:
authority = CASE
WHEN doc_code ~ '^DIEU-[0-9]+$' AND lifecycle_status='active' THEN 'enacted'
WHEN doc_code ~ '^DIEU-[0-9]+$' THEN 'draft'
WHEN doc_code ~ '^RUNTIME-' THEN 'runtime'
ELSE 'draft'
END
or alternative:
authority = derived from canonical_address prefix:
D{doc}-DIEU{N}-… → law artifact (use lifecycle to discriminate draft vs enacted)
runtime-… → 'runtime'
else → 'draft'
for_existing_86_rows:
DIEU-28 (27) + DIEU-32 (23) + DIEU-35 (36) — all law artifacts, all lifecycle 'draft_only'
→ all 86 → 'draft' (same concrete result as A and B)
semantics:
- "authority is determined by what KIND of artifact the row represents"
- introduces a third axis (artifact-kind) beyond lifecycle
pros:
- distinguishes law artifacts from runtime artifacts at the rule level
- useful when runtime IU data (which lives in information_unit, not tac_logical_unit) is later folded into the same authority vocabulary
cons:
- more complex rule; depends on doc_code naming convention being stable
- duplicates information already implicit in the table separation (tac_logical_unit = curated; information_unit + runtime tables = derived) — overengineering for v0.2 scope
- canonical_address-prefix-based regex couples authority to the syntax that BR-5 is about to ratify — circular coupling
risks:
- regex maintenance burden
- doc_code convention drift (if new doc_code patterns emerge)
- over-determines the rule when lifecycle_status alone is sufficient for v0.2 scope
required_governance:
Đ0-G review (authority semantics)
Đ24 review (doc_code naming convention stability)
Đ32 risk class: standard but with elevated review attention due to regex complexity
dry_run_requirement: larger scenario set (mix of doc_code patterns + lifecycle statuses)
3.4 Candidate D — Hybrid fallback rule for future expansion
rule:
on_backfill: Candidate B's mapping for the 3 currently-defined lifecycle values
on_unknown_lifecycle_value (future vocab additions):
- log to decision_backlog_entry (kind='authority_mapping_gap')
- default to 'draft' (most conservative)
- flag for Đ0-G review
on_new_writes: column DEFAULT 'draft'; lifecycle-transition triggers update authority (Phase β FUTURE)
semantics:
- Candidate B with explicit "we know we don't know everything" forward-compat guard
pros:
- graceful degradation under future vocabulary expansion
- explicit backlog signal when mapping needs Đ0-G attention
- safest long-term
cons:
- depends on decision_backlog_entry being live (it IS, post-v0.1 production execution)
- slightly more design surface
- the trigger / app-write side of "log to backlog" is out of v0.2 Phase α scope (Phase α is DDL + backfill only)
required_governance:
- same as Candidate B
- additionally: Đ32 sign-off on the fallback behavior
dry_run_requirement:
- Candidate B's scenarios
- + S-D1 synthetic future-vocab row → CASE returns NULL → fallback fires → 'draft' assigned, backlog entry created
§4 — Recommended Rule
recommended_rule: Candidate B — Derive from lifecycle_status mapping
rationale:
1. For current data (86 rows × draft_only), Candidate B produces the same concrete result as Candidates A, C, and D: authority='draft'. No data risk on Day 1.
2. Candidate B is the only rule that has a SEMANTICALLY TIGHT relationship between an existing governance column (lifecycle_status) and the new authority column. This is what discovery F-DISC-3 was asking for — a documented bridge between the two concerns, not a flat decoupling.
3. Candidate A is too loose; ignores the existing lifecycle vocab.
4. Candidate C is overengineered for v0.2 scope; couples authority to canonical_address syntax (which BR-5 is about to ratify) — circular.
5. Candidate D is Candidate B + a fallback. The fallback is itself good design but out of Phase α scope (it requires a trigger or write-side hook, which is Phase β). Recommend ADOPTING Candidate D's fallback DOCUMENTATION but not implementing the trigger in v0.2 Phase α.
binding_choice:
v0_2_phase_α:
- use Candidate B mapping for backfill of 86 existing rows
- all 86 become authority='draft' (because all 86 are lifecycle_status='draft_only')
- column DEFAULT 'draft' for new writes
- column nullable through Phase α (no NOT NULL constraint yet — added in Phase β after lifecycle-transition write hooks are wired)
v0_2_phase_β_or_v0_3:
- implement lifecycle-transition write hook (trigger or app-layer) per Candidate D
- add NOT NULL constraint after backfill rule generalizes to all observed lifecycle values
- revisit retired→enacted mapping with Đ0-G concrete sign-off
§5 — Đ0-G Review Notes (anticipated questions)
question_1: Is 'draft' the right floor for rows whose lifecycle is 'draft_only'?
answer_proposal: YES — `draft_only` means "never enacted"; 'draft' authority captures the controlled-provisional state exactly per P0-1 §7.
question_2: Should 'retired' map to 'enacted' (was-enacted) or to a new authority value 'retired'?
answer_proposal: 'enacted' for v0.2 — retirement is an operational lifecycle event, not a change in birth-gate authority. If Đ0-G later decides 'retired' is its own authority class, that is a vocabulary expansion handled via Đ24 + this mapping doc revision. NOTE: there are 0 retired rows in production today, so deferring the answer is safe.
question_3: Where does 'runtime' authority come from in v0.2?
answer_proposal: NOT from tac_logical_unit. Runtime artifacts live in `information_unit` and downstream tables; v0.2 Phase α scope EXCLUDES adding authority to information_unit. Runtime authority is a Phase β / v0.3 concern.
question_4: Is the authority column DEFAULT 'draft' (rather than NULL) safe?
answer_proposal: YES for new writes — 'draft' is the most-conservative non-enacted value; any writer that intends 'enacted' must set it explicitly. This matches the principle that promotion to 'enacted' requires explicit governance action.
question_5: What if doc_code conventions diverge (e.g., new artifact kinds beyond DIEU-{N})?
answer_proposal: Candidate B does not depend on doc_code; only on lifecycle_status. New doc_code conventions are orthogonal to authority and will not break Candidate B.
§6 — Effect on sandbox_tac
sandbox_tac.logical_unit (76 rows, all draft_only):
Phase α plan: MIRROR the additive `authority` column (Option II from BR-7) — column added with same default 'draft'
backfill_for_sandbox_in_phase_alpha: DEFER until BR-4 rule is ratified for sandbox data semantically
recommendation: when ratified, apply Candidate B identically to sandbox (rule generalizes cleanly because sandbox has the same lifecycle_status='draft_only' shape)
risk_of_skipping_sandbox_backfill_in_phase_alpha: LOW
- sandbox rows would have authority=NULL temporarily (column nullable through Phase α)
- no production decision depends on sandbox authority value
- sandbox backfill can be a one-line UPDATE done alongside Phase β
§7 — Hard Boundaries
no_DDL_written_in_this_document: TRUE
no_SQL_mutation: TRUE
no_ALTER_TABLE: TRUE
no_INSERT_UPDATE_DELETE_executed: TRUE (rule TEXT in §3 is illustrative; nothing is run)
no_migration: TRUE
no_change_to_tac_logical_unit: TRUE
no_change_to_sandbox_tac: TRUE
no_change_to_cutter_governance: TRUE
no_design_advanced_beyond_BR_4: TRUE
no_deploy: TRUE
no_phase_alpha_design_started: TRUE
BR_4_status: pending_gpt_review (Đ0-G review request to be issued by GPT or User after this doc is reviewed)
output_form: br_4_rule_design_planning_only
§8 — Cross-References
br_2_doc: knowledge/dev/laws/dieu44-trien-khai/v0.2-planning/dot-iu-cutter-v0.2-br-2-identity-profile-jsonb-discovery-2026-05-15.md
br_3_doc: knowledge/dev/laws/dieu44-trien-khai/v0.2-planning/dot-iu-cutter-v0.2-br-3-canonical-address-reader-writer-inventory-2026-05-15.md
br_7_doc: knowledge/dev/laws/dieu44-trien-khai/v0.2-planning/dot-iu-cutter-v0.2-br-7-sandbox-tac-role-clarification-2026-05-15.md
br_2_3_7_consolidated: knowledge/dev/laws/dieu44-trien-khai/v0.2-planning/dot-iu-cutter-v0.2-br-2-3-7-discovery-report-2026-05-15.md
br_5_companion: knowledge/dev/laws/dieu44-trien-khai/v0.2-planning/dot-iu-cutter-v0.2-br-5-dieu24-canonical-address-v1-ratification-request-2026-05-15.md
br_4_5_closure_report: knowledge/dev/laws/dieu44-trien-khai/v0.2-planning/dot-iu-cutter-v0.2-br-4-5-closure-readiness-report-2026-05-15.md
v0_1_p0_1_design (baseline for authority enum): knowledge/dev/laws/dieu44-trien-khai/migration-design/dot-iu-cutter-v0.1-p0-1-canonical-address-migration-design-2026-05-15.md
v0_2_scope_backlog: knowledge/dev/laws/dieu44-trien-khai/planning/dot-iu-cutter-v0.2-scope-backlog-2026-05-15.md
reconciliation_report: knowledge/dev/laws/dieu44-trien-khai/v0.2-planning/dot-iu-cutter-v0.2-canonical-address-reconciliation-report-2026-05-15.md
End of BR-4 authority backfill rule design.