KB-3A43
01 — Production Schemas for the 3 Candidate Registries (B-2 CLOSED)
8 min read Revision 1
g1candidate-registryfield-registryinput-form-registrytier-registryddlb-22026-05-29
01 — Branch A: Production Schemas (B-2 CLOSED)
Production-grade DDL for field_registry, input_form_registry, tier_registry. Every statement below was executed live in BEGIN..ROLLBACK (doc 05) — the tables created cleanly, all triggers/guards passed, and fn_pre_birth_check returned 5/5 PASS for each. This is no longer a paper stub.
Critical corrections vs the prior (foundation-superbundle) DDL
collection_registry.codehas NO unique constraint (only PK onid). The prior DDL'sfield_registry.collection_code REFERENCES collection_registry(code)is invalid (cannot FK to a non-unique column) and is removed.collection_codeis kept as a soft reference (plain text). To make it a real FK,collection_registrywould first needADD CONSTRAINT … UNIQUE (code)— a separate, larger change with its own approval; deferred, not required for activation.governance_roleis a MODE enum, not a GOV-code. Live distinct values:observed, excluded, governed, locked, law_artifact. The prior DDL'sgovernance_role='GOV-DOT'was wrong. All 3 registries usegovernance_role='governed'. Ownership-by-Mother is expressed ingovernance_registry.capability(doc 03), not here.- Valid FK targets confirmed:
birth_registry(id)(PK),design_templates(code)(UNIQUE),entity_species(code)/(species_code)(UNIQUE).birth_reftypedintegerto matchbirth_registry.id(serial int). - Per-registry birth trigger added (
fn_birth_registry_auto('code')) so that future rows in each registry are counted under Điều 0-G — a production requirement the stub omitted.
DDL (production, proven executable)
-- 1) field_registry (Đ36 collection-of-fields; owner GOV-MOIT)
CREATE TABLE public.field_registry (
id serial PRIMARY KEY,
code varchar UNIQUE NOT NULL, -- PREFIX-NNN e.g. FIELD-001
name varchar NOT NULL,
collection_code varchar, -- soft ref → collection_registry.code (no FK: not unique)
field_kind varchar NOT NULL, -- text|number|relation|json|boolean|datetime
data_type varchar NOT NULL,
is_required boolean NOT NULL DEFAULT false,
interface varchar, -- Directus interface hint
validation jsonb NOT NULL DEFAULT '{}'::jsonb,
owner_mother varchar, -- GOV-MOIT|GOV-MOT|GOV-MOW|GOV-MOUT
status varchar NOT NULL DEFAULT 'draft',
species_code varchar,
birth_ref integer REFERENCES birth_registry(id),
_dot_origin text NOT NULL DEFAULT 'DIRECTUS',
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz,
CONSTRAINT chk_field_registry_status CHECK (status IN ('draft','active','retired')),
UNIQUE (collection_code, name)
);
-- 2) input_form_registry (Đ28 template + Đ36; owner GOV-MOIT)
CREATE TABLE public.input_form_registry (
id serial PRIMARY KEY,
code varchar UNIQUE NOT NULL, -- FORM-001
name varchar NOT NULL,
form_kind varchar NOT NULL,
target_collection varchar,
design_template_code varchar REFERENCES design_templates(code), -- Đ28 binding (valid FK)
field_set jsonb NOT NULL DEFAULT '[]'::jsonb, -- ordered field_registry codes
form_schema jsonb NOT NULL DEFAULT '{}'::jsonb,
owner_mother varchar,
status varchar NOT NULL DEFAULT 'draft',
species_code varchar,
birth_ref integer REFERENCES birth_registry(id),
_dot_origin text NOT NULL DEFAULT 'DIRECTUS',
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz,
CONSTRAINT chk_input_form_registry_status CHECK (status IN ('draft','active','retired'))
);
-- 3) tier_registry (Đ37 governance tiers; owner = Đ37 authority, see doc 03)
CREATE TABLE public.tier_registry (
id serial PRIMARY KEY,
code varchar UNIQUE NOT NULL, -- TIER-001
name varchar NOT NULL,
tier_level int NOT NULL,
scope varchar NOT NULL, -- unit|collection|system
authority_role varchar, -- → governance_registry.code
policy jsonb NOT NULL DEFAULT '{}'::jsonb,
owner_governance varchar, -- GOV-COUNCIL (recommended)
status varchar NOT NULL DEFAULT 'draft',
species_code varchar,
birth_ref integer REFERENCES birth_registry(id),
_dot_origin text NOT NULL DEFAULT 'DIRECTUS',
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz,
CONSTRAINT chk_tier_registry_status CHECK (status IN ('draft','active','retired')),
UNIQUE (tier_level, scope)
);
-- per-registry birth trigger (one per table, after each CREATE TABLE)
CREATE TRIGGER trg_birth_field_registry AFTER INSERT ON public.field_registry FOR EACH ROW EXECUTE FUNCTION fn_birth_registry_auto('code');
CREATE TRIGGER trg_birth_input_form_registry AFTER INSERT ON public.input_form_registry FOR EACH ROW EXECUTE FUNCTION fn_birth_registry_auto('code');
CREATE TRIGGER trg_birth_tier_registry AFTER INSERT ON public.tier_registry FOR EACH ROW EXECUTE FUNCTION fn_birth_registry_auto('code');
Per-registry property table
| Property | field_registry | input_form_registry | tier_registry |
|---|---|---|---|
| PK | id serial |
id serial |
id serial |
| Business code | code UNIQUE, FIELD-001 |
code UNIQUE, FORM-001 |
code UNIQUE, TIER-001 |
| Code convention | PREFIX-NNN (^[A-Z]+-[0-9]+$) |
same | same |
| Owner law | Điều 36 (+29) | Điều 28 + 36 | Điều 37 |
| Governance owner (Mother/agency) | GOV-MOIT (already in capability.can_create) | GOV-MOIT (already in capability.can_create) | GOV-COUNCIL (Đ37 authority — doc 03) |
| Relation to Mother | input/field surface for MOIT/MOW forms | input UI for MOW/MOIT | consumed by all 4 Mothers |
| Lifecycle/status | status ∈ draft/active/retired (CHECK) |
same | same |
| Audit fields | created_at, updated_at, _dot_origin, birth_ref |
same | same |
| Unique business rule | (collection_code,name) |
code |
(tier_level,scope) |
| FK integrity | birth_registry(id); soft collection_code |
design_templates(code), birth_registry(id) |
birth_registry(id) |
No-double-ownership proof
- Each registry has exactly one species (
*_species), onecollection_registryrow, one primaryspecies_collection_maprow, and one governance owner. No row is owned by two agencies. field_registry+input_form_registryare claimed only byGOV-MOIT.capability.can_create(verified live). No other agency lists them.tier_registryis claimed by no Mother (by design — see doc 03); its owner is the Điều 37 authority. No conflict.- New registries reference existing SoT by FK; they never copy/shadow it (Điều 31). No hidden second SoT.
Rollback implications
- In-transaction:
ROLLBACKreverses everything (proven byte-identical, doc 05). - Committed:
DROP TABLE …drops the table + its birth trigger. The registration rows inmeta_catalog/collection_registry/entity_species/species_collection_map/measurement_registry/v_registry_counts+ the 60birth_registryrows must be cleaned via the soft-retire path (preferred) or the characterized hard-rollback path (doc 04 §rollback map).meta_catalogdeletes are guard-protected.
Difference from the rehearsal stub
The earlier "stub" had wrong FK targets (collection_registry(code)), a GOV-code in governance_role, no CHECK constraints, no audit columns, no per-registry birth trigger, and no birth_ref. This production schema fixes all of those and is the exact shape executed in doc 05.