@continuonai/rcan-ts 0.6.0 → 1.1.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 +91 -182
- package/dist/browser.d.mts +475 -43
- package/dist/browser.mjs +555 -83
- package/dist/browser.mjs.map +1 -1
- package/dist/index.d.mts +475 -43
- package/dist/index.d.ts +475 -43
- package/dist/index.js +606 -84
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +555 -83
- 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/browser.mjs
CHANGED
|
@@ -99,8 +99,8 @@ var RobotURI = class _RobotURI {
|
|
|
99
99
|
};
|
|
100
100
|
|
|
101
101
|
// src/version.ts
|
|
102
|
-
var SPEC_VERSION = "1.
|
|
103
|
-
var SDK_VERSION = "
|
|
102
|
+
var SPEC_VERSION = "2.1.0";
|
|
103
|
+
var SDK_VERSION = "1.1.0";
|
|
104
104
|
function validateVersionCompat(incomingVersion, localVersion = SPEC_VERSION) {
|
|
105
105
|
const parseParts = (v) => {
|
|
106
106
|
const parts = v.split(".");
|
|
@@ -121,18 +121,18 @@ var MessageType = /* @__PURE__ */ ((MessageType2) => {
|
|
|
121
121
|
MessageType2[MessageType2["HEARTBEAT"] = 4] = "HEARTBEAT";
|
|
122
122
|
MessageType2[MessageType2["CONFIG"] = 5] = "CONFIG";
|
|
123
123
|
MessageType2[MessageType2["SAFETY"] = 6] = "SAFETY";
|
|
124
|
-
MessageType2[MessageType2["
|
|
125
|
-
MessageType2[MessageType2["
|
|
124
|
+
MessageType2[MessageType2["AUTH"] = 7] = "AUTH";
|
|
125
|
+
MessageType2[MessageType2["ERROR"] = 8] = "ERROR";
|
|
126
126
|
MessageType2[MessageType2["DISCOVER"] = 9] = "DISCOVER";
|
|
127
|
-
MessageType2[MessageType2["
|
|
128
|
-
MessageType2[MessageType2["
|
|
129
|
-
MessageType2[MessageType2["
|
|
130
|
-
MessageType2[MessageType2["
|
|
131
|
-
MessageType2[MessageType2["
|
|
132
|
-
MessageType2[MessageType2["
|
|
133
|
-
MessageType2[MessageType2["
|
|
127
|
+
MessageType2[MessageType2["PENDING_AUTH"] = 10] = "PENDING_AUTH";
|
|
128
|
+
MessageType2[MessageType2["INVOKE"] = 11] = "INVOKE";
|
|
129
|
+
MessageType2[MessageType2["INVOKE_RESULT"] = 12] = "INVOKE_RESULT";
|
|
130
|
+
MessageType2[MessageType2["INVOKE_CANCEL"] = 13] = "INVOKE_CANCEL";
|
|
131
|
+
MessageType2[MessageType2["REGISTRY_REGISTER"] = 14] = "REGISTRY_REGISTER";
|
|
132
|
+
MessageType2[MessageType2["REGISTRY_RESOLVE"] = 15] = "REGISTRY_RESOLVE";
|
|
133
|
+
MessageType2[MessageType2["TRANSPARENCY"] = 16] = "TRANSPARENCY";
|
|
134
134
|
MessageType2[MessageType2["COMMAND_ACK"] = 17] = "COMMAND_ACK";
|
|
135
|
-
MessageType2[MessageType2["
|
|
135
|
+
MessageType2[MessageType2["COMMAND_NACK"] = 18] = "COMMAND_NACK";
|
|
136
136
|
MessageType2[MessageType2["ROBOT_REVOCATION"] = 19] = "ROBOT_REVOCATION";
|
|
137
137
|
MessageType2[MessageType2["CONSENT_REQUEST"] = 20] = "CONSENT_REQUEST";
|
|
138
138
|
MessageType2[MessageType2["CONSENT_GRANT"] = 21] = "CONSENT_GRANT";
|
|
@@ -141,7 +141,24 @@ var MessageType = /* @__PURE__ */ ((MessageType2) => {
|
|
|
141
141
|
MessageType2[MessageType2["SUBSCRIBE"] = 24] = "SUBSCRIBE";
|
|
142
142
|
MessageType2[MessageType2["UNSUBSCRIBE"] = 25] = "UNSUBSCRIBE";
|
|
143
143
|
MessageType2[MessageType2["FAULT_REPORT"] = 26] = "FAULT_REPORT";
|
|
144
|
-
MessageType2[MessageType2["
|
|
144
|
+
MessageType2[MessageType2["KEY_ROTATION"] = 27] = "KEY_ROTATION";
|
|
145
|
+
MessageType2[MessageType2["COMMAND_COMMIT"] = 28] = "COMMAND_COMMIT";
|
|
146
|
+
MessageType2[MessageType2["SENSOR_DATA"] = 29] = "SENSOR_DATA";
|
|
147
|
+
MessageType2[MessageType2["TRAINING_CONSENT_REQUEST"] = 30] = "TRAINING_CONSENT_REQUEST";
|
|
148
|
+
MessageType2[MessageType2["TRAINING_CONSENT_GRANT"] = 31] = "TRAINING_CONSENT_GRANT";
|
|
149
|
+
MessageType2[MessageType2["TRAINING_CONSENT_DENY"] = 32] = "TRAINING_CONSENT_DENY";
|
|
150
|
+
MessageType2[MessageType2["CONTRIBUTE_REQUEST"] = 33] = "CONTRIBUTE_REQUEST";
|
|
151
|
+
MessageType2[MessageType2["CONTRIBUTE_RESULT"] = 34] = "CONTRIBUTE_RESULT";
|
|
152
|
+
MessageType2[MessageType2["CONTRIBUTE_CANCEL"] = 35] = "CONTRIBUTE_CANCEL";
|
|
153
|
+
MessageType2[MessageType2["TRAINING_DATA"] = 36] = "TRAINING_DATA";
|
|
154
|
+
MessageType2[MessageType2["COMPETITION_ENTER"] = 37] = "COMPETITION_ENTER";
|
|
155
|
+
MessageType2[MessageType2["COMPETITION_SCORE"] = 38] = "COMPETITION_SCORE";
|
|
156
|
+
MessageType2[MessageType2["SEASON_STANDING"] = 39] = "SEASON_STANDING";
|
|
157
|
+
MessageType2[MessageType2["PERSONAL_RESEARCH_RESULT"] = 40] = "PERSONAL_RESEARCH_RESULT";
|
|
158
|
+
MessageType2[MessageType2["AUTHORITY_ACCESS"] = 41] = "AUTHORITY_ACCESS";
|
|
159
|
+
MessageType2[MessageType2["AUTHORITY_RESPONSE"] = 42] = "AUTHORITY_RESPONSE";
|
|
160
|
+
MessageType2[MessageType2["FIRMWARE_ATTESTATION"] = 43] = "FIRMWARE_ATTESTATION";
|
|
161
|
+
MessageType2[MessageType2["SBOM_UPDATE"] = 44] = "SBOM_UPDATE";
|
|
145
162
|
return MessageType2;
|
|
146
163
|
})(MessageType || {});
|
|
147
164
|
var RCANMessageError = class extends Error {
|
|
@@ -178,6 +195,10 @@ var RCANMessage = class _RCANMessage {
|
|
|
178
195
|
__publicField(this, "transportEncoding");
|
|
179
196
|
/** v1.6: GAP-18 multi-modal media chunks */
|
|
180
197
|
__publicField(this, "mediaChunks");
|
|
198
|
+
/** v2.1: SHA-256 of sender's firmware manifest */
|
|
199
|
+
__publicField(this, "firmwareHash");
|
|
200
|
+
/** v2.1: URI to sender's SBOM attestation endpoint */
|
|
201
|
+
__publicField(this, "attestationRef");
|
|
181
202
|
if (!data.cmd || data.cmd.trim() === "") {
|
|
182
203
|
throw new RCANMessageError("'cmd' is required");
|
|
183
204
|
}
|
|
@@ -205,6 +226,13 @@ var RCANMessage = class _RCANMessage {
|
|
|
205
226
|
this.loa = data.loa;
|
|
206
227
|
this.transportEncoding = data.transportEncoding;
|
|
207
228
|
this.mediaChunks = data.mediaChunks;
|
|
229
|
+
this.firmwareHash = data.firmwareHash;
|
|
230
|
+
this.attestationRef = data.attestationRef;
|
|
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
|
+
}
|
|
208
236
|
if (this.confidence !== void 0) {
|
|
209
237
|
if (this.confidence < 0 || this.confidence > 1) {
|
|
210
238
|
throw new RCANMessageError(
|
|
@@ -246,6 +274,8 @@ var RCANMessage = class _RCANMessage {
|
|
|
246
274
|
if (this.loa !== void 0) obj.loa = this.loa;
|
|
247
275
|
if (this.transportEncoding !== void 0) obj.transportEncoding = this.transportEncoding;
|
|
248
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;
|
|
249
279
|
return obj;
|
|
250
280
|
}
|
|
251
281
|
/** Serialize to JSON string */
|
|
@@ -288,7 +318,9 @@ var RCANMessage = class _RCANMessage {
|
|
|
288
318
|
readOnly: obj.readOnly,
|
|
289
319
|
loa: obj.loa,
|
|
290
320
|
transportEncoding: obj.transportEncoding,
|
|
291
|
-
mediaChunks: obj.mediaChunks
|
|
321
|
+
mediaChunks: obj.mediaChunks,
|
|
322
|
+
firmwareHash: obj.firmwareHash,
|
|
323
|
+
attestationRef: obj.attestationRef
|
|
292
324
|
});
|
|
293
325
|
}
|
|
294
326
|
};
|
|
@@ -1263,6 +1295,7 @@ async function fetchCanonicalSchema(schemaName) {
|
|
|
1263
1295
|
try {
|
|
1264
1296
|
const controller = new AbortController();
|
|
1265
1297
|
const timer = setTimeout(() => controller.abort(), 5e3);
|
|
1298
|
+
timer.unref?.();
|
|
1266
1299
|
const res = await fetch(`${SCHEMA_BASE}/${schemaName}`, { signal: controller.signal });
|
|
1267
1300
|
clearTimeout(timer);
|
|
1268
1301
|
if (!res.ok) return null;
|
|
@@ -1907,7 +1940,7 @@ function makeTrainingConsentDeny(params) {
|
|
|
1907
1940
|
return makeConsentDeny(params);
|
|
1908
1941
|
}
|
|
1909
1942
|
function validateTrainingDataMessage(msg) {
|
|
1910
|
-
if (msg.params.message_type !==
|
|
1943
|
+
if (msg.params.message_type !== 36 /* TRAINING_DATA */) {
|
|
1911
1944
|
return { valid: false, reason: "not a TRAINING_DATA message" };
|
|
1912
1945
|
}
|
|
1913
1946
|
const token = msg.params.consent_token;
|
|
@@ -2047,77 +2080,133 @@ function makeFaultReport(params) {
|
|
|
2047
2080
|
}
|
|
2048
2081
|
|
|
2049
2082
|
// src/identity.ts
|
|
2050
|
-
var
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2083
|
+
var Role = /* @__PURE__ */ ((Role2) => {
|
|
2084
|
+
Role2[Role2["GUEST"] = 1] = "GUEST";
|
|
2085
|
+
Role2[Role2["OPERATOR"] = 2] = "OPERATOR";
|
|
2086
|
+
Role2[Role2["CONTRIBUTOR"] = 3] = "CONTRIBUTOR";
|
|
2087
|
+
Role2[Role2["ADMIN"] = 4] = "ADMIN";
|
|
2088
|
+
Role2[Role2["M2M_PEER"] = 5] = "M2M_PEER";
|
|
2089
|
+
Role2[Role2["CREATOR"] = 6] = "CREATOR";
|
|
2090
|
+
Role2[Role2["M2M_TRUSTED"] = 7] = "M2M_TRUSTED";
|
|
2091
|
+
return Role2;
|
|
2092
|
+
})(Role || {});
|
|
2093
|
+
var LevelOfAssurance = Role;
|
|
2094
|
+
var ROLE_JWT_LEVEL = {
|
|
2095
|
+
[1 /* GUEST */]: 1,
|
|
2096
|
+
[2 /* OPERATOR */]: 2,
|
|
2097
|
+
[3 /* CONTRIBUTOR */]: 2.5,
|
|
2098
|
+
[4 /* ADMIN */]: 3,
|
|
2099
|
+
[5 /* M2M_PEER */]: 4,
|
|
2100
|
+
[6 /* CREATOR */]: 5,
|
|
2101
|
+
[7 /* M2M_TRUSTED */]: 6
|
|
2102
|
+
};
|
|
2103
|
+
var JWT_LEVEL_TO_ROLE = new Map(
|
|
2104
|
+
Object.entries(ROLE_JWT_LEVEL).map(
|
|
2105
|
+
([role, level]) => [level, Number(role)]
|
|
2106
|
+
)
|
|
2107
|
+
);
|
|
2108
|
+
function roleFromJwtLevel(level) {
|
|
2109
|
+
return JWT_LEVEL_TO_ROLE.get(level);
|
|
2110
|
+
}
|
|
2111
|
+
var SCOPE_MIN_ROLE = {
|
|
2112
|
+
"status": 1 /* GUEST */,
|
|
2113
|
+
"discover": 1 /* GUEST */,
|
|
2114
|
+
"chat": 1 /* GUEST */,
|
|
2115
|
+
"observer": 1 /* GUEST */,
|
|
2116
|
+
"contribute": 3 /* CONTRIBUTOR */,
|
|
2117
|
+
"control": 2 /* OPERATOR */,
|
|
2118
|
+
"teleop": 2 /* OPERATOR */,
|
|
2119
|
+
"training": 4 /* ADMIN */,
|
|
2120
|
+
"training_data": 4 /* ADMIN */,
|
|
2121
|
+
"config": 4 /* ADMIN */,
|
|
2122
|
+
"authority": 4 /* ADMIN */,
|
|
2123
|
+
"admin": 6 /* CREATOR */,
|
|
2124
|
+
"safety": 6 /* CREATOR */,
|
|
2125
|
+
"estop": 6 /* CREATOR */,
|
|
2126
|
+
"fleet.trusted": 7 /* M2M_TRUSTED */
|
|
2127
|
+
};
|
|
2056
2128
|
var DEFAULT_LOA_POLICY = {
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2129
|
+
minRoleForDiscover: 1 /* GUEST */,
|
|
2130
|
+
minRoleForStatus: 1 /* GUEST */,
|
|
2131
|
+
minRoleForChat: 1 /* GUEST */,
|
|
2132
|
+
minRoleForControl: 1 /* GUEST */,
|
|
2133
|
+
minRoleForSafety: 1 /* GUEST */
|
|
2062
2134
|
};
|
|
2063
2135
|
var PRODUCTION_LOA_POLICY = {
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2136
|
+
minRoleForDiscover: 1 /* GUEST */,
|
|
2137
|
+
minRoleForStatus: 1 /* GUEST */,
|
|
2138
|
+
minRoleForChat: 1 /* GUEST */,
|
|
2139
|
+
minRoleForControl: 2 /* OPERATOR */,
|
|
2140
|
+
minRoleForSafety: 6 /* CREATOR */
|
|
2069
2141
|
};
|
|
2070
|
-
function
|
|
2142
|
+
function decodeJwtPayload(token) {
|
|
2071
2143
|
try {
|
|
2072
2144
|
const parts = token.split(".");
|
|
2073
|
-
if (parts.length < 2) return
|
|
2145
|
+
if (parts.length < 2) return null;
|
|
2074
2146
|
const payloadB64 = (parts[1] ?? "").replace(/-/g, "+").replace(/_/g, "/");
|
|
2075
2147
|
const padded = payloadB64 + "=".repeat((4 - payloadB64.length % 4) % 4);
|
|
2076
|
-
|
|
2077
|
-
if (typeof atob !== "undefined") {
|
|
2078
|
-
json = atob(padded);
|
|
2079
|
-
} else {
|
|
2080
|
-
json = Buffer.from(padded, "base64").toString("utf-8");
|
|
2081
|
-
}
|
|
2082
|
-
const claims = JSON.parse(json);
|
|
2083
|
-
const loa = claims["loa"];
|
|
2084
|
-
if (typeof loa === "number" && loa >= 1 && loa <= 3) {
|
|
2085
|
-
return loa;
|
|
2086
|
-
}
|
|
2148
|
+
return JSON.parse(atob(padded));
|
|
2087
2149
|
} catch {
|
|
2150
|
+
return null;
|
|
2088
2151
|
}
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
}
|
|
2108
|
-
function
|
|
2109
|
-
const
|
|
2110
|
-
if (
|
|
2111
|
-
return {
|
|
2112
|
-
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2152
|
+
}
|
|
2153
|
+
function extractRoleFromJwt(token) {
|
|
2154
|
+
const payload = decodeJwtPayload(token);
|
|
2155
|
+
if (!payload) return 1 /* GUEST */;
|
|
2156
|
+
const rcanRole = payload["rcan_role"];
|
|
2157
|
+
if (rcanRole !== void 0 && rcanRole !== null) {
|
|
2158
|
+
const role = roleFromJwtLevel(Number(rcanRole));
|
|
2159
|
+
if (role !== void 0) return role;
|
|
2160
|
+
}
|
|
2161
|
+
const loa = payload["loa"];
|
|
2162
|
+
if (loa !== void 0 && loa !== null) {
|
|
2163
|
+
const role = roleFromJwtLevel(Number(loa));
|
|
2164
|
+
if (role !== void 0) return role;
|
|
2165
|
+
}
|
|
2166
|
+
return 1 /* GUEST */;
|
|
2167
|
+
}
|
|
2168
|
+
function extractLoaFromJwt(token) {
|
|
2169
|
+
return extractRoleFromJwt(token);
|
|
2170
|
+
}
|
|
2171
|
+
function extractIdentityFromJwt(token) {
|
|
2172
|
+
const payload = decodeJwtPayload(token);
|
|
2173
|
+
if (!payload) {
|
|
2174
|
+
return { sub: "", role: 1 /* GUEST */, jwtLevel: 1, scopes: [] };
|
|
2175
|
+
}
|
|
2176
|
+
const rcanRole = payload["rcan_role"];
|
|
2177
|
+
const loa = payload["loa"];
|
|
2178
|
+
const rawLevel = rcanRole !== void 0 ? Number(rcanRole) : loa !== void 0 ? Number(loa) : 1;
|
|
2179
|
+
const role = roleFromJwtLevel(rawLevel) ?? 1 /* GUEST */;
|
|
2180
|
+
const scopes = Array.isArray(payload["rcan_scopes"]) ? payload["rcan_scopes"] : Array.isArray(payload["scopes"]) ? payload["scopes"] : [];
|
|
2181
|
+
return {
|
|
2182
|
+
sub: String(payload["sub"] ?? ""),
|
|
2183
|
+
role,
|
|
2184
|
+
jwtLevel: ROLE_JWT_LEVEL[role],
|
|
2185
|
+
registryUrl: payload["registry_url"],
|
|
2186
|
+
scopes,
|
|
2187
|
+
verifiedAt: payload["verified_at"],
|
|
2188
|
+
peerRrn: payload["peer_rrn"],
|
|
2189
|
+
fleetRrns: Array.isArray(payload["fleet_rrns"]) ? payload["fleet_rrns"] : void 0
|
|
2190
|
+
};
|
|
2191
|
+
}
|
|
2192
|
+
function validateRoleForScope(role, scope) {
|
|
2193
|
+
const required = SCOPE_MIN_ROLE[scope.toLowerCase()];
|
|
2194
|
+
if (required === void 0) {
|
|
2195
|
+
if (role >= 2 /* OPERATOR */) return { ok: true, reason: "" };
|
|
2196
|
+
return {
|
|
2197
|
+
ok: false,
|
|
2198
|
+
reason: `Unknown scope '${scope}': applying OPERATOR minimum. Caller has ${Role[role]}.`
|
|
2199
|
+
};
|
|
2115
2200
|
}
|
|
2201
|
+
if (role >= required) return { ok: true, reason: "" };
|
|
2116
2202
|
return {
|
|
2117
|
-
|
|
2118
|
-
reason: `
|
|
2203
|
+
ok: false,
|
|
2204
|
+
reason: `Scope '${scope}' requires ${Role[required]} (JWT level ${ROLE_JWT_LEVEL[required]}), but caller has ${Role[role]} (JWT level ${ROLE_JWT_LEVEL[role]})`
|
|
2119
2205
|
};
|
|
2120
2206
|
}
|
|
2207
|
+
function validateLoaForScope(role, scope) {
|
|
2208
|
+
return validateRoleForScope(role, scope);
|
|
2209
|
+
}
|
|
2121
2210
|
|
|
2122
2211
|
// src/federation.ts
|
|
2123
2212
|
var RegistryTier = /* @__PURE__ */ ((RegistryTier2) => {
|
|
@@ -2243,12 +2332,12 @@ function generateId5() {
|
|
|
2243
2332
|
}
|
|
2244
2333
|
function makeFederationSync(source, target, syncType, payload) {
|
|
2245
2334
|
return new RCANMessage({
|
|
2246
|
-
rcan: "1.
|
|
2247
|
-
rcanVersion: "1.
|
|
2335
|
+
rcan: "2.1.0",
|
|
2336
|
+
rcanVersion: "2.1.0",
|
|
2248
2337
|
cmd: "federation_sync",
|
|
2249
2338
|
target,
|
|
2250
2339
|
params: {
|
|
2251
|
-
msg_type:
|
|
2340
|
+
msg_type: 23 /* FLEET_COMMAND */,
|
|
2252
2341
|
msg_id: generateId5(),
|
|
2253
2342
|
source_registry: source,
|
|
2254
2343
|
target_registry: target,
|
|
@@ -2275,17 +2364,17 @@ async function validateCrossRegistryCommand(msg, localRegistry, trustCache) {
|
|
|
2275
2364
|
reason: `REGISTRY_UNKNOWN: ${sourceRegistry} is not in the local trust cache`
|
|
2276
2365
|
};
|
|
2277
2366
|
}
|
|
2278
|
-
let loa = 1 /*
|
|
2367
|
+
let loa = 1 /* GUEST */;
|
|
2279
2368
|
const registryJwt = msg.params?.["registry_jwt"];
|
|
2280
2369
|
if (registryJwt) {
|
|
2281
2370
|
loa = extractLoaFromJwt(registryJwt);
|
|
2282
2371
|
} else if (typeof msg.loa === "number") {
|
|
2283
2372
|
loa = msg.loa;
|
|
2284
2373
|
}
|
|
2285
|
-
if (loa < 2 /*
|
|
2374
|
+
if (loa < 2 /* OPERATOR */) {
|
|
2286
2375
|
return {
|
|
2287
2376
|
valid: false,
|
|
2288
|
-
reason: `LOA_INSUFFICIENT: cross-registry commands require LoA>=2 (
|
|
2377
|
+
reason: `LOA_INSUFFICIENT: cross-registry commands require LoA>=2 (OPERATOR), got role=${loa}`
|
|
2289
2378
|
};
|
|
2290
2379
|
}
|
|
2291
2380
|
return { valid: true, reason: "cross-registry command accepted" };
|
|
@@ -2374,7 +2463,8 @@ async function sha256Bytes(input) {
|
|
|
2374
2463
|
const encoded = new TextEncoder().encode(input);
|
|
2375
2464
|
const ab = new ArrayBuffer(encoded.byteLength);
|
|
2376
2465
|
new Uint8Array(ab).set(encoded);
|
|
2377
|
-
const
|
|
2466
|
+
const subtle = globalThis.crypto?.subtle ?? (await import("crypto")).webcrypto.subtle;
|
|
2467
|
+
const hashBuffer = await subtle.digest("SHA-256", ab);
|
|
2378
2468
|
return new Uint8Array(hashBuffer);
|
|
2379
2469
|
}
|
|
2380
2470
|
async function encodeMinimal(message) {
|
|
@@ -2525,9 +2615,10 @@ function generateId6() {
|
|
|
2525
2615
|
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("")}`;
|
|
2526
2616
|
}
|
|
2527
2617
|
async function computeSha256Hex(data) {
|
|
2618
|
+
const subtle = globalThis.crypto?.subtle ?? (await import("crypto")).webcrypto.subtle;
|
|
2528
2619
|
const ab = new ArrayBuffer(data.byteLength);
|
|
2529
2620
|
new Uint8Array(ab).set(data);
|
|
2530
|
-
const hashBuffer = await
|
|
2621
|
+
const hashBuffer = await subtle.digest("SHA-256", ab);
|
|
2531
2622
|
const hashArray = new Uint8Array(hashBuffer);
|
|
2532
2623
|
return Array.from(hashArray).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
2533
2624
|
}
|
|
@@ -2620,7 +2711,7 @@ async function makeTrainingDataMessage(media) {
|
|
|
2620
2711
|
cmd: "training_data",
|
|
2621
2712
|
target: "rcan://training/data",
|
|
2622
2713
|
params: {
|
|
2623
|
-
msg_type:
|
|
2714
|
+
msg_type: 36 /* TRAINING_DATA */,
|
|
2624
2715
|
msg_id: generateId6()
|
|
2625
2716
|
},
|
|
2626
2717
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -2653,7 +2744,7 @@ async function makeStreamChunk(streamId, data, mimeType, chunkIndex, isFinal) {
|
|
|
2653
2744
|
cmd: "stream_chunk",
|
|
2654
2745
|
target: "rcan://streaming/chunk",
|
|
2655
2746
|
params: {
|
|
2656
|
-
msg_type:
|
|
2747
|
+
msg_type: 29 /* SENSOR_DATA */,
|
|
2657
2748
|
msg_id: generateId6(),
|
|
2658
2749
|
stream_chunk: streamChunkMeta
|
|
2659
2750
|
},
|
|
@@ -2663,23 +2754,371 @@ async function makeStreamChunk(streamId, data, mimeType, chunkIndex, isFinal) {
|
|
|
2663
2754
|
return msg;
|
|
2664
2755
|
}
|
|
2665
2756
|
|
|
2757
|
+
// src/contribute.ts
|
|
2758
|
+
var CONTRIBUTE_SCOPE_LEVEL = 2.5;
|
|
2759
|
+
var _idCounter = 0;
|
|
2760
|
+
function _generateId() {
|
|
2761
|
+
return `cr-${Date.now()}-${++_idCounter}`;
|
|
2762
|
+
}
|
|
2763
|
+
function makeContributeRequest(params = {}) {
|
|
2764
|
+
return {
|
|
2765
|
+
type: 33 /* CONTRIBUTE_REQUEST */,
|
|
2766
|
+
request_id: params.request_id ?? _generateId(),
|
|
2767
|
+
project_id: params.project_id ?? "",
|
|
2768
|
+
project_name: params.project_name ?? "",
|
|
2769
|
+
work_unit_id: params.work_unit_id ?? "",
|
|
2770
|
+
resource_type: params.resource_type ?? "cpu",
|
|
2771
|
+
estimated_duration_s: params.estimated_duration_s ?? 0,
|
|
2772
|
+
priority: params.priority ?? 0,
|
|
2773
|
+
payload: params.payload ?? {},
|
|
2774
|
+
timestamp: params.timestamp ?? Date.now() / 1e3
|
|
2775
|
+
};
|
|
2776
|
+
}
|
|
2777
|
+
function makeContributeResult(params = {}) {
|
|
2778
|
+
const result = {
|
|
2779
|
+
type: 34 /* CONTRIBUTE_RESULT */,
|
|
2780
|
+
request_id: params.request_id ?? "",
|
|
2781
|
+
work_unit_id: params.work_unit_id ?? "",
|
|
2782
|
+
status: params.status ?? "completed",
|
|
2783
|
+
resource_type: params.resource_type ?? "cpu",
|
|
2784
|
+
duration_s: params.duration_s ?? 0,
|
|
2785
|
+
compute_units: params.compute_units ?? 0,
|
|
2786
|
+
result_payload: params.result_payload ?? {},
|
|
2787
|
+
timestamp: params.timestamp ?? Date.now() / 1e3
|
|
2788
|
+
};
|
|
2789
|
+
if (params.error_message !== void 0) {
|
|
2790
|
+
result.error_message = params.error_message;
|
|
2791
|
+
}
|
|
2792
|
+
return result;
|
|
2793
|
+
}
|
|
2794
|
+
function makeContributeCancel(params = {}) {
|
|
2795
|
+
return {
|
|
2796
|
+
type: 35 /* CONTRIBUTE_CANCEL */,
|
|
2797
|
+
request_id: params.request_id ?? "",
|
|
2798
|
+
work_unit_id: params.work_unit_id ?? "",
|
|
2799
|
+
reason: params.reason ?? "",
|
|
2800
|
+
timestamp: params.timestamp ?? Date.now() / 1e3
|
|
2801
|
+
};
|
|
2802
|
+
}
|
|
2803
|
+
function validateContributeScope(scopeLevel, action = "request") {
|
|
2804
|
+
if (action === "request" || action === "result") {
|
|
2805
|
+
return scopeLevel >= CONTRIBUTE_SCOPE_LEVEL;
|
|
2806
|
+
}
|
|
2807
|
+
if (action === "cancel") {
|
|
2808
|
+
return scopeLevel >= 2;
|
|
2809
|
+
}
|
|
2810
|
+
return false;
|
|
2811
|
+
}
|
|
2812
|
+
function isPreemptedBy(scopeLevel) {
|
|
2813
|
+
return scopeLevel >= 3;
|
|
2814
|
+
}
|
|
2815
|
+
|
|
2816
|
+
// src/competition.ts
|
|
2817
|
+
var COMPETITION_SCOPE_LEVEL = 2;
|
|
2818
|
+
var _idCounter2 = 0;
|
|
2819
|
+
function _generateRunId() {
|
|
2820
|
+
return `run-${Date.now()}-${++_idCounter2}`;
|
|
2821
|
+
}
|
|
2822
|
+
function makeCompetitionEnter(params = {}) {
|
|
2823
|
+
return {
|
|
2824
|
+
type: 37 /* COMPETITION_ENTER */,
|
|
2825
|
+
competition_id: params.competition_id ?? "",
|
|
2826
|
+
competition_format: params.competition_format ?? "sprint",
|
|
2827
|
+
hardware_tier: params.hardware_tier ?? "",
|
|
2828
|
+
model_id: params.model_id ?? "",
|
|
2829
|
+
robot_rrn: params.robot_rrn ?? "",
|
|
2830
|
+
entered_at: params.entered_at ?? Date.now() / 1e3
|
|
2831
|
+
};
|
|
2832
|
+
}
|
|
2833
|
+
function makeCompetitionScore(params = {}) {
|
|
2834
|
+
const score = params.score ?? 0;
|
|
2835
|
+
if (score < 0 || score > 1) {
|
|
2836
|
+
throw new Error(`score must be in [0.0, 1.0], got ${score}`);
|
|
2837
|
+
}
|
|
2838
|
+
return {
|
|
2839
|
+
type: 38 /* COMPETITION_SCORE */,
|
|
2840
|
+
competition_id: params.competition_id ?? "",
|
|
2841
|
+
candidate_id: params.candidate_id ?? "",
|
|
2842
|
+
score,
|
|
2843
|
+
hardware_tier: params.hardware_tier ?? "",
|
|
2844
|
+
verified: params.verified ?? false,
|
|
2845
|
+
submitted_at: params.submitted_at ?? Date.now() / 1e3
|
|
2846
|
+
};
|
|
2847
|
+
}
|
|
2848
|
+
function makeSeasonStanding(params = {}) {
|
|
2849
|
+
return {
|
|
2850
|
+
type: 39 /* SEASON_STANDING */,
|
|
2851
|
+
season_id: params.season_id ?? "",
|
|
2852
|
+
class_id: params.class_id ?? "",
|
|
2853
|
+
standings: params.standings ?? [],
|
|
2854
|
+
days_remaining: params.days_remaining ?? 0,
|
|
2855
|
+
broadcast_at: params.broadcast_at ?? Date.now() / 1e3
|
|
2856
|
+
};
|
|
2857
|
+
}
|
|
2858
|
+
function makePersonalResearchResult(params = {}) {
|
|
2859
|
+
const score = params.score ?? 0;
|
|
2860
|
+
if (score < 0 || score > 1) {
|
|
2861
|
+
throw new Error(`score must be in [0.0, 1.0], got ${score}`);
|
|
2862
|
+
}
|
|
2863
|
+
return {
|
|
2864
|
+
type: 40 /* PERSONAL_RESEARCH_RESULT */,
|
|
2865
|
+
run_id: params.run_id ?? _generateRunId(),
|
|
2866
|
+
run_type: params.run_type ?? "personal",
|
|
2867
|
+
candidate_id: params.candidate_id ?? "",
|
|
2868
|
+
score,
|
|
2869
|
+
hardware_tier: params.hardware_tier ?? "",
|
|
2870
|
+
model_id: params.model_id ?? "",
|
|
2871
|
+
owner_uid: params.owner_uid ?? "",
|
|
2872
|
+
metrics: params.metrics ?? {
|
|
2873
|
+
success_rate: 0,
|
|
2874
|
+
p66_rate: 0,
|
|
2875
|
+
token_efficiency: 0,
|
|
2876
|
+
latency_score: 0
|
|
2877
|
+
},
|
|
2878
|
+
submitted_to_community: params.submitted_to_community ?? false,
|
|
2879
|
+
created_at: params.created_at ?? Date.now() / 1e3
|
|
2880
|
+
};
|
|
2881
|
+
}
|
|
2882
|
+
function validateCompetitionScope(scopeLevel) {
|
|
2883
|
+
return scopeLevel >= COMPETITION_SCOPE_LEVEL;
|
|
2884
|
+
}
|
|
2885
|
+
|
|
2886
|
+
// src/firmware.ts
|
|
2887
|
+
var FIRMWARE_MANIFEST_PATH = "/.well-known/rcan-firmware-manifest.json";
|
|
2888
|
+
function manifestToWire(m) {
|
|
2889
|
+
const wire = {
|
|
2890
|
+
rrn: m.rrn,
|
|
2891
|
+
firmware_version: m.firmwareVersion,
|
|
2892
|
+
build_hash: m.buildHash,
|
|
2893
|
+
components: m.components,
|
|
2894
|
+
signed_at: m.signedAt
|
|
2895
|
+
};
|
|
2896
|
+
if (m.signature) wire.signature = m.signature;
|
|
2897
|
+
return wire;
|
|
2898
|
+
}
|
|
2899
|
+
function manifestFromWire(w) {
|
|
2900
|
+
return {
|
|
2901
|
+
rrn: w.rrn,
|
|
2902
|
+
firmwareVersion: w.firmware_version,
|
|
2903
|
+
buildHash: w.build_hash,
|
|
2904
|
+
components: w.components ?? [],
|
|
2905
|
+
signedAt: w.signed_at ?? "",
|
|
2906
|
+
signature: w.signature
|
|
2907
|
+
};
|
|
2908
|
+
}
|
|
2909
|
+
function canonicalManifestJson(m) {
|
|
2910
|
+
const obj = {
|
|
2911
|
+
build_hash: m.buildHash,
|
|
2912
|
+
components: m.components.map((c) => ({
|
|
2913
|
+
hash: c.hash,
|
|
2914
|
+
name: c.name,
|
|
2915
|
+
version: c.version
|
|
2916
|
+
})),
|
|
2917
|
+
firmware_version: m.firmwareVersion,
|
|
2918
|
+
rrn: m.rrn,
|
|
2919
|
+
signed_at: m.signedAt
|
|
2920
|
+
};
|
|
2921
|
+
return JSON.stringify(obj);
|
|
2922
|
+
}
|
|
2923
|
+
var FirmwareIntegrityError = class extends Error {
|
|
2924
|
+
constructor(message) {
|
|
2925
|
+
super(message);
|
|
2926
|
+
this.name = "FirmwareIntegrityError";
|
|
2927
|
+
}
|
|
2928
|
+
};
|
|
2929
|
+
function validateManifest(m) {
|
|
2930
|
+
const errors = [];
|
|
2931
|
+
if (!m.rrn) errors.push("rrn is required");
|
|
2932
|
+
if (!m.firmwareVersion) errors.push("firmwareVersion is required");
|
|
2933
|
+
if (!m.buildHash) errors.push("buildHash is required");
|
|
2934
|
+
if (!m.buildHash.startsWith("sha256:")) errors.push("buildHash must start with 'sha256:'");
|
|
2935
|
+
if (!m.signedAt) errors.push("signedAt is required");
|
|
2936
|
+
if (!m.signature) errors.push("signature is required (manifest must be signed)");
|
|
2937
|
+
for (const [i, c] of m.components.entries()) {
|
|
2938
|
+
if (!c.name) errors.push(`components[${i}].name is required`);
|
|
2939
|
+
if (!c.version) errors.push(`components[${i}].version is required`);
|
|
2940
|
+
if (!c.hash.startsWith("sha256:")) errors.push(`components[${i}].hash must start with 'sha256:'`);
|
|
2941
|
+
}
|
|
2942
|
+
return errors;
|
|
2943
|
+
}
|
|
2944
|
+
|
|
2945
|
+
// src/authority.ts
|
|
2946
|
+
function authorityAccessToWire(p) {
|
|
2947
|
+
return {
|
|
2948
|
+
request_id: p.requestId,
|
|
2949
|
+
authority_id: p.authorityId,
|
|
2950
|
+
requested_data: p.requestedData,
|
|
2951
|
+
justification: p.justification,
|
|
2952
|
+
expires_at: p.expiresAt
|
|
2953
|
+
};
|
|
2954
|
+
}
|
|
2955
|
+
function authorityAccessFromWire(w) {
|
|
2956
|
+
return {
|
|
2957
|
+
requestId: w.request_id,
|
|
2958
|
+
authorityId: w.authority_id,
|
|
2959
|
+
requestedData: w.requested_data ?? [],
|
|
2960
|
+
justification: w.justification ?? "",
|
|
2961
|
+
expiresAt: w.expires_at ?? 0
|
|
2962
|
+
};
|
|
2963
|
+
}
|
|
2964
|
+
function validateAuthorityAccess(p) {
|
|
2965
|
+
const errors = [];
|
|
2966
|
+
if (!p.requestId) errors.push("requestId is required");
|
|
2967
|
+
if (!p.authorityId) errors.push("authorityId is required");
|
|
2968
|
+
if (!p.requestedData || p.requestedData.length === 0)
|
|
2969
|
+
errors.push("requestedData must include at least one category");
|
|
2970
|
+
if (!p.justification) errors.push("justification is required");
|
|
2971
|
+
if (!p.expiresAt || p.expiresAt <= 0) errors.push("expiresAt must be a positive Unix timestamp");
|
|
2972
|
+
if (p.expiresAt < Date.now() / 1e3) errors.push("expiresAt is in the past \u2014 request has expired");
|
|
2973
|
+
return errors;
|
|
2974
|
+
}
|
|
2975
|
+
function isAuthorityRequestValid(p) {
|
|
2976
|
+
return Date.now() / 1e3 < p.expiresAt && validateAuthorityAccess(p).length === 0;
|
|
2977
|
+
}
|
|
2978
|
+
var AUTHORITY_ERROR_CODES = {
|
|
2979
|
+
NOT_RECOGNIZED: "AUTHORITY_NOT_RECOGNIZED",
|
|
2980
|
+
REQUEST_EXPIRED: "AUTHORITY_REQUEST_EXPIRED",
|
|
2981
|
+
INVALID_TOKEN: "AUTHORITY_INVALID_TOKEN",
|
|
2982
|
+
RATE_LIMITED: "AUTHORITY_RATE_LIMITED"
|
|
2983
|
+
};
|
|
2984
|
+
|
|
2985
|
+
// src/m2m.ts
|
|
2986
|
+
var RRF_REVOCATION_URL = "https://api.rrf.rcan.dev/v2/revocations";
|
|
2987
|
+
var M2M_TRUSTED_ISSUER = "rrf.rcan.dev";
|
|
2988
|
+
var RRF_REVOCATION_CACHE_TTL_MS = 55e3;
|
|
2989
|
+
var M2MAuthError = class extends Error {
|
|
2990
|
+
constructor(message) {
|
|
2991
|
+
super(message);
|
|
2992
|
+
this.name = "M2MAuthError";
|
|
2993
|
+
}
|
|
2994
|
+
};
|
|
2995
|
+
function decodeJwtPayload2(token) {
|
|
2996
|
+
const parts = token.split(".");
|
|
2997
|
+
if (parts.length < 2) throw new M2MAuthError("Invalid JWT structure");
|
|
2998
|
+
const b64 = (parts[1] ?? "").replace(/-/g, "+").replace(/_/g, "/");
|
|
2999
|
+
const padded = b64 + "=".repeat((4 - b64.length % 4) % 4);
|
|
3000
|
+
try {
|
|
3001
|
+
return JSON.parse(atob(padded));
|
|
3002
|
+
} catch (e) {
|
|
3003
|
+
throw new M2MAuthError(`JWT payload decode failed: ${String(e)}`);
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
3006
|
+
function parseM2mPeerToken(token) {
|
|
3007
|
+
const payload = decodeJwtPayload2(token);
|
|
3008
|
+
const exp = Number(payload["exp"] ?? 0);
|
|
3009
|
+
if (exp > 0 && Date.now() / 1e3 > exp) {
|
|
3010
|
+
throw new M2MAuthError(`M2M_PEER token expired (sub=${String(payload["sub"])})`);
|
|
3011
|
+
}
|
|
3012
|
+
const peerRrn = String(payload["peer_rrn"] ?? "");
|
|
3013
|
+
if (!peerRrn) throw new M2MAuthError("M2M_PEER token missing peer_rrn claim");
|
|
3014
|
+
return {
|
|
3015
|
+
sub: String(payload["sub"] ?? ""),
|
|
3016
|
+
peerRrn,
|
|
3017
|
+
scopes: Array.isArray(payload["rcan_scopes"]) ? payload["rcan_scopes"] : Array.isArray(payload["scopes"]) ? payload["scopes"] : [],
|
|
3018
|
+
exp,
|
|
3019
|
+
iss: String(payload["iss"] ?? "")
|
|
3020
|
+
};
|
|
3021
|
+
}
|
|
3022
|
+
function parseM2mTrustedToken(token) {
|
|
3023
|
+
const payload = decodeJwtPayload2(token);
|
|
3024
|
+
const iss = String(payload["iss"] ?? "");
|
|
3025
|
+
if (iss !== M2M_TRUSTED_ISSUER) {
|
|
3026
|
+
throw new M2MAuthError(
|
|
3027
|
+
`M2M_TRUSTED issuer must be '${M2M_TRUSTED_ISSUER}', got '${iss}'`
|
|
3028
|
+
);
|
|
3029
|
+
}
|
|
3030
|
+
const scopes = Array.isArray(payload["rcan_scopes"]) ? payload["rcan_scopes"] : Array.isArray(payload["scopes"]) ? payload["scopes"] : [];
|
|
3031
|
+
if (!scopes.includes("fleet.trusted")) {
|
|
3032
|
+
throw new M2MAuthError("M2M_TRUSTED token missing required 'fleet.trusted' scope");
|
|
3033
|
+
}
|
|
3034
|
+
const exp = Number(payload["exp"] ?? 0);
|
|
3035
|
+
if (exp > 0 && Date.now() / 1e3 > exp) {
|
|
3036
|
+
throw new M2MAuthError(`M2M_TRUSTED token expired (sub=${String(payload["sub"])})`);
|
|
3037
|
+
}
|
|
3038
|
+
const rrfSig = String(payload["rrf_sig"] ?? "");
|
|
3039
|
+
if (!rrfSig) throw new M2MAuthError("M2M_TRUSTED token missing rrf_sig claim");
|
|
3040
|
+
const fleetRrns = Array.isArray(payload["fleet_rrns"]) ? payload["fleet_rrns"] : [];
|
|
3041
|
+
return {
|
|
3042
|
+
sub: String(payload["sub"] ?? ""),
|
|
3043
|
+
fleetRrns,
|
|
3044
|
+
scopes,
|
|
3045
|
+
exp,
|
|
3046
|
+
iss,
|
|
3047
|
+
rrfSig
|
|
3048
|
+
};
|
|
3049
|
+
}
|
|
3050
|
+
function verifyM2mTrustedTokenClaims(token, targetRrn) {
|
|
3051
|
+
const claims = parseM2mTrustedToken(token);
|
|
3052
|
+
if (!claims.fleetRrns.includes(targetRrn)) {
|
|
3053
|
+
throw new M2MAuthError(
|
|
3054
|
+
`M2M_TRUSTED token does not authorize commanding '${targetRrn}'. Authorized fleet: [${claims.fleetRrns.join(", ")}]`
|
|
3055
|
+
);
|
|
3056
|
+
}
|
|
3057
|
+
return claims;
|
|
3058
|
+
}
|
|
3059
|
+
var _revocationCache = null;
|
|
3060
|
+
async function fetchRRFRevocations(url = RRF_REVOCATION_URL) {
|
|
3061
|
+
const now = Date.now();
|
|
3062
|
+
if (_revocationCache && now - _revocationCache.fetchedAt < RRF_REVOCATION_CACHE_TTL_MS) {
|
|
3063
|
+
return _revocationCache;
|
|
3064
|
+
}
|
|
3065
|
+
try {
|
|
3066
|
+
const resp = await fetch(url, { signal: AbortSignal.timeout?.(5e3) });
|
|
3067
|
+
const data = await resp.json();
|
|
3068
|
+
_revocationCache = {
|
|
3069
|
+
revokedOrchestrators: new Set(data.revoked_orchestrators ?? []),
|
|
3070
|
+
revokedJtis: new Set(data.revoked_jtis ?? []),
|
|
3071
|
+
fetchedAt: now
|
|
3072
|
+
};
|
|
3073
|
+
} catch {
|
|
3074
|
+
if (_revocationCache) return _revocationCache;
|
|
3075
|
+
_revocationCache = { revokedOrchestrators: /* @__PURE__ */ new Set(), revokedJtis: /* @__PURE__ */ new Set(), fetchedAt: now };
|
|
3076
|
+
}
|
|
3077
|
+
return _revocationCache;
|
|
3078
|
+
}
|
|
3079
|
+
async function isM2mTrustedRevoked(claims, jti) {
|
|
3080
|
+
const cache = await fetchRRFRevocations();
|
|
3081
|
+
if (cache.revokedOrchestrators.has(claims.sub)) return true;
|
|
3082
|
+
if (jti && cache.revokedJtis.has(jti)) return true;
|
|
3083
|
+
return false;
|
|
3084
|
+
}
|
|
3085
|
+
async function verifyM2mTrustedToken(token, targetRrn, options) {
|
|
3086
|
+
const claims = verifyM2mTrustedTokenClaims(token, targetRrn);
|
|
3087
|
+
if (!options?.skipRevocationCheck) {
|
|
3088
|
+
const revoked = await isM2mTrustedRevoked(claims);
|
|
3089
|
+
if (revoked) {
|
|
3090
|
+
throw new M2MAuthError(
|
|
3091
|
+
`M2M_TRUSTED orchestrator '${claims.sub}' is on the RRF revocation list`
|
|
3092
|
+
);
|
|
3093
|
+
}
|
|
3094
|
+
}
|
|
3095
|
+
return claims;
|
|
3096
|
+
}
|
|
3097
|
+
|
|
2666
3098
|
// src/index.ts
|
|
2667
3099
|
var VERSION = "0.6.0";
|
|
2668
3100
|
var RCAN_VERSION = "1.6";
|
|
2669
3101
|
export {
|
|
3102
|
+
AUTHORITY_ERROR_CODES,
|
|
2670
3103
|
AuditChain,
|
|
2671
3104
|
AuditError,
|
|
3105
|
+
COMPETITION_SCOPE_LEVEL,
|
|
3106
|
+
CONTRIBUTE_SCOPE_LEVEL,
|
|
2672
3107
|
ClockDriftError,
|
|
2673
3108
|
CommitmentRecord,
|
|
2674
3109
|
ConfidenceGate,
|
|
2675
3110
|
DEFAULT_LOA_POLICY,
|
|
2676
3111
|
DataCategory,
|
|
3112
|
+
FIRMWARE_MANIFEST_PATH,
|
|
2677
3113
|
FaultCode,
|
|
2678
3114
|
FederationSyncType,
|
|
3115
|
+
FirmwareIntegrityError,
|
|
2679
3116
|
GateError,
|
|
2680
3117
|
HiTLGate,
|
|
2681
3118
|
KeyStore,
|
|
2682
3119
|
LevelOfAssurance,
|
|
3120
|
+
M2MAuthError,
|
|
3121
|
+
M2M_TRUSTED_ISSUER,
|
|
2683
3122
|
MediaEncoding,
|
|
2684
3123
|
MessageType,
|
|
2685
3124
|
NodeClient,
|
|
@@ -2705,13 +3144,18 @@ export {
|
|
|
2705
3144
|
RCANValidationError,
|
|
2706
3145
|
RCANVersionIncompatibleError,
|
|
2707
3146
|
RCAN_VERSION,
|
|
3147
|
+
ROLE_JWT_LEVEL,
|
|
3148
|
+
RRF_REVOCATION_CACHE_TTL_MS,
|
|
3149
|
+
RRF_REVOCATION_URL,
|
|
2708
3150
|
RegistryClient,
|
|
2709
3151
|
RegistryTier,
|
|
2710
3152
|
ReplayCache,
|
|
2711
3153
|
RevocationCache,
|
|
2712
3154
|
RobotURI,
|
|
2713
3155
|
RobotURIError,
|
|
3156
|
+
Role,
|
|
2714
3157
|
SAFETY_MESSAGE_TYPE,
|
|
3158
|
+
SCOPE_MIN_ROLE,
|
|
2715
3159
|
SDK_VERSION,
|
|
2716
3160
|
SPEC_VERSION,
|
|
2717
3161
|
TransportEncoding,
|
|
@@ -2722,6 +3166,9 @@ export {
|
|
|
2722
3166
|
addMediaInline,
|
|
2723
3167
|
addMediaRef,
|
|
2724
3168
|
assertClockSynced,
|
|
3169
|
+
authorityAccessFromWire,
|
|
3170
|
+
authorityAccessToWire,
|
|
3171
|
+
canonicalManifestJson,
|
|
2725
3172
|
checkClockSync,
|
|
2726
3173
|
checkRevocation,
|
|
2727
3174
|
decodeBleFrames,
|
|
@@ -2730,21 +3177,34 @@ export {
|
|
|
2730
3177
|
encodeBleFrames,
|
|
2731
3178
|
encodeCompact,
|
|
2732
3179
|
encodeMinimal,
|
|
3180
|
+
extractIdentityFromJwt,
|
|
2733
3181
|
extractLoaFromJwt,
|
|
3182
|
+
extractRoleFromJwt,
|
|
2734
3183
|
fetchCanonicalSchema,
|
|
3184
|
+
fetchRRFRevocations,
|
|
3185
|
+
isAuthorityRequestValid,
|
|
3186
|
+
isM2mTrustedRevoked,
|
|
3187
|
+
isPreemptedBy,
|
|
2735
3188
|
isSafetyMessage,
|
|
2736
3189
|
makeCloudRelayMessage,
|
|
3190
|
+
makeCompetitionEnter,
|
|
3191
|
+
makeCompetitionScore,
|
|
2737
3192
|
makeConfigUpdate,
|
|
2738
3193
|
makeConsentDeny,
|
|
2739
3194
|
makeConsentGrant,
|
|
2740
3195
|
makeConsentRequest,
|
|
3196
|
+
makeContributeCancel,
|
|
3197
|
+
makeContributeRequest,
|
|
3198
|
+
makeContributeResult,
|
|
2741
3199
|
makeEstopMessage,
|
|
2742
3200
|
makeEstopWithQoS,
|
|
2743
3201
|
makeFaultReport,
|
|
2744
3202
|
makeFederationSync,
|
|
2745
3203
|
makeKeyRotationMessage,
|
|
3204
|
+
makePersonalResearchResult,
|
|
2746
3205
|
makeResumeMessage,
|
|
2747
3206
|
makeRevocationBroadcast,
|
|
3207
|
+
makeSeasonStanding,
|
|
2748
3208
|
makeStopMessage,
|
|
2749
3209
|
makeStreamChunk,
|
|
2750
3210
|
makeTrainingConsentDeny,
|
|
@@ -2752,21 +3212,33 @@ export {
|
|
|
2752
3212
|
makeTrainingConsentRequest,
|
|
2753
3213
|
makeTrainingDataMessage,
|
|
2754
3214
|
makeTransparencyMessage,
|
|
3215
|
+
manifestFromWire,
|
|
3216
|
+
manifestToWire,
|
|
3217
|
+
parseM2mPeerToken,
|
|
3218
|
+
parseM2mTrustedToken,
|
|
3219
|
+
roleFromJwtLevel,
|
|
2755
3220
|
selectTransport,
|
|
3221
|
+
validateAuthorityAccess,
|
|
3222
|
+
validateCompetitionScope,
|
|
2756
3223
|
validateConfig,
|
|
2757
3224
|
validateConfigAgainstSchema,
|
|
2758
3225
|
validateConfigUpdate,
|
|
2759
3226
|
validateConsentMessage,
|
|
3227
|
+
validateContributeScope,
|
|
2760
3228
|
validateCrossRegistryCommand,
|
|
2761
3229
|
validateDelegationChain,
|
|
2762
3230
|
validateLoaForScope,
|
|
3231
|
+
validateManifest,
|
|
2763
3232
|
validateMediaChunks,
|
|
2764
3233
|
validateMessage,
|
|
2765
3234
|
validateNodeAgainstSchema,
|
|
2766
3235
|
validateReplay,
|
|
3236
|
+
validateRoleForScope,
|
|
2767
3237
|
validateSafetyMessage,
|
|
2768
3238
|
validateTrainingDataMessage,
|
|
2769
3239
|
validateURI,
|
|
2770
|
-
validateVersionCompat
|
|
3240
|
+
validateVersionCompat,
|
|
3241
|
+
verifyM2mTrustedToken,
|
|
3242
|
+
verifyM2mTrustedTokenClaims
|
|
2771
3243
|
};
|
|
2772
3244
|
//# sourceMappingURL=browser.mjs.map
|