Appearance
Snapshots, not deltas
This is the rule that catches most integrations.
- Every
story.contextcarries the whole story, not just what changed. Leave out a field you didn't change, and every consumer erases it. - Every snapshot carries a
sequence_numberthat strictly increases for that story, and anupdated_atthat never goes backwards. - An asset's
asset_typenever changes. An asset doesn't silently disappear from a later snapshot. - A story that reached a terminal
story_type(KILLED,SPIKED,ARCHIVED) doesn't come back.
seq 1 PLANNED headline
seq 2 ACTIVE headline, lifecycle, assets[feed]
seq 3 ACTIVE headline, lifecycle, assets[feed, transcript] ✓ whole story, seq up
seq 3 ACTIVE … ✗ 409 sequence_number.not_increasing
seq 4 ACTIVE headline, lifecycle, assets[transcript] ✗ 409 snapshot.assets_droppedSnapshot order
A single message can't show that it breaks a story; only the previous snapshot can. So the bus remembers what it needs from the last accepted snapshot of every story (its sequence number, updated_at, story_type, top-level members, asset ids and types, and which system wrote it and owns the story, never the payload), with no expiry, and checks each new one against it (SOM conformance, section 6). These checks report source: sequence:
| Rule | Outcome |
|---|---|
sequence_number.not_increasing | Refused, 409 |
updated_at.backwards | Refused, 409 |
snapshot.members_missing | Refused, 409 |
snapshot.assets_dropped | Refused, 409 |
asset.type_changed | Refused, 409 |
story_type.left_terminal | Refused, 409 |
sequence_number.gap | Accepted, with a warning under tolerated |
correlation_id.changed | Accepted, with a warning under tolerated |
Tests and reruns
Because the bus keeps each story's sequence state with no expiry, a test run needs a new story_id. A rerun under an old one starts again at sequence_number 1 and is refused as stale. Story state is kept per workspace; prefix your story ids with your app name so your own apps' runs don't collide.
After a refusal
Resynchronise from your own state: send a fresh, complete snapshot with the next sequence_number and a new message_id. The Playground in the portal, and your workspace's validate route, check a snapshot against the story's current state without publishing it.