KB-43B8
dot-iu-cutter v0.2 — Phase α Risk Review Plan (2026-05-15)
16 min read Revision 1
dieu44-trien-khaidot-iu-cutterv0.2phase-alpharisk-reviewdieu32planning-only2026-05-15
dot-iu-cutter v0.2 — Phase α Risk Review Plan
document_path: knowledge/dev/laws/dieu44-trien-khai/v0.2-design/dot-iu-cutter-v0.2-phase-alpha-risk-review-plan-2026-05-15.md
revision: r1
date: 2026-05-15
author: Agent (Claude Code CLI, Opus 4.7 1M)
phase: v0.2 — Phase α risk review PLAN (planning only)
no_mutation: TRUE
no_DDL_written: TRUE
no_risk_treatment_executed: TRUE
§1 — Đ32 Risk Class
proposed_risk_class: STANDARD
proposed_review_authority: Đ32 council (standard path)
escalation_to_HIGH-risk_path: NOT triggered by Phase α as-designed
rationale:
- all changes are ADDITIVE (no ALTER on existing columns, no constraint changes on existing data)
- data scale is small (86 production rows + 76 sandbox rows; 0 new rows added)
- rollback is trivial (DROP COLUMN / DROP TABLE on empty additions)
- no DOT-pair signing in this phase (cutter_governance.cut_change_set / verify_result remain empty)
- no production CUT / VERIFY operations
- no reader/writer surface requires app deploy (Nuxt uses explicit field selection per BR-3)
- existing SSOT column unchanged
triggers_that_would_escalate_to_HIGH-risk_path_(NOT_applicable_here):
- touching event_outbox (44,726 rows) → not in Phase α scope
- touching information_unit (98 rows + 5 active triggers) → not in scope
- altering existing constraint or column type on tac_logical_unit → not in scope
- introducing NOT NULL on authority in Phase α → deferred to Phase β
- introducing PG-enforced CHECK / FK on authority → deferred to Phase β
- any application code deploy coupled to the migration → not in scope
§2 — Risk Surfaces
2.1 Existing 86 production rows in public.tac_logical_unit
surface_id: RS-1
description: the 86 existing rows receive the new columns and a backfill via Candidate B mapping
data_at_risk: canonical_address (unchanged); doc_code (unchanged); lifecycle_status (unchanged); all other existing columns (unchanged)
new_data_introduced_per_row:
- authority = 'draft' (via backfill; 86 of 86 rows)
- canonical_address_format_version = 'canonical-address-v1' (via DEFAULT at column-add)
risk_class_per_surface: STANDARD
risk_signals_to_watch:
- any row that fails to backfill (CASE returns NULL) → would leave authority=NULL → benign since column is nullable in Phase α; but signals an unexpected lifecycle_status value
- any row that violates the existing UNIQUE on canonical_address as a side effect → not possible since UNIQUE is not modified
2.2 Sister tables (information_unit, unit_edit_draft, event_outbox, iu_notification_event, event_pending, birth_registry)
surface_id: RS-2
description: 6 sister tables share the canonical_address column name but are OUT OF PHASE α SCOPE
total_rows_in_scope_for_v0_1_OPTION_D_NON_TARGET: 98 + 13 + 44,726 + 0 + 0 + 338,285 = 383,122 rows
data_at_risk_in_phase_α: NONE — these tables are not touched
risk_class_per_surface: NONE (in scope: NONE; if scope expanded: HIGH because of event_outbox)
risk_signals_to_watch:
- any inadvertent reference to a sister table in Phase α DDL → MUST be caught at dry-run review time
- any trigger cascade that inadvertently writes to a sister table via fn_birth_registry_auto or similar → would only fire on tac_logical_unit/information_unit INSERT events; Phase α DDL is ADD COLUMN only, no INSERT; safe
2.3 sandbox_tac.logical_unit (76 rows)
surface_id: RS-3
description: 76 sandbox rows receive mirrored additive columns
data_at_risk: nothing (sandbox is a static test fixture; lifecycle of changes is operationally separate)
new_data_introduced_per_sandbox_row:
- authority = NULL (no backfill in Phase α; intentional)
- canonical_address_format_version = 'canonical-address-v1' (via DEFAULT)
risk_class_per_surface: STANDARD (advisory; Option II mirror per BR-7)
risk_signals_to_watch:
- sandbox_tac.fn_sbx_lu_parent_same_doc breaking under the new column shape → smoke test S21 verifies
- confusion if sandbox is treated as production-equivalent → mitigated by naming + isolation
2.4 Nuxt read-only reader
surface_id: RS-4
description: Nuxt SSR + client bundles read canonical_address via explicit field selection
canonical_address_usage_in_Nuxt:
- SSR: s.canonical_address + section_type + depthOf(a) — render path
- client: GraphQL field list includes logical_unit_id.canonical_address
new_columns_visible_to_Nuxt_in_Phase_α: NO
- explicit field selection means new columns are NOT auto-included
- Nuxt deploy NOT required for Phase α to land
risk_class_per_surface: LOW
risk_signals_to_watch:
- if a future Nuxt deploy starts requesting authority or format_version — that is a Phase β / γ design decision and must coordinate with Phase β NOT NULL + CHECK constraints
- Phase α dry-run smoke test should include the existing field-selection query path
2.5 PG functions (21 referencing canonical_address)
surface_id: RS-5
description: 21 PG functions reference canonical_address by name (BR-3 §4)
families:
IU lifecycle (15 functions)
IU notification + comment (2)
TAC + event (3)
sandbox helper (1)
new_columns_visible_to_these_functions: only when their function body references the new columns BY NAME — which none do today
risk_class_per_surface: LOW
risk_signals_to_watch:
- fn_tac_birth_gate_lu — runs BEFORE INSERT OR UPDATE on tac_logical_unit; need read-only inspection of its body during Phase α DDL authoring (design master §7 prereq) to confirm no implicit constraint
- fn_iu_create / fn_iu_save / fn_iu_edit — they write to information_unit (sister table), not tac_logical_unit; safe for Phase α
- any function that performs a SELECT * FROM tac_logical_unit — would auto-include the new columns; need to inspect at Phase α DDL authoring whether any function relies on a specific column count
mitigation:
- read-only inspection of all 4 GUARD-classified functions (fn_tac_birth_gate_lu, fn_iu_birth_gate_layer1, fn_iu_verify_invariants, sandbox_tac.fn_sbx_lu_parent_same_doc) during Phase α DDL authoring
- smoke tests S17–S22 of the dry-run plan verify behavior end-to-end
2.6 PG triggers (11 across 5 tables)
surface_id: RS-6
description: 11 triggers across tac_logical_unit (1) + information_unit (5) + unit_edit_draft (1) + event_outbox (1) + birth_registry (3)
trigger_on_tac_logical_unit: trg_tac_birth_gate_lu (BEFORE INSERT OR UPDATE → fn_tac_birth_gate_lu)
new_columns_visible_to_triggers: only if trigger body references them BY NAME — which they don't
risk_class_per_surface: LOW
mitigation:
- the only trigger on tac_logical_unit fires BEFORE INSERT/UPDATE; Phase α DDL is ADD COLUMN, which is a metadata operation that does NOT fire INSERT/UPDATE triggers
- dry-run smoke test S17 verifies trigger behavior post-Phase-α via a synthetic INSERT
2.7 identity_profile jsonb duplicate canonical_address
surface_id: RS-7
description: 27 of 86 rows duplicate canonical_address inside the identity_profile jsonb (BR-2 finding)
data_at_risk: the duplicated copy could drift from the column value if either is updated independently (currently both are the same value verbatim)
risk_class_per_surface: COSMETIC (not operational)
phase_α_treatment: IGNORE (cleanup is a future cosmetic pass; out of additive-only Phase α scope)
risk_signals_to_watch: NONE for Phase α (the duplicate is purely informational)
2.8 Cross-schema target_unit_id in alias table (no FK in Phase α)
surface_id: RS-8
description: cutter_governance.canonical_address_alias.target_unit_id is a uuid stored without a PG FK to public.tac_logical_unit.id
data_at_risk: orphaned alias rows if target_unit_id points to a deleted row
risk_class_per_surface: STANDARD (Phase α has 0 rows; risk is forward-looking)
mitigation:
- Phase α has 0 alias rows; risk is dormant
- Phase β write hook authors must perform a soft existence check before inserting an alias
- Phase γ can add cross-schema FK if desired
§3 — Risk Matrix Summary
| ID | Surface | Risk Class | Phase α treatment |
|---|---|---|---|
| RS-1 | 86 existing tac_logical_unit rows | STANDARD | additive columns + Candidate B backfill |
| RS-2 | 6 sister tables (383k rows) | NONE (out of scope) | explicit non-scope |
| RS-3 | 76 sandbox rows | STANDARD (advisory) | mirror columns; no backfill |
| RS-4 | Nuxt readers | LOW | no app change; smoke test |
| RS-5 | 21 PG functions | LOW | read-only body inspection of 4 GUARDs; smoke tests |
| RS-6 | 11 triggers | LOW | smoke test on tac trigger |
| RS-7 | identity_profile duplicate jsonb | COSMETIC | ignore in Phase α |
| RS-8 | cross-schema alias target_unit_id | STANDARD (dormant) | accept; Phase β soft check |
overall_phase_α_risk_class: STANDARD
escalation_to_HIGH-risk_council: NOT required
Đ32_standard_path_review: sufficient
Đ0-G_acknowledgement: already secured at BR-4 closure
Đ24_acknowledgement: already secured at BR-5 closure
§4 — Mitigations
4.1 Mitigation index
M-1: single-transaction DDL with ON_ERROR_STOP=1
applies_to: RS-1, RS-3, RS-8
effect: any failure rolls back the entire Phase α DDL atomically
M-2: fresh production-bound backup < 60 minutes before production migration
applies_to: RS-1
effect: full restore option available if production-side rollback fails
M-3: pre-migration schema + row-count snapshots
applies_to: RS-1, RS-2 (negative control), RS-3
effect: post-migration diff proves nothing outside the additive set changed
M-4: dry-run env separated from HB-05 v0.1 env
applies_to: RS-1, RS-2, RS-3
effect: no risk to v0.1 dry-run state; v0.1 env retained per final-readiness condition (d)
M-5: read-only inspection of fn_tac_birth_gate_lu body before DDL authoring
applies_to: RS-5, RS-6
effect: catches any implicit constraint clash at DDL design time
M-6: smoke tests S17–S22 in dry-run
applies_to: RS-4, RS-5, RS-6
effect: empirically confirms no reader/writer breakage
M-7: rollback test scenarios S23–S26 in dry-run
applies_to: RS-1, RS-3
effect: rollback story validated before production
M-8: explicit non-scope clause in Phase α DDL authoring
applies_to: RS-2
effect: any DDL line that touches sister tables is rejected at GPT review
M-9: Phase β separately designed for lifecycle-transition write hook + NOT NULL promotion
applies_to: RS-1 (forward-looking)
effect: defers higher-risk changes until they have their own dry-run cycle
M-10: cosmetic cleanup of identity_profile duplicate deferred
applies_to: RS-7
effect: cleanly scoped out of Phase α; revisit when other cosmetic work is batched
4.2 Mitigation coverage map
RS-1 ← M-1, M-2, M-3, M-6, M-7, M-9
RS-2 ← M-3, M-8
RS-3 ← M-1, M-4, M-7
RS-4 ← M-6
RS-5 ← M-5, M-6
RS-6 ← M-5, M-6
RS-7 ← M-10
RS-8 ← M-9 (Phase β handles)
§5 — Blockers Before Dry-Run
B-DR-1: Phase α DDL not yet authored
status: OPEN (Phase α DDL is a separate future session under explicit prompt)
resolution: author Phase α DDL after GPT review of all 6 design docs
B-DR-2: read-only inspection of fn_tac_birth_gate_lu body
status: OPEN (design master §7 prereq)
resolution: perform read-only inspection during Phase α DDL authoring session
read_only_check_only: TRUE — no modification to the function
B-DR-3: fresh dry-run env not yet provisioned
status: OPEN
resolution: spin pg-dry-run-v0.2-phase-alpha-<date> at Phase α dry-run authoring time
v0_1_HB_05_env_retained: TRUE (must remain UP)
B-DR-4: baseline backup for dry-run
status: OPEN
resolution: take a fresh production-bound backup at dry-run setup time, OR reuse the v0.1 fresh backup if production unchanged
B-DR-5: dry-run plan ratified by GPT
status: PENDING (this design cycle)
B-DR-6: explicit GPT/User prompt to enter the dry-run authoring lane
status: NOT YET issued
resolution: GPT review of these 6 Phase α design docs → explicit prompt
§6 — Blockers Before Production
B-PROD-1: dry-run 100% PASS across 26 scenarios
status: NOT STARTED
B-PROD-2: Phase α HB-equivalent closure document recorded
status: NOT STARTED
B-PROD-3: Phase α final readiness review document
status: NOT STARTED
B-PROD-4: Phase α command-review package
status: NOT STARTED
B-PROD-5: GPT review of (closure + readiness + command-review)
status: NOT STARTED
B-PROD-6: fresh < 60-min production-bound backup at execution time
status: NOT STARTED
B-PROD-7: explicit User production execution prompt referencing the Phase α command-review by path
status: NOT STARTED
B-PROD-8: separate session for production execution
status: NOT STARTED
B-PROD-9: HB-05 v0.1 dry-run env still UP at execution time (retain per v0.1 final-readiness condition (d))
status: ACTIVELY MAINTAINED
B-PROD-10: production canonical_address SSOT unchanged at execution time (verified via schema diff in command-review preflight)
status: ACTIVELY MAINTAINED
B-PROD-11: dot_tools rows 991/992 still active and unchanged
status: ACTIVELY MAINTAINED
all_pre_production_blockers_must_be_closed_before_first_DDL_dispatch: TRUE
each_terminates_at_GPT_review_or_explicit_user_prompt: TRUE
agent_self_advance_at_any_step: PROHIBITED
§7 — Hard Boundaries
no_risk_treatment_executed: TRUE
no_DDL_written: TRUE
no_SQL_executed: TRUE
no_mutation: TRUE
no_change_to_production: TRUE
no_dry_run_started: TRUE
no_phase_α_DDL_authoring_started: TRUE
no_production_migration_allowed: TRUE
output_form: phase_alpha_risk_review_planning_only
agent_self_advance_to_DDL_authoring: PROHIBITED
§8 — Cross-References
phase_α_design_master: knowledge/dev/laws/dieu44-trien-khai/v0.2-design/dot-iu-cutter-v0.2-phase-alpha-design-master-2026-05-15.md
schema_design: knowledge/dev/laws/dieu44-trien-khai/v0.2-design/dot-iu-cutter-v0.2-phase-alpha-canonical-address-schema-design-2026-05-15.md
alias_design: knowledge/dev/laws/dieu44-trien-khai/v0.2-design/dot-iu-cutter-v0.2-phase-alpha-canonical-address-alias-design-2026-05-15.md
dry_run_plan: knowledge/dev/laws/dieu44-trien-khai/v0.2-design/dot-iu-cutter-v0.2-phase-alpha-dry-run-plan-2026-05-15.md
design_report: knowledge/dev/laws/dieu44-trien-khai/v0.2-design/dot-iu-cutter-v0.2-phase-alpha-design-report-2026-05-15.md
v0_1_dieu32_risk_review_pattern: knowledge/dev/laws/dieu44-trien-khai/risk-review/ (referenced for pattern; not all files enumerated)
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_4_closure: knowledge/dev/laws/dieu44-trien-khai/v0.2-planning/dot-iu-cutter-v0.2-br-4-authority-backfill-rule-closure-2026-05-15.md
br_5_closure: knowledge/dev/laws/dieu44-trien-khai/v0.2-planning/dot-iu-cutter-v0.2-br-5-canonical-address-v1-ratification-closure-2026-05-15.md
v0_1_production_handoff: knowledge/dev/laws/dieu44-trien-khai/execution/dot-iu-cutter-v0.1-production-handoff-status-2026-05-15.md
End of Phase α risk review plan.