chainlesschain 0.51.0 → 0.81.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.
Files changed (70) hide show
  1. package/package.json +1 -1
  2. package/src/assets/web-panel/.build-hash +1 -1
  3. package/src/assets/web-panel/assets/{AppLayout-Rvi759IS.js → AppLayout-6SPt_8Y_.js} +1 -1
  4. package/src/assets/web-panel/assets/{Dashboard-DBhFxXYQ.js → Dashboard-Br7kCwKJ.js} +2 -2
  5. package/src/assets/web-panel/assets/Dashboard-CKeMmCoT.css +1 -0
  6. package/src/assets/web-panel/assets/{index-uL0cZ8N_.js → index-tN-8TosE.js} +2 -2
  7. package/src/assets/web-panel/index.html +2 -2
  8. package/src/commands/a2a.js +380 -0
  9. package/src/commands/agent-network.js +785 -0
  10. package/src/commands/automation.js +654 -0
  11. package/src/commands/bi.js +348 -0
  12. package/src/commands/crosschain.js +218 -0
  13. package/src/commands/dao.js +565 -0
  14. package/src/commands/did-v2.js +620 -0
  15. package/src/commands/dlp.js +341 -0
  16. package/src/commands/economy.js +578 -0
  17. package/src/commands/evolution.js +391 -0
  18. package/src/commands/evomap.js +394 -0
  19. package/src/commands/federation.js +283 -0
  20. package/src/commands/hmemory.js +442 -0
  21. package/src/commands/inference.js +318 -0
  22. package/src/commands/lowcode.js +356 -0
  23. package/src/commands/marketplace.js +256 -0
  24. package/src/commands/perf.js +433 -0
  25. package/src/commands/pipeline.js +449 -0
  26. package/src/commands/plugin-ecosystem.js +517 -0
  27. package/src/commands/privacy.js +321 -0
  28. package/src/commands/reputation.js +261 -0
  29. package/src/commands/sandbox.js +401 -0
  30. package/src/commands/siem.js +246 -0
  31. package/src/commands/sla.js +259 -0
  32. package/src/commands/social.js +311 -0
  33. package/src/commands/sso.js +798 -0
  34. package/src/commands/stress.js +230 -0
  35. package/src/commands/terraform.js +245 -0
  36. package/src/commands/workflow.js +320 -0
  37. package/src/commands/zkp.js +562 -1
  38. package/src/index.js +21 -0
  39. package/src/lib/a2a-protocol.js +451 -0
  40. package/src/lib/agent-economy.js +479 -0
  41. package/src/lib/agent-network.js +1121 -0
  42. package/src/lib/app-builder.js +239 -0
  43. package/src/lib/automation-engine.js +948 -0
  44. package/src/lib/bi-engine.js +338 -0
  45. package/src/lib/cross-chain.js +345 -0
  46. package/src/lib/dao-governance.js +569 -0
  47. package/src/lib/did-v2-manager.js +1127 -0
  48. package/src/lib/dlp-engine.js +389 -0
  49. package/src/lib/evolution-system.js +453 -0
  50. package/src/lib/evomap-federation.js +177 -0
  51. package/src/lib/evomap-governance.js +276 -0
  52. package/src/lib/federation-hardening.js +259 -0
  53. package/src/lib/hierarchical-memory.js +481 -0
  54. package/src/lib/inference-network.js +330 -0
  55. package/src/lib/perf-tuning.js +734 -0
  56. package/src/lib/pipeline-orchestrator.js +928 -0
  57. package/src/lib/plugin-ecosystem.js +1109 -0
  58. package/src/lib/privacy-computing.js +427 -0
  59. package/src/lib/reputation-optimizer.js +299 -0
  60. package/src/lib/sandbox-v2.js +306 -0
  61. package/src/lib/siem-exporter.js +333 -0
  62. package/src/lib/skill-marketplace.js +325 -0
  63. package/src/lib/sla-manager.js +275 -0
  64. package/src/lib/social-graph-analytics.js +707 -0
  65. package/src/lib/sso-manager.js +841 -0
  66. package/src/lib/stress-tester.js +330 -0
  67. package/src/lib/terraform-manager.js +363 -0
  68. package/src/lib/workflow-engine.js +454 -1
  69. package/src/lib/zkp-engine.js +523 -20
  70. package/src/assets/web-panel/assets/Dashboard-BS-tzGNj.css +0 -1
@@ -1,16 +1,34 @@
1
1
  /**
2
2
  * ZKP Engine — Zero-knowledge proof circuit compilation, proof generation,
3
- * verification, and selective identity disclosure.
3
+ * verification, and selective identity disclosure (Phase 88).
4
4
  */
5
5
 
6
6
  import crypto from "crypto";
7
7
 
8
+ /* ── Phase 88 frozen enums ─────────────────────────────────── */
9
+
10
+ export const PROOF_SCHEME = Object.freeze({
11
+ GROTH16: "groth16",
12
+ PLONK: "plonk",
13
+ BULLETPROOFS: "bulletproofs",
14
+ });
15
+
16
+ export const CIRCUIT_STATUS = Object.freeze({
17
+ DRAFT: "draft",
18
+ COMPILED: "compiled",
19
+ VERIFIED: "verified",
20
+ FAILED: "failed",
21
+ });
22
+
23
+ export const SUPPORTED_SCHEMES = new Set(Object.values(PROOF_SCHEME));
24
+
8
25
  /* ── In-memory stores ──────────────────────────────────────── */
9
26
  const _circuits = new Map();
10
27
  const _proofs = new Map();
11
28
  const _verificationKeys = new Map();
29
+ const _credentials = new Map();
12
30
 
13
- const DEFAULT_SCHEME = "groth16";
31
+ const DEFAULT_SCHEME = PROOF_SCHEME.GROTH16;
14
32
 
15
33
  /* ── Schema ────────────────────────────────────────────────── */
16
34
 
@@ -22,6 +40,7 @@ export function ensureZKPTables(db) {
22
40
  definition TEXT,
23
41
  compiled TEXT,
24
42
  verification_key TEXT,
43
+ status TEXT DEFAULT 'draft',
25
44
  created_at TEXT DEFAULT (datetime('now'))
26
45
  )
27
46
  `);
@@ -36,6 +55,15 @@ export function ensureZKPTables(db) {
36
55
  created_at TEXT DEFAULT (datetime('now'))
37
56
  )
38
57
  `);
58
+ db.exec(`
59
+ CREATE TABLE IF NOT EXISTS zkp_credentials (
60
+ id TEXT PRIMARY KEY,
61
+ did TEXT,
62
+ claims TEXT NOT NULL,
63
+ merkle_root TEXT NOT NULL,
64
+ created_at TEXT DEFAULT (datetime('now'))
65
+ )
66
+ `);
39
67
  }
40
68
 
41
69
  /* ── Circuit Compilation ───────────────────────────────────── */
@@ -82,6 +110,7 @@ export function compileCircuit(db, name, definition) {
82
110
  inputs,
83
111
  outputs,
84
112
  verificationKey,
113
+ status: CIRCUIT_STATUS.COMPILED,
85
114
  createdAt: now,
86
115
  };
87
116
 
@@ -89,40 +118,87 @@ export function compileCircuit(db, name, definition) {
89
118
  _verificationKeys.set(id, verificationKey);
90
119
 
91
120
  db.prepare(
92
- `INSERT INTO zkp_circuits (id, name, definition, compiled, verification_key, created_at)
93
- VALUES (?, ?, ?, ?, ?, ?)`,
121
+ `INSERT INTO zkp_circuits (id, name, definition, compiled, verification_key, status, created_at)
122
+ VALUES (?, ?, ?, ?, ?, ?, ?)`,
94
123
  ).run(
95
124
  id,
96
125
  name,
97
126
  JSON.stringify(parsed),
98
127
  JSON.stringify(compiled),
99
128
  verificationKey,
129
+ CIRCUIT_STATUS.COMPILED,
100
130
  now,
101
131
  );
102
132
 
103
133
  return circuit;
104
134
  }
105
135
 
136
+ /**
137
+ * Update a circuit's status (DRAFT / COMPILED / VERIFIED / FAILED).
138
+ */
139
+ export function setCircuitStatus(db, circuitId, status) {
140
+ if (!Object.values(CIRCUIT_STATUS).includes(status)) {
141
+ throw new Error(`Invalid circuit status: ${status}`);
142
+ }
143
+ const circuit = _circuits.get(circuitId);
144
+ if (!circuit) throw new Error(`Circuit not found: ${circuitId}`);
145
+ circuit.status = status;
146
+ db.prepare("UPDATE zkp_circuits SET status = ? WHERE id = ?").run(
147
+ status,
148
+ circuitId,
149
+ );
150
+ return { id: circuitId, status };
151
+ }
152
+
106
153
  /* ── Proof Generation ──────────────────────────────────────── */
107
154
 
108
- export function generateProof(db, circuitId, privateInputs, publicInputs) {
155
+ export function generateProof(
156
+ db,
157
+ circuitId,
158
+ privateInputs,
159
+ publicInputs,
160
+ options = {},
161
+ ) {
109
162
  const circuit = _circuits.get(circuitId);
110
163
  if (!circuit) throw new Error(`Circuit not found: ${circuitId}`);
111
164
 
165
+ const scheme = options.scheme || DEFAULT_SCHEME;
166
+ if (!SUPPORTED_SCHEMES.has(scheme)) {
167
+ throw new Error(
168
+ `Unsupported proof scheme: ${scheme}. Supported: ${[...SUPPORTED_SCHEMES].join(", ")}`,
169
+ );
170
+ }
171
+
112
172
  const id = crypto.randomUUID();
113
173
  const now = new Date().toISOString();
114
174
 
115
- // Mock zk-SNARK proof with {a, b, c} components (Groth16 structure)
116
- const proofData = {
117
- a: crypto.randomBytes(32).toString("hex"),
118
- b: crypto.randomBytes(64).toString("hex"),
119
- c: crypto.randomBytes(32).toString("hex"),
120
- };
175
+ // Scheme-shaped mock proof structure
176
+ let proofData;
177
+ if (scheme === PROOF_SCHEME.GROTH16) {
178
+ proofData = {
179
+ a: crypto.randomBytes(32).toString("hex"),
180
+ b: crypto.randomBytes(64).toString("hex"),
181
+ c: crypto.randomBytes(32).toString("hex"),
182
+ };
183
+ } else if (scheme === PROOF_SCHEME.PLONK) {
184
+ proofData = {
185
+ commitments: crypto.randomBytes(96).toString("hex"),
186
+ evaluations: crypto.randomBytes(64).toString("hex"),
187
+ };
188
+ } else {
189
+ // bulletproofs — range proof shape
190
+ proofData = {
191
+ V: crypto.randomBytes(32).toString("hex"),
192
+ A: crypto.randomBytes(32).toString("hex"),
193
+ S: crypto.randomBytes(32).toString("hex"),
194
+ t1: crypto.randomBytes(32).toString("hex"),
195
+ };
196
+ }
121
197
 
122
198
  const proof = {
123
199
  id,
124
200
  circuitId,
125
- scheme: DEFAULT_SCHEME,
201
+ scheme,
126
202
  proof: proofData,
127
203
  publicInputs: publicInputs || [],
128
204
  verified: false,
@@ -140,7 +216,7 @@ export function generateProof(db, circuitId, privateInputs, publicInputs) {
140
216
  JSON.stringify(proofData),
141
217
  JSON.stringify(publicInputs || []),
142
218
  0,
143
- DEFAULT_SCHEME,
219
+ scheme,
144
220
  now,
145
221
  );
146
222
 
@@ -156,13 +232,27 @@ export function verifyProof(db, proofId) {
156
232
  const circuit = _circuits.get(proof.circuitId);
157
233
  if (!circuit) throw new Error(`Circuit not found for proof: ${proofId}`);
158
234
 
159
- // Mock verification — check proof structure is valid
160
- const valid =
161
- proof.proof &&
162
- typeof proof.proof.a === "string" &&
163
- typeof proof.proof.b === "string" &&
164
- typeof proof.proof.c === "string" &&
165
- _verificationKeys.has(proof.circuitId);
235
+ // Scheme-aware structural validation
236
+ let structurallyValid = false;
237
+ if (proof.scheme === PROOF_SCHEME.GROTH16) {
238
+ structurallyValid =
239
+ proof.proof &&
240
+ typeof proof.proof.a === "string" &&
241
+ typeof proof.proof.b === "string" &&
242
+ typeof proof.proof.c === "string";
243
+ } else if (proof.scheme === PROOF_SCHEME.PLONK) {
244
+ structurallyValid =
245
+ proof.proof &&
246
+ typeof proof.proof.commitments === "string" &&
247
+ typeof proof.proof.evaluations === "string";
248
+ } else if (proof.scheme === PROOF_SCHEME.BULLETPROOFS) {
249
+ structurallyValid =
250
+ proof.proof &&
251
+ typeof proof.proof.V === "string" &&
252
+ typeof proof.proof.A === "string";
253
+ }
254
+
255
+ const valid = structurallyValid && _verificationKeys.has(proof.circuitId);
166
256
 
167
257
  proof.verified = valid;
168
258
 
@@ -207,14 +297,152 @@ export function createIdentityProof(claims, disclosedFields) {
207
297
  };
208
298
  }
209
299
 
300
+ /* ── Credentials + Merkle-tree selective disclosure ──────────── */
301
+
302
+ /**
303
+ * Compute a deterministic Merkle root over sorted (field, hash(value)) leaves.
304
+ * Each leaf = sha256(fieldName + ":" + sha256(stringified-value)).
305
+ * Pairs combine as sha256(left + right), odd leaves are duplicated (standard).
306
+ */
307
+ function _merkleRoot(claims) {
308
+ const fields = Object.keys(claims).sort();
309
+ if (fields.length === 0) {
310
+ return crypto.createHash("sha256").update("").digest("hex");
311
+ }
312
+
313
+ let level = fields.map((field) => {
314
+ const valHash = crypto
315
+ .createHash("sha256")
316
+ .update(JSON.stringify(claims[field]))
317
+ .digest("hex");
318
+ return crypto
319
+ .createHash("sha256")
320
+ .update(`${field}:${valHash}`)
321
+ .digest("hex");
322
+ });
323
+
324
+ while (level.length > 1) {
325
+ const next = [];
326
+ for (let i = 0; i < level.length; i += 2) {
327
+ const left = level[i];
328
+ const right = i + 1 < level.length ? level[i + 1] : left;
329
+ next.push(
330
+ crypto
331
+ .createHash("sha256")
332
+ .update(left + right)
333
+ .digest("hex"),
334
+ );
335
+ }
336
+ level = next;
337
+ }
338
+ return level[0];
339
+ }
340
+
341
+ /**
342
+ * Register a verifiable credential. Returns `{ id, did, merkleRoot, claims }`.
343
+ */
344
+ export function registerCredential(db, { did, claims }) {
345
+ if (!claims || typeof claims !== "object") {
346
+ throw new Error("Claims must be an object");
347
+ }
348
+ const id = crypto.randomUUID();
349
+ const now = new Date().toISOString();
350
+ const merkleRoot = _merkleRoot(claims);
351
+
352
+ const credential = {
353
+ id,
354
+ did: did || null,
355
+ claims,
356
+ merkleRoot,
357
+ createdAt: now,
358
+ };
359
+ _credentials.set(id, credential);
360
+
361
+ db.prepare(
362
+ `INSERT INTO zkp_credentials (id, did, claims, merkle_root, created_at)
363
+ VALUES (?, ?, ?, ?, ?)`,
364
+ ).run(id, did || null, JSON.stringify(claims), merkleRoot, now);
365
+
366
+ return credential;
367
+ }
368
+
369
+ /**
370
+ * Selectively disclose a subset of credential fields to a recipient.
371
+ * Returns `{ id, credentialId, recipientDid, disclosed, merkleRoot, hiddenCount }`.
372
+ * The receiver can recompute the Merkle root (given hashed pads for hidden fields)
373
+ * and match it against the credential's merkleRoot to confirm integrity.
374
+ */
375
+ export function selectiveDisclose(
376
+ db,
377
+ credentialId,
378
+ disclosedFields,
379
+ recipientDid = null,
380
+ ) {
381
+ const credential = _credentials.get(credentialId);
382
+ if (!credential) {
383
+ throw new Error(`Credential not found: ${credentialId}`);
384
+ }
385
+ if (!Array.isArray(disclosedFields)) {
386
+ throw new Error("disclosedFields must be an array");
387
+ }
388
+
389
+ const allFields = Object.keys(credential.claims);
390
+ const disclosed = {};
391
+ const hiddenFields = [];
392
+
393
+ for (const field of allFields) {
394
+ if (disclosedFields.includes(field)) {
395
+ disclosed[field] = credential.claims[field];
396
+ } else {
397
+ hiddenFields.push(field);
398
+ }
399
+ }
400
+
401
+ return {
402
+ id: crypto.randomUUID(),
403
+ type: "selective-disclosure",
404
+ credentialId,
405
+ recipientDid,
406
+ disclosed,
407
+ hiddenCount: hiddenFields.length,
408
+ hiddenFields,
409
+ merkleRoot: credential.merkleRoot,
410
+ disclosedAt: new Date().toISOString(),
411
+ };
412
+ }
413
+
414
+ /**
415
+ * List registered credentials, optionally filtered by DID.
416
+ */
417
+ export function listCredentials(db, options = {}) {
418
+ let creds = [..._credentials.values()];
419
+ if (options.did) {
420
+ creds = creds.filter((c) => c.did === options.did);
421
+ }
422
+ return creds;
423
+ }
424
+
210
425
  /* ── Stats ─────────────────────────────────────────────────── */
211
426
 
212
427
  export function getZKPStats() {
213
428
  const proofList = [..._proofs.values()];
429
+ const bySchemeCount = {};
430
+ for (const scheme of Object.values(PROOF_SCHEME)) {
431
+ bySchemeCount[scheme] = proofList.filter((p) => p.scheme === scheme).length;
432
+ }
433
+ const byStatusCount = {};
434
+ for (const status of Object.values(CIRCUIT_STATUS)) {
435
+ byStatusCount[status] = [..._circuits.values()].filter(
436
+ (c) => c.status === status,
437
+ ).length;
438
+ }
214
439
  return {
215
440
  circuits: _circuits.size,
216
441
  proofs: proofList.length,
217
442
  verifiedProofs: proofList.filter((p) => p.verified).length,
443
+ credentials: _credentials.size,
444
+ proofsByScheme: bySchemeCount,
445
+ circuitsByStatus: byStatusCount,
218
446
  };
219
447
  }
220
448
 
@@ -238,4 +466,279 @@ export function _resetState() {
238
466
  _circuits.clear();
239
467
  _proofs.clear();
240
468
  _verificationKeys.clear();
469
+ _credentials.clear();
470
+ _maxCircuitsPerCreator = ZKP_DEFAULT_MAX_CIRCUITS_PER_CREATOR;
471
+ _proofExpiryMs = ZKP_DEFAULT_PROOF_EXPIRY_MS;
472
+ }
473
+
474
+ /* ──────────────────────────────────────────────────────────
475
+ * V2 — Phase 88 surface (strictly additive)
476
+ * ────────────────────────────────────────────────────────── */
477
+
478
+ export const PROOF_SCHEME_V2 = PROOF_SCHEME;
479
+ export const CIRCUIT_STATUS_V2 = CIRCUIT_STATUS;
480
+
481
+ export const PROOF_STATUS_V2 = Object.freeze({
482
+ PENDING: "pending",
483
+ VERIFIED: "verified",
484
+ INVALID: "invalid",
485
+ EXPIRED: "expired",
486
+ });
487
+
488
+ export const ZKP_DEFAULT_MAX_CIRCUITS_PER_CREATOR = 10;
489
+ export const ZKP_DEFAULT_PROOF_EXPIRY_MS = 3600_000; // 1h
490
+
491
+ let _maxCircuitsPerCreator = ZKP_DEFAULT_MAX_CIRCUITS_PER_CREATOR;
492
+ let _proofExpiryMs = ZKP_DEFAULT_PROOF_EXPIRY_MS;
493
+
494
+ const CIRCUIT_TRANSITIONS_V2 = new Map([
495
+ ["draft", new Set(["compiled", "failed"])],
496
+ ["compiled", new Set(["verified", "failed"])],
497
+ ]);
498
+ const CIRCUIT_TERMINALS_V2 = new Set(["verified", "failed"]);
499
+
500
+ const PROOF_TRANSITIONS_V2 = new Map([
501
+ ["pending", new Set(["verified", "invalid", "expired"])],
502
+ ]);
503
+ const PROOF_TERMINALS_V2 = new Set(["verified", "invalid", "expired"]);
504
+
505
+ /* ── Config ────────────────────────────────────────────── */
506
+
507
+ export function setMaxCircuitsPerCreator(n) {
508
+ if (typeof n !== "number" || Number.isNaN(n) || n < 1) {
509
+ throw new Error("maxCircuitsPerCreator must be a positive integer");
510
+ }
511
+ _maxCircuitsPerCreator = Math.floor(n);
512
+ }
513
+
514
+ export function getMaxCircuitsPerCreator() {
515
+ return _maxCircuitsPerCreator;
516
+ }
517
+
518
+ export function getCircuitCountByCreator(creator) {
519
+ if (!creator) return 0;
520
+ let count = 0;
521
+ for (const c of _circuits.values()) {
522
+ if (c.creator === creator) count += 1;
523
+ }
524
+ return count;
525
+ }
526
+
527
+ export function setProofExpiryMs(ms) {
528
+ if (typeof ms !== "number" || Number.isNaN(ms) || ms < 1) {
529
+ throw new Error("proofExpiryMs must be a positive integer");
530
+ }
531
+ _proofExpiryMs = Math.floor(ms);
532
+ }
533
+
534
+ export function getProofExpiryMs() {
535
+ return _proofExpiryMs;
536
+ }
537
+
538
+ /* ── Circuit V2 ────────────────────────────────────────── */
539
+
540
+ export function compileCircuitV2(db, { name, definition, creator } = {}) {
541
+ if (!name) throw new Error("name is required");
542
+ if (creator) {
543
+ const count = getCircuitCountByCreator(creator);
544
+ if (count >= _maxCircuitsPerCreator) {
545
+ throw new Error(
546
+ `Max circuits per creator reached (${count}/${_maxCircuitsPerCreator})`,
547
+ );
548
+ }
549
+ }
550
+ const circuit = compileCircuit(db, name, definition);
551
+ if (creator) {
552
+ circuit.creator = creator;
553
+ }
554
+ return { ...circuit };
555
+ }
556
+
557
+ export function setCircuitStatusV2(db, circuitId, newStatus, patch = {}) {
558
+ const circuit = _circuits.get(circuitId);
559
+ if (!circuit) throw new Error(`Circuit not found: ${circuitId}`);
560
+ if (!Object.values(CIRCUIT_STATUS_V2).includes(newStatus)) {
561
+ throw new Error(`Unknown circuit status: ${newStatus}`);
562
+ }
563
+ const allowed = CIRCUIT_TRANSITIONS_V2.get(circuit.status);
564
+ if (!allowed || !allowed.has(newStatus)) {
565
+ throw new Error(`Invalid transition: ${circuit.status} → ${newStatus}`);
566
+ }
567
+ circuit.status = newStatus;
568
+ if (patch.errorMessage !== undefined)
569
+ circuit.errorMessage = patch.errorMessage;
570
+ db.prepare("UPDATE zkp_circuits SET status = ? WHERE id = ?").run(
571
+ newStatus,
572
+ circuitId,
573
+ );
574
+ return { ...circuit };
575
+ }
576
+
577
+ /* ── Proof V2 ──────────────────────────────────────────── */
578
+
579
+ export function generateProofV2(
580
+ db,
581
+ { circuitId, privateInputs, publicInputs, scheme } = {},
582
+ ) {
583
+ if (!circuitId) throw new Error("circuitId is required");
584
+ const circuit = _circuits.get(circuitId);
585
+ if (!circuit) throw new Error(`Circuit not found: ${circuitId}`);
586
+ if (
587
+ circuit.status !== CIRCUIT_STATUS.COMPILED &&
588
+ circuit.status !== CIRCUIT_STATUS.VERIFIED
589
+ ) {
590
+ throw new Error(
591
+ `Circuit not ready (status=${circuit.status}, must be compiled/verified)`,
592
+ );
593
+ }
594
+ const proof = generateProof(db, circuitId, privateInputs, publicInputs, {
595
+ scheme,
596
+ });
597
+ const stored = _proofs.get(proof.id);
598
+ stored.status = PROOF_STATUS_V2.PENDING;
599
+ stored.expiresAt = Date.now() + _proofExpiryMs;
600
+ return { ...stored };
601
+ }
602
+
603
+ export function verifyProofV2(db, proofId) {
604
+ const proof = _proofs.get(proofId);
605
+ if (!proof) throw new Error(`Proof not found: ${proofId}`);
606
+ const current = proof.status || PROOF_STATUS_V2.PENDING;
607
+ if (PROOF_TERMINALS_V2.has(current)) {
608
+ throw new Error(`Invalid transition: ${current} → verify (terminal)`);
609
+ }
610
+ if (proof.expiresAt && Date.now() > proof.expiresAt) {
611
+ proof.status = PROOF_STATUS_V2.EXPIRED;
612
+ db.prepare("UPDATE zkp_proofs SET verified = 0 WHERE id = ?").run(proofId);
613
+ return { ...proof, valid: false, reason: "expired" };
614
+ }
615
+ const result = verifyProof(db, proofId);
616
+ proof.status = result.valid
617
+ ? PROOF_STATUS_V2.VERIFIED
618
+ : PROOF_STATUS_V2.INVALID;
619
+ return { ...proof, valid: result.valid };
620
+ }
621
+
622
+ export function failProof(db, proofId, { reason } = {}) {
623
+ const proof = _proofs.get(proofId);
624
+ if (!proof) throw new Error(`Proof not found: ${proofId}`);
625
+ const current = proof.status || PROOF_STATUS_V2.PENDING;
626
+ if (PROOF_TERMINALS_V2.has(current)) {
627
+ throw new Error(`Invalid transition: ${current} → invalid (terminal)`);
628
+ }
629
+ proof.status = PROOF_STATUS_V2.INVALID;
630
+ proof.verified = false;
631
+ if (reason !== undefined) proof.errorMessage = reason;
632
+ db.prepare("UPDATE zkp_proofs SET verified = 0 WHERE id = ?").run(proofId);
633
+ return { ...proof };
634
+ }
635
+
636
+ export function setProofStatus(db, proofId, newStatus, patch = {}) {
637
+ const proof = _proofs.get(proofId);
638
+ if (!proof) throw new Error(`Proof not found: ${proofId}`);
639
+ if (!Object.values(PROOF_STATUS_V2).includes(newStatus)) {
640
+ throw new Error(`Unknown proof status: ${newStatus}`);
641
+ }
642
+ const current = proof.status || PROOF_STATUS_V2.PENDING;
643
+ const allowed = PROOF_TRANSITIONS_V2.get(current);
644
+ if (!allowed || !allowed.has(newStatus)) {
645
+ throw new Error(`Invalid transition: ${current} → ${newStatus}`);
646
+ }
647
+ proof.status = newStatus;
648
+ if (patch.errorMessage !== undefined) proof.errorMessage = patch.errorMessage;
649
+ if (newStatus === PROOF_STATUS_V2.VERIFIED) {
650
+ proof.verified = true;
651
+ db.prepare("UPDATE zkp_proofs SET verified = 1 WHERE id = ?").run(proofId);
652
+ } else {
653
+ proof.verified = false;
654
+ db.prepare("UPDATE zkp_proofs SET verified = 0 WHERE id = ?").run(proofId);
655
+ }
656
+ return { ...proof };
657
+ }
658
+
659
+ export function autoExpireProofs(db) {
660
+ const now = Date.now();
661
+ const expired = [];
662
+ for (const proof of _proofs.values()) {
663
+ const current = proof.status || PROOF_STATUS_V2.PENDING;
664
+ if (PROOF_TERMINALS_V2.has(current)) continue;
665
+ if (proof.expiresAt && now > proof.expiresAt) {
666
+ proof.status = PROOF_STATUS_V2.EXPIRED;
667
+ proof.verified = false;
668
+ db.prepare("UPDATE zkp_proofs SET verified = 0 WHERE id = ?").run(
669
+ proof.id,
670
+ );
671
+ expired.push({ ...proof });
672
+ }
673
+ }
674
+ return expired;
675
+ }
676
+
677
+ /* ── Selective Disclosure V2 ───────────────────────────── */
678
+
679
+ export function selectiveDiscloseV2(
680
+ db,
681
+ { credentialId, disclosedFields, requiredFields, recipientDid } = {},
682
+ ) {
683
+ if (!credentialId) throw new Error("credentialId is required");
684
+ if (!Array.isArray(disclosedFields)) {
685
+ throw new Error("disclosedFields must be an array");
686
+ }
687
+ const credential = _credentials.get(credentialId);
688
+ if (!credential) throw new Error(`Credential not found: ${credentialId}`);
689
+ if (Array.isArray(requiredFields)) {
690
+ for (const f of requiredFields) {
691
+ if (!disclosedFields.includes(f)) {
692
+ throw new Error(`Required field missing from disclosure: ${f}`);
693
+ }
694
+ if (!(f in credential.claims)) {
695
+ throw new Error(`Required field not in credential: ${f}`);
696
+ }
697
+ }
698
+ }
699
+ return selectiveDisclose(db, credentialId, disclosedFields, recipientDid);
700
+ }
701
+
702
+ /* ── V2 Stats ──────────────────────────────────────────── */
703
+
704
+ export function getZKPStatsV2() {
705
+ const circuitsByStatus = {};
706
+ for (const s of Object.values(CIRCUIT_STATUS_V2)) circuitsByStatus[s] = 0;
707
+ const proofsByStatus = {};
708
+ for (const s of Object.values(PROOF_STATUS_V2)) proofsByStatus[s] = 0;
709
+ const proofsByScheme = {};
710
+ for (const s of Object.values(PROOF_SCHEME_V2)) proofsByScheme[s] = 0;
711
+
712
+ for (const c of _circuits.values()) {
713
+ circuitsByStatus[c.status] = (circuitsByStatus[c.status] || 0) + 1;
714
+ }
715
+ let verifiedCount = 0;
716
+ let pendingCount = 0;
717
+ for (const p of _proofs.values()) {
718
+ const status = p.status || PROOF_STATUS_V2.PENDING;
719
+ proofsByStatus[status] = (proofsByStatus[status] || 0) + 1;
720
+ proofsByScheme[p.scheme] = (proofsByScheme[p.scheme] || 0) + 1;
721
+ if (status === PROOF_STATUS_V2.VERIFIED) verifiedCount += 1;
722
+ if (status === PROOF_STATUS_V2.PENDING) pendingCount += 1;
723
+ }
724
+
725
+ const credentialsByDid = {};
726
+ for (const c of _credentials.values()) {
727
+ const key = c.did || "_anonymous";
728
+ credentialsByDid[key] = (credentialsByDid[key] || 0) + 1;
729
+ }
730
+
731
+ return {
732
+ totalCircuits: _circuits.size,
733
+ totalProofs: _proofs.size,
734
+ totalCredentials: _credentials.size,
735
+ verifiedProofs: verifiedCount,
736
+ pendingProofs: pendingCount,
737
+ maxCircuitsPerCreator: _maxCircuitsPerCreator,
738
+ proofExpiryMs: _proofExpiryMs,
739
+ circuitsByStatus,
740
+ proofsByStatus,
741
+ proofsByScheme,
742
+ credentialsByDid,
743
+ };
241
744
  }
@@ -1 +0,0 @@
1
- .stat-card[data-v-39c5aabc]{background:var(--bg-card)!important;border-color:var(--border-color)!important;transition:border-color .2s}.stat-card[data-v-39c5aabc]:hover{border-color:var(--text-muted)!important}.stat-header[data-v-39c5aabc]{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px}.stat-label[data-v-39c5aabc]{color:var(--text-secondary);font-size:12px}.stat-value[data-v-39c5aabc]{font-size:22px;font-weight:600;line-height:1.2;margin-bottom:4px}.stat-sub[data-v-39c5aabc]{color:var(--text-muted);font-size:11px}.gateway-card[data-v-39c5aabc]{border-left:3px solid #1677ff!important}.status-log[data-v-39c5aabc]{background:var(--bg-base);border:1px solid var(--border-color);border-radius:6px;padding:10px 14px;color:var(--text-secondary);font-size:11px;font-family:Consolas,monospace;max-height:200px;overflow-y:auto;white-space:pre-wrap;margin:0;line-height:1.6}.telemetry-card[data-v-39c5aabc]{background:var(--bg-base);border:1px solid var(--border-color);border-radius:8px;padding:14px;height:100%}.telemetry-filter[data-v-39c5aabc]{display:flex;flex-direction:column;gap:6px}.telemetry-filter-label[data-v-39c5aabc]{color:var(--text-muted);font-size:12px}.telemetry-label[data-v-39c5aabc]{color:var(--text-muted);font-size:12px;margin-bottom:6px}.telemetry-value[data-v-39c5aabc]{color:#91caff;font-size:24px;font-weight:600;line-height:1.2}.telemetry-sub[data-v-39c5aabc]{color:var(--text-secondary);font-size:11px;margin-top:4px}.telemetry-section[data-v-39c5aabc]{background:var(--bg-base);border:1px solid var(--border-color);border-radius:8px;padding:14px;min-height:140px}.telemetry-section-title[data-v-39c5aabc]{color:var(--text-secondary);font-size:12px;margin-bottom:10px}.telemetry-list[data-v-39c5aabc]{display:flex;flex-direction:column;gap:8px}.telemetry-row[data-v-39c5aabc]{display:flex;justify-content:space-between;gap:12px;color:var(--text-secondary);font-size:12px}.telemetry-empty[data-v-39c5aabc]{color:var(--text-muted);font-size:12px}