@continuonai/rcan-ts 0.5.0 → 0.8.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,62 +1,50 @@
1
1
  # rcan-ts
2
2
 
3
- Official TypeScript SDK for the **RCAN v1.5** Robot Communication and Addressing Network protocol.
3
+ TypeScript SDK for the [RCAN protocol](https://rcan.dev/spec/) build robots that communicate securely, audit every action, and enforce safety gates in Node.js or the browser.
4
4
 
5
- [![npm version](https://badge.fury.io/js/%40continuonai%2Frcan-ts.svg)](https://www.npmjs.com/package/@continuonai/rcan-ts)
5
+ [![npm version](https://img.shields.io/npm/v/@continuonai/rcan-ts.svg)](https://www.npmjs.com/package/@continuonai/rcan-ts)
6
+ [![RCAN Spec](https://img.shields.io/badge/RCAN-v1.6-blue)](https://rcan.dev/spec/)
6
7
  [![CI](https://github.com/continuonai/rcan-ts/actions/workflows/ci.yml/badge.svg)](https://github.com/continuonai/rcan-ts/actions)
8
+ [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
9
+ [![Node](https://img.shields.io/badge/node-18%2B-green)](https://nodejs.org)
7
10
 
8
- ```
9
- npm install @continuonai/rcan-ts
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install @continuonai/rcan-ts@0.6.0
10
15
  ```
11
16
 
12
- > **v0.2.0** RCAN v1.2 spec compliance including §17 Distributed Registry Node Protocol
17
+ Node 18+ required (uses Web Crypto API for `transport.encodeMinimal`).
13
18
 
14
- ### CDN / Browser (no build step)
19
+ ### Browser / CDN (no build step)
15
20
 
16
21
  ```html
17
22
  <script src="https://unpkg.com/@continuonai/rcan-ts/dist/rcan.iife.js"></script>
18
23
  <script>
19
- const uri = new RCAN.RobotURI.parse('rcan://registry.rcan.dev/acme/arm/v1/unit-001');
24
+ const uri = RCAN.RobotURI.parse('rcan://registry.rcan.dev/acme/arm/v1/unit-001');
20
25
  console.log(uri.manufacturer); // acme
21
26
  </script>
22
27
  ```
23
28
 
24
- Also available via jsDelivr:
25
- ```html
26
- <script src="https://cdn.jsdelivr.net/npm/@continuonai/rcan-ts/dist/rcan.iife.js"></script>
27
- ```
28
-
29
- ---
30
-
31
29
  ## Quick Start
32
30
 
33
- ### Robot URI
34
-
35
- Every robot has a globally unique, resolvable address:
36
-
37
31
  ```typescript
38
- import { RobotURI } from "@continuonai/rcan-ts";
32
+ import { RobotURI, RCANMessage, ConfidenceGate } from "@continuonai/rcan-ts";
33
+ import { ReplayCache } from "@continuonai/rcan-ts";
34
+ import { AuditChain } from "@continuonai/rcan-ts";
39
35
 
36
+ // 1. Address a robot
40
37
  const uri = RobotURI.build({
41
38
  manufacturer: "acme",
42
- model: "robotarm",
39
+ model: "arm",
43
40
  version: "v2",
44
41
  deviceId: "unit-001",
45
42
  });
46
- console.log(uri.toString());
47
- // rcan://registry.rcan.dev/acme/robotarm/v2/unit-001
48
-
49
- const parsed = RobotURI.parse("rcan://registry.rcan.dev/acme/robotarm/v2/unit-001");
50
- console.log(parsed.namespace); // "acme/robotarm"
51
- ```
52
-
53
- ### Building a Message
54
-
55
- ```typescript
56
- import { RCANMessage, ConfidenceGate } from "@continuonai/rcan-ts";
43
+ // rcan://registry.rcan.dev/acme/arm/v2/unit-001
57
44
 
45
+ // 2. Gate on AI confidence before acting
58
46
  const gate = new ConfidenceGate(0.8);
59
- const confidence = 0.91; // from your AI model
47
+ const confidence = 0.91;
60
48
 
61
49
  if (gate.allows(confidence)) {
62
50
  const msg = new RCANMessage({
@@ -64,190 +52,110 @@ if (gate.allows(confidence)) {
64
52
  target: uri,
65
53
  params: { distance_m: 1.0 },
66
54
  confidence,
67
- modelIdentity: "Qwen2.5-7B-Q4",
55
+ modelIdentity: "gemini-2.5-flash",
68
56
  });
69
- console.log(msg.toJSONString(2));
70
- }
71
- ```
72
-
73
- ### Human-in-the-Loop Gate
74
-
75
- ```typescript
76
- import { HiTLGate } from "@continuonai/rcan-ts";
77
57
 
78
- const hitl = new HiTLGate();
79
- const token = hitl.request("stop_emergency", { reason: "obstacle detected" });
58
+ // 3. Replay attack prevention
59
+ const cache = new ReplayCache({ windowSeconds: 300 });
60
+ if (cache.isReplay(msg.msgId)) throw new Error("Replay attack detected");
61
+ cache.record(msg.msgId);
80
62
 
81
- // Later, from your operator UI:
82
- hitl.approve(token);
83
-
84
- if (hitl.check(token) === "approved") {
85
- // execute action
63
+ // 4. ESTOP with QoS 2 (EXACTLY_ONCE) — never dropped
64
+ const estop = new RCANMessage({
65
+ cmd: "estop",
66
+ target: uri,
67
+ qos: 2, // QoSLevel.EXACTLY_ONCE
68
+ });
86
69
  }
87
- ```
88
-
89
- ### Tamper-Evident Audit Chain
90
-
91
- ```typescript
92
- import { AuditChain } from "@continuonai/rcan-ts";
93
70
 
71
+ // 5. Tamper-evident audit chain
94
72
  const chain = new AuditChain("your-hmac-secret");
95
-
96
73
  chain.append({
97
74
  action: "move_forward",
98
75
  robotUri: uri.toString(),
99
76
  confidence: 0.91,
100
77
  safetyApproved: true,
101
78
  });
102
- chain.append({ action: "stop" });
103
-
104
- const { valid, count, errors } = chain.verifyAll();
79
+ const { valid, count } = chain.verifyAll();
105
80
  console.log(`Chain valid: ${valid}, ${count} records`);
106
81
 
107
- // Export to JSONL for long-term storage
82
+ // Export as JSONL for long-term storage
108
83
  const jsonl = chain.toJSONL();
109
84
  ```
110
85
 
111
- ### Validation
112
-
113
- ```typescript
114
- import { validateMessage, validateConfig, validateURI } from "@continuonai/rcan-ts";
115
-
116
- const result = validateMessage({
117
- rcan: "1.2",
118
- cmd: "move_forward",
119
- target: "rcan://registry.rcan.dev/acme/arm/v2/unit-001",
120
- confidence: 0.91,
121
- });
122
-
123
- if (!result.ok) {
124
- result.issues.forEach((i) => console.error("❌", i));
125
- }
126
- result.warnings.forEach((w) => console.warn("⚠️", w));
127
- ```
128
-
129
- ---
130
-
131
- ## API Reference
132
-
133
- | Export | Description |
134
- |--------|-------------|
135
- | `RobotURI` | Parse/build RCAN Robot URIs |
136
- | `RCANMessage` | RCAN command message with confidence + signing |
137
- | `ConfidenceGate` | AI confidence threshold gate |
138
- | `HiTLGate` | Human-in-the-loop approval gate |
139
- | `CommitmentRecord` | HMAC-sealed audit record |
140
- | `AuditChain` | Tamper-evident chain of CommitmentRecords |
141
- | `validateURI` | Validate a Robot URI string |
142
- | `validateMessage` | Validate a RCAN message object |
143
- | `validateConfig` | L1/L2/L3 conformance check for a robot RCAN config |
144
- | `NodeClient` | Resolve RRNs from federated registry nodes (§17) |
145
- | `fetchCanonicalSchema` | Fetch the canonical JSON schema from rcan.dev |
146
- | `validateConfigAgainstSchema` | Validate a config object against the live JSON schema |
147
- | `validateNodeAgainstSchema` | Validate a node manifest against the node schema |
148
-
149
- ---
150
-
151
- ## Distributed Registry Nodes (§17)
152
-
153
- RCAN v1.2 §17 introduces a federated registry network. `NodeClient` resolves RRNs from any node — root or delegated authoritative.
86
+ ## What's in v0.6.0
87
+
88
+ | Module | Description |
89
+ |---|---|
90
+ | `message` | Core `RCANMessage` envelope with all v1.6 fields |
91
+ | `address` | `RobotURI` — parse, build, and validate RCAN robot addresses |
92
+ | `audit` | `AuditChain` + `CommitmentRecord` — tamper-evident HMAC-chained logs |
93
+ | `gates` | `ConfidenceGate`, `HiTLGate` — safety gates for AI-driven actions |
94
+ | `replay` | `ReplayCache` — sliding-window replay attack prevention (GAP-03) |
95
+ | `clock` | `ClockSyncStatus` — NTP clock sync verification (GAP-04) |
96
+ | `qos` | `QoSLevel` — FIRE_AND_FORGET / ACKNOWLEDGED / EXACTLY_ONCE (GAP-11) |
97
+ | `consent` | Consent wire protocol — request/grant/deny (GAP-05) |
98
+ | `revocation` | Robot identity revocation with TTL cache (GAP-02) |
99
+ | `trainingConsent` | Training data consent, GDPR/EU AI Act Annex III §5 (GAP-10) |
100
+ | `delegation` | Command delegation chain, max 4 hops, Ed25519-signed (GAP-01) |
101
+ | `offline` | Offline operation mode — ESTOP always allowed (GAP-06) |
102
+ | `faultReport` | `FaultCode` structured fault taxonomy (GAP-20) |
103
+ | `federation` | Federated consent — cross-registry trust, DNS discovery (GAP-16) |
104
+ | `transport` | Constrained transports — compact CBOR, 32-byte ESTOP minimal, BLE (GAP-17) |
105
+ | `multimodal` | Multi-modal payloads — inline/ref media, streaming (GAP-18) |
106
+ | `identity` | Level of Assurance — LoA policies, JWT parsing (GAP-14) |
107
+ | `keys` | Key rotation with JWKS-compatible `KeyStore` (GAP-09) |
108
+ | `configUpdate` | `CONFIG_UPDATE` protocol with safety scope enforcement (GAP-07) |
109
+ | `node` | `NodeClient` — resolve RRNs across federated registry nodes (§17) |
110
+ | `validate` | L1/L2/L3 conformance validation for configs, messages, URIs |
111
+ | `schema` | Canonical JSON schema validation against rcan.dev |
112
+
113
+ ## Protocol 66 Compliance
114
+
115
+ - **ESTOP always delivered** send with `qos: 2` (`EXACTLY_ONCE`); never blocked
116
+ - **Local safety wins** — `OfflineMode` enforces limits without cloud connectivity
117
+ - **Confidence gates run locally** `ConfidenceGate` makes no network calls
118
+ - **Audit chain required** `AuditChain.verifyAll()` before executing flagged commands
119
+
120
+ ## Registry Resolution
154
121
 
155
122
  ```typescript
156
- import { NodeClient } from '@continuonai/rcan-ts';
123
+ import { NodeClient } from "@continuonai/rcan-ts";
157
124
 
158
125
  const client = new NodeClient();
159
126
 
160
127
  // Resolve an RRN across the federation
161
- const result = await client.resolve('RRN-BD-000000000001');
162
- console.log(`Resolved by: ${result.resolved_by}`);
163
- console.log(`Robot: ${result.record.name}`);
164
-
165
- // Discover the authoritative node for a namespace
166
- const node = await client.discover('RRN-BD-000000000001');
167
- console.log(`Authoritative: ${node.operator} at ${node.api_base}`);
168
-
169
- // List all known registry nodes
170
- const nodes = await client.listNodes();
171
- nodes.forEach(n => console.log(`${n.operator}: ${n.namespace_prefix}`));
172
-
173
- // Verify a node manifest
174
- const manifest = await client.getNodeManifest('https://registry.example.com');
175
- const isValid = client.verifyNode(manifest);
176
-
177
- // Error handling
178
- import { RCANNodeNotFoundError, RCANNodeTrustError } from '@continuonai/rcan-ts';
179
- try {
180
- const result = await client.resolve('RRN-UNKNOWN-000000000001');
181
- } catch (e) {
182
- if (e instanceof RCANNodeNotFoundError) {
183
- console.log(`Not found: ${e.rrn}`);
184
- } else if (e instanceof RCANNodeTrustError) {
185
- console.log(`Trust failure: ${e.reason}`);
186
- }
187
- }
188
- ```
128
+ const result = await client.resolve("RRN-000000000001");
129
+ console.log(result.record.name); // "Bob"
130
+ console.log(result.record.verification_tier); // "verified"
189
131
 
190
- ### RRN Format
191
-
192
- ```
193
- Root namespace: RRN-000000000001 (12-digit recommended, 8-digit still valid)
194
- Delegated: RRN-BD-000000000001 (prefix 2-8 alphanumeric chars)
195
- Legacy (valid): RRN-00000001 (8-digit, backward compatible)
132
+ // Discover which node is authoritative
133
+ const node = await client.discover("RRN-BD-000000000001");
134
+ console.log(node.operator); // "Boston Dynamics, Inc."
196
135
  ```
197
136
 
198
- ## Schema Validation
199
-
200
- Validate configs against the canonical JSON schema published at rcan.dev:
201
-
202
- ```typescript
203
- import { validateConfigAgainstSchema, validateNodeAgainstSchema } from '@continuonai/rcan-ts';
204
-
205
- // Validate a RCAN config against the canonical schema from rcan.dev
206
- const result = await validateConfigAgainstSchema(myConfig);
207
- if (!result.valid) {
208
- console.error('Config invalid:', result.errors);
209
- } else if (result.skipped) {
210
- console.warn('Schema validation skipped (rcan.dev unreachable)');
211
- }
137
+ ## Spec Compliance
212
138
 
213
- // Validate a node manifest
214
- const nodeResult = await validateNodeAgainstSchema(manifest);
215
- ```
139
+ Implements [RCAN v1.6](https://rcan.dev/spec/) 405 tests, 0 skipped.
216
140
 
217
- ### CDN / Browser Usage
218
-
219
- ```html
220
- <script src="https://unpkg.com/@continuonai/rcan-ts/dist/rcan.iife.js"></script>
221
- <script>
222
- const { validateConfig, NodeClient } = window.RCAN;
223
- const client = new NodeClient();
224
- client.resolve('RRN-000000000001').then(r => console.log(r));
225
- </script>
226
- ```
227
-
228
- ---
141
+ API surface is intentionally identical to rcan-py: `RobotURI`, `RCANMessage`, `ConfidenceGate`, `HiTLGate`, `AuditChain`, and `validateConfig` work the same way in both languages.
229
142
 
230
143
  ## Ecosystem
231
144
 
232
- | Package | Language | Install |
233
- |---------|----------|---------|
234
- | [rcan-py](https://github.com/continuonai/rcan-py) | Python 3.10+ | `pip install rcan` |
235
- | **rcan-ts** (this) | TypeScript / Node | `npm install @continuonai/rcan-ts` |
236
- | [OpenCastor](https://github.com/craigm26/OpenCastor) | Python (robot runtime) | `curl -sL opencastor.com/install \| bash` |
237
-
238
- The Python and TypeScript SDKs share an identical API surface — `RobotURI`, `RCANMessage`, `ConfidenceGate`, `HiTLGate`, `AuditChain`, and `validateConfig` work the same way in both languages.
145
+ | Package | Version | Purpose |
146
+ |---|---|---|
147
+ | [rcan-py](https://github.com/continuonai/rcan-py) | v0.6.0 | Python SDK |
148
+ | **rcan-ts** (this) | v0.6.0 | TypeScript SDK |
149
+ | [rcan-spec](https://github.com/continuonai/rcan-spec) | v1.6.0 | Protocol spec |
150
+ | [OpenCastor](https://github.com/craigm26/OpenCastor) | v2026.3.17.1 | Robot runtime (reference impl) |
151
+ | [RRF](https://robotregistryfoundation.org) | v1.6.0 | Robot identity registry |
152
+ | [Fleet UI](https://app.opencastor.com) | live | Web fleet dashboard |
239
153
 
240
- ## Links
154
+ ## Contributing
241
155
 
242
- - [Quickstart](https://rcan.dev/quickstart) — from zero to first message in 5 min
243
- - 📖 [RCAN Spec v1.5](https://rcan.dev/spec) — full protocol specification
244
- - 🌐 [rcan.dev](https://rcan.dev) — robot registry and documentation
245
- - 🐍 [rcan-py](https://github.com/continuonai/rcan-py) — Python SDK
246
- - 🤖 [OpenCastor](https://github.com/craigm26/OpenCastor) — Python robot runtime (RCAN reference implementation)
247
- - 🖥️ [OpenCastor Fleet UI](https://app.opencastor.com) — Flutter web app for remote fleet management (uses rcan-ts for message construction)
248
- - 🏛️ [Robot Registry Foundation](https://robotregistryfoundation.org) — global robot identity registry
156
+ Issues and PRs welcome at [github.com/continuonai/rcan-ts](https://github.com/continuonai/rcan-ts).
249
157
 
250
- ---
158
+ Spec discussions: [github.com/continuonai/rcan-spec/issues](https://github.com/continuonai/rcan-spec/issues)
251
159
 
252
160
  ## License
253
161