@continuonai/rcan-ts 0.8.0 → 1.2.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
@@ -30,20 +30,27 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ AUTHORITY_ERROR_CODES: () => AUTHORITY_ERROR_CODES,
33
34
  AuditChain: () => AuditChain,
34
35
  AuditError: () => AuditError,
36
+ COMPETITION_SCOPE_LEVEL: () => COMPETITION_SCOPE_LEVEL,
35
37
  CONTRIBUTE_SCOPE_LEVEL: () => CONTRIBUTE_SCOPE_LEVEL,
36
38
  ClockDriftError: () => ClockDriftError,
37
39
  CommitmentRecord: () => CommitmentRecord,
38
40
  ConfidenceGate: () => ConfidenceGate,
39
41
  DEFAULT_LOA_POLICY: () => DEFAULT_LOA_POLICY,
40
42
  DataCategory: () => DataCategory,
43
+ FIRMWARE_MANIFEST_PATH: () => FIRMWARE_MANIFEST_PATH,
41
44
  FaultCode: () => FaultCode,
42
45
  FederationSyncType: () => FederationSyncType,
46
+ FirmwareIntegrityError: () => FirmwareIntegrityError,
43
47
  GateError: () => GateError,
44
48
  HiTLGate: () => HiTLGate,
45
49
  KeyStore: () => KeyStore,
46
50
  LevelOfAssurance: () => LevelOfAssurance,
51
+ M2MAuthError: () => M2MAuthError,
52
+ M2M_TRUSTED_ISSUER: () => M2M_TRUSTED_ISSUER,
53
+ MLDSAKeyPair: () => MLDSAKeyPair,
47
54
  MediaEncoding: () => MediaEncoding,
48
55
  MessageType: () => MessageType,
49
56
  NodeClient: () => NodeClient,
@@ -69,13 +76,18 @@ __export(index_exports, {
69
76
  RCANValidationError: () => RCANValidationError,
70
77
  RCANVersionIncompatibleError: () => RCANVersionIncompatibleError,
71
78
  RCAN_VERSION: () => RCAN_VERSION,
79
+ ROLE_JWT_LEVEL: () => ROLE_JWT_LEVEL,
80
+ RRF_REVOCATION_CACHE_TTL_MS: () => RRF_REVOCATION_CACHE_TTL_MS,
81
+ RRF_REVOCATION_URL: () => RRF_REVOCATION_URL,
72
82
  RegistryClient: () => RegistryClient,
73
83
  RegistryTier: () => RegistryTier,
74
84
  ReplayCache: () => ReplayCache,
75
85
  RevocationCache: () => RevocationCache,
76
86
  RobotURI: () => RobotURI,
77
87
  RobotURIError: () => RobotURIError,
88
+ Role: () => Role,
78
89
  SAFETY_MESSAGE_TYPE: () => SAFETY_MESSAGE_TYPE,
90
+ SCOPE_MIN_ROLE: () => SCOPE_MIN_ROLE,
79
91
  SDK_VERSION: () => SDK_VERSION,
80
92
  SPEC_VERSION: () => SPEC_VERSION,
81
93
  TransportEncoding: () => TransportEncoding,
@@ -85,7 +97,11 @@ __export(index_exports, {
85
97
  addDelegationHop: () => addDelegationHop,
86
98
  addMediaInline: () => addMediaInline,
87
99
  addMediaRef: () => addMediaRef,
100
+ addPQSignature: () => addPQSignature,
88
101
  assertClockSynced: () => assertClockSynced,
102
+ authorityAccessFromWire: () => authorityAccessFromWire,
103
+ authorityAccessToWire: () => authorityAccessToWire,
104
+ canonicalManifestJson: () => canonicalManifestJson,
89
105
  checkClockSync: () => checkClockSync,
90
106
  checkRevocation: () => checkRevocation,
91
107
  decodeBleFrames: () => decodeBleFrames,
@@ -94,11 +110,18 @@ __export(index_exports, {
94
110
  encodeBleFrames: () => encodeBleFrames,
95
111
  encodeCompact: () => encodeCompact,
96
112
  encodeMinimal: () => encodeMinimal,
113
+ extractIdentityFromJwt: () => extractIdentityFromJwt,
97
114
  extractLoaFromJwt: () => extractLoaFromJwt,
115
+ extractRoleFromJwt: () => extractRoleFromJwt,
98
116
  fetchCanonicalSchema: () => fetchCanonicalSchema,
117
+ fetchRRFRevocations: () => fetchRRFRevocations,
118
+ isAuthorityRequestValid: () => isAuthorityRequestValid,
119
+ isM2mTrustedRevoked: () => isM2mTrustedRevoked,
99
120
  isPreemptedBy: () => isPreemptedBy,
100
121
  isSafetyMessage: () => isSafetyMessage,
101
122
  makeCloudRelayMessage: () => makeCloudRelayMessage,
123
+ makeCompetitionEnter: () => makeCompetitionEnter,
124
+ makeCompetitionScore: () => makeCompetitionScore,
102
125
  makeConfigUpdate: () => makeConfigUpdate,
103
126
  makeConsentDeny: () => makeConsentDeny,
104
127
  makeConsentGrant: () => makeConsentGrant,
@@ -111,8 +134,10 @@ __export(index_exports, {
111
134
  makeFaultReport: () => makeFaultReport,
112
135
  makeFederationSync: () => makeFederationSync,
113
136
  makeKeyRotationMessage: () => makeKeyRotationMessage,
137
+ makePersonalResearchResult: () => makePersonalResearchResult,
114
138
  makeResumeMessage: () => makeResumeMessage,
115
139
  makeRevocationBroadcast: () => makeRevocationBroadcast,
140
+ makeSeasonStanding: () => makeSeasonStanding,
116
141
  makeStopMessage: () => makeStopMessage,
117
142
  makeStreamChunk: () => makeStreamChunk,
118
143
  makeTrainingConsentDeny: () => makeTrainingConsentDeny,
@@ -120,7 +145,14 @@ __export(index_exports, {
120
145
  makeTrainingConsentRequest: () => makeTrainingConsentRequest,
121
146
  makeTrainingDataMessage: () => makeTrainingDataMessage,
122
147
  makeTransparencyMessage: () => makeTransparencyMessage,
148
+ manifestFromWire: () => manifestFromWire,
149
+ manifestToWire: () => manifestToWire,
150
+ parseM2mPeerToken: () => parseM2mPeerToken,
151
+ parseM2mTrustedToken: () => parseM2mTrustedToken,
152
+ roleFromJwtLevel: () => roleFromJwtLevel,
123
153
  selectTransport: () => selectTransport,
154
+ validateAuthorityAccess: () => validateAuthorityAccess,
155
+ validateCompetitionScope: () => validateCompetitionScope,
124
156
  validateConfig: () => validateConfig,
125
157
  validateConfigAgainstSchema: () => validateConfigAgainstSchema,
126
158
  validateConfigUpdate: () => validateConfigUpdate,
@@ -129,14 +161,19 @@ __export(index_exports, {
129
161
  validateCrossRegistryCommand: () => validateCrossRegistryCommand,
130
162
  validateDelegationChain: () => validateDelegationChain,
131
163
  validateLoaForScope: () => validateLoaForScope,
164
+ validateManifest: () => validateManifest,
132
165
  validateMediaChunks: () => validateMediaChunks,
133
166
  validateMessage: () => validateMessage,
134
167
  validateNodeAgainstSchema: () => validateNodeAgainstSchema,
135
168
  validateReplay: () => validateReplay,
169
+ validateRoleForScope: () => validateRoleForScope,
136
170
  validateSafetyMessage: () => validateSafetyMessage,
137
171
  validateTrainingDataMessage: () => validateTrainingDataMessage,
138
172
  validateURI: () => validateURI,
139
- validateVersionCompat: () => validateVersionCompat
173
+ validateVersionCompat: () => validateVersionCompat,
174
+ verifyM2mTrustedToken: () => verifyM2mTrustedToken,
175
+ verifyM2mTrustedTokenClaims: () => verifyM2mTrustedTokenClaims,
176
+ verifyPQSignature: () => verifyPQSignature
140
177
  });
141
178
  module.exports = __toCommonJS(index_exports);
142
179
 
@@ -231,8 +268,8 @@ var RobotURI = class _RobotURI {
231
268
  };
232
269
 
233
270
  // src/version.ts
234
- var SPEC_VERSION = "1.9.0";
235
- var SDK_VERSION = "0.8.0";
271
+ var SPEC_VERSION = "2.2.0";
272
+ var SDK_VERSION = "1.2.0";
236
273
  function validateVersionCompat(incomingVersion, localVersion = SPEC_VERSION) {
237
274
  const parseParts = (v) => {
238
275
  const parts = v.split(".");
@@ -283,9 +320,14 @@ var MessageType = /* @__PURE__ */ ((MessageType2) => {
283
320
  MessageType2[MessageType2["CONTRIBUTE_RESULT"] = 34] = "CONTRIBUTE_RESULT";
284
321
  MessageType2[MessageType2["CONTRIBUTE_CANCEL"] = 35] = "CONTRIBUTE_CANCEL";
285
322
  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";
323
+ MessageType2[MessageType2["COMPETITION_ENTER"] = 37] = "COMPETITION_ENTER";
324
+ MessageType2[MessageType2["COMPETITION_SCORE"] = 38] = "COMPETITION_SCORE";
325
+ MessageType2[MessageType2["SEASON_STANDING"] = 39] = "SEASON_STANDING";
326
+ MessageType2[MessageType2["PERSONAL_RESEARCH_RESULT"] = 40] = "PERSONAL_RESEARCH_RESULT";
327
+ MessageType2[MessageType2["AUTHORITY_ACCESS"] = 41] = "AUTHORITY_ACCESS";
328
+ MessageType2[MessageType2["AUTHORITY_RESPONSE"] = 42] = "AUTHORITY_RESPONSE";
329
+ MessageType2[MessageType2["FIRMWARE_ATTESTATION"] = 43] = "FIRMWARE_ATTESTATION";
330
+ MessageType2[MessageType2["SBOM_UPDATE"] = 44] = "SBOM_UPDATE";
289
331
  return MessageType2;
290
332
  })(MessageType || {});
291
333
  var RCANMessageError = class extends Error {
@@ -321,6 +363,12 @@ var RCANMessage = class _RCANMessage {
321
363
  transportEncoding;
322
364
  /** v1.6: GAP-18 multi-modal media chunks */
323
365
  mediaChunks;
366
+ /** v2.1: SHA-256 of sender's firmware manifest */
367
+ firmwareHash;
368
+ /** v2.1: URI to sender's SBOM attestation endpoint */
369
+ attestationRef;
370
+ /** v2.2: ML-DSA-65 post-quantum signature (field 16, FIPS 204). Hybrid alongside Ed25519. */
371
+ pqSig;
324
372
  constructor(data) {
325
373
  if (!data.cmd || data.cmd.trim() === "") {
326
374
  throw new RCANMessageError("'cmd' is required");
@@ -349,6 +397,14 @@ var RCANMessage = class _RCANMessage {
349
397
  this.loa = data.loa;
350
398
  this.transportEncoding = data.transportEncoding;
351
399
  this.mediaChunks = data.mediaChunks;
400
+ this.firmwareHash = data.firmwareHash;
401
+ this.attestationRef = data.attestationRef;
402
+ this.pqSig = data.pqSig;
403
+ if (this.signature !== void 0 && this.signature["sig"] === "pending") {
404
+ throw new RCANMessageError(
405
+ "signature.sig:'pending' is not valid in RCAN v2.1. Sign the message before sending."
406
+ );
407
+ }
352
408
  if (this.confidence !== void 0) {
353
409
  if (this.confidence < 0 || this.confidence > 1) {
354
410
  throw new RCANMessageError(
@@ -390,6 +446,9 @@ var RCANMessage = class _RCANMessage {
390
446
  if (this.loa !== void 0) obj.loa = this.loa;
391
447
  if (this.transportEncoding !== void 0) obj.transportEncoding = this.transportEncoding;
392
448
  if (this.mediaChunks !== void 0) obj.mediaChunks = this.mediaChunks;
449
+ if (this.firmwareHash !== void 0) obj.firmwareHash = this.firmwareHash;
450
+ if (this.attestationRef !== void 0) obj.attestationRef = this.attestationRef;
451
+ if (this.pqSig !== void 0) obj.pqSig = this.pqSig;
393
452
  return obj;
394
453
  }
395
454
  /** Serialize to JSON string */
@@ -432,7 +491,10 @@ var RCANMessage = class _RCANMessage {
432
491
  readOnly: obj.readOnly,
433
492
  loa: obj.loa,
434
493
  transportEncoding: obj.transportEncoding,
435
- mediaChunks: obj.mediaChunks
494
+ mediaChunks: obj.mediaChunks,
495
+ firmwareHash: obj.firmwareHash,
496
+ attestationRef: obj.attestationRef,
497
+ pqSig: obj.pqSig
436
498
  });
437
499
  }
438
500
  };
@@ -2186,80 +2248,133 @@ function makeFaultReport(params) {
2186
2248
  }
2187
2249
 
2188
2250
  // 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 || {});
2251
+ var Role = /* @__PURE__ */ ((Role2) => {
2252
+ Role2[Role2["GUEST"] = 1] = "GUEST";
2253
+ Role2[Role2["OPERATOR"] = 2] = "OPERATOR";
2254
+ Role2[Role2["CONTRIBUTOR"] = 3] = "CONTRIBUTOR";
2255
+ Role2[Role2["ADMIN"] = 4] = "ADMIN";
2256
+ Role2[Role2["M2M_PEER"] = 5] = "M2M_PEER";
2257
+ Role2[Role2["CREATOR"] = 6] = "CREATOR";
2258
+ Role2[Role2["M2M_TRUSTED"] = 7] = "M2M_TRUSTED";
2259
+ return Role2;
2260
+ })(Role || {});
2261
+ var LevelOfAssurance = Role;
2262
+ var ROLE_JWT_LEVEL = {
2263
+ [1 /* GUEST */]: 1,
2264
+ [2 /* OPERATOR */]: 2,
2265
+ [3 /* CONTRIBUTOR */]: 2.5,
2266
+ [4 /* ADMIN */]: 3,
2267
+ [5 /* M2M_PEER */]: 4,
2268
+ [6 /* CREATOR */]: 5,
2269
+ [7 /* M2M_TRUSTED */]: 6
2270
+ };
2271
+ var JWT_LEVEL_TO_ROLE = new Map(
2272
+ Object.entries(ROLE_JWT_LEVEL).map(
2273
+ ([role, level]) => [level, Number(role)]
2274
+ )
2275
+ );
2276
+ function roleFromJwtLevel(level) {
2277
+ return JWT_LEVEL_TO_ROLE.get(level);
2278
+ }
2279
+ var SCOPE_MIN_ROLE = {
2280
+ "status": 1 /* GUEST */,
2281
+ "discover": 1 /* GUEST */,
2282
+ "chat": 1 /* GUEST */,
2283
+ "observer": 1 /* GUEST */,
2284
+ "contribute": 3 /* CONTRIBUTOR */,
2285
+ "control": 2 /* OPERATOR */,
2286
+ "teleop": 2 /* OPERATOR */,
2287
+ "training": 4 /* ADMIN */,
2288
+ "training_data": 4 /* ADMIN */,
2289
+ "config": 4 /* ADMIN */,
2290
+ "authority": 4 /* ADMIN */,
2291
+ "admin": 6 /* CREATOR */,
2292
+ "safety": 6 /* CREATOR */,
2293
+ "estop": 6 /* CREATOR */,
2294
+ "fleet.trusted": 7 /* M2M_TRUSTED */
2295
+ };
2195
2296
  var DEFAULT_LOA_POLICY = {
2196
- minLoaDiscover: 1 /* ANONYMOUS */,
2197
- minLoaStatus: 1 /* ANONYMOUS */,
2198
- minLoaChat: 1 /* ANONYMOUS */,
2199
- minLoaControl: 1 /* ANONYMOUS */,
2200
- minLoaSafety: 1 /* ANONYMOUS */
2297
+ minRoleForDiscover: 1 /* GUEST */,
2298
+ minRoleForStatus: 1 /* GUEST */,
2299
+ minRoleForChat: 1 /* GUEST */,
2300
+ minRoleForControl: 1 /* GUEST */,
2301
+ minRoleForSafety: 1 /* GUEST */
2201
2302
  };
2202
2303
  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 */
2304
+ minRoleForDiscover: 1 /* GUEST */,
2305
+ minRoleForStatus: 1 /* GUEST */,
2306
+ minRoleForChat: 1 /* GUEST */,
2307
+ minRoleForControl: 2 /* OPERATOR */,
2308
+ minRoleForSafety: 6 /* CREATOR */
2208
2309
  };
2209
- function extractLoaFromJwt(token) {
2310
+ function decodeJwtPayload(token) {
2210
2311
  try {
2211
2312
  const parts = token.split(".");
2212
- if (parts.length < 2) return 1 /* ANONYMOUS */;
2313
+ if (parts.length < 2) return null;
2213
2314
  const payloadB64 = (parts[1] ?? "").replace(/-/g, "+").replace(/_/g, "/");
2214
2315
  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
- }
2316
+ return JSON.parse(atob(padded));
2226
2317
  } catch {
2318
+ return null;
2227
2319
  }
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" };
2320
+ }
2321
+ function extractRoleFromJwt(token) {
2322
+ const payload = decodeJwtPayload(token);
2323
+ if (!payload) return 1 /* GUEST */;
2324
+ const rcanRole = payload["rcan_role"];
2325
+ if (rcanRole !== void 0 && rcanRole !== null) {
2326
+ const role = roleFromJwtLevel(Number(rcanRole));
2327
+ if (role !== void 0) return role;
2257
2328
  }
2329
+ const loa = payload["loa"];
2330
+ if (loa !== void 0 && loa !== null) {
2331
+ const role = roleFromJwtLevel(Number(loa));
2332
+ if (role !== void 0) return role;
2333
+ }
2334
+ return 1 /* GUEST */;
2335
+ }
2336
+ function extractLoaFromJwt(token) {
2337
+ return extractRoleFromJwt(token);
2338
+ }
2339
+ function extractIdentityFromJwt(token) {
2340
+ const payload = decodeJwtPayload(token);
2341
+ if (!payload) {
2342
+ return { sub: "", role: 1 /* GUEST */, jwtLevel: 1, scopes: [] };
2343
+ }
2344
+ const rcanRole = payload["rcan_role"];
2345
+ const loa = payload["loa"];
2346
+ const rawLevel = rcanRole !== void 0 ? Number(rcanRole) : loa !== void 0 ? Number(loa) : 1;
2347
+ const role = roleFromJwtLevel(rawLevel) ?? 1 /* GUEST */;
2348
+ const scopes = Array.isArray(payload["rcan_scopes"]) ? payload["rcan_scopes"] : Array.isArray(payload["scopes"]) ? payload["scopes"] : [];
2258
2349
  return {
2259
- valid: false,
2260
- reason: `LOA_INSUFFICIENT: scope=${scope} requires LoA>=${min}, caller has LoA=${loa}`
2350
+ sub: String(payload["sub"] ?? ""),
2351
+ role,
2352
+ jwtLevel: ROLE_JWT_LEVEL[role],
2353
+ registryUrl: payload["registry_url"],
2354
+ scopes,
2355
+ verifiedAt: payload["verified_at"],
2356
+ peerRrn: payload["peer_rrn"],
2357
+ fleetRrns: Array.isArray(payload["fleet_rrns"]) ? payload["fleet_rrns"] : void 0
2261
2358
  };
2262
2359
  }
2360
+ function validateRoleForScope(role, scope) {
2361
+ const required = SCOPE_MIN_ROLE[scope.toLowerCase()];
2362
+ if (required === void 0) {
2363
+ if (role >= 2 /* OPERATOR */) return { ok: true, reason: "" };
2364
+ return {
2365
+ ok: false,
2366
+ reason: `Unknown scope '${scope}': applying OPERATOR minimum. Caller has ${Role[role]}.`
2367
+ };
2368
+ }
2369
+ if (role >= required) return { ok: true, reason: "" };
2370
+ return {
2371
+ ok: false,
2372
+ reason: `Scope '${scope}' requires ${Role[required]} (JWT level ${ROLE_JWT_LEVEL[required]}), but caller has ${Role[role]} (JWT level ${ROLE_JWT_LEVEL[role]})`
2373
+ };
2374
+ }
2375
+ function validateLoaForScope(role, scope) {
2376
+ return validateRoleForScope(role, scope);
2377
+ }
2263
2378
 
2264
2379
  // src/federation.ts
2265
2380
  var RegistryTier = /* @__PURE__ */ ((RegistryTier2) => {
@@ -2383,12 +2498,12 @@ function generateId5() {
2383
2498
  }
2384
2499
  function makeFederationSync(source, target, syncType, payload) {
2385
2500
  return new RCANMessage({
2386
- rcan: "1.6",
2387
- rcanVersion: "1.6",
2501
+ rcan: "2.1.0",
2502
+ rcanVersion: "2.1.0",
2388
2503
  cmd: "federation_sync",
2389
2504
  target,
2390
2505
  params: {
2391
- msg_type: 23 /* FEDERATION_SYNC */,
2506
+ msg_type: 23 /* FLEET_COMMAND */,
2392
2507
  msg_id: generateId5(),
2393
2508
  source_registry: source,
2394
2509
  target_registry: target,
@@ -2415,17 +2530,17 @@ async function validateCrossRegistryCommand(msg, localRegistry, trustCache) {
2415
2530
  reason: `REGISTRY_UNKNOWN: ${sourceRegistry} is not in the local trust cache`
2416
2531
  };
2417
2532
  }
2418
- let loa = 1 /* ANONYMOUS */;
2533
+ let loa = 1 /* GUEST */;
2419
2534
  const registryJwt = msg.params?.["registry_jwt"];
2420
2535
  if (registryJwt) {
2421
2536
  loa = extractLoaFromJwt(registryJwt);
2422
2537
  } else if (typeof msg.loa === "number") {
2423
2538
  loa = msg.loa;
2424
2539
  }
2425
- if (loa < 2 /* EMAIL_VERIFIED */) {
2540
+ if (loa < 2 /* OPERATOR */) {
2426
2541
  return {
2427
2542
  valid: false,
2428
- reason: `LOA_INSUFFICIENT: cross-registry commands require LoA>=2 (EMAIL_VERIFIED), got LoA=${loa}`
2543
+ reason: `LOA_INSUFFICIENT: cross-registry commands require LoA>=2 (OPERATOR), got role=${loa}`
2429
2544
  };
2430
2545
  }
2431
2546
  return { valid: true, reason: "cross-registry command accepted" };
@@ -2864,25 +2979,471 @@ function isPreemptedBy(scopeLevel) {
2864
2979
  return scopeLevel >= 3;
2865
2980
  }
2866
2981
 
2982
+ // src/competition.ts
2983
+ var COMPETITION_SCOPE_LEVEL = 2;
2984
+ var _idCounter2 = 0;
2985
+ function _generateRunId() {
2986
+ return `run-${Date.now()}-${++_idCounter2}`;
2987
+ }
2988
+ function makeCompetitionEnter(params = {}) {
2989
+ return {
2990
+ type: 37 /* COMPETITION_ENTER */,
2991
+ competition_id: params.competition_id ?? "",
2992
+ competition_format: params.competition_format ?? "sprint",
2993
+ hardware_tier: params.hardware_tier ?? "",
2994
+ model_id: params.model_id ?? "",
2995
+ robot_rrn: params.robot_rrn ?? "",
2996
+ entered_at: params.entered_at ?? Date.now() / 1e3
2997
+ };
2998
+ }
2999
+ function makeCompetitionScore(params = {}) {
3000
+ const score = params.score ?? 0;
3001
+ if (score < 0 || score > 1) {
3002
+ throw new Error(`score must be in [0.0, 1.0], got ${score}`);
3003
+ }
3004
+ return {
3005
+ type: 38 /* COMPETITION_SCORE */,
3006
+ competition_id: params.competition_id ?? "",
3007
+ candidate_id: params.candidate_id ?? "",
3008
+ score,
3009
+ hardware_tier: params.hardware_tier ?? "",
3010
+ verified: params.verified ?? false,
3011
+ submitted_at: params.submitted_at ?? Date.now() / 1e3
3012
+ };
3013
+ }
3014
+ function makeSeasonStanding(params = {}) {
3015
+ return {
3016
+ type: 39 /* SEASON_STANDING */,
3017
+ season_id: params.season_id ?? "",
3018
+ class_id: params.class_id ?? "",
3019
+ standings: params.standings ?? [],
3020
+ days_remaining: params.days_remaining ?? 0,
3021
+ broadcast_at: params.broadcast_at ?? Date.now() / 1e3
3022
+ };
3023
+ }
3024
+ function makePersonalResearchResult(params = {}) {
3025
+ const score = params.score ?? 0;
3026
+ if (score < 0 || score > 1) {
3027
+ throw new Error(`score must be in [0.0, 1.0], got ${score}`);
3028
+ }
3029
+ return {
3030
+ type: 40 /* PERSONAL_RESEARCH_RESULT */,
3031
+ run_id: params.run_id ?? _generateRunId(),
3032
+ run_type: params.run_type ?? "personal",
3033
+ candidate_id: params.candidate_id ?? "",
3034
+ score,
3035
+ hardware_tier: params.hardware_tier ?? "",
3036
+ model_id: params.model_id ?? "",
3037
+ owner_uid: params.owner_uid ?? "",
3038
+ metrics: params.metrics ?? {
3039
+ success_rate: 0,
3040
+ p66_rate: 0,
3041
+ token_efficiency: 0,
3042
+ latency_score: 0
3043
+ },
3044
+ submitted_to_community: params.submitted_to_community ?? false,
3045
+ created_at: params.created_at ?? Date.now() / 1e3
3046
+ };
3047
+ }
3048
+ function validateCompetitionScope(scopeLevel) {
3049
+ return scopeLevel >= COMPETITION_SCOPE_LEVEL;
3050
+ }
3051
+
3052
+ // src/firmware.ts
3053
+ var FIRMWARE_MANIFEST_PATH = "/.well-known/rcan-firmware-manifest.json";
3054
+ function manifestToWire(m) {
3055
+ const wire = {
3056
+ rrn: m.rrn,
3057
+ firmware_version: m.firmwareVersion,
3058
+ build_hash: m.buildHash,
3059
+ components: m.components,
3060
+ signed_at: m.signedAt
3061
+ };
3062
+ if (m.signature) wire.signature = m.signature;
3063
+ return wire;
3064
+ }
3065
+ function manifestFromWire(w) {
3066
+ return {
3067
+ rrn: w.rrn,
3068
+ firmwareVersion: w.firmware_version,
3069
+ buildHash: w.build_hash,
3070
+ components: w.components ?? [],
3071
+ signedAt: w.signed_at ?? "",
3072
+ signature: w.signature
3073
+ };
3074
+ }
3075
+ function canonicalManifestJson(m) {
3076
+ const obj = {
3077
+ build_hash: m.buildHash,
3078
+ components: m.components.map((c) => ({
3079
+ hash: c.hash,
3080
+ name: c.name,
3081
+ version: c.version
3082
+ })),
3083
+ firmware_version: m.firmwareVersion,
3084
+ rrn: m.rrn,
3085
+ signed_at: m.signedAt
3086
+ };
3087
+ return JSON.stringify(obj);
3088
+ }
3089
+ var FirmwareIntegrityError = class extends Error {
3090
+ constructor(message) {
3091
+ super(message);
3092
+ this.name = "FirmwareIntegrityError";
3093
+ }
3094
+ };
3095
+ function validateManifest(m) {
3096
+ const errors = [];
3097
+ if (!m.rrn) errors.push("rrn is required");
3098
+ if (!m.firmwareVersion) errors.push("firmwareVersion is required");
3099
+ if (!m.buildHash) errors.push("buildHash is required");
3100
+ if (!m.buildHash.startsWith("sha256:")) errors.push("buildHash must start with 'sha256:'");
3101
+ if (!m.signedAt) errors.push("signedAt is required");
3102
+ if (!m.signature) errors.push("signature is required (manifest must be signed)");
3103
+ for (const [i, c] of m.components.entries()) {
3104
+ if (!c.name) errors.push(`components[${i}].name is required`);
3105
+ if (!c.version) errors.push(`components[${i}].version is required`);
3106
+ if (!c.hash.startsWith("sha256:")) errors.push(`components[${i}].hash must start with 'sha256:'`);
3107
+ }
3108
+ return errors;
3109
+ }
3110
+
3111
+ // src/authority.ts
3112
+ function authorityAccessToWire(p) {
3113
+ return {
3114
+ request_id: p.requestId,
3115
+ authority_id: p.authorityId,
3116
+ requested_data: p.requestedData,
3117
+ justification: p.justification,
3118
+ expires_at: p.expiresAt
3119
+ };
3120
+ }
3121
+ function authorityAccessFromWire(w) {
3122
+ return {
3123
+ requestId: w.request_id,
3124
+ authorityId: w.authority_id,
3125
+ requestedData: w.requested_data ?? [],
3126
+ justification: w.justification ?? "",
3127
+ expiresAt: w.expires_at ?? 0
3128
+ };
3129
+ }
3130
+ function validateAuthorityAccess(p) {
3131
+ const errors = [];
3132
+ if (!p.requestId) errors.push("requestId is required");
3133
+ if (!p.authorityId) errors.push("authorityId is required");
3134
+ if (!p.requestedData || p.requestedData.length === 0)
3135
+ errors.push("requestedData must include at least one category");
3136
+ if (!p.justification) errors.push("justification is required");
3137
+ if (!p.expiresAt || p.expiresAt <= 0) errors.push("expiresAt must be a positive Unix timestamp");
3138
+ if (p.expiresAt < Date.now() / 1e3) errors.push("expiresAt is in the past \u2014 request has expired");
3139
+ return errors;
3140
+ }
3141
+ function isAuthorityRequestValid(p) {
3142
+ return Date.now() / 1e3 < p.expiresAt && validateAuthorityAccess(p).length === 0;
3143
+ }
3144
+ var AUTHORITY_ERROR_CODES = {
3145
+ NOT_RECOGNIZED: "AUTHORITY_NOT_RECOGNIZED",
3146
+ REQUEST_EXPIRED: "AUTHORITY_REQUEST_EXPIRED",
3147
+ INVALID_TOKEN: "AUTHORITY_INVALID_TOKEN",
3148
+ RATE_LIMITED: "AUTHORITY_RATE_LIMITED"
3149
+ };
3150
+
3151
+ // src/m2m.ts
3152
+ var RRF_REVOCATION_URL = "https://api.rrf.rcan.dev/v2/revocations";
3153
+ var M2M_TRUSTED_ISSUER = "rrf.rcan.dev";
3154
+ var RRF_REVOCATION_CACHE_TTL_MS = 55e3;
3155
+ var M2MAuthError = class extends Error {
3156
+ constructor(message) {
3157
+ super(message);
3158
+ this.name = "M2MAuthError";
3159
+ }
3160
+ };
3161
+ function decodeJwtPayload2(token) {
3162
+ const parts = token.split(".");
3163
+ if (parts.length < 2) throw new M2MAuthError("Invalid JWT structure");
3164
+ const b64 = (parts[1] ?? "").replace(/-/g, "+").replace(/_/g, "/");
3165
+ const padded = b64 + "=".repeat((4 - b64.length % 4) % 4);
3166
+ try {
3167
+ return JSON.parse(atob(padded));
3168
+ } catch (e) {
3169
+ throw new M2MAuthError(`JWT payload decode failed: ${String(e)}`);
3170
+ }
3171
+ }
3172
+ function parseM2mPeerToken(token) {
3173
+ const payload = decodeJwtPayload2(token);
3174
+ const exp = Number(payload["exp"] ?? 0);
3175
+ if (exp > 0 && Date.now() / 1e3 > exp) {
3176
+ throw new M2MAuthError(`M2M_PEER token expired (sub=${String(payload["sub"])})`);
3177
+ }
3178
+ const peerRrn = String(payload["peer_rrn"] ?? "");
3179
+ if (!peerRrn) throw new M2MAuthError("M2M_PEER token missing peer_rrn claim");
3180
+ return {
3181
+ sub: String(payload["sub"] ?? ""),
3182
+ peerRrn,
3183
+ scopes: Array.isArray(payload["rcan_scopes"]) ? payload["rcan_scopes"] : Array.isArray(payload["scopes"]) ? payload["scopes"] : [],
3184
+ exp,
3185
+ iss: String(payload["iss"] ?? "")
3186
+ };
3187
+ }
3188
+ function parseM2mTrustedToken(token) {
3189
+ const payload = decodeJwtPayload2(token);
3190
+ const iss = String(payload["iss"] ?? "");
3191
+ if (iss !== M2M_TRUSTED_ISSUER) {
3192
+ throw new M2MAuthError(
3193
+ `M2M_TRUSTED issuer must be '${M2M_TRUSTED_ISSUER}', got '${iss}'`
3194
+ );
3195
+ }
3196
+ const scopes = Array.isArray(payload["rcan_scopes"]) ? payload["rcan_scopes"] : Array.isArray(payload["scopes"]) ? payload["scopes"] : [];
3197
+ if (!scopes.includes("fleet.trusted")) {
3198
+ throw new M2MAuthError("M2M_TRUSTED token missing required 'fleet.trusted' scope");
3199
+ }
3200
+ const exp = Number(payload["exp"] ?? 0);
3201
+ if (exp > 0 && Date.now() / 1e3 > exp) {
3202
+ throw new M2MAuthError(`M2M_TRUSTED token expired (sub=${String(payload["sub"])})`);
3203
+ }
3204
+ const rrfSig = String(payload["rrf_sig"] ?? "");
3205
+ if (!rrfSig) throw new M2MAuthError("M2M_TRUSTED token missing rrf_sig claim");
3206
+ const fleetRrns = Array.isArray(payload["fleet_rrns"]) ? payload["fleet_rrns"] : [];
3207
+ return {
3208
+ sub: String(payload["sub"] ?? ""),
3209
+ fleetRrns,
3210
+ scopes,
3211
+ exp,
3212
+ iss,
3213
+ rrfSig
3214
+ };
3215
+ }
3216
+ function verifyM2mTrustedTokenClaims(token, targetRrn) {
3217
+ const claims = parseM2mTrustedToken(token);
3218
+ if (!claims.fleetRrns.includes(targetRrn)) {
3219
+ throw new M2MAuthError(
3220
+ `M2M_TRUSTED token does not authorize commanding '${targetRrn}'. Authorized fleet: [${claims.fleetRrns.join(", ")}]`
3221
+ );
3222
+ }
3223
+ return claims;
3224
+ }
3225
+ var _revocationCache = null;
3226
+ async function fetchRRFRevocations(url = RRF_REVOCATION_URL) {
3227
+ const now = Date.now();
3228
+ if (_revocationCache && now - _revocationCache.fetchedAt < RRF_REVOCATION_CACHE_TTL_MS) {
3229
+ return _revocationCache;
3230
+ }
3231
+ try {
3232
+ const resp = await fetch(url, { signal: AbortSignal.timeout?.(5e3) });
3233
+ const data = await resp.json();
3234
+ _revocationCache = {
3235
+ revokedOrchestrators: new Set(data.revoked_orchestrators ?? []),
3236
+ revokedJtis: new Set(data.revoked_jtis ?? []),
3237
+ fetchedAt: now
3238
+ };
3239
+ } catch {
3240
+ if (_revocationCache) return _revocationCache;
3241
+ _revocationCache = { revokedOrchestrators: /* @__PURE__ */ new Set(), revokedJtis: /* @__PURE__ */ new Set(), fetchedAt: now };
3242
+ }
3243
+ return _revocationCache;
3244
+ }
3245
+ async function isM2mTrustedRevoked(claims, jti) {
3246
+ const cache = await fetchRRFRevocations();
3247
+ if (cache.revokedOrchestrators.has(claims.sub)) return true;
3248
+ if (jti && cache.revokedJtis.has(jti)) return true;
3249
+ return false;
3250
+ }
3251
+ async function verifyM2mTrustedToken(token, targetRrn, options) {
3252
+ const claims = verifyM2mTrustedTokenClaims(token, targetRrn);
3253
+ if (!options?.skipRevocationCheck) {
3254
+ const revoked = await isM2mTrustedRevoked(claims);
3255
+ if (revoked) {
3256
+ throw new M2MAuthError(
3257
+ `M2M_TRUSTED orchestrator '${claims.sub}' is on the RRF revocation list`
3258
+ );
3259
+ }
3260
+ }
3261
+ return claims;
3262
+ }
3263
+
3264
+ // src/pqSigning.ts
3265
+ function toBase64url(bytes) {
3266
+ let binary = "";
3267
+ for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
3268
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
3269
+ }
3270
+ function fromBase64url(b64) {
3271
+ const padded = b64.replace(/-/g, "+").replace(/_/g, "/");
3272
+ const binary = atob(padded);
3273
+ const bytes = new Uint8Array(binary.length);
3274
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
3275
+ return bytes;
3276
+ }
3277
+ async function sha256hex(data) {
3278
+ const g = typeof globalThis !== "undefined" ? globalThis : {};
3279
+ const webcrypto = g.crypto;
3280
+ const subtle = webcrypto?.subtle;
3281
+ if (subtle) {
3282
+ const buf = await subtle.digest("SHA-256", data);
3283
+ return Array.from(new Uint8Array(buf)).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, 8);
3284
+ }
3285
+ const nodeCrypto = await import("crypto").catch(() => null);
3286
+ if (nodeCrypto) {
3287
+ return nodeCrypto.createHash("sha256").update(data).digest("hex").slice(0, 8);
3288
+ }
3289
+ throw new Error("No SHA-256 implementation available");
3290
+ }
3291
+ var _mlDsaModule;
3292
+ async function requireNoblePostQuantum() {
3293
+ if (_mlDsaModule) return _mlDsaModule;
3294
+ if (typeof require !== "undefined") {
3295
+ try {
3296
+ _mlDsaModule = require("@noble/post-quantum/ml-dsa.js");
3297
+ return _mlDsaModule;
3298
+ } catch {
3299
+ }
3300
+ }
3301
+ try {
3302
+ _mlDsaModule = await import("@noble/post-quantum/ml-dsa.js");
3303
+ return _mlDsaModule;
3304
+ } catch {
3305
+ throw new Error(
3306
+ "ML-DSA signing requires @noble/post-quantum. Install with: npm install @noble/post-quantum"
3307
+ );
3308
+ }
3309
+ }
3310
+ var MLDSAKeyPair = class _MLDSAKeyPair {
3311
+ keyId;
3312
+ publicKey;
3313
+ secretKey;
3314
+ constructor(data) {
3315
+ this.keyId = data.keyId;
3316
+ this.publicKey = data.publicKey;
3317
+ this.secretKey = data.secretKey;
3318
+ }
3319
+ /** Generate a new ML-DSA-65 key pair. */
3320
+ static async generate() {
3321
+ const { ml_dsa65 } = await requireNoblePostQuantum();
3322
+ const kp = ml_dsa65.keygen();
3323
+ const keyId = await sha256hex(kp.publicKey);
3324
+ return new _MLDSAKeyPair({
3325
+ publicKey: kp.publicKey,
3326
+ secretKey: kp.secretKey,
3327
+ keyId
3328
+ });
3329
+ }
3330
+ /** Build a verify-only key pair from raw public key bytes. */
3331
+ static async fromPublicKey(publicKey) {
3332
+ const keyId = await sha256hex(publicKey);
3333
+ return new _MLDSAKeyPair({ publicKey, keyId });
3334
+ }
3335
+ /** Build a full key pair from saved bytes (public + secret). */
3336
+ static async fromKeyMaterial(publicKey, secretKey) {
3337
+ const keyId = await sha256hex(publicKey);
3338
+ return new _MLDSAKeyPair({ publicKey, secretKey, keyId });
3339
+ }
3340
+ get hasPrivateKey() {
3341
+ return this.secretKey !== void 0;
3342
+ }
3343
+ /** Sign raw bytes; returns ML-DSA-65 signature (3309 bytes). */
3344
+ async signBytes(data) {
3345
+ if (!this.secretKey) {
3346
+ throw new Error("Cannot sign: MLDSAKeyPair has no private key (verify-only)");
3347
+ }
3348
+ const { ml_dsa65 } = await requireNoblePostQuantum();
3349
+ return ml_dsa65.sign(data, this.secretKey);
3350
+ }
3351
+ /**
3352
+ * Verify an ML-DSA-65 signature.
3353
+ * @returns true if valid
3354
+ * @throws {Error} on invalid signature
3355
+ */
3356
+ async verifyBytes(data, signature) {
3357
+ const { ml_dsa65 } = await requireNoblePostQuantum();
3358
+ const ok = ml_dsa65.verify(signature, data, this.publicKey);
3359
+ if (!ok) throw new Error("ML-DSA signature verification failed");
3360
+ }
3361
+ toString() {
3362
+ const mode = this.hasPrivateKey ? "private+public" : "public-only";
3363
+ return `MLDSAKeyPair(keyId=${this.keyId}, alg=ML-DSA-65, ${mode})`;
3364
+ }
3365
+ };
3366
+ function canonicalMessageBytes(msg) {
3367
+ const m = msg;
3368
+ const payload = {
3369
+ rcan: msg.rcan,
3370
+ msg_id: m["msgId"] ?? m["msg_id"] ?? "",
3371
+ timestamp: msg.timestamp,
3372
+ cmd: msg.cmd,
3373
+ target: msg.target,
3374
+ params: msg.params
3375
+ };
3376
+ const sorted = JSON.stringify(
3377
+ Object.fromEntries(Object.entries(payload).sort()),
3378
+ null,
3379
+ void 0
3380
+ );
3381
+ return new TextEncoder().encode(sorted);
3382
+ }
3383
+ async function addPQSignature(msg, keypair) {
3384
+ const payload = canonicalMessageBytes(msg);
3385
+ const rawSig = await keypair.signBytes(payload);
3386
+ const block = {
3387
+ alg: "ml-dsa-65",
3388
+ kid: keypair.keyId,
3389
+ sig: toBase64url(rawSig)
3390
+ };
3391
+ msg["pqSig"] = block;
3392
+ return msg;
3393
+ }
3394
+ async function verifyPQSignature(msg, trustedKeys, requirePQ = false) {
3395
+ const pqSig = msg["pqSig"];
3396
+ if (!pqSig) {
3397
+ if (requirePQ) {
3398
+ throw new Error("ML-DSA signature (pqSig) required but missing from message");
3399
+ }
3400
+ return;
3401
+ }
3402
+ if (pqSig.alg !== "ml-dsa-65") {
3403
+ throw new Error(`Unsupported PQ signature algorithm: ${pqSig.alg}`);
3404
+ }
3405
+ const matched = trustedKeys.find((k) => k.keyId === pqSig.kid);
3406
+ if (!matched) {
3407
+ throw new Error(
3408
+ `No trusted ML-DSA key with kid=${pqSig.kid}. Known kids: [${trustedKeys.map((k) => k.keyId).join(", ")}]`
3409
+ );
3410
+ }
3411
+ let rawSig;
3412
+ try {
3413
+ rawSig = fromBase64url(pqSig.sig);
3414
+ } catch (e) {
3415
+ throw new Error(`Invalid base64url ML-DSA signature: ${e}`);
3416
+ }
3417
+ const payload = canonicalMessageBytes(msg);
3418
+ await matched.verifyBytes(payload, rawSig);
3419
+ }
3420
+
2867
3421
  // src/index.ts
2868
3422
  var VERSION = "0.6.0";
2869
3423
  var RCAN_VERSION = "1.6";
2870
3424
  // Annotate the CommonJS export names for ESM import in node:
2871
3425
  0 && (module.exports = {
3426
+ AUTHORITY_ERROR_CODES,
2872
3427
  AuditChain,
2873
3428
  AuditError,
3429
+ COMPETITION_SCOPE_LEVEL,
2874
3430
  CONTRIBUTE_SCOPE_LEVEL,
2875
3431
  ClockDriftError,
2876
3432
  CommitmentRecord,
2877
3433
  ConfidenceGate,
2878
3434
  DEFAULT_LOA_POLICY,
2879
3435
  DataCategory,
3436
+ FIRMWARE_MANIFEST_PATH,
2880
3437
  FaultCode,
2881
3438
  FederationSyncType,
3439
+ FirmwareIntegrityError,
2882
3440
  GateError,
2883
3441
  HiTLGate,
2884
3442
  KeyStore,
2885
3443
  LevelOfAssurance,
3444
+ M2MAuthError,
3445
+ M2M_TRUSTED_ISSUER,
3446
+ MLDSAKeyPair,
2886
3447
  MediaEncoding,
2887
3448
  MessageType,
2888
3449
  NodeClient,
@@ -2908,13 +3469,18 @@ var RCAN_VERSION = "1.6";
2908
3469
  RCANValidationError,
2909
3470
  RCANVersionIncompatibleError,
2910
3471
  RCAN_VERSION,
3472
+ ROLE_JWT_LEVEL,
3473
+ RRF_REVOCATION_CACHE_TTL_MS,
3474
+ RRF_REVOCATION_URL,
2911
3475
  RegistryClient,
2912
3476
  RegistryTier,
2913
3477
  ReplayCache,
2914
3478
  RevocationCache,
2915
3479
  RobotURI,
2916
3480
  RobotURIError,
3481
+ Role,
2917
3482
  SAFETY_MESSAGE_TYPE,
3483
+ SCOPE_MIN_ROLE,
2918
3484
  SDK_VERSION,
2919
3485
  SPEC_VERSION,
2920
3486
  TransportEncoding,
@@ -2924,7 +3490,11 @@ var RCAN_VERSION = "1.6";
2924
3490
  addDelegationHop,
2925
3491
  addMediaInline,
2926
3492
  addMediaRef,
3493
+ addPQSignature,
2927
3494
  assertClockSynced,
3495
+ authorityAccessFromWire,
3496
+ authorityAccessToWire,
3497
+ canonicalManifestJson,
2928
3498
  checkClockSync,
2929
3499
  checkRevocation,
2930
3500
  decodeBleFrames,
@@ -2933,11 +3503,18 @@ var RCAN_VERSION = "1.6";
2933
3503
  encodeBleFrames,
2934
3504
  encodeCompact,
2935
3505
  encodeMinimal,
3506
+ extractIdentityFromJwt,
2936
3507
  extractLoaFromJwt,
3508
+ extractRoleFromJwt,
2937
3509
  fetchCanonicalSchema,
3510
+ fetchRRFRevocations,
3511
+ isAuthorityRequestValid,
3512
+ isM2mTrustedRevoked,
2938
3513
  isPreemptedBy,
2939
3514
  isSafetyMessage,
2940
3515
  makeCloudRelayMessage,
3516
+ makeCompetitionEnter,
3517
+ makeCompetitionScore,
2941
3518
  makeConfigUpdate,
2942
3519
  makeConsentDeny,
2943
3520
  makeConsentGrant,
@@ -2950,8 +3527,10 @@ var RCAN_VERSION = "1.6";
2950
3527
  makeFaultReport,
2951
3528
  makeFederationSync,
2952
3529
  makeKeyRotationMessage,
3530
+ makePersonalResearchResult,
2953
3531
  makeResumeMessage,
2954
3532
  makeRevocationBroadcast,
3533
+ makeSeasonStanding,
2955
3534
  makeStopMessage,
2956
3535
  makeStreamChunk,
2957
3536
  makeTrainingConsentDeny,
@@ -2959,7 +3538,14 @@ var RCAN_VERSION = "1.6";
2959
3538
  makeTrainingConsentRequest,
2960
3539
  makeTrainingDataMessage,
2961
3540
  makeTransparencyMessage,
3541
+ manifestFromWire,
3542
+ manifestToWire,
3543
+ parseM2mPeerToken,
3544
+ parseM2mTrustedToken,
3545
+ roleFromJwtLevel,
2962
3546
  selectTransport,
3547
+ validateAuthorityAccess,
3548
+ validateCompetitionScope,
2963
3549
  validateConfig,
2964
3550
  validateConfigAgainstSchema,
2965
3551
  validateConfigUpdate,
@@ -2968,13 +3554,18 @@ var RCAN_VERSION = "1.6";
2968
3554
  validateCrossRegistryCommand,
2969
3555
  validateDelegationChain,
2970
3556
  validateLoaForScope,
3557
+ validateManifest,
2971
3558
  validateMediaChunks,
2972
3559
  validateMessage,
2973
3560
  validateNodeAgainstSchema,
2974
3561
  validateReplay,
3562
+ validateRoleForScope,
2975
3563
  validateSafetyMessage,
2976
3564
  validateTrainingDataMessage,
2977
3565
  validateURI,
2978
- validateVersionCompat
3566
+ validateVersionCompat,
3567
+ verifyM2mTrustedToken,
3568
+ verifyM2mTrustedTokenClaims,
3569
+ verifyPQSignature
2979
3570
  });
2980
3571
  //# sourceMappingURL=index.js.map