KB-2E7B

06 — Notification / Cleanup Trigger Contract (system_issues + event_outbox)

5 min read Revision 1
architecturenotificationcleanup-triggersystem-issuesevent-outboxdieu-23dieu-45contract2026-05-31

title: 06 — Notification / Cleanup Trigger Contract date: 2026-05-31

06 — Notification / Cleanup Trigger Contract

Design-only. No production notification is wired this session. The contract reuses the live issue tracker and event spine; it does not propose a new notification system.

Live targets (verified)

  • system_issues (179,074 rows) — canonical issue/violation store. Columns used: issue_type, severity, status, entity_type, entity_code, source, issue_class, sub_class, coalesce_key, violation_hash, evidence_snapshot (json), occurrence_count, first_seen_at/last_seen_at, reopen_count. (Note: singular system_issue does NOT exist — system_issues is canonical.)
  • event_outbox + event_type_registry — the Đ45 PG-native queue (register-before-emit; signal-not-data; DLQ/retry). Cleanup workflows are triggered via events, not by the scanner doing the work.

Existing issue types to REUSE (no new taxonomy needed for most)

condition reuse issue_type (live) severity
orphan: missing relationship set thiếu_quan_hệ warning→HIGH
orphan: missing ID / birth thiếu_mã_định_danh warning→HIGH
unmonitored / un-onboarded collection collection_onboarding_gap warning→critical
data drift (record≠actual) sai_lệch_dữ_liệu warning
cross-store drift / ghost kb_pg_sync_drift warning
frontend/disguised hardcode hardcode_violation / hc_finding_sql|builtin|function warning→critical
phantom in approval flow apr_phantom_applied info

Proposed NEW issue types (propose-only — additive to the existing enum-by-convention)

  • count_integrity_failed — the accounting invariant fails for a scope (doc 02).
  • count_integrity_phantomrecord_count > actual_count on a leaf (phantom, doc 01).
  • label_missing — a list exceeds its max_ungrouped_threshold with no resolvable grouping dimension (doc 04).

Contract — per detected condition

on detect(condition, scope):
  upsert system_issues
    SET issue_type   = <reuse-or-propose>,
        severity     = <table above>,
        entity_type  = scope.kind, entity_code = scope.code,
        source       = 'registries-pivot-count-integrity',
        coalesce_key = condition || ':' || scope.code,   # idempotent: re-detect bumps occurrence_count, not a new row
        evidence_snapshot = <json: counted, actual, orphan, phantom, gap, last_scan_date>,
        status       = 'open'
  emit event_outbox(event_type = <registered type>, payload = signal-only ref to the system_issues row)   # DESIGN
  # cleanup workflow is the consumer of the event, keyed by issue_type → target workflow:
  #   thiếu_*            → birth/registration workflow (Side A)
  #   count_integrity_*  → refresh_meta_catalog_from_pivot + recount, then re-evaluate
  #   collection_onboarding_gap → onboarding workflow (fn_birth_onboarding_full_scan)
  #   label_missing      → label.classify workflow (governed label generation, Đ24)
  #   hardcode_violation → developer-facing finding (no auto-fix)

Hard rules (Đ23 / Đ28 / Đ45)

  • Never silently hide a mismatch — every invariant failure produces a visible system_issues row AND is reflected on the surface (verification_status / warning_flags / next_action columns).
  • Idempotentcoalesce_key collapses repeat detections (the live table already uses coalesce_key, violation_hash, occurrence_count for exactly this).
  • Signal-not-dataevent_outbox carries a reference to the issue, not the data payload (Đ45 §4 hard CHECK).
  • Register-before-emit — any new event_type must be in event_type_registry before first emit.
  • No self-execution by the scanner — detection writes an issue + emits a signal; a separate governed workflow performs cleanup. The scanner never deletes/repairs rows itself.

This session

Contract documented; zero system_issues rows written, zero events emitted. Detection rehearsal (doc 02) was pure read SELECT only.

Back to Knowledge Hub knowledge/dev/reports/architecture/registries-pivot-os-agency-count-integrity-orphan-phantom-label-pin-rehearsal-2026-05-31/06-notification-cleanup-trigger-contract.md