Branch H — Claude Code Handoff (engineering brief)
Branch H — Claude Code Handoff (engineering brief)
Audience: Claude Code only. Data contracts, backend views/functions, DOT action map, permission model, state/loading/error handling, test cases, acceptance. No visual design guessing — for look/tokens/components see doc 07. You wire a render shell to backend contracts; you invent no business logic and no visual decisions.
1. Architecture rules (Điều 28)
- Nuxt = render shell, zero business logic. No rules/calculations/workflow semantics in the front end.
- No direct PG from the UI. All reads go through Directus views/permissions or named DOTs. The UI never opens a PG connection.
- No hardcoded workflow/task/tier data. Everything comes from registry config + view rows.
- No raw writes to design columns. Every mutation is a DOT call (doc 05) enforcing gate/owner/approval.
- No realtime vector / no Qdrant write (
vector_sync_enabled=false, never_flip). - No PG tables not in the registry; no schema creation from the UI layer.
2. Data contracts (consume, don't redefine)
CanvasNode(22 fields +instance_data) andCanvasContext— doc 03 §1–2.- The UI is shape-driven: it renders whatever
CanvasNode[]the DOT returns and shows the action chips named inpermission_actions. It must not assume fields beyond the contract.
3. Backend views / functions (the read substrate)
| Object | Type | Backs | Notes |
|---|---|---|---|
v_mow_design_workflow |
view | Surface 1/3 header | scale fix required: replace the two correlated subqueries (step_count, bound_step_count) with a pre-aggregated LEFT JOIN (SELECT workflow_id, count(*) step_count, count(*) FILTER (WHERE step_iu_ref IS NOT NULL) bound_step_count FROM workflow_steps GROUP BY workflow_id) before exposing at thousands of rows |
v_mow_design_step |
view | Surface 3 steps | is_iu_bound = (step_iu_ref IS NOT NULL) |
v_mow_governance_cockpit |
view (doc 07 P1) | Surface 4 | over approval_requests/apr_approvals/workflow_change_requests/governance_registry |
fn_mow_design_health |
fn | health rollup | owner_set, version_set, bound_pct, dangling refs |
fn_mow_design_validate |
fn | validation findings | doc-06 checks |
fn_mow_design_render_tree |
fn | DAG | steps+relations+condition refs |
fn_mow_design_audit |
fn | change history | workflow_change_requests + approval_requests |
fn_workflow_rollup_compute |
fn | nav traffic_light | R1–R6 rollup → gray|green|yellow|red |
fn_iu_gate_verify_closed |
fn | cockpit gate light | all_safe / never_flip / governed_closed |
EXTEND columns this UI depends on (additive, pending Điều-32 commit — doc 02 Phase 1): workflows +8 (owner_gov_code, design_iu_ref, active_design_version, freeze_active, freeze_reason, freeze_at, freeze_by, design_health), workflow_steps +7 (step_iu_ref, guide_iu_ref, dot_ref, output_table_ref, event_domain_ref, event_type_ref, step_version), workflow_step_relations +1 (condition_iu_ref). 8 FKs land NOT VALID then VALIDATE off-peak.
Tier-table reality: tbl_linh_vuc/tbl_cong_ty/tbl_phong_ban/tbl_chuyen_mon/tbl_nhiem_vu_type/tbl_task_type are not yet born in live PG. Build T6–T4 against a mock/config source behind the same DOT interface; switch to tbl_* when ratified. T2/T1 run on workflows/workflow_steps/tasks today. First engineering task: a live-PG reuse-first survey confirming which of the 31 logical registries are REUSE/EXTEND/NEW/DEFER (the v1 pack's one blocking item P2).
4. DOT action map (consume doc 05)
- Read DOTs registerable post-EXTEND:
dot_mow_design_list/get/health/validate/render_tree/audit. - New canvas read DOTs to implement (
DOT_SPEC_ONLY):dot_mow_canvas_get_nodes/get_context/drill_down,dot_mot_get_task_card. Each must be added todot_iu_command_catalogwith a target function and a passing Điều-35 paired test before the UI calls it. - Mutating DOTs (deferred, need fn + approval): binds, freeze/unfreeze, propose_change, activate, rollback. The UI calls these only through the capability list; it must gracefully hide/disable any DOT the row's
permission_actionsomits. - Verify every DOT exists in
dot_iu_command_catalogbefore wiring it; treat absence as "render disabled + explain", never a crash.
5. Permission model (backend-enforced, Điều 37)
- Every list = DB view + Directus permission policy + per-tier Điều-37 predicate; super-admin is subject to the same predicate.
- The UI renders action chips only from each row's server-provided
permission_actions(view / propose / admin). No client-side permission logic. - Approve/Reject is NOT an agent-callable DOT — it writes
apr_approvalsand requires ≥2 human cross-signs; the backend automated-agent CHECK rejects any agent decision row (Điều 32). The agent UI shows governance read-only. - Activation/rollback owned by
GOV-COUNCIL; bind/freeze by MOW owner; propose by any author (queued).
6. State / loading / error handling
- Loading: skeleton rows/cards; never blank.
- Error: banner + retry; never a partial silent list; never hide a 🔴 governance item.
- Empty: contract-specified strings per surface (doc 02 §5, doc 04).
- Stale-data: every payload carries
as_of+ per-rowlast_updated_at; re-fetch on action completion; optimistic updates forbidden for governance. - Large-result guard: keyset pagination, hard page cap (~100), "refine filters" guard; never OFFSET at 10k+.
7. Test cases (acceptance-level)
- Contract conformance:
dot_mow_canvas_get_nodes(tier=T3, parent=X)returnsCanvasNode[]with all 22 fields,child_preview ≤ 3, rolluptraffic_lightcomputed in SQL. - Permission slice: a read-only role sees
permission_actions:[view]only; no mutate chip rendered; a forged mutate DOT call is rejected backend-side. - Agent self-approval blocked: an agent-authored
apr_approvalsinsert is rejected (automated-agent CHECK). - Scale:
v_mow_design_workflowreturns page 1 of 10k rows under target latency using the pre-agg join (no correlated-subquery regression). - Stale-data: after
dot_mow_design_propose_change, the card re-fetches andproposal_countincrements; no optimistic stale render persists. - Traffic-light correctness: a workflow with a dangling
dot_refrenders 🔴 at step and rolls up to 🔴 at the workflow card. - Empty/error/loading: each surface renders the contract strings; an injected view error shows banner+retry, not a partial list.
- WF-001 pilot (doc 09): the 10-step pilot renders 🟢 with all
is_iu_bound=trueafter binding; drill-down to IU works. - DOT existence guard: an unregistered DOT renders the action disabled+explained, never a crash.
- Tier-table absence: with
tbl_*absent, T6–T4 render from the mock/config source through the same DOT interface without UI changes.
8. Acceptance criteria
- UI is a pure render shell: removing all backend views/DOTs leaves zero business logic stranded in Nuxt.
- Every surface is server-paginated, server-sorted, server-filtered; no client full scan.
- Every action goes through a named DOT; no raw SQL/Directus item write to design columns.
- Permission chips come 100% from
permission_actions; no hardcoded role logic. - All 10 test cases pass against live (read) PG; mutating paths only after EXTEND commit + DOT registration + approval.
- No Qdrant write, no runtime instance creation, no event emission from the UI.
9. Code handoff verdict
READY (separated, engineering-only). Data contracts, backend views/functions, EXTEND-column dependency, DOT map with registration gaps, backend-enforced permission model, state/loading/error rules, 10 test cases, and acceptance criteria are specified with no visual guessing. The one prerequisite engineering task (live-PG reuse-first survey + read-model contract validation) is named as the first step.