@continuonai/rcan-ts 0.5.0 → 0.8.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/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -22,17 +32,23 @@ var index_exports = {};
22
32
  __export(index_exports, {
23
33
  AuditChain: () => AuditChain,
24
34
  AuditError: () => AuditError,
35
+ CONTRIBUTE_SCOPE_LEVEL: () => CONTRIBUTE_SCOPE_LEVEL,
25
36
  ClockDriftError: () => ClockDriftError,
26
37
  CommitmentRecord: () => CommitmentRecord,
27
38
  ConfidenceGate: () => ConfidenceGate,
39
+ DEFAULT_LOA_POLICY: () => DEFAULT_LOA_POLICY,
28
40
  DataCategory: () => DataCategory,
29
41
  FaultCode: () => FaultCode,
42
+ FederationSyncType: () => FederationSyncType,
30
43
  GateError: () => GateError,
31
44
  HiTLGate: () => HiTLGate,
32
45
  KeyStore: () => KeyStore,
46
+ LevelOfAssurance: () => LevelOfAssurance,
47
+ MediaEncoding: () => MediaEncoding,
33
48
  MessageType: () => MessageType,
34
49
  NodeClient: () => NodeClient,
35
50
  OfflineModeManager: () => OfflineModeManager,
51
+ PRODUCTION_LOA_POLICY: () => PRODUCTION_LOA_POLICY,
36
52
  QoSAckTimeoutError: () => QoSAckTimeoutError,
37
53
  QoSLevel: () => QoSLevel,
38
54
  QoSManager: () => QoSManager,
@@ -54,40 +70,66 @@ __export(index_exports, {
54
70
  RCANVersionIncompatibleError: () => RCANVersionIncompatibleError,
55
71
  RCAN_VERSION: () => RCAN_VERSION,
56
72
  RegistryClient: () => RegistryClient,
73
+ RegistryTier: () => RegistryTier,
57
74
  ReplayCache: () => ReplayCache,
58
75
  RevocationCache: () => RevocationCache,
59
76
  RobotURI: () => RobotURI,
60
77
  RobotURIError: () => RobotURIError,
61
78
  SAFETY_MESSAGE_TYPE: () => SAFETY_MESSAGE_TYPE,
79
+ SDK_VERSION: () => SDK_VERSION,
62
80
  SPEC_VERSION: () => SPEC_VERSION,
81
+ TransportEncoding: () => TransportEncoding,
82
+ TransportError: () => TransportError,
83
+ TrustAnchorCache: () => TrustAnchorCache,
63
84
  VERSION: () => VERSION,
64
85
  addDelegationHop: () => addDelegationHop,
86
+ addMediaInline: () => addMediaInline,
87
+ addMediaRef: () => addMediaRef,
65
88
  assertClockSynced: () => assertClockSynced,
66
89
  checkClockSync: () => checkClockSync,
67
90
  checkRevocation: () => checkRevocation,
91
+ decodeBleFrames: () => decodeBleFrames,
92
+ decodeCompact: () => decodeCompact,
93
+ decodeMinimal: () => decodeMinimal,
94
+ encodeBleFrames: () => encodeBleFrames,
95
+ encodeCompact: () => encodeCompact,
96
+ encodeMinimal: () => encodeMinimal,
97
+ extractLoaFromJwt: () => extractLoaFromJwt,
68
98
  fetchCanonicalSchema: () => fetchCanonicalSchema,
99
+ isPreemptedBy: () => isPreemptedBy,
69
100
  isSafetyMessage: () => isSafetyMessage,
70
101
  makeCloudRelayMessage: () => makeCloudRelayMessage,
71
102
  makeConfigUpdate: () => makeConfigUpdate,
72
103
  makeConsentDeny: () => makeConsentDeny,
73
104
  makeConsentGrant: () => makeConsentGrant,
74
105
  makeConsentRequest: () => makeConsentRequest,
106
+ makeContributeCancel: () => makeContributeCancel,
107
+ makeContributeRequest: () => makeContributeRequest,
108
+ makeContributeResult: () => makeContributeResult,
75
109
  makeEstopMessage: () => makeEstopMessage,
76
110
  makeEstopWithQoS: () => makeEstopWithQoS,
77
111
  makeFaultReport: () => makeFaultReport,
112
+ makeFederationSync: () => makeFederationSync,
78
113
  makeKeyRotationMessage: () => makeKeyRotationMessage,
79
114
  makeResumeMessage: () => makeResumeMessage,
80
115
  makeRevocationBroadcast: () => makeRevocationBroadcast,
81
116
  makeStopMessage: () => makeStopMessage,
117
+ makeStreamChunk: () => makeStreamChunk,
82
118
  makeTrainingConsentDeny: () => makeTrainingConsentDeny,
83
119
  makeTrainingConsentGrant: () => makeTrainingConsentGrant,
84
120
  makeTrainingConsentRequest: () => makeTrainingConsentRequest,
121
+ makeTrainingDataMessage: () => makeTrainingDataMessage,
85
122
  makeTransparencyMessage: () => makeTransparencyMessage,
123
+ selectTransport: () => selectTransport,
86
124
  validateConfig: () => validateConfig,
87
125
  validateConfigAgainstSchema: () => validateConfigAgainstSchema,
88
126
  validateConfigUpdate: () => validateConfigUpdate,
89
127
  validateConsentMessage: () => validateConsentMessage,
128
+ validateContributeScope: () => validateContributeScope,
129
+ validateCrossRegistryCommand: () => validateCrossRegistryCommand,
90
130
  validateDelegationChain: () => validateDelegationChain,
131
+ validateLoaForScope: () => validateLoaForScope,
132
+ validateMediaChunks: () => validateMediaChunks,
91
133
  validateMessage: () => validateMessage,
92
134
  validateNodeAgainstSchema: () => validateNodeAgainstSchema,
93
135
  validateReplay: () => validateReplay,
@@ -189,7 +231,8 @@ var RobotURI = class _RobotURI {
189
231
  };
190
232
 
191
233
  // src/version.ts
192
- var SPEC_VERSION = "1.5";
234
+ var SPEC_VERSION = "1.9.0";
235
+ var SDK_VERSION = "0.8.0";
193
236
  function validateVersionCompat(incomingVersion, localVersion = SPEC_VERSION) {
194
237
  const parseParts = (v) => {
195
238
  const parts = v.split(".");
@@ -210,18 +253,18 @@ var MessageType = /* @__PURE__ */ ((MessageType2) => {
210
253
  MessageType2[MessageType2["HEARTBEAT"] = 4] = "HEARTBEAT";
211
254
  MessageType2[MessageType2["CONFIG"] = 5] = "CONFIG";
212
255
  MessageType2[MessageType2["SAFETY"] = 6] = "SAFETY";
213
- MessageType2[MessageType2["SENSOR_DATA"] = 7] = "SENSOR_DATA";
214
- MessageType2[MessageType2["AUDIT"] = 8] = "AUDIT";
256
+ MessageType2[MessageType2["AUTH"] = 7] = "AUTH";
257
+ MessageType2[MessageType2["ERROR"] = 8] = "ERROR";
215
258
  MessageType2[MessageType2["DISCOVER"] = 9] = "DISCOVER";
216
- MessageType2[MessageType2["TRAINING_DATA"] = 10] = "TRAINING_DATA";
217
- MessageType2[MessageType2["TRANSPARENCY"] = 11] = "TRANSPARENCY";
218
- MessageType2[MessageType2["FEDERATION_SYNC"] = 12] = "FEDERATION_SYNC";
219
- MessageType2[MessageType2["ALERT"] = 13] = "ALERT";
220
- MessageType2[MessageType2["TELEOP"] = 14] = "TELEOP";
221
- MessageType2[MessageType2["CHAT"] = 15] = "CHAT";
222
- MessageType2[MessageType2["ERROR"] = 16] = "ERROR";
259
+ MessageType2[MessageType2["PENDING_AUTH"] = 10] = "PENDING_AUTH";
260
+ MessageType2[MessageType2["INVOKE"] = 11] = "INVOKE";
261
+ MessageType2[MessageType2["INVOKE_RESULT"] = 12] = "INVOKE_RESULT";
262
+ MessageType2[MessageType2["INVOKE_CANCEL"] = 13] = "INVOKE_CANCEL";
263
+ MessageType2[MessageType2["REGISTRY_REGISTER"] = 14] = "REGISTRY_REGISTER";
264
+ MessageType2[MessageType2["REGISTRY_RESOLVE"] = 15] = "REGISTRY_RESOLVE";
265
+ MessageType2[MessageType2["TRANSPARENCY"] = 16] = "TRANSPARENCY";
223
266
  MessageType2[MessageType2["COMMAND_ACK"] = 17] = "COMMAND_ACK";
224
- MessageType2[MessageType2["COMMAND_COMMIT"] = 18] = "COMMAND_COMMIT";
267
+ MessageType2[MessageType2["COMMAND_NACK"] = 18] = "COMMAND_NACK";
225
268
  MessageType2[MessageType2["ROBOT_REVOCATION"] = 19] = "ROBOT_REVOCATION";
226
269
  MessageType2[MessageType2["CONSENT_REQUEST"] = 20] = "CONSENT_REQUEST";
227
270
  MessageType2[MessageType2["CONSENT_GRANT"] = 21] = "CONSENT_GRANT";
@@ -230,7 +273,19 @@ var MessageType = /* @__PURE__ */ ((MessageType2) => {
230
273
  MessageType2[MessageType2["SUBSCRIBE"] = 24] = "SUBSCRIBE";
231
274
  MessageType2[MessageType2["UNSUBSCRIBE"] = 25] = "UNSUBSCRIBE";
232
275
  MessageType2[MessageType2["FAULT_REPORT"] = 26] = "FAULT_REPORT";
233
- MessageType2[MessageType2["COMMAND_NACK"] = 27] = "COMMAND_NACK";
276
+ MessageType2[MessageType2["KEY_ROTATION"] = 27] = "KEY_ROTATION";
277
+ MessageType2[MessageType2["COMMAND_COMMIT"] = 28] = "COMMAND_COMMIT";
278
+ MessageType2[MessageType2["SENSOR_DATA"] = 29] = "SENSOR_DATA";
279
+ MessageType2[MessageType2["TRAINING_CONSENT_REQUEST"] = 30] = "TRAINING_CONSENT_REQUEST";
280
+ MessageType2[MessageType2["TRAINING_CONSENT_GRANT"] = 31] = "TRAINING_CONSENT_GRANT";
281
+ MessageType2[MessageType2["TRAINING_CONSENT_DENY"] = 32] = "TRAINING_CONSENT_DENY";
282
+ MessageType2[MessageType2["CONTRIBUTE_REQUEST"] = 33] = "CONTRIBUTE_REQUEST";
283
+ MessageType2[MessageType2["CONTRIBUTE_RESULT"] = 34] = "CONTRIBUTE_RESULT";
284
+ MessageType2[MessageType2["CONTRIBUTE_CANCEL"] = 35] = "CONTRIBUTE_CANCEL";
285
+ MessageType2[MessageType2["TRAINING_DATA"] = 36] = "TRAINING_DATA";
286
+ MessageType2[MessageType2["FEDERATION_SYNC"] = 23] = "FEDERATION_SYNC";
287
+ MessageType2[MessageType2["ALERT"] = 26] = "ALERT";
288
+ MessageType2[MessageType2["AUDIT"] = 16] = "AUDIT";
234
289
  return MessageType2;
235
290
  })(MessageType || {});
236
291
  var RCANMessageError = class extends Error {
@@ -260,6 +315,12 @@ var RCANMessage = class _RCANMessage {
260
315
  presenceVerified;
261
316
  proximityMeters;
262
317
  readOnly;
318
+ /** v1.6: GAP-14 level of assurance */
319
+ loa;
320
+ /** v1.6: GAP-17 transport encoding hint */
321
+ transportEncoding;
322
+ /** v1.6: GAP-18 multi-modal media chunks */
323
+ mediaChunks;
263
324
  constructor(data) {
264
325
  if (!data.cmd || data.cmd.trim() === "") {
265
326
  throw new RCANMessageError("'cmd' is required");
@@ -285,6 +346,9 @@ var RCANMessage = class _RCANMessage {
285
346
  this.presenceVerified = data.presenceVerified;
286
347
  this.proximityMeters = data.proximityMeters;
287
348
  this.readOnly = data.readOnly;
349
+ this.loa = data.loa;
350
+ this.transportEncoding = data.transportEncoding;
351
+ this.mediaChunks = data.mediaChunks;
288
352
  if (this.confidence !== void 0) {
289
353
  if (this.confidence < 0 || this.confidence > 1) {
290
354
  throw new RCANMessageError(
@@ -323,6 +387,9 @@ var RCANMessage = class _RCANMessage {
323
387
  if (this.presenceVerified !== void 0) obj.presenceVerified = this.presenceVerified;
324
388
  if (this.proximityMeters !== void 0) obj.proximityMeters = this.proximityMeters;
325
389
  if (this.readOnly !== void 0) obj.readOnly = this.readOnly;
390
+ if (this.loa !== void 0) obj.loa = this.loa;
391
+ if (this.transportEncoding !== void 0) obj.transportEncoding = this.transportEncoding;
392
+ if (this.mediaChunks !== void 0) obj.mediaChunks = this.mediaChunks;
326
393
  return obj;
327
394
  }
328
395
  /** Serialize to JSON string */
@@ -362,7 +429,10 @@ var RCANMessage = class _RCANMessage {
362
429
  qos: obj.qos,
363
430
  presenceVerified: obj.presenceVerified,
364
431
  proximityMeters: obj.proximityMeters,
365
- readOnly: obj.readOnly
432
+ readOnly: obj.readOnly,
433
+ loa: obj.loa,
434
+ transportEncoding: obj.transportEncoding,
435
+ mediaChunks: obj.mediaChunks
366
436
  });
367
437
  }
368
438
  };
@@ -1335,6 +1405,7 @@ async function fetchCanonicalSchema(schemaName) {
1335
1405
  try {
1336
1406
  const controller = new AbortController();
1337
1407
  const timer = setTimeout(() => controller.abort(), 5e3);
1408
+ timer.unref?.();
1338
1409
  const res = await fetch(`${SCHEMA_BASE}/${schemaName}`, { signal: controller.signal });
1339
1410
  clearTimeout(timer);
1340
1411
  if (!res.ok) return null;
@@ -1975,7 +2046,7 @@ function makeTrainingConsentDeny(params) {
1975
2046
  return makeConsentDeny(params);
1976
2047
  }
1977
2048
  function validateTrainingDataMessage(msg) {
1978
- if (msg.params.message_type !== 10 /* TRAINING_DATA */) {
2049
+ if (msg.params.message_type !== 36 /* TRAINING_DATA */) {
1979
2050
  return { valid: false, reason: "not a TRAINING_DATA message" };
1980
2051
  }
1981
2052
  const token = msg.params.consent_token;
@@ -2114,24 +2185,709 @@ function makeFaultReport(params) {
2114
2185
  });
2115
2186
  }
2116
2187
 
2188
+ // src/identity.ts
2189
+ var LevelOfAssurance = /* @__PURE__ */ ((LevelOfAssurance2) => {
2190
+ LevelOfAssurance2[LevelOfAssurance2["ANONYMOUS"] = 1] = "ANONYMOUS";
2191
+ LevelOfAssurance2[LevelOfAssurance2["EMAIL_VERIFIED"] = 2] = "EMAIL_VERIFIED";
2192
+ LevelOfAssurance2[LevelOfAssurance2["HARDWARE_TOKEN"] = 3] = "HARDWARE_TOKEN";
2193
+ return LevelOfAssurance2;
2194
+ })(LevelOfAssurance || {});
2195
+ var DEFAULT_LOA_POLICY = {
2196
+ minLoaDiscover: 1 /* ANONYMOUS */,
2197
+ minLoaStatus: 1 /* ANONYMOUS */,
2198
+ minLoaChat: 1 /* ANONYMOUS */,
2199
+ minLoaControl: 1 /* ANONYMOUS */,
2200
+ minLoaSafety: 1 /* ANONYMOUS */
2201
+ };
2202
+ var PRODUCTION_LOA_POLICY = {
2203
+ minLoaDiscover: 1 /* ANONYMOUS */,
2204
+ minLoaStatus: 1 /* ANONYMOUS */,
2205
+ minLoaChat: 1 /* ANONYMOUS */,
2206
+ minLoaControl: 2 /* EMAIL_VERIFIED */,
2207
+ minLoaSafety: 3 /* HARDWARE_TOKEN */
2208
+ };
2209
+ function extractLoaFromJwt(token) {
2210
+ try {
2211
+ const parts = token.split(".");
2212
+ if (parts.length < 2) return 1 /* ANONYMOUS */;
2213
+ const payloadB64 = (parts[1] ?? "").replace(/-/g, "+").replace(/_/g, "/");
2214
+ const padded = payloadB64 + "=".repeat((4 - payloadB64.length % 4) % 4);
2215
+ let json;
2216
+ if (typeof atob !== "undefined") {
2217
+ json = atob(padded);
2218
+ } else {
2219
+ json = Buffer.from(padded, "base64").toString("utf-8");
2220
+ }
2221
+ const claims = JSON.parse(json);
2222
+ const loa = claims["loa"];
2223
+ if (typeof loa === "number" && loa >= 1 && loa <= 3) {
2224
+ return loa;
2225
+ }
2226
+ } catch {
2227
+ }
2228
+ return 1 /* ANONYMOUS */;
2229
+ }
2230
+ function minLoaForScope(scope, policy) {
2231
+ const s = scope.toLowerCase();
2232
+ switch (s) {
2233
+ case "discover":
2234
+ return policy.minLoaDiscover;
2235
+ case "status":
2236
+ return policy.minLoaStatus;
2237
+ case "chat":
2238
+ return policy.minLoaChat;
2239
+ case "contribute":
2240
+ return policy.minLoaChat;
2241
+ // v1.7: between chat and control
2242
+ case "control":
2243
+ return policy.minLoaControl;
2244
+ case "safety":
2245
+ return policy.minLoaSafety;
2246
+ default:
2247
+ return null;
2248
+ }
2249
+ }
2250
+ function validateLoaForScope(loa, scope, policy = DEFAULT_LOA_POLICY) {
2251
+ const min = minLoaForScope(scope, policy);
2252
+ if (min === null) {
2253
+ return { valid: true, reason: "unknown scope; allowed by default" };
2254
+ }
2255
+ if (loa >= min) {
2256
+ return { valid: true, reason: "ok" };
2257
+ }
2258
+ return {
2259
+ valid: false,
2260
+ reason: `LOA_INSUFFICIENT: scope=${scope} requires LoA>=${min}, caller has LoA=${loa}`
2261
+ };
2262
+ }
2263
+
2264
+ // src/federation.ts
2265
+ var RegistryTier = /* @__PURE__ */ ((RegistryTier2) => {
2266
+ RegistryTier2["ROOT"] = "root";
2267
+ RegistryTier2["AUTHORITATIVE"] = "authoritative";
2268
+ RegistryTier2["COMMUNITY"] = "community";
2269
+ return RegistryTier2;
2270
+ })(RegistryTier || {});
2271
+ var FederationSyncType = /* @__PURE__ */ ((FederationSyncType2) => {
2272
+ FederationSyncType2["CONSENT"] = "consent";
2273
+ FederationSyncType2["REVOCATION"] = "revocation";
2274
+ FederationSyncType2["KEY"] = "key";
2275
+ return FederationSyncType2;
2276
+ })(FederationSyncType || {});
2277
+ var CACHE_TTL_MS2 = 24 * 60 * 60 * 1e3;
2278
+ var TrustAnchorCache = class {
2279
+ store = /* @__PURE__ */ new Map();
2280
+ /** Store or refresh a registry identity. */
2281
+ set(identity) {
2282
+ this.store.set(identity.registryUrl, {
2283
+ identity,
2284
+ expiresAt: Date.now() + CACHE_TTL_MS2
2285
+ });
2286
+ }
2287
+ /**
2288
+ * Look up a registry URL.
2289
+ * Returns undefined when absent or when the TTL has expired.
2290
+ */
2291
+ lookup(url) {
2292
+ const entry = this.store.get(url);
2293
+ if (!entry) return void 0;
2294
+ if (Date.now() > entry.expiresAt) {
2295
+ this.store.delete(url);
2296
+ return void 0;
2297
+ }
2298
+ return entry.identity;
2299
+ }
2300
+ /**
2301
+ * Discover a registry via DNS TXT record `_rcan-registry.<domain>`.
2302
+ *
2303
+ * The TXT record is expected to contain a JSON object with the
2304
+ * RegistryIdentity fields. Returns the identity and caches it.
2305
+ *
2306
+ * Node.js only — returns undefined in environments without `dns.promises`.
2307
+ */
2308
+ async discoverViaDns(domain) {
2309
+ const hostname = `_rcan-registry.${domain}`;
2310
+ let records;
2311
+ try {
2312
+ const dnsModule = require("dns");
2313
+ records = await dnsModule.promises.resolveTxt(hostname);
2314
+ } catch {
2315
+ return void 0;
2316
+ }
2317
+ for (const record of records) {
2318
+ const text = record.join("");
2319
+ try {
2320
+ const parsed = JSON.parse(text);
2321
+ if (parsed.registryUrl && parsed.tier && parsed.publicKeyPem && parsed.domain) {
2322
+ const identity = {
2323
+ registryUrl: parsed.registryUrl,
2324
+ tier: parsed.tier,
2325
+ publicKeyPem: parsed.publicKeyPem,
2326
+ domain: parsed.domain,
2327
+ verifiedAt: (/* @__PURE__ */ new Date()).toISOString()
2328
+ };
2329
+ this.set(identity);
2330
+ return identity;
2331
+ }
2332
+ } catch {
2333
+ }
2334
+ }
2335
+ return void 0;
2336
+ }
2337
+ /**
2338
+ * Verify a JWT was issued by the registry at `url`.
2339
+ *
2340
+ * Validates the `iss` claim and checks the registry is in the trust cache.
2341
+ * Full cryptographic signature verification requires the registry's public
2342
+ * key material — callers should perform additional checks using `publicKeyPem`
2343
+ * from the returned identity.
2344
+ */
2345
+ async verifyRegistryJwt(token, url) {
2346
+ const identity = this.lookup(url);
2347
+ if (!identity) {
2348
+ throw new Error(`REGISTRY_UNKNOWN: ${url} is not in the trust cache`);
2349
+ }
2350
+ let iss;
2351
+ try {
2352
+ const parts = token.split(".");
2353
+ const payloadB64 = (parts[1] ?? "").replace(/-/g, "+").replace(/_/g, "/");
2354
+ const padded = payloadB64 + "=".repeat((4 - payloadB64.length % 4) % 4);
2355
+ let json;
2356
+ if (typeof atob !== "undefined") {
2357
+ json = atob(padded);
2358
+ } else {
2359
+ json = Buffer.from(padded, "base64").toString("utf-8");
2360
+ }
2361
+ const claims = JSON.parse(json);
2362
+ iss = typeof claims["iss"] === "string" ? claims["iss"] : void 0;
2363
+ } catch {
2364
+ throw new Error("REGISTRY_JWT_MALFORMED: cannot decode token payload");
2365
+ }
2366
+ if (iss !== url) {
2367
+ throw new Error(
2368
+ `REGISTRY_JWT_ISS_MISMATCH: expected iss=${url}, got iss=${iss ?? "(none)"}`
2369
+ );
2370
+ }
2371
+ return identity;
2372
+ }
2373
+ };
2374
+ function generateId5() {
2375
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
2376
+ return crypto.randomUUID();
2377
+ }
2378
+ const bytes = Array.from({ length: 16 }, () => Math.floor(Math.random() * 256));
2379
+ bytes[6] = (bytes[6] ?? 0) & 15 | 64;
2380
+ bytes[8] = (bytes[8] ?? 0) & 63 | 128;
2381
+ const hex = bytes.map((b) => b.toString(16).padStart(2, "0"));
2382
+ return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`;
2383
+ }
2384
+ function makeFederationSync(source, target, syncType, payload) {
2385
+ return new RCANMessage({
2386
+ rcan: "1.6",
2387
+ rcanVersion: "1.6",
2388
+ cmd: "federation_sync",
2389
+ target,
2390
+ params: {
2391
+ msg_type: 23 /* FEDERATION_SYNC */,
2392
+ msg_id: generateId5(),
2393
+ source_registry: source,
2394
+ target_registry: target,
2395
+ sync_type: syncType,
2396
+ payload
2397
+ },
2398
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2399
+ });
2400
+ }
2401
+ async function validateCrossRegistryCommand(msg, localRegistry, trustCache) {
2402
+ const msgType = msg.params?.["msg_type"];
2403
+ const isEstop = msgType === 6 /* SAFETY */ || msgType === 6 || msg.cmd === "estop" || msg.cmd === "ESTOP";
2404
+ if (isEstop) {
2405
+ return { valid: true, reason: "ESTOP always permitted (P66 invariant)" };
2406
+ }
2407
+ const sourceRegistry = msg.params?.["source_registry"] ?? msg.params?.["from_registry"];
2408
+ if (!sourceRegistry || sourceRegistry === localRegistry) {
2409
+ return { valid: true, reason: "local registry; no federation check needed" };
2410
+ }
2411
+ const identity = trustCache.lookup(sourceRegistry);
2412
+ if (!identity) {
2413
+ return {
2414
+ valid: false,
2415
+ reason: `REGISTRY_UNKNOWN: ${sourceRegistry} is not in the local trust cache`
2416
+ };
2417
+ }
2418
+ let loa = 1 /* ANONYMOUS */;
2419
+ const registryJwt = msg.params?.["registry_jwt"];
2420
+ if (registryJwt) {
2421
+ loa = extractLoaFromJwt(registryJwt);
2422
+ } else if (typeof msg.loa === "number") {
2423
+ loa = msg.loa;
2424
+ }
2425
+ if (loa < 2 /* EMAIL_VERIFIED */) {
2426
+ return {
2427
+ valid: false,
2428
+ reason: `LOA_INSUFFICIENT: cross-registry commands require LoA>=2 (EMAIL_VERIFIED), got LoA=${loa}`
2429
+ };
2430
+ }
2431
+ return { valid: true, reason: "cross-registry command accepted" };
2432
+ }
2433
+
2434
+ // src/transport.ts
2435
+ var TransportError = class _TransportError extends Error {
2436
+ constructor(message) {
2437
+ super(message);
2438
+ this.name = "TransportError";
2439
+ Object.setPrototypeOf(this, _TransportError.prototype);
2440
+ }
2441
+ };
2442
+ var TransportEncoding = /* @__PURE__ */ ((TransportEncoding2) => {
2443
+ TransportEncoding2["HTTP"] = "http";
2444
+ TransportEncoding2["COMPACT"] = "compact";
2445
+ TransportEncoding2["MINIMAL"] = "minimal";
2446
+ TransportEncoding2["BLE"] = "ble";
2447
+ return TransportEncoding2;
2448
+ })(TransportEncoding || {});
2449
+ var COMPACT_ENCODE = {
2450
+ msg_type: "t",
2451
+ msg_id: "i",
2452
+ timestamp: "ts",
2453
+ from_rrn: "f",
2454
+ to_rrn: "to",
2455
+ scope: "s",
2456
+ payload: "p",
2457
+ signature: "sig"
2458
+ };
2459
+ var COMPACT_DECODE = Object.fromEntries(
2460
+ Object.entries(COMPACT_ENCODE).map(([k, v]) => [v, k])
2461
+ );
2462
+ function encodeCompact(message) {
2463
+ const full = message.toJSON();
2464
+ const compact = {};
2465
+ for (const [key, value] of Object.entries(full)) {
2466
+ const short = COMPACT_ENCODE[key];
2467
+ compact[short ?? key] = value;
2468
+ }
2469
+ if (compact["p"] && typeof compact["p"] === "object") {
2470
+ const params = compact["p"];
2471
+ const compactParams = {};
2472
+ for (const [k, v] of Object.entries(params)) {
2473
+ const short = COMPACT_ENCODE[k];
2474
+ compactParams[short ?? k] = v;
2475
+ }
2476
+ compact["p"] = compactParams;
2477
+ }
2478
+ const json = JSON.stringify(compact);
2479
+ const encoder = new TextEncoder();
2480
+ return encoder.encode(json);
2481
+ }
2482
+ function decodeCompact(data) {
2483
+ const decoder = new TextDecoder();
2484
+ const json = decoder.decode(data);
2485
+ const compact = JSON.parse(json);
2486
+ const full = {};
2487
+ for (const [key, value] of Object.entries(compact)) {
2488
+ const long = COMPACT_DECODE[key];
2489
+ full[long ?? key] = value;
2490
+ }
2491
+ if (full["payload"] && typeof full["payload"] === "object") {
2492
+ const params = full["payload"];
2493
+ const expandedParams = {};
2494
+ for (const [k, v] of Object.entries(params)) {
2495
+ const long = COMPACT_DECODE[k];
2496
+ expandedParams[long ?? k] = v;
2497
+ }
2498
+ full["payload"] = expandedParams;
2499
+ }
2500
+ return new RCANMessage({
2501
+ rcan: full["rcan"] ?? "1.6",
2502
+ rcanVersion: full["rcanVersion"],
2503
+ cmd: full["cmd"],
2504
+ target: full["target"],
2505
+ params: full["params"] ?? full["payload"] ?? {},
2506
+ timestamp: full["timestamp"],
2507
+ confidence: full["confidence"],
2508
+ signature: full["signature"]
2509
+ });
2510
+ }
2511
+ var MINIMAL_SIZE = 32;
2512
+ var SAFETY_TYPE = 6;
2513
+ async function sha256Bytes(input) {
2514
+ const encoded = new TextEncoder().encode(input);
2515
+ const ab = new ArrayBuffer(encoded.byteLength);
2516
+ new Uint8Array(ab).set(encoded);
2517
+ const subtle = globalThis.crypto?.subtle ?? (await import("crypto")).webcrypto.subtle;
2518
+ const hashBuffer = await subtle.digest("SHA-256", ab);
2519
+ return new Uint8Array(hashBuffer);
2520
+ }
2521
+ async function encodeMinimal(message) {
2522
+ const msgType = message.params?.["msg_type"] ?? 0;
2523
+ if (msgType !== SAFETY_TYPE) {
2524
+ throw new TransportError(
2525
+ `encodeMinimal only supports SAFETY (type 6) messages; got type=${msgType}`
2526
+ );
2527
+ }
2528
+ const fromRrn = message.params?.["from_rrn"] ?? message.target ?? "";
2529
+ const toRrn = message.params?.["to_rrn"] ?? message.target ?? "";
2530
+ const fromHash = await sha256Bytes(fromRrn);
2531
+ const toHash = await sha256Bytes(toRrn);
2532
+ const sig = (message.signature?.sig ?? "").replace(/[^A-Za-z0-9+/=]/g, "");
2533
+ let sigBytes;
2534
+ try {
2535
+ if (typeof atob !== "undefined") {
2536
+ const raw = atob(sig.slice(0, 16));
2537
+ sigBytes = new Uint8Array(raw.length);
2538
+ for (let i = 0; i < raw.length; i++) sigBytes[i] = raw.charCodeAt(i);
2539
+ } else {
2540
+ sigBytes = Buffer.from(sig.slice(0, 16), "base64");
2541
+ }
2542
+ } catch {
2543
+ sigBytes = new Uint8Array(8);
2544
+ }
2545
+ const ts = message.timestamp ? Math.floor(new Date(message.timestamp).getTime() / 1e3) : Math.floor(Date.now() / 1e3);
2546
+ const unix32 = ts >>> 0;
2547
+ const out = new Uint8Array(MINIMAL_SIZE);
2548
+ const view = new DataView(out.buffer);
2549
+ view.setUint16(0, SAFETY_TYPE, false);
2550
+ out.set(fromHash.subarray(0, 8), 2);
2551
+ out.set(toHash.subarray(0, 8), 10);
2552
+ view.setUint32(18, unix32, false);
2553
+ const sigSlice = new Uint8Array(8);
2554
+ sigSlice.set(sigBytes.subarray(0, Math.min(8, sigBytes.length)));
2555
+ out.set(sigSlice, 22);
2556
+ let checksum = 0;
2557
+ for (let i = 0; i < 30; i++) checksum ^= out[i] ?? 0;
2558
+ view.setUint16(30, checksum & 65535, false);
2559
+ if (out.length !== MINIMAL_SIZE) {
2560
+ throw new TransportError(
2561
+ `encodeMinimal assertion failed: expected ${MINIMAL_SIZE} bytes, got ${out.length}`
2562
+ );
2563
+ }
2564
+ return out;
2565
+ }
2566
+ function decodeMinimal(data) {
2567
+ if (data.length !== MINIMAL_SIZE) {
2568
+ throw new TransportError(
2569
+ `decodeMinimal: expected ${MINIMAL_SIZE} bytes, got ${data.length}`
2570
+ );
2571
+ }
2572
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
2573
+ const msgType = view.getUint16(0, false);
2574
+ const fromHash = data.subarray(2, 10);
2575
+ const toHash = data.subarray(10, 18);
2576
+ const unix32 = view.getUint32(18, false);
2577
+ const sigTrunc = data.subarray(22, 30);
2578
+ const timestamp = new Date(unix32 * 1e3).toISOString();
2579
+ const toHex2 = (b) => Array.from(b).map((x) => x.toString(16).padStart(2, "0")).join("");
2580
+ return {
2581
+ params: {
2582
+ msg_type: msgType,
2583
+ from_hash: toHex2(fromHash),
2584
+ to_hash: toHex2(toHash),
2585
+ timestamp_s: unix32,
2586
+ sig_truncated: toHex2(sigTrunc)
2587
+ },
2588
+ timestamp
2589
+ };
2590
+ }
2591
+ var DEFAULT_MTU = 251;
2592
+ var BLE_HEADER_SIZE = 3;
2593
+ function encodeBleFrames(message, mtu = DEFAULT_MTU) {
2594
+ const payload = encodeCompact(message);
2595
+ const chunkSize = mtu - BLE_HEADER_SIZE;
2596
+ if (chunkSize <= 0) {
2597
+ throw new TransportError(`MTU ${mtu} is too small (need at least ${BLE_HEADER_SIZE + 1})`);
2598
+ }
2599
+ const totalChunks = Math.ceil(payload.length / chunkSize);
2600
+ const frames = [];
2601
+ for (let i = 0; i < totalChunks; i++) {
2602
+ const chunk = payload.subarray(i * chunkSize, (i + 1) * chunkSize);
2603
+ const frame = new Uint8Array(BLE_HEADER_SIZE + chunk.length);
2604
+ frame[0] = i;
2605
+ frame[1] = totalChunks;
2606
+ frame[2] = i === totalChunks - 1 ? 1 : 0;
2607
+ frame.set(chunk, BLE_HEADER_SIZE);
2608
+ frames.push(frame);
2609
+ }
2610
+ return frames;
2611
+ }
2612
+ function decodeBleFrames(frames) {
2613
+ if (frames.length === 0) {
2614
+ throw new TransportError("decodeBleFrames: no frames provided");
2615
+ }
2616
+ const sorted = [...frames].sort((a, b) => (a[0] ?? 0) - (b[0] ?? 0));
2617
+ const expectedTotal = sorted[0]?.[1] ?? sorted.length;
2618
+ if (sorted.length !== expectedTotal) {
2619
+ throw new TransportError(
2620
+ `decodeBleFrames: expected ${expectedTotal} frames, got ${sorted.length}`
2621
+ );
2622
+ }
2623
+ const payloadChunks = sorted.map((f) => f.subarray(BLE_HEADER_SIZE));
2624
+ const totalLen = payloadChunks.reduce((s, c) => s + c.length, 0);
2625
+ const payload = new Uint8Array(totalLen);
2626
+ let offset = 0;
2627
+ for (const chunk of payloadChunks) {
2628
+ payload.set(chunk, offset);
2629
+ offset += chunk.length;
2630
+ }
2631
+ return decodeCompact(payload);
2632
+ }
2633
+ function selectTransport(available, message) {
2634
+ const msgType = message.params?.["msg_type"] ?? 0;
2635
+ const isSafety = msgType === SAFETY_TYPE;
2636
+ const has = (enc) => available.includes(enc);
2637
+ if (isSafety) {
2638
+ if (has("minimal" /* MINIMAL */)) return "minimal" /* MINIMAL */;
2639
+ if (has("ble" /* BLE */)) return "ble" /* BLE */;
2640
+ if (has("compact" /* COMPACT */)) return "compact" /* COMPACT */;
2641
+ if (has("http" /* HTTP */)) return "http" /* HTTP */;
2642
+ } else {
2643
+ if (has("http" /* HTTP */)) return "http" /* HTTP */;
2644
+ if (has("compact" /* COMPACT */)) return "compact" /* COMPACT */;
2645
+ if (has("ble" /* BLE */)) return "ble" /* BLE */;
2646
+ }
2647
+ throw new TransportError(
2648
+ `No suitable transport available from: [${available.join(", ")}]`
2649
+ );
2650
+ }
2651
+
2652
+ // src/multimodal.ts
2653
+ var MediaEncoding = /* @__PURE__ */ ((MediaEncoding2) => {
2654
+ MediaEncoding2["BASE64"] = "base64";
2655
+ MediaEncoding2["REF"] = "ref";
2656
+ return MediaEncoding2;
2657
+ })(MediaEncoding || {});
2658
+ function generateId6() {
2659
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
2660
+ return crypto.randomUUID();
2661
+ }
2662
+ const bytes = Array.from({ length: 16 }, () => Math.floor(Math.random() * 256));
2663
+ bytes[6] = (bytes[6] ?? 0) & 15 | 64;
2664
+ bytes[8] = (bytes[8] ?? 0) & 63 | 128;
2665
+ const hex = bytes.map((b) => b.toString(16).padStart(2, "0"));
2666
+ return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`;
2667
+ }
2668
+ async function computeSha256Hex(data) {
2669
+ const subtle = globalThis.crypto?.subtle ?? (await import("crypto")).webcrypto.subtle;
2670
+ const ab = new ArrayBuffer(data.byteLength);
2671
+ new Uint8Array(ab).set(data);
2672
+ const hashBuffer = await subtle.digest("SHA-256", ab);
2673
+ const hashArray = new Uint8Array(hashBuffer);
2674
+ return Array.from(hashArray).map((b) => b.toString(16).padStart(2, "0")).join("");
2675
+ }
2676
+ function uint8ToBase64(data) {
2677
+ if (typeof Buffer !== "undefined") {
2678
+ return Buffer.from(data).toString("base64");
2679
+ }
2680
+ let binary = "";
2681
+ for (let i = 0; i < data.length; i++) binary += String.fromCharCode(data[i] ?? 0);
2682
+ return btoa(binary);
2683
+ }
2684
+ function rebuildMessage(base, overrides) {
2685
+ const data = { ...base.toJSON(), ...overrides };
2686
+ return RCANMessage.fromJSON(data);
2687
+ }
2688
+ async function addMediaInline(message, data, mimeType) {
2689
+ const hashSha256 = await computeSha256Hex(data);
2690
+ const dataB64 = uint8ToBase64(data);
2691
+ const chunk = {
2692
+ chunkId: generateId6(),
2693
+ mimeType,
2694
+ encoding: "base64" /* BASE64 */,
2695
+ hashSha256,
2696
+ dataB64,
2697
+ sizeBytes: data.length
2698
+ };
2699
+ const existing = message.mediaChunks ?? [];
2700
+ return rebuildMessage(message, { mediaChunks: [...existing, chunk] });
2701
+ }
2702
+ function addMediaRef(message, refUrl, mimeType, hashSha256, sizeBytes) {
2703
+ const chunk = {
2704
+ chunkId: generateId6(),
2705
+ mimeType,
2706
+ encoding: "ref" /* REF */,
2707
+ hashSha256,
2708
+ refUrl,
2709
+ sizeBytes
2710
+ };
2711
+ const existing = message.mediaChunks ?? [];
2712
+ return rebuildMessage(message, { mediaChunks: [...existing, chunk] });
2713
+ }
2714
+ async function validateMediaChunks(message) {
2715
+ const chunks = message.mediaChunks ?? [];
2716
+ if (chunks.length === 0) {
2717
+ return { valid: true, reason: "no media chunks" };
2718
+ }
2719
+ for (let i = 0; i < chunks.length; i++) {
2720
+ const chunk = chunks[i];
2721
+ if (!chunk.chunkId) return { valid: false, reason: `chunk[${i}]: missing chunkId` };
2722
+ if (!chunk.mimeType) return { valid: false, reason: `chunk[${i}]: missing mimeType` };
2723
+ if (!chunk.hashSha256) return { valid: false, reason: `chunk[${i}]: missing hashSha256` };
2724
+ if (chunk.sizeBytes < 0) return { valid: false, reason: `chunk[${i}]: sizeBytes must be >= 0` };
2725
+ if (chunk.encoding === "base64" /* BASE64 */) {
2726
+ if (!chunk.dataB64) {
2727
+ return { valid: false, reason: `chunk[${i}]: BASE64 encoding requires dataB64` };
2728
+ }
2729
+ let decoded;
2730
+ try {
2731
+ if (typeof Buffer !== "undefined") {
2732
+ decoded = Buffer.from(chunk.dataB64, "base64");
2733
+ } else {
2734
+ const raw = atob(chunk.dataB64);
2735
+ decoded = new Uint8Array(raw.length);
2736
+ for (let j = 0; j < raw.length; j++) decoded[j] = raw.charCodeAt(j);
2737
+ }
2738
+ } catch {
2739
+ return { valid: false, reason: `chunk[${i}]: failed to decode base64 data` };
2740
+ }
2741
+ const actualHash = await computeSha256Hex(decoded);
2742
+ if (actualHash !== chunk.hashSha256) {
2743
+ return {
2744
+ valid: false,
2745
+ reason: `chunk[${i}]: SHA-256 mismatch (expected ${chunk.hashSha256}, got ${actualHash})`
2746
+ };
2747
+ }
2748
+ } else if (chunk.encoding === "ref" /* REF */) {
2749
+ if (!chunk.refUrl) {
2750
+ return { valid: false, reason: `chunk[${i}]: REF encoding requires refUrl` };
2751
+ }
2752
+ } else {
2753
+ return { valid: false, reason: `chunk[${i}]: unknown encoding '${chunk.encoding}'` };
2754
+ }
2755
+ }
2756
+ return { valid: true, reason: "ok" };
2757
+ }
2758
+ async function makeTrainingDataMessage(media) {
2759
+ let msg = new RCANMessage({
2760
+ rcan: "1.6",
2761
+ rcanVersion: "1.6",
2762
+ cmd: "training_data",
2763
+ target: "rcan://training/data",
2764
+ params: {
2765
+ msg_type: 36 /* TRAINING_DATA */,
2766
+ msg_id: generateId6()
2767
+ },
2768
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2769
+ });
2770
+ for (const item of media) {
2771
+ msg = await addMediaInline(msg, item.data, item.mimeType);
2772
+ }
2773
+ return msg;
2774
+ }
2775
+ async function makeStreamChunk(streamId, data, mimeType, chunkIndex, isFinal) {
2776
+ const hashSha256 = await computeSha256Hex(data);
2777
+ const dataB64 = uint8ToBase64(data);
2778
+ const chunk = {
2779
+ chunkId: generateId6(),
2780
+ mimeType,
2781
+ encoding: "base64" /* BASE64 */,
2782
+ hashSha256,
2783
+ dataB64,
2784
+ sizeBytes: data.length
2785
+ };
2786
+ const streamChunkMeta = {
2787
+ streamId,
2788
+ chunkIndex,
2789
+ isFinal,
2790
+ chunk
2791
+ };
2792
+ let msg = new RCANMessage({
2793
+ rcan: "1.6",
2794
+ rcanVersion: "1.6",
2795
+ cmd: "stream_chunk",
2796
+ target: "rcan://streaming/chunk",
2797
+ params: {
2798
+ msg_type: 29 /* SENSOR_DATA */,
2799
+ msg_id: generateId6(),
2800
+ stream_chunk: streamChunkMeta
2801
+ },
2802
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2803
+ });
2804
+ msg = rebuildMessage(msg, { mediaChunks: [chunk] });
2805
+ return msg;
2806
+ }
2807
+
2808
+ // src/contribute.ts
2809
+ var CONTRIBUTE_SCOPE_LEVEL = 2.5;
2810
+ var _idCounter = 0;
2811
+ function _generateId() {
2812
+ return `cr-${Date.now()}-${++_idCounter}`;
2813
+ }
2814
+ function makeContributeRequest(params = {}) {
2815
+ return {
2816
+ type: 33 /* CONTRIBUTE_REQUEST */,
2817
+ request_id: params.request_id ?? _generateId(),
2818
+ project_id: params.project_id ?? "",
2819
+ project_name: params.project_name ?? "",
2820
+ work_unit_id: params.work_unit_id ?? "",
2821
+ resource_type: params.resource_type ?? "cpu",
2822
+ estimated_duration_s: params.estimated_duration_s ?? 0,
2823
+ priority: params.priority ?? 0,
2824
+ payload: params.payload ?? {},
2825
+ timestamp: params.timestamp ?? Date.now() / 1e3
2826
+ };
2827
+ }
2828
+ function makeContributeResult(params = {}) {
2829
+ const result = {
2830
+ type: 34 /* CONTRIBUTE_RESULT */,
2831
+ request_id: params.request_id ?? "",
2832
+ work_unit_id: params.work_unit_id ?? "",
2833
+ status: params.status ?? "completed",
2834
+ resource_type: params.resource_type ?? "cpu",
2835
+ duration_s: params.duration_s ?? 0,
2836
+ compute_units: params.compute_units ?? 0,
2837
+ result_payload: params.result_payload ?? {},
2838
+ timestamp: params.timestamp ?? Date.now() / 1e3
2839
+ };
2840
+ if (params.error_message !== void 0) {
2841
+ result.error_message = params.error_message;
2842
+ }
2843
+ return result;
2844
+ }
2845
+ function makeContributeCancel(params = {}) {
2846
+ return {
2847
+ type: 35 /* CONTRIBUTE_CANCEL */,
2848
+ request_id: params.request_id ?? "",
2849
+ work_unit_id: params.work_unit_id ?? "",
2850
+ reason: params.reason ?? "",
2851
+ timestamp: params.timestamp ?? Date.now() / 1e3
2852
+ };
2853
+ }
2854
+ function validateContributeScope(scopeLevel, action = "request") {
2855
+ if (action === "request" || action === "result") {
2856
+ return scopeLevel >= CONTRIBUTE_SCOPE_LEVEL;
2857
+ }
2858
+ if (action === "cancel") {
2859
+ return scopeLevel >= 2;
2860
+ }
2861
+ return false;
2862
+ }
2863
+ function isPreemptedBy(scopeLevel) {
2864
+ return scopeLevel >= 3;
2865
+ }
2866
+
2117
2867
  // src/index.ts
2118
- var VERSION = "0.5.0";
2119
- var RCAN_VERSION = "1.5";
2868
+ var VERSION = "0.6.0";
2869
+ var RCAN_VERSION = "1.6";
2120
2870
  // Annotate the CommonJS export names for ESM import in node:
2121
2871
  0 && (module.exports = {
2122
2872
  AuditChain,
2123
2873
  AuditError,
2874
+ CONTRIBUTE_SCOPE_LEVEL,
2124
2875
  ClockDriftError,
2125
2876
  CommitmentRecord,
2126
2877
  ConfidenceGate,
2878
+ DEFAULT_LOA_POLICY,
2127
2879
  DataCategory,
2128
2880
  FaultCode,
2881
+ FederationSyncType,
2129
2882
  GateError,
2130
2883
  HiTLGate,
2131
2884
  KeyStore,
2885
+ LevelOfAssurance,
2886
+ MediaEncoding,
2132
2887
  MessageType,
2133
2888
  NodeClient,
2134
2889
  OfflineModeManager,
2890
+ PRODUCTION_LOA_POLICY,
2135
2891
  QoSAckTimeoutError,
2136
2892
  QoSLevel,
2137
2893
  QoSManager,
@@ -2153,40 +2909,66 @@ var RCAN_VERSION = "1.5";
2153
2909
  RCANVersionIncompatibleError,
2154
2910
  RCAN_VERSION,
2155
2911
  RegistryClient,
2912
+ RegistryTier,
2156
2913
  ReplayCache,
2157
2914
  RevocationCache,
2158
2915
  RobotURI,
2159
2916
  RobotURIError,
2160
2917
  SAFETY_MESSAGE_TYPE,
2918
+ SDK_VERSION,
2161
2919
  SPEC_VERSION,
2920
+ TransportEncoding,
2921
+ TransportError,
2922
+ TrustAnchorCache,
2162
2923
  VERSION,
2163
2924
  addDelegationHop,
2925
+ addMediaInline,
2926
+ addMediaRef,
2164
2927
  assertClockSynced,
2165
2928
  checkClockSync,
2166
2929
  checkRevocation,
2930
+ decodeBleFrames,
2931
+ decodeCompact,
2932
+ decodeMinimal,
2933
+ encodeBleFrames,
2934
+ encodeCompact,
2935
+ encodeMinimal,
2936
+ extractLoaFromJwt,
2167
2937
  fetchCanonicalSchema,
2938
+ isPreemptedBy,
2168
2939
  isSafetyMessage,
2169
2940
  makeCloudRelayMessage,
2170
2941
  makeConfigUpdate,
2171
2942
  makeConsentDeny,
2172
2943
  makeConsentGrant,
2173
2944
  makeConsentRequest,
2945
+ makeContributeCancel,
2946
+ makeContributeRequest,
2947
+ makeContributeResult,
2174
2948
  makeEstopMessage,
2175
2949
  makeEstopWithQoS,
2176
2950
  makeFaultReport,
2951
+ makeFederationSync,
2177
2952
  makeKeyRotationMessage,
2178
2953
  makeResumeMessage,
2179
2954
  makeRevocationBroadcast,
2180
2955
  makeStopMessage,
2956
+ makeStreamChunk,
2181
2957
  makeTrainingConsentDeny,
2182
2958
  makeTrainingConsentGrant,
2183
2959
  makeTrainingConsentRequest,
2960
+ makeTrainingDataMessage,
2184
2961
  makeTransparencyMessage,
2962
+ selectTransport,
2185
2963
  validateConfig,
2186
2964
  validateConfigAgainstSchema,
2187
2965
  validateConfigUpdate,
2188
2966
  validateConsentMessage,
2967
+ validateContributeScope,
2968
+ validateCrossRegistryCommand,
2189
2969
  validateDelegationChain,
2970
+ validateLoaForScope,
2971
+ validateMediaChunks,
2190
2972
  validateMessage,
2191
2973
  validateNodeAgainstSchema,
2192
2974
  validateReplay,