@oatscenter/trellis 0.100.0-rc.1

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.
Files changed (264) hide show
  1. package/README.md +59 -0
  2. package/auth/authorization/client_context.d.ts +61 -0
  3. package/auth/authorization/client_context.js +266 -0
  4. package/auth/authorization/nats_registry.d.ts +41 -0
  5. package/auth/authorization/nats_registry.js +283 -0
  6. package/auth/authorization/provider_cache.d.ts +90 -0
  7. package/auth/authorization/provider_cache.js +783 -0
  8. package/auth/authorization/refresh.d.ts +46 -0
  9. package/auth/authorization/refresh.js +246 -0
  10. package/auth/authorization/types.d.ts +207 -0
  11. package/auth/authorization/types.js +60 -0
  12. package/auth/authorization_context.d.ts +11 -0
  13. package/auth/authorization_context.js +10 -0
  14. package/auth/browser/flow_types.d.ts +84 -0
  15. package/auth/browser/flow_types.js +70 -0
  16. package/auth/browser/portal.d.ts +21 -0
  17. package/auth/browser/portal.js +307 -0
  18. package/auth/browser/storage.d.ts +26 -0
  19. package/auth/browser/storage.js +224 -0
  20. package/auth/browser.d.ts +11 -0
  21. package/auth/browser.js +10 -0
  22. package/auth/browser_recovery.d.ts +13 -0
  23. package/auth/browser_recovery.js +38 -0
  24. package/auth/device_activation.d.ts +134 -0
  25. package/auth/device_activation.js +376 -0
  26. package/auth/http_error.d.ts +12 -0
  27. package/auth/http_error.js +32 -0
  28. package/auth/keys.d.ts +5 -0
  29. package/auth/keys.js +63 -0
  30. package/auth/mod.d.ts +16 -0
  31. package/auth/mod.js +16 -0
  32. package/auth/proof.d.ts +31 -0
  33. package/auth/proof.js +95 -0
  34. package/auth/protocol_wasm/trellis_protocol_wasm.d.ts +138 -0
  35. package/auth/protocol_wasm/trellis_protocol_wasm.js +605 -0
  36. package/auth/protocol_wasm/trellis_protocol_wasm_bg.wasm +0 -0
  37. package/auth/protocol_wasm/trellis_protocol_wasm_bytes.d.ts +1 -0
  38. package/auth/protocol_wasm/trellis_protocol_wasm_bytes.js +2 -0
  39. package/auth/protocol_wasm.d.ts +179 -0
  40. package/auth/protocol_wasm.js +133 -0
  41. package/auth/session_auth.d.ts +30 -0
  42. package/auth/session_auth.js +77 -0
  43. package/auth/session_proof.d.ts +53 -0
  44. package/auth/session_proof.js +43 -0
  45. package/auth/time.d.ts +6 -0
  46. package/auth/time.js +7 -0
  47. package/auth/trellis_id.d.ts +1 -0
  48. package/auth/trellis_id.js +5 -0
  49. package/auth/utils.d.ts +10 -0
  50. package/auth/utils.js +69 -0
  51. package/auth.d.ts +1 -0
  52. package/auth.js +1 -0
  53. package/caller.d.ts +111 -0
  54. package/caller.js +85 -0
  55. package/client.d.ts +14 -0
  56. package/client.js +1 -0
  57. package/client_connect.d.ts +143 -0
  58. package/client_connect.js +1097 -0
  59. package/codec.d.ts +13 -0
  60. package/codec.js +192 -0
  61. package/connection.d.ts +107 -0
  62. package/connection.js +396 -0
  63. package/device/activation.d.ts +42 -0
  64. package/device/activation.js +319 -0
  65. package/device.d.ts +80 -0
  66. package/device.js +687 -0
  67. package/env.d.ts +2 -0
  68. package/env.js +10 -0
  69. package/errors/AuthError.d.ts +30 -0
  70. package/errors/AuthError.js +34 -0
  71. package/errors/KVError.d.ts +30 -0
  72. package/errors/KVError.js +36 -0
  73. package/errors/OperationLifecycleError.d.ts +110 -0
  74. package/errors/OperationLifecycleError.js +142 -0
  75. package/errors/RemoteError.d.ts +61 -0
  76. package/errors/RemoteError.js +72 -0
  77. package/errors/SchemaValidationError.d.ts +48 -0
  78. package/errors/SchemaValidationError.js +49 -0
  79. package/errors/StoreError.d.ts +21 -0
  80. package/errors/StoreError.js +31 -0
  81. package/errors/TransferError.d.ts +21 -0
  82. package/errors/TransferError.js +31 -0
  83. package/errors/TransportError.d.ts +29 -0
  84. package/errors/TransportError.js +33 -0
  85. package/errors/TrellisError.d.ts +15 -0
  86. package/errors/TrellisError.js +15 -0
  87. package/errors/ValidationError.d.ts +50 -0
  88. package/errors/ValidationError.js +59 -0
  89. package/errors/index.d.ts +254 -0
  90. package/errors/index.js +238 -0
  91. package/generated.d.ts +4 -0
  92. package/generated.js +3 -0
  93. package/generated_support.d.ts +120 -0
  94. package/generated_support.js +359 -0
  95. package/globals.d.ts +9 -0
  96. package/globals.js +16 -0
  97. package/health_transport.d.ts +18 -0
  98. package/health_transport.js +32 -0
  99. package/helpers.d.ts +11 -0
  100. package/helpers.js +53 -0
  101. package/index.d.ts +2 -0
  102. package/index.js +2 -0
  103. package/internal_sdk/generated/apis/auth/mod.d.ts +805 -0
  104. package/internal_sdk/generated/apis/auth/mod.js +958 -0
  105. package/internal_sdk/generated/apis/core/mod.d.ts +79 -0
  106. package/internal_sdk/generated/apis/core/mod.js +93 -0
  107. package/internal_sdk/generated/apis/events/mod.d.ts +224 -0
  108. package/internal_sdk/generated/apis/events/mod.js +313 -0
  109. package/internal_sdk/generated/apis/health/mod.d.ts +106 -0
  110. package/internal_sdk/generated/apis/health/mod.js +132 -0
  111. package/internal_sdk/generated/apis/index.d.ts +7 -0
  112. package/internal_sdk/generated/apis/index.js +8 -0
  113. package/internal_sdk/generated/apis/jobs/mod.d.ts +176 -0
  114. package/internal_sdk/generated/apis/jobs/mod.js +209 -0
  115. package/internal_sdk/generated/apis/state/mod.d.ts +104 -0
  116. package/internal_sdk/generated/apis/state/mod.js +139 -0
  117. package/internal_sdk/generated/index.d.ts +4 -0
  118. package/internal_sdk/generated/index.js +5 -0
  119. package/internal_sdk/generated/package.json +18 -0
  120. package/internal_sdk/generated/participants/cli/mod.d.ts +402 -0
  121. package/internal_sdk/generated/participants/cli/mod.js +460 -0
  122. package/internal_sdk/generated/participants/cli/types.d.ts +2 -0
  123. package/internal_sdk/generated/participants/cli/types.js +3 -0
  124. package/internal_sdk/generated/participants/console/mod.d.ts +489 -0
  125. package/internal_sdk/generated/participants/console/mod.js +579 -0
  126. package/internal_sdk/generated/participants/console/types.d.ts +2 -0
  127. package/internal_sdk/generated/participants/console/types.js +3 -0
  128. package/internal_sdk/generated/participants/eventsRuntime/mod.d.ts +64 -0
  129. package/internal_sdk/generated/participants/eventsRuntime/mod.js +42 -0
  130. package/internal_sdk/generated/participants/eventsRuntime/types.d.ts +2 -0
  131. package/internal_sdk/generated/participants/eventsRuntime/types.js +3 -0
  132. package/internal_sdk/generated/participants/healthRuntime/mod.d.ts +58 -0
  133. package/internal_sdk/generated/participants/healthRuntime/mod.js +36 -0
  134. package/internal_sdk/generated/participants/healthRuntime/types.d.ts +2 -0
  135. package/internal_sdk/generated/participants/healthRuntime/types.js +3 -0
  136. package/internal_sdk/generated/participants/index.d.ts +8 -0
  137. package/internal_sdk/generated/participants/index.js +9 -0
  138. package/internal_sdk/generated/participants/jobsRuntime/mod.d.ts +64 -0
  139. package/internal_sdk/generated/participants/jobsRuntime/mod.js +42 -0
  140. package/internal_sdk/generated/participants/jobsRuntime/types.d.ts +2 -0
  141. package/internal_sdk/generated/participants/jobsRuntime/types.js +3 -0
  142. package/internal_sdk/generated/participants/platform/mod.d.ts +164 -0
  143. package/internal_sdk/generated/participants/platform/mod.js +149 -0
  144. package/internal_sdk/generated/participants/platform/types.d.ts +7 -0
  145. package/internal_sdk/generated/participants/platform/types.js +5 -0
  146. package/internal_sdk/generated/participants/portal/mod.d.ts +131 -0
  147. package/internal_sdk/generated/participants/portal/mod.js +109 -0
  148. package/internal_sdk/generated/participants/portal/types.d.ts +2 -0
  149. package/internal_sdk/generated/participants/portal/types.js +3 -0
  150. package/internal_sdk/generated/types/_internal/p0.d.ts +13511 -0
  151. package/internal_sdk/generated/types/_internal/p0.js +6105 -0
  152. package/internal_sdk/generated/types/index.d.ts +2951 -0
  153. package/internal_sdk/generated/types/index.js +1477 -0
  154. package/jobs.d.ts +309 -0
  155. package/jobs.js +389 -0
  156. package/kv.d.ts +85 -0
  157. package/kv.js +330 -0
  158. package/operations.d.ts +189 -0
  159. package/operations.js +847 -0
  160. package/package.json +73 -0
  161. package/pagination.d.ts +25 -0
  162. package/pagination.js +117 -0
  163. package/participant.d.ts +6 -0
  164. package/participant.js +6 -0
  165. package/participant_runtime/api.d.ts +131 -0
  166. package/participant_runtime/api.js +42 -0
  167. package/participant_runtime/json.d.ts +16 -0
  168. package/participant_runtime/json.js +193 -0
  169. package/participant_runtime/metadata.d.ts +34 -0
  170. package/participant_runtime/metadata.js +4 -0
  171. package/participant_runtime/participant.d.ts +200 -0
  172. package/participant_runtime/participant.js +330 -0
  173. package/participant_runtime/schemas.d.ts +347 -0
  174. package/participant_runtime/schemas.js +211 -0
  175. package/participant_runtime/surface_names.d.ts +16 -0
  176. package/participant_runtime/surface_names.js +34 -0
  177. package/portable.d.ts +30 -0
  178. package/portable.js +14 -0
  179. package/provider.d.ts +69 -0
  180. package/provider.js +68 -0
  181. package/runtime_transport.d.ts +25 -0
  182. package/runtime_transport.js +48 -0
  183. package/service/mod.d.ts +14 -0
  184. package/service/mod.js +13 -0
  185. package/service/outbox_inbox.d.ts +259 -0
  186. package/service/outbox_inbox.js +908 -0
  187. package/service/runtime/bootstrap.d.ts +56 -0
  188. package/service/runtime/bootstrap.js +226 -0
  189. package/service/runtime/core.d.ts +46 -0
  190. package/service/runtime/core.js +1747 -0
  191. package/service/runtime/health.d.ts +97 -0
  192. package/service/runtime/health.js +153 -0
  193. package/service/runtime/health_schemas.d.ts +23 -0
  194. package/service/runtime/health_schemas.js +20 -0
  195. package/service/runtime/internal_jobs/active-job.d.ts +40 -0
  196. package/service/runtime/internal_jobs/active-job.js +91 -0
  197. package/service/runtime/internal_jobs/bindings.d.ts +40 -0
  198. package/service/runtime/internal_jobs/bindings.js +1 -0
  199. package/service/runtime/internal_jobs/cancellation-registry.d.ts +13 -0
  200. package/service/runtime/internal_jobs/cancellation-registry.js +55 -0
  201. package/service/runtime/internal_jobs/heartbeat.d.ts +33 -0
  202. package/service/runtime/internal_jobs/heartbeat.js +65 -0
  203. package/service/runtime/internal_jobs/job-manager.d.ts +126 -0
  204. package/service/runtime/internal_jobs/job-manager.js +821 -0
  205. package/service/runtime/internal_jobs/key-coordinator.d.ts +280 -0
  206. package/service/runtime/internal_jobs/key-coordinator.js +747 -0
  207. package/service/runtime/internal_jobs/projection.d.ts +3 -0
  208. package/service/runtime/internal_jobs/projection.js +42 -0
  209. package/service/runtime/internal_jobs/runtime-worker.d.ts +126 -0
  210. package/service/runtime/internal_jobs/runtime-worker.js +454 -0
  211. package/service/runtime/internal_jobs/types.d.ts +246 -0
  212. package/service/runtime/internal_jobs/types.js +163 -0
  213. package/service/runtime/logger.d.ts +2 -0
  214. package/service/runtime/logger.js +7 -0
  215. package/service/runtime/runtime.d.ts +16 -0
  216. package/service/runtime/runtime.js +1 -0
  217. package/service/runtime/service.d.ts +372 -0
  218. package/service/runtime/service.js +1896 -0
  219. package/service/runtime/transfer/download.d.ts +27 -0
  220. package/service/runtime/transfer/download.js +1 -0
  221. package/service/runtime/transfer/protocol.d.ts +15 -0
  222. package/service/runtime/transfer/protocol.js +46 -0
  223. package/service/runtime/transfer/queue.d.ts +18 -0
  224. package/service/runtime/transfer/queue.js +136 -0
  225. package/service/runtime/transfer/upload.d.ts +40 -0
  226. package/service/runtime/transfer/upload.js +27 -0
  227. package/service/runtime/transfer.d.ts +62 -0
  228. package/service/runtime/transfer.js +763 -0
  229. package/session.d.ts +862 -0
  230. package/session.js +3407 -0
  231. package/store.d.ts +71 -0
  232. package/store.js +412 -0
  233. package/store_entry.d.ts +20 -0
  234. package/store_entry.js +75 -0
  235. package/tasks.d.ts +10 -0
  236. package/tasks.js +28 -0
  237. package/telemetry/carrier.d.ts +8 -0
  238. package/telemetry/carrier.js +20 -0
  239. package/telemetry/core.d.ts +7 -0
  240. package/telemetry/core.js +14 -0
  241. package/telemetry/env.d.ts +2 -0
  242. package/telemetry/env.js +10 -0
  243. package/telemetry/init.d.ts +2 -0
  244. package/telemetry/init.js +7 -0
  245. package/telemetry/metrics.d.ts +81 -0
  246. package/telemetry/metrics.js +267 -0
  247. package/telemetry/mod.d.ts +13 -0
  248. package/telemetry/mod.js +8 -0
  249. package/telemetry/nats.d.ts +6 -0
  250. package/telemetry/nats.js +6 -0
  251. package/telemetry/result.d.ts +1 -0
  252. package/telemetry/result.js +18 -0
  253. package/telemetry/runtime.d.ts +1 -0
  254. package/telemetry/runtime.js +141 -0
  255. package/telemetry/trace.d.ts +4 -0
  256. package/telemetry/trace.js +26 -0
  257. package/telemetry/trellis.d.ts +1 -0
  258. package/telemetry/trellis.js +1 -0
  259. package/telemetry.d.ts +1 -0
  260. package/telemetry.js +1 -0
  261. package/transfer.d.ts +112 -0
  262. package/transfer.js +525 -0
  263. package/transfer_protocol.d.ts +1 -0
  264. package/transfer_protocol.js +13 -0
@@ -0,0 +1,283 @@
1
+ import { AckPolicy, DeliverPolicy, jetstream, jetstreamManager, } from "@nats-io/jetstream";
2
+ import { createInbox } from "@nats-io/nats-core";
3
+ const REVOCATION_PREFIX = "revocation.";
4
+ class RegistryWatchQueue {
5
+ #values = [];
6
+ #waiting;
7
+ #closed = false;
8
+ #error;
9
+ push(value) {
10
+ if (this.#closed)
11
+ return;
12
+ if (this.#waiting) {
13
+ const waiting = this.#waiting;
14
+ this.#waiting = undefined;
15
+ waiting.resolve({ done: false, value });
16
+ }
17
+ else if (this.#values.length < 2) {
18
+ this.#values.push(value);
19
+ }
20
+ else {
21
+ throw new Error("authorization revocation watch queue overflow");
22
+ }
23
+ }
24
+ fail(error) {
25
+ if (this.#closed)
26
+ return;
27
+ this.#closed = true;
28
+ this.#error = error;
29
+ this.#values.length = 0;
30
+ this.#waiting?.reject(error);
31
+ this.#waiting = undefined;
32
+ }
33
+ close() {
34
+ if (this.#closed)
35
+ return;
36
+ this.#closed = true;
37
+ this.#values.length = 0;
38
+ this.#waiting?.resolve({ done: true, value: undefined });
39
+ this.#waiting = undefined;
40
+ }
41
+ next() {
42
+ if (this.#error)
43
+ return Promise.reject(this.#error);
44
+ if (this.#closed) {
45
+ return Promise.resolve({ done: true, value: undefined });
46
+ }
47
+ const value = this.#values.shift();
48
+ if (value)
49
+ return Promise.resolve({ done: false, value });
50
+ return new Promise((resolve, reject) => this.#waiting = { resolve, reject });
51
+ }
52
+ }
53
+ /** Connected NATS KV reader for authorization evidence. */
54
+ export class AuthorizationRegistryReader {
55
+ #nats;
56
+ #jetstream;
57
+ #direct;
58
+ #binding;
59
+ #inboxPrefix;
60
+ #contextGets = 0;
61
+ #watchStarts = 0;
62
+ constructor(nats, jetstreamClient, direct, binding, inboxPrefix) {
63
+ this.#nats = nats;
64
+ this.#jetstream = jetstreamClient;
65
+ this.#direct = direct;
66
+ this.#binding = binding;
67
+ this.#inboxPrefix = inboxPrefix;
68
+ }
69
+ /** Open the exact registry buckets from bootstrap-owned internal metadata. */
70
+ static async open(nats, binding, inboxPrefix) {
71
+ validateBinding(binding);
72
+ const manager = await jetstreamManager(nats);
73
+ return new AuthorizationRegistryReader(nats, jetstream(nats), manager.direct, binding, inboxPrefix);
74
+ }
75
+ /** Return a copy of internal registry counters. */
76
+ ioCounters() {
77
+ return {
78
+ contextGets: this.#contextGets,
79
+ watchStarts: this.#watchStarts,
80
+ };
81
+ }
82
+ /** Read one immutable context by its exact digest key. */
83
+ async getContext(digest) {
84
+ assertRegistryKey(digest, "authorization context digest");
85
+ this.#contextGets += 1;
86
+ return await this.#putOrNull(this.#binding.contextBucket, digest);
87
+ }
88
+ /** Subscribe only to the active context's revocation key. */
89
+ async watchRevocation(contextDigest) {
90
+ assertRegistryKey(contextDigest, "authorization context digest");
91
+ this.#watchStarts += 1;
92
+ const key = `${REVOCATION_PREFIX}${contextDigest}`;
93
+ const stream = `KV_${this.#binding.contextBucket}`;
94
+ const filterSubject = `$KV.${this.#binding.contextBucket}.${key}`;
95
+ const deliverSubject = createInbox(this.#inboxPrefix);
96
+ const name = `TrellisAuth${deliverSubject.split(".").at(-1) ?? ""}`;
97
+ const manager = await this.#jetstream.jetstreamManager();
98
+ await manager.consumers.add(stream, {
99
+ ack_policy: AckPolicy.None,
100
+ deliver_policy: DeliverPolicy.LastPerSubject,
101
+ deliver_subject: deliverSubject,
102
+ filter_subject: filterSubject,
103
+ flow_control: true,
104
+ idle_heartbeat: 5_000_000_000,
105
+ inactive_threshold: 10_000_000_000,
106
+ mem_storage: true,
107
+ name,
108
+ num_replicas: 1,
109
+ });
110
+ const consumer = await this.#jetstream.consumers.getPushConsumer(stream, name);
111
+ const queue = new RegistryWatchQueue();
112
+ let receivedConsumerSequence = 0;
113
+ let lastStreamRevision = 0;
114
+ let initialBoundary;
115
+ let initialized = false;
116
+ let stopped = false;
117
+ const initialize = () => {
118
+ if (!initialized && initialBoundary !== undefined &&
119
+ receivedConsumerSequence >= initialBoundary) {
120
+ initialized = true;
121
+ queue.push({ operation: "initialized" });
122
+ }
123
+ };
124
+ let stop = (error) => {
125
+ stopped = true;
126
+ if (error)
127
+ queue.fail(error);
128
+ else
129
+ queue.close();
130
+ };
131
+ const messages = await consumer.consume({
132
+ callback: (message) => {
133
+ try {
134
+ const current = message.info.deliverySequence;
135
+ const streamRevision = message.info.streamSequence;
136
+ if (message.subject !== filterSubject ||
137
+ current !== receivedConsumerSequence + 1 ||
138
+ streamRevision <= lastStreamRevision) {
139
+ throw new Error("authorization revocation watch sequence gap");
140
+ }
141
+ receivedConsumerSequence = current;
142
+ lastStreamRevision = streamRevision;
143
+ const operation = message.headers?.has("KV-Operation")
144
+ ? message.headers.get("KV-Operation")
145
+ : "PUT";
146
+ if (operation === "DEL" || operation === "PURGE") {
147
+ queue.push({ operation: "delete", key, revision: streamRevision });
148
+ }
149
+ else if (operation === "PUT") {
150
+ queue.push({
151
+ operation: "put",
152
+ key,
153
+ value: message.data,
154
+ revision: streamRevision,
155
+ });
156
+ }
157
+ else {
158
+ throw new Error("authorization revocation operation is invalid");
159
+ }
160
+ initialize();
161
+ }
162
+ catch (error) {
163
+ stop(error instanceof Error ? error : new Error(String(error)));
164
+ }
165
+ },
166
+ });
167
+ stop = (error) => {
168
+ if (stopped)
169
+ return;
170
+ stopped = true;
171
+ if (error)
172
+ queue.fail(error);
173
+ else
174
+ queue.close();
175
+ messages.stop(error);
176
+ };
177
+ const status = messages.status();
178
+ const statusTask = (async () => {
179
+ try {
180
+ for await (const event of status) {
181
+ if (event.type === "heartbeat" &&
182
+ event.lastConsumerSequence > receivedConsumerSequence) {
183
+ stop(new Error("authorization revocation watch sequence gap"));
184
+ return;
185
+ }
186
+ if (event.type === "heartbeats_missed" ||
187
+ event.type === "consumer_deleted" ||
188
+ event.type === "stream_not_found" ||
189
+ event.type === "consumer_not_found" ||
190
+ event.type === "no_responders" ||
191
+ event.type === "reset" ||
192
+ event.type === "ordered_consumer_recreated") {
193
+ stop(new Error(`authorization revocation watch lost coverage: ${event.type}`));
194
+ return;
195
+ }
196
+ }
197
+ }
198
+ catch (error) {
199
+ stop(error instanceof Error ? error : new Error(String(error)));
200
+ }
201
+ finally {
202
+ if (!stopped) {
203
+ stop(new Error("authorization revocation watch status ended"));
204
+ }
205
+ }
206
+ })();
207
+ const settled = async () => {
208
+ await messages.closed();
209
+ await statusTask;
210
+ };
211
+ try {
212
+ await this.#nats.flush();
213
+ const info = await consumer.info();
214
+ initialBoundary = info.delivered.consumer_seq + info.num_pending;
215
+ initialize();
216
+ }
217
+ catch (error) {
218
+ stop(error instanceof Error ? error : new Error(String(error)));
219
+ await settled();
220
+ throw error;
221
+ }
222
+ void messages.closed().then((error) => {
223
+ if (!stopped) {
224
+ stop(error instanceof Error
225
+ ? error
226
+ : new Error("authorization revocation watch ended"));
227
+ }
228
+ });
229
+ return {
230
+ iterator: {
231
+ next: () => queue.next(),
232
+ return: async () => {
233
+ stop();
234
+ await settled();
235
+ return { done: true, value: undefined };
236
+ },
237
+ },
238
+ close: async () => {
239
+ stop();
240
+ await settled();
241
+ },
242
+ };
243
+ }
244
+ async #putOrNull(bucket, key) {
245
+ let entry;
246
+ try {
247
+ entry = await this.#direct.getMessage(`KV_${bucket}`, {
248
+ last_by_subj: `$KV.${bucket}.${key}`,
249
+ });
250
+ }
251
+ catch (error) {
252
+ if (typeof error === "object" && error !== null && "code" in error &&
253
+ error.code === 404)
254
+ return null;
255
+ throw error;
256
+ }
257
+ if (!entry)
258
+ return null;
259
+ const operation = entry.header?.get("KV-Operation") || "PUT";
260
+ if (operation !== "PUT") {
261
+ throw new Error("authorization registry evidence disappeared");
262
+ }
263
+ return { value: entry.data, revision: entry.seq, operation };
264
+ }
265
+ }
266
+ function validateBinding(binding) {
267
+ const entries = Object.entries(binding);
268
+ if (entries.length !== 1 || !("contextBucket" in binding)) {
269
+ throw new Error("authorization registry binding is invalid");
270
+ }
271
+ for (const [name, value] of entries) {
272
+ if (typeof value !== "string" || !value.trim()) {
273
+ throw new Error(`authorization registry binding ${name} is empty`);
274
+ }
275
+ }
276
+ }
277
+ function assertRegistryKey(value, name) {
278
+ if (!isRegistryKey(value))
279
+ throw new Error(`${name} is invalid`);
280
+ }
281
+ function isRegistryKey(value) {
282
+ return value.length === 43 && /^[A-Za-z0-9_-]+$/.test(value);
283
+ }
@@ -0,0 +1,90 @@
1
+ import type { NatsConnection } from "@nats-io/nats-core";
2
+ import type { AuthorizationVerificationErrorCode, VerifiedAuthorizationContextTokenProjection, VerifiedAuthorizationEventPublisher } from "../protocol_wasm.ts";
3
+ import type { AuthorizationContextCache } from "./client_context.ts";
4
+ import { type AuthorizationRegistryIoCounters } from "./nats_registry.ts";
5
+ import type { AuthorizationProviderEvent, AuthorizationProviderRequest, AuthorizationRegistryBinding } from "./types.ts";
6
+ type VerificationFailure = {
7
+ ok: false;
8
+ error: {
9
+ code: AuthorizationVerificationErrorCode;
10
+ path: string;
11
+ };
12
+ };
13
+ type CachedRequestVerificationResult = {
14
+ ok: true;
15
+ contextDigest: string;
16
+ context: VerifiedAuthorizationContextTokenProjection["context"];
17
+ } | VerificationFailure;
18
+ type CachedEventVerificationResult = {
19
+ ok: true;
20
+ contextDigest: string;
21
+ context: VerifiedAuthorizationContextTokenProjection["context"];
22
+ publisher: VerifiedAuthorizationEventPublisher;
23
+ } | VerificationFailure;
24
+ /** Observable provider registry health. */
25
+ export type AuthorizationProviderCacheHealth = {
26
+ revocationRevision: number;
27
+ lastUpdateAt: number;
28
+ healthy: boolean;
29
+ };
30
+ /** Provider I/O counters used by local hot-path tests and diagnostics. */
31
+ export type AuthorizationProviderIoCounters = AuthorizationRegistryIoCounters & {
32
+ contextResolves: number;
33
+ contextVerifications: number;
34
+ };
35
+ /** Internal marker for retryable provider registry or readiness failure. */
36
+ export declare class AuthorizationProviderUnavailableError extends Error {
37
+ constructor(message: string, cause?: unknown);
38
+ }
39
+ /** Provider attach options. */
40
+ export type AuthorizationProviderCacheOptions = {
41
+ now?: () => number;
42
+ };
43
+ /** Connected provider-side authorization verifier. */
44
+ export declare class AuthorizationProviderCache {
45
+ #private;
46
+ private constructor();
47
+ /** Attach to the bootstrap-selected NATS authorization registry. */
48
+ static attach(nats: NatsConnection, binding: AuthorizationRegistryBinding, inboxPrefix: string, cache: AuthorizationContextCache, options?: AuthorizationProviderCacheOptions): Promise<AuthorizationProviderCache>;
49
+ /** Enable provider verification. */
50
+ start(): void;
51
+ /** Stop verification without closing the caller-owned NATS connection. */
52
+ stop(): void;
53
+ /** Retain exact revocation coverage for the currently installed own context. */
54
+ retainOwnContext(): Promise<void>;
55
+ /** Retain candidate coverage on the exact admitted connection generation. */
56
+ retainOwnCandidate(digest: string, generation: number): Promise<void>;
57
+ /** Promote the candidate only while its admitted coverage remains current. */
58
+ promoteOwnCandidate(digest: string, generation: number): void;
59
+ connectionGeneration(): number;
60
+ /** Returns whether the current own authorization may authenticate transport. */
61
+ ownUsable(): boolean;
62
+ /** A verified private candidate or a retained unrevoked installation may authenticate transport. */
63
+ transportUsable(): boolean;
64
+ /** Suspend stale transport authentication and request one current context. */
65
+ refreshOwnAuthorization(): void;
66
+ /** React to an authoritative NATS authentication rejection during reconnect. */
67
+ observeTransportEvent(event: unknown): void;
68
+ /** Register the connection-owned usability withdrawal for own revocation. */
69
+ onOwnInvalidated(callback: () => void): void;
70
+ /** Register the connection-owned resumption after same-context coverage initialization. */
71
+ onOwnResumed(callback: () => void): void;
72
+ /** Wait until the connected registry is available. */
73
+ waitReady(options?: {
74
+ signal?: AbortSignal;
75
+ timeoutMs?: number;
76
+ }): Promise<void>;
77
+ /** Return current provider health. */
78
+ health(): AuthorizationProviderCacheHealth;
79
+ /** Return provider and registry I/O counters. */
80
+ ioCounters(): AuthorizationProviderIoCounters;
81
+ /** Apply framework-level NATS lifecycle state to provider readiness. */
82
+ observeConnectionPhase(phase: "connected" | "disconnected" | "reconnecting" | "error" | "closed"): void;
83
+ /** Resolve one context digest through the connected registry. */
84
+ resolveContext(contextDigest: string): Promise<VerifiedAuthorizationContextTokenProjection>;
85
+ /** Verify a presented request proof with exact route permissions. */
86
+ verifyRequest(request: AuthorizationProviderRequest): Promise<CachedRequestVerificationResult>;
87
+ /** Verify a presented event proof, including historical issuer evidence. */
88
+ verifyEvent(event: AuthorizationProviderEvent): Promise<CachedEventVerificationResult>;
89
+ }
90
+ export {};