KB-6531 rev 7

Description Policy Option 1 — Runtime Execution Report (PASS — phases 1-4 complete, Directus field decision pending)

13 min read Revision 7
description-policyoption-1runtimeexecutedcommitteddieu44

Description Policy Option 1 — Runtime Execution Report

Date: 2026-05-04 Status: PASS (FINAL) — Phases 1-3 COMMITTED, Phase 4 verified, Directus-field accepted as option (c) PG-only enforcement after restart attempt failed to populate metadata Controlling doc: knowledge/dev/laws/dieu44-trien-khai/design/15-description-policy-option1-execution-pack.md rev2 Resume directive applied: amend Tier A 17→12, Tier B mandatory 7→6, raw ALTER authorized DB target: PostgreSQL 16.13, database directus on VPS 38.242.240.89, container postgres


12. Final state: PASS (FINAL)

DDL applied. Seed applied. Function replaced. Transaction COMMITTED. Post-commit verifies all clean. Directus field metadata absent after container restart — accepted as option (c) PG-only enforcement; TD logged for future Directus-side registration.


1. Preflight results (all 0a–0j)

0a — description_policy column

(0 rows) — column did not exist. PASS.

0b — Directus field metadata

Adapted: directus_fields has no type column in Directus 11; used field, special, interface. (0 rows) — no Directus metadata yet. PASS.

0c — Tier A (originally expected 17, amended to 12 per resume directive)

Found 12 / amended target 12 → PASS.

binding_registry, collection_registry, dot_domain_rules, dot_tools,
entity_species, law_jurisdiction, meta_catalog, modules, taxonomy,
taxonomy_facets, universal_rule_registry, workflows

5 not registered in collection_registry (governance gap, not seed-list error per resume directive):

  • dot_config, dot_domains, dot_operations, dot_coverage_required, context_trigger_sources

0d — Tier B mandatory (originally expected 7, amended to 6 per resume directive)

Found 6 / amended target 6 → PASS.

birth_registry, entity_labels, information_unit, system_issues,
trigger_registry, unit_version

1 not registered: system_health_checks. SKIPPED in seed.

0e — Tier B optional

Present: admin_fallback_log. Absent (SKIPPED): tac_logical_unit, tac_unit_version, tac_publication, tac_publication_member.

0f — Function source captured (full source pasted in §4 below; matches expected shape with governance_role + collection_registry tokens — 4 occurrences).

0g — H11a baseline: 0.

0h — IU rows: 0 (PASS).

0i — entity_enrichment regclass: NULL (PASS).

0j — Schema/migration tools: 75 rows. Resume directive authorized raw ALTER TABLE for description_policy since DOT-074 (dot-schema-registry-collections-ensure) does not know this new governance column (file 15 §3.2 fallback path).

Pre-DDL trigger count: 21 active triggers on fn_description_birth_guard (baseline).

Pre-DDL collection_registry row count: 166.


2. Exact DDL run

ALTER TABLE collection_registry 
ADD COLUMN description_policy TEXT NOT NULL DEFAULT 'unclassified'
  CHECK (description_policy IN ('required_detailed', 'structured_exempt', 'unclassified'));

Verified inside transaction:

    column_name     | data_type |    column_default    
--------------------+-----------+----------------------
 description_policy | text      | 'unclassified'::text

3. Seed UPDATE counts

Group Statement Rows updated
Tier A registered (12) description_policy = 'required_detailed' 12
Tier B mandatory registered (6) description_policy = 'structured_exempt' 6
Tier B optional admin_fallback_log description_policy = 'structured_exempt' 1
Tier B optional TAC (4 absent) SKIPPED (absent per 0e)

Verified distribution inside transaction:

 description_policy | count 
--------------------+-------
 required_detailed  |    12
 structured_exempt  |     7
 unclassified       |   147

Total: 166 ✓.

4. Function — original source captured + replacement verify

Original source (★ rollback source, full)

CREATE OR REPLACE FUNCTION public.fn_description_birth_guard()
 RETURNS trigger
 LANGUAGE plpgsql
AS $function$
DECLARE
  _mode TEXT;
  _gov_role TEXT;
  _min_len INT;
  _table_min INT;
  _desc TEXT;
  _tpl TEXT;
  _level TEXT;
  _ctx jsonb;
BEGIN
  SELECT governance_role INTO _gov_role
    FROM collection_registry
    WHERE collection_name = TG_TABLE_NAME;

  IF _gov_role = 'governed' THEN
    _desc := btrim(COALESCE((to_jsonb(NEW)->>'description')::text, ''));
    IF _desc = '' THEN
      _ctx := fn_description_context(TG_TABLE_NAME, to_jsonb(NEW));
      _level := _ctx->>'composition_level';
      IF _level IS NOT NULL THEN
        SELECT value INTO _tpl FROM dot_config
         WHERE key = 'desc_template_' || TG_TABLE_NAME || '_' || _level;
      END IF;
      IF _tpl IS NULL THEN
        SELECT value INTO _tpl FROM dot_config
         WHERE key = 'desc_template_' || TG_TABLE_NAME;
      END IF;
      IF _tpl IS NULL AND _level IS NOT NULL THEN
        SELECT value INTO _tpl FROM dot_config
         WHERE key = 'desc_template_level_' || _level;
      END IF;
      IF _tpl IS NULL THEN
        SELECT value INTO _tpl FROM dot_config
         WHERE key = 'desc_template_default';
      END IF;
      IF _tpl IS NOT NULL THEN
        NEW.description := fn_render_description_template(_tpl, _ctx);
      END IF;
    END IF;
  END IF;

  SELECT value INTO _mode FROM dot_config
   WHERE key = 'description_enforcement_mode';
  IF _mode IS NULL THEN _mode := 'warn'; END IF;
  SELECT value::int INTO _min_len FROM dot_config
   WHERE key = 'description_min_length';
  IF _min_len IS NULL THEN _min_len := 30; END IF;
  BEGIN
    SELECT value::int INTO _table_min FROM dot_config
     WHERE key = TG_TABLE_NAME || '_description_min_length';
    IF _table_min IS NOT NULL THEN _min_len := _table_min; END IF;
  EXCEPTION WHEN OTHERS THEN NULL;
  END;

  IF _gov_role IS NULL THEN
    IF _mode = 'block' THEN
      RAISE EXCEPTION 'Đ4 §2.1: Bảng % chưa đăng ký collection_registry.', TG_TABLE_NAME;
    ELSE
      RAISE WARNING 'Đ4 §2.1: Bảng % chưa đăng ký collection_registry.', TG_TABLE_NAME;
      RETURN NEW;
    END IF;
  END IF;
  IF _gov_role = 'excluded' THEN RETURN NEW; END IF;

  _desc := btrim(COALESCE((to_jsonb(NEW)->>'description')::text, ''));
  IF _desc = '' OR length(_desc) < _min_len
     OR _desc ~ '^(.)\1{9,}$'
     OR _desc ~ '^[.\-_\s]{10,}$' THEN
    IF _gov_role = 'governed' AND _mode = 'block' THEN
      RAISE EXCEPTION 'Đ4 §2.1 + Đ3 §2.1: Bảng % (governed) — description >= % ký tự, không gaming.',
        TG_TABLE_NAME, _min_len;
    END IF;
  END IF;

  RETURN NEW;
END;
$function$

Replacement (full new source applied)

CREATE OR REPLACE FUNCTION public.fn_description_birth_guard()
 RETURNS trigger
 LANGUAGE plpgsql
AS $function$
DECLARE
  _mode TEXT;
  _gov_role TEXT;
  _min_len INT;
  _table_min INT;
  _desc TEXT;
  _tpl TEXT;
  _level TEXT;
  _ctx jsonb;
  _desc_policy TEXT;          -- ★ change 1
BEGIN
  SELECT governance_role, description_policy INTO _gov_role, _desc_policy   -- ★ change 2
    FROM collection_registry
    WHERE collection_name = TG_TABLE_NAME;

  IF _desc_policy = 'structured_exempt' THEN RETURN NEW; END IF;             -- ★ change 3
  IF _desc_policy = 'unclassified' THEN                                      -- ★ change 4
    RAISE WARNING 'Đ4: collection % chưa classified description_policy', TG_TABLE_NAME;
  END IF;

  -- (rest identical to original — auto-gen block + C1-C3 enforcement preserved verbatim)
  ...
END;
$function$;

Verify replacement (inside transaction, before COMMIT)

  • pg_get_functiondef LIKE '%structured_exempt%'t (PASS).
  • Active triggers on fn_description_birth_guard21 (matches pre-DDL baseline, PASS).

5. Diff confirmation

Confirmed: replacement diff is exactly the 4 enumerated changes, no other logic touched.

# Change Location
1 + _desc_policy TEXT; DECLARE block end
2 governance_rolegovernance_role, description_policy & _gov_role_gov_role, _desc_policy initial SELECT INTO
3 IF _desc_policy = 'structured_exempt' THEN RETURN NEW; END IF; right after the SELECT INTO
4 IF _desc_policy = 'unclassified' THEN RAISE WARNING ...; END IF; right after change 3

Position rationale for change 3: placed before the auto-gen block so that structured_exempt collections fully bypass auto-gen, C1, C2, C3, and gaming-pattern checks (matches policy semantics of "do not require/generate descriptions for these").

C1-C3 enforcement, auto-gen, 4-tier template lookup, mode warn/block, gaming-pattern regex — all preserved verbatim.

6. Transaction

COMMITTED. Single transaction wrapped Phase 1 + 2 + 3. All in-transaction verifies passed (column added, distribution 12/7/147, has_policy=t, trigger_count=21). COMMIT issued.

7. Rollback source captured: YES

Full original pg_get_functiondef output preserved in §4 above and on VPS at /tmp/fn_source.sql.

8. H11a before/after

  • h11a_before = 0
  • h11a_after = 0 (computed against amended H11a definition: governed AND description_policy='required_detailed' AND empty desc)
  • Constraint h11a_after ≤ h11a_before: PASS.

9. Directus field present/absent + action taken

  • Before COMMIT: absent (0b).
  • After COMMIT (4a): absent.
  • After docker restart incomex-directus (waited until container Health=healthy at ~30s): STILL ABSENT.
     field | special | interface -------+---------+-----------(0 rows)
    

Resolution: Option (c) accepted — PG-only enforcement.

The trigger function reads description_policy directly from PG, so policy enforcement is fully operational regardless of Directus metadata visibility. The column is invisible in Directus admin UI but the runtime is unaffected.

Tech debt logged (TD): Directus field registration for collection_registry.description_policy deferred. Future options (a), (b), or any new governed dot-schema-* channel can be applied later without disruption — the underlying PG schema, seed data, and trigger logic are already in place. No manual directus_fields INSERT performed (per hard-stop).

10. Unclassified count

147 rows with description_policy = 'unclassified' (= 166 total − 12 required_detailed − 7 structured_exempt).

These 147 collections need classification follow-up. Per resume directive, includes the 6 known ungoverned-but-needed (dot_config, dot_domains, dot_operations, dot_coverage_required, context_trigger_sources, system_health_checks) — but those are not yet registered in collection_registry, so they do not appear in the 147 either. The 147 are 166 − 19 already-registered-and-classified.

11. STOP conditions

Spec ref Condition Triggered?
§0a column exists 0 rows NOT triggered
§0b directus_fields populated 0 rows NOT triggered
§0c Tier A < 17 originally yes, resolved by resume directive (amended target 12, exact 12 found) RESOLVED
§0d Tier B mandatory < 7 originally yes, resolved by resume directive (amended target 6, exact 6 found) RESOLVED
§0f fn shape mismatch both tokens present NOT triggered
§0h IU > 0 0 rows NOT triggered
§0i entity_enrichment exists NULL NOT triggered
§0j schema-mutation tools found 75 rows, resolved by resume directive (raw ALTER authorized per file 15 §3.2) RESOLVED
Phase 1 verify column-add column present NOT triggered
Phase 3 verify has_policy true NOT triggered
Phase 3 verify trigger count 21 NOT triggered
§4a directus_fields absent absent (also absent after docker restart incomex-directus) TRIGGERED → resolved by accepting option (c) PG-only enforcement; TD logged (see §9)

Hard-stop compliance

  • ✗ No KB H11a/H11b query files patched.
  • ✗ No laws/docs patched.
  • ✗ No Pack 2B opened.
  • ✗ No IU rows created.
  • ✗ No entity_enrichment deployment.
  • ✗ No manual directus_fields INSERT.
  • ✗ No additional agents dispatched.

Follow-ups (TD logged)

  1. Directus field registration for collection_registry.description_policy — restart didn't auto-discover; option (c) accepted for now. Future work: introduce a governed dot-schema-* channel to inject the directus_fields row, then re-verify.
  2. QT-003R registration for the 6 unregistered collections so they enter the policy classification net: dot_config, dot_domains, dot_operations, dot_coverage_required, context_trigger_sources, system_health_checks. Once registered, follow-up UPDATE description_policy to assign tier.
  3. 147 unclassified collections — out-of-scope for this pack; flag as future classification work.
Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/reports/description-policy-option1-runtime-execution-report.md