01 — Design Foundation and Điều 45 Compliance
01 — Design Foundation and Điều 45 Compliance
Date: 2026-05-26 | Mode: DESIGN-ONLY. | Anchor: Điều 45 v1.0 BAN HÀNH 2026-05-26.
This document anchors every decision in the pack to a specific clause of Điều 45 v1.0. It exists so that any reviewer can verify, line-by-line, that the design does not slip past an invariant.
§1. The 12 invariants we must honour
Restated from Điều 45 v1.0 in the prompt order:
| # | Invariant | Law § | Practical meaning for this design |
|---|---|---|---|
| 1 | queue_carries_signal_not_data |
§4 | Outbox + job tables hold *_ref columns only. No body, no blob, no vector, no secret. Forbid via CHECK that mirrors event_outbox.safe_payload. |
| 2 | event_vs_job_distinction |
§6.6 | Two tables (event_outbox for facts; job_queue for work). Not one merged table. Not one masquerading as the other. |
| 3 | work_state_machine_required |
§6.7 | Every job row carries status whose values are a subset of the 9-state minimum. Status transitions only through gated functions. |
| 4 | executor_boundary_required |
§11.5 | Only registered executors claim jobs. Executor whitelist: {DOT, Agent, Hermes, Codex, PG_worker, external_worker, future_Kestra_adapter}. MOT is NOT in the set. |
| 5 | MOT_is_not_executor |
§13.4 | MOT emits a job graph; queue executors run the steps. No fn_mot_step_execute is ever introduced. |
| 6 | PG_is_source_of_truth |
§5.1 | No external queue (Redis, NATS, Kafka) carries job state. NOTIFY does not replace tables. |
| 7 | LISTEN_NOTIFY_is_wakeup_signal_not_durable_storage |
§5.1, §5.3 | DP4's queue_wake_<domain> channel exists only to wake an external worker that then selects from PG. Missing a NOTIFY must not lose work. |
| 8 | no_vector_for_transient_payload |
§14 | The 4-layer guarantee applies to any new substrate. New table CHECKs forbid vector/embedding keys; no FK from new tables to iu_vector_sync_point. |
| 9 | silent_gap_heartbeat_required |
§15.5 | Every executor writes a heartbeat at a documented cadence. Missing heartbeat past stale_threshold emits a system/queue_worker_silent event and is a violation. |
| 10 | retry_dead_letter_required |
§8 | error_count, last_error, max_attempts (config), backoff strategy (config), dead-letter row, resolution vocab. |
| 11 | idempotency_required |
§7 | Every job row has an idempotency_key; partial unique index; ON CONFLICT DO NOTHING for re-enqueue. |
| 12 | status_visibility_required |
§15.1 | One unified v_queue_health view aggregates all cursors, DLQ counts, lease holders, heartbeat ages. |
§2. DP → invariant matrix
Each DP carries at least one invariant. The matrix below shows which DP enforces an invariant vs which DP observes it (a DP that depends on an invariant being honoured elsewhere).
| Invariant | DP1 sched | DP2 jobs | DP3 retry | DP4 NOTIFY | DP5 trig | DP6 sub | DP7 ret | doc 10 cut | doc 11 MOT | doc 12 mail | doc 13 outbox |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 signal-not-data | obs | enf | obs | obs | enf | obs | obs | obs | obs | enf | enf |
| 2 event-vs-job | obs | enf | obs | obs | obs | enf | obs | obs | obs | obs | enf |
| 3 work state machine | obs | enf | enf | obs | obs | obs | obs | enf | enf | enf | obs |
| 4 executor boundary | obs | obs | obs | obs | enf | enf | obs | obs | enf | obs | obs |
| 5 MOT-not-executor | obs | obs | obs | obs | obs | enf | obs | obs | enf | obs | obs |
| 6 PG SoT | enf | enf | enf | enf | enf | enf | enf | enf | enf | enf | enf |
| 7 NOTIFY = signal | enf | obs | obs | enf | obs | obs | obs | obs | obs | obs | obs |
| 8 no-vector transient | obs | enf | obs | obs | obs | obs | obs | obs | obs | enf | enf |
| 9 silent-gap heartbeat | enf | obs | obs | enf | obs | obs | obs | obs | obs | obs | obs |
| 10 retry+DLQ | obs | obs | enf | obs | obs | obs | enf | obs | obs | obs | obs |
| 11 idempotency | obs | enf | enf | obs | enf | obs | obs | obs | obs | obs | obs |
| 12 status visibility | obs | obs | obs | enf | obs | obs | obs | obs | obs | obs | obs |
Reading: invariant 6 (PG SoT) is enforced by every DP. Invariants 4 and 5 (executor boundary, MOT clause) are enforced by DP5/DP6 + the MOT cross-cutting doc.
§3. Cross-law compliance
Điều 45 §16 requires no amendment to D30/D31/D35/D36/D37/D44. This pack respects:
| Law | Touchpoint in this pack | Compliance |
|---|---|---|
| HP / Điều 0 / 0-B / 0-G / 0-H | Object identity, birth gate, assembly first — design uses canonical_address / unit_id refs only. |
✅ No identity rewrite. |
| Điều 22 | system/issue_opened continues to be the dominant event (131k+ rows). Design does NOT change emission. |
✅ Untouched. |
| Điều 30 | New job_queue lifecycle is regression-coverable; design includes a regression-rubric note in DP2 for future tests. | ✅ Compatible. |
| Điều 31 | Refusal contract (DP3 §refusal). System integrity watchdog continues to consume queue health via v_queue_health. |
✅ Extends, no amendment. |
| Điều 35 | DOT remains primary executor surface for governed mutations. dot_iu_command_run retains its ledger role; new job_queue references runs via run_id FK. |
✅ DOT is producer + executor per §11.3, never owner of the queue substrate. |
| Điều 36 | NVSZ ratified (§14); design adds no path from job substrate → vector tier. Collection birth still drives staging.* events. |
✅ 4-layer guarantee preserved. |
| Điều 37 | Recipient routing uses agency/role vocab (user:, agency:, role:, agent:) without modification. |
✅ Reused unchanged. |
| Điều 39 | KG events would register under event_domain='kg'; this pack opens the door but does not register types. |
✅ Vocab-only seam. |
| Điều 43 | system/queue_worker_silent red-zone signal feeds D43 health watchdog. |
✅ New surface, additive. |
| Điều 44 | IU-0 implementation discipline preserved. fn_iu_* names kept per §20.2 transitional clause. |
✅ No rename. |
§4. What this pack is and is not
This pack IS:
- A design pack consisting of 18 KB documents.
- A coherent plan covering DP1–DP7 + 5 cross-cutting surfaces.
- A set of NON-EXECUTABLE schema sketches that could become migrations after Council approval.
- A risk register and roadmap.
This pack is NOT:
- A migration. No SQL is executed.
- An amendment to Điều 45. The law text is not edited.
- A change to any live
dot_configkey. - A new event_type ratification. Vocab stays as-is.
- An installation of pg_cron.
- A start/stop of any worker.
- A touch of MARK/CUT operator aliases.
- A change to
iu_vector_sync_pointor Qdrant. - A change to START-HERE (a design note may be added in a separate report pack later, not here).
§5. Vocabulary discipline
This pack respects §6.1 vocab without addition:
event_domain ∈ {iu, piece, staging, birth_registry, governance, tac, kg, system, dot, health} — 9 values
event_stream ∈ {comment, review, update, birth, task, alert, health} — 7 values
delivery_lane ∈ {immediate, delayed} — 2 values
event_severity ∈ {info, warning, critical} ∪ {NULL} — 3+NULL
New vocab proposed in this pack (Council ratification required before implementation):
job_kindvocab — names likemark_file,verify_mark,cut_from_manifest,staging_cleanup_sweep,vector_sync_drain,mot_step,email_send,customer_message_classify. These are job-kind labels (not event_type entries); they live inconsumer_registry.job_kind(DP5).job_statusvocab — the §6.7 9-state minimum (queued, leased, in_progress, succeeded, failed, retry_waiting, dead_letter, cancelled, cleaned). This is already ratified by §6.7; this pack uses it verbatim.executorvocab — the §11.5 7-element whitelist. Verbatim from law.
No new event_domain, no new event_stream, no new lane.
§6. Naming convention
To avoid retroactive renames (Điều 45 §20.2 forbids opportunistic renames), this pack proposes:
- Existing tables/functions/views with
fn_iu_*/iu_*prefix: keep as-is. - New tables introduced by this pack's design: prefix
job_(notiu_job_, notqueue_). - New view aggregating queue+job health:
v_queue_health(no prefix because it spans both layers). - New
dot_configkeys: namespacequeue.*for queue-substrate-level settings;job.<kind>.*for per-job-kind overrides.
Council may push back on any of these in DP review.
§7. What "design-only" means concretely
Throughout this pack, when a section presents a table sketch, the format is:
NON-EXECUTABLE DESIGN SKETCH — DO NOT APPLY
table job_queue (
job_id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
job_kind text NOT NULL,
...
);
This is prose-shaped-like-DDL so reviewers can read the intent. It is not valid for psql execution as-presented. Migration authors in a later pack would convert each sketch into a real migration with CHECK details, FK target rows, INDEX names, default values, GRANT statements, and the gates required by §18.
§8. Compliance checklist (per-DP self-test)
Each DP doc ends with this checklist (filled in):
self_test:
cites_dieu45_section: yes
defines_status_lifecycle_compatible_with_§6_7: yes
defines_idempotency_key: yes
defines_retry_dlq: yes
defines_lease: yes
defines_observability_view: yes
defines_dot_config_disable_flag: yes
defines_executor_set_compatible_with_§11_5: yes
no_vector_in_transient: yes
signal_not_data: yes
pg_sot: yes
rollback_concept: yes
no_pg_cron_dependency_phase_1: yes
no_pg_18_dependency: yes
no_mutation_authored: yes
If any answer would be no, the DP doc explains the dispensation and routes the question to doc 15 (risk register).
Foundation doc. No mutation. Authored 2026-05-26 by Claude Opus 4.7 (1M) under Open Goal Prompt Guide v1.2.