GPT Review Round 3 — Điều 24 Luật Nhãn v1.2 (2026-03-15)
GPT Review Round 3 — Điều 24: Luật Nhãn v1.2
Ngày: 2026-03-15 Nguồn: Incomex Hội đồng AI (GPT) Phạm vi: Final consensus review, KHÔNG sửa luật gốc
Kết luận tổng quát
v1.2 rất sát mức chốt chính thức. Phần lớn các lỗ hổng lớn đã được xử lý đúng. Tuy nhiên tôi vẫn thấy 2 điểm 🔴 còn lại cần chốt trước khi gọi là bản cuối:
- Composite FK same-facet hiện còn lỗ hổng NULL ở
parent_facet. - DDL trigger per table vẫn chưa an toàn cho các bảng không có đủ
name, description.
Ngoài 2 điểm đó, phần còn lại là 🟡 hoặc 🟢.
1. 12 điểm đã sửa — có điểm nào sửa sai hoặc tạo vấn đề mới?
🔴 Cần sửa
(a) Composite FK same-facet chưa khóa chặt vì parent_facet có thể NULL.
Schema hiện có:
FOREIGN KEY (parent_id, parent_facet) REFERENCES taxonomy(id, facet_id)CHECK (parent_facet = facet_id)
Nhưng trong PostgreSQL:
- FK không enforce khi một cột tham chiếu là NULL
- CHECK trả NULL thì vẫn pass
Nghĩa là có thể rơi vào case:
parent_id IS NOT NULLparent_facet IS NULL- FK không chạy
- CHECK cũng không fail chắc chắn
=> same-facet bị bypass.
Đề xuất: thêm ràng buộc cứng:
CHECK (
(parent_id IS NULL AND parent_facet IS NULL)
OR (parent_id IS NOT NULL AND parent_facet IS NOT NULL)
)
Hoặc gộp luôn vào chk_root_no_parent mở rộng.
(b) Trigger DDL UPDATE OF name, description chưa chắc áp dụng được cho mọi table.
Function đã data-driven, tốt. Nhưng câu:
CREATE TRIGGER ... AFTER INSERT OR UPDATE OF name, description ON <table>
chỉ hợp lệ khi table đó thực sự có cả name và description. Với các bảng thiếu một trong hai cột, DDL có thể fail.
Đề xuất: trigger generator phải tạo per-table đúng cột thực có:
- bảng có
name, description→UPDATE OF name, description - chỉ có
name→UPDATE OF name - chỉ có
description→UPDATE OF description - không có cả hai → chỉ
AFTER INSERThoặc bỏ keyword layer cho table đó
🟡 Nên cân nhắc
v_all_entity_codesdùngUNION ALLlà ổn nếu code thật sự unique toàn hệ thống. Nếu vẫn còn legacy vi phạm uniqueness, DOT validate sẽ nhiễu. Không chặn deploy, nhưng nên verify uniqueness củacodeở tất cả nguồn trước.- Trigger chống cycle/replaced_by duyệt ≤5 bước là an toàn dư một chút, không vấn đề.
🟢 Đồng ý
- Chống cycle thật: đúng hướng
- fn data-driven với
to_jsonb(NEW): đúng - Soft reference + DOT validate qua
v_all_entity_codes: chấp nhận được - Scored union top N: đúng
- Gán leaf only: đúng
- meta_catalog priority: đúng
skip_wide_warning: hợp lý- IF NEW<>OLD guard: đúng
- Tắt Count junction Directus: đúng
2. Composite FK same-facet — có edge case nào với Directus CRUD?
🔴 Cần sửa
Có edge case triển khai: Directus không tự suy ra parent_facet từ parent_id nếu chỉ cấu hình M2O thông thường. Nghĩa là user/admin/DOT có thể chọn parent_id nhưng quên set parent_facet.
Khi đó:
- nếu chưa thêm ràng buộc NOT-NULL theo cặp, schema có thể lọt dữ liệu hở
- nếu đã thêm ràng buộc chặt, Directus create/update sẽ fail nếu UI không fill
parent_facet
Đề xuất tốt nhất:
- giữ composite FK
parent_facetkhông cho user nhập tay- dùng DB trigger BEFORE INSERT/UPDATE để tự fill
parent_facet := facet_id của parentkhiparent_idcó giá trị
Như vậy:
- schema vẫn mạnh
- Directus UX không bị bắt người dùng nhớ field phụ
- tránh dữ liệu lệch giữa
parent_idvàparent_facet
Nếu không muốn thêm trigger fill, thì Directus flow/hook phải đảm bảo điền, nhưng DB trigger đáng tin hơn.
3. v_all_entity_codes — ALTER VIEW mỗi khi thêm table mới, có ổn không?
🟡 Nên cân nhắc
Chấp nhận được ở v1.2.
Lý do:
- thêm managed collection là sự kiện hiếm
- Rule hệ thống đã có CI/CD guard khi thêm collection mới phải cập nhật meta_catalog
- ALTER VIEW lúc thêm loại mới là chi phí chấp nhận được
Cách dynamic hơn có thể làm bằng function đọc meta_catalog rồi dynamic SQL, nhưng sẽ phức tạp hơn và khó enforce ở DB-level/Directus hơn.
Kết luận: giữ VIEW tĩnh + cập nhật cùng migration mỗi khi thêm collection mới là hợp lý hơn cho v1.2.
4. Scored union "Cùng nhóm" — nên per-facet hay across facets?
🟢 Đồng ý
Giữ per-facet đơn giản ở v1.2 — chỉ theo domain (FAC-01) là đúng.
Lý do:
- “Cùng nhóm” bản chất gần nhất với cùng chuyên môn/domain
- trộn thêm action/audience vào score ngay ở v1.2 sẽ làm khái niệm đổi nghĩa từ “cùng nhóm” sang “liên quan tổng hợp”
- UI sẽ khó giải thích hơn
🟡 Nên cân nhắc
Phase sau có thể thêm:
Cùng nhóm= per-facet domainLiên quan mạnh= weighted multi-facet
Nhưng hiện tại nên giữ 1 nghĩa rõ ràng.
5. Cycle detection trigger — ≤5 có cần giảm xuống ≤3 không?
🟢 Đồng ý
≤5 không có vấn đề. Không cần giảm.
Với depth max=2, đúng là cycle thực tế ngắn hơn. Nhưng để 5:
- không gây hại đáng kể
- tăng dư địa an toàn nếu có legacy bẩn hoặc migration lỗi
Đây là guardrail kỹ thuật, không phải logic business chính.
6. Tổng thể còn góc khuất nào không?
🔴 Cần sửa
Tôi còn thấy đúng 2 góc khuất chặn deploy — chính là 2 điểm đầu:
- lỗ hổng NULL trong composite FK same-facet
- trigger DDL chưa an toàn cho bảng thiếu
name/description
🟡 Nên cân nhắc
entity_labelshiện có index đơnentity_code,label_code. Với query scored union lớn hơn về sau, có thể thêm index ghép(label_code, entity_code)để tối ưu join ngược. Không chặn deploy.v_all_entity_codesnên loại log/non-managed nếu DOT validate chỉ dành cho managed/business scope; nếu không, cần mô tả rõ chủ ý giữ cả taxonomy/meta/system_issues trong VIEW.
🟢 Đồng ý
Ngoài 2 điểm trên, tôi không còn thấy lỗ hổng kiến trúc lớn mới nào.
Phán quyết cuối theo format
🔴 Cần sửa (chặn deploy)
- Khóa chặt
parent_facetđể composite FK same-facet không bị bypass bởi NULL. - Sinh trigger per-table đúng cột thực có; không dùng chung
UPDATE OF name, descriptioncho mọi bảng nếu schema không đồng nhất.
🟡 Nên cân nhắc (không chặn deploy)
- Giữ
v_all_entity_codeslà VIEW tĩnh, ALTER VIEW khi thêm collection mới — chấp nhận được. - Giữ
Cùng nhómper-facet domain ở v1.2; multi-facet để phase sau. - Có thể thêm index ghép
(label_code, entity_code)sau. - Xác nhận lại uniqueness toàn hệ thống của
codeở các nguồn union.
🟢 Đồng ý (không thay đổi)
- 10/12 điểm còn lại đều đúng hướng và không tạo vấn đề mới đáng kể.
- Cycle trigger ≤5 là ổn.
- Scored union top N là lựa chọn đúng.
- Soft reference + DOT validate là quyết định thực tế hợp lý.
Kết luận chốt
Chưa đạt đồng thuận cuối cùng. Nếu sửa xong 2 điểm 🔴 trên, tôi sẽ xem v1.2 là đủ sạch để phê duyệt chính thức.