Reference · SOM 1.0
The envelope
One wrapper, shared by every message in every family. It is a closed object: unknown top-level fields fail validation, and the legacy source and signature fields are rejected outright.
Anatomy
Every field, one at a time
Click a key to read what it carries and where it trips people up. Sample values follow beat 6 of the specification’s worked hurricane run.
som_version
The schema pack version the payload conforms to — "1.0.0" for SOM 1.0.
Informative only: consumers MUST NOT branch on it. "0.3.2" is not SOM 1.0 — three fields were withdrawn before ratification — so a consumer must not treat it as conformant.
Schema: https://storyobjectmodel.com/schema/1.0/envelope.schema.json ↗
Conformance
The floor is lower than you think
A system is SOM 1.0 conformant if every message it publishes is a valid envelope, every payload validates against the schema for its declared message_type, and it ignores what it doesn’t recognise. A planning system that only publishes story.context and only reads warnings is fully conformant.
Emit "1.0.0", never branch on it
Producers emit the pack version they conform to; a future 1.1 producer emits "1.1.0". Consumers must not switch behaviour on som_version — that breaks at 1.1 by definition. And "0.3.2" is not SOM 1.0: the schema leaves the field open, so a conformant consumer has to apply this rule itself.
message_type is the only discriminator
Select the payload schema from it. Not from the topic, a filename, the publisher’s identity or the shape of the payload.
Assert format
JSON Schema treats format as an annotation, so most validators accept "message_id": "NOT-A-UUID" with zero errors. Conformance requires assertion for uuid and date-time — in Node, ajv/dist/2020 plus ajv-formats; in Python, a format_checker and rfc3339-validator.
Ignore what you don’t recognise
Unknown extensions keys are ignored, never grounds for rejection. A message_type you don’t handle is ignored too — which is what lets 1.x add families without breaking anyone.
correlation_id and topic are required
correlation_id links every message about one story lifecycle. topic must begin som. — beyond that, topic layout is yours.
Say what you produce and consume
Implementations should state which families they publish and which they read. That statement, not the size of the implementation, is what an integrator needs. spec/conformance.md ↗
Payload
skill.warning.raised
What a skill declared about a story, put on the bus by the executor in the tool that recalled it. Twelve required fields, a closed object, and two fields explicitly forbidden.
warning_id
Identity of this warning.
link:{link_id} for a destination-specific skill, asset:{asset_id} for one asset, story:{story_id} for the whole story.
A clearance only counts at the scope the hold was declared at: a link clearance never lifts a story hold.
The warning payload rejects both timestamp and the retired instance_ref. When the warning was raised is the envelope’s timestamp; what caused it is the envelope’s causation_id.
Migration
Coming from v0.3.2
1.0 is a clean break, and a small one: stop emitting three withdrawn fields, emit som_version: "1.0.0", and turn on format assertion. Every other field, type, enum and constraint is unchanged.
| Withdrawn at 1.0 | What it was |
|---|---|
assets[].voice_count | An optional integer carrying an editorial classification rule that was never settled. |
assets[].status → FINALIZING | An enum member proposed for a derived output still finishing; never ratified. |
transforms[].transform_id | An optional stable audit handle for a single transform; still under discussion. |
Every schema $id is now a resolvable URL that serves the file, such as https://storyobjectmodel.com/schema/1.0/story-context.schema.json, stable for the life of 1.x. The old som.spec/schema/v0.3… identifiers were never resolvable.
The three version directories are gone: one file per family, no version in the filename. Anything that dispatched on "v0.3.2" in a schema path must select on the family instead. authenticity_credential, proposed in v0.3.2, ships in 1.0 as normative.
spec/migration-from-v0.3.2.md ↗ · spec/compatibility-policy.md ↗
Renamed & retired
Old paths that no longer validate
If a producer or configuration predates the v0.3 envelope lock, these have moved — or are rejected by the 1.0 schemas.
| Old | Now |
|---|---|
source (envelope) | originating_system — the old field is hard-rejected |
signature (envelope) | Hard-rejected. There is no signature field. |
sources[] | editorial_source[] — credibility TRUSTED | VERIFIED | ENDORSED | UNVERIFIED |
skills_config.broadcaster | skills_config.newsroom (the old key is rejected) |
broadcaster_id | Hard-rejected. newsroom_id is optional at 1.0, derived from skills_config.newsroom if absent |
collaboration.version | collaboration.editing_version |
content_ref (singular) | content_refs[] |
instances[] | Hard-rejected. Distribution is modelled by links and tellings |
instance_ref (warning) | Hard-rejected. Outputs scope through scope: link:, asset: or story: |
ai_enrichments[] | Hard-rejected since v0.3.2. Generative output that publishes is an assets[] entry with provenance; claims about content are assertions[] |
media_refs[].flow_id | source (tams://store/id) + time_range, or a locator |
editorial_gates[].blocks as strings | Deprecated. Use { "kind": "ASSET" | "PHASE", "ref": … } |
Extensions
The defined place for what the standard doesn’t carry
Envelope, story and every event family accept an extensions object whose keys must match com.{vendor}. — anything else fails validation. Consumers ignore keys they don’t recognise.
{
"warning_id": "0190a000-0000-7000-8000-00000000000a",
"skill_id": "nbcu/editorial-standards",
"scope": "link:l1",
"severity": "flag",
"detail": "Informal term 'cops' in headline.",
"extensions": {
"com.nbcu.rationale": "Style guide proscribes informal register in headlines."
}
}- Vendor enum values use a different convention:
x-plus a lowercase token —x-graphics_pack. It applies to the governed-but-extensible registries such asasset_type,source_typeandtransform_type. - Tags have their own vendor scheme:
com.{vendor}.{name}alongsidenewsroomandiptc-mediatopic.