KB-1849

P10D-1A — Directus TAC Read Precheck for /knowledge/laws (2026-04-30)

6 min read Revision 1
p10dprecheckdirectustaclaws

P10D-1A — Directus TAC Read Precheck for /knowledge/laws

Date: 2026-04-30 Scope: Read-only precheck. No code/DDL/DML/permission changes. Verdict: FAIL — Public (anonymous) Directus role cannot read the four TAC collections required by /knowledge/laws.


1. Gate 0 — Machine identity

Check Result
Control host Nguyens-MacBook-Air.local (nmhuyen)
Runtime host (SSH contabo) vmi3080463.contaboserver.net
Repo path on VPS /opt/incomex
Containers running postgres, incomex-directus
DB identity directus/directus

Gate 0 PASS — runtime is VPS, DB identity matches expected.


2. Current /knowledge/laws Directus access pattern

File: /opt/incomex/docker/nuxt-repo/web/pages/knowledge/laws/index.vue

Pattern:

  • Imports readItems from @directus/sdk.
  • Uses const { $directus } = useNuxtApp();
  • Calls $directus.request(readItems('governance_docs', { ... })) inside useAsyncData('governance-docs', ...).

Plugin: web/modules/directus/runtime/plugins/directus.ts

  • Server (SSR): createDirectus(serverUrl).with(rest())no authentication() layer, no token. SSR fetches go as anonymous / public role.
  • Client (browser): createDirectus(/api/directus).with(authentication('session', { credentials: 'include' })).with(rest()) — uses session cookie if a user is logged in; otherwise still public.

useAsyncData resolves on the server first, so the effective role for the initial render of /knowledge/laws is the Directus Public role (no token).


3. TAC read test results

All HTTP calls executed on VPS against https://directus.incomexsaigoncorp.vn (same host the Nuxt server uses).

3a. Anonymous (matches /knowledge/laws SSR path)

Collection HTTP Result
tac_publication 403 FORBIDDEN — You don't have permission to access collection "tac_publication" or it does not exist.
tac_publication_member 403 Same FORBIDDEN message
tac_logical_unit 403 Same FORBIDDEN message
tac_unit_version 403 Same FORBIDDEN message
governance_docs (control) 200 Returns published rows — confirms current page works because public role has READ on this collection only.

3b. Admin token (sanity — tables exist and are populated)

Collection HTTP meta.total_count Notes
tac_publication 200 3 D35 (27e48995-…), D32, D28 visible.
tac_publication_member 200 86 Includes D35 pub_id rows.
tac_logical_unit 200 86 Has canonical_address, parent_id, sort_order, section_type.
tac_unit_version 200 86 Has title, body, version_number.

Conclusion: collections exist, schema fields present, data present. The 403s are permission-only, not missing-collection.

3c. Required deep/relation fields probe

Not executed. Anonymous read on parent collection already 403; deep-relation fields (logical_unit_id.*, unit_version_id.*) require READ on the related collections, which are also 403.


4. Permission gap (read-only inspection result)

The Directus Public role currently has READ on:

  • governance_docs

It is missing READ on:

  • tac_publication
  • tac_publication_member
  • tac_logical_unit
  • tac_unit_version

No fields/relations have been verified at the Public role level because the collection-level gate fails first.


5. Required fields for tree/reader

Confirmed available in DB (via admin probe), but not reachable by the Public role:

  • tac_publication: id, doc_code, version, name, lifecycle_status
  • tac_publication_member: render_order, logical_unit_id (m2o), unit_version_id (m2o)
  • tac_logical_unit: id, canonical_address, parent_id, sort_order, section_type
  • tac_unit_version: id, title, body, review_state, lifecycle_status

6. Verdict

FAIL. The current /knowledge/laws SSR path runs as the Directus Public role and is denied READ on all four TAC collections. PG/render correctness is not the blocker; the Directus permission “key” for the web role is missing.


7. Next action

Do not implement assembly wiring yet. Authorize a Directus admin (UI or API, separate session) to grant the Public role (or a dedicated web_reader policy applied to anonymous + authenticated sessions) READ permissions on:

Collection Action Fields
tac_publication read id, doc_code, version, name, lifecycle_status (consider filter lifecycle_status = 'enacted')
tac_publication_member read id, publication_id, logical_unit_id, unit_version_id, render_order
tac_logical_unit read id, canonical_address, parent_id, sort_order, section_type, doc_code
tac_unit_version read id, logical_unit_id, version_number, title, body, review_state, lifecycle_status

After permissions are granted, re-run this precheck (anonymous probe must return 200 on all four). Only then proceed to the one-file assembly wiring prompt for web/pages/knowledge/laws/index.vue.


8. STOP

Report uploaded. No implementation performed. No permission changes made.

Back to Knowledge Hub knowledge/dev/laws/dieu38-trien-khai/reports/p10d-1a-directus-tac-read-precheck-2026-04-30.md