Principles
Principle
Immutability
CRISP rejects silent overwrite of Conform history. Corrections are new versions. How you retire the prior version — interval close (UPDATE ends) vs stricter insert-only tombstones — is an implementor choice. Both stay compatible with tritemporal axes and with Span/Publish as-of reads.
What kind of immutability
The baseline is history-preserving immutability: keep past belief queryable; apply corrections as new versions; allow controlled incremental MERGE only where it preserves history semantics. It is not “never update a cell platform-wide” as a forced default — and it is not soft-delete flags without temporal axes.
Correction on a timeline
At t0 the platform stores limit 100. At t1 a correction arrives: limit 120. What can you still read afterward?
Overwrite-only
After t1 the store holds only 120. Ask “what did we believe between t0 and t1?” — no row left to answer.
Out of bounds for regulated Conform paths
Versioned history
Prior interval stays: 100 for [t0, t1), 120 from t1. As-of reads still work.
CRISP baseline — history-preserving
Two compatible modes
Both modes use the same tritemporal columns (valid_*, system_*, warehouse_*). They differ in whether the load may UPDATE interval ends on a prior row.
| Mode | On correction | Typical read of “current” |
|---|---|---|
| Interval closedefault / common | UPDATE prior system_to / warehouse_to, then INSERT successor | Open interval — e.g. system_to IS NULL |
| Strict tombstoninginsert-only | Never mutate prior rows; INSERT a close/tombstone marker, then INSERT successor | Tombstone-aware chain (Span encapsulates the logic) |
You may run one mode platform-wide, or a mixed policy by domain. What CRISP forbids is treating the sole Conform copy as a mutable current row with no recoverable history.
Two CRISP-compatible modes
Interval close
Default / common
Strict tombstone
Insert-only
# Prior belief stays queryable; only ends are stamped
UPDATE SP_CORE_CONFORM.{entity}
SET system_to = :close_ts,
warehouse_to = :load_ts
WHERE assertion_pk = :prior AND system_to IS NULL;
INSERT INTO SP_CORE_CONFORM.{entity}
(... successor columns, system_from = :close_ts ...);# Prior row bytes never change
INSERT INTO SP_CORE_CONFORM.{entity}
(record_kind, supersedes_assertion_id, ...) -- TOMBSTONE_CLOSE → prior PK
INSERT INTO SP_CORE_CONFORM.{entity}
(record_kind, supersedes_assertion_id, ...) -- ASSERTION successor → prior PKHow this hangs off tritemporal
- valid_* — business truth intervals (restatement questions).
- system_* — source assertion / belief intervals (audit “what did we believe then?”).
- warehouse_* — trusted load acceptance / supersession — stamped only by Conform load, not adaptors.
Interval-close mode stamps ends on the prior row. Strict mode encodes the same close event as an appended marker so physical rows stay insert-only. Span and Publish as-of contracts stay the same; only the load and “current open” helpers change.
What is out of bounds
- In-place overwrite of the only copy of a regulated assertion.
- Delete + insert without temporal identity of the assertion.
- Soft-delete flags without a disciplined valid / system / warehouse split.
- A separate “current” table that becomes a competing source of truth (current may be a projection of history — not a second author).
Upgrade-safe column contract
Deploy optional chain columns from day one (record_kind, supersedes_assertion_id) even if you start in interval-close mode. Switching to strict tombstoning then becomes a load + Span register change — not a DDL migration of assertion tables.
Checklist
- Never define Conform truth by silent overwrite.
- Pick interval-close and/or strict tombstone per domain; document it.
- Keep loads idempotent so reruns do not double-apply business effect.
- Stamp warehouse_* only in the trusted Conform load.
- Expose as-of through Span/Publish — not per-mart rewrite rules.