chainlesschain 0.47.9 → 0.49.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/bin/chainlesschain.js +0 -0
- package/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AppLayout-6SPt_8Y_.js → AppLayout-Rvi759IS.js} +1 -1
- package/src/assets/web-panel/assets/Dashboard-BS-tzGNj.css +1 -0
- package/src/assets/web-panel/assets/{Dashboard-Br7kCwKJ.js → Dashboard-DBhFxXYQ.js} +2 -2
- package/src/assets/web-panel/assets/{index-tN-8TosE.js → index-uL0cZ8N_.js} +2 -2
- package/src/assets/web-panel/index.html +2 -2
- package/src/commands/codegen.js +303 -0
- package/src/commands/collab.js +482 -0
- package/src/commands/crosschain.js +382 -0
- package/src/commands/dbevo.js +388 -0
- package/src/commands/dev.js +411 -0
- package/src/commands/federation.js +427 -0
- package/src/commands/fusion.js +332 -0
- package/src/commands/governance.js +505 -0
- package/src/commands/hardening.js +110 -0
- package/src/commands/incentive.js +373 -0
- package/src/commands/inference.js +304 -0
- package/src/commands/infra.js +361 -0
- package/src/commands/kg.js +371 -0
- package/src/commands/marketplace.js +326 -0
- package/src/commands/mcp.js +97 -18
- package/src/commands/nlprog.js +329 -0
- package/src/commands/ops.js +408 -0
- package/src/commands/perception.js +385 -0
- package/src/commands/pqc.js +34 -0
- package/src/commands/privacy.js +345 -0
- package/src/commands/quantization.js +280 -0
- package/src/commands/recommend.js +336 -0
- package/src/commands/reputation.js +349 -0
- package/src/commands/runtime.js +500 -0
- package/src/commands/sla.js +352 -0
- package/src/commands/stress.js +252 -0
- package/src/commands/tech.js +268 -0
- package/src/commands/tenant.js +576 -0
- package/src/commands/trust.js +366 -0
- package/src/harness/mcp-client.js +330 -54
- package/src/index.js +112 -0
- package/src/lib/aiops.js +523 -0
- package/src/lib/autonomous-developer.js +524 -0
- package/src/lib/code-agent.js +442 -0
- package/src/lib/collaboration-governance.js +556 -0
- package/src/lib/community-governance.js +649 -0
- package/src/lib/content-recommendation.js +600 -0
- package/src/lib/cross-chain.js +669 -0
- package/src/lib/dbevo.js +669 -0
- package/src/lib/decentral-infra.js +445 -0
- package/src/lib/federation-hardening.js +587 -0
- package/src/lib/hardening-manager.js +409 -0
- package/src/lib/inference-network.js +407 -0
- package/src/lib/knowledge-graph.js +530 -0
- package/src/lib/mcp-client.js +3 -0
- package/src/lib/multimodal.js +698 -0
- package/src/lib/nl-programming.js +595 -0
- package/src/lib/perception.js +500 -0
- package/src/lib/pqc-manager.js +141 -9
- package/src/lib/privacy-computing.js +575 -0
- package/src/lib/protocol-fusion.js +535 -0
- package/src/lib/quantization.js +362 -0
- package/src/lib/reputation-optimizer.js +509 -0
- package/src/lib/skill-marketplace.js +397 -0
- package/src/lib/sla-manager.js +484 -0
- package/src/lib/stress-tester.js +383 -0
- package/src/lib/tech-learning-engine.js +651 -0
- package/src/lib/tenant-saas.js +831 -0
- package/src/lib/token-incentive.js +513 -0
- package/src/lib/trust-security.js +473 -0
- package/src/lib/universal-runtime.js +771 -0
- package/src/assets/web-panel/assets/Dashboard-CKeMmCoT.css +0 -1
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cc trust` — CLI surface for Phase 68-71 Trust & Security.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
TRUST_ANCHOR,
|
|
9
|
+
ATTESTATION_STATUS,
|
|
10
|
+
SATELLITE_PROVIDER,
|
|
11
|
+
SAT_MESSAGE_STATUS,
|
|
12
|
+
HSM_VENDOR,
|
|
13
|
+
COMPLIANCE_LEVEL,
|
|
14
|
+
ensureTrustSecurityTables,
|
|
15
|
+
attest,
|
|
16
|
+
getAttestation,
|
|
17
|
+
listAttestations,
|
|
18
|
+
runInteropTest,
|
|
19
|
+
listInteropTests,
|
|
20
|
+
sendSatelliteMessage,
|
|
21
|
+
updateSatMessageStatus,
|
|
22
|
+
getSatMessage,
|
|
23
|
+
listSatMessages,
|
|
24
|
+
registerHsmDevice,
|
|
25
|
+
removeHsmDevice,
|
|
26
|
+
getHsmDevice,
|
|
27
|
+
listHsmDevices,
|
|
28
|
+
signWithHsm,
|
|
29
|
+
getTrustSecurityStats,
|
|
30
|
+
} from "../lib/trust-security.js";
|
|
31
|
+
|
|
32
|
+
function _dbFromCtx(cmd) {
|
|
33
|
+
const root = cmd?.parent?.parent ?? cmd?.parent;
|
|
34
|
+
return root?._db;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function registerTrustCommand(program) {
|
|
38
|
+
const tr = new Command("trust")
|
|
39
|
+
.description("Trust & security (Phase 68-71)")
|
|
40
|
+
.hook("preAction", (thisCmd) => {
|
|
41
|
+
const db = _dbFromCtx(thisCmd);
|
|
42
|
+
if (db) ensureTrustSecurityTables(db);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
/* ── Catalogs ────────────────────────────────────── */
|
|
46
|
+
|
|
47
|
+
tr.command("anchors")
|
|
48
|
+
.description("List trust anchors")
|
|
49
|
+
.option("--json", "JSON output")
|
|
50
|
+
.action((opts) => {
|
|
51
|
+
const anchors = Object.values(TRUST_ANCHOR);
|
|
52
|
+
if (opts.json) return console.log(JSON.stringify(anchors, null, 2));
|
|
53
|
+
for (const a of anchors) console.log(` ${a}`);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
tr.command("hsm-vendors")
|
|
57
|
+
.description("List HSM vendors")
|
|
58
|
+
.option("--json", "JSON output")
|
|
59
|
+
.action((opts) => {
|
|
60
|
+
const vendors = Object.values(HSM_VENDOR);
|
|
61
|
+
if (opts.json) return console.log(JSON.stringify(vendors, null, 2));
|
|
62
|
+
for (const v of vendors) console.log(` ${v}`);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
tr.command("compliance-levels")
|
|
66
|
+
.description("List compliance levels")
|
|
67
|
+
.option("--json", "JSON output")
|
|
68
|
+
.action((opts) => {
|
|
69
|
+
const levels = Object.values(COMPLIANCE_LEVEL);
|
|
70
|
+
if (opts.json) return console.log(JSON.stringify(levels, null, 2));
|
|
71
|
+
for (const l of levels) console.log(` ${l}`);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
tr.command("sat-providers")
|
|
75
|
+
.description("List satellite providers")
|
|
76
|
+
.option("--json", "JSON output")
|
|
77
|
+
.action((opts) => {
|
|
78
|
+
const providers = Object.values(SATELLITE_PROVIDER);
|
|
79
|
+
if (opts.json) return console.log(JSON.stringify(providers, null, 2));
|
|
80
|
+
for (const p of providers) console.log(` ${p}`);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
/* ── Trust Root (Phase 68) ───────────────────────── */
|
|
84
|
+
|
|
85
|
+
tr.command("attest <anchor>")
|
|
86
|
+
.description("Execute trust attestation (tpm/tee/secure_element)")
|
|
87
|
+
.option("-c, --challenge <hex>", "Challenge value")
|
|
88
|
+
.option("-f, --fingerprint <hash>", "Device fingerprint")
|
|
89
|
+
.option("--json", "JSON output")
|
|
90
|
+
.action((anchor, opts) => {
|
|
91
|
+
const db = _dbFromCtx(tr);
|
|
92
|
+
const result = attest(db, {
|
|
93
|
+
anchor,
|
|
94
|
+
challenge: opts.challenge,
|
|
95
|
+
deviceFingerprint: opts.fingerprint,
|
|
96
|
+
});
|
|
97
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
98
|
+
if (result.attestationId) {
|
|
99
|
+
console.log(`Attestation: ${result.attestationId}`);
|
|
100
|
+
console.log(`Status: ${result.status}`);
|
|
101
|
+
console.log(`Response: ${result.response}`);
|
|
102
|
+
} else console.log(`Failed: ${result.reason}`);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
tr.command("attest-show <id>")
|
|
106
|
+
.description("Show attestation details")
|
|
107
|
+
.option("--json", "JSON output")
|
|
108
|
+
.action((id, opts) => {
|
|
109
|
+
const db = _dbFromCtx(tr);
|
|
110
|
+
const a = getAttestation(db, id);
|
|
111
|
+
if (!a) return console.log("Attestation not found.");
|
|
112
|
+
if (opts.json) return console.log(JSON.stringify(a, null, 2));
|
|
113
|
+
console.log(`ID: ${a.id}`);
|
|
114
|
+
console.log(`Anchor: ${a.anchor}`);
|
|
115
|
+
console.log(`Status: ${a.status}`);
|
|
116
|
+
console.log(`Challenge: ${a.challenge}`);
|
|
117
|
+
console.log(`Response: ${a.response}`);
|
|
118
|
+
if (a.device_fingerprint)
|
|
119
|
+
console.log(`Fingerprint: ${a.device_fingerprint}`);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
tr.command("attestations")
|
|
123
|
+
.description("List attestations")
|
|
124
|
+
.option("-a, --anchor <type>", "Filter by anchor")
|
|
125
|
+
.option("-s, --status <status>", "Filter by status")
|
|
126
|
+
.option("--limit <n>", "Max results", parseInt)
|
|
127
|
+
.option("--json", "JSON output")
|
|
128
|
+
.action((opts) => {
|
|
129
|
+
const db = _dbFromCtx(tr);
|
|
130
|
+
const atts = listAttestations(db, {
|
|
131
|
+
anchor: opts.anchor,
|
|
132
|
+
status: opts.status,
|
|
133
|
+
limit: opts.limit,
|
|
134
|
+
});
|
|
135
|
+
if (opts.json) return console.log(JSON.stringify(atts, null, 2));
|
|
136
|
+
if (atts.length === 0) return console.log("No attestations.");
|
|
137
|
+
for (const a of atts) {
|
|
138
|
+
console.log(
|
|
139
|
+
` ${a.status.padEnd(10)} ${a.anchor.padEnd(16)} ${a.id.slice(0, 8)}`,
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
/* ── PQC Interop (Phase 69) ──────────────────────── */
|
|
145
|
+
|
|
146
|
+
tr.command("interop-test <algorithm>")
|
|
147
|
+
.description("Run PQC interoperability test")
|
|
148
|
+
.option("-p, --peer <id>", "Peer identifier")
|
|
149
|
+
.option("-l, --latency <ms>", "Latency in ms", parseInt)
|
|
150
|
+
.option("--json", "JSON output")
|
|
151
|
+
.action((algorithm, opts) => {
|
|
152
|
+
const db = _dbFromCtx(tr);
|
|
153
|
+
const result = runInteropTest(db, algorithm, {
|
|
154
|
+
peer: opts.peer,
|
|
155
|
+
latencyMs: opts.latency,
|
|
156
|
+
});
|
|
157
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
158
|
+
if (result.testId) {
|
|
159
|
+
console.log(`Test: ${result.testId}`);
|
|
160
|
+
console.log(
|
|
161
|
+
`Compatible: ${result.compatible ? "YES" : "NO"} (${result.result})`,
|
|
162
|
+
);
|
|
163
|
+
console.log(`Latency: ${result.latencyMs}ms`);
|
|
164
|
+
} else console.log(`Failed: ${result.reason}`);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
tr.command("interop-tests")
|
|
168
|
+
.description("List PQC interop tests")
|
|
169
|
+
.option("-a, --algorithm <algo>", "Filter by algorithm")
|
|
170
|
+
.option("--limit <n>", "Max results", parseInt)
|
|
171
|
+
.option("--json", "JSON output")
|
|
172
|
+
.action((opts) => {
|
|
173
|
+
const db = _dbFromCtx(tr);
|
|
174
|
+
const tests = listInteropTests(db, {
|
|
175
|
+
algorithm: opts.algorithm,
|
|
176
|
+
limit: opts.limit,
|
|
177
|
+
});
|
|
178
|
+
if (opts.json) return console.log(JSON.stringify(tests, null, 2));
|
|
179
|
+
if (tests.length === 0) return console.log("No interop tests.");
|
|
180
|
+
for (const t of tests) {
|
|
181
|
+
console.log(
|
|
182
|
+
` ${t.compatible ? "PASS" : "FAIL"} ${t.algorithm.padEnd(16)} ${t.latency_ms}ms ${t.id.slice(0, 8)}`,
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
/* ── Satellite (Phase 70) ────────────────────────── */
|
|
188
|
+
|
|
189
|
+
tr.command("sat-send <payload>")
|
|
190
|
+
.description("Send satellite message")
|
|
191
|
+
.option("-p, --provider <name>", "Provider (iridium/starlink/beidou)")
|
|
192
|
+
.option("-r, --priority <n>", "Priority (1-10)", parseInt)
|
|
193
|
+
.option("--json", "JSON output")
|
|
194
|
+
.action((payload, opts) => {
|
|
195
|
+
const db = _dbFromCtx(tr);
|
|
196
|
+
const result = sendSatelliteMessage(db, payload, {
|
|
197
|
+
provider: opts.provider,
|
|
198
|
+
priority: opts.priority,
|
|
199
|
+
});
|
|
200
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
201
|
+
if (result.messageId) console.log(`Message queued: ${result.messageId}`);
|
|
202
|
+
else console.log(`Failed: ${result.reason}`);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
tr.command("sat-status <id> <status>")
|
|
206
|
+
.description("Update satellite message status")
|
|
207
|
+
.option("--json", "JSON output")
|
|
208
|
+
.action((id, status, opts) => {
|
|
209
|
+
const db = _dbFromCtx(tr);
|
|
210
|
+
const result = updateSatMessageStatus(db, id, status);
|
|
211
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
212
|
+
console.log(
|
|
213
|
+
result.updated ? "Status updated." : `Failed: ${result.reason}`,
|
|
214
|
+
);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
tr.command("sat-show <id>")
|
|
218
|
+
.description("Show satellite message")
|
|
219
|
+
.option("--json", "JSON output")
|
|
220
|
+
.action((id, opts) => {
|
|
221
|
+
const db = _dbFromCtx(tr);
|
|
222
|
+
const m = getSatMessage(db, id);
|
|
223
|
+
if (!m) return console.log("Message not found.");
|
|
224
|
+
if (opts.json) return console.log(JSON.stringify(m, null, 2));
|
|
225
|
+
console.log(`ID: ${m.id}`);
|
|
226
|
+
console.log(`Provider: ${m.provider}`);
|
|
227
|
+
console.log(`Priority: ${m.priority}`);
|
|
228
|
+
console.log(`Status: ${m.status}`);
|
|
229
|
+
console.log(`Payload: ${m.payload}`);
|
|
230
|
+
if (m.sent_at)
|
|
231
|
+
console.log(`Sent: ${new Date(m.sent_at).toISOString()}`);
|
|
232
|
+
if (m.confirmed_at)
|
|
233
|
+
console.log(`Confirmed: ${new Date(m.confirmed_at).toISOString()}`);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
tr.command("sat-messages")
|
|
237
|
+
.description("List satellite messages")
|
|
238
|
+
.option("-p, --provider <name>", "Filter by provider")
|
|
239
|
+
.option("-s, --status <status>", "Filter by status")
|
|
240
|
+
.option("--limit <n>", "Max results", parseInt)
|
|
241
|
+
.option("--json", "JSON output")
|
|
242
|
+
.action((opts) => {
|
|
243
|
+
const db = _dbFromCtx(tr);
|
|
244
|
+
const msgs = listSatMessages(db, {
|
|
245
|
+
provider: opts.provider,
|
|
246
|
+
status: opts.status,
|
|
247
|
+
limit: opts.limit,
|
|
248
|
+
});
|
|
249
|
+
if (opts.json) return console.log(JSON.stringify(msgs, null, 2));
|
|
250
|
+
if (msgs.length === 0) return console.log("No messages.");
|
|
251
|
+
for (const m of msgs) {
|
|
252
|
+
console.log(
|
|
253
|
+
` ${m.status.padEnd(12)} ${m.provider.padEnd(10)} prio=${m.priority} ${m.id.slice(0, 8)}`,
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
/* ── HSM (Phase 71) ──────────────────────────────── */
|
|
259
|
+
|
|
260
|
+
tr.command("hsm-register <vendor>")
|
|
261
|
+
.description("Register HSM device")
|
|
262
|
+
.option("-m, --model <name>", "Device model")
|
|
263
|
+
.option("-s, --serial <sn>", "Serial number")
|
|
264
|
+
.option("-c, --compliance <level>", "Compliance level")
|
|
265
|
+
.option("-f, --firmware <version>", "Firmware version")
|
|
266
|
+
.option("--json", "JSON output")
|
|
267
|
+
.action((vendor, opts) => {
|
|
268
|
+
const db = _dbFromCtx(tr);
|
|
269
|
+
const result = registerHsmDevice(db, vendor, {
|
|
270
|
+
model: opts.model,
|
|
271
|
+
serialNumber: opts.serial,
|
|
272
|
+
complianceLevel: opts.compliance,
|
|
273
|
+
firmwareVersion: opts.firmware,
|
|
274
|
+
});
|
|
275
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
276
|
+
if (result.deviceId) console.log(`HSM registered: ${result.deviceId}`);
|
|
277
|
+
else console.log(`Failed: ${result.reason}`);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
tr.command("hsm-remove <id>")
|
|
281
|
+
.description("Remove HSM device")
|
|
282
|
+
.option("--json", "JSON output")
|
|
283
|
+
.action((id, opts) => {
|
|
284
|
+
const db = _dbFromCtx(tr);
|
|
285
|
+
const result = removeHsmDevice(db, id);
|
|
286
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
287
|
+
console.log(result.removed ? "HSM removed." : `Failed: ${result.reason}`);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
tr.command("hsm-show <id>")
|
|
291
|
+
.description("Show HSM device details")
|
|
292
|
+
.option("--json", "JSON output")
|
|
293
|
+
.action((id, opts) => {
|
|
294
|
+
const db = _dbFromCtx(tr);
|
|
295
|
+
const d = getHsmDevice(db, id);
|
|
296
|
+
if (!d) return console.log("Device not found.");
|
|
297
|
+
if (opts.json) return console.log(JSON.stringify(d, null, 2));
|
|
298
|
+
console.log(`ID: ${d.id}`);
|
|
299
|
+
console.log(`Vendor: ${d.vendor}`);
|
|
300
|
+
if (d.model) console.log(`Model: ${d.model}`);
|
|
301
|
+
if (d.serial_number) console.log(`Serial: ${d.serial_number}`);
|
|
302
|
+
if (d.compliance_level) console.log(`Compliance: ${d.compliance_level}`);
|
|
303
|
+
if (d.firmware_version) console.log(`Firmware: ${d.firmware_version}`);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
tr.command("hsm-devices")
|
|
307
|
+
.description("List HSM devices")
|
|
308
|
+
.option("-v, --vendor <name>", "Filter by vendor")
|
|
309
|
+
.option("--limit <n>", "Max results", parseInt)
|
|
310
|
+
.option("--json", "JSON output")
|
|
311
|
+
.action((opts) => {
|
|
312
|
+
const db = _dbFromCtx(tr);
|
|
313
|
+
const devs = listHsmDevices(db, {
|
|
314
|
+
vendor: opts.vendor,
|
|
315
|
+
limit: opts.limit,
|
|
316
|
+
});
|
|
317
|
+
if (opts.json) return console.log(JSON.stringify(devs, null, 2));
|
|
318
|
+
if (devs.length === 0) return console.log("No HSM devices.");
|
|
319
|
+
for (const d of devs) {
|
|
320
|
+
console.log(
|
|
321
|
+
` ${d.vendor.padEnd(10)} ${(d.model || "").padEnd(16)} ${(d.compliance_level || "").padEnd(12)} ${d.id.slice(0, 8)}`,
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
tr.command("hsm-sign <device-id>")
|
|
327
|
+
.description("Sign data with HSM")
|
|
328
|
+
.option("-d, --data <text>", "Data to sign")
|
|
329
|
+
.option("-a, --algorithm <algo>", "Algorithm")
|
|
330
|
+
.option("--json", "JSON output")
|
|
331
|
+
.action((deviceId, opts) => {
|
|
332
|
+
const db = _dbFromCtx(tr);
|
|
333
|
+
const result = signWithHsm(db, deviceId, {
|
|
334
|
+
data: opts.data,
|
|
335
|
+
algorithm: opts.algorithm,
|
|
336
|
+
});
|
|
337
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
338
|
+
if (result.signature) {
|
|
339
|
+
console.log(`Signature: ${result.signature}`);
|
|
340
|
+
console.log(`Algorithm: ${result.algorithm}`);
|
|
341
|
+
} else console.log(`Failed: ${result.reason}`);
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
/* ── Stats ───────────────────────────────────────── */
|
|
345
|
+
|
|
346
|
+
tr.command("stats")
|
|
347
|
+
.description("Trust & security statistics")
|
|
348
|
+
.option("--json", "JSON output")
|
|
349
|
+
.action((opts) => {
|
|
350
|
+
const db = _dbFromCtx(tr);
|
|
351
|
+
const s = getTrustSecurityStats(db);
|
|
352
|
+
if (opts.json) return console.log(JSON.stringify(s, null, 2));
|
|
353
|
+
console.log(
|
|
354
|
+
`Attestations: ${s.attestations.total} (${s.attestations.valid} valid)`,
|
|
355
|
+
);
|
|
356
|
+
console.log(
|
|
357
|
+
`PQC Tests: ${s.interopTests.total} (${s.interopTests.compatible} compatible, avg ${s.interopTests.avgLatencyMs}ms)`,
|
|
358
|
+
);
|
|
359
|
+
console.log(
|
|
360
|
+
`Satellite: ${s.satellite.total} (${s.satellite.queued} queued, ${s.satellite.confirmed} confirmed)`,
|
|
361
|
+
);
|
|
362
|
+
console.log(`HSM Devices: ${s.hsm.total}`);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
program.addCommand(tr);
|
|
366
|
+
}
|