@onlineapps/conn-orch-registry 6.0.2 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/API.md ADDED
@@ -0,0 +1,831 @@
1
+ ## Modules
2
+
3
+ <dl>
4
+ <dt><a href="#module_@onlineapps/conn-orch-registry/src/events">@onlineapps/conn-orch-registry/src/events</a></dt>
5
+ <dd><p>events.js</p>
6
+ <p>List of events used in the conn-orch-registry module.
7
+ Acts as a central place for constants to avoid typos
8
+ when emitting and listening for events.</p>
9
+ <p>Legacy <code>apiDescriptionRequest</code> / <code>apiDescriptionSent</code> events were removed —
10
+ the full service specification travels as part of the <code>register</code> message.</p>
11
+ </dd>
12
+ <dt><a href="#module_@onlineapps/conn-orch-registry">@onlineapps/conn-orch-registry</a></dt>
13
+ <dd><p>Service registry connector for dynamic service discovery, health monitoring,
14
+ and OpenAPI specification management in OA Drive microservices architecture.</p>
15
+ </dd>
16
+ <dt><a href="#module_@onlineapps/conn-orch-registry/src/queueManager">@onlineapps/conn-orch-registry/src/queueManager</a></dt>
17
+ <dd><p>queueManager.js</p>
18
+ <p>The one MQ connection of the registry connector, and the only surface through
19
+ which this package talks to the broker.</p>
20
+ <p>Overview:</p>
21
+ <ul>
22
+ <li>Owns a single <code>@onlineapps/mq-client-core</code> client: connect, declare,
23
+ publish, consume, close.</li>
24
+ <li>Queues managed by the microservice: <code>&lt;serviceName&gt;.registry</code> and
25
+ <code>&lt;serviceName&gt;.registry.events</code>. Their names are business-queue names and
26
+ their DECLARATION (durability, TTL, dead-letter route) belongs to
27
+ <code>queueConfig</code> in the core — never to an options object written here.</li>
28
+ <li>Infrastructure queues (<code>registry.register</code>, …) are CHECKED, never
29
+ asserted: they are created by the infrastructure service that owns them
30
+ (<code>api/docs/standards/queue-ownership.md</code>).</li>
31
+ </ul>
32
+ <p>Why there is no <code>channel</code> on this object any more (d.198b-3): until 2026-09-14
33
+ this class handed out a raw amqplib channel, and both consumers of the package
34
+ settled every delivery on it by hand — <code>channel.ack(msg)</code> / <code>channel.nack(msg, false, false)</code>. That is a second implementation of the delivery contract
35
+ (<code>.claude/rules/change-discipline.md</code> § One rail per concern) and the half that
36
+ cannot count: a hand-written nack knows nothing about the attempt budget, the
37
+ <code>x-oa-delivery-attempts</code> header or the <code>message_dlq</code> event the core publishes.
38
+ <code>consume()</code> below forwards to the core&#39;s, which owns all three.</p>
39
+ <p>Usage:
40
+ const qm = new QueueManager(amqpUrl, serviceName, logger);
41
+ await qm.init();
42
+ await qm.consume(<code>${serviceName}.registry</code>, handler, { requeueOnError: false });</p>
43
+ </dd>
44
+ <dt><a href="#module_@onlineapps/conn-orch-registry/src/registryClient">@onlineapps/conn-orch-registry/src/registryClient</a></dt>
45
+ <dd><p>registryClient.js</p>
46
+ <p>ServiceRegistryClient for communication between a microservice (via Agent)
47
+ and the central registry. Sends the service&#39;s <code>operations</code> map in the
48
+ <code>register</code> message and periodic heartbeat messages. Receives registration
49
+ responses (register.confirmed / register.rejected) and revalidation requests
50
+ from the registry.</p>
51
+ <p>Legacy <code>apiDescription</code> / <code>apiDescriptionRequest</code> round-trips have been
52
+ removed — what the registry validates travels in the <code>register</code> message
53
+ itself, as <code>operations</code> (schema-v3). The <code>spec</code> key that used to carry an
54
+ OpenAPI document beside it left in d.562: nothing ever read it.</p>
55
+ <p>Uses QueueManager to manage AMQP queues. Emits events through EventEmitter.</p>
56
+ <p>Events (see src/events.js):</p>
57
+ <ul>
58
+ <li>&#39;heartbeatSent&#39;</li>
59
+ <li>&#39;revalidate&#39;</li>
60
+ <li>&#39;registerConfirmed&#39;</li>
61
+ <li>&#39;registerRejected&#39;</li>
62
+ <li>&#39;error&#39;</li>
63
+ </ul>
64
+ </dd>
65
+ <dt><a href="#module_@onlineapps/conn-orch-registry/src/registryEventConsumer">@onlineapps/conn-orch-registry/src/registryEventConsumer</a></dt>
66
+ <dd><p>registryEventConsumer.js</p>
67
+ <p>Extension for ServiceRegistryClient to consume registry change events.
68
+ Implements opt-in subscription to registry.changes exchange.
69
+ Maintains local service index and enables lazy loading of specs.</p>
70
+ </dd>
71
+ </dl>
72
+
73
+ <a name="module_@onlineapps/conn-orch-registry/src/events"></a>
74
+
75
+ ## @onlineapps/conn-orch-registry/src/events
76
+ events.js
77
+
78
+ List of events used in the conn-orch-registry module.
79
+ Acts as a central place for constants to avoid typos
80
+ when emitting and listening for events.
81
+
82
+ Legacy `apiDescriptionRequest` / `apiDescriptionSent` events were removed —
83
+ the full service specification travels as part of the `register` message.
84
+
85
+ **See**: api/docs/biz/30-operations/registration-wire.md §2 MQ wire format
86
+
87
+ * [@onlineapps/conn-orch-registry/src/events](#module_@onlineapps/conn-orch-registry/src/events)
88
+ * [~EVENTS](#module_@onlineapps/conn-orch-registry/src/events..EVENTS)
89
+ * [.HEARTBEAT_SENT](#module_@onlineapps/conn-orch-registry/src/events..EVENTS.HEARTBEAT_SENT)
90
+ * [.REGISTER_CONFIRMED](#module_@onlineapps/conn-orch-registry/src/events..EVENTS.REGISTER_CONFIRMED)
91
+ * [.REGISTER_REJECTED](#module_@onlineapps/conn-orch-registry/src/events..EVENTS.REGISTER_REJECTED)
92
+ * [.REVALIDATE](#module_@onlineapps/conn-orch-registry/src/events..EVENTS.REVALIDATE)
93
+ * [.ERROR](#module_@onlineapps/conn-orch-registry/src/events..EVENTS.ERROR)
94
+
95
+ <a name="module_@onlineapps/conn-orch-registry/src/events..EVENTS"></a>
96
+
97
+ ### @onlineapps/conn-orch-registry/src/events~EVENTS
98
+ Named EventEmitter events for ServiceRegistryClient.
99
+
100
+ **Kind**: inner constant of [<code>@onlineapps/conn-orch-registry/src/events</code>](#module_@onlineapps/conn-orch-registry/src/events)
101
+
102
+ * [~EVENTS](#module_@onlineapps/conn-orch-registry/src/events..EVENTS)
103
+ * [.HEARTBEAT_SENT](#module_@onlineapps/conn-orch-registry/src/events..EVENTS.HEARTBEAT_SENT)
104
+ * [.REGISTER_CONFIRMED](#module_@onlineapps/conn-orch-registry/src/events..EVENTS.REGISTER_CONFIRMED)
105
+ * [.REGISTER_REJECTED](#module_@onlineapps/conn-orch-registry/src/events..EVENTS.REGISTER_REJECTED)
106
+ * [.REVALIDATE](#module_@onlineapps/conn-orch-registry/src/events..EVENTS.REVALIDATE)
107
+ * [.ERROR](#module_@onlineapps/conn-orch-registry/src/events..EVENTS.ERROR)
108
+
109
+ <a name="module_@onlineapps/conn-orch-registry/src/events..EVENTS.HEARTBEAT_SENT"></a>
110
+
111
+ #### EVENTS.HEARTBEAT\_SENT
112
+ Emitted after a successful heartbeat is sent. Payload: { id, type, serviceName, version, timestamp }
113
+
114
+ **Kind**: static property of [<code>EVENTS</code>](#module_@onlineapps/conn-orch-registry/src/events..EVENTS)
115
+ <a name="module_@onlineapps/conn-orch-registry/src/events..EVENTS.REGISTER_CONFIRMED"></a>
116
+
117
+ #### EVENTS.REGISTER\_CONFIRMED
118
+ Emitted when the registry confirms a successful registration. Payload: { requestId, certificate, ... }
119
+
120
+ **Kind**: static property of [<code>EVENTS</code>](#module_@onlineapps/conn-orch-registry/src/events..EVENTS)
121
+ <a name="module_@onlineapps/conn-orch-registry/src/events..EVENTS.REGISTER_REJECTED"></a>
122
+
123
+ #### EVENTS.REGISTER\_REJECTED
124
+ Emitted when the registry rejects a registration. Payload: { requestId, reason, errors, ... }
125
+
126
+ **Kind**: static property of [<code>EVENTS</code>](#module_@onlineapps/conn-orch-registry/src/events..EVENTS)
127
+ <a name="module_@onlineapps/conn-orch-registry/src/events..EVENTS.REVALIDATE"></a>
128
+
129
+ #### EVENTS.REVALIDATE
130
+ Emitted when the registry asks the service to revalidate (e.g. infra fingerprint change).
131
+
132
+ **Kind**: static property of [<code>EVENTS</code>](#module_@onlineapps/conn-orch-registry/src/events..EVENTS)
133
+ <a name="module_@onlineapps/conn-orch-registry/src/events..EVENTS.ERROR"></a>
134
+
135
+ #### EVENTS.ERROR
136
+ Emitted on internal errors. Payload: Error instance or error description.
137
+
138
+ **Kind**: static property of [<code>EVENTS</code>](#module_@onlineapps/conn-orch-registry/src/events..EVENTS)
139
+ <a name="module_@onlineapps/conn-orch-registry"></a>
140
+
141
+ ## @onlineapps/conn-orch-registry
142
+ Service registry connector for dynamic service discovery, health monitoring,
143
+ and OpenAPI specification management in OA Drive microservices architecture.
144
+
145
+ **Since**: 1.0.0
146
+ **Author**: OA Drive Team
147
+ **License**: MIT
148
+
149
+ * [@onlineapps/conn-orch-registry](#module_@onlineapps/conn-orch-registry)
150
+ * [.ServiceRegistryClient](#module_@onlineapps/conn-orch-registry.ServiceRegistryClient) : <code>function</code>
151
+ * [.RegistryEventConsumer](#module_@onlineapps/conn-orch-registry.RegistryEventConsumer) : <code>function</code>
152
+ * [.EVENTS](#module_@onlineapps/conn-orch-registry.EVENTS) : <code>Object</code>
153
+
154
+ <a name="module_@onlineapps/conn-orch-registry.ServiceRegistryClient"></a>
155
+
156
+ ### @onlineapps/conn-orch-registry.ServiceRegistryClient : <code>function</code>
157
+ Class for registering a service and sending heartbeats to the central registry.
158
+
159
+ **Kind**: static property of [<code>@onlineapps/conn-orch-registry</code>](#module_@onlineapps/conn-orch-registry)
160
+ <a name="module_@onlineapps/conn-orch-registry.RegistryEventConsumer"></a>
161
+
162
+ ### @onlineapps/conn-orch-registry.RegistryEventConsumer : <code>function</code>
163
+ Class for consuming registry change events (opt-in).
164
+
165
+ **Kind**: static property of [<code>@onlineapps/conn-orch-registry</code>](#module_@onlineapps/conn-orch-registry)
166
+ <a name="module_@onlineapps/conn-orch-registry.EVENTS"></a>
167
+
168
+ ### @onlineapps/conn-orch-registry.EVENTS : <code>Object</code>
169
+ Constant containing the list of events emitted by ServiceRegistryClient.
170
+
171
+ **Kind**: static property of [<code>@onlineapps/conn-orch-registry</code>](#module_@onlineapps/conn-orch-registry)
172
+ <a name="module_@onlineapps/conn-orch-registry/src/queueManager"></a>
173
+
174
+ ## @onlineapps/conn-orch-registry/src/queueManager
175
+ queueManager.js
176
+
177
+ The one MQ connection of the registry connector, and the only surface through
178
+ which this package talks to the broker.
179
+
180
+ Overview:
181
+ - Owns a single `@onlineapps/mq-client-core` client: connect, declare,
182
+ publish, consume, close.
183
+ - Queues managed by the microservice: `<serviceName>.registry` and
184
+ `<serviceName>.registry.events`. Their names are business-queue names and
185
+ their DECLARATION (durability, TTL, dead-letter route) belongs to
186
+ `queueConfig` in the core — never to an options object written here.
187
+ - Infrastructure queues (`registry.register`, …) are CHECKED, never
188
+ asserted: they are created by the infrastructure service that owns them
189
+ (`api/docs/standards/queue-ownership.md`).
190
+
191
+ Why there is no `channel` on this object any more (d.198b-3): until 2026-09-14
192
+ this class handed out a raw amqplib channel, and both consumers of the package
193
+ settled every delivery on it by hand — `channel.ack(msg)` / `channel.nack(msg,
194
+ false, false)`. That is a second implementation of the delivery contract
195
+ (`.claude/rules/change-discipline.md` § One rail per concern) and the half that
196
+ cannot count: a hand-written nack knows nothing about the attempt budget, the
197
+ `x-oa-delivery-attempts` header or the `message_dlq` event the core publishes.
198
+ `consume()` below forwards to the core's, which owns all three.
199
+
200
+ Usage:
201
+ const qm = new QueueManager(amqpUrl, serviceName, logger);
202
+ await qm.init();
203
+ await qm.consume(`${serviceName}.registry`, handler, { requeueOnError: false });
204
+
205
+ **See**: node_modules/@onlineapps/mq-client-core/README.md § `consume()` — the delivery contract
206
+
207
+ * [@onlineapps/conn-orch-registry/src/queueManager](#module_@onlineapps/conn-orch-registry/src/queueManager)
208
+ * [~QueueManager](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager)
209
+ * [new QueueManager(amqpUrl, serviceName, logger)](#new_module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager_new)
210
+ * [.init()](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+init) ⇒ <code>Promise.&lt;void&gt;</code>
211
+ * [.isConnected()](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+isConnected) ⇒ <code>boolean</code>
212
+ * [.ensureQueues([queues])](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+ensureQueues) ⇒ <code>Promise.&lt;void&gt;</code>
213
+ * [.checkQueue(queue)](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+checkQueue) ⇒ <code>Promise.&lt;Object&gt;</code>
214
+ * [.assertExchange(exchange, type, [options])](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+assertExchange) ⇒ <code>Promise.&lt;Object&gt;</code>
215
+ * [.bindQueue(queue, exchange, pattern)](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+bindQueue) ⇒ <code>Promise.&lt;Object&gt;</code>
216
+ * [.publish(queue, message, [options])](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+publish) ⇒ <code>Promise.&lt;void&gt;</code>
217
+ * [.consume(queue, handler, [options])](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+consume) ⇒ <code>Promise.&lt;string&gt;</code>
218
+ * [.close()](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+close) ⇒ <code>Promise.&lt;void&gt;</code>
219
+
220
+ <a name="module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager"></a>
221
+
222
+ ### @onlineapps/conn-orch-registry/src/queueManager~QueueManager
223
+ Queue manager for the microservice connector.
224
+
225
+ **Kind**: inner class of [<code>@onlineapps/conn-orch-registry/src/queueManager</code>](#module_@onlineapps/conn-orch-registry/src/queueManager)
226
+
227
+ * [~QueueManager](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager)
228
+ * [new QueueManager(amqpUrl, serviceName, logger)](#new_module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager_new)
229
+ * [.init()](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+init) ⇒ <code>Promise.&lt;void&gt;</code>
230
+ * [.isConnected()](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+isConnected) ⇒ <code>boolean</code>
231
+ * [.ensureQueues([queues])](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+ensureQueues) ⇒ <code>Promise.&lt;void&gt;</code>
232
+ * [.checkQueue(queue)](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+checkQueue) ⇒ <code>Promise.&lt;Object&gt;</code>
233
+ * [.assertExchange(exchange, type, [options])](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+assertExchange) ⇒ <code>Promise.&lt;Object&gt;</code>
234
+ * [.bindQueue(queue, exchange, pattern)](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+bindQueue) ⇒ <code>Promise.&lt;Object&gt;</code>
235
+ * [.publish(queue, message, [options])](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+publish) ⇒ <code>Promise.&lt;void&gt;</code>
236
+ * [.consume(queue, handler, [options])](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+consume) ⇒ <code>Promise.&lt;string&gt;</code>
237
+ * [.close()](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+close) ⇒ <code>Promise.&lt;void&gt;</code>
238
+
239
+ <a name="new_module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager_new"></a>
240
+
241
+ #### new QueueManager(amqpUrl, serviceName, logger)
242
+
243
+ | Param | Type | Description |
244
+ | --- | --- | --- |
245
+ | amqpUrl | <code>string</code> | RabbitMQ server URL (AMQP URI) |
246
+ | serviceName | <code>string</code> | Name of the microservice (e.g. 'invoicing') |
247
+ | logger | <code>Object</code> | Logger with info/warn/error/debug; required, validated here (docs/governance/confirmations/connector-logger-contract.md 001) |
248
+
249
+ <a name="module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+init"></a>
250
+
251
+ #### queueManager.init() ⇒ <code>Promise.&lt;void&gt;</code>
252
+ Opens the connection to RabbitMQ.
253
+
254
+ **Kind**: instance method of [<code>QueueManager</code>](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager)
255
+ **Throws**:
256
+
257
+ - <code>Error</code> If connecting fails; the message names the broker without its credential.
258
+
259
+ <a name="module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+isConnected"></a>
260
+
261
+ #### queueManager.isConnected() ⇒ <code>boolean</code>
262
+ Is the broker connection open? The one question `register()` asks before it
263
+ publishes; a closed client is not reusable.
264
+
265
+ **Kind**: instance method of [<code>QueueManager</code>](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager)
266
+ <a name="module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+ensureQueues"></a>
267
+
268
+ #### queueManager.ensureQueues([queues]) ⇒ <code>Promise.&lt;void&gt;</code>
269
+ Declares the business queues this service owns.
270
+
271
+ The declaration — durability, TTL, cap, dead-letter route — comes from
272
+ `queueConfig` inside the core and is never written here: a name the central
273
+ config declares carries no caller options, and asserting one with arguments
274
+ of our own is how a queue ends up declared two different ways and the broker
275
+ answers the second declarer `406 PRECONDITION-FAILED`.
276
+
277
+ **Kind**: instance method of [<code>QueueManager</code>](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager)
278
+ **Throws**:
279
+
280
+ - <code>Error</code> If a name is an infrastructure queue, or the broker refuses the declaration.
281
+
282
+
283
+ | Param | Type | Default | Description |
284
+ | --- | --- | --- | --- |
285
+ | [queues] | <code>Array.&lt;string&gt;</code> | <code>[]</code> | Business queue names owned by this service |
286
+
287
+ <a name="module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+checkQueue"></a>
288
+
289
+ #### queueManager.checkQueue(queue) ⇒ <code>Promise.&lt;Object&gt;</code>
290
+ Confirms an infrastructure queue exists without creating it.
291
+
292
+ **Kind**: instance method of [<code>QueueManager</code>](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager)
293
+ **Returns**: <code>Promise.&lt;Object&gt;</code> - The broker's `queue.declare-ok`
294
+
295
+ | Param | Type | Description |
296
+ | --- | --- | --- |
297
+ | queue | <code>string</code> | Queue name |
298
+
299
+ <a name="module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+assertExchange"></a>
300
+
301
+ #### queueManager.assertExchange(exchange, type, [options]) ⇒ <code>Promise.&lt;Object&gt;</code>
302
+ Declares an exchange this package binds to.
303
+
304
+ **Kind**: instance method of [<code>QueueManager</code>](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager)
305
+
306
+ | Param | Type | Description |
307
+ | --- | --- | --- |
308
+ | exchange | <code>string</code> | Exchange name |
309
+ | type | <code>string</code> | Exchange type; required, never guessed |
310
+ | [options] | <code>Object</code> | Exchange options |
311
+
312
+ <a name="module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+bindQueue"></a>
313
+
314
+ #### queueManager.bindQueue(queue, exchange, pattern) ⇒ <code>Promise.&lt;Object&gt;</code>
315
+ Binds one of this service's queues to an exchange.
316
+
317
+ **Kind**: instance method of [<code>QueueManager</code>](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager)
318
+
319
+ | Param | Type | Description |
320
+ | --- | --- | --- |
321
+ | queue | <code>string</code> | |
322
+ | exchange | <code>string</code> | |
323
+ | pattern | <code>string</code> | Routing pattern; `''` is legal for a fanout |
324
+
325
+ <a name="module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+publish"></a>
326
+
327
+ #### queueManager.publish(queue, message, [options]) ⇒ <code>Promise.&lt;void&gt;</code>
328
+ Publishes one message.
329
+
330
+ **Kind**: instance method of [<code>QueueManager</code>](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager)
331
+ **Returns**: <code>Promise.&lt;void&gt;</code> - Resolves when published; THROWS on failure — there is no falsy return
332
+
333
+ | Param | Type | Description |
334
+ | --- | --- | --- |
335
+ | queue | <code>string</code> | Target queue (or the exchange's name when `options.exchange` is set) |
336
+ | message | <code>Object</code> | Payload; serialized by the core |
337
+ | [options] | <code>Object</code> | `persistent`, `exchange`, `routingKey`, `headers` |
338
+
339
+ <a name="module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+consume"></a>
340
+
341
+ #### queueManager.consume(queue, handler, [options]) ⇒ <code>Promise.&lt;string&gt;</code>
342
+ Attaches a consumer on the core's delivery rail.
343
+
344
+ The handler reports failure by THROWING. Settling is the core's: a handler
345
+ that returns is acked once, a handler that throws is counted against the
346
+ delivery budget and, when the budget is spent, rejected into `<service>.dlq`
347
+ with a `message_dlq` event.
348
+
349
+ **Kind**: instance method of [<code>QueueManager</code>](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager)
350
+ **Returns**: <code>Promise.&lt;string&gt;</code> - The broker's consumer tag
351
+
352
+ | Param | Type | Description |
353
+ | --- | --- | --- |
354
+ | queue | <code>string</code> | |
355
+ | handler | <code>function</code> | |
356
+ | [options] | <code>Object</code> | `requeueOnError`, `maxAttempts`, `classify`, `prefetch` |
357
+
358
+ <a name="module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager+close"></a>
359
+
360
+ #### queueManager.close() ⇒ <code>Promise.&lt;void&gt;</code>
361
+ Closes the connection.
362
+
363
+ **Kind**: instance method of [<code>QueueManager</code>](#module_@onlineapps/conn-orch-registry/src/queueManager..QueueManager)
364
+ <a name="module_@onlineapps/conn-orch-registry/src/registryClient"></a>
365
+
366
+ ## @onlineapps/conn-orch-registry/src/registryClient
367
+ registryClient.js
368
+
369
+ ServiceRegistryClient for communication between a microservice (via Agent)
370
+ and the central registry. Sends the service's `operations` map in the
371
+ `register` message and periodic heartbeat messages. Receives registration
372
+ responses (register.confirmed / register.rejected) and revalidation requests
373
+ from the registry.
374
+
375
+ Legacy `apiDescription` / `apiDescriptionRequest` round-trips have been
376
+ removed — what the registry validates travels in the `register` message
377
+ itself, as `operations` (schema-v3). The `spec` key that used to carry an
378
+ OpenAPI document beside it left in d.562: nothing ever read it.
379
+
380
+ Uses QueueManager to manage AMQP queues. Emits events through EventEmitter.
381
+
382
+ Events (see src/events.js):
383
+ - 'heartbeatSent'
384
+ - 'revalidate'
385
+ - 'registerConfirmed'
386
+ - 'registerRejected'
387
+ - 'error'
388
+
389
+ **See**
390
+
391
+ - api/docs/biz/30-operations/registration-wire.md §2 MQ wire format
392
+ - api/docs/biz/30-operations/schema-v3.md
393
+
394
+
395
+ * [@onlineapps/conn-orch-registry/src/registryClient](#module_@onlineapps/conn-orch-registry/src/registryClient)
396
+ * [~ServiceRegistryClient](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient)
397
+ * [new ServiceRegistryClient(opts)](#new_module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient_new)
398
+ * [.init()](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+init) ⇒ <code>Promise.&lt;void&gt;</code>
399
+ * [.register(serviceInfo)](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+register) ⇒ <code>Promise.&lt;{success: boolean, message: string, serviceName: string, version: string, registrationId: (string\|undefined), validated: boolean, certificate: (Object\|null), errorCode: (string\|null\|undefined)}&gt;</code>
400
+ * [.deregister()](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+deregister) ⇒ <code>Promise.&lt;{requestId: string, serviceName: string, version: string, publishedTo: string, heartbeatStopped: boolean, publishedAt: string}&gt;</code>
401
+ * [.unregister()](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+unregister) ⇒ <code>Promise.&lt;Object&gt;</code>
402
+ * [.sendHeartbeat()](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+sendHeartbeat) ⇒ <code>Promise.&lt;void&gt;</code>
403
+ * [.startHeartbeat(options)](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+startHeartbeat)
404
+ * [.stopHeartbeat()](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+stopHeartbeat)
405
+ * [.subscribeToChanges()](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+subscribeToChanges) ⇒ <code>Promise.&lt;void&gt;</code>
406
+ * [.getService(serviceName)](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+getService) ⇒ <code>Promise.&lt;(ServiceSummary\|null)&gt;</code>
407
+ * [.close()](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+close) ⇒ <code>Promise.&lt;void&gt;</code>
408
+ * [~RETIRED_SERVICE_INFO_KEYS](#module_@onlineapps/conn-orch-registry/src/registryClient..RETIRED_SERVICE_INFO_KEYS)
409
+ * [~ACCEPTED_SERVICE_INFO_KEYS](#module_@onlineapps/conn-orch-registry/src/registryClient..ACCEPTED_SERVICE_INFO_KEYS)
410
+ * [~ServiceSummary](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceSummary) : <code>Object</code>
411
+
412
+ <a name="module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient"></a>
413
+
414
+ ### @onlineapps/conn-orch-registry/src/registryClient~ServiceRegistryClient
415
+ **Kind**: inner class of [<code>@onlineapps/conn-orch-registry/src/registryClient</code>](#module_@onlineapps/conn-orch-registry/src/registryClient)
416
+
417
+ * [~ServiceRegistryClient](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient)
418
+ * [new ServiceRegistryClient(opts)](#new_module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient_new)
419
+ * [.init()](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+init) ⇒ <code>Promise.&lt;void&gt;</code>
420
+ * [.register(serviceInfo)](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+register) ⇒ <code>Promise.&lt;{success: boolean, message: string, serviceName: string, version: string, registrationId: (string\|undefined), validated: boolean, certificate: (Object\|null), errorCode: (string\|null\|undefined)}&gt;</code>
421
+ * [.deregister()](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+deregister) ⇒ <code>Promise.&lt;{requestId: string, serviceName: string, version: string, publishedTo: string, heartbeatStopped: boolean, publishedAt: string}&gt;</code>
422
+ * [.unregister()](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+unregister) ⇒ <code>Promise.&lt;Object&gt;</code>
423
+ * [.sendHeartbeat()](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+sendHeartbeat) ⇒ <code>Promise.&lt;void&gt;</code>
424
+ * [.startHeartbeat(options)](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+startHeartbeat)
425
+ * [.stopHeartbeat()](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+stopHeartbeat)
426
+ * [.subscribeToChanges()](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+subscribeToChanges) ⇒ <code>Promise.&lt;void&gt;</code>
427
+ * [.getService(serviceName)](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+getService) ⇒ <code>Promise.&lt;(ServiceSummary\|null)&gt;</code>
428
+ * [.close()](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+close) ⇒ <code>Promise.&lt;void&gt;</code>
429
+
430
+ <a name="new_module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient_new"></a>
431
+
432
+ #### new ServiceRegistryClient(opts)
433
+
434
+ | Param | Type | Default | Description |
435
+ | --- | --- | --- | --- |
436
+ | opts | <code>Object</code> | | |
437
+ | opts.amqpUrl | <code>string</code> | | AMQP URI for connecting to RabbitMQ |
438
+ | opts.serviceName | <code>string</code> | | Name of the service (e.g., 'invoicing') |
439
+ | opts.version | <code>string</code> | | Version of the service (e.g., '1.2.0') |
440
+ | opts.specificationEndpoint | <code>string</code> | | Path the `register` and `heartbeat` messages carry. REQUIRED: the wire format declares it required (api/docs/biz/30-operations/registration-wire.md §2.1) and the registry stores what it is sent, so a default here would write a path nobody configured into `registry:services`. |
441
+ | opts.heartbeatInterval | <code>number</code> | | Milliseconds between heartbeats. REQUIRED: the cadence has ONE owner and it is not a library default (owner confirmation docs/governance/confirmations/biz-health-freshness.md 001 point 3); ServiceWrapper passes `wrapper.registry.heartbeatInterval`, itself fed from BIZ_HEARTBEAT_INTERVAL_MS. |
442
+ | [opts.apiQueue] | <code>string</code> | <code>&quot;&#x27;api_services_queuer&#x27;&quot;</code> | Queue name for heartbeat and API traffic |
443
+ | [opts.registryQueue] | <code>string</code> | <code>&quot;&#x27;registry.register&#x27;&quot;</code> | Queue name for registry messages |
444
+ | [opts.validationProof] | <code>Object</code> | <code></code> | Validation proof object {hash, data} (injected from outside) |
445
+ | [opts.registrationTimeoutMs] | <code>number</code> | | How long register() waits for the registry response before rejecting. Default comes from ./defaults.js (30000 ms); never read from the environment here. |
446
+ | opts.logger | <code>Object</code> | | Logger with info/warn/error/debug. Required and validated here: registration, heartbeat and revalidation events are what this client exists to report, and until 2026-09-05 they went to stdout through bare printing while this parameter was accepted and never read. Owner confirmation: docs/governance/confirmations/connector-logger-contract.md 001 + 002. |
447
+
448
+ <a name="module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+init"></a>
449
+
450
+ #### serviceRegistryClient.init() ⇒ <code>Promise.&lt;void&gt;</code>
451
+ Initializes the connection, ensures queues exist, and starts consuming the service response queue.
452
+
453
+ **Kind**: instance method of [<code>ServiceRegistryClient</code>](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient)
454
+ <a name="module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+register"></a>
455
+
456
+ #### serviceRegistryClient.register(serviceInfo) ⇒ <code>Promise.&lt;{success: boolean, message: string, serviceName: string, version: string, registrationId: (string\|undefined), validated: boolean, certificate: (Object\|null), errorCode: (string\|null\|undefined)}&gt;</code>
457
+ Registers the service with the registry.
458
+ Registry will validate if the service is properly tested and valid.
459
+ Upon successful validation, the service will be activated and can start heartbeats.
460
+
461
+ **Kind**: instance method of [<code>ServiceRegistryClient</code>](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient)
462
+ **Returns**: <code>Promise.&lt;{success: boolean, message: string, serviceName: string, version: string, registrationId: (string\|undefined), validated: boolean, certificate: (Object\|null), errorCode: (string\|null\|undefined)}&gt;</code> - The registry verdict. `errorCode` is the
463
+ registry's machine reason for a refusal (`UNDECLARED_SERVICE`,
464
+ `INVALID_OPERATIONS_SCHEMA`, `VALIDATOR_UNAVAILABLE`, …) — branch on it rather
465
+ than on `message`, whose wording is not a contract. It is passed through
466
+ verbatim: `null` on a confirmed registration, `undefined` when the reply
467
+ carried no code at all.
468
+ **See**: api/docs/biz/30-operations/registration-wire.md §8
469
+
470
+ | Param | Type | Description |
471
+ | --- | --- | --- |
472
+ | serviceInfo | <code>Object</code> | Service registration information. It accepts EXACTLY the keys below (`ACCEPTED_SERVICE_INFO_KEYS`) — any other key is refused by name, and a retired one (`RETIRED_SERVICE_INFO_KEYS`) with the reason it went. Nothing is dropped in silence: a key this call ignored would leave the caller believing it travelled. |
473
+ | [serviceInfo.endpoints] | <code>Array</code> | API endpoints provided by the service; `[]` for v3 services |
474
+ | [serviceInfo.operations] | <code>Object</code> | The complete `operations` map the registry validates |
475
+ | [serviceInfo.metadata] | <code>Object</code> | `{ version, description }` stored beside the spec |
476
+ | [serviceInfo.health] | <code>string</code> | Legacy health path; liveness travels by heartbeat |
477
+ | [serviceInfo.workspaceScoped] | <code>boolean</code> | Emitted only when the service declares it |
478
+ | [serviceInfo.timeout] | <code>number</code> | How long THIS call waits for the registry verdict (default: the constructor's registrationTimeoutMs). It reaches no message. |
479
+
480
+ <a name="module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+deregister"></a>
481
+
482
+ #### serviceRegistryClient.deregister() ⇒ <code>Promise.&lt;{requestId: string, serviceName: string, version: string, publishedTo: string, heartbeatStopped: boolean, publishedAt: string}&gt;</code>
483
+ Deregisters the service from the registry.
484
+
485
+ The registry sends NO reply to a `deregister`
486
+ (api/docs/biz/30-operations/registration-wire.md §2.3 — `processDeregistration`
487
+ removes the record and publishes `service.deregistered` to monitoring), so
488
+ there is no verdict to report and none is invented. Until d.278c this method
489
+ answered a hardcoded `{ success: true, message: 'Service deregistered
490
+ successfully' }` whatever happened — a claim about the registry made by the
491
+ one party that never heard from it.
492
+
493
+ What this call knows, and therefore what it returns: the request it published,
494
+ where it published it, and that the heartbeat timer is stopped. A publish that
495
+ fails REJECTS; reaching the return means the broker took the message.
496
+
497
+ **Kind**: instance method of [<code>ServiceRegistryClient</code>](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient)
498
+ <a name="module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+unregister"></a>
499
+
500
+ #### serviceRegistryClient.unregister() ⇒ <code>Promise.&lt;Object&gt;</code>
501
+ Alias for deregister() - used by ServiceWrapper.shutdown()
502
+
503
+ **Kind**: instance method of [<code>ServiceRegistryClient</code>](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient)
504
+ **Returns**: <code>Promise.&lt;Object&gt;</code> - Deregistration result
505
+ <a name="module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+sendHeartbeat"></a>
506
+
507
+ #### serviceRegistryClient.sendHeartbeat() ⇒ <code>Promise.&lt;void&gt;</code>
508
+ Sends a heartbeat message to the API queue.
509
+ Should be called only after successful registration.
510
+ Emits 'heartbeatSent'.
511
+
512
+ **Kind**: instance method of [<code>ServiceRegistryClient</code>](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient)
513
+ <a name="module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+startHeartbeat"></a>
514
+
515
+ #### serviceRegistryClient.startHeartbeat(options)
516
+ Starts periodic heartbeat messages, and gives up after a budget of
517
+ consecutive failures.
518
+
519
+ A heartbeat loop with no budget is worse than none: the beats stop reaching
520
+ the registry, the loop logs and reschedules forever, and the service keeps
521
+ running while every consumer of `registry:services` reads it as stale. Until
522
+ 2026-09-15 that budget lived in `@onlineapps/service-wrapper`, in a second
523
+ loop around `sendHeartbeat()` — two loops for one cadence
524
+ (`.claude/rules/change-discipline.md` § One rail per concern).
525
+
526
+ The cadence is NOT an argument here. It has one owner and it is the
527
+ constructor's `heartbeatInterval` (owner confirmation
528
+ docs/governance/confirmations/biz-health-freshness.md 001 point 3); taking it
529
+ again per call would be the second number that confirmation refuses.
530
+
531
+ Neither option is defaulted. How many missed beats mean death, and what death
532
+ means, are decisions of the caller that owns the process — this client only
533
+ counts and reports (`.claude/rules/architecture-principles.md` §3, §4).
534
+
535
+ **Kind**: instance method of [<code>ServiceRegistryClient</code>](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient)
536
+
537
+ | Param | Type | Description |
538
+ | --- | --- | --- |
539
+ | options | <code>Object</code> | |
540
+ | options.maxFailures | <code>number</code> | REQUIRED. Consecutive failed beats the service may accumulate before it can no longer prove it is alive. A positive whole number; one success resets the count to zero. |
541
+ | options.onFatal | <code>function</code> | REQUIRED. Called exactly once, with the §5 error naming the count and the last cause, at the moment the budget is spent. The loop is already stopped when it is called. |
542
+
543
+ <a name="module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+stopHeartbeat"></a>
544
+
545
+ #### serviceRegistryClient.stopHeartbeat()
546
+ Stops periodic heartbeat messages.
547
+
548
+ One scheduler, one cancel: `startHeartbeat()` arms the loop with a recursive
549
+ `setTimeout` and nothing in this class has created an interval since that
550
+ rewrite (d.503), so `clearTimeout` is the whole job. A `clearInterval` on the
551
+ same handle stood beside it until d.752, under a comment offering to cancel
552
+ "whether it's from setTimeout or setInterval" — a choice the class does not
553
+ have, and one that told every reader the loop might be an interval.
554
+
555
+ Setting `heartbeatTimer` to null is the second half and not a formality: the
556
+ loop reads it before arming the next beat, so a beat already in flight sees
557
+ the stop and schedules nothing.
558
+
559
+ **Kind**: instance method of [<code>ServiceRegistryClient</code>](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient)
560
+ <a name="module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+subscribeToChanges"></a>
561
+
562
+ #### serviceRegistryClient.subscribeToChanges() ⇒ <code>Promise.&lt;void&gt;</code>
563
+ Subscribe to registry change events (opt-in)
564
+ Creates event consumer and starts listening to registry.changes exchange
565
+
566
+ **Kind**: instance method of [<code>ServiceRegistryClient</code>](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient)
567
+ <a name="module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+getService"></a>
568
+
569
+ #### serviceRegistryClient.getService(serviceName) ⇒ <code>Promise.&lt;(ServiceSummary\|null)&gt;</code>
570
+ **Kind**: instance method of [<code>ServiceRegistryClient</code>](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient)
571
+
572
+ | Param | Type |
573
+ | --- | --- |
574
+ | serviceName | <code>string</code> |
575
+
576
+ <a name="module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient+close"></a>
577
+
578
+ #### serviceRegistryClient.close() ⇒ <code>Promise.&lt;void&gt;</code>
579
+ Releases resources: stops heartbeat and closes connection.
580
+
581
+ **Kind**: instance method of [<code>ServiceRegistryClient</code>](#module_@onlineapps/conn-orch-registry/src/registryClient..ServiceRegistryClient)
582
+ <a name="module_@onlineapps/conn-orch-registry/src/registryClient..RETIRED_SERVICE_INFO_KEYS"></a>
583
+
584
+ ### @onlineapps/conn-orch-registry/src/registryClient~RETIRED\_SERVICE\_INFO\_KEYS
585
+ Keys `register()` REFUSES, with the reason the caller needs to act on
586
+ (d.562, extended by d.592).
587
+
588
+ Each of them used to travel on every registration and nothing ever read them:
589
+ `api/infra/api_services_registry/src/listeners/registry.listener.js`
590
+ destructures the `register` message without them, and no other reader exists on
591
+ the platform (`api/docs/biz/30-operations/registration-wire.md` §2.1).
592
+
593
+ They are refused rather than ignored: a key silently dropped leaves the caller
594
+ believing something travelled. And they are refused under BOTH spellings each
595
+ was accepted by (`token` / `validationToken`, `secret` / `tokenSecret`) — two
596
+ names for one field is the defect this table closes, not a compatibility list.
597
+
598
+ **Kind**: inner constant of [<code>@onlineapps/conn-orch-registry/src/registryClient</code>](#module_@onlineapps/conn-orch-registry/src/registryClient)
599
+ <a name="module_@onlineapps/conn-orch-registry/src/registryClient..ACCEPTED_SERVICE_INFO_KEYS"></a>
600
+
601
+ ### @onlineapps/conn-orch-registry/src/registryClient~ACCEPTED\_SERVICE\_INFO\_KEYS
602
+ The keys `register()` ACCEPTS — the whole input contract of the call (d.702).
603
+
604
+ It is the caller's half of `api/docs/biz/30-operations/registration-wire.md`
605
+ §2.1: the five register-message fields a CALLER supplies, plus `timeout`, which
606
+ is this call's own response budget and reaches no message. The rest of §2.1
607
+ (`id`, `type`, `serviceName`, `version`, `specificationEndpoint`,
608
+ `responseQueue`, `timestamp`, `validationProof`, `validationData`) is client
609
+ state bound in the constructor, never caller input — a caller cannot set it and
610
+ this table must not invite one to try.
611
+
612
+ Any other key is refused BY NAME, for the same reason the table above exists:
613
+ until d.702 `register()` refused six retired keys and dropped everything else in
614
+ silence, so `helth`, `current_step` or `name` bought a confirmed registration
615
+ whose message never carried the value. A key silently dropped leaves the caller
616
+ believing something travelled, and a typo in an optional key is exactly the
617
+ shape nobody notices (`architecture-principles.md` §3 no fallbacks, §4
618
+ fail-fast).
619
+
620
+ `RETIRED_SERVICE_INFO_KEYS` is the subset that can still say WHY the key went;
621
+ ONE membership check reads both tables, so there is no second list to drift
622
+ (`.claude/rules/change-discipline.md` § One rail per concern).
623
+
624
+ **Kind**: inner constant of [<code>@onlineapps/conn-orch-registry/src/registryClient</code>](#module_@onlineapps/conn-orch-registry/src/registryClient)
625
+ <a name="module_@onlineapps/conn-orch-registry/src/registryClient..ServiceSummary"></a>
626
+
627
+ ### @onlineapps/conn-orch-registry/src/registryClient~ServiceSummary : <code>Object</code>
628
+ Get basic service state for service discovery.
629
+
630
+ Reads the projection the registry already maintains — the `<prefix>services`
631
+ hash, one JSON summary per service name. **Not HTTP.** The owner decided that
632
+ on 2026-09-02 (confirmation biz-discovery-redis-001). It is its own decision,
633
+ not a reading of ADR 0005: that ADR
634
+ (api/docs/biz/80-decisions/0005-no-http-in-biz-containers.md) bans an HTTP
635
+ LISTENER in a biz container and is silent on outbound calls — this extends the
636
+ same reasoning to the calls a biz container makes.
637
+ Until then this method polled `GET /services`, which is what made every biz
638
+ container an HTTP client of the registry ~142x a day.
639
+
640
+ There is deliberately no HTTP fallback. A missing Redis client is a wiring
641
+ error and says so (architecture-principles §3, §4) — falling back would
642
+ restore the very traffic this change removes, and hide the misconfiguration.
643
+
644
+ cookbook-router expects `{ status }`; the registry writes it lowercase
645
+ ('active'/'inactive') into the summary, so no normalization happens here.
646
+
647
+ **Kind**: inner typedef of [<code>@onlineapps/conn-orch-registry/src/registryClient</code>](#module_@onlineapps/conn-orch-registry/src/registryClient)
648
+ **Properties**
649
+
650
+ | Name | Type | Description |
651
+ | --- | --- | --- |
652
+ | serviceName | <code>string</code> | |
653
+ | status | <code>string</code> | lowercase, as the registry writes it ('active'/'inactive') |
654
+ | [version] | <code>string</code> | |
655
+ | [lastHeartbeatAt] | <code>string</code> | |
656
+
657
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer"></a>
658
+
659
+ ## @onlineapps/conn-orch-registry/src/registryEventConsumer
660
+ registryEventConsumer.js
661
+
662
+ Extension for ServiceRegistryClient to consume registry change events.
663
+ Implements opt-in subscription to registry.changes exchange.
664
+ Maintains local service index and enables lazy loading of specs.
665
+
666
+
667
+ * [@onlineapps/conn-orch-registry/src/registryEventConsumer](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer)
668
+ * [~RegistryEventConsumer](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
669
+ * [new RegistryEventConsumer(opts)](#new_module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer_new)
670
+ * [.initStorage()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+initStorage)
671
+ * [.subscribeToChanges()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+subscribeToChanges)
672
+ * [.handleSpecPublished()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+handleSpecPublished)
673
+ * [.handleStatusChanged()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+handleStatusChanged)
674
+ * [.handleSnapshot()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+handleSnapshot)
675
+ * [.handleServiceRemoved()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+handleServiceRemoved)
676
+ * [.requestSnapshot()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+requestSnapshot)
677
+ * [.getServiceSpec(serviceName)](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+getServiceSpec) ⇒ <code>Promise.&lt;Object&gt;</code>
678
+ * [.isServiceActive(serviceName)](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+isServiceActive) ⇒ <code>boolean</code>
679
+ * [.getActiveServices()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+getActiveServices) ⇒ <code>Array.&lt;string&gt;</code>
680
+ * [.getServiceInfo(serviceName)](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+getServiceInfo) ⇒ <code>Object</code> \| <code>null</code>
681
+ * [.persistIndex()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+persistIndex)
682
+ * [.loadIndexFromCache()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+loadIndexFromCache)
683
+ * [.clearCache()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+clearCache)
684
+ * [.getStats()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+getStats)
685
+
686
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer"></a>
687
+
688
+ ### @onlineapps/conn-orch-registry/src/registryEventConsumer~RegistryEventConsumer
689
+ **Kind**: inner class of [<code>@onlineapps/conn-orch-registry/src/registryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer)
690
+
691
+ * [~RegistryEventConsumer](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
692
+ * [new RegistryEventConsumer(opts)](#new_module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer_new)
693
+ * [.initStorage()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+initStorage)
694
+ * [.subscribeToChanges()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+subscribeToChanges)
695
+ * [.handleSpecPublished()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+handleSpecPublished)
696
+ * [.handleStatusChanged()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+handleStatusChanged)
697
+ * [.handleSnapshot()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+handleSnapshot)
698
+ * [.handleServiceRemoved()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+handleServiceRemoved)
699
+ * [.requestSnapshot()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+requestSnapshot)
700
+ * [.getServiceSpec(serviceName)](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+getServiceSpec) ⇒ <code>Promise.&lt;Object&gt;</code>
701
+ * [.isServiceActive(serviceName)](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+isServiceActive) ⇒ <code>boolean</code>
702
+ * [.getActiveServices()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+getActiveServices) ⇒ <code>Array.&lt;string&gt;</code>
703
+ * [.getServiceInfo(serviceName)](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+getServiceInfo) ⇒ <code>Object</code> \| <code>null</code>
704
+ * [.persistIndex()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+persistIndex)
705
+ * [.loadIndexFromCache()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+loadIndexFromCache)
706
+ * [.clearCache()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+clearCache)
707
+ * [.getStats()](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+getStats)
708
+
709
+ <a name="new_module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer_new"></a>
710
+
711
+ #### new RegistryEventConsumer(opts)
712
+
713
+ | Param | Type | Default | Description |
714
+ | --- | --- | --- | --- |
715
+ | opts | <code>Object</code> | | |
716
+ | opts.queueManager | <code>Object</code> | | QueueManager instance from ServiceRegistryClient |
717
+ | opts.serviceName | <code>string</code> | | Name of the consuming service |
718
+ | [opts.redis] | <code>Object</code> | | Optional Redis client for index persistence |
719
+ | [opts.storageConfig] | <code>Object</code> | | Configuration for StorageConnector |
720
+ | [opts.StorageConnector] | <code>Object</code> | | Injectable StorageConnector class for testing |
721
+ | opts.logger | <code>Object</code> | | Logger with info/warn/error/debug; required, validated here (docs/governance/confirmations/connector-logger-contract.md 001) |
722
+ | [opts.cacheEnabled] | <code>boolean</code> | <code>true</code> | Enable local spec caching |
723
+ | [opts.maxCacheSize] | <code>number</code> | <code>50</code> | Maximum cached specs |
724
+
725
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+initStorage"></a>
726
+
727
+ #### registryEventConsumer.initStorage()
728
+ Initialize storage connector
729
+
730
+ **Kind**: instance method of [<code>RegistryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
731
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+subscribeToChanges"></a>
732
+
733
+ #### registryEventConsumer.subscribeToChanges()
734
+ Subscribe to registry change events (opt-in)
735
+ Creates service-specific queue bound to registry.changes exchange
736
+
737
+ **Kind**: instance method of [<code>RegistryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
738
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+handleSpecPublished"></a>
739
+
740
+ #### registryEventConsumer.handleSpecPublished()
741
+ Handle SERVICE_SPEC_PUBLISHED event
742
+
743
+ **Kind**: instance method of [<code>RegistryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
744
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+handleStatusChanged"></a>
745
+
746
+ #### registryEventConsumer.handleStatusChanged()
747
+ Handle SERVICE_STATUS_CHANGED event
748
+
749
+ **Kind**: instance method of [<code>RegistryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
750
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+handleSnapshot"></a>
751
+
752
+ #### registryEventConsumer.handleSnapshot()
753
+ Handle REGISTRY_SNAPSHOT event
754
+
755
+ **Kind**: instance method of [<code>RegistryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
756
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+handleServiceRemoved"></a>
757
+
758
+ #### registryEventConsumer.handleServiceRemoved()
759
+ Handle SERVICE_REMOVED event
760
+
761
+ **Kind**: instance method of [<code>RegistryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
762
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+requestSnapshot"></a>
763
+
764
+ #### registryEventConsumer.requestSnapshot()
765
+ Request initial snapshot from registry
766
+
767
+ **Kind**: instance method of [<code>RegistryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
768
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+getServiceSpec"></a>
769
+
770
+ #### registryEventConsumer.getServiceSpec(serviceName) ⇒ <code>Promise.&lt;Object&gt;</code>
771
+ Get service spec with lazy loading from MinIO
772
+
773
+ **Kind**: instance method of [<code>RegistryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
774
+ **Returns**: <code>Promise.&lt;Object&gt;</code> - - Service specification
775
+
776
+ | Param | Type | Description |
777
+ | --- | --- | --- |
778
+ | serviceName | <code>string</code> | Name of the service |
779
+
780
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+isServiceActive"></a>
781
+
782
+ #### registryEventConsumer.isServiceActive(serviceName) ⇒ <code>boolean</code>
783
+ Check if service is active (synchronous, from local index)
784
+
785
+ **Kind**: instance method of [<code>RegistryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
786
+
787
+ | Param | Type | Description |
788
+ | --- | --- | --- |
789
+ | serviceName | <code>string</code> | Name of the service |
790
+
791
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+getActiveServices"></a>
792
+
793
+ #### registryEventConsumer.getActiveServices() ⇒ <code>Array.&lt;string&gt;</code>
794
+ Get list of active services (synchronous, from local index)
795
+
796
+ **Kind**: instance method of [<code>RegistryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
797
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+getServiceInfo"></a>
798
+
799
+ #### registryEventConsumer.getServiceInfo(serviceName) ⇒ <code>Object</code> \| <code>null</code>
800
+ Get service info from local index
801
+
802
+ **Kind**: instance method of [<code>RegistryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
803
+
804
+ | Param | Type |
805
+ | --- | --- |
806
+ | serviceName | <code>string</code> |
807
+
808
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+persistIndex"></a>
809
+
810
+ #### registryEventConsumer.persistIndex()
811
+ Persist index to Redis (if configured)
812
+
813
+ **Kind**: instance method of [<code>RegistryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
814
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+loadIndexFromCache"></a>
815
+
816
+ #### registryEventConsumer.loadIndexFromCache()
817
+ Load index from Redis cache
818
+
819
+ **Kind**: instance method of [<code>RegistryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
820
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+clearCache"></a>
821
+
822
+ #### registryEventConsumer.clearCache()
823
+ Clear all caches
824
+
825
+ **Kind**: instance method of [<code>RegistryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)
826
+ <a name="module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer+getStats"></a>
827
+
828
+ #### registryEventConsumer.getStats()
829
+ Get stats about current state
830
+
831
+ **Kind**: instance method of [<code>RegistryEventConsumer</code>](#module_@onlineapps/conn-orch-registry/src/registryEventConsumer..RegistryEventConsumer)