Story: Codegen: generate NATS subject constants per component
Table of Contents
This page documents a story in Product backlog — inbox, carried unfinished from Sprint 24 at close. It captures the goal, current status, acceptance criteria, and the tasks that compose it.
1. Goal
Every NATS subject in the codebase today is a raw string literal,
independently typed in at least three places: the protocol struct's
nats_subject constant, the server-side registrar's queue_subscribe
call, and (for publish-from-dq subjects specifically) DQ metadata SQL
that registers a target_subject for an artefact type. Nothing checks
these agree.
This was not a hypothetical risk: the CRM story's DQ-publishing task
(publish named CRM bundles, PR #1543) registered
marketdata.v1.crm-topology-bundles.publish-from-dq as a new artefact
type's target_subject in SQL, added the corresponding SQL function,
but never added a matching queue_subscribe in
registrar.cpp nor allow-listed the new function in
publish_from_dq_handler.cpp's is_known_fn() – caught only by PR
review (four independent automated review passes all found it), not by
the build. Publishing that bundle would have hung/failed silently for
every party provisioned after merge.
Codegen should generate, per component, an API header
(ores.<component>.api/messaging/nats_subjects.hpp or similar) of
named constexpr subject constants for every NATS subject the
component owns – requests, events, publish-from-dq subjects – derived
from the same source-of-truth the protocol structs and DQ artefact-type
registrations already read from. Registrar/handler/client code
references the constant, never a literal; a subject typo or a missing
subscription becomes a compile error (unresolved symbol) or, at worst,
a single place to grep, not a silent runtime gap four LLM reviewers
have to independently rediscover.
2. Status
| Field | Value |
|---|---|
| State | BACKLOG |
| Carried from | Sprint 24 (unfinished at close) |
| Now | Not yet started. |
| Waiting on | Nothing. |
| Next | Break the story into tasks. |
| Last touched | 2026-07-21 |
3. Acceptance
- Codegen generates one API header per component listing every NATS
subject that component's protocol/request/event/publish-from-dq
facets define, as named
constexpr std::string_viewconstants (or equivalent). - Existing hand-written/codegen-generated registrar, handler, and client call sites are migrated to reference the generated constants instead of string literals, component by component – no leftover raw subject strings once a component is migrated.
- For publish-from-dq subjects specifically: the DQ artefact-type
target_subjectregistration and the constant codegen generates are both derived from the same single source (the entity/facet model), so they cannot drift apart the way this story's motivating bug did. - A missing subscription for a subject a component's own constants declare is at minimum easy to lint/grep for (ideally a build-time check), not something that only surfaces via manual/reviewer discovery at runtime.
4. Tasks
| Task | State | Start | End | Description |
|---|---|---|---|---|