Config + DB driven request-type registry
Context and Problem Statement
The broker is generic: it must support many request types across many clients without a code change or redeploy each time a new one is added. How are request types defined, validated, and authorized per client?
Decision Drivers
- Add a request type for a client without redeploying the services.
- Ship sensible defaults in source control.
- Validate required keys and authorize
(ClientId, RequestType)consistently in both services.
Considered Options
- Two-tier registry:
requestTypes.json(shipped defaults) overlaid by database rows (per-client) - JSON only โ every change is a redeploy
- Database only โ no in-repo defaults, harder to review/diff
Decision Outcome
Chosen option: two-tier registry. RequestTypeRegistry loads the JSON defaults, then overlays
active database RequestTypeDefinition rows; DB rows win on conflict, so a client-specific override
needs no redeploy. Lookup and authorization are case-insensitive on (ClientId, RequestType).
Consequences
- Good, because defaults are reviewable in source, while per-client changes are data, not deploys.
- Good, because one registry serves validation in the Queue and dispatch context in the Processor.
- Bad, because there are two sources of truth to reason about; precedence (DB > JSON) must be clear.
- Neutral, because hot-reload from the DB is possible but must be invoked explicitly.
Confirmation
RequestTypeRegistryTests covers JSON load, case-insensitive lookup, DB-overrides-JSON, and that
inactive DB rows are ignored.
More Information
Implementation note: the registry's Dictionary is constructed with the default comparer, but keys are
lowercased on both insert and lookup, so matching is effectively case-insensitive. A follow-up could
simplify this by using a proper case-insensitive tuple comparer and dropping the manual lowercasing.