generated from coulomb/repo-seed
Some checks failed
Test / test (push) Has been cancelled
Implements IHUB-WP-0009: closes four GAAF-2026 gaps before domain hub work begins. - TypeRegistry helper + controllers/views (hub_kind, hub_capability_manifest) - HubCapabilityManifest entity with validation and registry linkage - ARCHITECTURE-LAYERS.md + CI-enforced boundary contracts - Alembic migration 1743724800, fitness tests (Test/Architecture/) - GAAF spec, Operational Architecture spec, domain hub extension guide - Updates to CLAUDE.md, SCOPE.md, Schema.sql, Routes, FrontController, Types state_hub_sync: pending (tunnel was STALE at completion time; run fix-consistency) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
105 lines
2.9 KiB
Markdown
105 lines
2.9 KiB
Markdown
# Append-Only Events Contract
|
|
|
|
**Name:** append-only-events
|
|
**Version:** 1.0
|
|
**Date:** 2026-03-31
|
|
**Status:** Active
|
|
**Layer:** Core
|
|
**Immutable:** Yes — this invariant is permanent and cannot be relaxed
|
|
|
|
---
|
|
|
|
## Purpose
|
|
|
|
Interaction events and outcome signals are the primary observational record of
|
|
the IHF. Their integrity as an append-only log is a foundational invariant:
|
|
governance, traceability, and antifragility all depend on the fact that the
|
|
historical record cannot be silently rewritten.
|
|
|
|
---
|
|
|
|
## Invariant
|
|
|
|
The following tables are **append-only**:
|
|
|
|
| Table | Trigger (no update) | Trigger (no delete) |
|
|
|---|---|---|
|
|
| `interaction_events` | `interaction_events_no_update` | `interaction_events_no_delete` |
|
|
| `outcome_signals` | `outcome_signals_no_update` | `outcome_signals_no_delete` |
|
|
|
|
No row in either table may be modified or deleted after insertion. This
|
|
invariant is enforced at the PostgreSQL level by `BEFORE UPDATE` and
|
|
`BEFORE DELETE` triggers that raise exceptions. It cannot be bypassed by
|
|
application code.
|
|
|
|
---
|
|
|
|
## Enforcement
|
|
|
|
```sql
|
|
-- Implemented in Application/Schema.sql
|
|
CREATE TRIGGER interaction_events_no_update
|
|
BEFORE UPDATE ON interaction_events
|
|
FOR EACH ROW EXECUTE FUNCTION prevent_interaction_event_mutation();
|
|
|
|
CREATE TRIGGER interaction_events_no_delete
|
|
BEFORE DELETE ON interaction_events
|
|
FOR EACH ROW EXECUTE FUNCTION prevent_interaction_event_mutation();
|
|
|
|
-- Same pattern for outcome_signals
|
|
```
|
|
|
|
The trigger function raises:
|
|
```
|
|
"interaction_events is append-only: UPDATE and DELETE are not permitted"
|
|
```
|
|
|
|
---
|
|
|
|
## Correction Policy
|
|
|
|
Erroneous events **must not** be corrected by modifying the original row.
|
|
The correct approach is to insert a new event:
|
|
|
|
```json
|
|
{
|
|
"event_type": "retracted",
|
|
"metadata": {
|
|
"retracted_event_id": "<uuid of original event>",
|
|
"reason": "incorrect actor attribution"
|
|
}
|
|
}
|
|
```
|
|
|
|
The original event remains in the table. Downstream analysis should treat
|
|
`retracted` events as markers that exclude the referenced event from
|
|
calculations.
|
|
|
|
---
|
|
|
|
## Failure Mode
|
|
|
|
Any attempt to UPDATE or DELETE a row in `interaction_events` or
|
|
`outcome_signals` raises a PostgreSQL exception with SQLSTATE `P0001`.
|
|
The calling transaction is aborted. No partial mutation is possible.
|
|
|
|
---
|
|
|
|
## Scope
|
|
|
|
This contract applies **only** to `interaction_events` and `outcome_signals`.
|
|
|
|
Other append-oriented tables (`triage_states`, `widget_ownerships`,
|
|
`stewardship_roles`) use the same conceptual pattern (soft expiry instead of
|
|
update, no hard delete) but are not covered by DB-trigger enforcement. Their
|
|
append semantics are enforced by application-layer controller conventions.
|
|
|
|
---
|
|
|
|
## Implementation Reference
|
|
|
|
- Functions: `prevent_interaction_event_mutation()`,
|
|
`prevent_outcome_signal_mutation()` in `Application/Schema.sql`
|
|
- The architectural fitness function `Test/Architecture/LayerBoundarySpec.hs`
|
|
(Test 1) verifies these trigger names are present in the schema
|