23-P3D4C2U — DOT Table Registration Implementation Prompt (rev4)
23-P3D4C2U — DOT Table Registration Implementation Prompt (rev4)
Date: 2026-05-08 Status: PROMPT rev4 — chờ GPT/User final review. CHƯA dispatch. Report: knowledge/dev/laws/dieu44-trien-khai/reports/23-p3d4c2u-dot-table-registration-implementation-report.md Scope: PG view + Directus DOT exposure + table_registry row. NO Nuxt code. Rev3→Rev4: View 2 variants, Directus permission/registry/field idempotent, publish report clear, recommendation granular.
Hard Boundaries
- ❌ KHÔNG code Nuxt / UI notification riêng
- ❌ KHÔNG Directus click-config (DOT/API only)
- ❌ KHÔNG Directus write/mark-read
- ❌ KHÔNG expose unsafe fields
- ❌ KHÔNG touch iu_notification_*
- ❌ KHÔNG worker/cron / Đ43 change
- ❌ KHÔNG publish nếu route smoke chưa verified
- ❌ KHÔNG tự tạo PG/Directus role mới
- ✅ PG DDL, Directus API, table_registry — all idempotent
- ✅ Report even on FAIL/BLOCKED
Step 0: Inventory + Smoke Gate
0A-0B. table_registry schema + system_issues row
Same as rev3. Agent uses ACTUAL schema.
0C. PG role convention
SELECT grantee, privilege_type FROM information_schema.role_table_grants
WHERE table_name = 'system_issues' AND privilege_type = 'SELECT';
Report: pg_read_role=<name>.
0D. Directus role convention
GET /permissions?filter[collection][_eq]=system_issues&filter[action][_eq]=read
Report: directus_read_role_id=<uuid>.
0E. Write channel — same as rev3.
0F. SMOKE system_issues (CRITICAL GATE)
GET /items/system_issues?limit=3
No hardcoded fields. Gate logic same as rev3.
0G. Event schema + payload_classification check
SELECT column_name FROM information_schema.columns WHERE table_name = 'event_outbox' AND column_name = 'payload_classification';
Report: payload_classification_exists=YES|NO.
0H. IU snapshot — same as rev3.
0I. Existing view — same as rev3 (absent/compatible/conflict).
0J. Directus view PK convention — same as rev3.
0K. Existing Directus permission check
GET /permissions?filter[collection][_eq]=v_event_outbox_table&filter[action][_eq]=read
- Not found → will create in Step 4
- Found + compatible (same role, read-only) → skip,
permission_status=ALREADY_PRESENT_COMPATIBLE - Found + broader/unsafe → STOP
0L. Existing table_registry row check
SELECT * FROM table_registry WHERE table_id = 'tbl_event_outbox' OR collection = 'v_event_outbox_table';
- Not found → will create in Step 5
- Found + compatible → skip,
registry_status=ALREADY_PRESENT_COMPATIBLE - Found + conflict → STOP
Step 1: CREATE VIEW (2 executable variants)
Agent chooses based on 0G result. No comment-based conditionals.
Variant A (payload_classification EXISTS):
CREATE VIEW v_event_outbox_table AS
SELECT id, occurred_at, event_domain, event_type, event_stream, delivery_lane,
severity, event_subject_table, event_subject_ref, canonical_address,
actor_ref, source_system, payload_classification
FROM event_outbox;
→ 13 columns.
Variant B (payload_classification ABSENT):
CREATE VIEW v_event_outbox_table AS
SELECT id, occurred_at, event_domain, event_type, event_stream, delivery_lane,
severity, event_subject_table, event_subject_ref, canonical_address,
actor_ref, source_system
FROM event_outbox;
→ 12 columns.
COMMENT ON VIEW v_event_outbox_table IS 'Metadata-only read projection. Created by P3D4C2U.';
Only if 0I = absent. Track: view_created_by_pack=P3D4C2U.
Step 2: GRANT — same as rev3 (pg_read_role from 0C). Track.
Step 3: Directus collection + PK — same as rev3. Track if newly registered.
Step 4: Directus field labels + permission (idempotent)
Field labels: For each field in view:
- Verify field exists in Directus schema:
GET /fields/v_event_outbox_table/<field> - If exists → PATCH label only, preserve other settings
- If not exists → skip (Directus should auto-discover view columns)
- Do NOT touch fields outside this collection
Permission (idempotent):
- Check 0K result
- If ALREADY_PRESENT_COMPATIBLE → skip
- If not found → POST /permissions (read-only, directus_read_role_id from 0D)
- Track:
permission_created_by_pack=P3D4C2U
Step 5: table_registry row (idempotent)
- Check 0L result
- If ALREADY_PRESENT_COMPATIBLE → skip
- If not found → INSERT via convention channel (0E)
status = 'draft'ALWAYS- Track:
registry_row_created_by_pack=P3D4C2U
Step 6: Smoke Tests — same as rev3 (S1-S6). Unsafe field list (13 fields):
safe_payload, payload, body, raw_payload, vector, embedding,
secret, token, password, correlation_id, causation_id,
ssn, personal_data
Step 7: Publish Decision
Report:
published=YES|NO
publish_block_reason=NONE|ROUTE_SMOKE_CANNOT_VERIFY|SMOKE_FAIL|CONFLICT|PK_BLOCKED
Step 8: Rollback (scoped) — same as rev3. Only remove *_created_by_pack=P3D4C2U.
Verification
preflight_table_registry_schema=PASS|FAIL
preflight_system_issues_row=PASS|FAIL
preflight_pg_read_role=<name>|NOT_FOUND
preflight_directus_read_role=<uuid>|NOT_FOUND
preflight_write_channel=DIRECTUS_API|RAW_SQL
smoke_system_issues_api=PASS|FAIL
smoke_system_issues_route=PASS|CANNOT_VERIFY|FAIL
smoke_gate=PASS|STOP
payload_classification_exists=YES|NO
view_variant=A_13_COLS|B_12_COLS
view_status=CREATED|ALREADY_PRESENT_COMPATIBLE|CONFLICT
view_created_by_pack=P3D4C2U|PRE_EXISTING|SKIPPED
pg_grant_applied=PASS|FAIL|SKIPPED
directus_collection_visible=PASS|FAIL
directus_pk_recognized=PASS|FAIL|STOP
directus_field_labels=PASS|FAIL
permission_status=CREATED|ALREADY_PRESENT_COMPATIBLE|BROADER_UNSAFE_STOP
permission_created_by_pack=P3D4C2U|PRE_EXISTING|SKIPPED
registry_status=CREATED|ALREADY_PRESENT_COMPATIBLE|CONFLICT_STOP
registry_row_created_by_pack=P3D4C2U|PRE_EXISTING|SKIPPED
registry_initial_status=draft
registry_final_status=draft|published|removed
published=YES|NO
publish_block_reason=NONE|ROUTE_SMOKE_CANNOT_VERIFY|SMOKE_FAIL|CONFLICT|PK_BLOCKED
unsafe_fields_absent=PASS|FAIL
iu_post_snapshot_match=PASS|FAIL
no_nuxt_code=true
no_bespoke_ui=true
no_new_role_created=true
phase_status=PASS|FAIL|BLOCKED
recommendation=READONLY_EXPOSURE_PUBLISHED|READONLY_EXPOSURE_DRAFT_PENDING_ROUTE_SMOKE|NEEDS_GENERIC_TEMPLATE_EXTENSION|DIRECTUS_VIEW_PK_BLOCKED|REVISION_REQUIRED|BLOCKED
next_required_pack=P3D4C3U_USER_VIEW_SMOKE_AND_MARK_READ_DECISION
P3D4C2U rev4 | All idempotent | 2 view variants | Granular recommendation | CHƯA dispatch | Chờ GPT/User final review