@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/README.md +1 -0
- package/dist/browser.d.mts +482 -39
- package/dist/browser.mjs +627 -73
- package/dist/browser.mjs.map +1 -1
- package/dist/index.d.mts +482 -39
- package/dist/index.d.ts +482 -39
- package/dist/index.js +665 -74
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +627 -73
- package/dist/index.mjs.map +1 -1
- package/dist/rcan-validate.js +22 -2
- package/dist/rcan.iife.js +16 -3
- package/package.json +28 -5
package/dist/index.mjs
CHANGED
|
@@ -96,8 +96,8 @@ var RobotURI = class _RobotURI {
|
|
|
96
96
|
};
|
|
97
97
|
|
|
98
98
|
// src/version.ts
|
|
99
|
-
var SPEC_VERSION = "
|
|
100
|
-
var SDK_VERSION = "
|
|
99
|
+
var SPEC_VERSION = "2.2.0";
|
|
100
|
+
var SDK_VERSION = "1.2.0";
|
|
101
101
|
function validateVersionCompat(incomingVersion, localVersion = SPEC_VERSION) {
|
|
102
102
|
const parseParts = (v) => {
|
|
103
103
|
const parts = v.split(".");
|
|
@@ -148,9 +148,14 @@ var MessageType = /* @__PURE__ */ ((MessageType2) => {
|
|
|
148
148
|
MessageType2[MessageType2["CONTRIBUTE_RESULT"] = 34] = "CONTRIBUTE_RESULT";
|
|
149
149
|
MessageType2[MessageType2["CONTRIBUTE_CANCEL"] = 35] = "CONTRIBUTE_CANCEL";
|
|
150
150
|
MessageType2[MessageType2["TRAINING_DATA"] = 36] = "TRAINING_DATA";
|
|
151
|
-
MessageType2[MessageType2["
|
|
152
|
-
MessageType2[MessageType2["
|
|
153
|
-
MessageType2[MessageType2["
|
|
151
|
+
MessageType2[MessageType2["COMPETITION_ENTER"] = 37] = "COMPETITION_ENTER";
|
|
152
|
+
MessageType2[MessageType2["COMPETITION_SCORE"] = 38] = "COMPETITION_SCORE";
|
|
153
|
+
MessageType2[MessageType2["SEASON_STANDING"] = 39] = "SEASON_STANDING";
|
|
154
|
+
MessageType2[MessageType2["PERSONAL_RESEARCH_RESULT"] = 40] = "PERSONAL_RESEARCH_RESULT";
|
|
155
|
+
MessageType2[MessageType2["AUTHORITY_ACCESS"] = 41] = "AUTHORITY_ACCESS";
|
|
156
|
+
MessageType2[MessageType2["AUTHORITY_RESPONSE"] = 42] = "AUTHORITY_RESPONSE";
|
|
157
|
+
MessageType2[MessageType2["FIRMWARE_ATTESTATION"] = 43] = "FIRMWARE_ATTESTATION";
|
|
158
|
+
MessageType2[MessageType2["SBOM_UPDATE"] = 44] = "SBOM_UPDATE";
|
|
154
159
|
return MessageType2;
|
|
155
160
|
})(MessageType || {});
|
|
156
161
|
var RCANMessageError = class extends Error {
|
|
@@ -186,6 +191,12 @@ var RCANMessage = class _RCANMessage {
|
|
|
186
191
|
transportEncoding;
|
|
187
192
|
/** v1.6: GAP-18 multi-modal media chunks */
|
|
188
193
|
mediaChunks;
|
|
194
|
+
/** v2.1: SHA-256 of sender's firmware manifest */
|
|
195
|
+
firmwareHash;
|
|
196
|
+
/** v2.1: URI to sender's SBOM attestation endpoint */
|
|
197
|
+
attestationRef;
|
|
198
|
+
/** v2.2: ML-DSA-65 post-quantum signature (field 16, FIPS 204). Hybrid alongside Ed25519. */
|
|
199
|
+
pqSig;
|
|
189
200
|
constructor(data) {
|
|
190
201
|
if (!data.cmd || data.cmd.trim() === "") {
|
|
191
202
|
throw new RCANMessageError("'cmd' is required");
|
|
@@ -214,6 +225,14 @@ var RCANMessage = class _RCANMessage {
|
|
|
214
225
|
this.loa = data.loa;
|
|
215
226
|
this.transportEncoding = data.transportEncoding;
|
|
216
227
|
this.mediaChunks = data.mediaChunks;
|
|
228
|
+
this.firmwareHash = data.firmwareHash;
|
|
229
|
+
this.attestationRef = data.attestationRef;
|
|
230
|
+
this.pqSig = data.pqSig;
|
|
231
|
+
if (this.signature !== void 0 && this.signature["sig"] === "pending") {
|
|
232
|
+
throw new RCANMessageError(
|
|
233
|
+
"signature.sig:'pending' is not valid in RCAN v2.1. Sign the message before sending."
|
|
234
|
+
);
|
|
235
|
+
}
|
|
217
236
|
if (this.confidence !== void 0) {
|
|
218
237
|
if (this.confidence < 0 || this.confidence > 1) {
|
|
219
238
|
throw new RCANMessageError(
|
|
@@ -255,6 +274,9 @@ var RCANMessage = class _RCANMessage {
|
|
|
255
274
|
if (this.loa !== void 0) obj.loa = this.loa;
|
|
256
275
|
if (this.transportEncoding !== void 0) obj.transportEncoding = this.transportEncoding;
|
|
257
276
|
if (this.mediaChunks !== void 0) obj.mediaChunks = this.mediaChunks;
|
|
277
|
+
if (this.firmwareHash !== void 0) obj.firmwareHash = this.firmwareHash;
|
|
278
|
+
if (this.attestationRef !== void 0) obj.attestationRef = this.attestationRef;
|
|
279
|
+
if (this.pqSig !== void 0) obj.pqSig = this.pqSig;
|
|
258
280
|
return obj;
|
|
259
281
|
}
|
|
260
282
|
/** Serialize to JSON string */
|
|
@@ -297,7 +319,10 @@ var RCANMessage = class _RCANMessage {
|
|
|
297
319
|
readOnly: obj.readOnly,
|
|
298
320
|
loa: obj.loa,
|
|
299
321
|
transportEncoding: obj.transportEncoding,
|
|
300
|
-
mediaChunks: obj.mediaChunks
|
|
322
|
+
mediaChunks: obj.mediaChunks,
|
|
323
|
+
firmwareHash: obj.firmwareHash,
|
|
324
|
+
attestationRef: obj.attestationRef,
|
|
325
|
+
pqSig: obj.pqSig
|
|
301
326
|
});
|
|
302
327
|
}
|
|
303
328
|
};
|
|
@@ -2051,80 +2076,133 @@ function makeFaultReport(params) {
|
|
|
2051
2076
|
}
|
|
2052
2077
|
|
|
2053
2078
|
// src/identity.ts
|
|
2054
|
-
var
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2079
|
+
var Role = /* @__PURE__ */ ((Role2) => {
|
|
2080
|
+
Role2[Role2["GUEST"] = 1] = "GUEST";
|
|
2081
|
+
Role2[Role2["OPERATOR"] = 2] = "OPERATOR";
|
|
2082
|
+
Role2[Role2["CONTRIBUTOR"] = 3] = "CONTRIBUTOR";
|
|
2083
|
+
Role2[Role2["ADMIN"] = 4] = "ADMIN";
|
|
2084
|
+
Role2[Role2["M2M_PEER"] = 5] = "M2M_PEER";
|
|
2085
|
+
Role2[Role2["CREATOR"] = 6] = "CREATOR";
|
|
2086
|
+
Role2[Role2["M2M_TRUSTED"] = 7] = "M2M_TRUSTED";
|
|
2087
|
+
return Role2;
|
|
2088
|
+
})(Role || {});
|
|
2089
|
+
var LevelOfAssurance = Role;
|
|
2090
|
+
var ROLE_JWT_LEVEL = {
|
|
2091
|
+
[1 /* GUEST */]: 1,
|
|
2092
|
+
[2 /* OPERATOR */]: 2,
|
|
2093
|
+
[3 /* CONTRIBUTOR */]: 2.5,
|
|
2094
|
+
[4 /* ADMIN */]: 3,
|
|
2095
|
+
[5 /* M2M_PEER */]: 4,
|
|
2096
|
+
[6 /* CREATOR */]: 5,
|
|
2097
|
+
[7 /* M2M_TRUSTED */]: 6
|
|
2098
|
+
};
|
|
2099
|
+
var JWT_LEVEL_TO_ROLE = new Map(
|
|
2100
|
+
Object.entries(ROLE_JWT_LEVEL).map(
|
|
2101
|
+
([role, level]) => [level, Number(role)]
|
|
2102
|
+
)
|
|
2103
|
+
);
|
|
2104
|
+
function roleFromJwtLevel(level) {
|
|
2105
|
+
return JWT_LEVEL_TO_ROLE.get(level);
|
|
2106
|
+
}
|
|
2107
|
+
var SCOPE_MIN_ROLE = {
|
|
2108
|
+
"status": 1 /* GUEST */,
|
|
2109
|
+
"discover": 1 /* GUEST */,
|
|
2110
|
+
"chat": 1 /* GUEST */,
|
|
2111
|
+
"observer": 1 /* GUEST */,
|
|
2112
|
+
"contribute": 3 /* CONTRIBUTOR */,
|
|
2113
|
+
"control": 2 /* OPERATOR */,
|
|
2114
|
+
"teleop": 2 /* OPERATOR */,
|
|
2115
|
+
"training": 4 /* ADMIN */,
|
|
2116
|
+
"training_data": 4 /* ADMIN */,
|
|
2117
|
+
"config": 4 /* ADMIN */,
|
|
2118
|
+
"authority": 4 /* ADMIN */,
|
|
2119
|
+
"admin": 6 /* CREATOR */,
|
|
2120
|
+
"safety": 6 /* CREATOR */,
|
|
2121
|
+
"estop": 6 /* CREATOR */,
|
|
2122
|
+
"fleet.trusted": 7 /* M2M_TRUSTED */
|
|
2123
|
+
};
|
|
2060
2124
|
var DEFAULT_LOA_POLICY = {
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2125
|
+
minRoleForDiscover: 1 /* GUEST */,
|
|
2126
|
+
minRoleForStatus: 1 /* GUEST */,
|
|
2127
|
+
minRoleForChat: 1 /* GUEST */,
|
|
2128
|
+
minRoleForControl: 1 /* GUEST */,
|
|
2129
|
+
minRoleForSafety: 1 /* GUEST */
|
|
2066
2130
|
};
|
|
2067
2131
|
var PRODUCTION_LOA_POLICY = {
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2132
|
+
minRoleForDiscover: 1 /* GUEST */,
|
|
2133
|
+
minRoleForStatus: 1 /* GUEST */,
|
|
2134
|
+
minRoleForChat: 1 /* GUEST */,
|
|
2135
|
+
minRoleForControl: 2 /* OPERATOR */,
|
|
2136
|
+
minRoleForSafety: 6 /* CREATOR */
|
|
2073
2137
|
};
|
|
2074
|
-
function
|
|
2138
|
+
function decodeJwtPayload(token) {
|
|
2075
2139
|
try {
|
|
2076
2140
|
const parts = token.split(".");
|
|
2077
|
-
if (parts.length < 2) return
|
|
2141
|
+
if (parts.length < 2) return null;
|
|
2078
2142
|
const payloadB64 = (parts[1] ?? "").replace(/-/g, "+").replace(/_/g, "/");
|
|
2079
2143
|
const padded = payloadB64 + "=".repeat((4 - payloadB64.length % 4) % 4);
|
|
2080
|
-
|
|
2081
|
-
if (typeof atob !== "undefined") {
|
|
2082
|
-
json = atob(padded);
|
|
2083
|
-
} else {
|
|
2084
|
-
json = Buffer.from(padded, "base64").toString("utf-8");
|
|
2085
|
-
}
|
|
2086
|
-
const claims = JSON.parse(json);
|
|
2087
|
-
const loa = claims["loa"];
|
|
2088
|
-
if (typeof loa === "number" && loa >= 1 && loa <= 3) {
|
|
2089
|
-
return loa;
|
|
2090
|
-
}
|
|
2144
|
+
return JSON.parse(atob(padded));
|
|
2091
2145
|
} catch {
|
|
2146
|
+
return null;
|
|
2092
2147
|
}
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
return policy.minLoaStatus;
|
|
2102
|
-
case "chat":
|
|
2103
|
-
return policy.minLoaChat;
|
|
2104
|
-
case "contribute":
|
|
2105
|
-
return policy.minLoaChat;
|
|
2106
|
-
// v1.7: between chat and control
|
|
2107
|
-
case "control":
|
|
2108
|
-
return policy.minLoaControl;
|
|
2109
|
-
case "safety":
|
|
2110
|
-
return policy.minLoaSafety;
|
|
2111
|
-
default:
|
|
2112
|
-
return null;
|
|
2113
|
-
}
|
|
2114
|
-
}
|
|
2115
|
-
function validateLoaForScope(loa, scope, policy = DEFAULT_LOA_POLICY) {
|
|
2116
|
-
const min = minLoaForScope(scope, policy);
|
|
2117
|
-
if (min === null) {
|
|
2118
|
-
return { valid: true, reason: "unknown scope; allowed by default" };
|
|
2119
|
-
}
|
|
2120
|
-
if (loa >= min) {
|
|
2121
|
-
return { valid: true, reason: "ok" };
|
|
2148
|
+
}
|
|
2149
|
+
function extractRoleFromJwt(token) {
|
|
2150
|
+
const payload = decodeJwtPayload(token);
|
|
2151
|
+
if (!payload) return 1 /* GUEST */;
|
|
2152
|
+
const rcanRole = payload["rcan_role"];
|
|
2153
|
+
if (rcanRole !== void 0 && rcanRole !== null) {
|
|
2154
|
+
const role = roleFromJwtLevel(Number(rcanRole));
|
|
2155
|
+
if (role !== void 0) return role;
|
|
2122
2156
|
}
|
|
2157
|
+
const loa = payload["loa"];
|
|
2158
|
+
if (loa !== void 0 && loa !== null) {
|
|
2159
|
+
const role = roleFromJwtLevel(Number(loa));
|
|
2160
|
+
if (role !== void 0) return role;
|
|
2161
|
+
}
|
|
2162
|
+
return 1 /* GUEST */;
|
|
2163
|
+
}
|
|
2164
|
+
function extractLoaFromJwt(token) {
|
|
2165
|
+
return extractRoleFromJwt(token);
|
|
2166
|
+
}
|
|
2167
|
+
function extractIdentityFromJwt(token) {
|
|
2168
|
+
const payload = decodeJwtPayload(token);
|
|
2169
|
+
if (!payload) {
|
|
2170
|
+
return { sub: "", role: 1 /* GUEST */, jwtLevel: 1, scopes: [] };
|
|
2171
|
+
}
|
|
2172
|
+
const rcanRole = payload["rcan_role"];
|
|
2173
|
+
const loa = payload["loa"];
|
|
2174
|
+
const rawLevel = rcanRole !== void 0 ? Number(rcanRole) : loa !== void 0 ? Number(loa) : 1;
|
|
2175
|
+
const role = roleFromJwtLevel(rawLevel) ?? 1 /* GUEST */;
|
|
2176
|
+
const scopes = Array.isArray(payload["rcan_scopes"]) ? payload["rcan_scopes"] : Array.isArray(payload["scopes"]) ? payload["scopes"] : [];
|
|
2123
2177
|
return {
|
|
2124
|
-
|
|
2125
|
-
|
|
2178
|
+
sub: String(payload["sub"] ?? ""),
|
|
2179
|
+
role,
|
|
2180
|
+
jwtLevel: ROLE_JWT_LEVEL[role],
|
|
2181
|
+
registryUrl: payload["registry_url"],
|
|
2182
|
+
scopes,
|
|
2183
|
+
verifiedAt: payload["verified_at"],
|
|
2184
|
+
peerRrn: payload["peer_rrn"],
|
|
2185
|
+
fleetRrns: Array.isArray(payload["fleet_rrns"]) ? payload["fleet_rrns"] : void 0
|
|
2126
2186
|
};
|
|
2127
2187
|
}
|
|
2188
|
+
function validateRoleForScope(role, scope) {
|
|
2189
|
+
const required = SCOPE_MIN_ROLE[scope.toLowerCase()];
|
|
2190
|
+
if (required === void 0) {
|
|
2191
|
+
if (role >= 2 /* OPERATOR */) return { ok: true, reason: "" };
|
|
2192
|
+
return {
|
|
2193
|
+
ok: false,
|
|
2194
|
+
reason: `Unknown scope '${scope}': applying OPERATOR minimum. Caller has ${Role[role]}.`
|
|
2195
|
+
};
|
|
2196
|
+
}
|
|
2197
|
+
if (role >= required) return { ok: true, reason: "" };
|
|
2198
|
+
return {
|
|
2199
|
+
ok: false,
|
|
2200
|
+
reason: `Scope '${scope}' requires ${Role[required]} (JWT level ${ROLE_JWT_LEVEL[required]}), but caller has ${Role[role]} (JWT level ${ROLE_JWT_LEVEL[role]})`
|
|
2201
|
+
};
|
|
2202
|
+
}
|
|
2203
|
+
function validateLoaForScope(role, scope) {
|
|
2204
|
+
return validateRoleForScope(role, scope);
|
|
2205
|
+
}
|
|
2128
2206
|
|
|
2129
2207
|
// src/federation.ts
|
|
2130
2208
|
var RegistryTier = /* @__PURE__ */ ((RegistryTier2) => {
|
|
@@ -2248,12 +2326,12 @@ function generateId5() {
|
|
|
2248
2326
|
}
|
|
2249
2327
|
function makeFederationSync(source, target, syncType, payload) {
|
|
2250
2328
|
return new RCANMessage({
|
|
2251
|
-
rcan: "1.
|
|
2252
|
-
rcanVersion: "1.
|
|
2329
|
+
rcan: "2.1.0",
|
|
2330
|
+
rcanVersion: "2.1.0",
|
|
2253
2331
|
cmd: "federation_sync",
|
|
2254
2332
|
target,
|
|
2255
2333
|
params: {
|
|
2256
|
-
msg_type: 23 /*
|
|
2334
|
+
msg_type: 23 /* FLEET_COMMAND */,
|
|
2257
2335
|
msg_id: generateId5(),
|
|
2258
2336
|
source_registry: source,
|
|
2259
2337
|
target_registry: target,
|
|
@@ -2280,17 +2358,17 @@ async function validateCrossRegistryCommand(msg, localRegistry, trustCache) {
|
|
|
2280
2358
|
reason: `REGISTRY_UNKNOWN: ${sourceRegistry} is not in the local trust cache`
|
|
2281
2359
|
};
|
|
2282
2360
|
}
|
|
2283
|
-
let loa = 1 /*
|
|
2361
|
+
let loa = 1 /* GUEST */;
|
|
2284
2362
|
const registryJwt = msg.params?.["registry_jwt"];
|
|
2285
2363
|
if (registryJwt) {
|
|
2286
2364
|
loa = extractLoaFromJwt(registryJwt);
|
|
2287
2365
|
} else if (typeof msg.loa === "number") {
|
|
2288
2366
|
loa = msg.loa;
|
|
2289
2367
|
}
|
|
2290
|
-
if (loa < 2 /*
|
|
2368
|
+
if (loa < 2 /* OPERATOR */) {
|
|
2291
2369
|
return {
|
|
2292
2370
|
valid: false,
|
|
2293
|
-
reason: `LOA_INSUFFICIENT: cross-registry commands require LoA>=2 (
|
|
2371
|
+
reason: `LOA_INSUFFICIENT: cross-registry commands require LoA>=2 (OPERATOR), got role=${loa}`
|
|
2294
2372
|
};
|
|
2295
2373
|
}
|
|
2296
2374
|
return { valid: true, reason: "cross-registry command accepted" };
|
|
@@ -2729,24 +2807,470 @@ function isPreemptedBy(scopeLevel) {
|
|
|
2729
2807
|
return scopeLevel >= 3;
|
|
2730
2808
|
}
|
|
2731
2809
|
|
|
2810
|
+
// src/competition.ts
|
|
2811
|
+
var COMPETITION_SCOPE_LEVEL = 2;
|
|
2812
|
+
var _idCounter2 = 0;
|
|
2813
|
+
function _generateRunId() {
|
|
2814
|
+
return `run-${Date.now()}-${++_idCounter2}`;
|
|
2815
|
+
}
|
|
2816
|
+
function makeCompetitionEnter(params = {}) {
|
|
2817
|
+
return {
|
|
2818
|
+
type: 37 /* COMPETITION_ENTER */,
|
|
2819
|
+
competition_id: params.competition_id ?? "",
|
|
2820
|
+
competition_format: params.competition_format ?? "sprint",
|
|
2821
|
+
hardware_tier: params.hardware_tier ?? "",
|
|
2822
|
+
model_id: params.model_id ?? "",
|
|
2823
|
+
robot_rrn: params.robot_rrn ?? "",
|
|
2824
|
+
entered_at: params.entered_at ?? Date.now() / 1e3
|
|
2825
|
+
};
|
|
2826
|
+
}
|
|
2827
|
+
function makeCompetitionScore(params = {}) {
|
|
2828
|
+
const score = params.score ?? 0;
|
|
2829
|
+
if (score < 0 || score > 1) {
|
|
2830
|
+
throw new Error(`score must be in [0.0, 1.0], got ${score}`);
|
|
2831
|
+
}
|
|
2832
|
+
return {
|
|
2833
|
+
type: 38 /* COMPETITION_SCORE */,
|
|
2834
|
+
competition_id: params.competition_id ?? "",
|
|
2835
|
+
candidate_id: params.candidate_id ?? "",
|
|
2836
|
+
score,
|
|
2837
|
+
hardware_tier: params.hardware_tier ?? "",
|
|
2838
|
+
verified: params.verified ?? false,
|
|
2839
|
+
submitted_at: params.submitted_at ?? Date.now() / 1e3
|
|
2840
|
+
};
|
|
2841
|
+
}
|
|
2842
|
+
function makeSeasonStanding(params = {}) {
|
|
2843
|
+
return {
|
|
2844
|
+
type: 39 /* SEASON_STANDING */,
|
|
2845
|
+
season_id: params.season_id ?? "",
|
|
2846
|
+
class_id: params.class_id ?? "",
|
|
2847
|
+
standings: params.standings ?? [],
|
|
2848
|
+
days_remaining: params.days_remaining ?? 0,
|
|
2849
|
+
broadcast_at: params.broadcast_at ?? Date.now() / 1e3
|
|
2850
|
+
};
|
|
2851
|
+
}
|
|
2852
|
+
function makePersonalResearchResult(params = {}) {
|
|
2853
|
+
const score = params.score ?? 0;
|
|
2854
|
+
if (score < 0 || score > 1) {
|
|
2855
|
+
throw new Error(`score must be in [0.0, 1.0], got ${score}`);
|
|
2856
|
+
}
|
|
2857
|
+
return {
|
|
2858
|
+
type: 40 /* PERSONAL_RESEARCH_RESULT */,
|
|
2859
|
+
run_id: params.run_id ?? _generateRunId(),
|
|
2860
|
+
run_type: params.run_type ?? "personal",
|
|
2861
|
+
candidate_id: params.candidate_id ?? "",
|
|
2862
|
+
score,
|
|
2863
|
+
hardware_tier: params.hardware_tier ?? "",
|
|
2864
|
+
model_id: params.model_id ?? "",
|
|
2865
|
+
owner_uid: params.owner_uid ?? "",
|
|
2866
|
+
metrics: params.metrics ?? {
|
|
2867
|
+
success_rate: 0,
|
|
2868
|
+
p66_rate: 0,
|
|
2869
|
+
token_efficiency: 0,
|
|
2870
|
+
latency_score: 0
|
|
2871
|
+
},
|
|
2872
|
+
submitted_to_community: params.submitted_to_community ?? false,
|
|
2873
|
+
created_at: params.created_at ?? Date.now() / 1e3
|
|
2874
|
+
};
|
|
2875
|
+
}
|
|
2876
|
+
function validateCompetitionScope(scopeLevel) {
|
|
2877
|
+
return scopeLevel >= COMPETITION_SCOPE_LEVEL;
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
// src/firmware.ts
|
|
2881
|
+
var FIRMWARE_MANIFEST_PATH = "/.well-known/rcan-firmware-manifest.json";
|
|
2882
|
+
function manifestToWire(m) {
|
|
2883
|
+
const wire = {
|
|
2884
|
+
rrn: m.rrn,
|
|
2885
|
+
firmware_version: m.firmwareVersion,
|
|
2886
|
+
build_hash: m.buildHash,
|
|
2887
|
+
components: m.components,
|
|
2888
|
+
signed_at: m.signedAt
|
|
2889
|
+
};
|
|
2890
|
+
if (m.signature) wire.signature = m.signature;
|
|
2891
|
+
return wire;
|
|
2892
|
+
}
|
|
2893
|
+
function manifestFromWire(w) {
|
|
2894
|
+
return {
|
|
2895
|
+
rrn: w.rrn,
|
|
2896
|
+
firmwareVersion: w.firmware_version,
|
|
2897
|
+
buildHash: w.build_hash,
|
|
2898
|
+
components: w.components ?? [],
|
|
2899
|
+
signedAt: w.signed_at ?? "",
|
|
2900
|
+
signature: w.signature
|
|
2901
|
+
};
|
|
2902
|
+
}
|
|
2903
|
+
function canonicalManifestJson(m) {
|
|
2904
|
+
const obj = {
|
|
2905
|
+
build_hash: m.buildHash,
|
|
2906
|
+
components: m.components.map((c) => ({
|
|
2907
|
+
hash: c.hash,
|
|
2908
|
+
name: c.name,
|
|
2909
|
+
version: c.version
|
|
2910
|
+
})),
|
|
2911
|
+
firmware_version: m.firmwareVersion,
|
|
2912
|
+
rrn: m.rrn,
|
|
2913
|
+
signed_at: m.signedAt
|
|
2914
|
+
};
|
|
2915
|
+
return JSON.stringify(obj);
|
|
2916
|
+
}
|
|
2917
|
+
var FirmwareIntegrityError = class extends Error {
|
|
2918
|
+
constructor(message) {
|
|
2919
|
+
super(message);
|
|
2920
|
+
this.name = "FirmwareIntegrityError";
|
|
2921
|
+
}
|
|
2922
|
+
};
|
|
2923
|
+
function validateManifest(m) {
|
|
2924
|
+
const errors = [];
|
|
2925
|
+
if (!m.rrn) errors.push("rrn is required");
|
|
2926
|
+
if (!m.firmwareVersion) errors.push("firmwareVersion is required");
|
|
2927
|
+
if (!m.buildHash) errors.push("buildHash is required");
|
|
2928
|
+
if (!m.buildHash.startsWith("sha256:")) errors.push("buildHash must start with 'sha256:'");
|
|
2929
|
+
if (!m.signedAt) errors.push("signedAt is required");
|
|
2930
|
+
if (!m.signature) errors.push("signature is required (manifest must be signed)");
|
|
2931
|
+
for (const [i, c] of m.components.entries()) {
|
|
2932
|
+
if (!c.name) errors.push(`components[${i}].name is required`);
|
|
2933
|
+
if (!c.version) errors.push(`components[${i}].version is required`);
|
|
2934
|
+
if (!c.hash.startsWith("sha256:")) errors.push(`components[${i}].hash must start with 'sha256:'`);
|
|
2935
|
+
}
|
|
2936
|
+
return errors;
|
|
2937
|
+
}
|
|
2938
|
+
|
|
2939
|
+
// src/authority.ts
|
|
2940
|
+
function authorityAccessToWire(p) {
|
|
2941
|
+
return {
|
|
2942
|
+
request_id: p.requestId,
|
|
2943
|
+
authority_id: p.authorityId,
|
|
2944
|
+
requested_data: p.requestedData,
|
|
2945
|
+
justification: p.justification,
|
|
2946
|
+
expires_at: p.expiresAt
|
|
2947
|
+
};
|
|
2948
|
+
}
|
|
2949
|
+
function authorityAccessFromWire(w) {
|
|
2950
|
+
return {
|
|
2951
|
+
requestId: w.request_id,
|
|
2952
|
+
authorityId: w.authority_id,
|
|
2953
|
+
requestedData: w.requested_data ?? [],
|
|
2954
|
+
justification: w.justification ?? "",
|
|
2955
|
+
expiresAt: w.expires_at ?? 0
|
|
2956
|
+
};
|
|
2957
|
+
}
|
|
2958
|
+
function validateAuthorityAccess(p) {
|
|
2959
|
+
const errors = [];
|
|
2960
|
+
if (!p.requestId) errors.push("requestId is required");
|
|
2961
|
+
if (!p.authorityId) errors.push("authorityId is required");
|
|
2962
|
+
if (!p.requestedData || p.requestedData.length === 0)
|
|
2963
|
+
errors.push("requestedData must include at least one category");
|
|
2964
|
+
if (!p.justification) errors.push("justification is required");
|
|
2965
|
+
if (!p.expiresAt || p.expiresAt <= 0) errors.push("expiresAt must be a positive Unix timestamp");
|
|
2966
|
+
if (p.expiresAt < Date.now() / 1e3) errors.push("expiresAt is in the past \u2014 request has expired");
|
|
2967
|
+
return errors;
|
|
2968
|
+
}
|
|
2969
|
+
function isAuthorityRequestValid(p) {
|
|
2970
|
+
return Date.now() / 1e3 < p.expiresAt && validateAuthorityAccess(p).length === 0;
|
|
2971
|
+
}
|
|
2972
|
+
var AUTHORITY_ERROR_CODES = {
|
|
2973
|
+
NOT_RECOGNIZED: "AUTHORITY_NOT_RECOGNIZED",
|
|
2974
|
+
REQUEST_EXPIRED: "AUTHORITY_REQUEST_EXPIRED",
|
|
2975
|
+
INVALID_TOKEN: "AUTHORITY_INVALID_TOKEN",
|
|
2976
|
+
RATE_LIMITED: "AUTHORITY_RATE_LIMITED"
|
|
2977
|
+
};
|
|
2978
|
+
|
|
2979
|
+
// src/m2m.ts
|
|
2980
|
+
var RRF_REVOCATION_URL = "https://api.rrf.rcan.dev/v2/revocations";
|
|
2981
|
+
var M2M_TRUSTED_ISSUER = "rrf.rcan.dev";
|
|
2982
|
+
var RRF_REVOCATION_CACHE_TTL_MS = 55e3;
|
|
2983
|
+
var M2MAuthError = class extends Error {
|
|
2984
|
+
constructor(message) {
|
|
2985
|
+
super(message);
|
|
2986
|
+
this.name = "M2MAuthError";
|
|
2987
|
+
}
|
|
2988
|
+
};
|
|
2989
|
+
function decodeJwtPayload2(token) {
|
|
2990
|
+
const parts = token.split(".");
|
|
2991
|
+
if (parts.length < 2) throw new M2MAuthError("Invalid JWT structure");
|
|
2992
|
+
const b64 = (parts[1] ?? "").replace(/-/g, "+").replace(/_/g, "/");
|
|
2993
|
+
const padded = b64 + "=".repeat((4 - b64.length % 4) % 4);
|
|
2994
|
+
try {
|
|
2995
|
+
return JSON.parse(atob(padded));
|
|
2996
|
+
} catch (e) {
|
|
2997
|
+
throw new M2MAuthError(`JWT payload decode failed: ${String(e)}`);
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
3000
|
+
function parseM2mPeerToken(token) {
|
|
3001
|
+
const payload = decodeJwtPayload2(token);
|
|
3002
|
+
const exp = Number(payload["exp"] ?? 0);
|
|
3003
|
+
if (exp > 0 && Date.now() / 1e3 > exp) {
|
|
3004
|
+
throw new M2MAuthError(`M2M_PEER token expired (sub=${String(payload["sub"])})`);
|
|
3005
|
+
}
|
|
3006
|
+
const peerRrn = String(payload["peer_rrn"] ?? "");
|
|
3007
|
+
if (!peerRrn) throw new M2MAuthError("M2M_PEER token missing peer_rrn claim");
|
|
3008
|
+
return {
|
|
3009
|
+
sub: String(payload["sub"] ?? ""),
|
|
3010
|
+
peerRrn,
|
|
3011
|
+
scopes: Array.isArray(payload["rcan_scopes"]) ? payload["rcan_scopes"] : Array.isArray(payload["scopes"]) ? payload["scopes"] : [],
|
|
3012
|
+
exp,
|
|
3013
|
+
iss: String(payload["iss"] ?? "")
|
|
3014
|
+
};
|
|
3015
|
+
}
|
|
3016
|
+
function parseM2mTrustedToken(token) {
|
|
3017
|
+
const payload = decodeJwtPayload2(token);
|
|
3018
|
+
const iss = String(payload["iss"] ?? "");
|
|
3019
|
+
if (iss !== M2M_TRUSTED_ISSUER) {
|
|
3020
|
+
throw new M2MAuthError(
|
|
3021
|
+
`M2M_TRUSTED issuer must be '${M2M_TRUSTED_ISSUER}', got '${iss}'`
|
|
3022
|
+
);
|
|
3023
|
+
}
|
|
3024
|
+
const scopes = Array.isArray(payload["rcan_scopes"]) ? payload["rcan_scopes"] : Array.isArray(payload["scopes"]) ? payload["scopes"] : [];
|
|
3025
|
+
if (!scopes.includes("fleet.trusted")) {
|
|
3026
|
+
throw new M2MAuthError("M2M_TRUSTED token missing required 'fleet.trusted' scope");
|
|
3027
|
+
}
|
|
3028
|
+
const exp = Number(payload["exp"] ?? 0);
|
|
3029
|
+
if (exp > 0 && Date.now() / 1e3 > exp) {
|
|
3030
|
+
throw new M2MAuthError(`M2M_TRUSTED token expired (sub=${String(payload["sub"])})`);
|
|
3031
|
+
}
|
|
3032
|
+
const rrfSig = String(payload["rrf_sig"] ?? "");
|
|
3033
|
+
if (!rrfSig) throw new M2MAuthError("M2M_TRUSTED token missing rrf_sig claim");
|
|
3034
|
+
const fleetRrns = Array.isArray(payload["fleet_rrns"]) ? payload["fleet_rrns"] : [];
|
|
3035
|
+
return {
|
|
3036
|
+
sub: String(payload["sub"] ?? ""),
|
|
3037
|
+
fleetRrns,
|
|
3038
|
+
scopes,
|
|
3039
|
+
exp,
|
|
3040
|
+
iss,
|
|
3041
|
+
rrfSig
|
|
3042
|
+
};
|
|
3043
|
+
}
|
|
3044
|
+
function verifyM2mTrustedTokenClaims(token, targetRrn) {
|
|
3045
|
+
const claims = parseM2mTrustedToken(token);
|
|
3046
|
+
if (!claims.fleetRrns.includes(targetRrn)) {
|
|
3047
|
+
throw new M2MAuthError(
|
|
3048
|
+
`M2M_TRUSTED token does not authorize commanding '${targetRrn}'. Authorized fleet: [${claims.fleetRrns.join(", ")}]`
|
|
3049
|
+
);
|
|
3050
|
+
}
|
|
3051
|
+
return claims;
|
|
3052
|
+
}
|
|
3053
|
+
var _revocationCache = null;
|
|
3054
|
+
async function fetchRRFRevocations(url = RRF_REVOCATION_URL) {
|
|
3055
|
+
const now = Date.now();
|
|
3056
|
+
if (_revocationCache && now - _revocationCache.fetchedAt < RRF_REVOCATION_CACHE_TTL_MS) {
|
|
3057
|
+
return _revocationCache;
|
|
3058
|
+
}
|
|
3059
|
+
try {
|
|
3060
|
+
const resp = await fetch(url, { signal: AbortSignal.timeout?.(5e3) });
|
|
3061
|
+
const data = await resp.json();
|
|
3062
|
+
_revocationCache = {
|
|
3063
|
+
revokedOrchestrators: new Set(data.revoked_orchestrators ?? []),
|
|
3064
|
+
revokedJtis: new Set(data.revoked_jtis ?? []),
|
|
3065
|
+
fetchedAt: now
|
|
3066
|
+
};
|
|
3067
|
+
} catch {
|
|
3068
|
+
if (_revocationCache) return _revocationCache;
|
|
3069
|
+
_revocationCache = { revokedOrchestrators: /* @__PURE__ */ new Set(), revokedJtis: /* @__PURE__ */ new Set(), fetchedAt: now };
|
|
3070
|
+
}
|
|
3071
|
+
return _revocationCache;
|
|
3072
|
+
}
|
|
3073
|
+
async function isM2mTrustedRevoked(claims, jti) {
|
|
3074
|
+
const cache = await fetchRRFRevocations();
|
|
3075
|
+
if (cache.revokedOrchestrators.has(claims.sub)) return true;
|
|
3076
|
+
if (jti && cache.revokedJtis.has(jti)) return true;
|
|
3077
|
+
return false;
|
|
3078
|
+
}
|
|
3079
|
+
async function verifyM2mTrustedToken(token, targetRrn, options) {
|
|
3080
|
+
const claims = verifyM2mTrustedTokenClaims(token, targetRrn);
|
|
3081
|
+
if (!options?.skipRevocationCheck) {
|
|
3082
|
+
const revoked = await isM2mTrustedRevoked(claims);
|
|
3083
|
+
if (revoked) {
|
|
3084
|
+
throw new M2MAuthError(
|
|
3085
|
+
`M2M_TRUSTED orchestrator '${claims.sub}' is on the RRF revocation list`
|
|
3086
|
+
);
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
return claims;
|
|
3090
|
+
}
|
|
3091
|
+
|
|
3092
|
+
// src/pqSigning.ts
|
|
3093
|
+
function toBase64url(bytes) {
|
|
3094
|
+
let binary = "";
|
|
3095
|
+
for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
|
|
3096
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
3097
|
+
}
|
|
3098
|
+
function fromBase64url(b64) {
|
|
3099
|
+
const padded = b64.replace(/-/g, "+").replace(/_/g, "/");
|
|
3100
|
+
const binary = atob(padded);
|
|
3101
|
+
const bytes = new Uint8Array(binary.length);
|
|
3102
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
3103
|
+
return bytes;
|
|
3104
|
+
}
|
|
3105
|
+
async function sha256hex(data) {
|
|
3106
|
+
const g = typeof globalThis !== "undefined" ? globalThis : {};
|
|
3107
|
+
const webcrypto = g.crypto;
|
|
3108
|
+
const subtle = webcrypto?.subtle;
|
|
3109
|
+
if (subtle) {
|
|
3110
|
+
const buf = await subtle.digest("SHA-256", data);
|
|
3111
|
+
return Array.from(new Uint8Array(buf)).map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, 8);
|
|
3112
|
+
}
|
|
3113
|
+
const nodeCrypto = await import("crypto").catch(() => null);
|
|
3114
|
+
if (nodeCrypto) {
|
|
3115
|
+
return nodeCrypto.createHash("sha256").update(data).digest("hex").slice(0, 8);
|
|
3116
|
+
}
|
|
3117
|
+
throw new Error("No SHA-256 implementation available");
|
|
3118
|
+
}
|
|
3119
|
+
var _mlDsaModule;
|
|
3120
|
+
async function requireNoblePostQuantum() {
|
|
3121
|
+
if (_mlDsaModule) return _mlDsaModule;
|
|
3122
|
+
if (typeof __require !== "undefined") {
|
|
3123
|
+
try {
|
|
3124
|
+
_mlDsaModule = __require("@noble/post-quantum/ml-dsa.js");
|
|
3125
|
+
return _mlDsaModule;
|
|
3126
|
+
} catch {
|
|
3127
|
+
}
|
|
3128
|
+
}
|
|
3129
|
+
try {
|
|
3130
|
+
_mlDsaModule = await import("@noble/post-quantum/ml-dsa.js");
|
|
3131
|
+
return _mlDsaModule;
|
|
3132
|
+
} catch {
|
|
3133
|
+
throw new Error(
|
|
3134
|
+
"ML-DSA signing requires @noble/post-quantum. Install with: npm install @noble/post-quantum"
|
|
3135
|
+
);
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
var MLDSAKeyPair = class _MLDSAKeyPair {
|
|
3139
|
+
keyId;
|
|
3140
|
+
publicKey;
|
|
3141
|
+
secretKey;
|
|
3142
|
+
constructor(data) {
|
|
3143
|
+
this.keyId = data.keyId;
|
|
3144
|
+
this.publicKey = data.publicKey;
|
|
3145
|
+
this.secretKey = data.secretKey;
|
|
3146
|
+
}
|
|
3147
|
+
/** Generate a new ML-DSA-65 key pair. */
|
|
3148
|
+
static async generate() {
|
|
3149
|
+
const { ml_dsa65 } = await requireNoblePostQuantum();
|
|
3150
|
+
const kp = ml_dsa65.keygen();
|
|
3151
|
+
const keyId = await sha256hex(kp.publicKey);
|
|
3152
|
+
return new _MLDSAKeyPair({
|
|
3153
|
+
publicKey: kp.publicKey,
|
|
3154
|
+
secretKey: kp.secretKey,
|
|
3155
|
+
keyId
|
|
3156
|
+
});
|
|
3157
|
+
}
|
|
3158
|
+
/** Build a verify-only key pair from raw public key bytes. */
|
|
3159
|
+
static async fromPublicKey(publicKey) {
|
|
3160
|
+
const keyId = await sha256hex(publicKey);
|
|
3161
|
+
return new _MLDSAKeyPair({ publicKey, keyId });
|
|
3162
|
+
}
|
|
3163
|
+
/** Build a full key pair from saved bytes (public + secret). */
|
|
3164
|
+
static async fromKeyMaterial(publicKey, secretKey) {
|
|
3165
|
+
const keyId = await sha256hex(publicKey);
|
|
3166
|
+
return new _MLDSAKeyPair({ publicKey, secretKey, keyId });
|
|
3167
|
+
}
|
|
3168
|
+
get hasPrivateKey() {
|
|
3169
|
+
return this.secretKey !== void 0;
|
|
3170
|
+
}
|
|
3171
|
+
/** Sign raw bytes; returns ML-DSA-65 signature (3309 bytes). */
|
|
3172
|
+
async signBytes(data) {
|
|
3173
|
+
if (!this.secretKey) {
|
|
3174
|
+
throw new Error("Cannot sign: MLDSAKeyPair has no private key (verify-only)");
|
|
3175
|
+
}
|
|
3176
|
+
const { ml_dsa65 } = await requireNoblePostQuantum();
|
|
3177
|
+
return ml_dsa65.sign(data, this.secretKey);
|
|
3178
|
+
}
|
|
3179
|
+
/**
|
|
3180
|
+
* Verify an ML-DSA-65 signature.
|
|
3181
|
+
* @returns true if valid
|
|
3182
|
+
* @throws {Error} on invalid signature
|
|
3183
|
+
*/
|
|
3184
|
+
async verifyBytes(data, signature) {
|
|
3185
|
+
const { ml_dsa65 } = await requireNoblePostQuantum();
|
|
3186
|
+
const ok = ml_dsa65.verify(signature, data, this.publicKey);
|
|
3187
|
+
if (!ok) throw new Error("ML-DSA signature verification failed");
|
|
3188
|
+
}
|
|
3189
|
+
toString() {
|
|
3190
|
+
const mode = this.hasPrivateKey ? "private+public" : "public-only";
|
|
3191
|
+
return `MLDSAKeyPair(keyId=${this.keyId}, alg=ML-DSA-65, ${mode})`;
|
|
3192
|
+
}
|
|
3193
|
+
};
|
|
3194
|
+
function canonicalMessageBytes(msg) {
|
|
3195
|
+
const m = msg;
|
|
3196
|
+
const payload = {
|
|
3197
|
+
rcan: msg.rcan,
|
|
3198
|
+
msg_id: m["msgId"] ?? m["msg_id"] ?? "",
|
|
3199
|
+
timestamp: msg.timestamp,
|
|
3200
|
+
cmd: msg.cmd,
|
|
3201
|
+
target: msg.target,
|
|
3202
|
+
params: msg.params
|
|
3203
|
+
};
|
|
3204
|
+
const sorted = JSON.stringify(
|
|
3205
|
+
Object.fromEntries(Object.entries(payload).sort()),
|
|
3206
|
+
null,
|
|
3207
|
+
void 0
|
|
3208
|
+
);
|
|
3209
|
+
return new TextEncoder().encode(sorted);
|
|
3210
|
+
}
|
|
3211
|
+
async function addPQSignature(msg, keypair) {
|
|
3212
|
+
const payload = canonicalMessageBytes(msg);
|
|
3213
|
+
const rawSig = await keypair.signBytes(payload);
|
|
3214
|
+
const block = {
|
|
3215
|
+
alg: "ml-dsa-65",
|
|
3216
|
+
kid: keypair.keyId,
|
|
3217
|
+
sig: toBase64url(rawSig)
|
|
3218
|
+
};
|
|
3219
|
+
msg["pqSig"] = block;
|
|
3220
|
+
return msg;
|
|
3221
|
+
}
|
|
3222
|
+
async function verifyPQSignature(msg, trustedKeys, requirePQ = false) {
|
|
3223
|
+
const pqSig = msg["pqSig"];
|
|
3224
|
+
if (!pqSig) {
|
|
3225
|
+
if (requirePQ) {
|
|
3226
|
+
throw new Error("ML-DSA signature (pqSig) required but missing from message");
|
|
3227
|
+
}
|
|
3228
|
+
return;
|
|
3229
|
+
}
|
|
3230
|
+
if (pqSig.alg !== "ml-dsa-65") {
|
|
3231
|
+
throw new Error(`Unsupported PQ signature algorithm: ${pqSig.alg}`);
|
|
3232
|
+
}
|
|
3233
|
+
const matched = trustedKeys.find((k) => k.keyId === pqSig.kid);
|
|
3234
|
+
if (!matched) {
|
|
3235
|
+
throw new Error(
|
|
3236
|
+
`No trusted ML-DSA key with kid=${pqSig.kid}. Known kids: [${trustedKeys.map((k) => k.keyId).join(", ")}]`
|
|
3237
|
+
);
|
|
3238
|
+
}
|
|
3239
|
+
let rawSig;
|
|
3240
|
+
try {
|
|
3241
|
+
rawSig = fromBase64url(pqSig.sig);
|
|
3242
|
+
} catch (e) {
|
|
3243
|
+
throw new Error(`Invalid base64url ML-DSA signature: ${e}`);
|
|
3244
|
+
}
|
|
3245
|
+
const payload = canonicalMessageBytes(msg);
|
|
3246
|
+
await matched.verifyBytes(payload, rawSig);
|
|
3247
|
+
}
|
|
3248
|
+
|
|
2732
3249
|
// src/index.ts
|
|
2733
3250
|
var VERSION = "0.6.0";
|
|
2734
3251
|
var RCAN_VERSION = "1.6";
|
|
2735
3252
|
export {
|
|
3253
|
+
AUTHORITY_ERROR_CODES,
|
|
2736
3254
|
AuditChain,
|
|
2737
3255
|
AuditError,
|
|
3256
|
+
COMPETITION_SCOPE_LEVEL,
|
|
2738
3257
|
CONTRIBUTE_SCOPE_LEVEL,
|
|
2739
3258
|
ClockDriftError,
|
|
2740
3259
|
CommitmentRecord,
|
|
2741
3260
|
ConfidenceGate,
|
|
2742
3261
|
DEFAULT_LOA_POLICY,
|
|
2743
3262
|
DataCategory,
|
|
3263
|
+
FIRMWARE_MANIFEST_PATH,
|
|
2744
3264
|
FaultCode,
|
|
2745
3265
|
FederationSyncType,
|
|
3266
|
+
FirmwareIntegrityError,
|
|
2746
3267
|
GateError,
|
|
2747
3268
|
HiTLGate,
|
|
2748
3269
|
KeyStore,
|
|
2749
3270
|
LevelOfAssurance,
|
|
3271
|
+
M2MAuthError,
|
|
3272
|
+
M2M_TRUSTED_ISSUER,
|
|
3273
|
+
MLDSAKeyPair,
|
|
2750
3274
|
MediaEncoding,
|
|
2751
3275
|
MessageType,
|
|
2752
3276
|
NodeClient,
|
|
@@ -2772,13 +3296,18 @@ export {
|
|
|
2772
3296
|
RCANValidationError,
|
|
2773
3297
|
RCANVersionIncompatibleError,
|
|
2774
3298
|
RCAN_VERSION,
|
|
3299
|
+
ROLE_JWT_LEVEL,
|
|
3300
|
+
RRF_REVOCATION_CACHE_TTL_MS,
|
|
3301
|
+
RRF_REVOCATION_URL,
|
|
2775
3302
|
RegistryClient,
|
|
2776
3303
|
RegistryTier,
|
|
2777
3304
|
ReplayCache,
|
|
2778
3305
|
RevocationCache,
|
|
2779
3306
|
RobotURI,
|
|
2780
3307
|
RobotURIError,
|
|
3308
|
+
Role,
|
|
2781
3309
|
SAFETY_MESSAGE_TYPE,
|
|
3310
|
+
SCOPE_MIN_ROLE,
|
|
2782
3311
|
SDK_VERSION,
|
|
2783
3312
|
SPEC_VERSION,
|
|
2784
3313
|
TransportEncoding,
|
|
@@ -2788,7 +3317,11 @@ export {
|
|
|
2788
3317
|
addDelegationHop,
|
|
2789
3318
|
addMediaInline,
|
|
2790
3319
|
addMediaRef,
|
|
3320
|
+
addPQSignature,
|
|
2791
3321
|
assertClockSynced,
|
|
3322
|
+
authorityAccessFromWire,
|
|
3323
|
+
authorityAccessToWire,
|
|
3324
|
+
canonicalManifestJson,
|
|
2792
3325
|
checkClockSync,
|
|
2793
3326
|
checkRevocation,
|
|
2794
3327
|
decodeBleFrames,
|
|
@@ -2797,11 +3330,18 @@ export {
|
|
|
2797
3330
|
encodeBleFrames,
|
|
2798
3331
|
encodeCompact,
|
|
2799
3332
|
encodeMinimal,
|
|
3333
|
+
extractIdentityFromJwt,
|
|
2800
3334
|
extractLoaFromJwt,
|
|
3335
|
+
extractRoleFromJwt,
|
|
2801
3336
|
fetchCanonicalSchema,
|
|
3337
|
+
fetchRRFRevocations,
|
|
3338
|
+
isAuthorityRequestValid,
|
|
3339
|
+
isM2mTrustedRevoked,
|
|
2802
3340
|
isPreemptedBy,
|
|
2803
3341
|
isSafetyMessage,
|
|
2804
3342
|
makeCloudRelayMessage,
|
|
3343
|
+
makeCompetitionEnter,
|
|
3344
|
+
makeCompetitionScore,
|
|
2805
3345
|
makeConfigUpdate,
|
|
2806
3346
|
makeConsentDeny,
|
|
2807
3347
|
makeConsentGrant,
|
|
@@ -2814,8 +3354,10 @@ export {
|
|
|
2814
3354
|
makeFaultReport,
|
|
2815
3355
|
makeFederationSync,
|
|
2816
3356
|
makeKeyRotationMessage,
|
|
3357
|
+
makePersonalResearchResult,
|
|
2817
3358
|
makeResumeMessage,
|
|
2818
3359
|
makeRevocationBroadcast,
|
|
3360
|
+
makeSeasonStanding,
|
|
2819
3361
|
makeStopMessage,
|
|
2820
3362
|
makeStreamChunk,
|
|
2821
3363
|
makeTrainingConsentDeny,
|
|
@@ -2823,7 +3365,14 @@ export {
|
|
|
2823
3365
|
makeTrainingConsentRequest,
|
|
2824
3366
|
makeTrainingDataMessage,
|
|
2825
3367
|
makeTransparencyMessage,
|
|
3368
|
+
manifestFromWire,
|
|
3369
|
+
manifestToWire,
|
|
3370
|
+
parseM2mPeerToken,
|
|
3371
|
+
parseM2mTrustedToken,
|
|
3372
|
+
roleFromJwtLevel,
|
|
2826
3373
|
selectTransport,
|
|
3374
|
+
validateAuthorityAccess,
|
|
3375
|
+
validateCompetitionScope,
|
|
2827
3376
|
validateConfig,
|
|
2828
3377
|
validateConfigAgainstSchema,
|
|
2829
3378
|
validateConfigUpdate,
|
|
@@ -2832,13 +3381,18 @@ export {
|
|
|
2832
3381
|
validateCrossRegistryCommand,
|
|
2833
3382
|
validateDelegationChain,
|
|
2834
3383
|
validateLoaForScope,
|
|
3384
|
+
validateManifest,
|
|
2835
3385
|
validateMediaChunks,
|
|
2836
3386
|
validateMessage,
|
|
2837
3387
|
validateNodeAgainstSchema,
|
|
2838
3388
|
validateReplay,
|
|
3389
|
+
validateRoleForScope,
|
|
2839
3390
|
validateSafetyMessage,
|
|
2840
3391
|
validateTrainingDataMessage,
|
|
2841
3392
|
validateURI,
|
|
2842
|
-
validateVersionCompat
|
|
3393
|
+
validateVersionCompat,
|
|
3394
|
+
verifyM2mTrustedToken,
|
|
3395
|
+
verifyM2mTrustedTokenClaims,
|
|
3396
|
+
verifyPQSignature
|
|
2843
3397
|
};
|
|
2844
3398
|
//# sourceMappingURL=index.mjs.map
|