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.

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.

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

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_view constants (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_subject registration 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.

Tasks

Task State Start End Description
         

Decisions

Out of scope

Emacs 29.3 (Org mode 9.6.15)