Concepts
Audit chain
Every state change is an event in a per-organization hash chain. How rows are hashed, and how to verify the chain.
Every change to a post or target writes an event in the same database transaction as the change itself. Events are never updated or deleted; the database refuses both.
What each event records§
- The event (
created,validated,submitted,approved,scheduled,published,failed…) and the post and target it concerns. - The actor: a person, an API key, an MCP client or the worker. Agent calls also carry
agent_meta: name, model, run id. - The content hash at that moment, and the request id that caused it.
- A sequence number, the previous row’s hash and its own hash.
How rows are chained§
row_hash = sha256( prev_hash || canonical_json(row without id, prev_hash, row_hash) )Each organization has its own chain and head. Change any field in any past row and every hash after it stops matching; delete a row and the sequence shows a gap.
Verify it§
curl $API/v1/audit/verify -H "Authorization: Bearer $ADMIN_KEY"If a row does not match, the response names first_bad_seq. Per post, GET /v1/posts/{id}/events returns the rows and a chain check for just that post.