Core concepts

The invalidation loop

One metadata change becomes a campaign, an assessment per affected decision, and a governed writeback — with no human in the path.

The path a change takes

1

A change arrives

DataHub emits a MetadataChangeLogEvent_v1. The Action normalises supported payloads into a closed change model before any policy runs. Unsupported aspects are acknowledged as no-ops; a malformed supported event raises, so the Actions framework retries it rather than silently dropping it.

2

Reverse lookup

The changed entity is looked up against the signed-receipt dependency index. This is the step the whole design exists to make possible: without a recorded, URN-resolved dependency set, there is nothing to look up.

3

A campaign is created

Matching receipts become one content-addressed campaign, bound to the exact change event and the exact policy version that will judge it.

4

Each decision is assessed

The materiality engine runs — pure, deterministic, versioned — and produces a state and a reason code per receipt.

5

Findings write back

Material findings become DataHub incidents. Affected receipts can be quarantined. Everything is recorded in an append-only audit.

Campaigns are content-addressed

A campaign is identified by its content, so re-processing the same change event produces the same campaign rather than a duplicate. That is what makes redelivery safe: at-least-once transport plus content addressing gives you effectively-once outcomes without a distributed transaction.

Feedback-loop protection

GlassBox writes incidents into DataHub, and DataHub emits change events. Without a guard, its own writeback would arrive back as a new change to assess. The Action recognises its own effects and does not re-enter on them.

Leases, not locks

Campaign work is leased, not locked.

  • A worker claims a campaign with an expiring lease.
  • If the worker dies, the lease expires and the work is recovered.
  • A restarting worker cannot steal a live lease held by another process.
  • SQLite uses the caller clock; PostgreSQL uses the database server clock, which is what makes multi-worker coordination sound.

Two state profiles

SQLite (WAL)PostgreSQL 14+
ScopeMulti-process, one hostMultiple workers
ClaimsTransactionalRow-locked
ClockCallerDatabase server
BootstrapinitOperator-only postgres-init
Extrabuilt in--extra postgres

Both profiles implement one behavioural protocol: signed receipt registration, reverse lookup, campaign leases, sealed DataHub evidence, and durable outboxes. A detector or a state transition cannot exist in one profile and silently not in the other.

Honest boundary

The SQLite profile coordinates processes on one host. It is deliberately not presented as a multi-node or network-filesystem deployment. The PostgreSQL proof establishes real multi-connection coordination on a real server; it does not claim physical multi-host deployment, managed failover, or network-partition recovery.

Three durable outboxes

Every effect that leaves the process is an obligation recorded in the same transaction as the state it describes:

Receipt publication

Inserted READY with every new signed receipt. Drives the governed DataHub projection.

Campaign writeback

Carries findings to DataHub incidents and receipt quarantine.

Owner routing

Created in the same transaction as verified writeback, so a notification cannot exist without the finding that justified it.

Each row carries READY / LEASED / COMPLETED, an attempt counter, a bounded error type, and worker ownership. Completed redelivery performs a fresh DataHub readback with zero writes.

Next

Deterministic invalidation covers what the materiality engine actually decides, and DataHub covers the writeback side.