@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/index.mjs
CHANGED
|
@@ -96,8 +96,8 @@ var RobotURI = class _RobotURI {
|
|
|
96
96
|
};
|
|
97
97
|
|
|
98
98
|
// src/version.ts
|
|
99
|
-
var SPEC_VERSION = "1.
|
|
100
|
-
var SDK_VERSION = "
|
|
99
|
+
var SPEC_VERSION = "2.1.0";
|
|
100
|
+
var SDK_VERSION = "1.1.0";
|
|
101
101
|
function validateVersionCompat(incomingVersion, localVersion = SPEC_VERSION) {
|
|
102
102
|
const parseParts = (v) => {
|
|
103
103
|
const parts = v.split(".");
|
|
@@ -118,18 +118,18 @@ var MessageType = /* @__PURE__ */ ((MessageType2) => {
|
|
|
118
118
|
MessageType2[MessageType2["HEARTBEAT"] = 4] = "HEARTBEAT";
|
|
119
119
|
MessageType2[MessageType2["CONFIG"] = 5] = "CONFIG";
|
|
120
120
|
MessageType2[MessageType2["SAFETY"] = 6] = "SAFETY";
|
|
121
|
-
MessageType2[MessageType2["
|
|
122
|
-
MessageType2[MessageType2["
|
|
121
|
+
MessageType2[MessageType2["AUTH"] = 7] = "AUTH";
|
|
122
|
+
MessageType2[MessageType2["ERROR"] = 8] = "ERROR";
|
|
123
123
|
MessageType2[MessageType2["DISCOVER"] = 9] = "DISCOVER";
|
|
124
|
-
MessageType2[MessageType2["
|
|
125
|
-
MessageType2[MessageType2["
|
|
126
|
-
MessageType2[MessageType2["
|
|
127
|
-
MessageType2[MessageType2["
|
|
128
|
-
MessageType2[MessageType2["
|
|
129
|
-
MessageType2[MessageType2["
|
|
130
|
-
MessageType2[MessageType2["
|
|
124
|
+
MessageType2[MessageType2["PENDING_AUTH"] = 10] = "PENDING_AUTH";
|
|
125
|
+
MessageType2[MessageType2["INVOKE"] = 11] = "INVOKE";
|
|
126
|
+
MessageType2[MessageType2["INVOKE_RESULT"] = 12] = "INVOKE_RESULT";
|
|
127
|
+
MessageType2[MessageType2["INVOKE_CANCEL"] = 13] = "INVOKE_CANCEL";
|
|
128
|
+
MessageType2[MessageType2["REGISTRY_REGISTER"] = 14] = "REGISTRY_REGISTER";
|
|
129
|
+
MessageType2[MessageType2["REGISTRY_RESOLVE"] = 15] = "REGISTRY_RESOLVE";
|
|
130
|
+
MessageType2[MessageType2["TRANSPARENCY"] = 16] = "TRANSPARENCY";
|
|
131
131
|
MessageType2[MessageType2["COMMAND_ACK"] = 17] = "COMMAND_ACK";
|
|
132
|
-
MessageType2[MessageType2["
|
|
132
|
+
MessageType2[MessageType2["COMMAND_NACK"] = 18] = "COMMAND_NACK";
|
|
133
133
|
MessageType2[MessageType2["ROBOT_REVOCATION"] = 19] = "ROBOT_REVOCATION";
|
|
134
134
|
MessageType2[MessageType2["CONSENT_REQUEST"] = 20] = "CONSENT_REQUEST";
|
|
135
135
|
MessageType2[MessageType2["CONSENT_GRANT"] = 21] = "CONSENT_GRANT";
|
|
@@ -138,7 +138,24 @@ var MessageType = /* @__PURE__ */ ((MessageType2) => {
|
|
|
138
138
|
MessageType2[MessageType2["SUBSCRIBE"] = 24] = "SUBSCRIBE";
|
|
139
139
|
MessageType2[MessageType2["UNSUBSCRIBE"] = 25] = "UNSUBSCRIBE";
|
|
140
140
|
MessageType2[MessageType2["FAULT_REPORT"] = 26] = "FAULT_REPORT";
|
|
141
|
-
MessageType2[MessageType2["
|
|
141
|
+
MessageType2[MessageType2["KEY_ROTATION"] = 27] = "KEY_ROTATION";
|
|
142
|
+
MessageType2[MessageType2["COMMAND_COMMIT"] = 28] = "COMMAND_COMMIT";
|
|
143
|
+
MessageType2[MessageType2["SENSOR_DATA"] = 29] = "SENSOR_DATA";
|
|
144
|
+
MessageType2[MessageType2["TRAINING_CONSENT_REQUEST"] = 30] = "TRAINING_CONSENT_REQUEST";
|
|
145
|
+
MessageType2[MessageType2["TRAINING_CONSENT_GRANT"] = 31] = "TRAINING_CONSENT_GRANT";
|
|
146
|
+
MessageType2[MessageType2["TRAINING_CONSENT_DENY"] = 32] = "TRAINING_CONSENT_DENY";
|
|
147
|
+
MessageType2[MessageType2["CONTRIBUTE_REQUEST"] = 33] = "CONTRIBUTE_REQUEST";
|
|
148
|
+
MessageType2[MessageType2["CONTRIBUTE_RESULT"] = 34] = "CONTRIBUTE_RESULT";
|
|
149
|
+
MessageType2[MessageType2["CONTRIBUTE_CANCEL"] = 35] = "CONTRIBUTE_CANCEL";
|
|
150
|
+
MessageType2[MessageType2["TRAINING_DATA"] = 36] = "TRAINING_DATA";
|
|
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";
|
|
142
159
|
return MessageType2;
|
|
143
160
|
})(MessageType || {});
|
|
144
161
|
var RCANMessageError = class extends Error {
|
|
@@ -174,6 +191,10 @@ var RCANMessage = class _RCANMessage {
|
|
|
174
191
|
transportEncoding;
|
|
175
192
|
/** v1.6: GAP-18 multi-modal media chunks */
|
|
176
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;
|
|
177
198
|
constructor(data) {
|
|
178
199
|
if (!data.cmd || data.cmd.trim() === "") {
|
|
179
200
|
throw new RCANMessageError("'cmd' is required");
|
|
@@ -202,6 +223,13 @@ var RCANMessage = class _RCANMessage {
|
|
|
202
223
|
this.loa = data.loa;
|
|
203
224
|
this.transportEncoding = data.transportEncoding;
|
|
204
225
|
this.mediaChunks = data.mediaChunks;
|
|
226
|
+
this.firmwareHash = data.firmwareHash;
|
|
227
|
+
this.attestationRef = data.attestationRef;
|
|
228
|
+
if (this.signature !== void 0 && this.signature["sig"] === "pending") {
|
|
229
|
+
throw new RCANMessageError(
|
|
230
|
+
"signature.sig:'pending' is not valid in RCAN v2.1. Sign the message before sending."
|
|
231
|
+
);
|
|
232
|
+
}
|
|
205
233
|
if (this.confidence !== void 0) {
|
|
206
234
|
if (this.confidence < 0 || this.confidence > 1) {
|
|
207
235
|
throw new RCANMessageError(
|
|
@@ -243,6 +271,8 @@ var RCANMessage = class _RCANMessage {
|
|
|
243
271
|
if (this.loa !== void 0) obj.loa = this.loa;
|
|
244
272
|
if (this.transportEncoding !== void 0) obj.transportEncoding = this.transportEncoding;
|
|
245
273
|
if (this.mediaChunks !== void 0) obj.mediaChunks = this.mediaChunks;
|
|
274
|
+
if (this.firmwareHash !== void 0) obj.firmwareHash = this.firmwareHash;
|
|
275
|
+
if (this.attestationRef !== void 0) obj.attestationRef = this.attestationRef;
|
|
246
276
|
return obj;
|
|
247
277
|
}
|
|
248
278
|
/** Serialize to JSON string */
|
|
@@ -285,7 +315,9 @@ var RCANMessage = class _RCANMessage {
|
|
|
285
315
|
readOnly: obj.readOnly,
|
|
286
316
|
loa: obj.loa,
|
|
287
317
|
transportEncoding: obj.transportEncoding,
|
|
288
|
-
mediaChunks: obj.mediaChunks
|
|
318
|
+
mediaChunks: obj.mediaChunks,
|
|
319
|
+
firmwareHash: obj.firmwareHash,
|
|
320
|
+
attestationRef: obj.attestationRef
|
|
289
321
|
});
|
|
290
322
|
}
|
|
291
323
|
};
|
|
@@ -1258,6 +1290,7 @@ async function fetchCanonicalSchema(schemaName) {
|
|
|
1258
1290
|
try {
|
|
1259
1291
|
const controller = new AbortController();
|
|
1260
1292
|
const timer = setTimeout(() => controller.abort(), 5e3);
|
|
1293
|
+
timer.unref?.();
|
|
1261
1294
|
const res = await fetch(`${SCHEMA_BASE}/${schemaName}`, { signal: controller.signal });
|
|
1262
1295
|
clearTimeout(timer);
|
|
1263
1296
|
if (!res.ok) return null;
|
|
@@ -1898,7 +1931,7 @@ function makeTrainingConsentDeny(params) {
|
|
|
1898
1931
|
return makeConsentDeny(params);
|
|
1899
1932
|
}
|
|
1900
1933
|
function validateTrainingDataMessage(msg) {
|
|
1901
|
-
if (msg.params.message_type !==
|
|
1934
|
+
if (msg.params.message_type !== 36 /* TRAINING_DATA */) {
|
|
1902
1935
|
return { valid: false, reason: "not a TRAINING_DATA message" };
|
|
1903
1936
|
}
|
|
1904
1937
|
const token = msg.params.consent_token;
|
|
@@ -2038,77 +2071,133 @@ function makeFaultReport(params) {
|
|
|
2038
2071
|
}
|
|
2039
2072
|
|
|
2040
2073
|
// src/identity.ts
|
|
2041
|
-
var
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2074
|
+
var Role = /* @__PURE__ */ ((Role2) => {
|
|
2075
|
+
Role2[Role2["GUEST"] = 1] = "GUEST";
|
|
2076
|
+
Role2[Role2["OPERATOR"] = 2] = "OPERATOR";
|
|
2077
|
+
Role2[Role2["CONTRIBUTOR"] = 3] = "CONTRIBUTOR";
|
|
2078
|
+
Role2[Role2["ADMIN"] = 4] = "ADMIN";
|
|
2079
|
+
Role2[Role2["M2M_PEER"] = 5] = "M2M_PEER";
|
|
2080
|
+
Role2[Role2["CREATOR"] = 6] = "CREATOR";
|
|
2081
|
+
Role2[Role2["M2M_TRUSTED"] = 7] = "M2M_TRUSTED";
|
|
2082
|
+
return Role2;
|
|
2083
|
+
})(Role || {});
|
|
2084
|
+
var LevelOfAssurance = Role;
|
|
2085
|
+
var ROLE_JWT_LEVEL = {
|
|
2086
|
+
[1 /* GUEST */]: 1,
|
|
2087
|
+
[2 /* OPERATOR */]: 2,
|
|
2088
|
+
[3 /* CONTRIBUTOR */]: 2.5,
|
|
2089
|
+
[4 /* ADMIN */]: 3,
|
|
2090
|
+
[5 /* M2M_PEER */]: 4,
|
|
2091
|
+
[6 /* CREATOR */]: 5,
|
|
2092
|
+
[7 /* M2M_TRUSTED */]: 6
|
|
2093
|
+
};
|
|
2094
|
+
var JWT_LEVEL_TO_ROLE = new Map(
|
|
2095
|
+
Object.entries(ROLE_JWT_LEVEL).map(
|
|
2096
|
+
([role, level]) => [level, Number(role)]
|
|
2097
|
+
)
|
|
2098
|
+
);
|
|
2099
|
+
function roleFromJwtLevel(level) {
|
|
2100
|
+
return JWT_LEVEL_TO_ROLE.get(level);
|
|
2101
|
+
}
|
|
2102
|
+
var SCOPE_MIN_ROLE = {
|
|
2103
|
+
"status": 1 /* GUEST */,
|
|
2104
|
+
"discover": 1 /* GUEST */,
|
|
2105
|
+
"chat": 1 /* GUEST */,
|
|
2106
|
+
"observer": 1 /* GUEST */,
|
|
2107
|
+
"contribute": 3 /* CONTRIBUTOR */,
|
|
2108
|
+
"control": 2 /* OPERATOR */,
|
|
2109
|
+
"teleop": 2 /* OPERATOR */,
|
|
2110
|
+
"training": 4 /* ADMIN */,
|
|
2111
|
+
"training_data": 4 /* ADMIN */,
|
|
2112
|
+
"config": 4 /* ADMIN */,
|
|
2113
|
+
"authority": 4 /* ADMIN */,
|
|
2114
|
+
"admin": 6 /* CREATOR */,
|
|
2115
|
+
"safety": 6 /* CREATOR */,
|
|
2116
|
+
"estop": 6 /* CREATOR */,
|
|
2117
|
+
"fleet.trusted": 7 /* M2M_TRUSTED */
|
|
2118
|
+
};
|
|
2047
2119
|
var DEFAULT_LOA_POLICY = {
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2120
|
+
minRoleForDiscover: 1 /* GUEST */,
|
|
2121
|
+
minRoleForStatus: 1 /* GUEST */,
|
|
2122
|
+
minRoleForChat: 1 /* GUEST */,
|
|
2123
|
+
minRoleForControl: 1 /* GUEST */,
|
|
2124
|
+
minRoleForSafety: 1 /* GUEST */
|
|
2053
2125
|
};
|
|
2054
2126
|
var PRODUCTION_LOA_POLICY = {
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2127
|
+
minRoleForDiscover: 1 /* GUEST */,
|
|
2128
|
+
minRoleForStatus: 1 /* GUEST */,
|
|
2129
|
+
minRoleForChat: 1 /* GUEST */,
|
|
2130
|
+
minRoleForControl: 2 /* OPERATOR */,
|
|
2131
|
+
minRoleForSafety: 6 /* CREATOR */
|
|
2060
2132
|
};
|
|
2061
|
-
function
|
|
2133
|
+
function decodeJwtPayload(token) {
|
|
2062
2134
|
try {
|
|
2063
2135
|
const parts = token.split(".");
|
|
2064
|
-
if (parts.length < 2) return
|
|
2136
|
+
if (parts.length < 2) return null;
|
|
2065
2137
|
const payloadB64 = (parts[1] ?? "").replace(/-/g, "+").replace(/_/g, "/");
|
|
2066
2138
|
const padded = payloadB64 + "=".repeat((4 - payloadB64.length % 4) % 4);
|
|
2067
|
-
|
|
2068
|
-
if (typeof atob !== "undefined") {
|
|
2069
|
-
json = atob(padded);
|
|
2070
|
-
} else {
|
|
2071
|
-
json = Buffer.from(padded, "base64").toString("utf-8");
|
|
2072
|
-
}
|
|
2073
|
-
const claims = JSON.parse(json);
|
|
2074
|
-
const loa = claims["loa"];
|
|
2075
|
-
if (typeof loa === "number" && loa >= 1 && loa <= 3) {
|
|
2076
|
-
return loa;
|
|
2077
|
-
}
|
|
2139
|
+
return JSON.parse(atob(padded));
|
|
2078
2140
|
} catch {
|
|
2141
|
+
return null;
|
|
2079
2142
|
}
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
}
|
|
2099
|
-
function
|
|
2100
|
-
const
|
|
2101
|
-
if (
|
|
2102
|
-
return {
|
|
2103
|
-
}
|
|
2104
|
-
|
|
2105
|
-
|
|
2143
|
+
}
|
|
2144
|
+
function extractRoleFromJwt(token) {
|
|
2145
|
+
const payload = decodeJwtPayload(token);
|
|
2146
|
+
if (!payload) return 1 /* GUEST */;
|
|
2147
|
+
const rcanRole = payload["rcan_role"];
|
|
2148
|
+
if (rcanRole !== void 0 && rcanRole !== null) {
|
|
2149
|
+
const role = roleFromJwtLevel(Number(rcanRole));
|
|
2150
|
+
if (role !== void 0) return role;
|
|
2151
|
+
}
|
|
2152
|
+
const loa = payload["loa"];
|
|
2153
|
+
if (loa !== void 0 && loa !== null) {
|
|
2154
|
+
const role = roleFromJwtLevel(Number(loa));
|
|
2155
|
+
if (role !== void 0) return role;
|
|
2156
|
+
}
|
|
2157
|
+
return 1 /* GUEST */;
|
|
2158
|
+
}
|
|
2159
|
+
function extractLoaFromJwt(token) {
|
|
2160
|
+
return extractRoleFromJwt(token);
|
|
2161
|
+
}
|
|
2162
|
+
function extractIdentityFromJwt(token) {
|
|
2163
|
+
const payload = decodeJwtPayload(token);
|
|
2164
|
+
if (!payload) {
|
|
2165
|
+
return { sub: "", role: 1 /* GUEST */, jwtLevel: 1, scopes: [] };
|
|
2166
|
+
}
|
|
2167
|
+
const rcanRole = payload["rcan_role"];
|
|
2168
|
+
const loa = payload["loa"];
|
|
2169
|
+
const rawLevel = rcanRole !== void 0 ? Number(rcanRole) : loa !== void 0 ? Number(loa) : 1;
|
|
2170
|
+
const role = roleFromJwtLevel(rawLevel) ?? 1 /* GUEST */;
|
|
2171
|
+
const scopes = Array.isArray(payload["rcan_scopes"]) ? payload["rcan_scopes"] : Array.isArray(payload["scopes"]) ? payload["scopes"] : [];
|
|
2172
|
+
return {
|
|
2173
|
+
sub: String(payload["sub"] ?? ""),
|
|
2174
|
+
role,
|
|
2175
|
+
jwtLevel: ROLE_JWT_LEVEL[role],
|
|
2176
|
+
registryUrl: payload["registry_url"],
|
|
2177
|
+
scopes,
|
|
2178
|
+
verifiedAt: payload["verified_at"],
|
|
2179
|
+
peerRrn: payload["peer_rrn"],
|
|
2180
|
+
fleetRrns: Array.isArray(payload["fleet_rrns"]) ? payload["fleet_rrns"] : void 0
|
|
2181
|
+
};
|
|
2182
|
+
}
|
|
2183
|
+
function validateRoleForScope(role, scope) {
|
|
2184
|
+
const required = SCOPE_MIN_ROLE[scope.toLowerCase()];
|
|
2185
|
+
if (required === void 0) {
|
|
2186
|
+
if (role >= 2 /* OPERATOR */) return { ok: true, reason: "" };
|
|
2187
|
+
return {
|
|
2188
|
+
ok: false,
|
|
2189
|
+
reason: `Unknown scope '${scope}': applying OPERATOR minimum. Caller has ${Role[role]}.`
|
|
2190
|
+
};
|
|
2106
2191
|
}
|
|
2192
|
+
if (role >= required) return { ok: true, reason: "" };
|
|
2107
2193
|
return {
|
|
2108
|
-
|
|
2109
|
-
reason: `
|
|
2194
|
+
ok: false,
|
|
2195
|
+
reason: `Scope '${scope}' requires ${Role[required]} (JWT level ${ROLE_JWT_LEVEL[required]}), but caller has ${Role[role]} (JWT level ${ROLE_JWT_LEVEL[role]})`
|
|
2110
2196
|
};
|
|
2111
2197
|
}
|
|
2198
|
+
function validateLoaForScope(role, scope) {
|
|
2199
|
+
return validateRoleForScope(role, scope);
|
|
2200
|
+
}
|
|
2112
2201
|
|
|
2113
2202
|
// src/federation.ts
|
|
2114
2203
|
var RegistryTier = /* @__PURE__ */ ((RegistryTier2) => {
|
|
@@ -2232,12 +2321,12 @@ function generateId5() {
|
|
|
2232
2321
|
}
|
|
2233
2322
|
function makeFederationSync(source, target, syncType, payload) {
|
|
2234
2323
|
return new RCANMessage({
|
|
2235
|
-
rcan: "1.
|
|
2236
|
-
rcanVersion: "1.
|
|
2324
|
+
rcan: "2.1.0",
|
|
2325
|
+
rcanVersion: "2.1.0",
|
|
2237
2326
|
cmd: "federation_sync",
|
|
2238
2327
|
target,
|
|
2239
2328
|
params: {
|
|
2240
|
-
msg_type:
|
|
2329
|
+
msg_type: 23 /* FLEET_COMMAND */,
|
|
2241
2330
|
msg_id: generateId5(),
|
|
2242
2331
|
source_registry: source,
|
|
2243
2332
|
target_registry: target,
|
|
@@ -2264,17 +2353,17 @@ async function validateCrossRegistryCommand(msg, localRegistry, trustCache) {
|
|
|
2264
2353
|
reason: `REGISTRY_UNKNOWN: ${sourceRegistry} is not in the local trust cache`
|
|
2265
2354
|
};
|
|
2266
2355
|
}
|
|
2267
|
-
let loa = 1 /*
|
|
2356
|
+
let loa = 1 /* GUEST */;
|
|
2268
2357
|
const registryJwt = msg.params?.["registry_jwt"];
|
|
2269
2358
|
if (registryJwt) {
|
|
2270
2359
|
loa = extractLoaFromJwt(registryJwt);
|
|
2271
2360
|
} else if (typeof msg.loa === "number") {
|
|
2272
2361
|
loa = msg.loa;
|
|
2273
2362
|
}
|
|
2274
|
-
if (loa < 2 /*
|
|
2363
|
+
if (loa < 2 /* OPERATOR */) {
|
|
2275
2364
|
return {
|
|
2276
2365
|
valid: false,
|
|
2277
|
-
reason: `LOA_INSUFFICIENT: cross-registry commands require LoA>=2 (
|
|
2366
|
+
reason: `LOA_INSUFFICIENT: cross-registry commands require LoA>=2 (OPERATOR), got role=${loa}`
|
|
2278
2367
|
};
|
|
2279
2368
|
}
|
|
2280
2369
|
return { valid: true, reason: "cross-registry command accepted" };
|
|
@@ -2363,7 +2452,8 @@ async function sha256Bytes(input) {
|
|
|
2363
2452
|
const encoded = new TextEncoder().encode(input);
|
|
2364
2453
|
const ab = new ArrayBuffer(encoded.byteLength);
|
|
2365
2454
|
new Uint8Array(ab).set(encoded);
|
|
2366
|
-
const
|
|
2455
|
+
const subtle = globalThis.crypto?.subtle ?? (await import("crypto")).webcrypto.subtle;
|
|
2456
|
+
const hashBuffer = await subtle.digest("SHA-256", ab);
|
|
2367
2457
|
return new Uint8Array(hashBuffer);
|
|
2368
2458
|
}
|
|
2369
2459
|
async function encodeMinimal(message) {
|
|
@@ -2514,9 +2604,10 @@ function generateId6() {
|
|
|
2514
2604
|
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("")}`;
|
|
2515
2605
|
}
|
|
2516
2606
|
async function computeSha256Hex(data) {
|
|
2607
|
+
const subtle = globalThis.crypto?.subtle ?? (await import("crypto")).webcrypto.subtle;
|
|
2517
2608
|
const ab = new ArrayBuffer(data.byteLength);
|
|
2518
2609
|
new Uint8Array(ab).set(data);
|
|
2519
|
-
const hashBuffer = await
|
|
2610
|
+
const hashBuffer = await subtle.digest("SHA-256", ab);
|
|
2520
2611
|
const hashArray = new Uint8Array(hashBuffer);
|
|
2521
2612
|
return Array.from(hashArray).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
2522
2613
|
}
|
|
@@ -2609,7 +2700,7 @@ async function makeTrainingDataMessage(media) {
|
|
|
2609
2700
|
cmd: "training_data",
|
|
2610
2701
|
target: "rcan://training/data",
|
|
2611
2702
|
params: {
|
|
2612
|
-
msg_type:
|
|
2703
|
+
msg_type: 36 /* TRAINING_DATA */,
|
|
2613
2704
|
msg_id: generateId6()
|
|
2614
2705
|
},
|
|
2615
2706
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -2642,7 +2733,7 @@ async function makeStreamChunk(streamId, data, mimeType, chunkIndex, isFinal) {
|
|
|
2642
2733
|
cmd: "stream_chunk",
|
|
2643
2734
|
target: "rcan://streaming/chunk",
|
|
2644
2735
|
params: {
|
|
2645
|
-
msg_type:
|
|
2736
|
+
msg_type: 29 /* SENSOR_DATA */,
|
|
2646
2737
|
msg_id: generateId6(),
|
|
2647
2738
|
stream_chunk: streamChunkMeta
|
|
2648
2739
|
},
|
|
@@ -2652,23 +2743,371 @@ async function makeStreamChunk(streamId, data, mimeType, chunkIndex, isFinal) {
|
|
|
2652
2743
|
return msg;
|
|
2653
2744
|
}
|
|
2654
2745
|
|
|
2746
|
+
// src/contribute.ts
|
|
2747
|
+
var CONTRIBUTE_SCOPE_LEVEL = 2.5;
|
|
2748
|
+
var _idCounter = 0;
|
|
2749
|
+
function _generateId() {
|
|
2750
|
+
return `cr-${Date.now()}-${++_idCounter}`;
|
|
2751
|
+
}
|
|
2752
|
+
function makeContributeRequest(params = {}) {
|
|
2753
|
+
return {
|
|
2754
|
+
type: 33 /* CONTRIBUTE_REQUEST */,
|
|
2755
|
+
request_id: params.request_id ?? _generateId(),
|
|
2756
|
+
project_id: params.project_id ?? "",
|
|
2757
|
+
project_name: params.project_name ?? "",
|
|
2758
|
+
work_unit_id: params.work_unit_id ?? "",
|
|
2759
|
+
resource_type: params.resource_type ?? "cpu",
|
|
2760
|
+
estimated_duration_s: params.estimated_duration_s ?? 0,
|
|
2761
|
+
priority: params.priority ?? 0,
|
|
2762
|
+
payload: params.payload ?? {},
|
|
2763
|
+
timestamp: params.timestamp ?? Date.now() / 1e3
|
|
2764
|
+
};
|
|
2765
|
+
}
|
|
2766
|
+
function makeContributeResult(params = {}) {
|
|
2767
|
+
const result = {
|
|
2768
|
+
type: 34 /* CONTRIBUTE_RESULT */,
|
|
2769
|
+
request_id: params.request_id ?? "",
|
|
2770
|
+
work_unit_id: params.work_unit_id ?? "",
|
|
2771
|
+
status: params.status ?? "completed",
|
|
2772
|
+
resource_type: params.resource_type ?? "cpu",
|
|
2773
|
+
duration_s: params.duration_s ?? 0,
|
|
2774
|
+
compute_units: params.compute_units ?? 0,
|
|
2775
|
+
result_payload: params.result_payload ?? {},
|
|
2776
|
+
timestamp: params.timestamp ?? Date.now() / 1e3
|
|
2777
|
+
};
|
|
2778
|
+
if (params.error_message !== void 0) {
|
|
2779
|
+
result.error_message = params.error_message;
|
|
2780
|
+
}
|
|
2781
|
+
return result;
|
|
2782
|
+
}
|
|
2783
|
+
function makeContributeCancel(params = {}) {
|
|
2784
|
+
return {
|
|
2785
|
+
type: 35 /* CONTRIBUTE_CANCEL */,
|
|
2786
|
+
request_id: params.request_id ?? "",
|
|
2787
|
+
work_unit_id: params.work_unit_id ?? "",
|
|
2788
|
+
reason: params.reason ?? "",
|
|
2789
|
+
timestamp: params.timestamp ?? Date.now() / 1e3
|
|
2790
|
+
};
|
|
2791
|
+
}
|
|
2792
|
+
function validateContributeScope(scopeLevel, action = "request") {
|
|
2793
|
+
if (action === "request" || action === "result") {
|
|
2794
|
+
return scopeLevel >= CONTRIBUTE_SCOPE_LEVEL;
|
|
2795
|
+
}
|
|
2796
|
+
if (action === "cancel") {
|
|
2797
|
+
return scopeLevel >= 2;
|
|
2798
|
+
}
|
|
2799
|
+
return false;
|
|
2800
|
+
}
|
|
2801
|
+
function isPreemptedBy(scopeLevel) {
|
|
2802
|
+
return scopeLevel >= 3;
|
|
2803
|
+
}
|
|
2804
|
+
|
|
2805
|
+
// src/competition.ts
|
|
2806
|
+
var COMPETITION_SCOPE_LEVEL = 2;
|
|
2807
|
+
var _idCounter2 = 0;
|
|
2808
|
+
function _generateRunId() {
|
|
2809
|
+
return `run-${Date.now()}-${++_idCounter2}`;
|
|
2810
|
+
}
|
|
2811
|
+
function makeCompetitionEnter(params = {}) {
|
|
2812
|
+
return {
|
|
2813
|
+
type: 37 /* COMPETITION_ENTER */,
|
|
2814
|
+
competition_id: params.competition_id ?? "",
|
|
2815
|
+
competition_format: params.competition_format ?? "sprint",
|
|
2816
|
+
hardware_tier: params.hardware_tier ?? "",
|
|
2817
|
+
model_id: params.model_id ?? "",
|
|
2818
|
+
robot_rrn: params.robot_rrn ?? "",
|
|
2819
|
+
entered_at: params.entered_at ?? Date.now() / 1e3
|
|
2820
|
+
};
|
|
2821
|
+
}
|
|
2822
|
+
function makeCompetitionScore(params = {}) {
|
|
2823
|
+
const score = params.score ?? 0;
|
|
2824
|
+
if (score < 0 || score > 1) {
|
|
2825
|
+
throw new Error(`score must be in [0.0, 1.0], got ${score}`);
|
|
2826
|
+
}
|
|
2827
|
+
return {
|
|
2828
|
+
type: 38 /* COMPETITION_SCORE */,
|
|
2829
|
+
competition_id: params.competition_id ?? "",
|
|
2830
|
+
candidate_id: params.candidate_id ?? "",
|
|
2831
|
+
score,
|
|
2832
|
+
hardware_tier: params.hardware_tier ?? "",
|
|
2833
|
+
verified: params.verified ?? false,
|
|
2834
|
+
submitted_at: params.submitted_at ?? Date.now() / 1e3
|
|
2835
|
+
};
|
|
2836
|
+
}
|
|
2837
|
+
function makeSeasonStanding(params = {}) {
|
|
2838
|
+
return {
|
|
2839
|
+
type: 39 /* SEASON_STANDING */,
|
|
2840
|
+
season_id: params.season_id ?? "",
|
|
2841
|
+
class_id: params.class_id ?? "",
|
|
2842
|
+
standings: params.standings ?? [],
|
|
2843
|
+
days_remaining: params.days_remaining ?? 0,
|
|
2844
|
+
broadcast_at: params.broadcast_at ?? Date.now() / 1e3
|
|
2845
|
+
};
|
|
2846
|
+
}
|
|
2847
|
+
function makePersonalResearchResult(params = {}) {
|
|
2848
|
+
const score = params.score ?? 0;
|
|
2849
|
+
if (score < 0 || score > 1) {
|
|
2850
|
+
throw new Error(`score must be in [0.0, 1.0], got ${score}`);
|
|
2851
|
+
}
|
|
2852
|
+
return {
|
|
2853
|
+
type: 40 /* PERSONAL_RESEARCH_RESULT */,
|
|
2854
|
+
run_id: params.run_id ?? _generateRunId(),
|
|
2855
|
+
run_type: params.run_type ?? "personal",
|
|
2856
|
+
candidate_id: params.candidate_id ?? "",
|
|
2857
|
+
score,
|
|
2858
|
+
hardware_tier: params.hardware_tier ?? "",
|
|
2859
|
+
model_id: params.model_id ?? "",
|
|
2860
|
+
owner_uid: params.owner_uid ?? "",
|
|
2861
|
+
metrics: params.metrics ?? {
|
|
2862
|
+
success_rate: 0,
|
|
2863
|
+
p66_rate: 0,
|
|
2864
|
+
token_efficiency: 0,
|
|
2865
|
+
latency_score: 0
|
|
2866
|
+
},
|
|
2867
|
+
submitted_to_community: params.submitted_to_community ?? false,
|
|
2868
|
+
created_at: params.created_at ?? Date.now() / 1e3
|
|
2869
|
+
};
|
|
2870
|
+
}
|
|
2871
|
+
function validateCompetitionScope(scopeLevel) {
|
|
2872
|
+
return scopeLevel >= COMPETITION_SCOPE_LEVEL;
|
|
2873
|
+
}
|
|
2874
|
+
|
|
2875
|
+
// src/firmware.ts
|
|
2876
|
+
var FIRMWARE_MANIFEST_PATH = "/.well-known/rcan-firmware-manifest.json";
|
|
2877
|
+
function manifestToWire(m) {
|
|
2878
|
+
const wire = {
|
|
2879
|
+
rrn: m.rrn,
|
|
2880
|
+
firmware_version: m.firmwareVersion,
|
|
2881
|
+
build_hash: m.buildHash,
|
|
2882
|
+
components: m.components,
|
|
2883
|
+
signed_at: m.signedAt
|
|
2884
|
+
};
|
|
2885
|
+
if (m.signature) wire.signature = m.signature;
|
|
2886
|
+
return wire;
|
|
2887
|
+
}
|
|
2888
|
+
function manifestFromWire(w) {
|
|
2889
|
+
return {
|
|
2890
|
+
rrn: w.rrn,
|
|
2891
|
+
firmwareVersion: w.firmware_version,
|
|
2892
|
+
buildHash: w.build_hash,
|
|
2893
|
+
components: w.components ?? [],
|
|
2894
|
+
signedAt: w.signed_at ?? "",
|
|
2895
|
+
signature: w.signature
|
|
2896
|
+
};
|
|
2897
|
+
}
|
|
2898
|
+
function canonicalManifestJson(m) {
|
|
2899
|
+
const obj = {
|
|
2900
|
+
build_hash: m.buildHash,
|
|
2901
|
+
components: m.components.map((c) => ({
|
|
2902
|
+
hash: c.hash,
|
|
2903
|
+
name: c.name,
|
|
2904
|
+
version: c.version
|
|
2905
|
+
})),
|
|
2906
|
+
firmware_version: m.firmwareVersion,
|
|
2907
|
+
rrn: m.rrn,
|
|
2908
|
+
signed_at: m.signedAt
|
|
2909
|
+
};
|
|
2910
|
+
return JSON.stringify(obj);
|
|
2911
|
+
}
|
|
2912
|
+
var FirmwareIntegrityError = class extends Error {
|
|
2913
|
+
constructor(message) {
|
|
2914
|
+
super(message);
|
|
2915
|
+
this.name = "FirmwareIntegrityError";
|
|
2916
|
+
}
|
|
2917
|
+
};
|
|
2918
|
+
function validateManifest(m) {
|
|
2919
|
+
const errors = [];
|
|
2920
|
+
if (!m.rrn) errors.push("rrn is required");
|
|
2921
|
+
if (!m.firmwareVersion) errors.push("firmwareVersion is required");
|
|
2922
|
+
if (!m.buildHash) errors.push("buildHash is required");
|
|
2923
|
+
if (!m.buildHash.startsWith("sha256:")) errors.push("buildHash must start with 'sha256:'");
|
|
2924
|
+
if (!m.signedAt) errors.push("signedAt is required");
|
|
2925
|
+
if (!m.signature) errors.push("signature is required (manifest must be signed)");
|
|
2926
|
+
for (const [i, c] of m.components.entries()) {
|
|
2927
|
+
if (!c.name) errors.push(`components[${i}].name is required`);
|
|
2928
|
+
if (!c.version) errors.push(`components[${i}].version is required`);
|
|
2929
|
+
if (!c.hash.startsWith("sha256:")) errors.push(`components[${i}].hash must start with 'sha256:'`);
|
|
2930
|
+
}
|
|
2931
|
+
return errors;
|
|
2932
|
+
}
|
|
2933
|
+
|
|
2934
|
+
// src/authority.ts
|
|
2935
|
+
function authorityAccessToWire(p) {
|
|
2936
|
+
return {
|
|
2937
|
+
request_id: p.requestId,
|
|
2938
|
+
authority_id: p.authorityId,
|
|
2939
|
+
requested_data: p.requestedData,
|
|
2940
|
+
justification: p.justification,
|
|
2941
|
+
expires_at: p.expiresAt
|
|
2942
|
+
};
|
|
2943
|
+
}
|
|
2944
|
+
function authorityAccessFromWire(w) {
|
|
2945
|
+
return {
|
|
2946
|
+
requestId: w.request_id,
|
|
2947
|
+
authorityId: w.authority_id,
|
|
2948
|
+
requestedData: w.requested_data ?? [],
|
|
2949
|
+
justification: w.justification ?? "",
|
|
2950
|
+
expiresAt: w.expires_at ?? 0
|
|
2951
|
+
};
|
|
2952
|
+
}
|
|
2953
|
+
function validateAuthorityAccess(p) {
|
|
2954
|
+
const errors = [];
|
|
2955
|
+
if (!p.requestId) errors.push("requestId is required");
|
|
2956
|
+
if (!p.authorityId) errors.push("authorityId is required");
|
|
2957
|
+
if (!p.requestedData || p.requestedData.length === 0)
|
|
2958
|
+
errors.push("requestedData must include at least one category");
|
|
2959
|
+
if (!p.justification) errors.push("justification is required");
|
|
2960
|
+
if (!p.expiresAt || p.expiresAt <= 0) errors.push("expiresAt must be a positive Unix timestamp");
|
|
2961
|
+
if (p.expiresAt < Date.now() / 1e3) errors.push("expiresAt is in the past \u2014 request has expired");
|
|
2962
|
+
return errors;
|
|
2963
|
+
}
|
|
2964
|
+
function isAuthorityRequestValid(p) {
|
|
2965
|
+
return Date.now() / 1e3 < p.expiresAt && validateAuthorityAccess(p).length === 0;
|
|
2966
|
+
}
|
|
2967
|
+
var AUTHORITY_ERROR_CODES = {
|
|
2968
|
+
NOT_RECOGNIZED: "AUTHORITY_NOT_RECOGNIZED",
|
|
2969
|
+
REQUEST_EXPIRED: "AUTHORITY_REQUEST_EXPIRED",
|
|
2970
|
+
INVALID_TOKEN: "AUTHORITY_INVALID_TOKEN",
|
|
2971
|
+
RATE_LIMITED: "AUTHORITY_RATE_LIMITED"
|
|
2972
|
+
};
|
|
2973
|
+
|
|
2974
|
+
// src/m2m.ts
|
|
2975
|
+
var RRF_REVOCATION_URL = "https://api.rrf.rcan.dev/v2/revocations";
|
|
2976
|
+
var M2M_TRUSTED_ISSUER = "rrf.rcan.dev";
|
|
2977
|
+
var RRF_REVOCATION_CACHE_TTL_MS = 55e3;
|
|
2978
|
+
var M2MAuthError = class extends Error {
|
|
2979
|
+
constructor(message) {
|
|
2980
|
+
super(message);
|
|
2981
|
+
this.name = "M2MAuthError";
|
|
2982
|
+
}
|
|
2983
|
+
};
|
|
2984
|
+
function decodeJwtPayload2(token) {
|
|
2985
|
+
const parts = token.split(".");
|
|
2986
|
+
if (parts.length < 2) throw new M2MAuthError("Invalid JWT structure");
|
|
2987
|
+
const b64 = (parts[1] ?? "").replace(/-/g, "+").replace(/_/g, "/");
|
|
2988
|
+
const padded = b64 + "=".repeat((4 - b64.length % 4) % 4);
|
|
2989
|
+
try {
|
|
2990
|
+
return JSON.parse(atob(padded));
|
|
2991
|
+
} catch (e) {
|
|
2992
|
+
throw new M2MAuthError(`JWT payload decode failed: ${String(e)}`);
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
function parseM2mPeerToken(token) {
|
|
2996
|
+
const payload = decodeJwtPayload2(token);
|
|
2997
|
+
const exp = Number(payload["exp"] ?? 0);
|
|
2998
|
+
if (exp > 0 && Date.now() / 1e3 > exp) {
|
|
2999
|
+
throw new M2MAuthError(`M2M_PEER token expired (sub=${String(payload["sub"])})`);
|
|
3000
|
+
}
|
|
3001
|
+
const peerRrn = String(payload["peer_rrn"] ?? "");
|
|
3002
|
+
if (!peerRrn) throw new M2MAuthError("M2M_PEER token missing peer_rrn claim");
|
|
3003
|
+
return {
|
|
3004
|
+
sub: String(payload["sub"] ?? ""),
|
|
3005
|
+
peerRrn,
|
|
3006
|
+
scopes: Array.isArray(payload["rcan_scopes"]) ? payload["rcan_scopes"] : Array.isArray(payload["scopes"]) ? payload["scopes"] : [],
|
|
3007
|
+
exp,
|
|
3008
|
+
iss: String(payload["iss"] ?? "")
|
|
3009
|
+
};
|
|
3010
|
+
}
|
|
3011
|
+
function parseM2mTrustedToken(token) {
|
|
3012
|
+
const payload = decodeJwtPayload2(token);
|
|
3013
|
+
const iss = String(payload["iss"] ?? "");
|
|
3014
|
+
if (iss !== M2M_TRUSTED_ISSUER) {
|
|
3015
|
+
throw new M2MAuthError(
|
|
3016
|
+
`M2M_TRUSTED issuer must be '${M2M_TRUSTED_ISSUER}', got '${iss}'`
|
|
3017
|
+
);
|
|
3018
|
+
}
|
|
3019
|
+
const scopes = Array.isArray(payload["rcan_scopes"]) ? payload["rcan_scopes"] : Array.isArray(payload["scopes"]) ? payload["scopes"] : [];
|
|
3020
|
+
if (!scopes.includes("fleet.trusted")) {
|
|
3021
|
+
throw new M2MAuthError("M2M_TRUSTED token missing required 'fleet.trusted' scope");
|
|
3022
|
+
}
|
|
3023
|
+
const exp = Number(payload["exp"] ?? 0);
|
|
3024
|
+
if (exp > 0 && Date.now() / 1e3 > exp) {
|
|
3025
|
+
throw new M2MAuthError(`M2M_TRUSTED token expired (sub=${String(payload["sub"])})`);
|
|
3026
|
+
}
|
|
3027
|
+
const rrfSig = String(payload["rrf_sig"] ?? "");
|
|
3028
|
+
if (!rrfSig) throw new M2MAuthError("M2M_TRUSTED token missing rrf_sig claim");
|
|
3029
|
+
const fleetRrns = Array.isArray(payload["fleet_rrns"]) ? payload["fleet_rrns"] : [];
|
|
3030
|
+
return {
|
|
3031
|
+
sub: String(payload["sub"] ?? ""),
|
|
3032
|
+
fleetRrns,
|
|
3033
|
+
scopes,
|
|
3034
|
+
exp,
|
|
3035
|
+
iss,
|
|
3036
|
+
rrfSig
|
|
3037
|
+
};
|
|
3038
|
+
}
|
|
3039
|
+
function verifyM2mTrustedTokenClaims(token, targetRrn) {
|
|
3040
|
+
const claims = parseM2mTrustedToken(token);
|
|
3041
|
+
if (!claims.fleetRrns.includes(targetRrn)) {
|
|
3042
|
+
throw new M2MAuthError(
|
|
3043
|
+
`M2M_TRUSTED token does not authorize commanding '${targetRrn}'. Authorized fleet: [${claims.fleetRrns.join(", ")}]`
|
|
3044
|
+
);
|
|
3045
|
+
}
|
|
3046
|
+
return claims;
|
|
3047
|
+
}
|
|
3048
|
+
var _revocationCache = null;
|
|
3049
|
+
async function fetchRRFRevocations(url = RRF_REVOCATION_URL) {
|
|
3050
|
+
const now = Date.now();
|
|
3051
|
+
if (_revocationCache && now - _revocationCache.fetchedAt < RRF_REVOCATION_CACHE_TTL_MS) {
|
|
3052
|
+
return _revocationCache;
|
|
3053
|
+
}
|
|
3054
|
+
try {
|
|
3055
|
+
const resp = await fetch(url, { signal: AbortSignal.timeout?.(5e3) });
|
|
3056
|
+
const data = await resp.json();
|
|
3057
|
+
_revocationCache = {
|
|
3058
|
+
revokedOrchestrators: new Set(data.revoked_orchestrators ?? []),
|
|
3059
|
+
revokedJtis: new Set(data.revoked_jtis ?? []),
|
|
3060
|
+
fetchedAt: now
|
|
3061
|
+
};
|
|
3062
|
+
} catch {
|
|
3063
|
+
if (_revocationCache) return _revocationCache;
|
|
3064
|
+
_revocationCache = { revokedOrchestrators: /* @__PURE__ */ new Set(), revokedJtis: /* @__PURE__ */ new Set(), fetchedAt: now };
|
|
3065
|
+
}
|
|
3066
|
+
return _revocationCache;
|
|
3067
|
+
}
|
|
3068
|
+
async function isM2mTrustedRevoked(claims, jti) {
|
|
3069
|
+
const cache = await fetchRRFRevocations();
|
|
3070
|
+
if (cache.revokedOrchestrators.has(claims.sub)) return true;
|
|
3071
|
+
if (jti && cache.revokedJtis.has(jti)) return true;
|
|
3072
|
+
return false;
|
|
3073
|
+
}
|
|
3074
|
+
async function verifyM2mTrustedToken(token, targetRrn, options) {
|
|
3075
|
+
const claims = verifyM2mTrustedTokenClaims(token, targetRrn);
|
|
3076
|
+
if (!options?.skipRevocationCheck) {
|
|
3077
|
+
const revoked = await isM2mTrustedRevoked(claims);
|
|
3078
|
+
if (revoked) {
|
|
3079
|
+
throw new M2MAuthError(
|
|
3080
|
+
`M2M_TRUSTED orchestrator '${claims.sub}' is on the RRF revocation list`
|
|
3081
|
+
);
|
|
3082
|
+
}
|
|
3083
|
+
}
|
|
3084
|
+
return claims;
|
|
3085
|
+
}
|
|
3086
|
+
|
|
2655
3087
|
// src/index.ts
|
|
2656
3088
|
var VERSION = "0.6.0";
|
|
2657
3089
|
var RCAN_VERSION = "1.6";
|
|
2658
3090
|
export {
|
|
3091
|
+
AUTHORITY_ERROR_CODES,
|
|
2659
3092
|
AuditChain,
|
|
2660
3093
|
AuditError,
|
|
3094
|
+
COMPETITION_SCOPE_LEVEL,
|
|
3095
|
+
CONTRIBUTE_SCOPE_LEVEL,
|
|
2661
3096
|
ClockDriftError,
|
|
2662
3097
|
CommitmentRecord,
|
|
2663
3098
|
ConfidenceGate,
|
|
2664
3099
|
DEFAULT_LOA_POLICY,
|
|
2665
3100
|
DataCategory,
|
|
3101
|
+
FIRMWARE_MANIFEST_PATH,
|
|
2666
3102
|
FaultCode,
|
|
2667
3103
|
FederationSyncType,
|
|
3104
|
+
FirmwareIntegrityError,
|
|
2668
3105
|
GateError,
|
|
2669
3106
|
HiTLGate,
|
|
2670
3107
|
KeyStore,
|
|
2671
3108
|
LevelOfAssurance,
|
|
3109
|
+
M2MAuthError,
|
|
3110
|
+
M2M_TRUSTED_ISSUER,
|
|
2672
3111
|
MediaEncoding,
|
|
2673
3112
|
MessageType,
|
|
2674
3113
|
NodeClient,
|
|
@@ -2694,13 +3133,18 @@ export {
|
|
|
2694
3133
|
RCANValidationError,
|
|
2695
3134
|
RCANVersionIncompatibleError,
|
|
2696
3135
|
RCAN_VERSION,
|
|
3136
|
+
ROLE_JWT_LEVEL,
|
|
3137
|
+
RRF_REVOCATION_CACHE_TTL_MS,
|
|
3138
|
+
RRF_REVOCATION_URL,
|
|
2697
3139
|
RegistryClient,
|
|
2698
3140
|
RegistryTier,
|
|
2699
3141
|
ReplayCache,
|
|
2700
3142
|
RevocationCache,
|
|
2701
3143
|
RobotURI,
|
|
2702
3144
|
RobotURIError,
|
|
3145
|
+
Role,
|
|
2703
3146
|
SAFETY_MESSAGE_TYPE,
|
|
3147
|
+
SCOPE_MIN_ROLE,
|
|
2704
3148
|
SDK_VERSION,
|
|
2705
3149
|
SPEC_VERSION,
|
|
2706
3150
|
TransportEncoding,
|
|
@@ -2711,6 +3155,9 @@ export {
|
|
|
2711
3155
|
addMediaInline,
|
|
2712
3156
|
addMediaRef,
|
|
2713
3157
|
assertClockSynced,
|
|
3158
|
+
authorityAccessFromWire,
|
|
3159
|
+
authorityAccessToWire,
|
|
3160
|
+
canonicalManifestJson,
|
|
2714
3161
|
checkClockSync,
|
|
2715
3162
|
checkRevocation,
|
|
2716
3163
|
decodeBleFrames,
|
|
@@ -2719,21 +3166,34 @@ export {
|
|
|
2719
3166
|
encodeBleFrames,
|
|
2720
3167
|
encodeCompact,
|
|
2721
3168
|
encodeMinimal,
|
|
3169
|
+
extractIdentityFromJwt,
|
|
2722
3170
|
extractLoaFromJwt,
|
|
3171
|
+
extractRoleFromJwt,
|
|
2723
3172
|
fetchCanonicalSchema,
|
|
3173
|
+
fetchRRFRevocations,
|
|
3174
|
+
isAuthorityRequestValid,
|
|
3175
|
+
isM2mTrustedRevoked,
|
|
3176
|
+
isPreemptedBy,
|
|
2724
3177
|
isSafetyMessage,
|
|
2725
3178
|
makeCloudRelayMessage,
|
|
3179
|
+
makeCompetitionEnter,
|
|
3180
|
+
makeCompetitionScore,
|
|
2726
3181
|
makeConfigUpdate,
|
|
2727
3182
|
makeConsentDeny,
|
|
2728
3183
|
makeConsentGrant,
|
|
2729
3184
|
makeConsentRequest,
|
|
3185
|
+
makeContributeCancel,
|
|
3186
|
+
makeContributeRequest,
|
|
3187
|
+
makeContributeResult,
|
|
2730
3188
|
makeEstopMessage,
|
|
2731
3189
|
makeEstopWithQoS,
|
|
2732
3190
|
makeFaultReport,
|
|
2733
3191
|
makeFederationSync,
|
|
2734
3192
|
makeKeyRotationMessage,
|
|
3193
|
+
makePersonalResearchResult,
|
|
2735
3194
|
makeResumeMessage,
|
|
2736
3195
|
makeRevocationBroadcast,
|
|
3196
|
+
makeSeasonStanding,
|
|
2737
3197
|
makeStopMessage,
|
|
2738
3198
|
makeStreamChunk,
|
|
2739
3199
|
makeTrainingConsentDeny,
|
|
@@ -2741,21 +3201,33 @@ export {
|
|
|
2741
3201
|
makeTrainingConsentRequest,
|
|
2742
3202
|
makeTrainingDataMessage,
|
|
2743
3203
|
makeTransparencyMessage,
|
|
3204
|
+
manifestFromWire,
|
|
3205
|
+
manifestToWire,
|
|
3206
|
+
parseM2mPeerToken,
|
|
3207
|
+
parseM2mTrustedToken,
|
|
3208
|
+
roleFromJwtLevel,
|
|
2744
3209
|
selectTransport,
|
|
3210
|
+
validateAuthorityAccess,
|
|
3211
|
+
validateCompetitionScope,
|
|
2745
3212
|
validateConfig,
|
|
2746
3213
|
validateConfigAgainstSchema,
|
|
2747
3214
|
validateConfigUpdate,
|
|
2748
3215
|
validateConsentMessage,
|
|
3216
|
+
validateContributeScope,
|
|
2749
3217
|
validateCrossRegistryCommand,
|
|
2750
3218
|
validateDelegationChain,
|
|
2751
3219
|
validateLoaForScope,
|
|
3220
|
+
validateManifest,
|
|
2752
3221
|
validateMediaChunks,
|
|
2753
3222
|
validateMessage,
|
|
2754
3223
|
validateNodeAgainstSchema,
|
|
2755
3224
|
validateReplay,
|
|
3225
|
+
validateRoleForScope,
|
|
2756
3226
|
validateSafetyMessage,
|
|
2757
3227
|
validateTrainingDataMessage,
|
|
2758
3228
|
validateURI,
|
|
2759
|
-
validateVersionCompat
|
|
3229
|
+
validateVersionCompat,
|
|
3230
|
+
verifyM2mTrustedToken,
|
|
3231
|
+
verifyM2mTrustedTokenClaims
|
|
2760
3232
|
};
|
|
2761
3233
|
//# sourceMappingURL=index.mjs.map
|