Build
Get started
Bring up a bus, publish a story, watch skills fire, approve one warning and reject another. Fifteen minutes, end to end.
Quick start
Two commands
The reference starter is a single .NET process hosting an executor, a dashboard and a story simulator, with a bundled broker alongside it.
cd som-hackathon-starter-dotnet # 1. the bus (plus a broker UI on :8080) docker compose up -d # 2. executor + dashboard on :5050 dotnet run
Prerequisites: the .NET 10 SDK and Docker. Topics auto-create on first publish in local mode.
- Open
http://localhost:5050— the websocket pill, top right, should read connected. - Click a seed-story button in the header to publish a
story.contextevent. - Watch the four lanes: stories → skill runs → pending approval → decisions.
- Approve or reject each staged warning to push it to
som.skills.eventsorsom.skills.rejected.
Verify
Sixty seconds to know it works
Connect
The dashboard’s websocket pill says connected. If it says reconnecting, the app is down — the page will re-attach itself once it’s back.
Publish
Click the Informal seed. A story lands in Stories on Bus and two style warnings appear in Pending Approval within a second or two.
Decide
Approve one and reject the other. Both show up in Decisions, and the bus event log at the bottom shows the full message trail.
The six seed stories each exercise a different combination of fields — a full compliance and gates set, a story with the compliance key absent at URGENT priority, informal headline terms, a clean story that should fire nothing at all, an election story on EDITORIAL_HOLD, and a hurricane story whose live feed transitions CAPTURING → CAPTURED.
Shell
The whole loop without the UI
B=http://localhost:5050
# publish a story (a live feed, still CAPTURING, open-ended range)
curl -X POST $B/api/publish/hurricane
# see what's waiting on the gate
curl $B/api/pending
# decide
curl -X POST $B/api/decision/<warning_id> \
-H 'Content-Type: application/json' \
-d '{"decision":"approve","reviewer":"me"}'Endpoint paths belong to the reference implementation, not to SOM itself — the standard defines messages, not an HTTP API. Check the starter’s README for the current list.
Media
Drive a TAMS arrival
The mock MAM plays the store; the media coordinator plays the consuming participant. Two arrivals show both halves of the contract.
# a rolling arrival — noted, no story change
curl -X POST $B/api/mam/emit/landfall-feed-01 \
-H 'Content-Type: application/json' -d '{"timeRange":"[0:0_30:0)"}'
# the final one — the asset flips CAPTURING → CAPTURED,
# skills re-run, and an inform lands in Pending Approval
curl -X POST $B/api/mam/emit/landfall-feed-01 \
-H 'Content-Type: application/json' -d '{"captureComplete":true}'
# the safe-state path — media no story references
curl -X POST $B/api/mam/emit/ugc-flood-77aa41b0 # → WITHHELD on som.system.audit“I emitted the clip and nothing happened.” If it matched no story, that is the result — look for the WITHHELD record on the audit topic. By design, no story is created.
“The final emit didn’t flip the asset.” Either the story isn’t on the bus yet — publish the seed first, since the coordinator only re-checks for about a second — or the asset is already CAPTURED.
Where next
Pick your path
Write a skill
One JSON file, seven rule types, three validation layers. No C# required.
Skill anatomy →Publish stories
Copy a seed envelope and keep the five envelope rules. It is the exact wire shape.
Envelope reference →Join as a consumer
Anything that speaks the bus and JSON can participate — in any language, in its own process.
Roles & topics →The schemas win. When any prose — this site included — disagrees with a vendored JSON Schema, the schema is right. Validate candidate payloads against the shipped examples before you publish them. Browse the schema pack ↗