Reference

The envelope

One wrapper, shared by every message on every topic. It is a closed object: unknown top-level fields fail validation, and the legacy source and signature fields are hard-rejected.

Anatomy

Every field, one at a time

Click a key to read what it carries and where it trips people up.

{
"som_version": "0.3.2",
"message_id": "0190a000-…-7000-aaa1",
"correlation_id": "0190a000-…-7000-0c14",
"causation_id": "0190a000-…-7000-91ff",
"message_type": "story.context",
"timestamp": "2026-06-12T09:30:00.000000Z",
"originating_system": { "system_id": "enps-lon-01", "system_type": "ncs", … },
"topic": "som.story.context",
"modification_header": { "story_version": 7, "modified_by": "ed1" },
"_actors": { "ed1": { "name": "A. Editor", … } },
"@context": null,
"extensions": { "com.nbcu.desk": "news" },
"payload": { … }
}

som_version

requiredstring

The schema pack version the payload conforms to — "0.3.2" on the current pack.

Informative only. Never branch on it — message_type is what identifies the payload family. Traffic recorded before 12 Aug 2026 reads 0.2.0, the retired SOM-048 wire freeze.

Integration

The five rules that bite

Nearly every integration problem reported against SOM comes back to one of these.

01

som_version is informative

It carries the schema pack version the payload conforms to — "0.3.2" today. Don’t gate on it, don’t branch on it. message_type is what identifies the payload family. Traffic recorded before 12 Aug 2026 reads 0.2.0: that was a wire freeze, since retired, and readers who took it for the payload shape concluded they were on the wrong schema.

02

correlation_id is required

Thread it end-to-end. A downstream event must be traceable back to the story or action that caused it. Skill outputs echo the inbound envelope’s id; republished story versions keep theirs.

03

timestamp lives on the envelope

Never inside the payload. There is no signature field either — both settled in the same design decision.

04

originating_system, not source

Renamed at v0.3; the old field is hard-rejected. system_id and system_type are required. The newsroom system value is ncs — there is no newsroom value in the enum.

05

Message types are suffixed

On the wire it is skill.warning.raised, not skill.warning; telling.started, not telling. Consumers parse the suffixed form for routing.

+

Validate before you publish

The vendored JSON Schemas are the source of truth — not any prose description, including this page. Drop your candidate payload next to the shipped examples and run the repo’s validator.

Addressing

Field paths are relative to the payload

Skill rules address fields by dot-notation path. The executor walks the path against the payload object — never the envelope.

Rule config fieldResolves to
headlinepayload.headline — string
lifecycle.phasepayload.lifecycle.phase — string
compliancepayload.compliance — array, checked for empty/present
priority.levelpayload.priority.level — string
premise.premise_changedpayload.premise.premise_changed — boolean
assets[].acquisition_stateOne array wildcard, supported by field_changed only

Most rule types check an array field for presence or absence as a whole. The field_changed type additionally supports one [] wildcard, matching elements across story versions by their asset_id / source_id / flag_id / id. Anything more selective — “any compliance flag of type X” — means a custom rule type in the executor.

Payload

skill.warning.raised

The most common outbound payload: an editorial warning raised by a skill against a story, or against one surface of it. Twelve normative fields, plus the optional instance binding.

{
"warning_id": "wrn-019536b1-0001",
"skill_id": "nbcu/editorial-standards",
"skill_version": "0.1.0",
"story_id": "story-2026-0612-001",
"scope": "story",
"severity": "flag",
"rule_id": "nbcu-style-001",
"non_overridable": false,
"affected_fields": ["headline"],
"detail": "Informal term 'cops' in headline.",
"blocks": [],
"skill_warning_ref": "wrn-ref-019536b1",
"instance_ref": "inst-nbcnews-web-001"
}

warning_id

requiredstring (UUIDv7)

Identity of this warning. One warning, one pending row, one approve/reject.

Severity semantics

hold — the executor must withhold all output on the affected fields until resolved, and subscribers must not use held content.

flag — mark output as requiring review; a subscriber may show a visual warning.

inform — advisory only. No blocking action, no mandatory response.

Instance scoping

A story can air on several surfaces at once. When a warning applies to one of them, set instance_ref to that instance_id. Omit it for story-wide warnings.

It is singular on purpose: one warning, one pending row, one approve/reject per surface. Two surfaces means two warnings with two ids.

A warning referencing an instance_id that doesn’t exist should be rejected by the consumer — fail closed.

Instance scoping rides in the payload, never in the topic name. Do not split skill warnings across som.skills.staging.{instance}-style topics.

Migration

Renames that break old configs

If a rule config or producer predates the v0.3.x migration, these paths have moved — or gone.

Old pathNow
sources[]editorial_source[] — credibility enum TRUSTED | VERIFIED | ENDORSED | UNVERIFIED
skills_config.broadcasterskills_config.newsroom
collaboration.versioncollaboration.editing_version
instances[]Hard-rejected since v0.3 — links and tellings model distribution instead
ai_enrichments[]Hard-rejected since v0.3.2 — generative output that publishes is an assets[] entry with provenance; claims about content are assertions[]

Extensions

The sanctioned escape hatch

Anything outside the canonical schema rides under payload.extensions["com.{vendor}.{field}"], where {vendor} is the reverse-DNS short form of the broadcaster or skill author. The namespace prevents collisions and keeps a clean upgrade path: anything promoted into the spec drops its prefix.

{
  "warning_id": "wrn-019536b1-0001",
  "skill_id":   "nbcu/editorial-standards",
  "severity":   "flag",
  "detail":     "Informal term 'cops' in headline.",
  "extensions": {
    "com.nbcu.citations": [
      { "source_id": "nbcu-style-guide-2026",
        "quote": "Use 'police' or 'officers'. Avoid 'cops' in headlines." }
    ],
    "com.nbcu.rationale": "Term is on the Standards informal-terms list."
  }
}
  • Consumers that don’t recognise an extension key must ignore it silently.
  • Vendor-specific enum values follow a different convention: x- plus the lowercase token, underscores preserved — x-graphics_pack, never x-GRAPHICS_PACK.
  • The reference implementation uses the hatch itself, for com.ibc-poc.capture_complete on delivery events.

Next: the topics these messages travel on →