chainlesschain 0.47.9 → 0.51.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/ipfs.js +392 -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/multimodal.js +404 -0
- 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 +118 -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/ipfs-storage.js +575 -0
- package/src/lib/knowledge-graph.js +530 -0
- package/src/lib/mcp-client.js +3 -0
- package/src/lib/multimodal.js +725 -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,473 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trust & Security — CLI port of Phase 68-71 信任安全系统
|
|
3
|
+
* (docs/design/modules/39_信任安全系统.md).
|
|
4
|
+
*
|
|
5
|
+
* Desktop uses TPM/TEE/SE hardware trust root, PQC migration manager,
|
|
6
|
+
* Iridium satellite comms, and multi-vendor HSM adapters.
|
|
7
|
+
* CLI port ships:
|
|
8
|
+
*
|
|
9
|
+
* - Trust attestation CRUD (TPM/TEE/SE anchors, simulated challenge-response)
|
|
10
|
+
* - PQC interop test records (algorithm compatibility tracking)
|
|
11
|
+
* - Satellite message queue (simulated send/confirm lifecycle)
|
|
12
|
+
* - HSM device registry (discover/sign simulation)
|
|
13
|
+
*
|
|
14
|
+
* What does NOT port: real TPM/TEE/SE hardware, actual PQC key exchange,
|
|
15
|
+
* real satellite transceivers, USB HSM drivers.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import crypto from "crypto";
|
|
19
|
+
|
|
20
|
+
/* ── Constants ─────────────────────────────────────────────── */
|
|
21
|
+
|
|
22
|
+
export const TRUST_ANCHOR = Object.freeze({
|
|
23
|
+
TPM: "tpm",
|
|
24
|
+
TEE: "tee",
|
|
25
|
+
SECURE_ELEMENT: "secure_element",
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const ATTESTATION_STATUS = Object.freeze({
|
|
29
|
+
VALID: "valid",
|
|
30
|
+
EXPIRED: "expired",
|
|
31
|
+
FAILED: "failed",
|
|
32
|
+
PENDING: "pending",
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export const SATELLITE_PROVIDER = Object.freeze({
|
|
36
|
+
IRIDIUM: "iridium",
|
|
37
|
+
STARLINK: "starlink",
|
|
38
|
+
BEIDOU: "beidou",
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export const SAT_MESSAGE_STATUS = Object.freeze({
|
|
42
|
+
QUEUED: "queued",
|
|
43
|
+
SENT: "sent",
|
|
44
|
+
CONFIRMED: "confirmed",
|
|
45
|
+
FAILED: "failed",
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export const HSM_VENDOR = Object.freeze({
|
|
49
|
+
YUBIKEY: "yubikey",
|
|
50
|
+
LEDGER: "ledger",
|
|
51
|
+
TREZOR: "trezor",
|
|
52
|
+
GENERIC: "generic",
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
export const COMPLIANCE_LEVEL = Object.freeze({
|
|
56
|
+
FIPS_140_2: "fips_140_2",
|
|
57
|
+
FIPS_140_3: "fips_140_3",
|
|
58
|
+
CC_EAL4: "cc_eal4",
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
/* ── State ─────────────────────────────────────────────── */
|
|
62
|
+
|
|
63
|
+
let _attestations = new Map();
|
|
64
|
+
let _interopTests = new Map();
|
|
65
|
+
let _satMessages = new Map();
|
|
66
|
+
let _hsmDevices = new Map();
|
|
67
|
+
|
|
68
|
+
function _id() {
|
|
69
|
+
return crypto.randomUUID();
|
|
70
|
+
}
|
|
71
|
+
function _now() {
|
|
72
|
+
return Date.now();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function _strip(row) {
|
|
76
|
+
if (!row) return null;
|
|
77
|
+
const out = {};
|
|
78
|
+
for (const [k, v] of Object.entries(row)) {
|
|
79
|
+
if (k !== "_rowid_" && k !== "rowid") out[k] = v;
|
|
80
|
+
}
|
|
81
|
+
return out;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* ── Schema ────────────────────────────────────────────── */
|
|
85
|
+
|
|
86
|
+
export function ensureTrustSecurityTables(db) {
|
|
87
|
+
db.exec(`CREATE TABLE IF NOT EXISTS trust_attestations (
|
|
88
|
+
id TEXT PRIMARY KEY,
|
|
89
|
+
anchor TEXT NOT NULL,
|
|
90
|
+
challenge TEXT,
|
|
91
|
+
response TEXT,
|
|
92
|
+
status TEXT DEFAULT 'pending',
|
|
93
|
+
device_fingerprint TEXT,
|
|
94
|
+
created_at INTEGER
|
|
95
|
+
)`);
|
|
96
|
+
|
|
97
|
+
db.exec(`CREATE TABLE IF NOT EXISTS pqc_interop_tests (
|
|
98
|
+
id TEXT PRIMARY KEY,
|
|
99
|
+
algorithm TEXT NOT NULL,
|
|
100
|
+
peer TEXT,
|
|
101
|
+
result TEXT,
|
|
102
|
+
compatible INTEGER DEFAULT 0,
|
|
103
|
+
latency_ms INTEGER,
|
|
104
|
+
created_at INTEGER
|
|
105
|
+
)`);
|
|
106
|
+
|
|
107
|
+
db.exec(`CREATE TABLE IF NOT EXISTS satellite_messages (
|
|
108
|
+
id TEXT PRIMARY KEY,
|
|
109
|
+
payload TEXT,
|
|
110
|
+
provider TEXT DEFAULT 'iridium',
|
|
111
|
+
priority INTEGER DEFAULT 5,
|
|
112
|
+
status TEXT DEFAULT 'queued',
|
|
113
|
+
sent_at INTEGER,
|
|
114
|
+
confirmed_at INTEGER,
|
|
115
|
+
created_at INTEGER
|
|
116
|
+
)`);
|
|
117
|
+
|
|
118
|
+
db.exec(`CREATE TABLE IF NOT EXISTS hsm_devices (
|
|
119
|
+
id TEXT PRIMARY KEY,
|
|
120
|
+
vendor TEXT NOT NULL,
|
|
121
|
+
model TEXT,
|
|
122
|
+
serial_number TEXT,
|
|
123
|
+
compliance_level TEXT,
|
|
124
|
+
firmware_version TEXT,
|
|
125
|
+
last_seen INTEGER,
|
|
126
|
+
created_at INTEGER
|
|
127
|
+
)`);
|
|
128
|
+
|
|
129
|
+
_loadAll(db);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function _loadAll(db) {
|
|
133
|
+
_attestations.clear();
|
|
134
|
+
_interopTests.clear();
|
|
135
|
+
_satMessages.clear();
|
|
136
|
+
_hsmDevices.clear();
|
|
137
|
+
|
|
138
|
+
const tables = [
|
|
139
|
+
["trust_attestations", _attestations],
|
|
140
|
+
["pqc_interop_tests", _interopTests],
|
|
141
|
+
["satellite_messages", _satMessages],
|
|
142
|
+
["hsm_devices", _hsmDevices],
|
|
143
|
+
];
|
|
144
|
+
for (const [table, map] of tables) {
|
|
145
|
+
try {
|
|
146
|
+
for (const row of db.prepare(`SELECT * FROM ${table}`).all()) {
|
|
147
|
+
const r = _strip(row);
|
|
148
|
+
map.set(r.id, r);
|
|
149
|
+
}
|
|
150
|
+
} catch (_e) {
|
|
151
|
+
/* table may not exist */
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/* ── Phase 68: Trust Root Attestation ──────────────────── */
|
|
157
|
+
|
|
158
|
+
const VALID_ANCHORS = new Set(Object.values(TRUST_ANCHOR));
|
|
159
|
+
|
|
160
|
+
export function attest(db, { anchor, challenge, deviceFingerprint } = {}) {
|
|
161
|
+
if (!anchor || !VALID_ANCHORS.has(anchor))
|
|
162
|
+
return { attestationId: null, reason: "invalid_anchor" };
|
|
163
|
+
|
|
164
|
+
const id = _id();
|
|
165
|
+
const now = _now();
|
|
166
|
+
const ch = challenge || crypto.randomBytes(32).toString("hex");
|
|
167
|
+
|
|
168
|
+
// Simulated attestation: TPM → always valid, TEE → valid, SE → valid
|
|
169
|
+
const response = crypto
|
|
170
|
+
.createHash("sha256")
|
|
171
|
+
.update(ch + anchor)
|
|
172
|
+
.digest("hex")
|
|
173
|
+
.slice(0, 32);
|
|
174
|
+
const status = "valid";
|
|
175
|
+
|
|
176
|
+
const att = {
|
|
177
|
+
id,
|
|
178
|
+
anchor,
|
|
179
|
+
challenge: ch,
|
|
180
|
+
response,
|
|
181
|
+
status,
|
|
182
|
+
device_fingerprint: deviceFingerprint || null,
|
|
183
|
+
created_at: now,
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
db.prepare(
|
|
187
|
+
`INSERT INTO trust_attestations (id, anchor, challenge, response, status, device_fingerprint, created_at)
|
|
188
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
189
|
+
).run(id, anchor, ch, response, status, att.device_fingerprint, now);
|
|
190
|
+
|
|
191
|
+
_attestations.set(id, att);
|
|
192
|
+
return { attestationId: id, status, response };
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export function getAttestation(db, id) {
|
|
196
|
+
const a = _attestations.get(id);
|
|
197
|
+
return a ? { ...a } : null;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export function listAttestations(db, { anchor, status, limit = 50 } = {}) {
|
|
201
|
+
let atts = [..._attestations.values()];
|
|
202
|
+
if (anchor) atts = atts.filter((a) => a.anchor === anchor);
|
|
203
|
+
if (status) atts = atts.filter((a) => a.status === status);
|
|
204
|
+
return atts
|
|
205
|
+
.sort((a, b) => b.created_at - a.created_at)
|
|
206
|
+
.slice(0, limit)
|
|
207
|
+
.map((a) => ({ ...a }));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/* ── Phase 69: PQC Interop Tests ──────────────────────── */
|
|
211
|
+
|
|
212
|
+
export function runInteropTest(db, algorithm, { peer, latencyMs } = {}) {
|
|
213
|
+
if (!algorithm) return { testId: null, reason: "missing_algorithm" };
|
|
214
|
+
|
|
215
|
+
const id = _id();
|
|
216
|
+
const now = _now();
|
|
217
|
+
|
|
218
|
+
// Simulated compatibility check
|
|
219
|
+
const supportedAlgos = [
|
|
220
|
+
"ml-kem-768",
|
|
221
|
+
"ml-kem-1024",
|
|
222
|
+
"ml-dsa-65",
|
|
223
|
+
"ml-dsa-87",
|
|
224
|
+
"slh-dsa-128s",
|
|
225
|
+
"slh-dsa-128f",
|
|
226
|
+
];
|
|
227
|
+
const compatible = supportedAlgos.includes(algorithm.toLowerCase()) ? 1 : 0;
|
|
228
|
+
const result = compatible ? "pass" : "unsupported";
|
|
229
|
+
const lat = latencyMs || Math.floor(Math.random() * 50 + 5);
|
|
230
|
+
|
|
231
|
+
const test = {
|
|
232
|
+
id,
|
|
233
|
+
algorithm,
|
|
234
|
+
peer: peer || null,
|
|
235
|
+
result,
|
|
236
|
+
compatible,
|
|
237
|
+
latency_ms: lat,
|
|
238
|
+
created_at: now,
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
db.prepare(
|
|
242
|
+
`INSERT INTO pqc_interop_tests (id, algorithm, peer, result, compatible, latency_ms, created_at)
|
|
243
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
244
|
+
).run(id, algorithm, test.peer, result, compatible, lat, now);
|
|
245
|
+
|
|
246
|
+
_interopTests.set(id, test);
|
|
247
|
+
return { testId: id, compatible: !!compatible, result, latencyMs: lat };
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export function listInteropTests(db, { algorithm, limit = 50 } = {}) {
|
|
251
|
+
let tests = [..._interopTests.values()];
|
|
252
|
+
if (algorithm)
|
|
253
|
+
tests = tests.filter(
|
|
254
|
+
(t) => t.algorithm.toLowerCase() === algorithm.toLowerCase(),
|
|
255
|
+
);
|
|
256
|
+
return tests
|
|
257
|
+
.sort((a, b) => b.created_at - a.created_at)
|
|
258
|
+
.slice(0, limit)
|
|
259
|
+
.map((t) => ({ ...t }));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/* ── Phase 70: Satellite Messages ─────────────────────── */
|
|
263
|
+
|
|
264
|
+
const VALID_SAT_PROVIDERS = new Set(Object.values(SATELLITE_PROVIDER));
|
|
265
|
+
|
|
266
|
+
export function sendSatelliteMessage(db, payload, { provider, priority } = {}) {
|
|
267
|
+
if (!payload) return { messageId: null, reason: "missing_payload" };
|
|
268
|
+
|
|
269
|
+
const prov = provider || "iridium";
|
|
270
|
+
if (!VALID_SAT_PROVIDERS.has(prov))
|
|
271
|
+
return { messageId: null, reason: "invalid_provider" };
|
|
272
|
+
|
|
273
|
+
const prio = Math.min(Math.max(priority || 5, 1), 10);
|
|
274
|
+
const id = _id();
|
|
275
|
+
const now = _now();
|
|
276
|
+
|
|
277
|
+
const msg = {
|
|
278
|
+
id,
|
|
279
|
+
payload,
|
|
280
|
+
provider: prov,
|
|
281
|
+
priority: prio,
|
|
282
|
+
status: "queued",
|
|
283
|
+
sent_at: null,
|
|
284
|
+
confirmed_at: null,
|
|
285
|
+
created_at: now,
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
db.prepare(
|
|
289
|
+
`INSERT INTO satellite_messages (id, payload, provider, priority, status, sent_at, confirmed_at, created_at)
|
|
290
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
291
|
+
).run(id, payload, prov, prio, "queued", null, null, now);
|
|
292
|
+
|
|
293
|
+
_satMessages.set(id, msg);
|
|
294
|
+
return { messageId: id };
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export function updateSatMessageStatus(db, id, status) {
|
|
298
|
+
const validTransitions = {
|
|
299
|
+
queued: ["sent", "failed"],
|
|
300
|
+
sent: ["confirmed", "failed"],
|
|
301
|
+
failed: ["queued"], // retry
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
const m = _satMessages.get(id);
|
|
305
|
+
if (!m) return { updated: false, reason: "not_found" };
|
|
306
|
+
|
|
307
|
+
const allowed = validTransitions[m.status];
|
|
308
|
+
if (!allowed || !allowed.includes(status))
|
|
309
|
+
return { updated: false, reason: "invalid_transition" };
|
|
310
|
+
|
|
311
|
+
m.status = status;
|
|
312
|
+
if (status === "sent") m.sent_at = _now();
|
|
313
|
+
if (status === "confirmed") m.confirmed_at = _now();
|
|
314
|
+
|
|
315
|
+
db.prepare(
|
|
316
|
+
"UPDATE satellite_messages SET status = ?, sent_at = ?, confirmed_at = ? WHERE id = ?",
|
|
317
|
+
).run(m.status, m.sent_at, m.confirmed_at, id);
|
|
318
|
+
|
|
319
|
+
return { updated: true };
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export function getSatMessage(db, id) {
|
|
323
|
+
const m = _satMessages.get(id);
|
|
324
|
+
return m ? { ...m } : null;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export function listSatMessages(db, { provider, status, limit = 50 } = {}) {
|
|
328
|
+
let msgs = [..._satMessages.values()];
|
|
329
|
+
if (provider) msgs = msgs.filter((m) => m.provider === provider);
|
|
330
|
+
if (status) msgs = msgs.filter((m) => m.status === status);
|
|
331
|
+
return msgs
|
|
332
|
+
.sort((a, b) => b.created_at - a.created_at)
|
|
333
|
+
.slice(0, limit)
|
|
334
|
+
.map((m) => ({ ...m }));
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/* ── Phase 71: HSM Devices ────────────────────────────── */
|
|
338
|
+
|
|
339
|
+
const VALID_HSM_VENDORS = new Set(Object.values(HSM_VENDOR));
|
|
340
|
+
|
|
341
|
+
export function registerHsmDevice(
|
|
342
|
+
db,
|
|
343
|
+
vendor,
|
|
344
|
+
{ model, serialNumber, complianceLevel, firmwareVersion } = {},
|
|
345
|
+
) {
|
|
346
|
+
if (!vendor || !VALID_HSM_VENDORS.has(vendor))
|
|
347
|
+
return { deviceId: null, reason: "invalid_vendor" };
|
|
348
|
+
|
|
349
|
+
const id = _id();
|
|
350
|
+
const now = _now();
|
|
351
|
+
|
|
352
|
+
const dev = {
|
|
353
|
+
id,
|
|
354
|
+
vendor,
|
|
355
|
+
model: model || null,
|
|
356
|
+
serial_number: serialNumber || null,
|
|
357
|
+
compliance_level: complianceLevel || null,
|
|
358
|
+
firmware_version: firmwareVersion || null,
|
|
359
|
+
last_seen: now,
|
|
360
|
+
created_at: now,
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
db.prepare(
|
|
364
|
+
`INSERT INTO hsm_devices (id, vendor, model, serial_number, compliance_level, firmware_version, last_seen, created_at)
|
|
365
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
366
|
+
).run(
|
|
367
|
+
id,
|
|
368
|
+
vendor,
|
|
369
|
+
dev.model,
|
|
370
|
+
dev.serial_number,
|
|
371
|
+
dev.compliance_level,
|
|
372
|
+
dev.firmware_version,
|
|
373
|
+
now,
|
|
374
|
+
now,
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
_hsmDevices.set(id, dev);
|
|
378
|
+
return { deviceId: id };
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
export function removeHsmDevice(db, id) {
|
|
382
|
+
const d = _hsmDevices.get(id);
|
|
383
|
+
if (!d) return { removed: false, reason: "not_found" };
|
|
384
|
+
db.prepare("DELETE FROM hsm_devices WHERE id = ?").run(id);
|
|
385
|
+
_hsmDevices.delete(id);
|
|
386
|
+
return { removed: true };
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
export function getHsmDevice(db, id) {
|
|
390
|
+
const d = _hsmDevices.get(id);
|
|
391
|
+
return d ? { ...d } : null;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export function listHsmDevices(db, { vendor, limit = 50 } = {}) {
|
|
395
|
+
let devs = [..._hsmDevices.values()];
|
|
396
|
+
if (vendor) devs = devs.filter((d) => d.vendor === vendor);
|
|
397
|
+
return devs
|
|
398
|
+
.sort((a, b) => b.last_seen - a.last_seen)
|
|
399
|
+
.slice(0, limit)
|
|
400
|
+
.map((d) => ({ ...d }));
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
export function signWithHsm(db, deviceId, { data, algorithm } = {}) {
|
|
404
|
+
const d = _hsmDevices.get(deviceId);
|
|
405
|
+
if (!d) return { signature: null, reason: "device_not_found" };
|
|
406
|
+
if (!data) return { signature: null, reason: "missing_data" };
|
|
407
|
+
|
|
408
|
+
// Simulated HSM signature
|
|
409
|
+
const algo = algorithm || "ecdsa-p256";
|
|
410
|
+
const sig = crypto
|
|
411
|
+
.createHash("sha256")
|
|
412
|
+
.update(data + d.id + algo)
|
|
413
|
+
.digest("hex");
|
|
414
|
+
|
|
415
|
+
d.last_seen = _now();
|
|
416
|
+
db.prepare("UPDATE hsm_devices SET last_seen = ? WHERE id = ?").run(
|
|
417
|
+
d.last_seen,
|
|
418
|
+
deviceId,
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
return { signature: sig, algorithm: algo, deviceId };
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/* ── Stats ─────────────────────────────────────────────── */
|
|
425
|
+
|
|
426
|
+
export function getTrustSecurityStats(db) {
|
|
427
|
+
const atts = [..._attestations.values()];
|
|
428
|
+
const tests = [..._interopTests.values()];
|
|
429
|
+
const msgs = [..._satMessages.values()];
|
|
430
|
+
const devs = [..._hsmDevices.values()];
|
|
431
|
+
|
|
432
|
+
return {
|
|
433
|
+
attestations: {
|
|
434
|
+
total: atts.length,
|
|
435
|
+
valid: atts.filter((a) => a.status === "valid").length,
|
|
436
|
+
byAnchor: atts.reduce((acc, a) => {
|
|
437
|
+
acc[a.anchor] = (acc[a.anchor] || 0) + 1;
|
|
438
|
+
return acc;
|
|
439
|
+
}, {}),
|
|
440
|
+
},
|
|
441
|
+
interopTests: {
|
|
442
|
+
total: tests.length,
|
|
443
|
+
compatible: tests.filter((t) => t.compatible).length,
|
|
444
|
+
avgLatencyMs:
|
|
445
|
+
tests.length > 0
|
|
446
|
+
? Math.round(
|
|
447
|
+
tests.reduce((s, t) => s + (t.latency_ms || 0), 0) / tests.length,
|
|
448
|
+
)
|
|
449
|
+
: 0,
|
|
450
|
+
},
|
|
451
|
+
satellite: {
|
|
452
|
+
total: msgs.length,
|
|
453
|
+
queued: msgs.filter((m) => m.status === "queued").length,
|
|
454
|
+
confirmed: msgs.filter((m) => m.status === "confirmed").length,
|
|
455
|
+
},
|
|
456
|
+
hsm: {
|
|
457
|
+
total: devs.length,
|
|
458
|
+
byVendor: devs.reduce((acc, d) => {
|
|
459
|
+
acc[d.vendor] = (acc[d.vendor] || 0) + 1;
|
|
460
|
+
return acc;
|
|
461
|
+
}, {}),
|
|
462
|
+
},
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/* ── Reset (tests) ─────────────────────────────────────── */
|
|
467
|
+
|
|
468
|
+
export function _resetState() {
|
|
469
|
+
_attestations.clear();
|
|
470
|
+
_interopTests.clear();
|
|
471
|
+
_satMessages.clear();
|
|
472
|
+
_hsmDevices.clear();
|
|
473
|
+
}
|