@continuonai/rcan-ts 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # rcan-ts
2
2
 
3
- Official TypeScript SDK for the **RCAN v1.5** Robot Communication and Addressing Network protocol.
3
+ Official TypeScript SDK for the **RCAN v1.6** Robot Communication and Addressing Network protocol.
4
4
 
5
5
  [![npm version](https://badge.fury.io/js/%40continuonai%2Frcan-ts.svg)](https://www.npmjs.com/package/@continuonai/rcan-ts)
6
6
  [![CI](https://github.com/continuonai/rcan-ts/actions/workflows/ci.yml/badge.svg)](https://github.com/continuonai/rcan-ts/actions)
@@ -121,6 +121,12 @@ interface RCANMessageData {
121
121
  proximityMeters?: number;
122
122
  /** v1.5: GAP-15 observer */
123
123
  readOnly?: boolean;
124
+ /** v1.6: GAP-14 level of assurance */
125
+ loa?: number;
126
+ /** v1.6: GAP-17 transport encoding hint */
127
+ transportEncoding?: string;
128
+ /** v1.6: GAP-18 multi-modal media chunks */
129
+ mediaChunks?: Array<Record<string, unknown>>;
124
130
  [key: string]: unknown;
125
131
  }
126
132
  declare class RCANMessageError extends Error {
@@ -147,6 +153,12 @@ declare class RCANMessage {
147
153
  readonly presenceVerified: boolean | undefined;
148
154
  readonly proximityMeters: number | undefined;
149
155
  readonly readOnly: boolean | undefined;
156
+ /** v1.6: GAP-14 level of assurance */
157
+ readonly loa: number | undefined;
158
+ /** v1.6: GAP-17 transport encoding hint */
159
+ readonly transportEncoding: string | undefined;
160
+ /** v1.6: GAP-18 multi-modal media chunks */
161
+ readonly mediaChunks: Array<Record<string, unknown>> | undefined;
150
162
  constructor(data: RCANMessageData);
151
163
  /** Whether this message has a signature block */
152
164
  get isSigned(): boolean;
@@ -714,7 +726,9 @@ declare function makeTransparencyMessage(ruri: string, disclosure: string, deleg
714
726
  * §3.5 — Protocol Version Compatibility
715
727
  */
716
728
  /** The RCAN spec version this SDK implements. */
717
- declare const SPEC_VERSION = "1.5";
729
+ declare const SPEC_VERSION = "1.6";
730
+ /** The SDK release version. */
731
+ declare const SDK_VERSION = "0.6.0";
718
732
  /**
719
733
  * Validate version compatibility.
720
734
  *
@@ -1176,15 +1190,246 @@ interface AuditExportRequest {
1176
1190
  }
1177
1191
 
1178
1192
  /**
1179
- * rcan-ts Official TypeScript SDK for RCAN v1.5
1193
+ * RCAN Identity & Level of Assurance (LoA) — GAP-14.
1194
+ *
1195
+ * Provides JWT-based LoA extraction and per-scope policy enforcement.
1196
+ * Backward compatible: DEFAULT_LOA_POLICY requires only ANONYMOUS (LoA 1).
1197
+ */
1198
+ declare enum LevelOfAssurance {
1199
+ ANONYMOUS = 1,
1200
+ EMAIL_VERIFIED = 2,
1201
+ HARDWARE_TOKEN = 3
1202
+ }
1203
+ interface LoaPolicy {
1204
+ minLoaDiscover: LevelOfAssurance;
1205
+ minLoaStatus: LevelOfAssurance;
1206
+ minLoaChat: LevelOfAssurance;
1207
+ minLoaControl: LevelOfAssurance;
1208
+ minLoaSafety: LevelOfAssurance;
1209
+ }
1210
+ /** Backward-compatible policy — every scope accepts anonymous callers. */
1211
+ declare const DEFAULT_LOA_POLICY: LoaPolicy;
1212
+ /** Production-hardened policy — control needs e-mail, safety needs hardware token. */
1213
+ declare const PRODUCTION_LOA_POLICY: LoaPolicy;
1214
+ /**
1215
+ * Decode a JWT (header.payload.sig) and return the `loa` claim.
1216
+ * Defaults to ANONYMOUS when the claim is absent or the token is malformed.
1217
+ */
1218
+ declare function extractLoaFromJwt(token: string): LevelOfAssurance;
1219
+ /**
1220
+ * Check whether `loa` satisfies the minimum required for `scope`.
1221
+ *
1222
+ * @param loa - Caller's assurance level
1223
+ * @param scope - One of discover | status | chat | control | safety
1224
+ * @param policy - Defaults to DEFAULT_LOA_POLICY (backward compatible)
1225
+ */
1226
+ declare function validateLoaForScope(loa: LevelOfAssurance, scope: string, policy?: LoaPolicy): {
1227
+ valid: boolean;
1228
+ reason: string;
1229
+ };
1230
+
1231
+ /**
1232
+ * RCAN Federation — cross-registry trust and sync (GAP-16).
1233
+ *
1234
+ * Provides:
1235
+ * - Registry tier model (root / authoritative / community)
1236
+ * - TrustAnchorCache with 24-hour TTL and DNS-TXT discovery
1237
+ * - JWT verification against a trusted registry
1238
+ * - Cross-registry command validation (LoA ≥ 2 required; ESTOP always allowed)
1239
+ */
1240
+
1241
+ declare enum RegistryTier {
1242
+ ROOT = "root",
1243
+ AUTHORITATIVE = "authoritative",
1244
+ COMMUNITY = "community"
1245
+ }
1246
+ declare enum FederationSyncType {
1247
+ CONSENT = "consent",
1248
+ REVOCATION = "revocation",
1249
+ KEY = "key"
1250
+ }
1251
+ interface RegistryIdentity {
1252
+ registryUrl: string;
1253
+ tier: RegistryTier;
1254
+ publicKeyPem: string;
1255
+ domain: string;
1256
+ verifiedAt?: string;
1257
+ }
1258
+ interface FederationSyncPayload {
1259
+ sourceRegistry: string;
1260
+ targetRegistry: string;
1261
+ syncType: FederationSyncType;
1262
+ payload: Record<string, unknown>;
1263
+ signature: string;
1264
+ }
1265
+ /**
1266
+ * In-memory cache of trusted registry identities.
1267
+ *
1268
+ * Entries expire after 24 hours. Discovery via DNS TXT records
1269
+ * (_rcan-registry.<domain>) is supported in Node.js environments.
1270
+ */
1271
+ declare class TrustAnchorCache {
1272
+ private readonly store;
1273
+ /** Store or refresh a registry identity. */
1274
+ set(identity: RegistryIdentity): void;
1275
+ /**
1276
+ * Look up a registry URL.
1277
+ * Returns undefined when absent or when the TTL has expired.
1278
+ */
1279
+ lookup(url: string): RegistryIdentity | undefined;
1280
+ /**
1281
+ * Discover a registry via DNS TXT record `_rcan-registry.<domain>`.
1282
+ *
1283
+ * The TXT record is expected to contain a JSON object with the
1284
+ * RegistryIdentity fields. Returns the identity and caches it.
1285
+ *
1286
+ * Node.js only — returns undefined in environments without `dns.promises`.
1287
+ */
1288
+ discoverViaDns(domain: string): Promise<RegistryIdentity | undefined>;
1289
+ /**
1290
+ * Verify a JWT was issued by the registry at `url`.
1291
+ *
1292
+ * Validates the `iss` claim and checks the registry is in the trust cache.
1293
+ * Full cryptographic signature verification requires the registry's public
1294
+ * key material — callers should perform additional checks using `publicKeyPem`
1295
+ * from the returned identity.
1296
+ */
1297
+ verifyRegistryJwt(token: string, url: string): Promise<RegistryIdentity>;
1298
+ }
1299
+ /**
1300
+ * Build a FEDERATION_SYNC message (MessageType 12).
1301
+ */
1302
+ declare function makeFederationSync(source: string, target: string, syncType: FederationSyncType, payload: FederationSyncPayload): RCANMessage;
1303
+ /**
1304
+ * Validate a cross-registry command against the local trust anchor cache.
1305
+ *
1306
+ * Rules:
1307
+ * - ESTOP (SAFETY type 6 or cmd=estop) always returns valid (P66 invariant).
1308
+ * - All other cross-registry commands require LoA ≥ 2 (EMAIL_VERIFIED).
1309
+ * - If the message originates from `localRegistry` it is not cross-registry.
1310
+ */
1311
+ declare function validateCrossRegistryCommand(msg: RCANMessage, localRegistry: string, trustCache: TrustAnchorCache): Promise<{
1312
+ valid: boolean;
1313
+ reason: string;
1314
+ }>;
1315
+
1316
+ /**
1317
+ * RCAN Constrained-Transport Encodings — GAP-17.
1318
+ *
1319
+ * Provides compact JSON, 32-byte minimal (ESTOP-only), BLE frame fragmentation,
1320
+ * and a transport-selection helper. No external runtime dependencies.
1321
+ */
1322
+
1323
+ declare class TransportError extends Error {
1324
+ constructor(message: string);
1325
+ }
1326
+ declare enum TransportEncoding {
1327
+ HTTP = "http",
1328
+ COMPACT = "compact",
1329
+ MINIMAL = "minimal",
1330
+ BLE = "ble"
1331
+ }
1332
+ /** Serialize a RCANMessage to compact JSON bytes. */
1333
+ declare function encodeCompact(message: RCANMessage): Uint8Array;
1334
+ /** Deserialize compact JSON bytes to a RCANMessage. */
1335
+ declare function decodeCompact(data: Uint8Array): RCANMessage;
1336
+ /**
1337
+ * Encode a SAFETY (type 6) message to a 32-byte minimal frame.
1338
+ *
1339
+ * Layout: [2B type][8B from_hash][8B to_hash][4B unix32][8B sig_truncated][2B checksum]
1340
+ *
1341
+ * - Only SAFETY (type 6) messages are accepted; throws `TransportError` for others.
1342
+ * - Runtime assertion: output MUST be exactly 32 bytes.
1343
+ */
1344
+ declare function encodeMinimal(message: RCANMessage): Promise<Uint8Array>;
1345
+ /**
1346
+ * Decode a 32-byte minimal frame to a partial RCANMessage.
1347
+ */
1348
+ declare function decodeMinimal(data: Uint8Array): Partial<RCANMessage>;
1349
+ /**
1350
+ * Fragment a RCANMessage into BLE advertisement frames.
1351
+ * Compact JSON encoding is used for the payload; each chunk is ≤ `mtu` bytes.
1352
+ */
1353
+ declare function encodeBleFrames(message: RCANMessage, mtu?: number): Uint8Array[];
1354
+ /**
1355
+ * Reassemble BLE frames (in order) into a RCANMessage.
1356
+ */
1357
+ declare function decodeBleFrames(frames: Uint8Array[]): RCANMessage;
1358
+ /**
1359
+ * Select the most appropriate transport encoding from an availability list.
1360
+ *
1361
+ * Priority:
1362
+ * - SAFETY (type 6) messages: prefer MINIMAL → BLE → COMPACT → HTTP
1363
+ * - All others: prefer HTTP → COMPACT → BLE
1364
+ */
1365
+ declare function selectTransport(available: TransportEncoding[], message: RCANMessage): TransportEncoding;
1366
+
1367
+ /**
1368
+ * RCAN Multi-modal Data — GAP-18.
1369
+ *
1370
+ * Provides inline and by-reference media attachment for RCANMessage,
1371
+ * streaming chunk helpers, and training-data message construction.
1372
+ * SHA-256 is computed via the Web Crypto API (built-in Node 18+).
1373
+ */
1374
+
1375
+ declare enum MediaEncoding {
1376
+ BASE64 = "base64",
1377
+ REF = "ref"
1378
+ }
1379
+ interface MediaChunk {
1380
+ chunkId: string;
1381
+ mimeType: string;
1382
+ encoding: MediaEncoding;
1383
+ hashSha256: string;
1384
+ dataB64?: string;
1385
+ refUrl?: string;
1386
+ sizeBytes: number;
1387
+ }
1388
+ interface StreamChunk {
1389
+ streamId: string;
1390
+ chunkIndex: number;
1391
+ isFinal: boolean;
1392
+ chunk: MediaChunk;
1393
+ }
1394
+ /**
1395
+ * Attach inline (base64-encoded) media to a message.
1396
+ * SHA-256 is computed via Web Crypto API.
1397
+ */
1398
+ declare function addMediaInline(message: RCANMessage, data: Uint8Array, mimeType: string): Promise<RCANMessage>;
1399
+ /**
1400
+ * Attach a media reference (URL + pre-computed hash) to a message.
1401
+ */
1402
+ declare function addMediaRef(message: RCANMessage, refUrl: string, mimeType: string, hashSha256: string, sizeBytes: number): RCANMessage;
1403
+ /**
1404
+ * Validate media chunks on a message.
1405
+ * Checks that inline chunks have dataB64 and ref chunks have refUrl.
1406
+ */
1407
+ declare function validateMediaChunks(message: RCANMessage): Promise<{
1408
+ valid: boolean;
1409
+ reason: string;
1410
+ }>;
1411
+ /**
1412
+ * Build a TRAINING_DATA message (MessageType 10) with multiple media attachments.
1413
+ */
1414
+ declare function makeTrainingDataMessage(media: Array<{
1415
+ data: Uint8Array;
1416
+ mimeType: string;
1417
+ }>): Promise<RCANMessage>;
1418
+ /**
1419
+ * Build a streaming chunk message wrapping a single media item.
1420
+ */
1421
+ declare function makeStreamChunk(streamId: string, data: Uint8Array, mimeType: string, chunkIndex: number, isFinal: boolean): Promise<RCANMessage>;
1422
+
1423
+ /**
1424
+ * rcan-ts — Official TypeScript SDK for RCAN v1.6
1180
1425
  * Robot Communication and Accountability Network
1181
1426
  *
1182
1427
  * @see https://rcan.dev
1183
1428
  * @see https://github.com/continuonai/rcan-ts
1184
1429
  */
1185
1430
 
1186
- declare const VERSION = "0.5.0";
1431
+ declare const VERSION = "0.6.0";
1187
1432
  /** @deprecated Use SPEC_VERSION from ./version instead */
1188
- declare const RCAN_VERSION = "1.5";
1433
+ declare const RCAN_VERSION = "1.6";
1189
1434
 
1190
- export { type ApprovalStatus, AuditChain, AuditError, type AuditExportRequest, type CachedKey, type ChainVerifyResult, ClockDriftError, type ClockSyncStatus, CommitmentRecord, type CommitmentRecordData, type CommitmentRecordJSON, ConfidenceGate, type ConsentRequestParams, type ConsentResponseParams, type ConsentType, DataCategory, type DelegationHop, FaultCode, type FaultReportParams, type FaultSeverity, GateError, HiTLGate, type JWKEntry, type JWKSDocument, KeyStore, type ListResult, MessageType, NodeClient, type OfflineCommandResult, OfflineModeManager, type OfflineState, type PendingApproval, QoSAckTimeoutError, QoSLevel, QoSManager, type QoSResult, type QoSSendOptions, RCANAddressError, type RCANAgentConfig, type RCANConfig, RCANConfigAuthorizationError, RCANDelegationChainError, RCANError, RCANGateError, RCANMessage, type RCANMessageData, type RCANMessageEnvelope, RCANMessageError, type RCANMetadata, RCANNodeError, RCANNodeNotFoundError, RCANNodeSyncError, RCANNodeTrustError, RCANRegistryError, type RCANRegistryNode, RCANReplayAttackError, type RCANResolveResult, RCANSignatureError, RCANValidationError, RCANVersionIncompatibleError, RCAN_VERSION, type RegistrationResult, RegistryClient, ReplayCache, type ReplayCheckResult, type ReplayableMessage, RevocationCache, type RevocationStatus, type RevocationStatusValue, type Robot, type RobotRegistration, RobotURI, RobotURIError, type RobotURIOptions, SAFETY_MESSAGE_TYPE, SPEC_VERSION, type SafetyEvent, type SafetyMessage, type SenderType, type SignatureBlock, type TrainingConsentRequestParams, type TransparencyMessage, VERSION, type ValidationResult, addDelegationHop, assertClockSynced, checkClockSync, checkRevocation, fetchCanonicalSchema, isSafetyMessage, makeCloudRelayMessage, makeConfigUpdate, makeConsentDeny, makeConsentGrant, makeConsentRequest, makeEstopMessage, makeEstopWithQoS, makeFaultReport, makeKeyRotationMessage, makeResumeMessage, makeRevocationBroadcast, makeStopMessage, makeTrainingConsentDeny, makeTrainingConsentGrant, makeTrainingConsentRequest, makeTransparencyMessage, validateConfig, validateConfigAgainstSchema, validateConfigUpdate, validateConsentMessage, validateDelegationChain, validateMessage, validateNodeAgainstSchema, validateReplay, validateSafetyMessage, validateTrainingDataMessage, validateURI, validateVersionCompat };
1435
+ export { type ApprovalStatus, AuditChain, AuditError, type AuditExportRequest, type CachedKey, type ChainVerifyResult, ClockDriftError, type ClockSyncStatus, CommitmentRecord, type CommitmentRecordData, type CommitmentRecordJSON, ConfidenceGate, type ConsentRequestParams, type ConsentResponseParams, type ConsentType, DEFAULT_LOA_POLICY, DataCategory, type DelegationHop, FaultCode, type FaultReportParams, type FaultSeverity, type FederationSyncPayload, FederationSyncType, GateError, HiTLGate, type JWKEntry, type JWKSDocument, KeyStore, LevelOfAssurance, type ListResult, type LoaPolicy, type MediaChunk, MediaEncoding, MessageType, NodeClient, type OfflineCommandResult, OfflineModeManager, type OfflineState, PRODUCTION_LOA_POLICY, type PendingApproval, QoSAckTimeoutError, QoSLevel, QoSManager, type QoSResult, type QoSSendOptions, RCANAddressError, type RCANAgentConfig, type RCANConfig, RCANConfigAuthorizationError, RCANDelegationChainError, RCANError, RCANGateError, RCANMessage, type RCANMessageData, type RCANMessageEnvelope, RCANMessageError, type RCANMetadata, RCANNodeError, RCANNodeNotFoundError, RCANNodeSyncError, RCANNodeTrustError, RCANRegistryError, type RCANRegistryNode, RCANReplayAttackError, type RCANResolveResult, RCANSignatureError, RCANValidationError, RCANVersionIncompatibleError, RCAN_VERSION, type RegistrationResult, RegistryClient, type RegistryIdentity, RegistryTier, ReplayCache, type ReplayCheckResult, type ReplayableMessage, RevocationCache, type RevocationStatus, type RevocationStatusValue, type Robot, type RobotRegistration, RobotURI, RobotURIError, type RobotURIOptions, SAFETY_MESSAGE_TYPE, SDK_VERSION, SPEC_VERSION, type SafetyEvent, type SafetyMessage, type SenderType, type SignatureBlock, type StreamChunk, type TrainingConsentRequestParams, type TransparencyMessage, TransportEncoding, TransportError, TrustAnchorCache, VERSION, type ValidationResult, addDelegationHop, addMediaInline, addMediaRef, assertClockSynced, checkClockSync, checkRevocation, decodeBleFrames, decodeCompact, decodeMinimal, encodeBleFrames, encodeCompact, encodeMinimal, extractLoaFromJwt, fetchCanonicalSchema, isSafetyMessage, makeCloudRelayMessage, makeConfigUpdate, makeConsentDeny, makeConsentGrant, makeConsentRequest, makeEstopMessage, makeEstopWithQoS, makeFaultReport, makeFederationSync, makeKeyRotationMessage, makeResumeMessage, makeRevocationBroadcast, makeStopMessage, makeStreamChunk, makeTrainingConsentDeny, makeTrainingConsentGrant, makeTrainingConsentRequest, makeTrainingDataMessage, makeTransparencyMessage, selectTransport, validateConfig, validateConfigAgainstSchema, validateConfigUpdate, validateConsentMessage, validateCrossRegistryCommand, validateDelegationChain, validateLoaForScope, validateMediaChunks, validateMessage, validateNodeAgainstSchema, validateReplay, validateSafetyMessage, validateTrainingDataMessage, validateURI, validateVersionCompat };