Skip to content

Available now

Prove your error paths ​

A good integration is refused when it should be, and reacts well when it is. Run these from a test harness, not your production code path: you're sending bad messages on purpose.

  • A. The published SOM negative cases: your validator and the bus agree.
  • B. Snapshot-sequence cases: your story state handling.
  • C. Policy cases: your configuration and grants.

A. The published negative cases ​

The SOM repository publishes 20 messages every SOM 1.0 implementation must refuse (examples/negative/), and 18 positive examples it must accept. The bus refuses all 20 and accepts all 18. Send each negative case through the Playground or your workspace's validate route (Token service and workspace API), and check the rule:

CaseWhy it must failStatus · rule
envelope-extensions-not-namespacedextensions keys must be com.<vendor>.…400 · envelope.additionalProperties
envelope-message-id-not-uuidmessage_id must be a UUID400 · envelope.format.uuid
envelope-missing-correlation-idcorrelation_id is required400 · envelope.required
envelope-signature-not-allowedNo signature in the 1.0 envelope400 · envelope.false_schema
envelope-som-version-0-3-2Only 1.0.0 is SOM 1.0400 · som_version.pre_1_0 (source conformance)
envelope-source-not-allowedsource was renamed originating_system400 · envelope.false_schema
envelope-system-type-unknownsystem_type is a closed list400 · envelope.enum
envelope-timestamp-not-date-timetimestamp must be RFC 3339400 · envelope.format.date-time
envelope-topic-not-somtopic must start with som.400 · envelope.pattern
envelope-unknown-propertyNo unknown envelope fields400 · envelope.additionalProperties
story-context-missing-story-idstory_id is required400 · story-context.required
story-context-ai-enrichmentsai_enrichments was removed400 · story-context.false_schema
story-context-asset-status-finalizingFINALIZING was withdrawn at 1.0400 · story-context.enum
story-context-asset-voice-countvoice_count was withdrawn400 · story-context.additionalProperties
story-context-lifecycle-phase-liveLIVE comes from the telling, never the story400 · story-context.enum
link-gate-status-unknownNot a compliance gate status400 · link-event.enum
telling-transform-idtransform_id was withdrawn400 · telling-event.additionalProperties
telling-transform-missing-typeEvery transform needs transform_type400 · telling-event.required
delivery-neither-source-nor-locatorA delivery needs a source or a locator400 · delivery-media-available.anyOf and .required
audit-flat-actoractor is an object, not a flat id400 · system-audit.required and .additionalProperties
  • Each file holds its case under message, next to must_fail_because. Send only what's under message.
  • In the envelope-* cases that's a complete message. In the rest it's a bare payload: wrap it in a valid envelope with the matching message_type, or you'll only see envelope errors.
  • A message can break several rules at once, and the bus reports them all. Assert on the rule named here, not on the count.

Then try to make your product produce each of them through its normal UI or API: an unknown system_type in its settings, a free-text timestamp, a withdrawn enum value. It should never get as far as sending one.

B. Snapshot-sequence cases ​

Start a fresh story, publish snapshots 1 to 3 of the hurricane run, then send one of these. A refused snapshot leaves the story as it was, so you can try the refused cases one after another. An accepted one moves the story on: run each accepted case on a fresh story of its own.

SendExpect
Snapshot 2 again, with a new message_id409 · sequence_number.not_increasing
Snapshot 4 with sequence_number: 3409 · sequence_number.not_increasing
Snapshot 4 with updated_at before snapshot 3's409 · updated_at.backwards
Snapshot 4 without editorial_source409 · snapshot.members_missing
Snapshot 4 without the asset-presser-feed asset409 · snapshot.assets_dropped
Snapshot 4 with that asset's asset_type changed to AUDIO409 · asset.type_changed
Snapshot 4 with sequence_number: 6202, with sequence_number.gap under tolerated
Snapshot 4 with a different correlation_id202, with correlation_id.changed under tolerated
A KILLED snapshot, then an ACTIVE one202, then 409 · story_type.left_terminal

Then do it through your product: restore its database from an earlier backup and edit the story again. Does it notice it's behind and resynchronise, or keep sending stale snapshots?

C. Policy cases ​

SendExpect
No Authorization header401 · producer.unauthenticated
A token from the other environment, or with one character changed401 · producer.unauthenticated
A valid message to another workspace's {t}403 · tenant.mismatch
A valid message as a system_id your app doesn't have403 · producer.system_id_not_allowed
A message type outside your grants403 · producer.message_type_not_allowed
A message over 240,000 bytes413 · message.too_large
A body that isn't JSON400 · message.not_json
The same message_id with different content409 · message_id.reused

Checkpoint ​

  • [ ] All 20 published negative cases are refused with the rules above.
  • [ ] My product can't be made to produce any of them through its normal UI or API.
  • [ ] Every sequence case behaves as listed, and my product handles each 409.
  • [ ] Every policy case behaves as listed.

Next: Consume messages, or the readiness checklist if you only produce.

SOM is an open standard maintained by the SOM working group. This service is not endorsed by it.