CRUMB a card from devarno-cloud

NATS Subject Taxonomy

choco intermediate 4 min read

ELI5

Every event the factory emits goes onto a labelled conveyor belt. The label format is choco.events.<room>.<action>. If you want everything from the Fudge Room you subscribe to choco.events.coordination.>; if you only want conflict events you narrow it down.

Technical Deep Dive

Subject names are documented in the per-event proto comments under proto/events/<domain>/v1/*.proto. The pattern is choco.events.<domain>.<action>, with domain matching the proto package’s middle segment.

Domain Inventory

flowchart LR
subgraph streams["JetStream Streams"]
onb[choco:events:onboarding]
mon[choco:events:monetization]
coord[choco:events:coordination]
docu[choco:events:documentation]
hyd[choco:events:hydration]
ref[choco:events:refinement]
res[choco:events:resolution]
end
onb -->|onboarding.started, site.provision.*| C1[cho-co-web SSE]
mon -->|golden_ticket.issued| C2[airlock + choco-ledger]
coord -->|property_sync.*, conflict.*| C3[the-conch]
docu -->|page.generated, content.published| C4[choco-search, analytics]
hyd -->|hydration.*| C5[the-mould]
ref -->|slop_detected, smartblock_created| C6[choco-consumers]
res -->|tag_resolved, cross_repo_link_verified| C7[the-wrapper]

Ordering Disciplines

Two values appear in the Ordering: comment annotation across protos:

  • causally_ordered (per-aggregate) — OnboardingStarted and most domain events (onboarding/v1/lifecycle.proto:11). Order is preserved within one aggregate_id; cross-aggregate order is not guaranteed.
  • globally_orderedGoldenTicketIssued and GoldenTicketRedeemed (monetization/v1/golden.proto:51-52, :65-66). Backed by a single-writer constraint (advisory lock — see choco-008).

Subject ↔ Service Map

Each factory-equipment service owns one subject prefix:

ServiceSubject prefixSource
the-winnowerchoco.events.refinement.>services/the-winnower/README.md:9
the-conchchoco.events.coordination.>services/the-conch/README.md:9
the-mouldchoco.events.hydration.>services/the-mould/README.md:9
the-wrapperchoco.events.resolution.>services/the-wrapper/README.md:9

Retention

monetization events involving Golden Tickets carry Retention: infinite (golden.proto:52). Other domains do not declare retention in the proto and inherit the JetStream default configured at infrastructure time (not in this repo).

Key Terms

  • subject → NATS hierarchical topic name; dotted, single-token wildcard *, multi-token wildcard >.
  • stream → JetStream’s persisted, replayable view over one or more subjects.
  • aggregate ordering → events for the same aggregate_id are delivered in publish order; the proto’s Ordering: line is the contract.

Q&A

Q: Why is golden_ticket.issued globally_ordered instead of causally_ordered? A: The five-ticket cap is a system-wide invariant (golden.proto:53-54), so issuance must serialise across all writers — not just per-user.

Q: What does the wildcard > do? A: Matches the rest of the subject path (any depth). choco.events.coordination.> catches property_sync.started, conflict.detected, etc.

Q: Where is the literal subject string for OnboardingStarted defined? A: It is documented in the proto comment (Stream: choco:events:onboarding) but the actual nats.Publish(subject, ...) call lives in the producer service, not the proto.

Examples

the-conch subscribes to choco.events.coordination.> to consume sync requests, then re-publishes conflict.detected and conflict.resolved on the same prefix. Stream name uses colons (choco:events:coordination) per JetStream convention; subject names use dots.

neighbors on the map