@continuonai/rcan-ts 0.5.0 → 0.6.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/README.md +1 -1
- package/dist/browser.d.mts +250 -5
- package/dist/browser.mjs +663 -4
- package/dist/browser.mjs.map +1 -1
- package/dist/index.d.mts +250 -5
- package/dist/index.d.ts +250 -5
- package/dist/index.js +687 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +661 -4
- package/dist/index.mjs.map +1 -1
- package/dist/rcan-validate.js +17 -2
- package/dist/rcan.iife.js +3 -3
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -25,14 +25,19 @@ __export(index_exports, {
|
|
|
25
25
|
ClockDriftError: () => ClockDriftError,
|
|
26
26
|
CommitmentRecord: () => CommitmentRecord,
|
|
27
27
|
ConfidenceGate: () => ConfidenceGate,
|
|
28
|
+
DEFAULT_LOA_POLICY: () => DEFAULT_LOA_POLICY,
|
|
28
29
|
DataCategory: () => DataCategory,
|
|
29
30
|
FaultCode: () => FaultCode,
|
|
31
|
+
FederationSyncType: () => FederationSyncType,
|
|
30
32
|
GateError: () => GateError,
|
|
31
33
|
HiTLGate: () => HiTLGate,
|
|
32
34
|
KeyStore: () => KeyStore,
|
|
35
|
+
LevelOfAssurance: () => LevelOfAssurance,
|
|
36
|
+
MediaEncoding: () => MediaEncoding,
|
|
33
37
|
MessageType: () => MessageType,
|
|
34
38
|
NodeClient: () => NodeClient,
|
|
35
39
|
OfflineModeManager: () => OfflineModeManager,
|
|
40
|
+
PRODUCTION_LOA_POLICY: () => PRODUCTION_LOA_POLICY,
|
|
36
41
|
QoSAckTimeoutError: () => QoSAckTimeoutError,
|
|
37
42
|
QoSLevel: () => QoSLevel,
|
|
38
43
|
QoSManager: () => QoSManager,
|
|
@@ -54,17 +59,31 @@ __export(index_exports, {
|
|
|
54
59
|
RCANVersionIncompatibleError: () => RCANVersionIncompatibleError,
|
|
55
60
|
RCAN_VERSION: () => RCAN_VERSION,
|
|
56
61
|
RegistryClient: () => RegistryClient,
|
|
62
|
+
RegistryTier: () => RegistryTier,
|
|
57
63
|
ReplayCache: () => ReplayCache,
|
|
58
64
|
RevocationCache: () => RevocationCache,
|
|
59
65
|
RobotURI: () => RobotURI,
|
|
60
66
|
RobotURIError: () => RobotURIError,
|
|
61
67
|
SAFETY_MESSAGE_TYPE: () => SAFETY_MESSAGE_TYPE,
|
|
68
|
+
SDK_VERSION: () => SDK_VERSION,
|
|
62
69
|
SPEC_VERSION: () => SPEC_VERSION,
|
|
70
|
+
TransportEncoding: () => TransportEncoding,
|
|
71
|
+
TransportError: () => TransportError,
|
|
72
|
+
TrustAnchorCache: () => TrustAnchorCache,
|
|
63
73
|
VERSION: () => VERSION,
|
|
64
74
|
addDelegationHop: () => addDelegationHop,
|
|
75
|
+
addMediaInline: () => addMediaInline,
|
|
76
|
+
addMediaRef: () => addMediaRef,
|
|
65
77
|
assertClockSynced: () => assertClockSynced,
|
|
66
78
|
checkClockSync: () => checkClockSync,
|
|
67
79
|
checkRevocation: () => checkRevocation,
|
|
80
|
+
decodeBleFrames: () => decodeBleFrames,
|
|
81
|
+
decodeCompact: () => decodeCompact,
|
|
82
|
+
decodeMinimal: () => decodeMinimal,
|
|
83
|
+
encodeBleFrames: () => encodeBleFrames,
|
|
84
|
+
encodeCompact: () => encodeCompact,
|
|
85
|
+
encodeMinimal: () => encodeMinimal,
|
|
86
|
+
extractLoaFromJwt: () => extractLoaFromJwt,
|
|
68
87
|
fetchCanonicalSchema: () => fetchCanonicalSchema,
|
|
69
88
|
isSafetyMessage: () => isSafetyMessage,
|
|
70
89
|
makeCloudRelayMessage: () => makeCloudRelayMessage,
|
|
@@ -75,19 +94,26 @@ __export(index_exports, {
|
|
|
75
94
|
makeEstopMessage: () => makeEstopMessage,
|
|
76
95
|
makeEstopWithQoS: () => makeEstopWithQoS,
|
|
77
96
|
makeFaultReport: () => makeFaultReport,
|
|
97
|
+
makeFederationSync: () => makeFederationSync,
|
|
78
98
|
makeKeyRotationMessage: () => makeKeyRotationMessage,
|
|
79
99
|
makeResumeMessage: () => makeResumeMessage,
|
|
80
100
|
makeRevocationBroadcast: () => makeRevocationBroadcast,
|
|
81
101
|
makeStopMessage: () => makeStopMessage,
|
|
102
|
+
makeStreamChunk: () => makeStreamChunk,
|
|
82
103
|
makeTrainingConsentDeny: () => makeTrainingConsentDeny,
|
|
83
104
|
makeTrainingConsentGrant: () => makeTrainingConsentGrant,
|
|
84
105
|
makeTrainingConsentRequest: () => makeTrainingConsentRequest,
|
|
106
|
+
makeTrainingDataMessage: () => makeTrainingDataMessage,
|
|
85
107
|
makeTransparencyMessage: () => makeTransparencyMessage,
|
|
108
|
+
selectTransport: () => selectTransport,
|
|
86
109
|
validateConfig: () => validateConfig,
|
|
87
110
|
validateConfigAgainstSchema: () => validateConfigAgainstSchema,
|
|
88
111
|
validateConfigUpdate: () => validateConfigUpdate,
|
|
89
112
|
validateConsentMessage: () => validateConsentMessage,
|
|
113
|
+
validateCrossRegistryCommand: () => validateCrossRegistryCommand,
|
|
90
114
|
validateDelegationChain: () => validateDelegationChain,
|
|
115
|
+
validateLoaForScope: () => validateLoaForScope,
|
|
116
|
+
validateMediaChunks: () => validateMediaChunks,
|
|
91
117
|
validateMessage: () => validateMessage,
|
|
92
118
|
validateNodeAgainstSchema: () => validateNodeAgainstSchema,
|
|
93
119
|
validateReplay: () => validateReplay,
|
|
@@ -189,7 +215,8 @@ var RobotURI = class _RobotURI {
|
|
|
189
215
|
};
|
|
190
216
|
|
|
191
217
|
// src/version.ts
|
|
192
|
-
var SPEC_VERSION = "1.
|
|
218
|
+
var SPEC_VERSION = "1.6";
|
|
219
|
+
var SDK_VERSION = "0.6.0";
|
|
193
220
|
function validateVersionCompat(incomingVersion, localVersion = SPEC_VERSION) {
|
|
194
221
|
const parseParts = (v) => {
|
|
195
222
|
const parts = v.split(".");
|
|
@@ -260,6 +287,12 @@ var RCANMessage = class _RCANMessage {
|
|
|
260
287
|
presenceVerified;
|
|
261
288
|
proximityMeters;
|
|
262
289
|
readOnly;
|
|
290
|
+
/** v1.6: GAP-14 level of assurance */
|
|
291
|
+
loa;
|
|
292
|
+
/** v1.6: GAP-17 transport encoding hint */
|
|
293
|
+
transportEncoding;
|
|
294
|
+
/** v1.6: GAP-18 multi-modal media chunks */
|
|
295
|
+
mediaChunks;
|
|
263
296
|
constructor(data) {
|
|
264
297
|
if (!data.cmd || data.cmd.trim() === "") {
|
|
265
298
|
throw new RCANMessageError("'cmd' is required");
|
|
@@ -285,6 +318,9 @@ var RCANMessage = class _RCANMessage {
|
|
|
285
318
|
this.presenceVerified = data.presenceVerified;
|
|
286
319
|
this.proximityMeters = data.proximityMeters;
|
|
287
320
|
this.readOnly = data.readOnly;
|
|
321
|
+
this.loa = data.loa;
|
|
322
|
+
this.transportEncoding = data.transportEncoding;
|
|
323
|
+
this.mediaChunks = data.mediaChunks;
|
|
288
324
|
if (this.confidence !== void 0) {
|
|
289
325
|
if (this.confidence < 0 || this.confidence > 1) {
|
|
290
326
|
throw new RCANMessageError(
|
|
@@ -323,6 +359,9 @@ var RCANMessage = class _RCANMessage {
|
|
|
323
359
|
if (this.presenceVerified !== void 0) obj.presenceVerified = this.presenceVerified;
|
|
324
360
|
if (this.proximityMeters !== void 0) obj.proximityMeters = this.proximityMeters;
|
|
325
361
|
if (this.readOnly !== void 0) obj.readOnly = this.readOnly;
|
|
362
|
+
if (this.loa !== void 0) obj.loa = this.loa;
|
|
363
|
+
if (this.transportEncoding !== void 0) obj.transportEncoding = this.transportEncoding;
|
|
364
|
+
if (this.mediaChunks !== void 0) obj.mediaChunks = this.mediaChunks;
|
|
326
365
|
return obj;
|
|
327
366
|
}
|
|
328
367
|
/** Serialize to JSON string */
|
|
@@ -362,7 +401,10 @@ var RCANMessage = class _RCANMessage {
|
|
|
362
401
|
qos: obj.qos,
|
|
363
402
|
presenceVerified: obj.presenceVerified,
|
|
364
403
|
proximityMeters: obj.proximityMeters,
|
|
365
|
-
readOnly: obj.readOnly
|
|
404
|
+
readOnly: obj.readOnly,
|
|
405
|
+
loa: obj.loa,
|
|
406
|
+
transportEncoding: obj.transportEncoding,
|
|
407
|
+
mediaChunks: obj.mediaChunks
|
|
366
408
|
});
|
|
367
409
|
}
|
|
368
410
|
};
|
|
@@ -2114,9 +2156,624 @@ function makeFaultReport(params) {
|
|
|
2114
2156
|
});
|
|
2115
2157
|
}
|
|
2116
2158
|
|
|
2159
|
+
// src/identity.ts
|
|
2160
|
+
var LevelOfAssurance = /* @__PURE__ */ ((LevelOfAssurance2) => {
|
|
2161
|
+
LevelOfAssurance2[LevelOfAssurance2["ANONYMOUS"] = 1] = "ANONYMOUS";
|
|
2162
|
+
LevelOfAssurance2[LevelOfAssurance2["EMAIL_VERIFIED"] = 2] = "EMAIL_VERIFIED";
|
|
2163
|
+
LevelOfAssurance2[LevelOfAssurance2["HARDWARE_TOKEN"] = 3] = "HARDWARE_TOKEN";
|
|
2164
|
+
return LevelOfAssurance2;
|
|
2165
|
+
})(LevelOfAssurance || {});
|
|
2166
|
+
var DEFAULT_LOA_POLICY = {
|
|
2167
|
+
minLoaDiscover: 1 /* ANONYMOUS */,
|
|
2168
|
+
minLoaStatus: 1 /* ANONYMOUS */,
|
|
2169
|
+
minLoaChat: 1 /* ANONYMOUS */,
|
|
2170
|
+
minLoaControl: 1 /* ANONYMOUS */,
|
|
2171
|
+
minLoaSafety: 1 /* ANONYMOUS */
|
|
2172
|
+
};
|
|
2173
|
+
var PRODUCTION_LOA_POLICY = {
|
|
2174
|
+
minLoaDiscover: 1 /* ANONYMOUS */,
|
|
2175
|
+
minLoaStatus: 1 /* ANONYMOUS */,
|
|
2176
|
+
minLoaChat: 1 /* ANONYMOUS */,
|
|
2177
|
+
minLoaControl: 2 /* EMAIL_VERIFIED */,
|
|
2178
|
+
minLoaSafety: 3 /* HARDWARE_TOKEN */
|
|
2179
|
+
};
|
|
2180
|
+
function extractLoaFromJwt(token) {
|
|
2181
|
+
try {
|
|
2182
|
+
const parts = token.split(".");
|
|
2183
|
+
if (parts.length < 2) return 1 /* ANONYMOUS */;
|
|
2184
|
+
const payloadB64 = (parts[1] ?? "").replace(/-/g, "+").replace(/_/g, "/");
|
|
2185
|
+
const padded = payloadB64 + "=".repeat((4 - payloadB64.length % 4) % 4);
|
|
2186
|
+
let json;
|
|
2187
|
+
if (typeof atob !== "undefined") {
|
|
2188
|
+
json = atob(padded);
|
|
2189
|
+
} else {
|
|
2190
|
+
json = Buffer.from(padded, "base64").toString("utf-8");
|
|
2191
|
+
}
|
|
2192
|
+
const claims = JSON.parse(json);
|
|
2193
|
+
const loa = claims["loa"];
|
|
2194
|
+
if (typeof loa === "number" && loa >= 1 && loa <= 3) {
|
|
2195
|
+
return loa;
|
|
2196
|
+
}
|
|
2197
|
+
} catch {
|
|
2198
|
+
}
|
|
2199
|
+
return 1 /* ANONYMOUS */;
|
|
2200
|
+
}
|
|
2201
|
+
function minLoaForScope(scope, policy) {
|
|
2202
|
+
const s = scope.toLowerCase();
|
|
2203
|
+
switch (s) {
|
|
2204
|
+
case "discover":
|
|
2205
|
+
return policy.minLoaDiscover;
|
|
2206
|
+
case "status":
|
|
2207
|
+
return policy.minLoaStatus;
|
|
2208
|
+
case "chat":
|
|
2209
|
+
return policy.minLoaChat;
|
|
2210
|
+
case "control":
|
|
2211
|
+
return policy.minLoaControl;
|
|
2212
|
+
case "safety":
|
|
2213
|
+
return policy.minLoaSafety;
|
|
2214
|
+
default:
|
|
2215
|
+
return null;
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
function validateLoaForScope(loa, scope, policy = DEFAULT_LOA_POLICY) {
|
|
2219
|
+
const min = minLoaForScope(scope, policy);
|
|
2220
|
+
if (min === null) {
|
|
2221
|
+
return { valid: true, reason: "unknown scope; allowed by default" };
|
|
2222
|
+
}
|
|
2223
|
+
if (loa >= min) {
|
|
2224
|
+
return { valid: true, reason: "ok" };
|
|
2225
|
+
}
|
|
2226
|
+
return {
|
|
2227
|
+
valid: false,
|
|
2228
|
+
reason: `LOA_INSUFFICIENT: scope=${scope} requires LoA>=${min}, caller has LoA=${loa}`
|
|
2229
|
+
};
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
// src/federation.ts
|
|
2233
|
+
var RegistryTier = /* @__PURE__ */ ((RegistryTier2) => {
|
|
2234
|
+
RegistryTier2["ROOT"] = "root";
|
|
2235
|
+
RegistryTier2["AUTHORITATIVE"] = "authoritative";
|
|
2236
|
+
RegistryTier2["COMMUNITY"] = "community";
|
|
2237
|
+
return RegistryTier2;
|
|
2238
|
+
})(RegistryTier || {});
|
|
2239
|
+
var FederationSyncType = /* @__PURE__ */ ((FederationSyncType2) => {
|
|
2240
|
+
FederationSyncType2["CONSENT"] = "consent";
|
|
2241
|
+
FederationSyncType2["REVOCATION"] = "revocation";
|
|
2242
|
+
FederationSyncType2["KEY"] = "key";
|
|
2243
|
+
return FederationSyncType2;
|
|
2244
|
+
})(FederationSyncType || {});
|
|
2245
|
+
var CACHE_TTL_MS2 = 24 * 60 * 60 * 1e3;
|
|
2246
|
+
var TrustAnchorCache = class {
|
|
2247
|
+
store = /* @__PURE__ */ new Map();
|
|
2248
|
+
/** Store or refresh a registry identity. */
|
|
2249
|
+
set(identity) {
|
|
2250
|
+
this.store.set(identity.registryUrl, {
|
|
2251
|
+
identity,
|
|
2252
|
+
expiresAt: Date.now() + CACHE_TTL_MS2
|
|
2253
|
+
});
|
|
2254
|
+
}
|
|
2255
|
+
/**
|
|
2256
|
+
* Look up a registry URL.
|
|
2257
|
+
* Returns undefined when absent or when the TTL has expired.
|
|
2258
|
+
*/
|
|
2259
|
+
lookup(url) {
|
|
2260
|
+
const entry = this.store.get(url);
|
|
2261
|
+
if (!entry) return void 0;
|
|
2262
|
+
if (Date.now() > entry.expiresAt) {
|
|
2263
|
+
this.store.delete(url);
|
|
2264
|
+
return void 0;
|
|
2265
|
+
}
|
|
2266
|
+
return entry.identity;
|
|
2267
|
+
}
|
|
2268
|
+
/**
|
|
2269
|
+
* Discover a registry via DNS TXT record `_rcan-registry.<domain>`.
|
|
2270
|
+
*
|
|
2271
|
+
* The TXT record is expected to contain a JSON object with the
|
|
2272
|
+
* RegistryIdentity fields. Returns the identity and caches it.
|
|
2273
|
+
*
|
|
2274
|
+
* Node.js only — returns undefined in environments without `dns.promises`.
|
|
2275
|
+
*/
|
|
2276
|
+
async discoverViaDns(domain) {
|
|
2277
|
+
const hostname = `_rcan-registry.${domain}`;
|
|
2278
|
+
let records;
|
|
2279
|
+
try {
|
|
2280
|
+
const dnsModule = require("dns");
|
|
2281
|
+
records = await dnsModule.promises.resolveTxt(hostname);
|
|
2282
|
+
} catch {
|
|
2283
|
+
return void 0;
|
|
2284
|
+
}
|
|
2285
|
+
for (const record of records) {
|
|
2286
|
+
const text = record.join("");
|
|
2287
|
+
try {
|
|
2288
|
+
const parsed = JSON.parse(text);
|
|
2289
|
+
if (parsed.registryUrl && parsed.tier && parsed.publicKeyPem && parsed.domain) {
|
|
2290
|
+
const identity = {
|
|
2291
|
+
registryUrl: parsed.registryUrl,
|
|
2292
|
+
tier: parsed.tier,
|
|
2293
|
+
publicKeyPem: parsed.publicKeyPem,
|
|
2294
|
+
domain: parsed.domain,
|
|
2295
|
+
verifiedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2296
|
+
};
|
|
2297
|
+
this.set(identity);
|
|
2298
|
+
return identity;
|
|
2299
|
+
}
|
|
2300
|
+
} catch {
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
return void 0;
|
|
2304
|
+
}
|
|
2305
|
+
/**
|
|
2306
|
+
* Verify a JWT was issued by the registry at `url`.
|
|
2307
|
+
*
|
|
2308
|
+
* Validates the `iss` claim and checks the registry is in the trust cache.
|
|
2309
|
+
* Full cryptographic signature verification requires the registry's public
|
|
2310
|
+
* key material — callers should perform additional checks using `publicKeyPem`
|
|
2311
|
+
* from the returned identity.
|
|
2312
|
+
*/
|
|
2313
|
+
async verifyRegistryJwt(token, url) {
|
|
2314
|
+
const identity = this.lookup(url);
|
|
2315
|
+
if (!identity) {
|
|
2316
|
+
throw new Error(`REGISTRY_UNKNOWN: ${url} is not in the trust cache`);
|
|
2317
|
+
}
|
|
2318
|
+
let iss;
|
|
2319
|
+
try {
|
|
2320
|
+
const parts = token.split(".");
|
|
2321
|
+
const payloadB64 = (parts[1] ?? "").replace(/-/g, "+").replace(/_/g, "/");
|
|
2322
|
+
const padded = payloadB64 + "=".repeat((4 - payloadB64.length % 4) % 4);
|
|
2323
|
+
let json;
|
|
2324
|
+
if (typeof atob !== "undefined") {
|
|
2325
|
+
json = atob(padded);
|
|
2326
|
+
} else {
|
|
2327
|
+
json = Buffer.from(padded, "base64").toString("utf-8");
|
|
2328
|
+
}
|
|
2329
|
+
const claims = JSON.parse(json);
|
|
2330
|
+
iss = typeof claims["iss"] === "string" ? claims["iss"] : void 0;
|
|
2331
|
+
} catch {
|
|
2332
|
+
throw new Error("REGISTRY_JWT_MALFORMED: cannot decode token payload");
|
|
2333
|
+
}
|
|
2334
|
+
if (iss !== url) {
|
|
2335
|
+
throw new Error(
|
|
2336
|
+
`REGISTRY_JWT_ISS_MISMATCH: expected iss=${url}, got iss=${iss ?? "(none)"}`
|
|
2337
|
+
);
|
|
2338
|
+
}
|
|
2339
|
+
return identity;
|
|
2340
|
+
}
|
|
2341
|
+
};
|
|
2342
|
+
function generateId5() {
|
|
2343
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
2344
|
+
return crypto.randomUUID();
|
|
2345
|
+
}
|
|
2346
|
+
const bytes = Array.from({ length: 16 }, () => Math.floor(Math.random() * 256));
|
|
2347
|
+
bytes[6] = (bytes[6] ?? 0) & 15 | 64;
|
|
2348
|
+
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
2349
|
+
const hex = bytes.map((b) => b.toString(16).padStart(2, "0"));
|
|
2350
|
+
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("")}`;
|
|
2351
|
+
}
|
|
2352
|
+
function makeFederationSync(source, target, syncType, payload) {
|
|
2353
|
+
return new RCANMessage({
|
|
2354
|
+
rcan: "1.6",
|
|
2355
|
+
rcanVersion: "1.6",
|
|
2356
|
+
cmd: "federation_sync",
|
|
2357
|
+
target,
|
|
2358
|
+
params: {
|
|
2359
|
+
msg_type: 12 /* FEDERATION_SYNC */,
|
|
2360
|
+
msg_id: generateId5(),
|
|
2361
|
+
source_registry: source,
|
|
2362
|
+
target_registry: target,
|
|
2363
|
+
sync_type: syncType,
|
|
2364
|
+
payload
|
|
2365
|
+
},
|
|
2366
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2367
|
+
});
|
|
2368
|
+
}
|
|
2369
|
+
async function validateCrossRegistryCommand(msg, localRegistry, trustCache) {
|
|
2370
|
+
const msgType = msg.params?.["msg_type"];
|
|
2371
|
+
const isEstop = msgType === 6 /* SAFETY */ || msgType === 6 || msg.cmd === "estop" || msg.cmd === "ESTOP";
|
|
2372
|
+
if (isEstop) {
|
|
2373
|
+
return { valid: true, reason: "ESTOP always permitted (P66 invariant)" };
|
|
2374
|
+
}
|
|
2375
|
+
const sourceRegistry = msg.params?.["source_registry"] ?? msg.params?.["from_registry"];
|
|
2376
|
+
if (!sourceRegistry || sourceRegistry === localRegistry) {
|
|
2377
|
+
return { valid: true, reason: "local registry; no federation check needed" };
|
|
2378
|
+
}
|
|
2379
|
+
const identity = trustCache.lookup(sourceRegistry);
|
|
2380
|
+
if (!identity) {
|
|
2381
|
+
return {
|
|
2382
|
+
valid: false,
|
|
2383
|
+
reason: `REGISTRY_UNKNOWN: ${sourceRegistry} is not in the local trust cache`
|
|
2384
|
+
};
|
|
2385
|
+
}
|
|
2386
|
+
let loa = 1 /* ANONYMOUS */;
|
|
2387
|
+
const registryJwt = msg.params?.["registry_jwt"];
|
|
2388
|
+
if (registryJwt) {
|
|
2389
|
+
loa = extractLoaFromJwt(registryJwt);
|
|
2390
|
+
} else if (typeof msg.loa === "number") {
|
|
2391
|
+
loa = msg.loa;
|
|
2392
|
+
}
|
|
2393
|
+
if (loa < 2 /* EMAIL_VERIFIED */) {
|
|
2394
|
+
return {
|
|
2395
|
+
valid: false,
|
|
2396
|
+
reason: `LOA_INSUFFICIENT: cross-registry commands require LoA>=2 (EMAIL_VERIFIED), got LoA=${loa}`
|
|
2397
|
+
};
|
|
2398
|
+
}
|
|
2399
|
+
return { valid: true, reason: "cross-registry command accepted" };
|
|
2400
|
+
}
|
|
2401
|
+
|
|
2402
|
+
// src/transport.ts
|
|
2403
|
+
var TransportError = class _TransportError extends Error {
|
|
2404
|
+
constructor(message) {
|
|
2405
|
+
super(message);
|
|
2406
|
+
this.name = "TransportError";
|
|
2407
|
+
Object.setPrototypeOf(this, _TransportError.prototype);
|
|
2408
|
+
}
|
|
2409
|
+
};
|
|
2410
|
+
var TransportEncoding = /* @__PURE__ */ ((TransportEncoding2) => {
|
|
2411
|
+
TransportEncoding2["HTTP"] = "http";
|
|
2412
|
+
TransportEncoding2["COMPACT"] = "compact";
|
|
2413
|
+
TransportEncoding2["MINIMAL"] = "minimal";
|
|
2414
|
+
TransportEncoding2["BLE"] = "ble";
|
|
2415
|
+
return TransportEncoding2;
|
|
2416
|
+
})(TransportEncoding || {});
|
|
2417
|
+
var COMPACT_ENCODE = {
|
|
2418
|
+
msg_type: "t",
|
|
2419
|
+
msg_id: "i",
|
|
2420
|
+
timestamp: "ts",
|
|
2421
|
+
from_rrn: "f",
|
|
2422
|
+
to_rrn: "to",
|
|
2423
|
+
scope: "s",
|
|
2424
|
+
payload: "p",
|
|
2425
|
+
signature: "sig"
|
|
2426
|
+
};
|
|
2427
|
+
var COMPACT_DECODE = Object.fromEntries(
|
|
2428
|
+
Object.entries(COMPACT_ENCODE).map(([k, v]) => [v, k])
|
|
2429
|
+
);
|
|
2430
|
+
function encodeCompact(message) {
|
|
2431
|
+
const full = message.toJSON();
|
|
2432
|
+
const compact = {};
|
|
2433
|
+
for (const [key, value] of Object.entries(full)) {
|
|
2434
|
+
const short = COMPACT_ENCODE[key];
|
|
2435
|
+
compact[short ?? key] = value;
|
|
2436
|
+
}
|
|
2437
|
+
if (compact["p"] && typeof compact["p"] === "object") {
|
|
2438
|
+
const params = compact["p"];
|
|
2439
|
+
const compactParams = {};
|
|
2440
|
+
for (const [k, v] of Object.entries(params)) {
|
|
2441
|
+
const short = COMPACT_ENCODE[k];
|
|
2442
|
+
compactParams[short ?? k] = v;
|
|
2443
|
+
}
|
|
2444
|
+
compact["p"] = compactParams;
|
|
2445
|
+
}
|
|
2446
|
+
const json = JSON.stringify(compact);
|
|
2447
|
+
const encoder = new TextEncoder();
|
|
2448
|
+
return encoder.encode(json);
|
|
2449
|
+
}
|
|
2450
|
+
function decodeCompact(data) {
|
|
2451
|
+
const decoder = new TextDecoder();
|
|
2452
|
+
const json = decoder.decode(data);
|
|
2453
|
+
const compact = JSON.parse(json);
|
|
2454
|
+
const full = {};
|
|
2455
|
+
for (const [key, value] of Object.entries(compact)) {
|
|
2456
|
+
const long = COMPACT_DECODE[key];
|
|
2457
|
+
full[long ?? key] = value;
|
|
2458
|
+
}
|
|
2459
|
+
if (full["payload"] && typeof full["payload"] === "object") {
|
|
2460
|
+
const params = full["payload"];
|
|
2461
|
+
const expandedParams = {};
|
|
2462
|
+
for (const [k, v] of Object.entries(params)) {
|
|
2463
|
+
const long = COMPACT_DECODE[k];
|
|
2464
|
+
expandedParams[long ?? k] = v;
|
|
2465
|
+
}
|
|
2466
|
+
full["payload"] = expandedParams;
|
|
2467
|
+
}
|
|
2468
|
+
return new RCANMessage({
|
|
2469
|
+
rcan: full["rcan"] ?? "1.6",
|
|
2470
|
+
rcanVersion: full["rcanVersion"],
|
|
2471
|
+
cmd: full["cmd"],
|
|
2472
|
+
target: full["target"],
|
|
2473
|
+
params: full["params"] ?? full["payload"] ?? {},
|
|
2474
|
+
timestamp: full["timestamp"],
|
|
2475
|
+
confidence: full["confidence"],
|
|
2476
|
+
signature: full["signature"]
|
|
2477
|
+
});
|
|
2478
|
+
}
|
|
2479
|
+
var MINIMAL_SIZE = 32;
|
|
2480
|
+
var SAFETY_TYPE = 6;
|
|
2481
|
+
async function sha256Bytes(input) {
|
|
2482
|
+
const encoded = new TextEncoder().encode(input);
|
|
2483
|
+
const ab = new ArrayBuffer(encoded.byteLength);
|
|
2484
|
+
new Uint8Array(ab).set(encoded);
|
|
2485
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", ab);
|
|
2486
|
+
return new Uint8Array(hashBuffer);
|
|
2487
|
+
}
|
|
2488
|
+
async function encodeMinimal(message) {
|
|
2489
|
+
const msgType = message.params?.["msg_type"] ?? 0;
|
|
2490
|
+
if (msgType !== SAFETY_TYPE) {
|
|
2491
|
+
throw new TransportError(
|
|
2492
|
+
`encodeMinimal only supports SAFETY (type 6) messages; got type=${msgType}`
|
|
2493
|
+
);
|
|
2494
|
+
}
|
|
2495
|
+
const fromRrn = message.params?.["from_rrn"] ?? message.target ?? "";
|
|
2496
|
+
const toRrn = message.params?.["to_rrn"] ?? message.target ?? "";
|
|
2497
|
+
const fromHash = await sha256Bytes(fromRrn);
|
|
2498
|
+
const toHash = await sha256Bytes(toRrn);
|
|
2499
|
+
const sig = (message.signature?.sig ?? "").replace(/[^A-Za-z0-9+/=]/g, "");
|
|
2500
|
+
let sigBytes;
|
|
2501
|
+
try {
|
|
2502
|
+
if (typeof atob !== "undefined") {
|
|
2503
|
+
const raw = atob(sig.slice(0, 16));
|
|
2504
|
+
sigBytes = new Uint8Array(raw.length);
|
|
2505
|
+
for (let i = 0; i < raw.length; i++) sigBytes[i] = raw.charCodeAt(i);
|
|
2506
|
+
} else {
|
|
2507
|
+
sigBytes = Buffer.from(sig.slice(0, 16), "base64");
|
|
2508
|
+
}
|
|
2509
|
+
} catch {
|
|
2510
|
+
sigBytes = new Uint8Array(8);
|
|
2511
|
+
}
|
|
2512
|
+
const ts = message.timestamp ? Math.floor(new Date(message.timestamp).getTime() / 1e3) : Math.floor(Date.now() / 1e3);
|
|
2513
|
+
const unix32 = ts >>> 0;
|
|
2514
|
+
const out = new Uint8Array(MINIMAL_SIZE);
|
|
2515
|
+
const view = new DataView(out.buffer);
|
|
2516
|
+
view.setUint16(0, SAFETY_TYPE, false);
|
|
2517
|
+
out.set(fromHash.subarray(0, 8), 2);
|
|
2518
|
+
out.set(toHash.subarray(0, 8), 10);
|
|
2519
|
+
view.setUint32(18, unix32, false);
|
|
2520
|
+
const sigSlice = new Uint8Array(8);
|
|
2521
|
+
sigSlice.set(sigBytes.subarray(0, Math.min(8, sigBytes.length)));
|
|
2522
|
+
out.set(sigSlice, 22);
|
|
2523
|
+
let checksum = 0;
|
|
2524
|
+
for (let i = 0; i < 30; i++) checksum ^= out[i] ?? 0;
|
|
2525
|
+
view.setUint16(30, checksum & 65535, false);
|
|
2526
|
+
if (out.length !== MINIMAL_SIZE) {
|
|
2527
|
+
throw new TransportError(
|
|
2528
|
+
`encodeMinimal assertion failed: expected ${MINIMAL_SIZE} bytes, got ${out.length}`
|
|
2529
|
+
);
|
|
2530
|
+
}
|
|
2531
|
+
return out;
|
|
2532
|
+
}
|
|
2533
|
+
function decodeMinimal(data) {
|
|
2534
|
+
if (data.length !== MINIMAL_SIZE) {
|
|
2535
|
+
throw new TransportError(
|
|
2536
|
+
`decodeMinimal: expected ${MINIMAL_SIZE} bytes, got ${data.length}`
|
|
2537
|
+
);
|
|
2538
|
+
}
|
|
2539
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
2540
|
+
const msgType = view.getUint16(0, false);
|
|
2541
|
+
const fromHash = data.subarray(2, 10);
|
|
2542
|
+
const toHash = data.subarray(10, 18);
|
|
2543
|
+
const unix32 = view.getUint32(18, false);
|
|
2544
|
+
const sigTrunc = data.subarray(22, 30);
|
|
2545
|
+
const timestamp = new Date(unix32 * 1e3).toISOString();
|
|
2546
|
+
const toHex2 = (b) => Array.from(b).map((x) => x.toString(16).padStart(2, "0")).join("");
|
|
2547
|
+
return {
|
|
2548
|
+
params: {
|
|
2549
|
+
msg_type: msgType,
|
|
2550
|
+
from_hash: toHex2(fromHash),
|
|
2551
|
+
to_hash: toHex2(toHash),
|
|
2552
|
+
timestamp_s: unix32,
|
|
2553
|
+
sig_truncated: toHex2(sigTrunc)
|
|
2554
|
+
},
|
|
2555
|
+
timestamp
|
|
2556
|
+
};
|
|
2557
|
+
}
|
|
2558
|
+
var DEFAULT_MTU = 251;
|
|
2559
|
+
var BLE_HEADER_SIZE = 3;
|
|
2560
|
+
function encodeBleFrames(message, mtu = DEFAULT_MTU) {
|
|
2561
|
+
const payload = encodeCompact(message);
|
|
2562
|
+
const chunkSize = mtu - BLE_HEADER_SIZE;
|
|
2563
|
+
if (chunkSize <= 0) {
|
|
2564
|
+
throw new TransportError(`MTU ${mtu} is too small (need at least ${BLE_HEADER_SIZE + 1})`);
|
|
2565
|
+
}
|
|
2566
|
+
const totalChunks = Math.ceil(payload.length / chunkSize);
|
|
2567
|
+
const frames = [];
|
|
2568
|
+
for (let i = 0; i < totalChunks; i++) {
|
|
2569
|
+
const chunk = payload.subarray(i * chunkSize, (i + 1) * chunkSize);
|
|
2570
|
+
const frame = new Uint8Array(BLE_HEADER_SIZE + chunk.length);
|
|
2571
|
+
frame[0] = i;
|
|
2572
|
+
frame[1] = totalChunks;
|
|
2573
|
+
frame[2] = i === totalChunks - 1 ? 1 : 0;
|
|
2574
|
+
frame.set(chunk, BLE_HEADER_SIZE);
|
|
2575
|
+
frames.push(frame);
|
|
2576
|
+
}
|
|
2577
|
+
return frames;
|
|
2578
|
+
}
|
|
2579
|
+
function decodeBleFrames(frames) {
|
|
2580
|
+
if (frames.length === 0) {
|
|
2581
|
+
throw new TransportError("decodeBleFrames: no frames provided");
|
|
2582
|
+
}
|
|
2583
|
+
const sorted = [...frames].sort((a, b) => (a[0] ?? 0) - (b[0] ?? 0));
|
|
2584
|
+
const expectedTotal = sorted[0]?.[1] ?? sorted.length;
|
|
2585
|
+
if (sorted.length !== expectedTotal) {
|
|
2586
|
+
throw new TransportError(
|
|
2587
|
+
`decodeBleFrames: expected ${expectedTotal} frames, got ${sorted.length}`
|
|
2588
|
+
);
|
|
2589
|
+
}
|
|
2590
|
+
const payloadChunks = sorted.map((f) => f.subarray(BLE_HEADER_SIZE));
|
|
2591
|
+
const totalLen = payloadChunks.reduce((s, c) => s + c.length, 0);
|
|
2592
|
+
const payload = new Uint8Array(totalLen);
|
|
2593
|
+
let offset = 0;
|
|
2594
|
+
for (const chunk of payloadChunks) {
|
|
2595
|
+
payload.set(chunk, offset);
|
|
2596
|
+
offset += chunk.length;
|
|
2597
|
+
}
|
|
2598
|
+
return decodeCompact(payload);
|
|
2599
|
+
}
|
|
2600
|
+
function selectTransport(available, message) {
|
|
2601
|
+
const msgType = message.params?.["msg_type"] ?? 0;
|
|
2602
|
+
const isSafety = msgType === SAFETY_TYPE;
|
|
2603
|
+
const has = (enc) => available.includes(enc);
|
|
2604
|
+
if (isSafety) {
|
|
2605
|
+
if (has("minimal" /* MINIMAL */)) return "minimal" /* MINIMAL */;
|
|
2606
|
+
if (has("ble" /* BLE */)) return "ble" /* BLE */;
|
|
2607
|
+
if (has("compact" /* COMPACT */)) return "compact" /* COMPACT */;
|
|
2608
|
+
if (has("http" /* HTTP */)) return "http" /* HTTP */;
|
|
2609
|
+
} else {
|
|
2610
|
+
if (has("http" /* HTTP */)) return "http" /* HTTP */;
|
|
2611
|
+
if (has("compact" /* COMPACT */)) return "compact" /* COMPACT */;
|
|
2612
|
+
if (has("ble" /* BLE */)) return "ble" /* BLE */;
|
|
2613
|
+
}
|
|
2614
|
+
throw new TransportError(
|
|
2615
|
+
`No suitable transport available from: [${available.join(", ")}]`
|
|
2616
|
+
);
|
|
2617
|
+
}
|
|
2618
|
+
|
|
2619
|
+
// src/multimodal.ts
|
|
2620
|
+
var MediaEncoding = /* @__PURE__ */ ((MediaEncoding2) => {
|
|
2621
|
+
MediaEncoding2["BASE64"] = "base64";
|
|
2622
|
+
MediaEncoding2["REF"] = "ref";
|
|
2623
|
+
return MediaEncoding2;
|
|
2624
|
+
})(MediaEncoding || {});
|
|
2625
|
+
function generateId6() {
|
|
2626
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
2627
|
+
return crypto.randomUUID();
|
|
2628
|
+
}
|
|
2629
|
+
const bytes = Array.from({ length: 16 }, () => Math.floor(Math.random() * 256));
|
|
2630
|
+
bytes[6] = (bytes[6] ?? 0) & 15 | 64;
|
|
2631
|
+
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
2632
|
+
const hex = bytes.map((b) => b.toString(16).padStart(2, "0"));
|
|
2633
|
+
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("")}`;
|
|
2634
|
+
}
|
|
2635
|
+
async function computeSha256Hex(data) {
|
|
2636
|
+
const ab = new ArrayBuffer(data.byteLength);
|
|
2637
|
+
new Uint8Array(ab).set(data);
|
|
2638
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", ab);
|
|
2639
|
+
const hashArray = new Uint8Array(hashBuffer);
|
|
2640
|
+
return Array.from(hashArray).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
2641
|
+
}
|
|
2642
|
+
function uint8ToBase64(data) {
|
|
2643
|
+
if (typeof Buffer !== "undefined") {
|
|
2644
|
+
return Buffer.from(data).toString("base64");
|
|
2645
|
+
}
|
|
2646
|
+
let binary = "";
|
|
2647
|
+
for (let i = 0; i < data.length; i++) binary += String.fromCharCode(data[i] ?? 0);
|
|
2648
|
+
return btoa(binary);
|
|
2649
|
+
}
|
|
2650
|
+
function rebuildMessage(base, overrides) {
|
|
2651
|
+
const data = { ...base.toJSON(), ...overrides };
|
|
2652
|
+
return RCANMessage.fromJSON(data);
|
|
2653
|
+
}
|
|
2654
|
+
async function addMediaInline(message, data, mimeType) {
|
|
2655
|
+
const hashSha256 = await computeSha256Hex(data);
|
|
2656
|
+
const dataB64 = uint8ToBase64(data);
|
|
2657
|
+
const chunk = {
|
|
2658
|
+
chunkId: generateId6(),
|
|
2659
|
+
mimeType,
|
|
2660
|
+
encoding: "base64" /* BASE64 */,
|
|
2661
|
+
hashSha256,
|
|
2662
|
+
dataB64,
|
|
2663
|
+
sizeBytes: data.length
|
|
2664
|
+
};
|
|
2665
|
+
const existing = message.mediaChunks ?? [];
|
|
2666
|
+
return rebuildMessage(message, { mediaChunks: [...existing, chunk] });
|
|
2667
|
+
}
|
|
2668
|
+
function addMediaRef(message, refUrl, mimeType, hashSha256, sizeBytes) {
|
|
2669
|
+
const chunk = {
|
|
2670
|
+
chunkId: generateId6(),
|
|
2671
|
+
mimeType,
|
|
2672
|
+
encoding: "ref" /* REF */,
|
|
2673
|
+
hashSha256,
|
|
2674
|
+
refUrl,
|
|
2675
|
+
sizeBytes
|
|
2676
|
+
};
|
|
2677
|
+
const existing = message.mediaChunks ?? [];
|
|
2678
|
+
return rebuildMessage(message, { mediaChunks: [...existing, chunk] });
|
|
2679
|
+
}
|
|
2680
|
+
async function validateMediaChunks(message) {
|
|
2681
|
+
const chunks = message.mediaChunks ?? [];
|
|
2682
|
+
if (chunks.length === 0) {
|
|
2683
|
+
return { valid: true, reason: "no media chunks" };
|
|
2684
|
+
}
|
|
2685
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
2686
|
+
const chunk = chunks[i];
|
|
2687
|
+
if (!chunk.chunkId) return { valid: false, reason: `chunk[${i}]: missing chunkId` };
|
|
2688
|
+
if (!chunk.mimeType) return { valid: false, reason: `chunk[${i}]: missing mimeType` };
|
|
2689
|
+
if (!chunk.hashSha256) return { valid: false, reason: `chunk[${i}]: missing hashSha256` };
|
|
2690
|
+
if (chunk.sizeBytes < 0) return { valid: false, reason: `chunk[${i}]: sizeBytes must be >= 0` };
|
|
2691
|
+
if (chunk.encoding === "base64" /* BASE64 */) {
|
|
2692
|
+
if (!chunk.dataB64) {
|
|
2693
|
+
return { valid: false, reason: `chunk[${i}]: BASE64 encoding requires dataB64` };
|
|
2694
|
+
}
|
|
2695
|
+
let decoded;
|
|
2696
|
+
try {
|
|
2697
|
+
if (typeof Buffer !== "undefined") {
|
|
2698
|
+
decoded = Buffer.from(chunk.dataB64, "base64");
|
|
2699
|
+
} else {
|
|
2700
|
+
const raw = atob(chunk.dataB64);
|
|
2701
|
+
decoded = new Uint8Array(raw.length);
|
|
2702
|
+
for (let j = 0; j < raw.length; j++) decoded[j] = raw.charCodeAt(j);
|
|
2703
|
+
}
|
|
2704
|
+
} catch {
|
|
2705
|
+
return { valid: false, reason: `chunk[${i}]: failed to decode base64 data` };
|
|
2706
|
+
}
|
|
2707
|
+
const actualHash = await computeSha256Hex(decoded);
|
|
2708
|
+
if (actualHash !== chunk.hashSha256) {
|
|
2709
|
+
return {
|
|
2710
|
+
valid: false,
|
|
2711
|
+
reason: `chunk[${i}]: SHA-256 mismatch (expected ${chunk.hashSha256}, got ${actualHash})`
|
|
2712
|
+
};
|
|
2713
|
+
}
|
|
2714
|
+
} else if (chunk.encoding === "ref" /* REF */) {
|
|
2715
|
+
if (!chunk.refUrl) {
|
|
2716
|
+
return { valid: false, reason: `chunk[${i}]: REF encoding requires refUrl` };
|
|
2717
|
+
}
|
|
2718
|
+
} else {
|
|
2719
|
+
return { valid: false, reason: `chunk[${i}]: unknown encoding '${chunk.encoding}'` };
|
|
2720
|
+
}
|
|
2721
|
+
}
|
|
2722
|
+
return { valid: true, reason: "ok" };
|
|
2723
|
+
}
|
|
2724
|
+
async function makeTrainingDataMessage(media) {
|
|
2725
|
+
let msg = new RCANMessage({
|
|
2726
|
+
rcan: "1.6",
|
|
2727
|
+
rcanVersion: "1.6",
|
|
2728
|
+
cmd: "training_data",
|
|
2729
|
+
target: "rcan://training/data",
|
|
2730
|
+
params: {
|
|
2731
|
+
msg_type: 10 /* TRAINING_DATA */,
|
|
2732
|
+
msg_id: generateId6()
|
|
2733
|
+
},
|
|
2734
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2735
|
+
});
|
|
2736
|
+
for (const item of media) {
|
|
2737
|
+
msg = await addMediaInline(msg, item.data, item.mimeType);
|
|
2738
|
+
}
|
|
2739
|
+
return msg;
|
|
2740
|
+
}
|
|
2741
|
+
async function makeStreamChunk(streamId, data, mimeType, chunkIndex, isFinal) {
|
|
2742
|
+
const hashSha256 = await computeSha256Hex(data);
|
|
2743
|
+
const dataB64 = uint8ToBase64(data);
|
|
2744
|
+
const chunk = {
|
|
2745
|
+
chunkId: generateId6(),
|
|
2746
|
+
mimeType,
|
|
2747
|
+
encoding: "base64" /* BASE64 */,
|
|
2748
|
+
hashSha256,
|
|
2749
|
+
dataB64,
|
|
2750
|
+
sizeBytes: data.length
|
|
2751
|
+
};
|
|
2752
|
+
const streamChunkMeta = {
|
|
2753
|
+
streamId,
|
|
2754
|
+
chunkIndex,
|
|
2755
|
+
isFinal,
|
|
2756
|
+
chunk
|
|
2757
|
+
};
|
|
2758
|
+
let msg = new RCANMessage({
|
|
2759
|
+
rcan: "1.6",
|
|
2760
|
+
rcanVersion: "1.6",
|
|
2761
|
+
cmd: "stream_chunk",
|
|
2762
|
+
target: "rcan://streaming/chunk",
|
|
2763
|
+
params: {
|
|
2764
|
+
msg_type: 7 /* SENSOR_DATA */,
|
|
2765
|
+
msg_id: generateId6(),
|
|
2766
|
+
stream_chunk: streamChunkMeta
|
|
2767
|
+
},
|
|
2768
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2769
|
+
});
|
|
2770
|
+
msg = rebuildMessage(msg, { mediaChunks: [chunk] });
|
|
2771
|
+
return msg;
|
|
2772
|
+
}
|
|
2773
|
+
|
|
2117
2774
|
// src/index.ts
|
|
2118
|
-
var VERSION = "0.
|
|
2119
|
-
var RCAN_VERSION = "1.
|
|
2775
|
+
var VERSION = "0.6.0";
|
|
2776
|
+
var RCAN_VERSION = "1.6";
|
|
2120
2777
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2121
2778
|
0 && (module.exports = {
|
|
2122
2779
|
AuditChain,
|
|
@@ -2124,14 +2781,19 @@ var RCAN_VERSION = "1.5";
|
|
|
2124
2781
|
ClockDriftError,
|
|
2125
2782
|
CommitmentRecord,
|
|
2126
2783
|
ConfidenceGate,
|
|
2784
|
+
DEFAULT_LOA_POLICY,
|
|
2127
2785
|
DataCategory,
|
|
2128
2786
|
FaultCode,
|
|
2787
|
+
FederationSyncType,
|
|
2129
2788
|
GateError,
|
|
2130
2789
|
HiTLGate,
|
|
2131
2790
|
KeyStore,
|
|
2791
|
+
LevelOfAssurance,
|
|
2792
|
+
MediaEncoding,
|
|
2132
2793
|
MessageType,
|
|
2133
2794
|
NodeClient,
|
|
2134
2795
|
OfflineModeManager,
|
|
2796
|
+
PRODUCTION_LOA_POLICY,
|
|
2135
2797
|
QoSAckTimeoutError,
|
|
2136
2798
|
QoSLevel,
|
|
2137
2799
|
QoSManager,
|
|
@@ -2153,17 +2815,31 @@ var RCAN_VERSION = "1.5";
|
|
|
2153
2815
|
RCANVersionIncompatibleError,
|
|
2154
2816
|
RCAN_VERSION,
|
|
2155
2817
|
RegistryClient,
|
|
2818
|
+
RegistryTier,
|
|
2156
2819
|
ReplayCache,
|
|
2157
2820
|
RevocationCache,
|
|
2158
2821
|
RobotURI,
|
|
2159
2822
|
RobotURIError,
|
|
2160
2823
|
SAFETY_MESSAGE_TYPE,
|
|
2824
|
+
SDK_VERSION,
|
|
2161
2825
|
SPEC_VERSION,
|
|
2826
|
+
TransportEncoding,
|
|
2827
|
+
TransportError,
|
|
2828
|
+
TrustAnchorCache,
|
|
2162
2829
|
VERSION,
|
|
2163
2830
|
addDelegationHop,
|
|
2831
|
+
addMediaInline,
|
|
2832
|
+
addMediaRef,
|
|
2164
2833
|
assertClockSynced,
|
|
2165
2834
|
checkClockSync,
|
|
2166
2835
|
checkRevocation,
|
|
2836
|
+
decodeBleFrames,
|
|
2837
|
+
decodeCompact,
|
|
2838
|
+
decodeMinimal,
|
|
2839
|
+
encodeBleFrames,
|
|
2840
|
+
encodeCompact,
|
|
2841
|
+
encodeMinimal,
|
|
2842
|
+
extractLoaFromJwt,
|
|
2167
2843
|
fetchCanonicalSchema,
|
|
2168
2844
|
isSafetyMessage,
|
|
2169
2845
|
makeCloudRelayMessage,
|
|
@@ -2174,19 +2850,26 @@ var RCAN_VERSION = "1.5";
|
|
|
2174
2850
|
makeEstopMessage,
|
|
2175
2851
|
makeEstopWithQoS,
|
|
2176
2852
|
makeFaultReport,
|
|
2853
|
+
makeFederationSync,
|
|
2177
2854
|
makeKeyRotationMessage,
|
|
2178
2855
|
makeResumeMessage,
|
|
2179
2856
|
makeRevocationBroadcast,
|
|
2180
2857
|
makeStopMessage,
|
|
2858
|
+
makeStreamChunk,
|
|
2181
2859
|
makeTrainingConsentDeny,
|
|
2182
2860
|
makeTrainingConsentGrant,
|
|
2183
2861
|
makeTrainingConsentRequest,
|
|
2862
|
+
makeTrainingDataMessage,
|
|
2184
2863
|
makeTransparencyMessage,
|
|
2864
|
+
selectTransport,
|
|
2185
2865
|
validateConfig,
|
|
2186
2866
|
validateConfigAgainstSchema,
|
|
2187
2867
|
validateConfigUpdate,
|
|
2188
2868
|
validateConsentMessage,
|
|
2869
|
+
validateCrossRegistryCommand,
|
|
2189
2870
|
validateDelegationChain,
|
|
2871
|
+
validateLoaForScope,
|
|
2872
|
+
validateMediaChunks,
|
|
2190
2873
|
validateMessage,
|
|
2191
2874
|
validateNodeAgainstSchema,
|
|
2192
2875
|
validateReplay,
|