Mission 1: Pivot CHẠY Report
Mission 1: Pivot CHẠY — Report (Điều 26 v3.5)
Date: 2026-03-28 | PR: #640 | Status: MERGED + DEPLOYED
Step 0: Checkpoint Quotes
Operating Rules v5.x
v5.3 | 2026-03-28 — S141 Điều 26 v3.5 BAN HÀNH. Hiến pháp v3.9. Mission 0.5 DONE. Mission 1 tiếp.
Merge Rule
CI GREEN = CHỈ 4 required checks GREEN: Pass Gate, Quality Gate, check-critical-files, Contract Schema Validation.
Verify Nuxt Rule
§0-AF: EVIDENCE bắt buộc từ production URL https://vps.incomexsaigoncorp.vn/api/...
Assembly Gate
| # | Question | Answer |
|---|---|---|
| Q0 | PostgreSQL ready? | YES — pivot_definitions table + pivot_count() function created |
| Q1 | §II Assembly First quoted? | YES — see above |
| Q2 | Directus available? | v_registry_counts table, meta_catalog (source data) |
| Q3 | Nuxt available? | registries/index.vue, [entityType]/index.vue, /api/registry/*.ts |
| Q4 | New code lines? | ~100 SQL + ~20 Nuxt changes |
| Q5 | DOT tools reuse? | None needed for Mission 1 |
Step 1: Dependency Audit
| File | Reading | Decision |
|---|---|---|
| web/pages/knowledge/registries/index.vue:110 | readItems(v_registry_counts) | FIXED → reads meta_catalog directly |
| web/pages/knowledge/registries/[entityType]/index.vue:83 | readItems(v_registry_counts) | FIXED → reads meta_catalog directly |
| web/server/api/registry/counts.get.ts | meta_catalog.record_count SUM | KEEP — reads meta_catalog, not v_registry_counts |
| web/server/api/registry/raw-counts.get.ts | meta_catalog.record_count | KEEP — reads meta_catalog |
| web/server/api/registry/refresh-counts.post.ts | Updates meta_catalog | KEEP — still populates meta_catalog.record_count |
| sql/s167*.sql, s168*.sql, s169b*.sql | v_registry_counts refs | NO IMPACT — already-executed scripts |
| web/tests/e2e/registries.spec.ts | record_count column | KEEP — tests UI column name, unchanged |
Step 2: SQL Executed
pivot_definitions: CREATED
- 21 rows seeded from meta_catalog (§0-AU: NO hardcode)
- 20 active (PIV-020 _uncategorized deactivated — no real table)
pivot_count(): CREATED
- Returns TABLE(code, name, source_object, count_value)
- Reads from pivot_definitions dynamically
- Operator whitelist: =, !=, >, <, >=, <=, in, not_in, is_null, is_not_null, like
- SQL injection protection: %I for identifiers, %L for literals
Step 3: #DISABLE List
- 26 trg_count_* triggers: ALL DISABLED (tgenabled = D)
- birth_trigger_v_registry_counts: DISABLED
- trg_auto_create_counting: DISABLED
- trg_auto_sync_registry_counts: DISABLED
- trg_guard_v_registry_counts: DISABLED
- refresh_registry_counts(): body replaced with RETURN (neutered)
- 0 enabled counting triggers remain
Step 4: Nuxt Endpoint Changes
- web/pages/knowledge/registries/index.vue: removed v_registry_counts read, now reads meta_catalog with fields [code, name, entity_type, composition_level, identity_class, record_count, active_count, orphan_count, baseline_count]
- web/pages/knowledge/registries/[entityType]/index.vue: same change
Step 5: VERIFY NUXT
Summary
| # | Check | Status |
|---|---|---|
| 1 | Step 0 quotes | ✅ |
| 2 | Dependency audit | ✅ |
| 3 | pivot_definitions created + seeded | ✅ 21 rows (20 active) |
| 4 | pivot_count() correct counts | ✅ 20 rows |
| 5 | Triggers #DISABLED | ✅ 26+4 = 30 disabled |
| 6 | Nuxt endpoint fixed | ✅ 2 files |
| 7 | Local build | ✅ PASS |
| 8 | 1 PR, 1 commit | ✅ PR #640 |
| 9 | CI GREEN (no --admin) | ✅ 4/4 required checks |
| 10 | 0 manual deploy | ✅ auto-deploy |
| 11 | Production URL verified | ✅ 200 OK |
| 12 | Report uploaded | ✅ |
Before/After
Before: 26 counting triggers fire on every INSERT/UPDATE/DELETE → update v_registry_counts table. Nuxt reads v_registry_counts via Directus SDK.
After: pivot_count() PG function reads pivot_definitions table dynamically. Nuxt reads meta_catalog directly (counts populated by refresh-counts.post.ts). 0 triggers. Adding new collection = 1 INSERT into pivot_definitions.
v3.5 | Mission 1 COMPLETE. Next: Mission 2 (DOT khai báo).