KB-3AEF
KB Protection Phase 1 Report
5 min read Revision 1
reportkb-protectiontriggers
KB Protection Phase 1 — Report
Date: 2026-04-04 | Session: S165 | Agent: Claude Code
Summary
Deployed PG trigger-based protection layer for Agent Data KB (kb_documents in incomex_metadata). Zero code changes. Triggers are transparent — API writes continue normally.
Investigation (Step 1)
| Item | Value |
|---|---|
| Target table | kb_documents |
| Target DB | incomex_metadata (user: incomex) |
| Schema | key TEXT PK + data JSONB (all fields in JSONB) |
| Content path | data->'content'->>'body' |
| Existing triggers | 0 (NONE before this session) |
| Existing audit tables | 0 in incomex_metadata |
| Sync mechanisms | event_system.py -> directus_sync.py (async, knowledge/ prefix only) |
| Directus Flows | 3 KB-related flows, ALL INACTIVE |
| Conflicts found | NONE — clean install |
Tables Created (incomex_metadata)
| Table | Status | Purpose |
|---|---|---|
kb_documents_history |
OK | Full JSONB snapshot before each UPDATE/DELETE |
kb_audit_log |
OK | Lightweight write operation log (no content) |
Triggers Created (on kb_documents)
| Trigger | Type | Status | Purpose |
|---|---|---|---|
trg_kb_truncation_guard |
BEFORE UPDATE | OK | Warns when body shrinks >80% (>500 chars) |
trg_kb_snapshot_update |
BEFORE UPDATE | OK | Saves OLD.data to history |
trg_kb_snapshot_delete |
BEFORE DELETE | OK | Saves OLD.data to history |
trg_kb_audit |
AFTER INSERT/UPDATE/DELETE | OK | Logs all write ops |
Safety: All triggers use EXCEPTION WHEN OTHERS THEN RAISE WARNING — never block production writes.
PG Functions
| Function | Status | Purpose |
|---|---|---|
fn_kb_snapshot |
OK | Snapshot trigger function |
fn_kb_audit |
OK | Audit trigger function |
fn_kb_truncation_guard |
OK | Truncation detection |
fn_kb_restore(key, rev) |
OK | Restore document from history |
View
v_kb_recent_changes: Last 7 days write operations with severity
Safety Tests
| Test | Result |
|---|---|
| INSERT -> audit log | PASS |
| UPDATE -> history snapshot + audit | PASS |
| DELETE -> history snapshot + audit | PASS |
| Truncation guard (body <500 skip) | PASS (by design) |
| fn_kb_restore | PASS (restored rev 1, content correct) |
| API POST /documents after triggers | PASS (200 OK) |
| API DELETE after triggers | PASS (soft-delete captured) |
| Qdrant + health probes | OK (no disruption) |
DOT Registration (directus DB)
| Item | Code | Status |
|---|---|---|
| Domain | kb (Quan ly tri thuc) |
Created |
| DOT_KB_PROTECT | Tier B, event trigger | Registered |
| DOT_KB_VERIFY | Tier A, cron trigger | Registered |
| DOT_KB_RESTORE | Tier B, on-demand | Registered |
| Paired | PROTECT <-> VERIFY | Set |
Birth + Collection Registry
| Entity | Collection | Status |
|---|---|---|
kb_documents_history |
birth + COL-158 | Registered |
kb_audit_log |
birth + COL-159 | Registered |
Cron
0 21 * * * /opt/incomex/scripts/dot-kb-verify.sh >> /var/log/incomex/dot-kb-verify.log 2>&1
Scripts
/opt/incomex/scripts/dot-kb-verify.sh— daily integrity check (5 checks)/opt/incomex/scripts/dot-kb-restore.sh— restore tool
First Verify Run
- 303 docs with rev>1 but no history — expected (pre-trigger data, will populate going forward)
- 0 truncation warnings
- 0 suspicious short docs
- PG active: 856
Directus Sync Note
Tables are in incomex_metadata (not directus), so Directus UI cannot see them. This is correct — they are infrastructure tables managed via SQL only.
Architecture
API Write -> PG kb_documents
|-> BEFORE: trg_kb_truncation_guard (warn if shrink >80%)
|-> BEFORE: trg_kb_snapshot (copy OLD.data -> history)
|-> WRITE executes
|-> AFTER: trg_kb_audit (log operation)
|-> Event System (existing, unchanged)
|-> Directus Sync (existing, unchanged)
Zero impact on existing write flow. Triggers are transparent.