@agentvault/agentvault 0.19.58 → 0.19.60

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 (66) hide show
  1. package/dist/_cp.d.ts +10 -0
  2. package/dist/_cp.d.ts.map +1 -0
  3. package/dist/account-config.d.ts +20 -0
  4. package/dist/account-config.d.ts.map +1 -0
  5. package/dist/channel.d.ts +391 -0
  6. package/dist/channel.d.ts.map +1 -0
  7. package/dist/cli.d.ts +2 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +1218 -473
  10. package/dist/cli.js.map +3 -3
  11. package/dist/create-agent.d.ts +28 -0
  12. package/dist/create-agent.d.ts.map +1 -0
  13. package/dist/credential-store.d.ts +62 -0
  14. package/dist/credential-store.d.ts.map +1 -0
  15. package/dist/crypto-helpers.d.ts +2 -0
  16. package/dist/crypto-helpers.d.ts.map +1 -0
  17. package/dist/doctor.d.ts +41 -0
  18. package/dist/doctor.d.ts.map +1 -0
  19. package/dist/fetch-interceptor.d.ts +32 -0
  20. package/dist/fetch-interceptor.d.ts.map +1 -0
  21. package/dist/gateway-send.d.ts +98 -0
  22. package/dist/gateway-send.d.ts.map +1 -0
  23. package/dist/http-handlers.d.ts +53 -0
  24. package/dist/http-handlers.d.ts.map +1 -0
  25. package/dist/index.d.ts +27 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +1156 -473
  28. package/dist/index.js.map +3 -3
  29. package/dist/mcp-handlers.d.ts +26 -0
  30. package/dist/mcp-handlers.d.ts.map +1 -0
  31. package/dist/mcp-proxy-helpers.d.ts +9 -0
  32. package/dist/mcp-proxy-helpers.d.ts.map +1 -0
  33. package/dist/mcp-server.d.ts +91 -0
  34. package/dist/mcp-server.d.ts.map +1 -0
  35. package/dist/mls-state.d.ts +16 -0
  36. package/dist/mls-state.d.ts.map +1 -0
  37. package/dist/openclaw-compat.d.ts +33 -0
  38. package/dist/openclaw-compat.d.ts.map +1 -0
  39. package/dist/openclaw-entry.d.ts +32 -0
  40. package/dist/openclaw-entry.d.ts.map +1 -0
  41. package/dist/openclaw-plugin.d.ts +102 -0
  42. package/dist/openclaw-plugin.d.ts.map +1 -0
  43. package/dist/openclaw-types.d.ts +186 -0
  44. package/dist/openclaw-types.d.ts.map +1 -0
  45. package/dist/policy-enforcer.d.ts +78 -0
  46. package/dist/policy-enforcer.d.ts.map +1 -0
  47. package/dist/setup.d.ts +27 -0
  48. package/dist/setup.d.ts.map +1 -0
  49. package/dist/skill-invoker.d.ts +30 -0
  50. package/dist/skill-invoker.d.ts.map +1 -0
  51. package/dist/skill-manifest.d.ts +30 -0
  52. package/dist/skill-manifest.d.ts.map +1 -0
  53. package/dist/skill-telemetry.d.ts +36 -0
  54. package/dist/skill-telemetry.d.ts.map +1 -0
  55. package/dist/skills-publish.d.ts +8 -0
  56. package/dist/skills-publish.d.ts.map +1 -0
  57. package/dist/state.d.ts +32 -0
  58. package/dist/state.d.ts.map +1 -0
  59. package/dist/transport.d.ts +24 -0
  60. package/dist/transport.d.ts.map +1 -0
  61. package/dist/types.d.ts +421 -0
  62. package/dist/types.d.ts.map +1 -0
  63. package/dist/workspace-handlers.d.ts +62 -0
  64. package/dist/workspace-handlers.d.ts.map +1 -0
  65. package/openclaw.plugin.json +1 -1
  66. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -44666,6 +44666,13 @@ function computeFingerprint(publicKey) {
44666
44666
  function createProofOfPossession(privateKey, publicKey) {
44667
44667
  return libsodium_wrappers_default.crypto_sign_detached(publicKey, privateKey);
44668
44668
  }
44669
+ function verifyProofOfPossession(proof, publicKey) {
44670
+ try {
44671
+ return libsodium_wrappers_default.crypto_sign_verify_detached(proof, publicKey, publicKey);
44672
+ } catch {
44673
+ return false;
44674
+ }
44675
+ }
44669
44676
  var init_keys = __esm({
44670
44677
  async "../crypto/dist/keys.js"() {
44671
44678
  "use strict";
@@ -45134,6 +45141,74 @@ function jsonCanonical(value) {
45134
45141
  }
45135
45142
  return JSON.stringify(value);
45136
45143
  }
45144
+ function base58Encode(bytes) {
45145
+ let zeros = 0;
45146
+ for (const b2 of bytes) {
45147
+ if (b2 === 0)
45148
+ zeros++;
45149
+ else
45150
+ break;
45151
+ }
45152
+ let num = BigInt(0);
45153
+ for (const b2 of bytes) {
45154
+ num = num * 256n + BigInt(b2);
45155
+ }
45156
+ let result = "";
45157
+ while (num > 0n) {
45158
+ const remainder = Number(num % 58n);
45159
+ num = num / 58n;
45160
+ result = BASE58_ALPHABET[remainder] + result;
45161
+ }
45162
+ return "1".repeat(zeros) + result;
45163
+ }
45164
+ function base58Decode(str) {
45165
+ let zeros = 0;
45166
+ for (const c2 of str) {
45167
+ if (c2 === "1")
45168
+ zeros++;
45169
+ else
45170
+ break;
45171
+ }
45172
+ let num = BigInt(0);
45173
+ for (const c2 of str.slice(zeros)) {
45174
+ const idx = BASE58_ALPHABET.indexOf(c2);
45175
+ if (idx === -1)
45176
+ throw new Error(`Invalid base58 character: ${c2}`);
45177
+ num = num * 58n + BigInt(idx);
45178
+ }
45179
+ const hex3 = num === 0n ? "" : num.toString(16).padStart(2, "0");
45180
+ const paddedHex = hex3.length % 2 ? "0" + hex3 : hex3;
45181
+ const dataBytes = new Uint8Array((paddedHex.match(/.{2}/g) ?? []).map((b2) => parseInt(b2, 16)));
45182
+ const result = new Uint8Array(zeros + dataBytes.length);
45183
+ result.set(dataBytes, zeros);
45184
+ return result;
45185
+ }
45186
+ function publicKeyToMultibase(publicKey) {
45187
+ const prefixed = new Uint8Array(2 + publicKey.length);
45188
+ prefixed[0] = 237;
45189
+ prefixed[1] = 1;
45190
+ prefixed.set(publicKey, 2);
45191
+ return "z" + base58Encode(prefixed);
45192
+ }
45193
+ function multibaseToPublicKey(multibase) {
45194
+ if (!multibase.startsWith("z")) {
45195
+ throw new Error("Multibase string must start with 'z' (base58btc)");
45196
+ }
45197
+ const decoded = base58Decode(multibase.slice(1));
45198
+ if (decoded.length < 2 || decoded[0] !== 237 || decoded[1] !== 1) {
45199
+ throw new Error("Invalid Ed25519 multicodec prefix");
45200
+ }
45201
+ return decoded.slice(2);
45202
+ }
45203
+ async function signDocument(document, privateKey) {
45204
+ await libsodium_wrappers_default.ready;
45205
+ const canonical = canonicalize(document);
45206
+ const domainPrefix = libsodium_wrappers_default.from_string(DOMAIN_DID_DOCUMENT);
45207
+ const message = new Uint8Array(domainPrefix.length + canonical.length);
45208
+ message.set(domainPrefix);
45209
+ message.set(canonical, domainPrefix.length);
45210
+ return libsodium_wrappers_default.crypto_sign_detached(message, privateKey);
45211
+ }
45137
45212
  async function verifyDocumentSignature(document, signature, publicKey) {
45138
45213
  await libsodium_wrappers_default.ready;
45139
45214
  const canonical = canonicalize(document);
@@ -45147,12 +45222,61 @@ async function verifyDocumentSignature(document, signature, publicKey) {
45147
45222
  return false;
45148
45223
  }
45149
45224
  }
45150
- var DOMAIN_DID_DOCUMENT;
45225
+ function buildDidDocument(params) {
45226
+ const { hubAddress, ownerPublicKey, agentPublicKey, serviceEndpoint, profileEndpoint } = params;
45227
+ const didId = `did:hub:${hubAddress}`;
45228
+ const ownerMultibase = publicKeyToMultibase(ownerPublicKey);
45229
+ const agentMultibase = publicKeyToMultibase(agentPublicKey);
45230
+ const controllerDid = `did:key:${ownerMultibase}`;
45231
+ const now = params.created ?? (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
45232
+ return {
45233
+ "@context": [
45234
+ "https://www.w3.org/ns/did/v1",
45235
+ "https://w3id.org/security/suites/ed25519-2020/v1"
45236
+ ],
45237
+ id: didId,
45238
+ controller: controllerDid,
45239
+ verificationMethod: [
45240
+ {
45241
+ id: `${didId}#owner-key`,
45242
+ type: "Ed25519VerificationKey2020",
45243
+ controller: didId,
45244
+ publicKeyMultibase: ownerMultibase
45245
+ },
45246
+ {
45247
+ id: `${didId}#agent-key`,
45248
+ type: "Ed25519VerificationKey2020",
45249
+ controller: didId,
45250
+ publicKeyMultibase: agentMultibase
45251
+ }
45252
+ ],
45253
+ authentication: [`${didId}#owner-key`],
45254
+ assertionMethod: [`${didId}#owner-key`, `${didId}#agent-key`],
45255
+ service: [
45256
+ {
45257
+ id: `${didId}#messaging`,
45258
+ type: "AgentVaultSecureChannel",
45259
+ serviceEndpoint
45260
+ },
45261
+ {
45262
+ id: `${didId}#profile`,
45263
+ type: "AgentVaultProfile",
45264
+ serviceEndpoint: profileEndpoint
45265
+ }
45266
+ ],
45267
+ created: now,
45268
+ updated: now
45269
+ };
45270
+ }
45271
+ var DOMAIN_DID_DOCUMENT, DOMAIN_TRANSFER_INTENT, DOMAIN_TRANSFER_ACCEPT, BASE58_ALPHABET;
45151
45272
  var init_did = __esm({
45152
45273
  async "../crypto/dist/did.js"() {
45153
45274
  "use strict";
45154
45275
  await init_libsodium_wrappers();
45155
45276
  DOMAIN_DID_DOCUMENT = "DID-DOCUMENT:";
45277
+ DOMAIN_TRANSFER_INTENT = "TRANSFER-INTENT:";
45278
+ DOMAIN_TRANSFER_ACCEPT = "TRANSFER-ACCEPT:";
45279
+ BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
45156
45280
  }
45157
45281
  });
45158
45282
 
@@ -45435,25 +45559,373 @@ var init_scan_engine = __esm({
45435
45559
  });
45436
45560
 
45437
45561
  // ../crypto/dist/merkle.js
45562
+ function jcsCanonical(value) {
45563
+ if (value === void 0)
45564
+ return void 0;
45565
+ if (value === null)
45566
+ return "null";
45567
+ if (typeof value === "boolean" || typeof value === "number")
45568
+ return JSON.stringify(value);
45569
+ if (typeof value === "string")
45570
+ return JSON.stringify(value);
45571
+ if (Array.isArray(value)) {
45572
+ return "[" + value.map(jcsCanonical).join(",") + "]";
45573
+ }
45574
+ if (typeof value === "object") {
45575
+ const keys = Object.keys(value).sort();
45576
+ const entries = keys.map((k2) => {
45577
+ const v2 = jcsCanonical(value[k2]);
45578
+ if (v2 === void 0)
45579
+ return void 0;
45580
+ return JSON.stringify(k2) + ":" + v2;
45581
+ }).filter((entry) => entry !== void 0);
45582
+ return "{" + entries.join(",") + "}";
45583
+ }
45584
+ return JSON.stringify(value);
45585
+ }
45586
+ function hexToBytes(hex3) {
45587
+ const h2 = hex3.startsWith("0x") ? hex3.slice(2) : hex3;
45588
+ const bytes = new Uint8Array(h2.length / 2);
45589
+ for (let i2 = 0; i2 < bytes.length; i2++) {
45590
+ bytes[i2] = parseInt(h2.substr(i2 * 2, 2), 16);
45591
+ }
45592
+ return bytes;
45593
+ }
45594
+ function bytesToHex(bytes) {
45595
+ return Array.from(bytes).map((b2) => b2.toString(16).padStart(2, "0")).join("");
45596
+ }
45597
+ function computeDidHash(didDocument) {
45598
+ const json2 = jcsCanonical(didDocument) ?? "";
45599
+ const bytes = libsodium_wrappers_default.from_string(json2);
45600
+ const hash2 = libsodium_wrappers_default.crypto_hash_sha256(bytes);
45601
+ return "0x" + bytesToHex(hash2);
45602
+ }
45603
+ function verifyMerkleProof(leafHash, proof, merkleRoot) {
45604
+ let current = hexToBytes(leafHash);
45605
+ for (const step of proof) {
45606
+ const sibling2 = hexToBytes(step.hash);
45607
+ const combined = new Uint8Array(current.length + sibling2.length);
45608
+ if (step.position === "left") {
45609
+ combined.set(sibling2);
45610
+ combined.set(current, sibling2.length);
45611
+ } else {
45612
+ combined.set(current);
45613
+ combined.set(sibling2, current.length);
45614
+ }
45615
+ current = libsodium_wrappers_default.crypto_hash_sha256(combined);
45616
+ }
45617
+ const rootBytes = hexToBytes(merkleRoot);
45618
+ if (current.length !== rootBytes.length)
45619
+ return false;
45620
+ for (let i2 = 0; i2 < current.length; i2++) {
45621
+ if (current[i2] !== rootBytes[i2])
45622
+ return false;
45623
+ }
45624
+ return true;
45625
+ }
45438
45626
  var init_merkle = __esm({
45439
45627
  async "../crypto/dist/merkle.js"() {
45440
45628
  "use strict";
45629
+ await init_libsodium_wrappers();
45441
45630
  }
45442
45631
  });
45443
45632
 
45444
45633
  // ../crypto/dist/vc.js
45634
+ async function sha256(data) {
45635
+ await libsodium_wrappers_default.ready;
45636
+ return libsodium_wrappers_default.crypto_hash_sha256(data);
45637
+ }
45638
+ function base58Encode2(bytes) {
45639
+ let zeros = 0;
45640
+ for (const b2 of bytes) {
45641
+ if (b2 === 0)
45642
+ zeros++;
45643
+ else
45644
+ break;
45645
+ }
45646
+ let num = BigInt(0);
45647
+ for (const b2 of bytes) {
45648
+ num = num * 256n + BigInt(b2);
45649
+ }
45650
+ let result = "";
45651
+ while (num > 0n) {
45652
+ const remainder = Number(num % 58n);
45653
+ num = num / 58n;
45654
+ result = BASE58_ALPHABET2[remainder] + result;
45655
+ }
45656
+ return "1".repeat(zeros) + result;
45657
+ }
45658
+ function base58Decode2(str) {
45659
+ let zeros = 0;
45660
+ for (const c2 of str) {
45661
+ if (c2 === "1")
45662
+ zeros++;
45663
+ else
45664
+ break;
45665
+ }
45666
+ let num = BigInt(0);
45667
+ for (const c2 of str.slice(zeros)) {
45668
+ const idx = BASE58_ALPHABET2.indexOf(c2);
45669
+ if (idx === -1)
45670
+ throw new Error(`Invalid base58 character: ${c2}`);
45671
+ num = num * 58n + BigInt(idx);
45672
+ }
45673
+ const hex3 = num === 0n ? "" : num.toString(16).padStart(2, "0");
45674
+ const paddedHex = hex3.length % 2 ? "0" + hex3 : hex3;
45675
+ const dataBytes = new Uint8Array((paddedHex.match(/.{2}/g) ?? []).map((b2) => parseInt(b2, 16)));
45676
+ const result = new Uint8Array(zeros + dataBytes.length);
45677
+ result.set(dataBytes, zeros);
45678
+ return result;
45679
+ }
45680
+ async function computeHashData(document, proofConfig) {
45681
+ const proofConfigBytes = canonicalize(proofConfig);
45682
+ const proofConfigHash = await sha256(proofConfigBytes);
45683
+ const docWithoutProof = { ...document };
45684
+ delete docWithoutProof.proof;
45685
+ const documentBytes = canonicalize(docWithoutProof);
45686
+ const documentHash = await sha256(documentBytes);
45687
+ const hashData = new Uint8Array(64);
45688
+ hashData.set(proofConfigHash, 0);
45689
+ hashData.set(documentHash, 32);
45690
+ return hashData;
45691
+ }
45692
+ async function signWithDataIntegrity(document, privateKey, verificationMethod, proofPurpose = "assertionMethod", created) {
45693
+ await libsodium_wrappers_default.ready;
45694
+ const timestamp = created ?? (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
45695
+ const proofConfig = {
45696
+ type: "DataIntegrityProof",
45697
+ cryptosuite: CRYPTOSUITE,
45698
+ created: timestamp,
45699
+ verificationMethod,
45700
+ proofPurpose
45701
+ };
45702
+ const hashData = await computeHashData(document, proofConfig);
45703
+ const signature = libsodium_wrappers_default.crypto_sign_detached(hashData, privateKey);
45704
+ const proofValue = "z" + base58Encode2(signature);
45705
+ const proof = {
45706
+ type: "DataIntegrityProof",
45707
+ cryptosuite: CRYPTOSUITE,
45708
+ created: timestamp,
45709
+ verificationMethod,
45710
+ proofPurpose,
45711
+ proofValue
45712
+ };
45713
+ return { ...document, proof };
45714
+ }
45715
+ async function verifyDataIntegrity(document, publicKey) {
45716
+ await libsodium_wrappers_default.ready;
45717
+ const proof = document.proof;
45718
+ if (!proof || proof.type !== "DataIntegrityProof" || proof.cryptosuite !== CRYPTOSUITE) {
45719
+ return false;
45720
+ }
45721
+ if (!proof.proofValue.startsWith("z")) {
45722
+ return false;
45723
+ }
45724
+ const signature = base58Decode2(proof.proofValue.slice(1));
45725
+ if (signature.length !== 64) {
45726
+ return false;
45727
+ }
45728
+ const proofConfig = {
45729
+ type: proof.type,
45730
+ cryptosuite: proof.cryptosuite,
45731
+ created: proof.created,
45732
+ verificationMethod: proof.verificationMethod,
45733
+ proofPurpose: proof.proofPurpose
45734
+ };
45735
+ const hashData = await computeHashData(document, proofConfig);
45736
+ try {
45737
+ return libsodium_wrappers_default.crypto_sign_verify_detached(signature, hashData, publicKey);
45738
+ } catch {
45739
+ return false;
45740
+ }
45741
+ }
45742
+ function buildAgentTrustCredential(params) {
45743
+ const now = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
45744
+ return {
45745
+ "@context": [
45746
+ VC_CONTEXT_V2,
45747
+ {
45748
+ AgentTrustCredential: "https://agentvault.chat/vocab#AgentTrustCredential",
45749
+ trustTier: "https://agentvault.chat/vocab#trustTier",
45750
+ compositeScore: "https://agentvault.chat/vocab#compositeScore",
45751
+ scoreWindow: "https://agentvault.chat/vocab#scoreWindow",
45752
+ scoreDimensions: "https://agentvault.chat/vocab#scoreDimensions",
45753
+ volume: "https://agentvault.chat/vocab#volume",
45754
+ responsiveness: "https://agentvault.chat/vocab#responsiveness",
45755
+ uptime: "https://agentvault.chat/vocab#uptime",
45756
+ compliance: "https://agentvault.chat/vocab#compliance",
45757
+ verificationEndpoint: "https://agentvault.chat/vocab#verificationEndpoint"
45758
+ }
45759
+ ],
45760
+ id: params.credentialId,
45761
+ type: ["VerifiableCredential", "AgentTrustCredential"],
45762
+ issuer: params.issuerName ? { id: params.issuerDid, name: params.issuerName } : params.issuerDid,
45763
+ validFrom: params.validFrom ?? now,
45764
+ ...params.validUntil ? { validUntil: params.validUntil } : {},
45765
+ credentialSubject: {
45766
+ id: params.subjectDid,
45767
+ trustTier: params.trustTier,
45768
+ compositeScore: params.compositeScore,
45769
+ scoreWindow: params.scoreWindow,
45770
+ ...params.dimensions ? {
45771
+ scoreDimensions: {
45772
+ volume: params.dimensions.volume,
45773
+ responsiveness: params.dimensions.responsiveness,
45774
+ uptime: params.dimensions.uptime,
45775
+ compliance: params.dimensions.compliance
45776
+ }
45777
+ } : {},
45778
+ ...params.verificationEndpoint ? { verificationEndpoint: params.verificationEndpoint } : {}
45779
+ }
45780
+ };
45781
+ }
45782
+ function buildSkillAttestation(params) {
45783
+ const now = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
45784
+ return {
45785
+ "@context": [
45786
+ VC_CONTEXT_V2,
45787
+ {
45788
+ SkillAttestation: "https://agentvault.chat/vocab#SkillAttestation",
45789
+ skillName: "https://agentvault.chat/vocab#skillName",
45790
+ skillNamespace: "https://agentvault.chat/vocab#skillNamespace",
45791
+ proficiencyLevel: "https://agentvault.chat/vocab#proficiencyLevel",
45792
+ totalInvocations: "https://agentvault.chat/vocab#totalInvocations",
45793
+ successRate: "https://agentvault.chat/vocab#successRate",
45794
+ assessedAt: "https://agentvault.chat/vocab#assessedAt"
45795
+ }
45796
+ ],
45797
+ id: params.credentialId,
45798
+ type: ["VerifiableCredential", "SkillAttestation"],
45799
+ issuer: params.issuerName ? { id: params.issuerDid, name: params.issuerName } : params.issuerDid,
45800
+ validFrom: params.validFrom ?? now,
45801
+ ...params.validUntil ? { validUntil: params.validUntil } : {},
45802
+ credentialSubject: {
45803
+ id: params.subjectDid,
45804
+ skillName: params.skillName,
45805
+ skillNamespace: params.skillNamespace,
45806
+ ...params.proficiencyLevel ? { proficiencyLevel: params.proficiencyLevel } : {},
45807
+ ...params.totalInvocations !== void 0 ? { totalInvocations: params.totalInvocations } : {},
45808
+ ...params.successRate !== void 0 ? { successRate: params.successRate } : {},
45809
+ ...params.assessedAt ? { assessedAt: params.assessedAt } : {}
45810
+ }
45811
+ };
45812
+ }
45813
+ function buildPerformanceRecord(params) {
45814
+ const now = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
45815
+ return {
45816
+ "@context": [
45817
+ VC_CONTEXT_V2,
45818
+ {
45819
+ PerformanceRecord: "https://agentvault.chat/vocab#PerformanceRecord",
45820
+ periodStart: "https://agentvault.chat/vocab#periodStart",
45821
+ periodEnd: "https://agentvault.chat/vocab#periodEnd",
45822
+ messagesHandled: "https://agentvault.chat/vocab#messagesHandled",
45823
+ avgResponseTimeMs: "https://agentvault.chat/vocab#avgResponseTimeMs",
45824
+ uptimePercentage: "https://agentvault.chat/vocab#uptimePercentage",
45825
+ policyViolations: "https://agentvault.chat/vocab#policyViolations",
45826
+ compositeScore: "https://agentvault.chat/vocab#compositeScore"
45827
+ }
45828
+ ],
45829
+ id: params.credentialId,
45830
+ type: ["VerifiableCredential", "PerformanceRecord"],
45831
+ issuer: params.issuerName ? { id: params.issuerDid, name: params.issuerName } : params.issuerDid,
45832
+ validFrom: params.validFrom ?? now,
45833
+ ...params.validUntil ? { validUntil: params.validUntil } : {},
45834
+ credentialSubject: {
45835
+ id: params.subjectDid,
45836
+ periodStart: params.periodStart,
45837
+ periodEnd: params.periodEnd,
45838
+ messagesHandled: params.messagesHandled,
45839
+ avgResponseTimeMs: params.avgResponseTimeMs,
45840
+ uptimePercentage: params.uptimePercentage,
45841
+ policyViolations: params.policyViolations,
45842
+ compositeScore: params.compositeScore
45843
+ }
45844
+ };
45845
+ }
45846
+ function buildAgentTrustReportCredential(params) {
45847
+ const now = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
45848
+ const subject = {
45849
+ id: params.subjectDid,
45850
+ reportPeriod: {
45851
+ start: params.reportPeriodStart,
45852
+ end: params.reportPeriodEnd
45853
+ },
45854
+ trustTier: params.trustTier,
45855
+ compositeScore: params.compositeScore
45856
+ };
45857
+ if (params.dimensions)
45858
+ subject.dimensions = params.dimensions;
45859
+ if (params.trending)
45860
+ subject.trending = params.trending;
45861
+ if (params.fleetComparison)
45862
+ subject.fleetComparison = params.fleetComparison;
45863
+ if (params.driftStatus)
45864
+ subject.driftStatus = params.driftStatus;
45865
+ if (params.auditIntegrity)
45866
+ subject.auditIntegrity = params.auditIntegrity;
45867
+ if (params.telemetrySummary)
45868
+ subject.telemetrySummary = params.telemetrySummary;
45869
+ if (params.verificationEndpoint)
45870
+ subject.verificationEndpoint = params.verificationEndpoint;
45871
+ return {
45872
+ "@context": [
45873
+ VC_CONTEXT_V2,
45874
+ {
45875
+ AgentTrustReport: "https://agentvault.chat/vocab#AgentTrustReport",
45876
+ reportPeriod: "https://agentvault.chat/vocab#reportPeriod",
45877
+ trustTier: "https://agentvault.chat/vocab#trustTier",
45878
+ compositeScore: "https://agentvault.chat/vocab#compositeScore",
45879
+ dimensions: "https://agentvault.chat/vocab#dimensions",
45880
+ trending: "https://agentvault.chat/vocab#trending",
45881
+ fleetComparison: "https://agentvault.chat/vocab#fleetComparison",
45882
+ driftStatus: "https://agentvault.chat/vocab#driftStatus",
45883
+ auditIntegrity: "https://agentvault.chat/vocab#auditIntegrity",
45884
+ telemetrySummary: "https://agentvault.chat/vocab#telemetrySummary",
45885
+ verificationEndpoint: "https://agentvault.chat/vocab#verificationEndpoint"
45886
+ }
45887
+ ],
45888
+ id: params.credentialId,
45889
+ type: ["VerifiableCredential", "AgentTrustReport"],
45890
+ issuer: params.issuerName ? { id: params.issuerDid, name: params.issuerName } : params.issuerDid,
45891
+ validFrom: params.validFrom ?? now,
45892
+ ...params.validUntil ? { validUntil: params.validUntil } : {},
45893
+ credentialSubject: subject
45894
+ };
45895
+ }
45896
+ function buildVerifiablePresentation(holderDid, credentials, presentationId) {
45897
+ return {
45898
+ "@context": [VC_CONTEXT_V2],
45899
+ type: "VerifiablePresentation",
45900
+ ...presentationId ? { id: presentationId } : {},
45901
+ holder: holderDid,
45902
+ verifiableCredential: credentials
45903
+ };
45904
+ }
45905
+ async function issueCredential(credential, privateKey, verificationMethod) {
45906
+ return signWithDataIntegrity(credential, privateKey, verificationMethod, "assertionMethod");
45907
+ }
45908
+ async function presentCredentials(presentation, privateKey, verificationMethod) {
45909
+ return signWithDataIntegrity(presentation, privateKey, verificationMethod, "authentication");
45910
+ }
45911
+ var VC_CONTEXT_V2, AV_CREDENTIAL_CONTEXT, CRYPTOSUITE, BASE58_ALPHABET2;
45445
45912
  var init_vc = __esm({
45446
45913
  async "../crypto/dist/vc.js"() {
45447
45914
  "use strict";
45915
+ await init_libsodium_wrappers();
45448
45916
  await init_did();
45917
+ VC_CONTEXT_V2 = "https://www.w3.org/ns/credentials/v2";
45918
+ AV_CREDENTIAL_CONTEXT = "https://agentvault.chat/ns/credentials/v1";
45919
+ CRYPTOSUITE = "eddsa-jcs-2022";
45920
+ BASE58_ALPHABET2 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
45449
45921
  }
45450
45922
  });
45451
45923
 
45452
45924
  // ../crypto/dist/transport.js
45453
- function hexToBytes(hex3) {
45925
+ function hexToBytes2(hex3) {
45454
45926
  return libsodium_wrappers_default.from_hex(hex3);
45455
45927
  }
45456
- function bytesToHex(bytes) {
45928
+ function bytesToHex2(bytes) {
45457
45929
  return libsodium_wrappers_default.to_hex(bytes);
45458
45930
  }
45459
45931
  function base64ToBytes(b64) {
@@ -45491,6 +45963,70 @@ function transportToEncryptedMessage(transport) {
45491
45963
  ciphertext: base64ToBytes(transport.ciphertext)
45492
45964
  };
45493
45965
  }
45966
+ function encryptedMessageToTransportV2(msg) {
45967
+ if (!msg.encryptedHeader || !msg.headerNonce) {
45968
+ throw new Error("encryptedMessageToTransportV2 requires v2 encrypted message");
45969
+ }
45970
+ return {
45971
+ envelope_version: "2.0.0",
45972
+ encrypted_header: bytesToBase64(msg.encryptedHeader),
45973
+ header_nonce: bytesToBase64(msg.headerNonce),
45974
+ header_signature: bytesToBase64(msg.headerSignature),
45975
+ nonce: bytesToBase64(msg.nonce),
45976
+ ciphertext: bytesToBase64(msg.ciphertext)
45977
+ };
45978
+ }
45979
+ function transportV2ToEncryptedMessage(transport, plaintextHeader) {
45980
+ return {
45981
+ header: plaintextHeader,
45982
+ headerSignature: base64ToBytes(transport.header_signature),
45983
+ ciphertext: base64ToBytes(transport.ciphertext),
45984
+ nonce: base64ToBytes(transport.nonce),
45985
+ envelopeVersion: "2.0.0",
45986
+ encryptedHeader: base64ToBytes(transport.encrypted_header),
45987
+ headerNonce: base64ToBytes(transport.header_nonce)
45988
+ };
45989
+ }
45990
+ function encryptedMessageToTransportV2Full(msg) {
45991
+ if (!msg.encryptedHeader || !msg.headerNonce) {
45992
+ throw new Error("encryptedMessageToTransportV2Full requires v2 encrypted message");
45993
+ }
45994
+ const v1 = encryptedMessageToTransport(msg);
45995
+ return {
45996
+ ...v1,
45997
+ envelope_version: "2.0.0",
45998
+ encrypted_header: bytesToBase64(msg.encryptedHeader),
45999
+ header_nonce: bytesToBase64(msg.headerNonce)
46000
+ };
46001
+ }
46002
+ function encryptedMessageToHexTransport(msg) {
46003
+ const headerObj = {
46004
+ dhPublicKey: bytesToHex2(msg.header.dhPublicKey),
46005
+ previousChainLength: msg.header.previousChainLength,
46006
+ messageNumber: msg.header.messageNumber
46007
+ };
46008
+ const headerBlobHex = Buffer.from(JSON.stringify(headerObj)).toString("hex");
46009
+ return {
46010
+ header_blob: headerBlobHex,
46011
+ header_signature: bytesToHex2(msg.headerSignature),
46012
+ ciphertext: bytesToHex2(msg.ciphertext),
46013
+ nonce: bytesToHex2(msg.nonce)
46014
+ };
46015
+ }
46016
+ function hexTransportToEncryptedMessage(transport) {
46017
+ const headerJson = Buffer.from(transport.header_blob, "hex").toString("utf-8");
46018
+ const headerObj = JSON.parse(headerJson);
46019
+ return {
46020
+ header: {
46021
+ dhPublicKey: hexToBytes2(headerObj.dhPublicKey),
46022
+ previousChainLength: headerObj.previousChainLength,
46023
+ messageNumber: headerObj.messageNumber
46024
+ },
46025
+ headerSignature: hexToBytes2(transport.header_signature),
46026
+ ciphertext: hexToBytes2(transport.ciphertext),
46027
+ nonce: hexToBytes2(transport.nonce)
46028
+ };
46029
+ }
45494
46030
  var init_transport = __esm({
45495
46031
  async "../crypto/dist/transport.js"() {
45496
46032
  "use strict";
@@ -45695,6 +46231,40 @@ function buildTaskSpan(opts) {
45695
46231
  status
45696
46232
  };
45697
46233
  }
46234
+ function buildSkillInvocationSpan(opts) {
46235
+ const now = Date.now();
46236
+ const attributes = {
46237
+ "ai.agent.skill.invocation.id": opts.invocationId,
46238
+ "ai.agent.skill.phase": opts.phase
46239
+ };
46240
+ if (opts.skillName)
46241
+ attributes["ai.agent.skill.name"] = opts.skillName;
46242
+ if (opts.version !== void 0)
46243
+ attributes["ai.agent.skill.version"] = opts.version;
46244
+ if (opts.inputTokens !== void 0)
46245
+ attributes["ai.agent.skill.input_tokens"] = opts.inputTokens;
46246
+ if (opts.outputTokens !== void 0)
46247
+ attributes["ai.agent.skill.output_tokens"] = opts.outputTokens;
46248
+ if (opts.costCents !== void 0)
46249
+ attributes["ai.agent.skill.cost_cents"] = opts.costCents;
46250
+ if (opts.toolsUsed !== void 0)
46251
+ attributes["ai.agent.skill.tools_used"] = opts.toolsUsed.join(",");
46252
+ if (opts.schemaMatch !== void 0)
46253
+ attributes["ai.agent.skill.schema_match"] = opts.schemaMatch;
46254
+ const isError = opts.status === "error";
46255
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46256
+ return {
46257
+ traceId: opts.traceId ?? generateTraceId(),
46258
+ spanId: opts.spanId ?? generateSpanId(),
46259
+ parentSpanId: opts.parentSpanId,
46260
+ name: "skill.invoke",
46261
+ kind: "internal",
46262
+ startTime: now - opts.latencyMs,
46263
+ endTime: now,
46264
+ attributes,
46265
+ status
46266
+ };
46267
+ }
45698
46268
  function buildEvalSpan(opts) {
45699
46269
  const now = Date.now();
45700
46270
  const attributes = {
@@ -45717,12 +46287,364 @@ function buildEvalSpan(opts) {
45717
46287
  startTime: now,
45718
46288
  endTime: now,
45719
46289
  attributes,
45720
- status: { code: 0 }
46290
+ status: { code: 0 }
46291
+ };
46292
+ }
46293
+ function buildForgeSpan(opts) {
46294
+ const now = Date.now();
46295
+ const attributes = {
46296
+ "ai.agent.forge.session_id": opts.forgeSessionId,
46297
+ "ai.agent.forge.phase": opts.phase
46298
+ };
46299
+ if (opts.stageNumber !== void 0)
46300
+ attributes["ai.agent.forge.stage_number"] = opts.stageNumber;
46301
+ if (opts.artifactCount !== void 0)
46302
+ attributes["ai.agent.forge.artifact_count"] = opts.artifactCount;
46303
+ if (opts.scanStatus !== void 0)
46304
+ attributes["ai.agent.forge.scan_status"] = opts.scanStatus;
46305
+ applySkillName(attributes, opts.skillName);
46306
+ const isError = opts.status === "error";
46307
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46308
+ return {
46309
+ traceId: opts.traceId ?? generateTraceId(),
46310
+ spanId: opts.spanId ?? generateSpanId(),
46311
+ parentSpanId: opts.parentSpanId,
46312
+ name: `forge.${opts.phase}`,
46313
+ kind: "internal",
46314
+ startTime: now - opts.latencyMs,
46315
+ endTime: now,
46316
+ attributes,
46317
+ status
46318
+ };
46319
+ }
46320
+ function buildPolicyViolationSpan(opts) {
46321
+ const now = Date.now();
46322
+ const attributes = {
46323
+ "av.policy.rule_id": opts.ruleId,
46324
+ "av.policy.scope": opts.policyScope,
46325
+ "av.policy.action_taken": opts.actionTaken,
46326
+ "av.policy.violation_type": opts.violationType
46327
+ };
46328
+ if (opts.targetTool)
46329
+ attributes["av.policy.target_tool"] = opts.targetTool;
46330
+ if (opts.targetModel)
46331
+ attributes["av.policy.target_model"] = opts.targetModel;
46332
+ if (opts.messageType)
46333
+ attributes["av.policy.message_type"] = opts.messageType;
46334
+ applySkillName(attributes, opts.skillName);
46335
+ const isBlock = opts.actionTaken === "block";
46336
+ return {
46337
+ traceId: opts.traceId ?? generateTraceId(),
46338
+ spanId: opts.spanId ?? generateSpanId(),
46339
+ parentSpanId: opts.parentSpanId,
46340
+ name: "av.policy.evaluate",
46341
+ kind: "internal",
46342
+ startTime: now,
46343
+ endTime: now,
46344
+ attributes,
46345
+ status: isBlock ? { code: 2, message: `Policy violation: ${opts.violationType}` } : { code: 0 }
46346
+ };
46347
+ }
46348
+ function buildDecisionSpan(opts) {
46349
+ const now = Date.now();
46350
+ const attributes = {
46351
+ "av.decision.id": opts.decisionId,
46352
+ "av.decision.phase": opts.phase
46353
+ };
46354
+ if (opts.priority)
46355
+ attributes["av.decision.priority"] = opts.priority;
46356
+ if (opts.category)
46357
+ attributes["av.decision.category"] = opts.category;
46358
+ applySkillName(attributes, opts.skillName);
46359
+ const isError = opts.status === "error";
46360
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46361
+ return {
46362
+ traceId: opts.traceId ?? generateTraceId(),
46363
+ spanId: opts.spanId ?? generateSpanId(),
46364
+ parentSpanId: opts.parentSpanId,
46365
+ name: "av.decision",
46366
+ kind: "internal",
46367
+ startTime: now - opts.latencyMs,
46368
+ endTime: now,
46369
+ attributes,
46370
+ status
46371
+ };
46372
+ }
46373
+ function buildResyncSpan(opts) {
46374
+ const now = Date.now();
46375
+ const attributes = {
46376
+ "av.resync.conversation_id": opts.conversationId,
46377
+ "av.resync.phase": opts.phase
46378
+ };
46379
+ if (opts.reason)
46380
+ attributes["av.resync.reason"] = opts.reason;
46381
+ applySkillName(attributes, opts.skillName);
46382
+ const isError = opts.status === "error";
46383
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46384
+ return {
46385
+ traceId: opts.traceId ?? generateTraceId(),
46386
+ spanId: opts.spanId ?? generateSpanId(),
46387
+ parentSpanId: opts.parentSpanId,
46388
+ name: "av.resync",
46389
+ kind: "internal",
46390
+ startTime: now - opts.latencyMs,
46391
+ endTime: now,
46392
+ attributes,
46393
+ status
46394
+ };
46395
+ }
46396
+ function buildA2aSpan(opts) {
46397
+ const now = Date.now();
46398
+ const attributes = {
46399
+ "av.a2a.channel_id": opts.channelId,
46400
+ "av.a2a.operation": opts.operation
46401
+ };
46402
+ if (opts.peerHubAddress)
46403
+ attributes["av.a2a.peer_hub_address"] = opts.peerHubAddress;
46404
+ if (opts.role)
46405
+ attributes["av.a2a.role"] = opts.role;
46406
+ applySkillName(attributes, opts.skillName);
46407
+ const isError = opts.status === "error";
46408
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46409
+ return {
46410
+ traceId: opts.traceId ?? generateTraceId(),
46411
+ spanId: opts.spanId ?? generateSpanId(),
46412
+ parentSpanId: opts.parentSpanId,
46413
+ name: "av.a2a",
46414
+ kind: "internal",
46415
+ startTime: now - opts.latencyMs,
46416
+ endTime: now,
46417
+ attributes,
46418
+ status
46419
+ };
46420
+ }
46421
+ function buildScanSpan(opts) {
46422
+ const now = Date.now();
46423
+ const attributes = {
46424
+ "av.scan.target": opts.scanTarget,
46425
+ "av.scan.type": opts.scanType,
46426
+ "av.scan.violation_count": opts.violationCount,
46427
+ "av.scan.rule_count": opts.ruleCount
46428
+ };
46429
+ applySkillName(attributes, opts.skillName);
46430
+ const isError = opts.status === "error" || opts.violationCount > 0;
46431
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46432
+ return {
46433
+ traceId: opts.traceId ?? generateTraceId(),
46434
+ spanId: opts.spanId ?? generateSpanId(),
46435
+ parentSpanId: opts.parentSpanId,
46436
+ name: "av.scan",
46437
+ kind: "internal",
46438
+ startTime: now - opts.latencyMs,
46439
+ endTime: now,
46440
+ attributes,
46441
+ status
46442
+ };
46443
+ }
46444
+ function buildWorkspaceSpan(opts) {
46445
+ const now = Date.now();
46446
+ const attributes = {
46447
+ "av.workspace.id": opts.workspaceId,
46448
+ "av.workspace.operation": opts.operation
46449
+ };
46450
+ if (opts.fileName)
46451
+ attributes["av.workspace.file_name"] = opts.fileName;
46452
+ if (opts.fileSizeBytes !== void 0)
46453
+ attributes["av.workspace.file_size_bytes"] = opts.fileSizeBytes;
46454
+ if (opts.encrypted !== void 0)
46455
+ attributes["av.workspace.encrypted"] = opts.encrypted;
46456
+ applySkillName(attributes, opts.skillName);
46457
+ const isError = opts.status === "error";
46458
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46459
+ return {
46460
+ traceId: opts.traceId ?? generateTraceId(),
46461
+ spanId: opts.spanId ?? generateSpanId(),
46462
+ parentSpanId: opts.parentSpanId,
46463
+ name: "av.workspace",
46464
+ kind: "internal",
46465
+ startTime: now - opts.latencyMs,
46466
+ endTime: now,
46467
+ attributes,
46468
+ status
46469
+ };
46470
+ }
46471
+ function buildCapabilitySpan(opts) {
46472
+ const now = Date.now();
46473
+ const attributes = {
46474
+ "av.skill.operation": opts.operation,
46475
+ "av.skill.success": opts.success
46476
+ };
46477
+ if (opts.skillName)
46478
+ attributes["av.skill.name"] = opts.skillName;
46479
+ if (opts.version)
46480
+ attributes["av.skill.version"] = opts.version;
46481
+ if (opts.certificationTier)
46482
+ attributes["av.skill.certification_tier"] = opts.certificationTier;
46483
+ if (opts.toolsUsed?.length)
46484
+ attributes["av.skill.tools_used"] = opts.toolsUsed.join(",");
46485
+ const status = opts.success ? { code: 0 } : { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} };
46486
+ return {
46487
+ traceId: opts.traceId ?? generateTraceId(),
46488
+ spanId: opts.spanId ?? generateSpanId(),
46489
+ parentSpanId: opts.parentSpanId,
46490
+ name: "av.skill.invoke",
46491
+ kind: "internal",
46492
+ startTime: now - opts.latencyMs,
46493
+ endTime: now,
46494
+ attributes,
46495
+ status
46496
+ };
46497
+ }
46498
+ function buildEnrollmentSpan(opts) {
46499
+ const now = Date.now();
46500
+ const attributes = {
46501
+ "av.enrollment.phase": opts.phase
46502
+ };
46503
+ if (opts.deviceId)
46504
+ attributes["av.enrollment.device_id"] = opts.deviceId;
46505
+ if (opts.enrollmentType)
46506
+ attributes["av.enrollment.type"] = opts.enrollmentType;
46507
+ applySkillName(attributes, opts.skillName);
46508
+ const isError = opts.status === "error" || opts.phase === "fail";
46509
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46510
+ return {
46511
+ traceId: opts.traceId ?? generateTraceId(),
46512
+ spanId: opts.spanId ?? generateSpanId(),
46513
+ parentSpanId: opts.parentSpanId,
46514
+ name: "av.enrollment",
46515
+ kind: "internal",
46516
+ startTime: now - opts.latencyMs,
46517
+ endTime: now,
46518
+ attributes,
46519
+ status
46520
+ };
46521
+ }
46522
+ function buildRoomSpan(opts) {
46523
+ const now = Date.now();
46524
+ const attributes = {
46525
+ "av.room.id": opts.roomId,
46526
+ "av.room.operation": opts.operation
46527
+ };
46528
+ if (opts.roomName)
46529
+ attributes["av.room.name"] = opts.roomName;
46530
+ if (opts.memberCount !== void 0)
46531
+ attributes["av.room.member_count"] = opts.memberCount;
46532
+ applySkillName(attributes, opts.skillName);
46533
+ const isError = opts.status === "error";
46534
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46535
+ return {
46536
+ traceId: opts.traceId ?? generateTraceId(),
46537
+ spanId: opts.spanId ?? generateSpanId(),
46538
+ parentSpanId: opts.parentSpanId,
46539
+ name: "av.room",
46540
+ kind: "internal",
46541
+ startTime: now - opts.latencyMs,
46542
+ endTime: now,
46543
+ attributes,
46544
+ status
46545
+ };
46546
+ }
46547
+ function buildTrustSpan(opts) {
46548
+ const now = Date.now();
46549
+ const attributes = {
46550
+ "av.trust.agent_hub_address": opts.agentHubAddress,
46551
+ "av.trust.operation": opts.operation
46552
+ };
46553
+ if (opts.previousTier)
46554
+ attributes["av.trust.previous_tier"] = opts.previousTier;
46555
+ if (opts.newTier)
46556
+ attributes["av.trust.new_tier"] = opts.newTier;
46557
+ if (opts.overallScore !== void 0)
46558
+ attributes["av.trust.overall_score"] = opts.overallScore;
46559
+ if (opts.dimension)
46560
+ attributes["av.trust.dimension"] = opts.dimension;
46561
+ if (opts.dimensionScore !== void 0)
46562
+ attributes["av.trust.dimension_score"] = opts.dimensionScore;
46563
+ applySkillName(attributes, opts.skillName);
46564
+ const isError = opts.status === "error";
46565
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46566
+ return {
46567
+ traceId: opts.traceId ?? generateTraceId(),
46568
+ spanId: opts.spanId ?? generateSpanId(),
46569
+ parentSpanId: opts.parentSpanId,
46570
+ name: "av.trust",
46571
+ kind: "internal",
46572
+ startTime: now - opts.latencyMs,
46573
+ endTime: now,
46574
+ attributes,
46575
+ status
46576
+ };
46577
+ }
46578
+ function buildEvalRunSpan(opts) {
46579
+ const now = Date.now();
46580
+ const attributes = {
46581
+ "av.eval.scenario_id": opts.scenarioId,
46582
+ "av.eval.agent_id": opts.agentId,
46583
+ "av.eval.status": opts.status,
46584
+ "av.eval.latency_ms": opts.latencyMs
46585
+ };
46586
+ if (opts.scenarioName)
46587
+ attributes["av.eval.scenario_name"] = opts.scenarioName;
46588
+ if (opts.variationType)
46589
+ attributes["av.eval.variation_type"] = opts.variationType;
46590
+ if (opts.shiftMagnitude !== void 0)
46591
+ attributes["av.eval.shift_magnitude"] = opts.shiftMagnitude;
46592
+ if (opts.outcomeMatch !== void 0)
46593
+ attributes["av.eval.outcome_match"] = opts.outcomeMatch;
46594
+ if (opts.flagged !== void 0)
46595
+ attributes["av.eval.flagged"] = opts.flagged;
46596
+ if (opts.flagReason)
46597
+ attributes["av.eval.flag_reason"] = opts.flagReason;
46598
+ const isError = opts.status === "failed";
46599
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46600
+ return {
46601
+ traceId: opts.traceId ?? generateTraceId(),
46602
+ spanId: opts.spanId ?? generateSpanId(),
46603
+ parentSpanId: opts.parentSpanId,
46604
+ name: "av.eval.run",
46605
+ kind: "internal",
46606
+ startTime: now - opts.latencyMs,
46607
+ endTime: now,
46608
+ attributes,
46609
+ status
45721
46610
  };
45722
46611
  }
45723
46612
  function buildTraceparent(span) {
45724
46613
  return `00-${span.traceId}-${span.spanId}-01`;
45725
46614
  }
46615
+ function parseTraceparent(header) {
46616
+ const parts = header.split("-");
46617
+ if (parts.length !== 4)
46618
+ return null;
46619
+ const [version2, traceId, parentId, traceFlags] = parts;
46620
+ if (!version2 || !traceId || !parentId || !traceFlags)
46621
+ return null;
46622
+ if (traceId.length !== 32 || parentId.length !== 16)
46623
+ return null;
46624
+ return { version: version2, traceId, parentId, traceFlags };
46625
+ }
46626
+ function spanToTraceContext(span, tracestate) {
46627
+ return {
46628
+ traceparent: buildTraceparent(span),
46629
+ tracestate: tracestate ?? `av=s:${span.spanId}`
46630
+ };
46631
+ }
46632
+ function propagateContext(incomingTraceparent) {
46633
+ const parsed = parseTraceparent(incomingTraceparent);
46634
+ if (!parsed)
46635
+ return null;
46636
+ return {
46637
+ traceId: parsed.traceId,
46638
+ parentSpanId: parsed.parentId,
46639
+ spanId: generateSpanId()
46640
+ };
46641
+ }
46642
+ function spanToW3CHeaders(span, tracestate) {
46643
+ return {
46644
+ traceparent: buildTraceparent(span),
46645
+ tracestate: tracestate ?? `av=s:${span.spanId}`
46646
+ };
46647
+ }
45726
46648
  var init_telemetry = __esm({
45727
46649
  "../crypto/dist/telemetry.js"() {
45728
46650
  "use strict";
@@ -45893,6 +46815,29 @@ var init_telemetry_reporter = __esm({
45893
46815
  });
45894
46816
 
45895
46817
  // ../crypto/dist/backup.js
46818
+ async function generateBackupCode() {
46819
+ await libsodium_wrappers_default.ready;
46820
+ const bytes = libsodium_wrappers_default.randombytes_buf(13);
46821
+ let bits = 0n;
46822
+ for (const b2 of bytes) {
46823
+ bits = bits << 8n | BigInt(b2);
46824
+ }
46825
+ bits >>= 4n;
46826
+ let code = "";
46827
+ for (let i2 = 0; i2 < 20; i2++) {
46828
+ const idx = Number(bits & 0x1fn);
46829
+ code = CROCKFORD[idx] + code;
46830
+ bits >>= 5n;
46831
+ }
46832
+ return code;
46833
+ }
46834
+ function formatBackupCode(code) {
46835
+ const clean5 = code.replace(/[-\s]/g, "").toUpperCase();
46836
+ return clean5.match(/.{1,4}/g)?.join("-") ?? clean5;
46837
+ }
46838
+ function normalizeBackupCode(input) {
46839
+ return input.replace(/[-\s]/g, "").toUpperCase();
46840
+ }
45896
46841
  async function deriveBackupKey(code, salt) {
45897
46842
  await libsodium_wrappers_default.ready;
45898
46843
  return libsodium_wrappers_default.crypto_pwhash(KEY_BYTES, code, salt, ARGON2_OPSLIMIT, ARGON2_MEMLIMIT, libsodium_wrappers_default.crypto_pwhash_ALG_ARGON2ID13);
@@ -45914,28 +46859,88 @@ async function encryptBackupWithKey(bundle, key, salt) {
45914
46859
  result.set(ciphertext, SALT_BYTES + NONCE_BYTES);
45915
46860
  return result;
45916
46861
  }
46862
+ async function decryptBackup(encrypted, code) {
46863
+ await libsodium_wrappers_default.ready;
46864
+ const minLen = SALT_BYTES + NONCE_BYTES + libsodium_wrappers_default.crypto_aead_xchacha20poly1305_ietf_ABYTES;
46865
+ if (encrypted.length < minLen) {
46866
+ throw new Error("Incorrect backup code or corrupt backup");
46867
+ }
46868
+ const salt = encrypted.slice(0, SALT_BYTES);
46869
+ const nonce = encrypted.slice(SALT_BYTES, SALT_BYTES + NONCE_BYTES);
46870
+ const ciphertext = encrypted.slice(SALT_BYTES + NONCE_BYTES);
46871
+ const key = await deriveBackupKey(code, salt);
46872
+ let plaintext;
46873
+ try {
46874
+ plaintext = libsodium_wrappers_default.crypto_aead_xchacha20poly1305_ietf_decrypt(null, ciphertext, null, nonce, key);
46875
+ } catch {
46876
+ throw new Error("Incorrect backup code or corrupt backup");
46877
+ }
46878
+ let bundle;
46879
+ try {
46880
+ bundle = JSON.parse(libsodium_wrappers_default.to_string(plaintext));
46881
+ } catch {
46882
+ throw new Error("Incorrect backup code or corrupt backup");
46883
+ }
46884
+ if (bundle.version !== BACKUP_VERSION) {
46885
+ throw new Error(`Unsupported backup version: ${bundle.version}`);
46886
+ }
46887
+ return bundle;
46888
+ }
45917
46889
  async function hashBackupCode(code) {
45918
46890
  await libsodium_wrappers_default.ready;
45919
46891
  return libsodium_wrappers_default.crypto_generichash(32, libsodium_wrappers_default.from_string(code));
45920
46892
  }
45921
- var ARGON2_OPSLIMIT, ARGON2_MEMLIMIT, SALT_BYTES, NONCE_BYTES, KEY_BYTES, MAX_BACKUP_SIZE;
46893
+ var CROCKFORD, ARGON2_OPSLIMIT, ARGON2_MEMLIMIT, SALT_BYTES, NONCE_BYTES, KEY_BYTES, BACKUP_VERSION, MAX_BACKUP_SIZE;
45922
46894
  var init_backup = __esm({
45923
46895
  async "../crypto/dist/backup.js"() {
45924
46896
  "use strict";
45925
46897
  await init_libsodium_wrappers();
46898
+ CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
45926
46899
  ARGON2_OPSLIMIT = 2;
45927
46900
  ARGON2_MEMLIMIT = 67108864;
45928
46901
  SALT_BYTES = 16;
45929
46902
  NONCE_BYTES = 24;
45930
46903
  KEY_BYTES = 32;
46904
+ BACKUP_VERSION = 1;
45931
46905
  MAX_BACKUP_SIZE = 512 * 1024;
45932
46906
  }
45933
46907
  });
45934
46908
 
45935
46909
  // ../crypto/dist/approval.js
46910
+ async function createApprovalArtifact(content, privateKeyHex) {
46911
+ await libsodium_wrappers_default.ready;
46912
+ const sodium = libsodium_wrappers_default;
46913
+ const privateKey = sodium.from_hex(privateKeyHex);
46914
+ const publicKey = privateKey.slice(32);
46915
+ const message = canonicalize(content);
46916
+ const signatureBytes = sodium.crypto_sign_detached(message, privateKey);
46917
+ return {
46918
+ content,
46919
+ signature: sodium.to_hex(signatureBytes),
46920
+ signerPublicKey: sodium.to_hex(publicKey),
46921
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
46922
+ version: 1
46923
+ };
46924
+ }
46925
+ async function verifyApprovalArtifact(artifact, expectedPublicKeyHex) {
46926
+ await libsodium_wrappers_default.ready;
46927
+ const sodium = libsodium_wrappers_default;
46928
+ if (expectedPublicKeyHex && artifact.signerPublicKey !== expectedPublicKeyHex) {
46929
+ return false;
46930
+ }
46931
+ try {
46932
+ const publicKey = sodium.from_hex(artifact.signerPublicKey);
46933
+ const signature = sodium.from_hex(artifact.signature);
46934
+ const message = canonicalize(artifact.content);
46935
+ return sodium.crypto_sign_verify_detached(signature, message, publicKey);
46936
+ } catch {
46937
+ return false;
46938
+ }
46939
+ }
45936
46940
  var init_approval = __esm({
45937
46941
  async "../crypto/dist/approval.js"() {
45938
46942
  "use strict";
46943
+ await init_libsodium_wrappers();
45939
46944
  await init_did();
45940
46945
  }
45941
46946
  });
@@ -54882,7 +55887,7 @@ function byteSwap32(arr) {
54882
55887
  }
54883
55888
  return arr;
54884
55889
  }
54885
- function bytesToHex3(bytes) {
55890
+ function bytesToHex4(bytes) {
54886
55891
  abytes3(bytes);
54887
55892
  if (hasHexBuiltin)
54888
55893
  return bytes.toHex();
@@ -54901,7 +55906,7 @@ function asciiToBase16(ch) {
54901
55906
  return ch - (asciis.a - 10);
54902
55907
  return;
54903
55908
  }
54904
- function hexToBytes3(hex3) {
55909
+ function hexToBytes4(hex3) {
54905
55910
  if (typeof hex3 !== "string")
54906
55911
  throw new Error("hex string expected, got " + typeof hex3);
54907
55912
  if (hasHexBuiltin)
@@ -55197,7 +56202,7 @@ var init_u642 = __esm({
55197
56202
  });
55198
56203
 
55199
56204
  // ../../node_modules/@noble/curves/node_modules/@noble/hashes/esm/sha2.js
55200
- var SHA256_K, SHA256_W, SHA256, K512, SHA512_Kh, SHA512_Kl, SHA512_W_H, SHA512_W_L, SHA512, SHA384, sha2562, sha5122, sha3842;
56205
+ var SHA256_K, SHA256_W, SHA256, K512, SHA512_Kh, SHA512_Kl, SHA512_W_H, SHA512_W_L, SHA512, SHA384, sha2563, sha5122, sha3842;
55201
56206
  var init_sha22 = __esm({
55202
56207
  "../../node_modules/@noble/curves/node_modules/@noble/hashes/esm/sha2.js"() {
55203
56208
  init_md2();
@@ -55558,7 +56563,7 @@ var init_sha22 = __esm({
55558
56563
  this.Hl = SHA384_IV2[15] | 0;
55559
56564
  }
55560
56565
  };
55561
- sha2562 = /* @__PURE__ */ createHasher2(() => new SHA256());
56566
+ sha2563 = /* @__PURE__ */ createHasher2(() => new SHA256());
55562
56567
  sha5122 = /* @__PURE__ */ createHasher2(() => new SHA512());
55563
56568
  sha3842 = /* @__PURE__ */ createHasher2(() => new SHA384());
55564
56569
  }
@@ -55594,14 +56599,14 @@ function hexToNumber3(hex3) {
55594
56599
  return hex3 === "" ? _0n2 : BigInt("0x" + hex3);
55595
56600
  }
55596
56601
  function bytesToNumberBE(bytes) {
55597
- return hexToNumber3(bytesToHex3(bytes));
56602
+ return hexToNumber3(bytesToHex4(bytes));
55598
56603
  }
55599
56604
  function bytesToNumberLE2(bytes) {
55600
56605
  abytes3(bytes);
55601
- return hexToNumber3(bytesToHex3(Uint8Array.from(bytes).reverse()));
56606
+ return hexToNumber3(bytesToHex4(Uint8Array.from(bytes).reverse()));
55602
56607
  }
55603
56608
  function numberToBytesBE2(n2, len) {
55604
- return hexToBytes3(n2.toString(16).padStart(len * 2, "0"));
56609
+ return hexToBytes4(n2.toString(16).padStart(len * 2, "0"));
55605
56610
  }
55606
56611
  function numberToBytesLE2(n2, len) {
55607
56612
  return numberToBytesBE2(n2, len).reverse();
@@ -55610,7 +56615,7 @@ function ensureBytes(title, hex3, expectedLength) {
55610
56615
  let res;
55611
56616
  if (typeof hex3 === "string") {
55612
56617
  try {
55613
- res = hexToBytes3(hex3);
56618
+ res = hexToBytes4(hex3);
55614
56619
  } catch (e) {
55615
56620
  throw new Error(title + " must be hex string or Uint8Array, cause: " + e);
55616
56621
  }
@@ -56638,7 +57643,7 @@ function edwards(params, extraOpts = {}) {
56638
57643
  return bytes;
56639
57644
  }
56640
57645
  toHex() {
56641
- return bytesToHex3(this.toBytes());
57646
+ return bytesToHex4(this.toBytes());
56642
57647
  }
56643
57648
  toString() {
56644
57649
  return `<Point ${this.is0() ? "ZERO" : this.toHex()}>`;
@@ -56910,7 +57915,7 @@ var init_edwards = __esm({
56910
57915
  return this.ep.toAffine(invertedZ);
56911
57916
  }
56912
57917
  toHex() {
56913
- return bytesToHex3(this.toBytes());
57918
+ return bytesToHex4(this.toBytes());
56914
57919
  }
56915
57920
  toString() {
56916
57921
  return this.toHex();
@@ -58711,7 +59716,7 @@ function weierstrassN(params, extraOpts = {}) {
58711
59716
  return encodePoint(Point, this, isCompressed);
58712
59717
  }
58713
59718
  toHex(isCompressed = true) {
58714
- return bytesToHex3(this.toBytes(isCompressed));
59719
+ return bytesToHex4(this.toBytes(isCompressed));
58715
59720
  }
58716
59721
  toString() {
58717
59722
  return `<Point ${this.is0() ? "ZERO" : this.toHex()}>`;
@@ -58995,7 +60000,7 @@ function ecdsa(Point, hash2, ecdsaOpts = {}) {
58995
60000
  return new Signature(Fn3.fromBytes(r2), Fn3.fromBytes(s2), recid);
58996
60001
  }
58997
60002
  static fromHex(hex3, format) {
58998
- return this.fromBytes(hexToBytes3(hex3), format);
60003
+ return this.fromBytes(hexToBytes4(hex3), format);
58999
60004
  }
59000
60005
  addRecoveryBit(recovery) {
59001
60006
  return new Signature(this.r, this.s, recovery);
@@ -59030,7 +60035,7 @@ function ecdsa(Point, hash2, ecdsaOpts = {}) {
59030
60035
  toBytes(format = defaultSigOpts_format) {
59031
60036
  validateSigFormat(format);
59032
60037
  if (format === "der")
59033
- return hexToBytes3(DER.hexFromSig(this));
60038
+ return hexToBytes4(DER.hexFromSig(this));
59034
60039
  const r2 = Fn3.toBytes(this.r);
59035
60040
  const s2 = Fn3.toBytes(this.s);
59036
60041
  if (format === "recovered") {
@@ -59041,7 +60046,7 @@ function ecdsa(Point, hash2, ecdsaOpts = {}) {
59041
60046
  return concatBytes2(r2, s2);
59042
60047
  }
59043
60048
  toHex(format) {
59044
- return bytesToHex3(this.toBytes(format));
60049
+ return bytesToHex4(this.toBytes(format));
59045
60050
  }
59046
60051
  // TODO: remove
59047
60052
  assertValidity() {
@@ -59059,13 +60064,13 @@ function ecdsa(Point, hash2, ecdsaOpts = {}) {
59059
60064
  return this.toBytes("der");
59060
60065
  }
59061
60066
  toDERHex() {
59062
- return bytesToHex3(this.toBytes("der"));
60067
+ return bytesToHex4(this.toBytes("der"));
59063
60068
  }
59064
60069
  toCompactRawBytes() {
59065
60070
  return this.toBytes("compact");
59066
60071
  }
59067
60072
  toCompactHex() {
59068
- return bytesToHex3(this.toBytes("compact"));
60073
+ return bytesToHex4(this.toBytes("compact"));
59069
60074
  }
59070
60075
  }
59071
60076
  const bits2int = ecdsaOpts.bits2int || function bits2int_def(bytes) {
@@ -59444,7 +60449,7 @@ var init_nist = __esm({
59444
60449
  Fp256 = Field(p256_CURVE.p);
59445
60450
  Fp384 = Field(p384_CURVE.p);
59446
60451
  Fp521 = Field(p521_CURVE.p);
59447
- p256 = createCurve({ ...p256_CURVE, Fp: Fp256, lowS: false }, sha2562);
60452
+ p256 = createCurve({ ...p256_CURVE, Fp: Fp256, lowS: false }, sha2563);
59448
60453
  p256_hasher = /* @__PURE__ */ (() => {
59449
60454
  return createHasher3(p256.Point, createSWU(p256.Point, {
59450
60455
  A: p256_CURVE.a,
@@ -59457,7 +60462,7 @@ var init_nist = __esm({
59457
60462
  m: 1,
59458
60463
  k: 128,
59459
60464
  expand: "xmd",
59460
- hash: sha2562
60465
+ hash: sha2563
59461
60466
  });
59462
60467
  })();
59463
60468
  p384 = createCurve({ ...p384_CURVE, Fp: Fp384, lowS: false }, sha3842);
@@ -59965,7 +60970,7 @@ var init_u643 = __esm({
59965
60970
  });
59966
60971
 
59967
60972
  // ../crypto/node_modules/@noble/hashes/sha2.js
59968
- var SHA256_K2, SHA256_W2, SHA2_32B, _SHA256, K5122, SHA512_Kh2, SHA512_Kl2, SHA512_W_H2, SHA512_W_L2, SHA2_64B, _SHA512, _SHA384, sha2563, sha5123, sha3843;
60973
+ var SHA256_K2, SHA256_W2, SHA2_32B, _SHA256, K5122, SHA512_Kh2, SHA512_Kl2, SHA512_W_H2, SHA512_W_L2, SHA2_64B, _SHA512, _SHA384, sha2564, sha5123, sha3843;
59969
60974
  var init_sha23 = __esm({
59970
60975
  "../crypto/node_modules/@noble/hashes/sha2.js"() {
59971
60976
  init_md3();
@@ -60338,7 +61343,7 @@ var init_sha23 = __esm({
60338
61343
  super(48);
60339
61344
  }
60340
61345
  };
60341
- sha2563 = /* @__PURE__ */ createHasher4(
61346
+ sha2564 = /* @__PURE__ */ createHasher4(
60342
61347
  () => new _SHA256(),
60343
61348
  /* @__PURE__ */ oidNist2(1)
60344
61349
  );
@@ -60436,7 +61441,7 @@ function makeHashImpl2(h2) {
60436
61441
  async digest(data) {
60437
61442
  switch (h2) {
60438
61443
  case "SHA-256":
60439
- return sha2563(data);
61444
+ return sha2564(data);
60440
61445
  case "SHA-384":
60441
61446
  return sha3843(data);
60442
61447
  case "SHA-512":
@@ -60448,7 +61453,7 @@ function makeHashImpl2(h2) {
60448
61453
  async mac(key, data) {
60449
61454
  switch (h2) {
60450
61455
  case "SHA-256":
60451
- return hmac3(sha2563, key, data);
61456
+ return hmac3(sha2564, key, data);
60452
61457
  case "SHA-384":
60453
61458
  return hmac3(sha3843, key, data);
60454
61459
  case "SHA-512":
@@ -61615,6 +62620,92 @@ var init_mls_group = __esm({
61615
62620
  });
61616
62621
 
61617
62622
  // ../crypto/dist/index.js
62623
+ var dist_exports = {};
62624
+ __export(dist_exports, {
62625
+ AV_CREDENTIAL_CONTEXT: () => AV_CREDENTIAL_CONTEXT,
62626
+ CRYPTOSUITE: () => CRYPTOSUITE,
62627
+ DOMAIN_DID_DOCUMENT: () => DOMAIN_DID_DOCUMENT,
62628
+ DOMAIN_TRANSFER_ACCEPT: () => DOMAIN_TRANSFER_ACCEPT,
62629
+ DOMAIN_TRANSFER_INTENT: () => DOMAIN_TRANSFER_INTENT,
62630
+ DoubleRatchet: () => DoubleRatchet,
62631
+ MLSGroupManager: () => MLSGroupManager,
62632
+ ScanEngine: () => ScanEngine,
62633
+ TelemetryReporter: () => TelemetryReporter,
62634
+ VC_CONTEXT_V2: () => VC_CONTEXT_V2,
62635
+ base64ToBytes: () => base64ToBytes,
62636
+ buildA2aSpan: () => buildA2aSpan,
62637
+ buildActionSpan: () => buildActionSpan,
62638
+ buildAgentTrustCredential: () => buildAgentTrustCredential,
62639
+ buildAgentTrustReportCredential: () => buildAgentTrustReportCredential,
62640
+ buildCapabilitySpan: () => buildCapabilitySpan,
62641
+ buildDecisionSpan: () => buildDecisionSpan,
62642
+ buildDidDocument: () => buildDidDocument,
62643
+ buildEnrollmentSpan: () => buildEnrollmentSpan,
62644
+ buildErrorSpan: () => buildErrorSpan,
62645
+ buildEvalRunSpan: () => buildEvalRunSpan,
62646
+ buildEvalSpan: () => buildEvalSpan,
62647
+ buildForgeSpan: () => buildForgeSpan,
62648
+ buildHttpSpan: () => buildHttpSpan,
62649
+ buildLlmSpan: () => buildLlmSpan,
62650
+ buildNavSpan: () => buildNavSpan,
62651
+ buildPerformanceRecord: () => buildPerformanceRecord,
62652
+ buildPolicyViolationSpan: () => buildPolicyViolationSpan,
62653
+ buildResyncSpan: () => buildResyncSpan,
62654
+ buildRoomSpan: () => buildRoomSpan,
62655
+ buildScanSpan: () => buildScanSpan,
62656
+ buildSkillAttestation: () => buildSkillAttestation,
62657
+ buildSkillInvocationSpan: () => buildSkillInvocationSpan,
62658
+ buildTaskSpan: () => buildTaskSpan,
62659
+ buildToolSpan: () => buildToolSpan,
62660
+ buildTraceparent: () => buildTraceparent,
62661
+ buildTrustSpan: () => buildTrustSpan,
62662
+ buildVerifiablePresentation: () => buildVerifiablePresentation,
62663
+ buildWorkspaceSpan: () => buildWorkspaceSpan,
62664
+ bytesToBase64: () => bytesToBase64,
62665
+ bytesToHex: () => bytesToHex2,
62666
+ canonicalize: () => canonicalize,
62667
+ computeDidHash: () => computeDidHash,
62668
+ computeFileDigest: () => computeFileDigest,
62669
+ computeFingerprint: () => computeFingerprint,
62670
+ createApprovalArtifact: () => createApprovalArtifact,
62671
+ createProofOfPossession: () => createProofOfPossession,
62672
+ decryptBackup: () => decryptBackup,
62673
+ decryptFile: () => decryptFile,
62674
+ deriveBackupKey: () => deriveBackupKey,
62675
+ encryptBackup: () => encryptBackup,
62676
+ encryptBackupWithKey: () => encryptBackupWithKey,
62677
+ encryptFile: () => encryptFile,
62678
+ encryptedMessageToHexTransport: () => encryptedMessageToHexTransport,
62679
+ encryptedMessageToTransport: () => encryptedMessageToTransport,
62680
+ encryptedMessageToTransportV2: () => encryptedMessageToTransportV2,
62681
+ encryptedMessageToTransportV2Full: () => encryptedMessageToTransportV2Full,
62682
+ formatBackupCode: () => formatBackupCode,
62683
+ generateBackupCode: () => generateBackupCode,
62684
+ generateEphemeralKeypair: () => generateEphemeralKeypair,
62685
+ generateIdentityKeypair: () => generateIdentityKeypair,
62686
+ hashBackupCode: () => hashBackupCode,
62687
+ hexToBytes: () => hexToBytes2,
62688
+ hexTransportToEncryptedMessage: () => hexTransportToEncryptedMessage,
62689
+ issueCredential: () => issueCredential,
62690
+ multibaseToPublicKey: () => multibaseToPublicKey,
62691
+ normalizeBackupCode: () => normalizeBackupCode,
62692
+ parseTraceparent: () => parseTraceparent,
62693
+ performX3DH: () => performX3DH,
62694
+ presentCredentials: () => presentCredentials,
62695
+ propagateContext: () => propagateContext,
62696
+ publicKeyToMultibase: () => publicKeyToMultibase,
62697
+ signDocument: () => signDocument,
62698
+ signWithDataIntegrity: () => signWithDataIntegrity,
62699
+ spanToTraceContext: () => spanToTraceContext,
62700
+ spanToW3CHeaders: () => spanToW3CHeaders,
62701
+ transportToEncryptedMessage: () => transportToEncryptedMessage,
62702
+ transportV2ToEncryptedMessage: () => transportV2ToEncryptedMessage,
62703
+ verifyApprovalArtifact: () => verifyApprovalArtifact,
62704
+ verifyDataIntegrity: () => verifyDataIntegrity,
62705
+ verifyDocumentSignature: () => verifyDocumentSignature,
62706
+ verifyMerkleProof: () => verifyMerkleProof,
62707
+ verifyProofOfPossession: () => verifyProofOfPossession
62708
+ });
61618
62709
  var init_dist = __esm({
61619
62710
  async "../crypto/dist/index.js"() {
61620
62711
  "use strict";
@@ -61905,7 +62996,7 @@ async function uploadBackupToServer(state, backupCode, apiUrl2, deviceJwt) {
61905
62996
  },
61906
62997
  body: JSON.stringify({
61907
62998
  backup_blob: bytesToBase64(encrypted),
61908
- backup_code_hash: bytesToHex(codeHash)
62999
+ backup_code_hash: bytesToHex2(codeHash)
61909
63000
  })
61910
63001
  });
61911
63002
  if (!resp.ok) {
@@ -62549,6 +63640,8 @@ var init_channel = __esm({
62549
63640
  _mlsGroups = /* @__PURE__ */ new Map();
62550
63641
  /** Cached MLS KeyPackage bundle for this device (regenerated on each connect). */
62551
63642
  _mlsKeyPackage = null;
63643
+ /** Pending KeyPackage bundle from request-Welcome flow (used by _handleMlsWelcome). */
63644
+ _pendingMlsKpBundle;
62552
63645
  /** In-memory credential store for renter-provided credentials (never persisted). */
62553
63646
  _credentialStore = new CredentialStore();
62554
63647
  /** Dedup buffer for A2A message IDs (prevents double-delivery via direct + Redis) */
@@ -62647,6 +63740,24 @@ var init_channel = __esm({
62647
63740
  if (this._persisted.seenA2AMessageIds) {
62648
63741
  this._a2aSeenMessageIds = new Set(this._persisted.seenA2AMessageIds.slice(-_SecureChannel.A2A_SEEN_MAX));
62649
63742
  }
63743
+ if (this._persisted?.rooms) {
63744
+ const roomConvIds = /* @__PURE__ */ new Set();
63745
+ for (const room of Object.values(this._persisted.rooms)) {
63746
+ for (const cid of room.conversationIds || []) {
63747
+ roomConvIds.add(cid);
63748
+ }
63749
+ }
63750
+ let cleanedCount = 0;
63751
+ for (const cid of roomConvIds) {
63752
+ if (this._persisted.sessions[cid]) {
63753
+ delete this._persisted.sessions[cid];
63754
+ cleanedCount++;
63755
+ }
63756
+ }
63757
+ if (cleanedCount > 0) {
63758
+ console.log(`[SecureChannel] Cleaned ${cleanedCount} stale DR room sessions`);
63759
+ }
63760
+ }
62650
63761
  for (const [convId, sessionData] of Object.entries(
62651
63762
  this._persisted.sessions
62652
63763
  )) {
@@ -63019,89 +64130,21 @@ var init_channel = __esm({
63019
64130
  }
63020
64131
  // --- Multi-agent room methods ---
63021
64132
  /**
63022
- * Join a room by performing X3DH key exchange with each member
63023
- * for the pairwise conversations involving this device.
64133
+ * Join a room by collecting pairwise conversation IDs involving this device.
64134
+ * Encryption is handled by MLS group operations, not per-member DR sessions.
63024
64135
  */
63025
64136
  async joinRoom(roomData) {
63026
64137
  if (!this._persisted) {
63027
64138
  throw new Error("Channel not initialized");
63028
64139
  }
63029
64140
  await libsodium_wrappers_default.ready;
63030
- if (roomData.forceRekey) {
63031
- let cleared = 0;
63032
- const existingRoom = this._persisted.rooms?.[roomData.roomId];
63033
- if (existingRoom) {
63034
- for (const convId of existingRoom.conversationIds) {
63035
- if (this._sessions.has(convId)) {
63036
- this._sessions.delete(convId);
63037
- cleared++;
63038
- }
63039
- delete this._persisted.sessions[convId];
63040
- }
63041
- }
63042
- if (this._persisted) {
63043
- this._persisted.lastMessageTimestamp = (/* @__PURE__ */ new Date()).toISOString();
63044
- }
63045
- console.log(
63046
- `[SecureChannel] Force rekey: cleared ${cleared} sessions for room ${roomData.roomId.slice(0, 8)}...`
63047
- );
63048
- }
63049
- const identity = this._persisted.identityKeypair;
63050
- const ephemeral = this._persisted.ephemeralKeypair;
63051
64141
  const myDeviceId = this._deviceId;
63052
64142
  const conversationIds = [];
63053
64143
  for (const conv of roomData.conversations) {
63054
64144
  if (conv.participantA !== myDeviceId && conv.participantB !== myDeviceId) {
63055
64145
  continue;
63056
64146
  }
63057
- if (this._sessions.has(conv.id)) {
63058
- conversationIds.push(conv.id);
63059
- continue;
63060
- }
63061
- const otherDeviceId = conv.participantA === myDeviceId ? conv.participantB : conv.participantA;
63062
- const otherMember = roomData.members.find((m2) => m2.deviceId === otherDeviceId);
63063
- if (!otherMember?.identityPublicKey) {
63064
- console.warn(
63065
- `[SecureChannel] No public key for member ${otherDeviceId.slice(0, 8)}..., skipping`
63066
- );
63067
- continue;
63068
- }
63069
- const isInitiator = myDeviceId < otherDeviceId;
63070
- const theirEphKey = otherMember.ephemeralPublicKey ?? otherMember.identityPublicKey;
63071
- const sharedSecret = performX3DH({
63072
- myIdentityPrivate: hexToBytes(identity.privateKey),
63073
- myEphemeralPrivate: hexToBytes(ephemeral.privateKey),
63074
- theirIdentityPublic: hexToBytes(otherMember.identityPublicKey),
63075
- theirEphemeralPublic: hexToBytes(theirEphKey),
63076
- isInitiator
63077
- });
63078
- const peerIdentityPub = hexToBytes(otherMember.identityPublicKey);
63079
- const ratchet = isInitiator ? DoubleRatchet.initSender(sharedSecret, {
63080
- publicKey: hexToBytes(identity.publicKey),
63081
- privateKey: hexToBytes(identity.privateKey),
63082
- keyType: "ed25519"
63083
- }, peerIdentityPub) : DoubleRatchet.initReceiver(sharedSecret, {
63084
- publicKey: hexToBytes(identity.publicKey),
63085
- privateKey: hexToBytes(identity.privateKey),
63086
- keyType: "ed25519"
63087
- }, peerIdentityPub);
63088
- this._sessions.set(conv.id, {
63089
- ownerDeviceId: otherDeviceId,
63090
- ratchet,
63091
- activated: isInitiator,
63092
- // initiator can send immediately
63093
- epoch: 1
63094
- });
63095
- this._persisted.sessions[conv.id] = {
63096
- ownerDeviceId: otherDeviceId,
63097
- ratchetState: ratchet.serialize(),
63098
- activated: isInitiator,
63099
- epoch: 1
63100
- };
63101
64147
  conversationIds.push(conv.id);
63102
- console.log(
63103
- `[SecureChannel] Room session initialized: conv ${conv.id.slice(0, 8)}... with ${otherDeviceId.slice(0, 8)}... (initiator=${isInitiator})`
63104
- );
63105
64148
  }
63106
64149
  if (!this._persisted.rooms) {
63107
64150
  this._persisted.rooms = {};
@@ -63197,68 +64240,15 @@ var init_channel = __esm({
63197
64240
  }
63198
64241
  return;
63199
64242
  } catch (mlsErr) {
63200
- console.warn(`[SecureChannel] MLS encrypt failed for room ${roomId.slice(0, 8)}, falling through to legacy:`, mlsErr);
63201
- }
63202
- }
63203
- }
63204
- const recipients = [];
63205
- for (const convId of room.conversationIds) {
63206
- const session = this._sessions.get(convId);
63207
- if (!session) {
63208
- console.warn(`[SecureChannel] No session for room conv ${convId.slice(0, 8)}..., skipping`);
63209
- continue;
63210
- }
63211
- const encrypted = session.ratchet.encrypt(plaintext);
63212
- const transport = encryptedMessageToTransport(encrypted);
63213
- recipients.push({
63214
- device_id: session.ownerDeviceId,
63215
- header_blob: transport.header_blob,
63216
- ciphertext: transport.ciphertext
63217
- });
63218
- }
63219
- if (recipients.length === 0) {
63220
- throw new Error("No active sessions in room");
63221
- }
63222
- await this._persistState();
63223
- if (this._state === "ready" && this._ws) {
63224
- this._ws.send(
63225
- JSON.stringify({
63226
- event: "room_message",
63227
- data: {
63228
- room_id: roomId,
63229
- recipients,
63230
- message_type: messageType,
63231
- priority: opts?.priority ?? "normal",
63232
- metadata: opts?.metadata
63233
- }
63234
- })
63235
- );
63236
- } else {
63237
- try {
63238
- const res = await fetch(
63239
- `${this.config.apiUrl}/api/v1/rooms/${roomId}/messages`,
63240
- {
63241
- method: "POST",
63242
- headers: {
63243
- "Content-Type": "application/json",
63244
- Authorization: `Bearer ${this._deviceJwt}`
63245
- },
63246
- body: JSON.stringify({
63247
- recipients,
63248
- message_type: messageType,
63249
- priority: opts?.priority ?? "normal",
63250
- metadata: opts?.metadata
63251
- })
63252
- }
63253
- );
63254
- if (!res.ok) {
63255
- const detail = await res.text();
63256
- throw new Error(`Room message failed (${res.status}): ${detail}`);
64243
+ throw new Error(
64244
+ `MLS encrypt failed for room ${roomId.slice(0, 8)}... \u2014 MLS group must be initialized before sending. Error: ${mlsErr}`
64245
+ );
63257
64246
  }
63258
- } catch (err) {
63259
- throw new Error(`Failed to send room message: ${err}`);
63260
64247
  }
63261
64248
  }
64249
+ throw new Error(
64250
+ `Room ${roomId.slice(0, 8)}... has no initialized MLS group. MLS initialization must complete before messages can be sent.`
64251
+ );
63262
64252
  }
63263
64253
  /**
63264
64254
  * Leave a room: remove sessions and persisted room state.
@@ -64088,9 +65078,9 @@ var init_channel = __esm({
64088
65078
  const result = await enrollDevice(
64089
65079
  this.config.apiUrl,
64090
65080
  this.config.inviteToken,
64091
- bytesToHex(identity.publicKey),
64092
- bytesToHex(ephemeral.publicKey),
64093
- bytesToHex(proof),
65081
+ bytesToHex2(identity.publicKey),
65082
+ bytesToHex2(ephemeral.publicKey),
65083
+ bytesToHex2(proof),
64094
65084
  this.config.platform
64095
65085
  );
64096
65086
  this._deviceId = result.device_id;
@@ -64104,12 +65094,12 @@ var init_channel = __esm({
64104
65094
  sessions: {},
64105
65095
  // populated after activation
64106
65096
  identityKeypair: {
64107
- publicKey: bytesToHex(identity.publicKey),
64108
- privateKey: bytesToHex(identity.privateKey)
65097
+ publicKey: bytesToHex2(identity.publicKey),
65098
+ privateKey: bytesToHex2(identity.privateKey)
64109
65099
  },
64110
65100
  ephemeralKeypair: {
64111
- publicKey: bytesToHex(ephemeral.publicKey),
64112
- privateKey: bytesToHex(ephemeral.privateKey)
65101
+ publicKey: bytesToHex2(ephemeral.publicKey),
65102
+ privateKey: bytesToHex2(ephemeral.privateKey)
64113
65103
  },
64114
65104
  fingerprint: result.fingerprint,
64115
65105
  messageHistory: []
@@ -64172,17 +65162,17 @@ var init_channel = __esm({
64172
65162
  const ownerIdentityKey = conv.owner_identity_public_key || result.owner_identity_public_key;
64173
65163
  const ownerEphemeralKey = conv.owner_ephemeral_public_key || result.owner_ephemeral_public_key || ownerIdentityKey;
64174
65164
  const sharedSecret = performX3DH({
64175
- myIdentityPrivate: hexToBytes(identity.privateKey),
64176
- myEphemeralPrivate: hexToBytes(ephemeral.privateKey),
64177
- theirIdentityPublic: hexToBytes(ownerIdentityKey),
64178
- theirEphemeralPublic: hexToBytes(ownerEphemeralKey),
65165
+ myIdentityPrivate: hexToBytes2(identity.privateKey),
65166
+ myEphemeralPrivate: hexToBytes2(ephemeral.privateKey),
65167
+ theirIdentityPublic: hexToBytes2(ownerIdentityKey),
65168
+ theirEphemeralPublic: hexToBytes2(ownerEphemeralKey),
64179
65169
  isInitiator: false
64180
65170
  });
64181
65171
  const ratchet = DoubleRatchet.initReceiver(sharedSecret, {
64182
- publicKey: hexToBytes(identity.publicKey),
64183
- privateKey: hexToBytes(identity.privateKey),
65172
+ publicKey: hexToBytes2(identity.publicKey),
65173
+ privateKey: hexToBytes2(identity.privateKey),
64184
65174
  keyType: "ed25519"
64185
- }, hexToBytes(ownerIdentityKey));
65175
+ }, hexToBytes2(ownerIdentityKey));
64186
65176
  this._sessions.set(conv.conversation_id, {
64187
65177
  ownerDeviceId: conv.owner_device_id,
64188
65178
  ratchet,
@@ -65308,19 +66298,19 @@ ${messageText}`;
65308
66298
  const identity = this._persisted.identityKeypair;
65309
66299
  const ephemeral = this._persisted.ephemeralKeypair;
65310
66300
  const sharedSecret = performX3DH({
65311
- myIdentityPrivate: hexToBytes(identity.privateKey),
65312
- myEphemeralPrivate: hexToBytes(ephemeral.privateKey),
65313
- theirIdentityPublic: hexToBytes(event.owner_identity_public_key),
65314
- theirEphemeralPublic: hexToBytes(
66301
+ myIdentityPrivate: hexToBytes2(identity.privateKey),
66302
+ myEphemeralPrivate: hexToBytes2(ephemeral.privateKey),
66303
+ theirIdentityPublic: hexToBytes2(event.owner_identity_public_key),
66304
+ theirEphemeralPublic: hexToBytes2(
65315
66305
  event.owner_ephemeral_public_key ?? event.owner_identity_public_key
65316
66306
  ),
65317
66307
  isInitiator: false
65318
66308
  });
65319
66309
  const ratchet = DoubleRatchet.initReceiver(sharedSecret, {
65320
- publicKey: hexToBytes(identity.publicKey),
65321
- privateKey: hexToBytes(identity.privateKey),
66310
+ publicKey: hexToBytes2(identity.publicKey),
66311
+ privateKey: hexToBytes2(identity.privateKey),
65322
66312
  keyType: "ed25519"
65323
- }, hexToBytes(event.owner_identity_public_key));
66313
+ }, hexToBytes2(event.owner_identity_public_key));
65324
66314
  this._sessions.set(event.conversation_id, {
65325
66315
  ownerDeviceId: event.owner_device_id,
65326
66316
  ratchet,
@@ -65367,17 +66357,17 @@ ${messageText}`;
65367
66357
  const identity = this._persisted.identityKeypair;
65368
66358
  const ephemeral = this._persisted.ephemeralKeypair;
65369
66359
  const sharedSecret = performX3DH({
65370
- myIdentityPrivate: hexToBytes(identity.privateKey),
65371
- myEphemeralPrivate: hexToBytes(ephemeral.privateKey),
65372
- theirIdentityPublic: hexToBytes(data.identity_public_key),
65373
- theirEphemeralPublic: hexToBytes(data.ephemeral_public_key),
66360
+ myIdentityPrivate: hexToBytes2(identity.privateKey),
66361
+ myEphemeralPrivate: hexToBytes2(ephemeral.privateKey),
66362
+ theirIdentityPublic: hexToBytes2(data.identity_public_key),
66363
+ theirEphemeralPublic: hexToBytes2(data.ephemeral_public_key),
65374
66364
  isInitiator: false
65375
66365
  });
65376
66366
  const ratchet = DoubleRatchet.initReceiver(sharedSecret, {
65377
- publicKey: hexToBytes(identity.publicKey),
65378
- privateKey: hexToBytes(identity.privateKey),
66367
+ publicKey: hexToBytes2(identity.publicKey),
66368
+ privateKey: hexToBytes2(identity.privateKey),
65379
66369
  keyType: "ed25519"
65380
- }, hexToBytes(data.identity_public_key));
66370
+ }, hexToBytes2(data.identity_public_key));
65381
66371
  const existingSession = this._sessions.get(convId);
65382
66372
  const existingPersisted = this._persisted.sessions[convId];
65383
66373
  const ownerDeviceId = data.sender_device_id ?? existingSession?.ownerDeviceId ?? "";
@@ -65418,250 +66408,8 @@ ${messageText}`;
65418
66408
  this.emit("error", err);
65419
66409
  }
65420
66410
  }
65421
- /**
65422
- * Send a resync_request for a room conversation if the cooldown has elapsed.
65423
- * Shared by all room ratchet failure paths to avoid code duplication.
65424
- */
65425
- _sendRoomResyncIfCooled(convId, reason, session) {
65426
- const RESYNC_COOLDOWN_MS = 5 * 60 * 1e3;
65427
- const lastResync = this._lastResyncRequest.get(convId) ?? 0;
65428
- if (Date.now() - lastResync > RESYNC_COOLDOWN_MS && this._ws && this._persisted) {
65429
- this._lastResyncRequest.set(convId, Date.now());
65430
- this._ws.send(
65431
- JSON.stringify({
65432
- event: "resync_request",
65433
- data: {
65434
- conversation_id: convId,
65435
- reason,
65436
- identity_public_key: this._persisted.identityKeypair.publicKey,
65437
- ephemeral_public_key: this._persisted.ephemeralKeypair.publicKey,
65438
- epoch: session?.epoch
65439
- }
65440
- })
65441
- );
65442
- console.log(
65443
- `[SecureChannel] Room resync requested for conv ${convId.slice(0, 8)} (${reason})`
65444
- );
65445
- }
65446
- }
65447
- /**
65448
- * Handle an incoming room message (pairwise path — used by sync replay and pairwise room fallback).
65449
- * Finds the pairwise conversation for the sender, decrypts, and emits a room_message event.
65450
- */
65451
- async _handleRoomMessage(msgData) {
65452
- if (msgData.sender_device_id === this._deviceId) return;
65453
- this._lastInboundRoomId = msgData.room_id;
65454
- const convId = msgData.conversation_id ?? this._findConversationForSender(msgData.sender_device_id, msgData.room_id);
65455
- if (!convId) {
65456
- console.warn(
65457
- `[SecureChannel] No conversation found for sender ${msgData.sender_device_id.slice(0, 8)}... in room ${msgData.room_id}`
65458
- );
65459
- return;
65460
- }
65461
- let session = this._sessions.get(convId);
65462
- if (!session) {
65463
- console.warn(
65464
- `[SecureChannel] No session for room conv ${convId.slice(0, 8)}..., fetching room data`
65465
- );
65466
- try {
65467
- const roomRes = await fetch(
65468
- `${this.config.apiUrl}/api/v1/rooms/${msgData.room_id}`,
65469
- {
65470
- headers: {
65471
- Authorization: `Bearer ${this._persisted.deviceJwt}`
65472
- }
65473
- }
65474
- );
65475
- if (roomRes.ok) {
65476
- const roomData = await roomRes.json();
65477
- await this.joinRoom({
65478
- roomId: roomData.id,
65479
- name: roomData.name,
65480
- members: (roomData.members || []).map((m2) => ({
65481
- deviceId: m2.device_id,
65482
- entityType: m2.entity_type,
65483
- displayName: m2.display_name,
65484
- identityPublicKey: m2.identity_public_key,
65485
- ephemeralPublicKey: m2.ephemeral_public_key
65486
- })),
65487
- conversations: (roomData.conversations || []).map((c2) => ({
65488
- id: c2.id,
65489
- participantA: c2.participant_a,
65490
- participantB: c2.participant_b
65491
- }))
65492
- });
65493
- session = this._sessions.get(convId);
65494
- }
65495
- } catch (fetchErr) {
65496
- console.error(
65497
- `[SecureChannel] Failed to fetch room data for ${msgData.room_id}:`,
65498
- fetchErr
65499
- );
65500
- }
65501
- if (!session) {
65502
- console.warn(
65503
- `[SecureChannel] Still no session for room conv ${convId.slice(0, 8)}... after refresh, skipping`
65504
- );
65505
- return;
65506
- }
65507
- }
65508
- const encrypted = transportToEncryptedMessage({
65509
- header_blob: msgData.header_blob,
65510
- ciphertext: msgData.ciphertext
65511
- });
65512
- let plaintext;
65513
- const ratchetSnapshot = session.ratchet.serialize();
65514
- try {
65515
- plaintext = session.ratchet.decrypt(encrypted);
65516
- } catch (decryptErr) {
65517
- try {
65518
- session.ratchet = DoubleRatchet.deserialize(ratchetSnapshot);
65519
- } catch {
65520
- }
65521
- console.warn(
65522
- `[SecureChannel] Room decrypt failed for conv ${convId.slice(0, 8)}...: ${String(decryptErr)}, re-initializing ratchet`
65523
- );
65524
- try {
65525
- const roomEntry = this._persisted?.rooms ? Object.values(this._persisted.rooms).find(
65526
- (r2) => r2.conversationIds.includes(convId)
65527
- ) : null;
65528
- if (!roomEntry) throw new Error("Room not found for conversation");
65529
- const otherMember = roomEntry.members.find(
65530
- (m2) => m2.deviceId === msgData.sender_device_id
65531
- );
65532
- if (!otherMember?.identityPublicKey) throw new Error("No key for sender");
65533
- const isInitiator = this._deviceId < msgData.sender_device_id;
65534
- const identity = this._persisted.identityKeypair;
65535
- const ephemeral = this._persisted.ephemeralKeypair;
65536
- const sharedSecret = performX3DH({
65537
- myIdentityPrivate: hexToBytes(identity.privateKey),
65538
- myEphemeralPrivate: hexToBytes(ephemeral.privateKey),
65539
- theirIdentityPublic: hexToBytes(otherMember.identityPublicKey),
65540
- theirEphemeralPublic: hexToBytes(
65541
- otherMember.ephemeralPublicKey ?? otherMember.identityPublicKey
65542
- ),
65543
- isInitiator
65544
- });
65545
- const peerIdPub = hexToBytes(otherMember.identityPublicKey);
65546
- const newRatchet = isInitiator ? DoubleRatchet.initSender(sharedSecret, {
65547
- publicKey: hexToBytes(identity.publicKey),
65548
- privateKey: hexToBytes(identity.privateKey),
65549
- keyType: "ed25519"
65550
- }, peerIdPub) : DoubleRatchet.initReceiver(sharedSecret, {
65551
- publicKey: hexToBytes(identity.publicKey),
65552
- privateKey: hexToBytes(identity.privateKey),
65553
- keyType: "ed25519"
65554
- }, peerIdPub);
65555
- session.ratchet = newRatchet;
65556
- session.activated = false;
65557
- this._persisted.sessions[convId] = {
65558
- ownerDeviceId: session.ownerDeviceId,
65559
- ratchetState: newRatchet.serialize(),
65560
- activated: false
65561
- };
65562
- await this._persistState();
65563
- console.log(
65564
- `[SecureChannel] Room ratchet re-initialized for conv ${convId.slice(0, 8)}...`
65565
- );
65566
- const incomingMsgNum = encrypted.header.messageNumber;
65567
- if (incomingMsgNum <= 5) {
65568
- try {
65569
- plaintext = session.ratchet.decrypt(encrypted);
65570
- session.activated = true;
65571
- if (this._persisted.sessions[convId]) {
65572
- this._persisted.sessions[convId].activated = true;
65573
- }
65574
- await this._persistState();
65575
- console.log(
65576
- `[SecureChannel] Room session ${convId.slice(0, 8)}... re-activated after ratchet re-init`
65577
- );
65578
- } catch (retryErr) {
65579
- console.warn(
65580
- `[SecureChannel] Room re-init retry failed for conv ${convId.slice(0, 8)} (msgNum=${incomingMsgNum}):`,
65581
- retryErr
65582
- );
65583
- this._sendRoomResyncIfCooled(convId, "room_reinit_retry_failed", session);
65584
- return;
65585
- }
65586
- } else {
65587
- console.log(
65588
- `[SecureChannel] Room re-init: skipping message with msgNum=${incomingMsgNum} for conv ${convId.slice(0, 8)} (too far ahead for fresh ratchet)`
65589
- );
65590
- this._sendRoomResyncIfCooled(convId, "room_message_skip");
65591
- return;
65592
- }
65593
- } catch (reinitErr) {
65594
- console.error(
65595
- `[SecureChannel] Room ratchet re-init failed for conv ${convId.slice(0, 8)}...:`,
65596
- reinitErr
65597
- );
65598
- this._sendRoomResyncIfCooled(convId, "room_reinit_failed");
65599
- return;
65600
- }
65601
- }
65602
- let messageText;
65603
- let messageType;
65604
- try {
65605
- const parsed = JSON.parse(plaintext);
65606
- messageType = parsed.type || "message";
65607
- messageText = parsed.text || plaintext;
65608
- } catch {
65609
- messageType = "message";
65610
- messageText = plaintext;
65611
- }
65612
- if (CREDENTIAL_MESSAGE_TYPES.has(messageType)) {
65613
- this._handleCredentialMessage(msgData.room_id, messageType, messageText, msgData.message_id);
65614
- if (msgData.created_at && this._persisted) {
65615
- this._persisted.lastMessageTimestamp = msgData.created_at;
65616
- }
65617
- await this._persistState();
65618
- return;
65619
- }
65620
- if (!ROOM_AGENT_TYPES.has(messageType)) {
65621
- return;
65622
- }
65623
- if (!session.activated) {
65624
- session.activated = true;
65625
- console.log(
65626
- `[SecureChannel] Room session ${convId.slice(0, 8)}... activated by first message`
65627
- );
65628
- }
65629
- if (msgData.message_id) {
65630
- this._sendAck(msgData.message_id);
65631
- }
65632
- if (msgData.created_at && this._persisted) {
65633
- this._persisted.lastMessageTimestamp = msgData.created_at;
65634
- }
65635
- await this._persistState();
65636
- const legacyRoomMembers = this._persisted?.rooms?.[msgData.room_id]?.members ?? [];
65637
- const legacySenderMember = legacyRoomMembers.find((m2) => m2.deviceId === msgData.sender_device_id);
65638
- const legacySenderIsAgent = legacySenderMember?.entityType === "agent";
65639
- const legacySenderLabel = legacySenderMember?.displayName || "someone";
65640
- const metadata = {
65641
- messageId: msgData.message_id ?? "",
65642
- conversationId: convId,
65643
- timestamp: msgData.created_at ?? (/* @__PURE__ */ new Date()).toISOString(),
65644
- messageType,
65645
- roomId: msgData.room_id,
65646
- senderDeviceId: msgData.sender_device_id,
65647
- senderIsAgent: legacySenderIsAgent,
65648
- senderName: legacySenderLabel,
65649
- roomName: this._persisted?.rooms?.[msgData.room_id]?.name
65650
- };
65651
- this._appendHistory("owner", messageText, `room:${msgData.room_id}`);
65652
- this.emit("room_message", {
65653
- roomId: msgData.room_id,
65654
- senderDeviceId: msgData.sender_device_id,
65655
- senderName: legacySenderLabel,
65656
- plaintext: messageText,
65657
- messageType,
65658
- timestamp: msgData.created_at ?? (/* @__PURE__ */ new Date()).toISOString()
65659
- });
65660
- const legacyContextualMessage = legacySenderIsAgent ? messageText : `[${legacySenderLabel}]: ${messageText}`;
65661
- Promise.resolve(this.config.onMessage?.(legacyContextualMessage, metadata)).catch((err) => {
65662
- console.error("[SecureChannel] onMessage callback error:", err);
65663
- });
65664
- }
66411
+ // _sendRoomResyncIfCooled removed — rooms are MLS-only now
66412
+ // _handleRoomMessage removed rooms are MLS-only now
65665
66413
  /**
65666
66414
  * Handle credential protocol messages (grant, revoke, request).
65667
66415
  * These are intercepted before reaching the agent's onMessage callback.
@@ -65750,20 +66498,7 @@ ${messageText}`;
65750
66498
  purgeRoomCredentials(roomId) {
65751
66499
  this._credentialStore.purgeForRoom(roomId);
65752
66500
  }
65753
- /**
65754
- * Find the pairwise conversation ID for a given sender in a room.
65755
- */
65756
- _findConversationForSender(senderDeviceId, roomId) {
65757
- const room = this._persisted?.rooms?.[roomId];
65758
- if (!room) return null;
65759
- for (const convId of room.conversationIds) {
65760
- const session = this._sessions.get(convId);
65761
- if (session && session.ownerDeviceId === senderDeviceId) {
65762
- return convId;
65763
- }
65764
- }
65765
- return null;
65766
- }
66501
+ // _findConversationForSender removed — rooms are MLS-only now
65767
66502
  // ---------------------------------------------------------------------------
65768
66503
  // MLS room message handlers
65769
66504
  // ---------------------------------------------------------------------------
@@ -65787,11 +66522,33 @@ ${messageText}`;
65787
66522
  return;
65788
66523
  }
65789
66524
  }
65790
- this._lastInboundRoomId = roomId;
65791
- const mlsGroup = this._mlsGroups.get(roomId);
65792
- console.log(`[SecureChannel] MLS decrypt attempt room=${roomId.slice(0, 8)} group=${groupId?.slice(0, 8)} loaded=${!!mlsGroup} init=${mlsGroup?.isInitialized} mlsGroupsKeys=[${Array.from(this._mlsGroups.keys()).join(",")}]`);
66525
+ const resolvedRoomId = roomId;
66526
+ this._lastInboundRoomId = resolvedRoomId;
66527
+ const mlsGroup = this._mlsGroups.get(resolvedRoomId);
66528
+ console.log(`[SecureChannel] MLS decrypt attempt room=${resolvedRoomId.slice(0, 8)} group=${groupId?.slice(0, 8)} loaded=${!!mlsGroup} init=${mlsGroup?.isInitialized} mlsGroupsKeys=[${Array.from(this._mlsGroups.keys()).join(",")}]`);
65793
66529
  if (!mlsGroup?.isInitialized) {
65794
- console.warn(`[SecureChannel] MLS group not loaded for room ${roomId.slice(0, 8)}`);
66530
+ console.warn(`[SecureChannel] MLS group not loaded for room ${resolvedRoomId.slice(0, 8)}, requesting Welcome`);
66531
+ try {
66532
+ const { MLSGroupManager: MLS } = await init_dist().then(() => dist_exports);
66533
+ const mgr = new MLS();
66534
+ const kp = await mgr.generateKeyPackage(new TextEncoder().encode(this._deviceId));
66535
+ const kpBytes = MLS.serializeKeyPackage(kp.publicPackage);
66536
+ const kpHex = Buffer.from(kpBytes).toString("hex");
66537
+ await fetch(`${this.config.apiUrl}/api/v1/mls/key-packages`, {
66538
+ method: "POST",
66539
+ headers: { Authorization: `Bearer ${this._deviceJwt}`, "Content-Type": "application/json" },
66540
+ body: JSON.stringify({ key_package: kpHex, device_id: this._deviceId })
66541
+ });
66542
+ this._pendingMlsKpBundle = kp;
66543
+ await fetch(`${this.config.apiUrl}/api/v1/mls/groups/${groupId}/request-welcome`, {
66544
+ method: "POST",
66545
+ headers: { Authorization: `Bearer ${this._deviceJwt}`, "Content-Type": "application/json" },
66546
+ body: JSON.stringify({ device_id: this._deviceId })
66547
+ });
66548
+ console.log(`[SecureChannel] Welcome requested for room ${resolvedRoomId.slice(0, 8)} group ${groupId?.slice(0, 8)}`);
66549
+ } catch (reqErr) {
66550
+ console.warn(`[SecureChannel] Welcome request failed for room ${resolvedRoomId.slice(0, 8)}:`, reqErr);
66551
+ }
65795
66552
  return;
65796
66553
  }
65797
66554
  try {
@@ -65813,7 +66570,7 @@ ${messageText}`;
65813
66570
  messageText = rawPlaintext;
65814
66571
  }
65815
66572
  if (CREDENTIAL_MESSAGE_TYPES.has(messageType)) {
65816
- this._handleCredentialMessage(roomId, messageType, messageText, data.message_id);
66573
+ this._handleCredentialMessage(resolvedRoomId, messageType, messageText, data.message_id);
65817
66574
  if (data.created_at && this._persisted) {
65818
66575
  this._persisted.lastMessageTimestamp = data.created_at;
65819
66576
  }
@@ -65828,13 +66585,13 @@ ${messageText}`;
65828
66585
  }
65829
66586
  if (data.created_at && this._persisted) {
65830
66587
  this._persisted.lastMessageTimestamp = data.created_at;
65831
- const roomState = this._persisted.rooms?.[roomId];
66588
+ const roomState = this._persisted.rooms?.[resolvedRoomId];
65832
66589
  if (roomState) {
65833
66590
  roomState.lastMlsMessageTs = data.created_at;
65834
66591
  }
65835
66592
  }
65836
66593
  await this._persistState();
65837
- const roomMembers = this._persisted?.rooms?.[roomId]?.members ?? [];
66594
+ const roomMembers = this._persisted?.rooms?.[resolvedRoomId]?.members ?? [];
65838
66595
  const senderMember = roomMembers.find((m2) => m2.deviceId === senderDeviceId);
65839
66596
  const senderIsAgent = senderMember?.entityType === "agent";
65840
66597
  const metadata = {
@@ -65842,16 +66599,16 @@ ${messageText}`;
65842
66599
  conversationId: "",
65843
66600
  timestamp: data.created_at ?? (/* @__PURE__ */ new Date()).toISOString(),
65844
66601
  messageType,
65845
- roomId,
66602
+ roomId: resolvedRoomId,
65846
66603
  senderDeviceId,
65847
66604
  senderIsAgent,
65848
66605
  senderName: senderMember?.displayName || "unknown",
65849
- roomName: this._persisted?.rooms?.[roomId]?.name
66606
+ roomName: this._persisted?.rooms?.[resolvedRoomId]?.name
65850
66607
  };
65851
66608
  const senderLabel = senderMember?.displayName || "someone";
65852
- this._appendHistory("owner", messageText, `room:${roomId}`);
66609
+ this._appendHistory("owner", messageText, `room:${resolvedRoomId}`);
65853
66610
  this.emit("room_message", {
65854
- roomId,
66611
+ roomId: resolvedRoomId,
65855
66612
  senderDeviceId,
65856
66613
  senderName: senderLabel,
65857
66614
  plaintext: messageText,
@@ -65863,7 +66620,7 @@ ${messageText}`;
65863
66620
  console.error("[SecureChannel] onMessage callback error (MLS):", err);
65864
66621
  });
65865
66622
  } catch (err) {
65866
- console.error(`[SecureChannel] MLS room decrypt failed for ${roomId.slice(0, 8)}:`, err);
66623
+ console.error(`[SecureChannel] MLS room decrypt failed for ${resolvedRoomId.slice(0, 8)}:`, err);
65867
66624
  }
65868
66625
  }
65869
66626
  async _handleMlsCommit(data) {
@@ -65892,7 +66649,7 @@ ${messageText}`;
65892
66649
  try {
65893
66650
  const welcomeBytes = new Uint8Array(Buffer.from(data.payload, "hex"));
65894
66651
  const mgr = new MLSGroupManager();
65895
- const kp = this._mlsKeyPackage ?? await (async () => {
66652
+ const kp = this._pendingMlsKpBundle ?? this._mlsKeyPackage ?? await (async () => {
65896
66653
  const identity = new TextEncoder().encode(this._deviceId);
65897
66654
  return mgr.generateKeyPackage(identity);
65898
66655
  })();
@@ -65909,11 +66666,15 @@ ${messageText}`;
65909
66666
  console.log(`[SecureChannel] Joined 1:1 MLS group for conv ${conversationId.slice(0, 8)} via Welcome (epoch=${mgr.epoch})`);
65910
66667
  return;
65911
66668
  }
66669
+ const welcomeRoomId = data.room_id;
65912
66670
  for (const [roomId, room] of Object.entries(this._persisted?.rooms ?? {})) {
65913
- if (room.mlsGroupId === groupId) {
66671
+ if (room.mlsGroupId === groupId || roomId === welcomeRoomId) {
66672
+ room.mlsGroupId = groupId;
65914
66673
  this._mlsGroups.set(roomId, mgr);
65915
66674
  await saveMlsState(this.config.dataDir, groupId, JSON.stringify(mgr.exportState()));
66675
+ await this._persistState();
65916
66676
  console.log(`[SecureChannel] Joined MLS group for room ${roomId.slice(0, 8)} via Welcome (epoch=${mgr.epoch})`);
66677
+ this._pendingMlsKpBundle = void 0;
65917
66678
  return;
65918
66679
  }
65919
66680
  }
@@ -66190,22 +66951,6 @@ ${messageText}`;
66190
66951
  }
66191
66952
  }
66192
66953
  if (roomId) {
66193
- try {
66194
- await this._handleRoomMessage({
66195
- room_id: roomId,
66196
- sender_device_id: msg.sender_device_id,
66197
- conversation_id: msg.conversation_id,
66198
- header_blob: msg.header_blob,
66199
- ciphertext: msg.ciphertext,
66200
- message_id: msg.id,
66201
- created_at: msg.created_at
66202
- });
66203
- } catch (roomErr) {
66204
- console.warn(
66205
- `[SecureChannel] Sync room message failed for ${msg.conversation_id.slice(0, 8)}...:`,
66206
- roomErr
66207
- );
66208
- }
66209
66954
  this._persisted.lastMessageTimestamp = msg.created_at;
66210
66955
  since = msg.created_at;
66211
66956
  continue;