@agentvault/agentvault 0.19.59 → 0.19.61

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -44659,6 +44659,13 @@ function computeFingerprint(publicKey) {
44659
44659
  function createProofOfPossession(privateKey, publicKey) {
44660
44660
  return libsodium_wrappers_default.crypto_sign_detached(publicKey, privateKey);
44661
44661
  }
44662
+ function verifyProofOfPossession(proof, publicKey) {
44663
+ try {
44664
+ return libsodium_wrappers_default.crypto_sign_verify_detached(proof, publicKey, publicKey);
44665
+ } catch {
44666
+ return false;
44667
+ }
44668
+ }
44662
44669
  var init_keys = __esm({
44663
44670
  async "../crypto/dist/keys.js"() {
44664
44671
  "use strict";
@@ -45127,6 +45134,74 @@ function jsonCanonical(value) {
45127
45134
  }
45128
45135
  return JSON.stringify(value);
45129
45136
  }
45137
+ function base58Encode(bytes) {
45138
+ let zeros = 0;
45139
+ for (const b2 of bytes) {
45140
+ if (b2 === 0)
45141
+ zeros++;
45142
+ else
45143
+ break;
45144
+ }
45145
+ let num = BigInt(0);
45146
+ for (const b2 of bytes) {
45147
+ num = num * 256n + BigInt(b2);
45148
+ }
45149
+ let result = "";
45150
+ while (num > 0n) {
45151
+ const remainder = Number(num % 58n);
45152
+ num = num / 58n;
45153
+ result = BASE58_ALPHABET[remainder] + result;
45154
+ }
45155
+ return "1".repeat(zeros) + result;
45156
+ }
45157
+ function base58Decode(str) {
45158
+ let zeros = 0;
45159
+ for (const c2 of str) {
45160
+ if (c2 === "1")
45161
+ zeros++;
45162
+ else
45163
+ break;
45164
+ }
45165
+ let num = BigInt(0);
45166
+ for (const c2 of str.slice(zeros)) {
45167
+ const idx = BASE58_ALPHABET.indexOf(c2);
45168
+ if (idx === -1)
45169
+ throw new Error(`Invalid base58 character: ${c2}`);
45170
+ num = num * 58n + BigInt(idx);
45171
+ }
45172
+ const hex3 = num === 0n ? "" : num.toString(16).padStart(2, "0");
45173
+ const paddedHex = hex3.length % 2 ? "0" + hex3 : hex3;
45174
+ const dataBytes = new Uint8Array((paddedHex.match(/.{2}/g) ?? []).map((b2) => parseInt(b2, 16)));
45175
+ const result = new Uint8Array(zeros + dataBytes.length);
45176
+ result.set(dataBytes, zeros);
45177
+ return result;
45178
+ }
45179
+ function publicKeyToMultibase(publicKey) {
45180
+ const prefixed = new Uint8Array(2 + publicKey.length);
45181
+ prefixed[0] = 237;
45182
+ prefixed[1] = 1;
45183
+ prefixed.set(publicKey, 2);
45184
+ return "z" + base58Encode(prefixed);
45185
+ }
45186
+ function multibaseToPublicKey(multibase) {
45187
+ if (!multibase.startsWith("z")) {
45188
+ throw new Error("Multibase string must start with 'z' (base58btc)");
45189
+ }
45190
+ const decoded = base58Decode(multibase.slice(1));
45191
+ if (decoded.length < 2 || decoded[0] !== 237 || decoded[1] !== 1) {
45192
+ throw new Error("Invalid Ed25519 multicodec prefix");
45193
+ }
45194
+ return decoded.slice(2);
45195
+ }
45196
+ async function signDocument(document, privateKey) {
45197
+ await libsodium_wrappers_default.ready;
45198
+ const canonical = canonicalize(document);
45199
+ const domainPrefix = libsodium_wrappers_default.from_string(DOMAIN_DID_DOCUMENT);
45200
+ const message = new Uint8Array(domainPrefix.length + canonical.length);
45201
+ message.set(domainPrefix);
45202
+ message.set(canonical, domainPrefix.length);
45203
+ return libsodium_wrappers_default.crypto_sign_detached(message, privateKey);
45204
+ }
45130
45205
  async function verifyDocumentSignature(document, signature, publicKey) {
45131
45206
  await libsodium_wrappers_default.ready;
45132
45207
  const canonical = canonicalize(document);
@@ -45140,12 +45215,61 @@ async function verifyDocumentSignature(document, signature, publicKey) {
45140
45215
  return false;
45141
45216
  }
45142
45217
  }
45143
- var DOMAIN_DID_DOCUMENT;
45218
+ function buildDidDocument(params) {
45219
+ const { hubAddress, ownerPublicKey, agentPublicKey, serviceEndpoint, profileEndpoint } = params;
45220
+ const didId = `did:hub:${hubAddress}`;
45221
+ const ownerMultibase = publicKeyToMultibase(ownerPublicKey);
45222
+ const agentMultibase = publicKeyToMultibase(agentPublicKey);
45223
+ const controllerDid = `did:key:${ownerMultibase}`;
45224
+ const now = params.created ?? (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
45225
+ return {
45226
+ "@context": [
45227
+ "https://www.w3.org/ns/did/v1",
45228
+ "https://w3id.org/security/suites/ed25519-2020/v1"
45229
+ ],
45230
+ id: didId,
45231
+ controller: controllerDid,
45232
+ verificationMethod: [
45233
+ {
45234
+ id: `${didId}#owner-key`,
45235
+ type: "Ed25519VerificationKey2020",
45236
+ controller: didId,
45237
+ publicKeyMultibase: ownerMultibase
45238
+ },
45239
+ {
45240
+ id: `${didId}#agent-key`,
45241
+ type: "Ed25519VerificationKey2020",
45242
+ controller: didId,
45243
+ publicKeyMultibase: agentMultibase
45244
+ }
45245
+ ],
45246
+ authentication: [`${didId}#owner-key`],
45247
+ assertionMethod: [`${didId}#owner-key`, `${didId}#agent-key`],
45248
+ service: [
45249
+ {
45250
+ id: `${didId}#messaging`,
45251
+ type: "AgentVaultSecureChannel",
45252
+ serviceEndpoint
45253
+ },
45254
+ {
45255
+ id: `${didId}#profile`,
45256
+ type: "AgentVaultProfile",
45257
+ serviceEndpoint: profileEndpoint
45258
+ }
45259
+ ],
45260
+ created: now,
45261
+ updated: now
45262
+ };
45263
+ }
45264
+ var DOMAIN_DID_DOCUMENT, DOMAIN_TRANSFER_INTENT, DOMAIN_TRANSFER_ACCEPT, BASE58_ALPHABET;
45144
45265
  var init_did = __esm({
45145
45266
  async "../crypto/dist/did.js"() {
45146
45267
  "use strict";
45147
45268
  await init_libsodium_wrappers();
45148
45269
  DOMAIN_DID_DOCUMENT = "DID-DOCUMENT:";
45270
+ DOMAIN_TRANSFER_INTENT = "TRANSFER-INTENT:";
45271
+ DOMAIN_TRANSFER_ACCEPT = "TRANSFER-ACCEPT:";
45272
+ BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
45149
45273
  }
45150
45274
  });
45151
45275
 
@@ -45428,25 +45552,373 @@ var init_scan_engine = __esm({
45428
45552
  });
45429
45553
 
45430
45554
  // ../crypto/dist/merkle.js
45555
+ function jcsCanonical(value) {
45556
+ if (value === void 0)
45557
+ return void 0;
45558
+ if (value === null)
45559
+ return "null";
45560
+ if (typeof value === "boolean" || typeof value === "number")
45561
+ return JSON.stringify(value);
45562
+ if (typeof value === "string")
45563
+ return JSON.stringify(value);
45564
+ if (Array.isArray(value)) {
45565
+ return "[" + value.map(jcsCanonical).join(",") + "]";
45566
+ }
45567
+ if (typeof value === "object") {
45568
+ const keys = Object.keys(value).sort();
45569
+ const entries = keys.map((k2) => {
45570
+ const v2 = jcsCanonical(value[k2]);
45571
+ if (v2 === void 0)
45572
+ return void 0;
45573
+ return JSON.stringify(k2) + ":" + v2;
45574
+ }).filter((entry) => entry !== void 0);
45575
+ return "{" + entries.join(",") + "}";
45576
+ }
45577
+ return JSON.stringify(value);
45578
+ }
45579
+ function hexToBytes(hex3) {
45580
+ const h2 = hex3.startsWith("0x") ? hex3.slice(2) : hex3;
45581
+ const bytes = new Uint8Array(h2.length / 2);
45582
+ for (let i2 = 0; i2 < bytes.length; i2++) {
45583
+ bytes[i2] = parseInt(h2.substr(i2 * 2, 2), 16);
45584
+ }
45585
+ return bytes;
45586
+ }
45587
+ function bytesToHex(bytes) {
45588
+ return Array.from(bytes).map((b2) => b2.toString(16).padStart(2, "0")).join("");
45589
+ }
45590
+ function computeDidHash(didDocument) {
45591
+ const json2 = jcsCanonical(didDocument) ?? "";
45592
+ const bytes = libsodium_wrappers_default.from_string(json2);
45593
+ const hash2 = libsodium_wrappers_default.crypto_hash_sha256(bytes);
45594
+ return "0x" + bytesToHex(hash2);
45595
+ }
45596
+ function verifyMerkleProof(leafHash, proof, merkleRoot) {
45597
+ let current = hexToBytes(leafHash);
45598
+ for (const step of proof) {
45599
+ const sibling2 = hexToBytes(step.hash);
45600
+ const combined = new Uint8Array(current.length + sibling2.length);
45601
+ if (step.position === "left") {
45602
+ combined.set(sibling2);
45603
+ combined.set(current, sibling2.length);
45604
+ } else {
45605
+ combined.set(current);
45606
+ combined.set(sibling2, current.length);
45607
+ }
45608
+ current = libsodium_wrappers_default.crypto_hash_sha256(combined);
45609
+ }
45610
+ const rootBytes = hexToBytes(merkleRoot);
45611
+ if (current.length !== rootBytes.length)
45612
+ return false;
45613
+ for (let i2 = 0; i2 < current.length; i2++) {
45614
+ if (current[i2] !== rootBytes[i2])
45615
+ return false;
45616
+ }
45617
+ return true;
45618
+ }
45431
45619
  var init_merkle = __esm({
45432
45620
  async "../crypto/dist/merkle.js"() {
45433
45621
  "use strict";
45622
+ await init_libsodium_wrappers();
45434
45623
  }
45435
45624
  });
45436
45625
 
45437
45626
  // ../crypto/dist/vc.js
45627
+ async function sha256(data) {
45628
+ await libsodium_wrappers_default.ready;
45629
+ return libsodium_wrappers_default.crypto_hash_sha256(data);
45630
+ }
45631
+ function base58Encode2(bytes) {
45632
+ let zeros = 0;
45633
+ for (const b2 of bytes) {
45634
+ if (b2 === 0)
45635
+ zeros++;
45636
+ else
45637
+ break;
45638
+ }
45639
+ let num = BigInt(0);
45640
+ for (const b2 of bytes) {
45641
+ num = num * 256n + BigInt(b2);
45642
+ }
45643
+ let result = "";
45644
+ while (num > 0n) {
45645
+ const remainder = Number(num % 58n);
45646
+ num = num / 58n;
45647
+ result = BASE58_ALPHABET2[remainder] + result;
45648
+ }
45649
+ return "1".repeat(zeros) + result;
45650
+ }
45651
+ function base58Decode2(str) {
45652
+ let zeros = 0;
45653
+ for (const c2 of str) {
45654
+ if (c2 === "1")
45655
+ zeros++;
45656
+ else
45657
+ break;
45658
+ }
45659
+ let num = BigInt(0);
45660
+ for (const c2 of str.slice(zeros)) {
45661
+ const idx = BASE58_ALPHABET2.indexOf(c2);
45662
+ if (idx === -1)
45663
+ throw new Error(`Invalid base58 character: ${c2}`);
45664
+ num = num * 58n + BigInt(idx);
45665
+ }
45666
+ const hex3 = num === 0n ? "" : num.toString(16).padStart(2, "0");
45667
+ const paddedHex = hex3.length % 2 ? "0" + hex3 : hex3;
45668
+ const dataBytes = new Uint8Array((paddedHex.match(/.{2}/g) ?? []).map((b2) => parseInt(b2, 16)));
45669
+ const result = new Uint8Array(zeros + dataBytes.length);
45670
+ result.set(dataBytes, zeros);
45671
+ return result;
45672
+ }
45673
+ async function computeHashData(document, proofConfig) {
45674
+ const proofConfigBytes = canonicalize(proofConfig);
45675
+ const proofConfigHash = await sha256(proofConfigBytes);
45676
+ const docWithoutProof = { ...document };
45677
+ delete docWithoutProof.proof;
45678
+ const documentBytes = canonicalize(docWithoutProof);
45679
+ const documentHash = await sha256(documentBytes);
45680
+ const hashData = new Uint8Array(64);
45681
+ hashData.set(proofConfigHash, 0);
45682
+ hashData.set(documentHash, 32);
45683
+ return hashData;
45684
+ }
45685
+ async function signWithDataIntegrity(document, privateKey, verificationMethod, proofPurpose = "assertionMethod", created) {
45686
+ await libsodium_wrappers_default.ready;
45687
+ const timestamp = created ?? (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
45688
+ const proofConfig = {
45689
+ type: "DataIntegrityProof",
45690
+ cryptosuite: CRYPTOSUITE,
45691
+ created: timestamp,
45692
+ verificationMethod,
45693
+ proofPurpose
45694
+ };
45695
+ const hashData = await computeHashData(document, proofConfig);
45696
+ const signature = libsodium_wrappers_default.crypto_sign_detached(hashData, privateKey);
45697
+ const proofValue = "z" + base58Encode2(signature);
45698
+ const proof = {
45699
+ type: "DataIntegrityProof",
45700
+ cryptosuite: CRYPTOSUITE,
45701
+ created: timestamp,
45702
+ verificationMethod,
45703
+ proofPurpose,
45704
+ proofValue
45705
+ };
45706
+ return { ...document, proof };
45707
+ }
45708
+ async function verifyDataIntegrity(document, publicKey) {
45709
+ await libsodium_wrappers_default.ready;
45710
+ const proof = document.proof;
45711
+ if (!proof || proof.type !== "DataIntegrityProof" || proof.cryptosuite !== CRYPTOSUITE) {
45712
+ return false;
45713
+ }
45714
+ if (!proof.proofValue.startsWith("z")) {
45715
+ return false;
45716
+ }
45717
+ const signature = base58Decode2(proof.proofValue.slice(1));
45718
+ if (signature.length !== 64) {
45719
+ return false;
45720
+ }
45721
+ const proofConfig = {
45722
+ type: proof.type,
45723
+ cryptosuite: proof.cryptosuite,
45724
+ created: proof.created,
45725
+ verificationMethod: proof.verificationMethod,
45726
+ proofPurpose: proof.proofPurpose
45727
+ };
45728
+ const hashData = await computeHashData(document, proofConfig);
45729
+ try {
45730
+ return libsodium_wrappers_default.crypto_sign_verify_detached(signature, hashData, publicKey);
45731
+ } catch {
45732
+ return false;
45733
+ }
45734
+ }
45735
+ function buildAgentTrustCredential(params) {
45736
+ const now = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
45737
+ return {
45738
+ "@context": [
45739
+ VC_CONTEXT_V2,
45740
+ {
45741
+ AgentTrustCredential: "https://agentvault.chat/vocab#AgentTrustCredential",
45742
+ trustTier: "https://agentvault.chat/vocab#trustTier",
45743
+ compositeScore: "https://agentvault.chat/vocab#compositeScore",
45744
+ scoreWindow: "https://agentvault.chat/vocab#scoreWindow",
45745
+ scoreDimensions: "https://agentvault.chat/vocab#scoreDimensions",
45746
+ volume: "https://agentvault.chat/vocab#volume",
45747
+ responsiveness: "https://agentvault.chat/vocab#responsiveness",
45748
+ uptime: "https://agentvault.chat/vocab#uptime",
45749
+ compliance: "https://agentvault.chat/vocab#compliance",
45750
+ verificationEndpoint: "https://agentvault.chat/vocab#verificationEndpoint"
45751
+ }
45752
+ ],
45753
+ id: params.credentialId,
45754
+ type: ["VerifiableCredential", "AgentTrustCredential"],
45755
+ issuer: params.issuerName ? { id: params.issuerDid, name: params.issuerName } : params.issuerDid,
45756
+ validFrom: params.validFrom ?? now,
45757
+ ...params.validUntil ? { validUntil: params.validUntil } : {},
45758
+ credentialSubject: {
45759
+ id: params.subjectDid,
45760
+ trustTier: params.trustTier,
45761
+ compositeScore: params.compositeScore,
45762
+ scoreWindow: params.scoreWindow,
45763
+ ...params.dimensions ? {
45764
+ scoreDimensions: {
45765
+ volume: params.dimensions.volume,
45766
+ responsiveness: params.dimensions.responsiveness,
45767
+ uptime: params.dimensions.uptime,
45768
+ compliance: params.dimensions.compliance
45769
+ }
45770
+ } : {},
45771
+ ...params.verificationEndpoint ? { verificationEndpoint: params.verificationEndpoint } : {}
45772
+ }
45773
+ };
45774
+ }
45775
+ function buildSkillAttestation(params) {
45776
+ const now = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
45777
+ return {
45778
+ "@context": [
45779
+ VC_CONTEXT_V2,
45780
+ {
45781
+ SkillAttestation: "https://agentvault.chat/vocab#SkillAttestation",
45782
+ skillName: "https://agentvault.chat/vocab#skillName",
45783
+ skillNamespace: "https://agentvault.chat/vocab#skillNamespace",
45784
+ proficiencyLevel: "https://agentvault.chat/vocab#proficiencyLevel",
45785
+ totalInvocations: "https://agentvault.chat/vocab#totalInvocations",
45786
+ successRate: "https://agentvault.chat/vocab#successRate",
45787
+ assessedAt: "https://agentvault.chat/vocab#assessedAt"
45788
+ }
45789
+ ],
45790
+ id: params.credentialId,
45791
+ type: ["VerifiableCredential", "SkillAttestation"],
45792
+ issuer: params.issuerName ? { id: params.issuerDid, name: params.issuerName } : params.issuerDid,
45793
+ validFrom: params.validFrom ?? now,
45794
+ ...params.validUntil ? { validUntil: params.validUntil } : {},
45795
+ credentialSubject: {
45796
+ id: params.subjectDid,
45797
+ skillName: params.skillName,
45798
+ skillNamespace: params.skillNamespace,
45799
+ ...params.proficiencyLevel ? { proficiencyLevel: params.proficiencyLevel } : {},
45800
+ ...params.totalInvocations !== void 0 ? { totalInvocations: params.totalInvocations } : {},
45801
+ ...params.successRate !== void 0 ? { successRate: params.successRate } : {},
45802
+ ...params.assessedAt ? { assessedAt: params.assessedAt } : {}
45803
+ }
45804
+ };
45805
+ }
45806
+ function buildPerformanceRecord(params) {
45807
+ const now = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
45808
+ return {
45809
+ "@context": [
45810
+ VC_CONTEXT_V2,
45811
+ {
45812
+ PerformanceRecord: "https://agentvault.chat/vocab#PerformanceRecord",
45813
+ periodStart: "https://agentvault.chat/vocab#periodStart",
45814
+ periodEnd: "https://agentvault.chat/vocab#periodEnd",
45815
+ messagesHandled: "https://agentvault.chat/vocab#messagesHandled",
45816
+ avgResponseTimeMs: "https://agentvault.chat/vocab#avgResponseTimeMs",
45817
+ uptimePercentage: "https://agentvault.chat/vocab#uptimePercentage",
45818
+ policyViolations: "https://agentvault.chat/vocab#policyViolations",
45819
+ compositeScore: "https://agentvault.chat/vocab#compositeScore"
45820
+ }
45821
+ ],
45822
+ id: params.credentialId,
45823
+ type: ["VerifiableCredential", "PerformanceRecord"],
45824
+ issuer: params.issuerName ? { id: params.issuerDid, name: params.issuerName } : params.issuerDid,
45825
+ validFrom: params.validFrom ?? now,
45826
+ ...params.validUntil ? { validUntil: params.validUntil } : {},
45827
+ credentialSubject: {
45828
+ id: params.subjectDid,
45829
+ periodStart: params.periodStart,
45830
+ periodEnd: params.periodEnd,
45831
+ messagesHandled: params.messagesHandled,
45832
+ avgResponseTimeMs: params.avgResponseTimeMs,
45833
+ uptimePercentage: params.uptimePercentage,
45834
+ policyViolations: params.policyViolations,
45835
+ compositeScore: params.compositeScore
45836
+ }
45837
+ };
45838
+ }
45839
+ function buildAgentTrustReportCredential(params) {
45840
+ const now = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d{3}Z$/, "Z");
45841
+ const subject = {
45842
+ id: params.subjectDid,
45843
+ reportPeriod: {
45844
+ start: params.reportPeriodStart,
45845
+ end: params.reportPeriodEnd
45846
+ },
45847
+ trustTier: params.trustTier,
45848
+ compositeScore: params.compositeScore
45849
+ };
45850
+ if (params.dimensions)
45851
+ subject.dimensions = params.dimensions;
45852
+ if (params.trending)
45853
+ subject.trending = params.trending;
45854
+ if (params.fleetComparison)
45855
+ subject.fleetComparison = params.fleetComparison;
45856
+ if (params.driftStatus)
45857
+ subject.driftStatus = params.driftStatus;
45858
+ if (params.auditIntegrity)
45859
+ subject.auditIntegrity = params.auditIntegrity;
45860
+ if (params.telemetrySummary)
45861
+ subject.telemetrySummary = params.telemetrySummary;
45862
+ if (params.verificationEndpoint)
45863
+ subject.verificationEndpoint = params.verificationEndpoint;
45864
+ return {
45865
+ "@context": [
45866
+ VC_CONTEXT_V2,
45867
+ {
45868
+ AgentTrustReport: "https://agentvault.chat/vocab#AgentTrustReport",
45869
+ reportPeriod: "https://agentvault.chat/vocab#reportPeriod",
45870
+ trustTier: "https://agentvault.chat/vocab#trustTier",
45871
+ compositeScore: "https://agentvault.chat/vocab#compositeScore",
45872
+ dimensions: "https://agentvault.chat/vocab#dimensions",
45873
+ trending: "https://agentvault.chat/vocab#trending",
45874
+ fleetComparison: "https://agentvault.chat/vocab#fleetComparison",
45875
+ driftStatus: "https://agentvault.chat/vocab#driftStatus",
45876
+ auditIntegrity: "https://agentvault.chat/vocab#auditIntegrity",
45877
+ telemetrySummary: "https://agentvault.chat/vocab#telemetrySummary",
45878
+ verificationEndpoint: "https://agentvault.chat/vocab#verificationEndpoint"
45879
+ }
45880
+ ],
45881
+ id: params.credentialId,
45882
+ type: ["VerifiableCredential", "AgentTrustReport"],
45883
+ issuer: params.issuerName ? { id: params.issuerDid, name: params.issuerName } : params.issuerDid,
45884
+ validFrom: params.validFrom ?? now,
45885
+ ...params.validUntil ? { validUntil: params.validUntil } : {},
45886
+ credentialSubject: subject
45887
+ };
45888
+ }
45889
+ function buildVerifiablePresentation(holderDid, credentials, presentationId) {
45890
+ return {
45891
+ "@context": [VC_CONTEXT_V2],
45892
+ type: "VerifiablePresentation",
45893
+ ...presentationId ? { id: presentationId } : {},
45894
+ holder: holderDid,
45895
+ verifiableCredential: credentials
45896
+ };
45897
+ }
45898
+ async function issueCredential(credential, privateKey, verificationMethod) {
45899
+ return signWithDataIntegrity(credential, privateKey, verificationMethod, "assertionMethod");
45900
+ }
45901
+ async function presentCredentials(presentation, privateKey, verificationMethod) {
45902
+ return signWithDataIntegrity(presentation, privateKey, verificationMethod, "authentication");
45903
+ }
45904
+ var VC_CONTEXT_V2, AV_CREDENTIAL_CONTEXT, CRYPTOSUITE, BASE58_ALPHABET2;
45438
45905
  var init_vc = __esm({
45439
45906
  async "../crypto/dist/vc.js"() {
45440
45907
  "use strict";
45908
+ await init_libsodium_wrappers();
45441
45909
  await init_did();
45910
+ VC_CONTEXT_V2 = "https://www.w3.org/ns/credentials/v2";
45911
+ AV_CREDENTIAL_CONTEXT = "https://agentvault.chat/ns/credentials/v1";
45912
+ CRYPTOSUITE = "eddsa-jcs-2022";
45913
+ BASE58_ALPHABET2 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
45442
45914
  }
45443
45915
  });
45444
45916
 
45445
45917
  // ../crypto/dist/transport.js
45446
- function hexToBytes(hex3) {
45918
+ function hexToBytes2(hex3) {
45447
45919
  return libsodium_wrappers_default.from_hex(hex3);
45448
45920
  }
45449
- function bytesToHex(bytes) {
45921
+ function bytesToHex2(bytes) {
45450
45922
  return libsodium_wrappers_default.to_hex(bytes);
45451
45923
  }
45452
45924
  function base64ToBytes(b64) {
@@ -45484,6 +45956,70 @@ function transportToEncryptedMessage(transport) {
45484
45956
  ciphertext: base64ToBytes(transport.ciphertext)
45485
45957
  };
45486
45958
  }
45959
+ function encryptedMessageToTransportV2(msg) {
45960
+ if (!msg.encryptedHeader || !msg.headerNonce) {
45961
+ throw new Error("encryptedMessageToTransportV2 requires v2 encrypted message");
45962
+ }
45963
+ return {
45964
+ envelope_version: "2.0.0",
45965
+ encrypted_header: bytesToBase64(msg.encryptedHeader),
45966
+ header_nonce: bytesToBase64(msg.headerNonce),
45967
+ header_signature: bytesToBase64(msg.headerSignature),
45968
+ nonce: bytesToBase64(msg.nonce),
45969
+ ciphertext: bytesToBase64(msg.ciphertext)
45970
+ };
45971
+ }
45972
+ function transportV2ToEncryptedMessage(transport, plaintextHeader) {
45973
+ return {
45974
+ header: plaintextHeader,
45975
+ headerSignature: base64ToBytes(transport.header_signature),
45976
+ ciphertext: base64ToBytes(transport.ciphertext),
45977
+ nonce: base64ToBytes(transport.nonce),
45978
+ envelopeVersion: "2.0.0",
45979
+ encryptedHeader: base64ToBytes(transport.encrypted_header),
45980
+ headerNonce: base64ToBytes(transport.header_nonce)
45981
+ };
45982
+ }
45983
+ function encryptedMessageToTransportV2Full(msg) {
45984
+ if (!msg.encryptedHeader || !msg.headerNonce) {
45985
+ throw new Error("encryptedMessageToTransportV2Full requires v2 encrypted message");
45986
+ }
45987
+ const v1 = encryptedMessageToTransport(msg);
45988
+ return {
45989
+ ...v1,
45990
+ envelope_version: "2.0.0",
45991
+ encrypted_header: bytesToBase64(msg.encryptedHeader),
45992
+ header_nonce: bytesToBase64(msg.headerNonce)
45993
+ };
45994
+ }
45995
+ function encryptedMessageToHexTransport(msg) {
45996
+ const headerObj = {
45997
+ dhPublicKey: bytesToHex2(msg.header.dhPublicKey),
45998
+ previousChainLength: msg.header.previousChainLength,
45999
+ messageNumber: msg.header.messageNumber
46000
+ };
46001
+ const headerBlobHex = Buffer.from(JSON.stringify(headerObj)).toString("hex");
46002
+ return {
46003
+ header_blob: headerBlobHex,
46004
+ header_signature: bytesToHex2(msg.headerSignature),
46005
+ ciphertext: bytesToHex2(msg.ciphertext),
46006
+ nonce: bytesToHex2(msg.nonce)
46007
+ };
46008
+ }
46009
+ function hexTransportToEncryptedMessage(transport) {
46010
+ const headerJson = Buffer.from(transport.header_blob, "hex").toString("utf-8");
46011
+ const headerObj = JSON.parse(headerJson);
46012
+ return {
46013
+ header: {
46014
+ dhPublicKey: hexToBytes2(headerObj.dhPublicKey),
46015
+ previousChainLength: headerObj.previousChainLength,
46016
+ messageNumber: headerObj.messageNumber
46017
+ },
46018
+ headerSignature: hexToBytes2(transport.header_signature),
46019
+ ciphertext: hexToBytes2(transport.ciphertext),
46020
+ nonce: hexToBytes2(transport.nonce)
46021
+ };
46022
+ }
45487
46023
  var init_transport = __esm({
45488
46024
  async "../crypto/dist/transport.js"() {
45489
46025
  "use strict";
@@ -45747,6 +46283,33 @@ function buildEvalSpan(opts) {
45747
46283
  status: { code: 0 }
45748
46284
  };
45749
46285
  }
46286
+ function buildForgeSpan(opts) {
46287
+ const now = Date.now();
46288
+ const attributes = {
46289
+ "ai.agent.forge.session_id": opts.forgeSessionId,
46290
+ "ai.agent.forge.phase": opts.phase
46291
+ };
46292
+ if (opts.stageNumber !== void 0)
46293
+ attributes["ai.agent.forge.stage_number"] = opts.stageNumber;
46294
+ if (opts.artifactCount !== void 0)
46295
+ attributes["ai.agent.forge.artifact_count"] = opts.artifactCount;
46296
+ if (opts.scanStatus !== void 0)
46297
+ attributes["ai.agent.forge.scan_status"] = opts.scanStatus;
46298
+ applySkillName(attributes, opts.skillName);
46299
+ const isError = opts.status === "error";
46300
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46301
+ return {
46302
+ traceId: opts.traceId ?? generateTraceId(),
46303
+ spanId: opts.spanId ?? generateSpanId(),
46304
+ parentSpanId: opts.parentSpanId,
46305
+ name: `forge.${opts.phase}`,
46306
+ kind: "internal",
46307
+ startTime: now - opts.latencyMs,
46308
+ endTime: now,
46309
+ attributes,
46310
+ status
46311
+ };
46312
+ }
45750
46313
  function buildPolicyViolationSpan(opts) {
45751
46314
  const now = Date.now();
45752
46315
  const attributes = {
@@ -45775,9 +46338,306 @@ function buildPolicyViolationSpan(opts) {
45775
46338
  status: isBlock ? { code: 2, message: `Policy violation: ${opts.violationType}` } : { code: 0 }
45776
46339
  };
45777
46340
  }
46341
+ function buildDecisionSpan(opts) {
46342
+ const now = Date.now();
46343
+ const attributes = {
46344
+ "av.decision.id": opts.decisionId,
46345
+ "av.decision.phase": opts.phase
46346
+ };
46347
+ if (opts.priority)
46348
+ attributes["av.decision.priority"] = opts.priority;
46349
+ if (opts.category)
46350
+ attributes["av.decision.category"] = opts.category;
46351
+ applySkillName(attributes, opts.skillName);
46352
+ const isError = opts.status === "error";
46353
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46354
+ return {
46355
+ traceId: opts.traceId ?? generateTraceId(),
46356
+ spanId: opts.spanId ?? generateSpanId(),
46357
+ parentSpanId: opts.parentSpanId,
46358
+ name: "av.decision",
46359
+ kind: "internal",
46360
+ startTime: now - opts.latencyMs,
46361
+ endTime: now,
46362
+ attributes,
46363
+ status
46364
+ };
46365
+ }
46366
+ function buildResyncSpan(opts) {
46367
+ const now = Date.now();
46368
+ const attributes = {
46369
+ "av.resync.conversation_id": opts.conversationId,
46370
+ "av.resync.phase": opts.phase
46371
+ };
46372
+ if (opts.reason)
46373
+ attributes["av.resync.reason"] = opts.reason;
46374
+ applySkillName(attributes, opts.skillName);
46375
+ const isError = opts.status === "error";
46376
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46377
+ return {
46378
+ traceId: opts.traceId ?? generateTraceId(),
46379
+ spanId: opts.spanId ?? generateSpanId(),
46380
+ parentSpanId: opts.parentSpanId,
46381
+ name: "av.resync",
46382
+ kind: "internal",
46383
+ startTime: now - opts.latencyMs,
46384
+ endTime: now,
46385
+ attributes,
46386
+ status
46387
+ };
46388
+ }
46389
+ function buildA2aSpan(opts) {
46390
+ const now = Date.now();
46391
+ const attributes = {
46392
+ "av.a2a.channel_id": opts.channelId,
46393
+ "av.a2a.operation": opts.operation
46394
+ };
46395
+ if (opts.peerHubAddress)
46396
+ attributes["av.a2a.peer_hub_address"] = opts.peerHubAddress;
46397
+ if (opts.role)
46398
+ attributes["av.a2a.role"] = opts.role;
46399
+ applySkillName(attributes, opts.skillName);
46400
+ const isError = opts.status === "error";
46401
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46402
+ return {
46403
+ traceId: opts.traceId ?? generateTraceId(),
46404
+ spanId: opts.spanId ?? generateSpanId(),
46405
+ parentSpanId: opts.parentSpanId,
46406
+ name: "av.a2a",
46407
+ kind: "internal",
46408
+ startTime: now - opts.latencyMs,
46409
+ endTime: now,
46410
+ attributes,
46411
+ status
46412
+ };
46413
+ }
46414
+ function buildScanSpan(opts) {
46415
+ const now = Date.now();
46416
+ const attributes = {
46417
+ "av.scan.target": opts.scanTarget,
46418
+ "av.scan.type": opts.scanType,
46419
+ "av.scan.violation_count": opts.violationCount,
46420
+ "av.scan.rule_count": opts.ruleCount
46421
+ };
46422
+ applySkillName(attributes, opts.skillName);
46423
+ const isError = opts.status === "error" || opts.violationCount > 0;
46424
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46425
+ return {
46426
+ traceId: opts.traceId ?? generateTraceId(),
46427
+ spanId: opts.spanId ?? generateSpanId(),
46428
+ parentSpanId: opts.parentSpanId,
46429
+ name: "av.scan",
46430
+ kind: "internal",
46431
+ startTime: now - opts.latencyMs,
46432
+ endTime: now,
46433
+ attributes,
46434
+ status
46435
+ };
46436
+ }
46437
+ function buildWorkspaceSpan(opts) {
46438
+ const now = Date.now();
46439
+ const attributes = {
46440
+ "av.workspace.id": opts.workspaceId,
46441
+ "av.workspace.operation": opts.operation
46442
+ };
46443
+ if (opts.fileName)
46444
+ attributes["av.workspace.file_name"] = opts.fileName;
46445
+ if (opts.fileSizeBytes !== void 0)
46446
+ attributes["av.workspace.file_size_bytes"] = opts.fileSizeBytes;
46447
+ if (opts.encrypted !== void 0)
46448
+ attributes["av.workspace.encrypted"] = opts.encrypted;
46449
+ applySkillName(attributes, opts.skillName);
46450
+ const isError = opts.status === "error";
46451
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46452
+ return {
46453
+ traceId: opts.traceId ?? generateTraceId(),
46454
+ spanId: opts.spanId ?? generateSpanId(),
46455
+ parentSpanId: opts.parentSpanId,
46456
+ name: "av.workspace",
46457
+ kind: "internal",
46458
+ startTime: now - opts.latencyMs,
46459
+ endTime: now,
46460
+ attributes,
46461
+ status
46462
+ };
46463
+ }
46464
+ function buildCapabilitySpan(opts) {
46465
+ const now = Date.now();
46466
+ const attributes = {
46467
+ "av.skill.operation": opts.operation,
46468
+ "av.skill.success": opts.success
46469
+ };
46470
+ if (opts.skillName)
46471
+ attributes["av.skill.name"] = opts.skillName;
46472
+ if (opts.version)
46473
+ attributes["av.skill.version"] = opts.version;
46474
+ if (opts.certificationTier)
46475
+ attributes["av.skill.certification_tier"] = opts.certificationTier;
46476
+ if (opts.toolsUsed?.length)
46477
+ attributes["av.skill.tools_used"] = opts.toolsUsed.join(",");
46478
+ const status = opts.success ? { code: 0 } : { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} };
46479
+ return {
46480
+ traceId: opts.traceId ?? generateTraceId(),
46481
+ spanId: opts.spanId ?? generateSpanId(),
46482
+ parentSpanId: opts.parentSpanId,
46483
+ name: "av.skill.invoke",
46484
+ kind: "internal",
46485
+ startTime: now - opts.latencyMs,
46486
+ endTime: now,
46487
+ attributes,
46488
+ status
46489
+ };
46490
+ }
46491
+ function buildEnrollmentSpan(opts) {
46492
+ const now = Date.now();
46493
+ const attributes = {
46494
+ "av.enrollment.phase": opts.phase
46495
+ };
46496
+ if (opts.deviceId)
46497
+ attributes["av.enrollment.device_id"] = opts.deviceId;
46498
+ if (opts.enrollmentType)
46499
+ attributes["av.enrollment.type"] = opts.enrollmentType;
46500
+ applySkillName(attributes, opts.skillName);
46501
+ const isError = opts.status === "error" || opts.phase === "fail";
46502
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46503
+ return {
46504
+ traceId: opts.traceId ?? generateTraceId(),
46505
+ spanId: opts.spanId ?? generateSpanId(),
46506
+ parentSpanId: opts.parentSpanId,
46507
+ name: "av.enrollment",
46508
+ kind: "internal",
46509
+ startTime: now - opts.latencyMs,
46510
+ endTime: now,
46511
+ attributes,
46512
+ status
46513
+ };
46514
+ }
46515
+ function buildRoomSpan(opts) {
46516
+ const now = Date.now();
46517
+ const attributes = {
46518
+ "av.room.id": opts.roomId,
46519
+ "av.room.operation": opts.operation
46520
+ };
46521
+ if (opts.roomName)
46522
+ attributes["av.room.name"] = opts.roomName;
46523
+ if (opts.memberCount !== void 0)
46524
+ attributes["av.room.member_count"] = opts.memberCount;
46525
+ applySkillName(attributes, opts.skillName);
46526
+ const isError = opts.status === "error";
46527
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46528
+ return {
46529
+ traceId: opts.traceId ?? generateTraceId(),
46530
+ spanId: opts.spanId ?? generateSpanId(),
46531
+ parentSpanId: opts.parentSpanId,
46532
+ name: "av.room",
46533
+ kind: "internal",
46534
+ startTime: now - opts.latencyMs,
46535
+ endTime: now,
46536
+ attributes,
46537
+ status
46538
+ };
46539
+ }
46540
+ function buildTrustSpan(opts) {
46541
+ const now = Date.now();
46542
+ const attributes = {
46543
+ "av.trust.agent_hub_address": opts.agentHubAddress,
46544
+ "av.trust.operation": opts.operation
46545
+ };
46546
+ if (opts.previousTier)
46547
+ attributes["av.trust.previous_tier"] = opts.previousTier;
46548
+ if (opts.newTier)
46549
+ attributes["av.trust.new_tier"] = opts.newTier;
46550
+ if (opts.overallScore !== void 0)
46551
+ attributes["av.trust.overall_score"] = opts.overallScore;
46552
+ if (opts.dimension)
46553
+ attributes["av.trust.dimension"] = opts.dimension;
46554
+ if (opts.dimensionScore !== void 0)
46555
+ attributes["av.trust.dimension_score"] = opts.dimensionScore;
46556
+ applySkillName(attributes, opts.skillName);
46557
+ const isError = opts.status === "error";
46558
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46559
+ return {
46560
+ traceId: opts.traceId ?? generateTraceId(),
46561
+ spanId: opts.spanId ?? generateSpanId(),
46562
+ parentSpanId: opts.parentSpanId,
46563
+ name: "av.trust",
46564
+ kind: "internal",
46565
+ startTime: now - opts.latencyMs,
46566
+ endTime: now,
46567
+ attributes,
46568
+ status
46569
+ };
46570
+ }
46571
+ function buildEvalRunSpan(opts) {
46572
+ const now = Date.now();
46573
+ const attributes = {
46574
+ "av.eval.scenario_id": opts.scenarioId,
46575
+ "av.eval.agent_id": opts.agentId,
46576
+ "av.eval.status": opts.status,
46577
+ "av.eval.latency_ms": opts.latencyMs
46578
+ };
46579
+ if (opts.scenarioName)
46580
+ attributes["av.eval.scenario_name"] = opts.scenarioName;
46581
+ if (opts.variationType)
46582
+ attributes["av.eval.variation_type"] = opts.variationType;
46583
+ if (opts.shiftMagnitude !== void 0)
46584
+ attributes["av.eval.shift_magnitude"] = opts.shiftMagnitude;
46585
+ if (opts.outcomeMatch !== void 0)
46586
+ attributes["av.eval.outcome_match"] = opts.outcomeMatch;
46587
+ if (opts.flagged !== void 0)
46588
+ attributes["av.eval.flagged"] = opts.flagged;
46589
+ if (opts.flagReason)
46590
+ attributes["av.eval.flag_reason"] = opts.flagReason;
46591
+ const isError = opts.status === "failed";
46592
+ const status = isError ? { code: 2, ...opts.statusMessage ? { message: opts.statusMessage } : {} } : { code: 0 };
46593
+ return {
46594
+ traceId: opts.traceId ?? generateTraceId(),
46595
+ spanId: opts.spanId ?? generateSpanId(),
46596
+ parentSpanId: opts.parentSpanId,
46597
+ name: "av.eval.run",
46598
+ kind: "internal",
46599
+ startTime: now - opts.latencyMs,
46600
+ endTime: now,
46601
+ attributes,
46602
+ status
46603
+ };
46604
+ }
45778
46605
  function buildTraceparent(span) {
45779
46606
  return `00-${span.traceId}-${span.spanId}-01`;
45780
46607
  }
46608
+ function parseTraceparent(header) {
46609
+ const parts = header.split("-");
46610
+ if (parts.length !== 4)
46611
+ return null;
46612
+ const [version2, traceId, parentId, traceFlags] = parts;
46613
+ if (!version2 || !traceId || !parentId || !traceFlags)
46614
+ return null;
46615
+ if (traceId.length !== 32 || parentId.length !== 16)
46616
+ return null;
46617
+ return { version: version2, traceId, parentId, traceFlags };
46618
+ }
46619
+ function spanToTraceContext(span, tracestate) {
46620
+ return {
46621
+ traceparent: buildTraceparent(span),
46622
+ tracestate: tracestate ?? `av=s:${span.spanId}`
46623
+ };
46624
+ }
46625
+ function propagateContext(incomingTraceparent) {
46626
+ const parsed = parseTraceparent(incomingTraceparent);
46627
+ if (!parsed)
46628
+ return null;
46629
+ return {
46630
+ traceId: parsed.traceId,
46631
+ parentSpanId: parsed.parentId,
46632
+ spanId: generateSpanId()
46633
+ };
46634
+ }
46635
+ function spanToW3CHeaders(span, tracestate) {
46636
+ return {
46637
+ traceparent: buildTraceparent(span),
46638
+ tracestate: tracestate ?? `av=s:${span.spanId}`
46639
+ };
46640
+ }
45781
46641
  var init_telemetry = __esm({
45782
46642
  "../crypto/dist/telemetry.js"() {
45783
46643
  "use strict";
@@ -45948,6 +46808,29 @@ var init_telemetry_reporter = __esm({
45948
46808
  });
45949
46809
 
45950
46810
  // ../crypto/dist/backup.js
46811
+ async function generateBackupCode() {
46812
+ await libsodium_wrappers_default.ready;
46813
+ const bytes = libsodium_wrappers_default.randombytes_buf(13);
46814
+ let bits = 0n;
46815
+ for (const b2 of bytes) {
46816
+ bits = bits << 8n | BigInt(b2);
46817
+ }
46818
+ bits >>= 4n;
46819
+ let code = "";
46820
+ for (let i2 = 0; i2 < 20; i2++) {
46821
+ const idx = Number(bits & 0x1fn);
46822
+ code = CROCKFORD[idx] + code;
46823
+ bits >>= 5n;
46824
+ }
46825
+ return code;
46826
+ }
46827
+ function formatBackupCode(code) {
46828
+ const clean5 = code.replace(/[-\s]/g, "").toUpperCase();
46829
+ return clean5.match(/.{1,4}/g)?.join("-") ?? clean5;
46830
+ }
46831
+ function normalizeBackupCode(input) {
46832
+ return input.replace(/[-\s]/g, "").toUpperCase();
46833
+ }
45951
46834
  async function deriveBackupKey(code, salt) {
45952
46835
  await libsodium_wrappers_default.ready;
45953
46836
  return libsodium_wrappers_default.crypto_pwhash(KEY_BYTES, code, salt, ARGON2_OPSLIMIT, ARGON2_MEMLIMIT, libsodium_wrappers_default.crypto_pwhash_ALG_ARGON2ID13);
@@ -45969,28 +46852,88 @@ async function encryptBackupWithKey(bundle, key, salt) {
45969
46852
  result.set(ciphertext, SALT_BYTES + NONCE_BYTES);
45970
46853
  return result;
45971
46854
  }
46855
+ async function decryptBackup(encrypted, code) {
46856
+ await libsodium_wrappers_default.ready;
46857
+ const minLen = SALT_BYTES + NONCE_BYTES + libsodium_wrappers_default.crypto_aead_xchacha20poly1305_ietf_ABYTES;
46858
+ if (encrypted.length < minLen) {
46859
+ throw new Error("Incorrect backup code or corrupt backup");
46860
+ }
46861
+ const salt = encrypted.slice(0, SALT_BYTES);
46862
+ const nonce = encrypted.slice(SALT_BYTES, SALT_BYTES + NONCE_BYTES);
46863
+ const ciphertext = encrypted.slice(SALT_BYTES + NONCE_BYTES);
46864
+ const key = await deriveBackupKey(code, salt);
46865
+ let plaintext;
46866
+ try {
46867
+ plaintext = libsodium_wrappers_default.crypto_aead_xchacha20poly1305_ietf_decrypt(null, ciphertext, null, nonce, key);
46868
+ } catch {
46869
+ throw new Error("Incorrect backup code or corrupt backup");
46870
+ }
46871
+ let bundle;
46872
+ try {
46873
+ bundle = JSON.parse(libsodium_wrappers_default.to_string(plaintext));
46874
+ } catch {
46875
+ throw new Error("Incorrect backup code or corrupt backup");
46876
+ }
46877
+ if (bundle.version !== BACKUP_VERSION) {
46878
+ throw new Error(`Unsupported backup version: ${bundle.version}`);
46879
+ }
46880
+ return bundle;
46881
+ }
45972
46882
  async function hashBackupCode(code) {
45973
46883
  await libsodium_wrappers_default.ready;
45974
46884
  return libsodium_wrappers_default.crypto_generichash(32, libsodium_wrappers_default.from_string(code));
45975
46885
  }
45976
- var ARGON2_OPSLIMIT, ARGON2_MEMLIMIT, SALT_BYTES, NONCE_BYTES, KEY_BYTES, MAX_BACKUP_SIZE;
46886
+ var CROCKFORD, ARGON2_OPSLIMIT, ARGON2_MEMLIMIT, SALT_BYTES, NONCE_BYTES, KEY_BYTES, BACKUP_VERSION, MAX_BACKUP_SIZE;
45977
46887
  var init_backup = __esm({
45978
46888
  async "../crypto/dist/backup.js"() {
45979
46889
  "use strict";
45980
46890
  await init_libsodium_wrappers();
46891
+ CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
45981
46892
  ARGON2_OPSLIMIT = 2;
45982
46893
  ARGON2_MEMLIMIT = 67108864;
45983
46894
  SALT_BYTES = 16;
45984
46895
  NONCE_BYTES = 24;
45985
46896
  KEY_BYTES = 32;
46897
+ BACKUP_VERSION = 1;
45986
46898
  MAX_BACKUP_SIZE = 512 * 1024;
45987
46899
  }
45988
46900
  });
45989
46901
 
45990
46902
  // ../crypto/dist/approval.js
46903
+ async function createApprovalArtifact(content, privateKeyHex) {
46904
+ await libsodium_wrappers_default.ready;
46905
+ const sodium = libsodium_wrappers_default;
46906
+ const privateKey = sodium.from_hex(privateKeyHex);
46907
+ const publicKey = privateKey.slice(32);
46908
+ const message = canonicalize(content);
46909
+ const signatureBytes = sodium.crypto_sign_detached(message, privateKey);
46910
+ return {
46911
+ content,
46912
+ signature: sodium.to_hex(signatureBytes),
46913
+ signerPublicKey: sodium.to_hex(publicKey),
46914
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
46915
+ version: 1
46916
+ };
46917
+ }
46918
+ async function verifyApprovalArtifact(artifact, expectedPublicKeyHex) {
46919
+ await libsodium_wrappers_default.ready;
46920
+ const sodium = libsodium_wrappers_default;
46921
+ if (expectedPublicKeyHex && artifact.signerPublicKey !== expectedPublicKeyHex) {
46922
+ return false;
46923
+ }
46924
+ try {
46925
+ const publicKey = sodium.from_hex(artifact.signerPublicKey);
46926
+ const signature = sodium.from_hex(artifact.signature);
46927
+ const message = canonicalize(artifact.content);
46928
+ return sodium.crypto_sign_verify_detached(signature, message, publicKey);
46929
+ } catch {
46930
+ return false;
46931
+ }
46932
+ }
45991
46933
  var init_approval = __esm({
45992
46934
  async "../crypto/dist/approval.js"() {
45993
46935
  "use strict";
46936
+ await init_libsodium_wrappers();
45994
46937
  await init_did();
45995
46938
  }
45996
46939
  });
@@ -54937,7 +55880,7 @@ function byteSwap32(arr) {
54937
55880
  }
54938
55881
  return arr;
54939
55882
  }
54940
- function bytesToHex3(bytes) {
55883
+ function bytesToHex4(bytes) {
54941
55884
  abytes3(bytes);
54942
55885
  if (hasHexBuiltin)
54943
55886
  return bytes.toHex();
@@ -54956,7 +55899,7 @@ function asciiToBase16(ch) {
54956
55899
  return ch - (asciis.a - 10);
54957
55900
  return;
54958
55901
  }
54959
- function hexToBytes3(hex3) {
55902
+ function hexToBytes4(hex3) {
54960
55903
  if (typeof hex3 !== "string")
54961
55904
  throw new Error("hex string expected, got " + typeof hex3);
54962
55905
  if (hasHexBuiltin)
@@ -55252,7 +56195,7 @@ var init_u642 = __esm({
55252
56195
  });
55253
56196
 
55254
56197
  // ../../node_modules/@noble/curves/node_modules/@noble/hashes/esm/sha2.js
55255
- var SHA256_K, SHA256_W, SHA256, K512, SHA512_Kh, SHA512_Kl, SHA512_W_H, SHA512_W_L, SHA512, SHA384, sha2562, sha5122, sha3842;
56198
+ var SHA256_K, SHA256_W, SHA256, K512, SHA512_Kh, SHA512_Kl, SHA512_W_H, SHA512_W_L, SHA512, SHA384, sha2563, sha5122, sha3842;
55256
56199
  var init_sha22 = __esm({
55257
56200
  "../../node_modules/@noble/curves/node_modules/@noble/hashes/esm/sha2.js"() {
55258
56201
  init_md2();
@@ -55613,7 +56556,7 @@ var init_sha22 = __esm({
55613
56556
  this.Hl = SHA384_IV2[15] | 0;
55614
56557
  }
55615
56558
  };
55616
- sha2562 = /* @__PURE__ */ createHasher2(() => new SHA256());
56559
+ sha2563 = /* @__PURE__ */ createHasher2(() => new SHA256());
55617
56560
  sha5122 = /* @__PURE__ */ createHasher2(() => new SHA512());
55618
56561
  sha3842 = /* @__PURE__ */ createHasher2(() => new SHA384());
55619
56562
  }
@@ -55649,14 +56592,14 @@ function hexToNumber3(hex3) {
55649
56592
  return hex3 === "" ? _0n2 : BigInt("0x" + hex3);
55650
56593
  }
55651
56594
  function bytesToNumberBE(bytes) {
55652
- return hexToNumber3(bytesToHex3(bytes));
56595
+ return hexToNumber3(bytesToHex4(bytes));
55653
56596
  }
55654
56597
  function bytesToNumberLE2(bytes) {
55655
56598
  abytes3(bytes);
55656
- return hexToNumber3(bytesToHex3(Uint8Array.from(bytes).reverse()));
56599
+ return hexToNumber3(bytesToHex4(Uint8Array.from(bytes).reverse()));
55657
56600
  }
55658
56601
  function numberToBytesBE2(n2, len) {
55659
- return hexToBytes3(n2.toString(16).padStart(len * 2, "0"));
56602
+ return hexToBytes4(n2.toString(16).padStart(len * 2, "0"));
55660
56603
  }
55661
56604
  function numberToBytesLE2(n2, len) {
55662
56605
  return numberToBytesBE2(n2, len).reverse();
@@ -55665,7 +56608,7 @@ function ensureBytes(title, hex3, expectedLength) {
55665
56608
  let res;
55666
56609
  if (typeof hex3 === "string") {
55667
56610
  try {
55668
- res = hexToBytes3(hex3);
56611
+ res = hexToBytes4(hex3);
55669
56612
  } catch (e) {
55670
56613
  throw new Error(title + " must be hex string or Uint8Array, cause: " + e);
55671
56614
  }
@@ -56693,7 +57636,7 @@ function edwards(params, extraOpts = {}) {
56693
57636
  return bytes;
56694
57637
  }
56695
57638
  toHex() {
56696
- return bytesToHex3(this.toBytes());
57639
+ return bytesToHex4(this.toBytes());
56697
57640
  }
56698
57641
  toString() {
56699
57642
  return `<Point ${this.is0() ? "ZERO" : this.toHex()}>`;
@@ -56965,7 +57908,7 @@ var init_edwards = __esm({
56965
57908
  return this.ep.toAffine(invertedZ);
56966
57909
  }
56967
57910
  toHex() {
56968
- return bytesToHex3(this.toBytes());
57911
+ return bytesToHex4(this.toBytes());
56969
57912
  }
56970
57913
  toString() {
56971
57914
  return this.toHex();
@@ -58766,7 +59709,7 @@ function weierstrassN(params, extraOpts = {}) {
58766
59709
  return encodePoint(Point, this, isCompressed);
58767
59710
  }
58768
59711
  toHex(isCompressed = true) {
58769
- return bytesToHex3(this.toBytes(isCompressed));
59712
+ return bytesToHex4(this.toBytes(isCompressed));
58770
59713
  }
58771
59714
  toString() {
58772
59715
  return `<Point ${this.is0() ? "ZERO" : this.toHex()}>`;
@@ -59050,7 +59993,7 @@ function ecdsa(Point, hash2, ecdsaOpts = {}) {
59050
59993
  return new Signature(Fn3.fromBytes(r2), Fn3.fromBytes(s2), recid);
59051
59994
  }
59052
59995
  static fromHex(hex3, format) {
59053
- return this.fromBytes(hexToBytes3(hex3), format);
59996
+ return this.fromBytes(hexToBytes4(hex3), format);
59054
59997
  }
59055
59998
  addRecoveryBit(recovery) {
59056
59999
  return new Signature(this.r, this.s, recovery);
@@ -59085,7 +60028,7 @@ function ecdsa(Point, hash2, ecdsaOpts = {}) {
59085
60028
  toBytes(format = defaultSigOpts_format) {
59086
60029
  validateSigFormat(format);
59087
60030
  if (format === "der")
59088
- return hexToBytes3(DER.hexFromSig(this));
60031
+ return hexToBytes4(DER.hexFromSig(this));
59089
60032
  const r2 = Fn3.toBytes(this.r);
59090
60033
  const s2 = Fn3.toBytes(this.s);
59091
60034
  if (format === "recovered") {
@@ -59096,7 +60039,7 @@ function ecdsa(Point, hash2, ecdsaOpts = {}) {
59096
60039
  return concatBytes2(r2, s2);
59097
60040
  }
59098
60041
  toHex(format) {
59099
- return bytesToHex3(this.toBytes(format));
60042
+ return bytesToHex4(this.toBytes(format));
59100
60043
  }
59101
60044
  // TODO: remove
59102
60045
  assertValidity() {
@@ -59114,13 +60057,13 @@ function ecdsa(Point, hash2, ecdsaOpts = {}) {
59114
60057
  return this.toBytes("der");
59115
60058
  }
59116
60059
  toDERHex() {
59117
- return bytesToHex3(this.toBytes("der"));
60060
+ return bytesToHex4(this.toBytes("der"));
59118
60061
  }
59119
60062
  toCompactRawBytes() {
59120
60063
  return this.toBytes("compact");
59121
60064
  }
59122
60065
  toCompactHex() {
59123
- return bytesToHex3(this.toBytes("compact"));
60066
+ return bytesToHex4(this.toBytes("compact"));
59124
60067
  }
59125
60068
  }
59126
60069
  const bits2int = ecdsaOpts.bits2int || function bits2int_def(bytes) {
@@ -59499,7 +60442,7 @@ var init_nist = __esm({
59499
60442
  Fp256 = Field(p256_CURVE.p);
59500
60443
  Fp384 = Field(p384_CURVE.p);
59501
60444
  Fp521 = Field(p521_CURVE.p);
59502
- p256 = createCurve({ ...p256_CURVE, Fp: Fp256, lowS: false }, sha2562);
60445
+ p256 = createCurve({ ...p256_CURVE, Fp: Fp256, lowS: false }, sha2563);
59503
60446
  p256_hasher = /* @__PURE__ */ (() => {
59504
60447
  return createHasher3(p256.Point, createSWU(p256.Point, {
59505
60448
  A: p256_CURVE.a,
@@ -59512,7 +60455,7 @@ var init_nist = __esm({
59512
60455
  m: 1,
59513
60456
  k: 128,
59514
60457
  expand: "xmd",
59515
- hash: sha2562
60458
+ hash: sha2563
59516
60459
  });
59517
60460
  })();
59518
60461
  p384 = createCurve({ ...p384_CURVE, Fp: Fp384, lowS: false }, sha3842);
@@ -60020,7 +60963,7 @@ var init_u643 = __esm({
60020
60963
  });
60021
60964
 
60022
60965
  // ../crypto/node_modules/@noble/hashes/sha2.js
60023
- 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;
60966
+ 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;
60024
60967
  var init_sha23 = __esm({
60025
60968
  "../crypto/node_modules/@noble/hashes/sha2.js"() {
60026
60969
  init_md3();
@@ -60393,7 +61336,7 @@ var init_sha23 = __esm({
60393
61336
  super(48);
60394
61337
  }
60395
61338
  };
60396
- sha2563 = /* @__PURE__ */ createHasher4(
61339
+ sha2564 = /* @__PURE__ */ createHasher4(
60397
61340
  () => new _SHA256(),
60398
61341
  /* @__PURE__ */ oidNist2(1)
60399
61342
  );
@@ -60491,7 +61434,7 @@ function makeHashImpl2(h2) {
60491
61434
  async digest(data) {
60492
61435
  switch (h2) {
60493
61436
  case "SHA-256":
60494
- return sha2563(data);
61437
+ return sha2564(data);
60495
61438
  case "SHA-384":
60496
61439
  return sha3843(data);
60497
61440
  case "SHA-512":
@@ -60503,7 +61446,7 @@ function makeHashImpl2(h2) {
60503
61446
  async mac(key, data) {
60504
61447
  switch (h2) {
60505
61448
  case "SHA-256":
60506
- return hmac3(sha2563, key, data);
61449
+ return hmac3(sha2564, key, data);
60507
61450
  case "SHA-384":
60508
61451
  return hmac3(sha3843, key, data);
60509
61452
  case "SHA-512":
@@ -61670,6 +62613,92 @@ var init_mls_group = __esm({
61670
62613
  });
61671
62614
 
61672
62615
  // ../crypto/dist/index.js
62616
+ var dist_exports = {};
62617
+ __export(dist_exports, {
62618
+ AV_CREDENTIAL_CONTEXT: () => AV_CREDENTIAL_CONTEXT,
62619
+ CRYPTOSUITE: () => CRYPTOSUITE,
62620
+ DOMAIN_DID_DOCUMENT: () => DOMAIN_DID_DOCUMENT,
62621
+ DOMAIN_TRANSFER_ACCEPT: () => DOMAIN_TRANSFER_ACCEPT,
62622
+ DOMAIN_TRANSFER_INTENT: () => DOMAIN_TRANSFER_INTENT,
62623
+ DoubleRatchet: () => DoubleRatchet,
62624
+ MLSGroupManager: () => MLSGroupManager,
62625
+ ScanEngine: () => ScanEngine,
62626
+ TelemetryReporter: () => TelemetryReporter,
62627
+ VC_CONTEXT_V2: () => VC_CONTEXT_V2,
62628
+ base64ToBytes: () => base64ToBytes,
62629
+ buildA2aSpan: () => buildA2aSpan,
62630
+ buildActionSpan: () => buildActionSpan,
62631
+ buildAgentTrustCredential: () => buildAgentTrustCredential,
62632
+ buildAgentTrustReportCredential: () => buildAgentTrustReportCredential,
62633
+ buildCapabilitySpan: () => buildCapabilitySpan,
62634
+ buildDecisionSpan: () => buildDecisionSpan,
62635
+ buildDidDocument: () => buildDidDocument,
62636
+ buildEnrollmentSpan: () => buildEnrollmentSpan,
62637
+ buildErrorSpan: () => buildErrorSpan,
62638
+ buildEvalRunSpan: () => buildEvalRunSpan,
62639
+ buildEvalSpan: () => buildEvalSpan,
62640
+ buildForgeSpan: () => buildForgeSpan,
62641
+ buildHttpSpan: () => buildHttpSpan,
62642
+ buildLlmSpan: () => buildLlmSpan,
62643
+ buildNavSpan: () => buildNavSpan,
62644
+ buildPerformanceRecord: () => buildPerformanceRecord,
62645
+ buildPolicyViolationSpan: () => buildPolicyViolationSpan,
62646
+ buildResyncSpan: () => buildResyncSpan,
62647
+ buildRoomSpan: () => buildRoomSpan,
62648
+ buildScanSpan: () => buildScanSpan,
62649
+ buildSkillAttestation: () => buildSkillAttestation,
62650
+ buildSkillInvocationSpan: () => buildSkillInvocationSpan,
62651
+ buildTaskSpan: () => buildTaskSpan,
62652
+ buildToolSpan: () => buildToolSpan,
62653
+ buildTraceparent: () => buildTraceparent,
62654
+ buildTrustSpan: () => buildTrustSpan,
62655
+ buildVerifiablePresentation: () => buildVerifiablePresentation,
62656
+ buildWorkspaceSpan: () => buildWorkspaceSpan,
62657
+ bytesToBase64: () => bytesToBase64,
62658
+ bytesToHex: () => bytesToHex2,
62659
+ canonicalize: () => canonicalize,
62660
+ computeDidHash: () => computeDidHash,
62661
+ computeFileDigest: () => computeFileDigest,
62662
+ computeFingerprint: () => computeFingerprint,
62663
+ createApprovalArtifact: () => createApprovalArtifact,
62664
+ createProofOfPossession: () => createProofOfPossession,
62665
+ decryptBackup: () => decryptBackup,
62666
+ decryptFile: () => decryptFile,
62667
+ deriveBackupKey: () => deriveBackupKey,
62668
+ encryptBackup: () => encryptBackup,
62669
+ encryptBackupWithKey: () => encryptBackupWithKey,
62670
+ encryptFile: () => encryptFile,
62671
+ encryptedMessageToHexTransport: () => encryptedMessageToHexTransport,
62672
+ encryptedMessageToTransport: () => encryptedMessageToTransport,
62673
+ encryptedMessageToTransportV2: () => encryptedMessageToTransportV2,
62674
+ encryptedMessageToTransportV2Full: () => encryptedMessageToTransportV2Full,
62675
+ formatBackupCode: () => formatBackupCode,
62676
+ generateBackupCode: () => generateBackupCode,
62677
+ generateEphemeralKeypair: () => generateEphemeralKeypair,
62678
+ generateIdentityKeypair: () => generateIdentityKeypair,
62679
+ hashBackupCode: () => hashBackupCode,
62680
+ hexToBytes: () => hexToBytes2,
62681
+ hexTransportToEncryptedMessage: () => hexTransportToEncryptedMessage,
62682
+ issueCredential: () => issueCredential,
62683
+ multibaseToPublicKey: () => multibaseToPublicKey,
62684
+ normalizeBackupCode: () => normalizeBackupCode,
62685
+ parseTraceparent: () => parseTraceparent,
62686
+ performX3DH: () => performX3DH,
62687
+ presentCredentials: () => presentCredentials,
62688
+ propagateContext: () => propagateContext,
62689
+ publicKeyToMultibase: () => publicKeyToMultibase,
62690
+ signDocument: () => signDocument,
62691
+ signWithDataIntegrity: () => signWithDataIntegrity,
62692
+ spanToTraceContext: () => spanToTraceContext,
62693
+ spanToW3CHeaders: () => spanToW3CHeaders,
62694
+ transportToEncryptedMessage: () => transportToEncryptedMessage,
62695
+ transportV2ToEncryptedMessage: () => transportV2ToEncryptedMessage,
62696
+ verifyApprovalArtifact: () => verifyApprovalArtifact,
62697
+ verifyDataIntegrity: () => verifyDataIntegrity,
62698
+ verifyDocumentSignature: () => verifyDocumentSignature,
62699
+ verifyMerkleProof: () => verifyMerkleProof,
62700
+ verifyProofOfPossession: () => verifyProofOfPossession
62701
+ });
61673
62702
  var init_dist = __esm({
61674
62703
  async "../crypto/dist/index.js"() {
61675
62704
  "use strict";
@@ -61960,7 +62989,7 @@ async function uploadBackupToServer(state, backupCode, apiUrl, deviceJwt) {
61960
62989
  },
61961
62990
  body: JSON.stringify({
61962
62991
  backup_blob: bytesToBase64(encrypted),
61963
- backup_code_hash: bytesToHex(codeHash)
62992
+ backup_code_hash: bytesToHex2(codeHash)
61964
62993
  })
61965
62994
  });
61966
62995
  if (!resp.ok) {
@@ -62533,7 +63562,7 @@ function migratePersistedState(raw) {
62533
63562
  messageHistory: []
62534
63563
  };
62535
63564
  }
62536
- var ROOM_AGENT_TYPES, CREDENTIAL_MESSAGE_TYPES, POLL_INTERVAL_MS, RECONNECT_BASE_MS, RECONNECT_MAX_MS, PENDING_POLL_INTERVAL_MS, SecureChannel;
63565
+ var ROOM_AGENT_TYPES, CREDENTIAL_MESSAGE_TYPES, CATCHUP_MESSAGE_TYPES, POLL_INTERVAL_MS, RECONNECT_BASE_MS, RECONNECT_MAX_MS, PENDING_POLL_INTERVAL_MS, SecureChannel;
62537
63566
  var init_channel = __esm({
62538
63567
  async "src/channel.ts"() {
62539
63568
  "use strict";
@@ -62556,6 +63585,10 @@ var init_channel = __esm({
62556
63585
  "credential_revoke",
62557
63586
  "credential_request"
62558
63587
  ]);
63588
+ CATCHUP_MESSAGE_TYPES = /* @__PURE__ */ new Set([
63589
+ "history_catchup_request",
63590
+ "history_catchup_response"
63591
+ ]);
62559
63592
  POLL_INTERVAL_MS = 6e3;
62560
63593
  RECONNECT_BASE_MS = 1e3;
62561
63594
  RECONNECT_MAX_MS = 3e4;
@@ -62604,6 +63637,8 @@ var init_channel = __esm({
62604
63637
  _mlsGroups = /* @__PURE__ */ new Map();
62605
63638
  /** Cached MLS KeyPackage bundle for this device (regenerated on each connect). */
62606
63639
  _mlsKeyPackage = null;
63640
+ /** Pending KeyPackage bundle from request-Welcome flow (used by _handleMlsWelcome). */
63641
+ _pendingMlsKpBundle;
62607
63642
  /** In-memory credential store for renter-provided credentials (never persisted). */
62608
63643
  _credentialStore = new CredentialStore();
62609
63644
  /** Dedup buffer for A2A message IDs (prevents double-delivery via direct + Redis) */
@@ -64040,9 +65075,9 @@ var init_channel = __esm({
64040
65075
  const result = await enrollDevice(
64041
65076
  this.config.apiUrl,
64042
65077
  this.config.inviteToken,
64043
- bytesToHex(identity.publicKey),
64044
- bytesToHex(ephemeral.publicKey),
64045
- bytesToHex(proof),
65078
+ bytesToHex2(identity.publicKey),
65079
+ bytesToHex2(ephemeral.publicKey),
65080
+ bytesToHex2(proof),
64046
65081
  this.config.platform
64047
65082
  );
64048
65083
  this._deviceId = result.device_id;
@@ -64056,12 +65091,12 @@ var init_channel = __esm({
64056
65091
  sessions: {},
64057
65092
  // populated after activation
64058
65093
  identityKeypair: {
64059
- publicKey: bytesToHex(identity.publicKey),
64060
- privateKey: bytesToHex(identity.privateKey)
65094
+ publicKey: bytesToHex2(identity.publicKey),
65095
+ privateKey: bytesToHex2(identity.privateKey)
64061
65096
  },
64062
65097
  ephemeralKeypair: {
64063
- publicKey: bytesToHex(ephemeral.publicKey),
64064
- privateKey: bytesToHex(ephemeral.privateKey)
65098
+ publicKey: bytesToHex2(ephemeral.publicKey),
65099
+ privateKey: bytesToHex2(ephemeral.privateKey)
64065
65100
  },
64066
65101
  fingerprint: result.fingerprint,
64067
65102
  messageHistory: []
@@ -64124,17 +65159,17 @@ var init_channel = __esm({
64124
65159
  const ownerIdentityKey = conv.owner_identity_public_key || result.owner_identity_public_key;
64125
65160
  const ownerEphemeralKey = conv.owner_ephemeral_public_key || result.owner_ephemeral_public_key || ownerIdentityKey;
64126
65161
  const sharedSecret = performX3DH({
64127
- myIdentityPrivate: hexToBytes(identity.privateKey),
64128
- myEphemeralPrivate: hexToBytes(ephemeral.privateKey),
64129
- theirIdentityPublic: hexToBytes(ownerIdentityKey),
64130
- theirEphemeralPublic: hexToBytes(ownerEphemeralKey),
65162
+ myIdentityPrivate: hexToBytes2(identity.privateKey),
65163
+ myEphemeralPrivate: hexToBytes2(ephemeral.privateKey),
65164
+ theirIdentityPublic: hexToBytes2(ownerIdentityKey),
65165
+ theirEphemeralPublic: hexToBytes2(ownerEphemeralKey),
64131
65166
  isInitiator: false
64132
65167
  });
64133
65168
  const ratchet = DoubleRatchet.initReceiver(sharedSecret, {
64134
- publicKey: hexToBytes(identity.publicKey),
64135
- privateKey: hexToBytes(identity.privateKey),
65169
+ publicKey: hexToBytes2(identity.publicKey),
65170
+ privateKey: hexToBytes2(identity.privateKey),
64136
65171
  keyType: "ed25519"
64137
- }, hexToBytes(ownerIdentityKey));
65172
+ }, hexToBytes2(ownerIdentityKey));
64138
65173
  this._sessions.set(conv.conversation_id, {
64139
65174
  ownerDeviceId: conv.owner_device_id,
64140
65175
  ratchet,
@@ -65260,19 +66295,19 @@ ${messageText}`;
65260
66295
  const identity = this._persisted.identityKeypair;
65261
66296
  const ephemeral = this._persisted.ephemeralKeypair;
65262
66297
  const sharedSecret = performX3DH({
65263
- myIdentityPrivate: hexToBytes(identity.privateKey),
65264
- myEphemeralPrivate: hexToBytes(ephemeral.privateKey),
65265
- theirIdentityPublic: hexToBytes(event.owner_identity_public_key),
65266
- theirEphemeralPublic: hexToBytes(
66298
+ myIdentityPrivate: hexToBytes2(identity.privateKey),
66299
+ myEphemeralPrivate: hexToBytes2(ephemeral.privateKey),
66300
+ theirIdentityPublic: hexToBytes2(event.owner_identity_public_key),
66301
+ theirEphemeralPublic: hexToBytes2(
65267
66302
  event.owner_ephemeral_public_key ?? event.owner_identity_public_key
65268
66303
  ),
65269
66304
  isInitiator: false
65270
66305
  });
65271
66306
  const ratchet = DoubleRatchet.initReceiver(sharedSecret, {
65272
- publicKey: hexToBytes(identity.publicKey),
65273
- privateKey: hexToBytes(identity.privateKey),
66307
+ publicKey: hexToBytes2(identity.publicKey),
66308
+ privateKey: hexToBytes2(identity.privateKey),
65274
66309
  keyType: "ed25519"
65275
- }, hexToBytes(event.owner_identity_public_key));
66310
+ }, hexToBytes2(event.owner_identity_public_key));
65276
66311
  this._sessions.set(event.conversation_id, {
65277
66312
  ownerDeviceId: event.owner_device_id,
65278
66313
  ratchet,
@@ -65319,17 +66354,17 @@ ${messageText}`;
65319
66354
  const identity = this._persisted.identityKeypair;
65320
66355
  const ephemeral = this._persisted.ephemeralKeypair;
65321
66356
  const sharedSecret = performX3DH({
65322
- myIdentityPrivate: hexToBytes(identity.privateKey),
65323
- myEphemeralPrivate: hexToBytes(ephemeral.privateKey),
65324
- theirIdentityPublic: hexToBytes(data.identity_public_key),
65325
- theirEphemeralPublic: hexToBytes(data.ephemeral_public_key),
66357
+ myIdentityPrivate: hexToBytes2(identity.privateKey),
66358
+ myEphemeralPrivate: hexToBytes2(ephemeral.privateKey),
66359
+ theirIdentityPublic: hexToBytes2(data.identity_public_key),
66360
+ theirEphemeralPublic: hexToBytes2(data.ephemeral_public_key),
65326
66361
  isInitiator: false
65327
66362
  });
65328
66363
  const ratchet = DoubleRatchet.initReceiver(sharedSecret, {
65329
- publicKey: hexToBytes(identity.publicKey),
65330
- privateKey: hexToBytes(identity.privateKey),
66364
+ publicKey: hexToBytes2(identity.publicKey),
66365
+ privateKey: hexToBytes2(identity.privateKey),
65331
66366
  keyType: "ed25519"
65332
- }, hexToBytes(data.identity_public_key));
66367
+ }, hexToBytes2(data.identity_public_key));
65333
66368
  const existingSession = this._sessions.get(convId);
65334
66369
  const existingPersisted = this._persisted.sessions[convId];
65335
66370
  const ownerDeviceId = data.sender_device_id ?? existingSession?.ownerDeviceId ?? "";
@@ -65489,7 +66524,28 @@ ${messageText}`;
65489
66524
  const mlsGroup = this._mlsGroups.get(resolvedRoomId);
65490
66525
  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(",")}]`);
65491
66526
  if (!mlsGroup?.isInitialized) {
65492
- console.warn(`[SecureChannel] MLS group not loaded for room ${resolvedRoomId.slice(0, 8)}`);
66527
+ console.warn(`[SecureChannel] MLS group not loaded for room ${resolvedRoomId.slice(0, 8)}, requesting Welcome`);
66528
+ try {
66529
+ const { MLSGroupManager: MLS } = await init_dist().then(() => dist_exports);
66530
+ const mgr = new MLS();
66531
+ const kp = await mgr.generateKeyPackage(new TextEncoder().encode(this._deviceId));
66532
+ const kpBytes = MLS.serializeKeyPackage(kp.publicPackage);
66533
+ const kpHex = Buffer.from(kpBytes).toString("hex");
66534
+ await fetch(`${this.config.apiUrl}/api/v1/mls/key-packages`, {
66535
+ method: "POST",
66536
+ headers: { Authorization: `Bearer ${this._deviceJwt}`, "Content-Type": "application/json" },
66537
+ body: JSON.stringify({ key_package: kpHex, device_id: this._deviceId })
66538
+ });
66539
+ this._pendingMlsKpBundle = kp;
66540
+ await fetch(`${this.config.apiUrl}/api/v1/mls/groups/${groupId}/request-welcome`, {
66541
+ method: "POST",
66542
+ headers: { Authorization: `Bearer ${this._deviceJwt}`, "Content-Type": "application/json" },
66543
+ body: JSON.stringify({ device_id: this._deviceId })
66544
+ });
66545
+ console.log(`[SecureChannel] Welcome requested for room ${resolvedRoomId.slice(0, 8)} group ${groupId?.slice(0, 8)}`);
66546
+ } catch (reqErr) {
66547
+ console.warn(`[SecureChannel] Welcome request failed for room ${resolvedRoomId.slice(0, 8)}:`, reqErr);
66548
+ }
65493
66549
  return;
65494
66550
  }
65495
66551
  try {
@@ -65518,6 +66574,12 @@ ${messageText}`;
65518
66574
  await this._persistState();
65519
66575
  return;
65520
66576
  }
66577
+ if (CATCHUP_MESSAGE_TYPES.has(messageType)) {
66578
+ if (messageType === "history_catchup_request") {
66579
+ await this._handleHistoryCatchupRequest(resolvedRoomId, messageText, data.message_id);
66580
+ }
66581
+ return;
66582
+ }
65521
66583
  if (!ROOM_AGENT_TYPES.has(messageType)) {
65522
66584
  return;
65523
66585
  }
@@ -65564,6 +66626,55 @@ ${messageText}`;
65564
66626
  console.error(`[SecureChannel] MLS room decrypt failed for ${resolvedRoomId.slice(0, 8)}:`, err);
65565
66627
  }
65566
66628
  }
66629
+ /**
66630
+ * Handle a history catch-up request from a device that just rejoined a room.
66631
+ * Only the elected agent (smallest device_id among agents) responds.
66632
+ */
66633
+ async _handleHistoryCatchupRequest(roomId, requestText, messageId) {
66634
+ let request;
66635
+ try {
66636
+ request = JSON.parse(requestText);
66637
+ } catch {
66638
+ return;
66639
+ }
66640
+ const roomMembers = this._persisted?.rooms?.[roomId]?.members ?? [];
66641
+ const agentDeviceIds = roomMembers.filter((m2) => m2.entityType !== "owner" && m2.entityType !== "human").map((m2) => m2.deviceId).sort();
66642
+ const isElected = agentDeviceIds.length > 0 && agentDeviceIds[0] === this._deviceId;
66643
+ if (!isElected && !request.retry) {
66644
+ console.log(
66645
+ `[SecureChannel] History catchup: not elected (elected=${agentDeviceIds[0]?.slice(0, 8)}), ignoring`
66646
+ );
66647
+ return;
66648
+ }
66649
+ const history = this.getRoomHistory(roomId, 100);
66650
+ let filtered = history;
66651
+ if (request.since_ts) {
66652
+ const sinceTime = new Date(request.since_ts).getTime();
66653
+ filtered = history.filter((e) => new Date(e.ts).getTime() > sinceTime);
66654
+ }
66655
+ console.log(
66656
+ `[SecureChannel] History catchup for room ${roomId.slice(0, 8)}: ${filtered.length} messages since ${request.since_ts || "beginning"} (total history: ${history.length})`
66657
+ );
66658
+ const responsePayload = JSON.stringify({
66659
+ type: "history_catchup_response",
66660
+ target_device_id: request.requesting_device_id,
66661
+ messages: filtered.map((e) => ({
66662
+ sender: e.sender,
66663
+ sender_name: e.sender === "agent" ? this.config.agentName ?? "Agent" : "Owner",
66664
+ text: e.text,
66665
+ ts: e.ts
66666
+ })),
66667
+ no_history: filtered.length === 0
66668
+ });
66669
+ try {
66670
+ await this.sendToRoom(roomId, responsePayload, { messageType: "history_catchup_response" });
66671
+ console.log(
66672
+ `[SecureChannel] Sent history catchup response: ${filtered.length} messages to ${request.requesting_device_id?.slice(0, 8)}`
66673
+ );
66674
+ } catch (sendErr) {
66675
+ console.warn(`[SecureChannel] Failed to send history catchup response:`, sendErr);
66676
+ }
66677
+ }
65567
66678
  async _handleMlsCommit(data) {
65568
66679
  const groupId = data.group_id;
65569
66680
  for (const [roomId, room] of Object.entries(this._persisted?.rooms ?? {})) {
@@ -65590,7 +66701,7 @@ ${messageText}`;
65590
66701
  try {
65591
66702
  const welcomeBytes = new Uint8Array(Buffer.from(data.payload, "hex"));
65592
66703
  const mgr = new MLSGroupManager();
65593
- const kp = this._mlsKeyPackage ?? await (async () => {
66704
+ const kp = this._pendingMlsKpBundle ?? this._mlsKeyPackage ?? await (async () => {
65594
66705
  const identity = new TextEncoder().encode(this._deviceId);
65595
66706
  return mgr.generateKeyPackage(identity);
65596
66707
  })();
@@ -65607,11 +66718,15 @@ ${messageText}`;
65607
66718
  console.log(`[SecureChannel] Joined 1:1 MLS group for conv ${conversationId.slice(0, 8)} via Welcome (epoch=${mgr.epoch})`);
65608
66719
  return;
65609
66720
  }
66721
+ const welcomeRoomId = data.room_id;
65610
66722
  for (const [roomId, room] of Object.entries(this._persisted?.rooms ?? {})) {
65611
- if (room.mlsGroupId === groupId) {
66723
+ if (room.mlsGroupId === groupId || roomId === welcomeRoomId) {
66724
+ room.mlsGroupId = groupId;
65612
66725
  this._mlsGroups.set(roomId, mgr);
65613
66726
  await saveMlsState(this.config.dataDir, groupId, JSON.stringify(mgr.exportState()));
66727
+ await this._persistState();
65614
66728
  console.log(`[SecureChannel] Joined MLS group for room ${roomId.slice(0, 8)} via Welcome (epoch=${mgr.epoch})`);
66729
+ this._pendingMlsKpBundle = void 0;
65615
66730
  return;
65616
66731
  }
65617
66732
  }
@@ -65774,6 +66889,71 @@ ${messageText}`;
65774
66889
  console.warn("[SecureChannel] Delivery ack failed:", ackErr);
65775
66890
  }
65776
66891
  }
66892
+ for (const [roomId, mlsGroup] of this._mlsGroups) {
66893
+ if (!mlsGroup?.isInitialized) continue;
66894
+ if (roomId.includes(":")) continue;
66895
+ const roomState = this._persisted?.rooms?.[roomId];
66896
+ if (!roomState?.mlsGroupId) continue;
66897
+ try {
66898
+ const pendingRes = await fetch(
66899
+ `${this.config.apiUrl}/api/v1/mls/groups/${roomState.mlsGroupId}/pending-welcomes`,
66900
+ { headers: { Authorization: `Bearer ${this._deviceJwt}` } }
66901
+ );
66902
+ if (!pendingRes.ok) continue;
66903
+ const pending = await pendingRes.json();
66904
+ if (pending.length === 0) continue;
66905
+ console.log(`[SecureChannel] ${pending.length} pending Welcome requests for room ${roomId.slice(0, 8)}`);
66906
+ for (const req of pending) {
66907
+ try {
66908
+ const kpRes = await fetch(
66909
+ `${this.config.apiUrl}/api/v1/mls/key-packages/batch?device_ids=${req.requesting_device_id}`,
66910
+ { headers: { Authorization: `Bearer ${this._deviceJwt}` } }
66911
+ );
66912
+ if (!kpRes.ok) continue;
66913
+ const kpData = await kpRes.json();
66914
+ const kpHex = kpData[req.requesting_device_id];
66915
+ if (!kpHex) continue;
66916
+ const kpBytes = new Uint8Array(Buffer.from(kpHex, "hex"));
66917
+ const memberKp = MLSGroupManager.deserializeKeyPackage(kpBytes);
66918
+ const { commit, welcome } = await mlsGroup.addMembers([memberKp]);
66919
+ if (this._ws) {
66920
+ this._ws.send(JSON.stringify({
66921
+ event: "mls_commit",
66922
+ data: {
66923
+ group_id: roomState.mlsGroupId,
66924
+ epoch: Number(mlsGroup.epoch),
66925
+ payload: Buffer.from(commit).toString("hex")
66926
+ }
66927
+ }));
66928
+ }
66929
+ if (welcome && this._ws) {
66930
+ this._ws.send(JSON.stringify({
66931
+ event: "mls_welcome",
66932
+ data: {
66933
+ target_device_id: req.requesting_device_id,
66934
+ group_id: roomState.mlsGroupId,
66935
+ room_id: roomId,
66936
+ payload: Buffer.from(welcome).toString("hex")
66937
+ }
66938
+ }));
66939
+ }
66940
+ await fetch(
66941
+ `${this.config.apiUrl}/api/v1/mls/groups/${roomState.mlsGroupId}/fulfill-welcome`,
66942
+ {
66943
+ method: "POST",
66944
+ headers: { Authorization: `Bearer ${this._deviceJwt}`, "Content-Type": "application/json" },
66945
+ body: JSON.stringify({ request_id: req.id })
66946
+ }
66947
+ );
66948
+ await saveMlsState(this.config.dataDir, roomState.mlsGroupId, JSON.stringify(mlsGroup.exportState()));
66949
+ console.log(`[SecureChannel] Fulfilled Welcome for ${req.requesting_device_id.slice(0, 8)} in room ${roomId.slice(0, 8)}`);
66950
+ } catch (fulfillErr) {
66951
+ console.warn(`[SecureChannel] Welcome fulfill failed for ${req.requesting_device_id.slice(0, 8)}:`, fulfillErr);
66952
+ }
66953
+ }
66954
+ } catch {
66955
+ }
66956
+ }
65777
66957
  } catch (err) {
65778
66958
  console.warn("[SecureChannel] Delivery pull error:", err);
65779
66959
  } finally {