@tinycloud/cli 1.5.0-beta.3 → 1.5.0-beta.30

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
@@ -932,6 +932,12 @@ function abytes(b, ...lengths) {
932
932
  if (lengths.length > 0 && !lengths.includes(b.length))
933
933
  throw new Error("Uint8Array expected of length " + lengths + ", got length=" + b.length);
934
934
  }
935
+ function ahash(h) {
936
+ if (typeof h !== "function" || typeof h.create !== "function")
937
+ throw new Error("Hash should be wrapped by utils.createHasher");
938
+ anumber(h.outputLen);
939
+ anumber(h.blockLen);
940
+ }
935
941
  function aexists(instance, checkFinished = true) {
936
942
  if (instance.destroyed)
937
943
  throw new Error("Hash instance has been destroyed");
@@ -1100,7 +1106,7 @@ function Chi(a, b, c) {
1100
1106
  function Maj(a, b, c) {
1101
1107
  return a & b ^ a & c ^ b & c;
1102
1108
  }
1103
- var HashMD, SHA256_IV, SHA512_IV;
1109
+ var HashMD, SHA256_IV, SHA384_IV, SHA512_IV;
1104
1110
  var init_md = __esm({
1105
1111
  "../../node_modules/@noble/hashes/esm/_md.js"() {
1106
1112
  "use strict";
@@ -1205,6 +1211,24 @@ var init_md = __esm({
1205
1211
  528734635,
1206
1212
  1541459225
1207
1213
  ]);
1214
+ SHA384_IV = /* @__PURE__ */ Uint32Array.from([
1215
+ 3418070365,
1216
+ 3238371032,
1217
+ 1654270250,
1218
+ 914150663,
1219
+ 2438529370,
1220
+ 812702999,
1221
+ 355462360,
1222
+ 4144912697,
1223
+ 1731405415,
1224
+ 4290775857,
1225
+ 2394180231,
1226
+ 1750603025,
1227
+ 3675008525,
1228
+ 1694076839,
1229
+ 1203062813,
1230
+ 3204075428
1231
+ ]);
1208
1232
  SHA512_IV = /* @__PURE__ */ Uint32Array.from([
1209
1233
  1779033703,
1210
1234
  4089235720,
@@ -1227,7 +1251,7 @@ var init_md = __esm({
1227
1251
  });
1228
1252
 
1229
1253
  // ../../node_modules/@noble/hashes/esm/sha2.js
1230
- var SHA256_K, SHA256_W, SHA256, K512, SHA512_Kh, SHA512_Kl, SHA512_W_H, SHA512_W_L, SHA512, sha256, sha512;
1254
+ var SHA256_K, SHA256_W, SHA256, K512, SHA512_Kh, SHA512_Kl, SHA512_W_H, SHA512_W_L, SHA512, SHA384, sha256, sha512, sha384;
1231
1255
  var init_sha2 = __esm({
1232
1256
  "../../node_modules/@noble/hashes/esm/sha2.js"() {
1233
1257
  "use strict";
@@ -1568,8 +1592,30 @@ var init_sha2 = __esm({
1568
1592
  this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1569
1593
  }
1570
1594
  };
1595
+ SHA384 = class extends SHA512 {
1596
+ constructor() {
1597
+ super(48);
1598
+ this.Ah = SHA384_IV[0] | 0;
1599
+ this.Al = SHA384_IV[1] | 0;
1600
+ this.Bh = SHA384_IV[2] | 0;
1601
+ this.Bl = SHA384_IV[3] | 0;
1602
+ this.Ch = SHA384_IV[4] | 0;
1603
+ this.Cl = SHA384_IV[5] | 0;
1604
+ this.Dh = SHA384_IV[6] | 0;
1605
+ this.Dl = SHA384_IV[7] | 0;
1606
+ this.Eh = SHA384_IV[8] | 0;
1607
+ this.El = SHA384_IV[9] | 0;
1608
+ this.Fh = SHA384_IV[10] | 0;
1609
+ this.Fl = SHA384_IV[11] | 0;
1610
+ this.Gh = SHA384_IV[12] | 0;
1611
+ this.Gl = SHA384_IV[13] | 0;
1612
+ this.Hh = SHA384_IV[14] | 0;
1613
+ this.Hl = SHA384_IV[15] | 0;
1614
+ }
1615
+ };
1571
1616
  sha256 = /* @__PURE__ */ createHasher(() => new SHA256());
1572
1617
  sha512 = /* @__PURE__ */ createHasher(() => new SHA512());
1618
+ sha384 = /* @__PURE__ */ createHasher(() => new SHA384());
1573
1619
  }
1574
1620
  });
1575
1621
 
@@ -1583,6 +1629,81 @@ var init_sha256 = __esm({
1583
1629
  }
1584
1630
  });
1585
1631
 
1632
+ // ../../node_modules/@noble/hashes/esm/hmac.js
1633
+ var HMAC, hmac;
1634
+ var init_hmac = __esm({
1635
+ "../../node_modules/@noble/hashes/esm/hmac.js"() {
1636
+ "use strict";
1637
+ init_utils();
1638
+ HMAC = class extends Hash {
1639
+ constructor(hash, _key) {
1640
+ super();
1641
+ this.finished = false;
1642
+ this.destroyed = false;
1643
+ ahash(hash);
1644
+ const key = toBytes(_key);
1645
+ this.iHash = hash.create();
1646
+ if (typeof this.iHash.update !== "function")
1647
+ throw new Error("Expected instance of class which extends utils.Hash");
1648
+ this.blockLen = this.iHash.blockLen;
1649
+ this.outputLen = this.iHash.outputLen;
1650
+ const blockLen = this.blockLen;
1651
+ const pad = new Uint8Array(blockLen);
1652
+ pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
1653
+ for (let i = 0; i < pad.length; i++)
1654
+ pad[i] ^= 54;
1655
+ this.iHash.update(pad);
1656
+ this.oHash = hash.create();
1657
+ for (let i = 0; i < pad.length; i++)
1658
+ pad[i] ^= 54 ^ 92;
1659
+ this.oHash.update(pad);
1660
+ clean(pad);
1661
+ }
1662
+ update(buf) {
1663
+ aexists(this);
1664
+ this.iHash.update(buf);
1665
+ return this;
1666
+ }
1667
+ digestInto(out) {
1668
+ aexists(this);
1669
+ abytes(out, this.outputLen);
1670
+ this.finished = true;
1671
+ this.iHash.digestInto(out);
1672
+ this.oHash.update(out);
1673
+ this.oHash.digestInto(out);
1674
+ this.destroy();
1675
+ }
1676
+ digest() {
1677
+ const out = new Uint8Array(this.oHash.outputLen);
1678
+ this.digestInto(out);
1679
+ return out;
1680
+ }
1681
+ _cloneInto(to) {
1682
+ to || (to = Object.create(Object.getPrototypeOf(this), {}));
1683
+ const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
1684
+ to = to;
1685
+ to.finished = finished;
1686
+ to.destroyed = destroyed;
1687
+ to.blockLen = blockLen;
1688
+ to.outputLen = outputLen;
1689
+ to.oHash = oHash._cloneInto(to.oHash);
1690
+ to.iHash = iHash._cloneInto(to.iHash);
1691
+ return to;
1692
+ }
1693
+ clone() {
1694
+ return this._cloneInto();
1695
+ }
1696
+ destroy() {
1697
+ this.destroyed = true;
1698
+ this.oHash.destroy();
1699
+ this.iHash.destroy();
1700
+ }
1701
+ };
1702
+ hmac = (hash, key, message) => new HMAC(hash, key).update(message).digest();
1703
+ hmac.create = (hash, key) => new HMAC(hash, key);
1704
+ }
1705
+ });
1706
+
1586
1707
  // src/lib/raw-encryption.ts
1587
1708
  var init_raw_encryption = __esm({
1588
1709
  "src/lib/raw-encryption.ts"() {
@@ -1782,8 +1903,8 @@ function createReplicationEventSink(profileRoot, options) {
1782
1903
  `);
1783
1904
  } else if (event.type === "replication.sync") {
1784
1905
  const pending = event.pendingCleared === void 0 ? "" : ` pendingCleared:${event.pendingCleared}`;
1785
- const origin = event.origin === void 0 ? "" : ` origin:${event.origin}`;
1786
- process.stderr.write(`[replication] sync ${event.replica} ${event.outcome}${event.code ? ` ${event.code}` : ""}${pending}${origin}
1906
+ const origin2 = event.origin === void 0 ? "" : ` origin:${event.origin}`;
1907
+ process.stderr.write(`[replication] sync ${event.replica} ${event.outcome}${event.code ? ` ${event.code}` : ""}${pending}${origin2}
1787
1908
  `);
1788
1909
  } else if (event.type === "replication.grant") {
1789
1910
  process.stderr.write(`[replication] grant ${event.replicaId} ${event.action}${event.code ? ` ${event.code}` : ""}${event.effectiveExpiresAt ? ` effectiveExpiresAt:${event.effectiveExpiresAt}` : ""}
@@ -2188,6 +2309,10 @@ function _abytes2(value, length5, title = "") {
2188
2309
  }
2189
2310
  return value;
2190
2311
  }
2312
+ function numberToHexUnpadded(num) {
2313
+ const hex3 = num.toString(16);
2314
+ return hex3.length & 1 ? "0" + hex3 : hex3;
2315
+ }
2191
2316
  function hexToNumber(hex3) {
2192
2317
  if (typeof hex3 !== "string")
2193
2318
  throw new Error("hex string expected, got " + typeof hex3);
@@ -2248,6 +2373,56 @@ function bitLen(n) {
2248
2373
  ;
2249
2374
  return len;
2250
2375
  }
2376
+ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
2377
+ if (typeof hashLen !== "number" || hashLen < 2)
2378
+ throw new Error("hashLen must be a number");
2379
+ if (typeof qByteLen !== "number" || qByteLen < 2)
2380
+ throw new Error("qByteLen must be a number");
2381
+ if (typeof hmacFn !== "function")
2382
+ throw new Error("hmacFn must be a function");
2383
+ const u8n = (len) => new Uint8Array(len);
2384
+ const u8of = (byte) => Uint8Array.of(byte);
2385
+ let v = u8n(hashLen);
2386
+ let k = u8n(hashLen);
2387
+ let i = 0;
2388
+ const reset = () => {
2389
+ v.fill(1);
2390
+ k.fill(0);
2391
+ i = 0;
2392
+ };
2393
+ const h = (...b) => hmacFn(k, v, ...b);
2394
+ const reseed = (seed = u8n(0)) => {
2395
+ k = h(u8of(0), seed);
2396
+ v = h();
2397
+ if (seed.length === 0)
2398
+ return;
2399
+ k = h(u8of(1), seed);
2400
+ v = h();
2401
+ };
2402
+ const gen = () => {
2403
+ if (i++ >= 1e3)
2404
+ throw new Error("drbg: tried 1000 values");
2405
+ let len = 0;
2406
+ const out = [];
2407
+ while (len < qByteLen) {
2408
+ v = h();
2409
+ const sl = v.slice();
2410
+ out.push(sl);
2411
+ len += v.length;
2412
+ }
2413
+ return concatBytes(...out);
2414
+ };
2415
+ const genUntil = (seed, pred) => {
2416
+ reset();
2417
+ reseed(seed);
2418
+ let res = void 0;
2419
+ while (!(res = pred(gen())))
2420
+ reseed();
2421
+ reset();
2422
+ return res;
2423
+ };
2424
+ return genUntil;
2425
+ }
2251
2426
  function _validateObject(object3, fields, optFields = {}) {
2252
2427
  if (!object3 || typeof object3 !== "object")
2253
2428
  throw new Error("expected valid options object");
@@ -2584,6 +2759,26 @@ function Field(ORDER, bitLenOrOpts, isLE2 = false, opts = {}) {
2584
2759
  });
2585
2760
  return Object.freeze(f);
2586
2761
  }
2762
+ function getFieldBytesLength(fieldOrder) {
2763
+ if (typeof fieldOrder !== "bigint")
2764
+ throw new Error("field order must be bigint");
2765
+ const bitLength = fieldOrder.toString(2).length;
2766
+ return Math.ceil(bitLength / 8);
2767
+ }
2768
+ function getMinHashLength(fieldOrder) {
2769
+ const length5 = getFieldBytesLength(fieldOrder);
2770
+ return length5 + Math.ceil(length5 / 2);
2771
+ }
2772
+ function mapHashToField(key, fieldOrder, isLE2 = false) {
2773
+ const len = key.length;
2774
+ const fieldLen = getFieldBytesLength(fieldOrder);
2775
+ const minLen = getMinHashLength(fieldOrder);
2776
+ if (len < 16 || len < minLen || len > 1024)
2777
+ throw new Error("expected " + minLen + "-1024 bytes of input, got " + len);
2778
+ const num = isLE2 ? bytesToNumberLE(key) : bytesToNumberBE(key);
2779
+ const reduced = mod(num, fieldOrder - _1n2) + _1n2;
2780
+ return isLE2 ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);
2781
+ }
2587
2782
  var _0n2, _1n2, _2n, _3n, _4n, _5n, _7n, _8n, _9n, _16n, isNegativeLE, FIELD_FIELDS;
2588
2783
  var init_modular = __esm({
2589
2784
  "../../node_modules/@noble/curves/esm/abstract/modular.js"() {
@@ -2683,6 +2878,21 @@ function assert0(n) {
2683
2878
  if (n !== _0n3)
2684
2879
  throw new Error("invalid wNAF");
2685
2880
  }
2881
+ function mulEndoUnsafe(Point, point, k1, k2) {
2882
+ let acc = point;
2883
+ let p1 = Point.ZERO;
2884
+ let p2 = Point.ZERO;
2885
+ while (k1 > _0n3 || k2 > _0n3) {
2886
+ if (k1 & _1n3)
2887
+ p1 = p1.add(acc);
2888
+ if (k2 & _1n3)
2889
+ p2 = p2.add(acc);
2890
+ acc = acc.double();
2891
+ k1 >>= _1n3;
2892
+ k2 >>= _1n3;
2893
+ }
2894
+ return { p1, p2 };
2895
+ }
2686
2896
  function pippenger(c, fieldN, points, scalars) {
2687
2897
  validateMSMPoints(points, c);
2688
2898
  validateMSMScalars(scalars, fieldN);
@@ -6592,7 +6802,7 @@ var init_profile_replicas = __esm({
6592
6802
  });
6593
6803
 
6594
6804
  // src/lib/logout-pending.ts
6595
- import { lstat as lstat4, open as open5, readFile as readFile5 } from "fs/promises";
6805
+ import { lstat as lstat4, open as open5, readFile as readFile5, rm as rm4 } from "fs/promises";
6596
6806
  import { join as join9 } from "path";
6597
6807
  import { createProfileReplicaPurge, logoutPrincipalDigest, REPLICA_LOGOUT_PENDING_FILE as REPLICA_LOGOUT_PENDING_FILE2, RESTORED_GATE_MESSAGE } from "@tinycloud/node-sdk";
6598
6808
  import { namedProfilePath, profilePath as profilePath4 } from "@tinycloud/operations/state";
@@ -6673,32 +6883,35 @@ async function assertPendingRemoteLogoutSession(name, expected) {
6673
6883
  }, { requireProfile: true });
6674
6884
  }
6675
6885
  async function clearProfileCredentials(name, syncDirectory = false, legacyCleanup = false) {
6676
- const profile = await ProfileManager.getProfile(name);
6677
- const { namedKeys: _namedKeys, ...signedOutProfile } = profile;
6678
- await ProfileManager.setProfileDurable(name, { ...signedOutProfile, authSignedOut: true, ...legacyCleanup ? { legacyReplicaCleanup: true } : {} });
6679
- let failed = false;
6680
- let error;
6681
- try {
6682
- await ProfileManager.removeKey(name);
6683
- } catch (cause) {
6684
- failed = true;
6685
- error = cause;
6686
- }
6687
- try {
6688
- await ProfileManager.clearSession(name);
6689
- } catch (cause) {
6690
- if (!failed) error = cause;
6691
- failed = true;
6692
- }
6693
- if (failed) throw error;
6694
- if (syncDirectory) {
6695
- const directory = await open5(profilePath4(name), "r");
6886
+ await ProfileManager.withLock(name, async () => {
6887
+ const profile = await ProfileManager.getProfile(name);
6888
+ const { namedKeys: _namedKeys, ...signedOutProfile } = profile;
6889
+ await rm4(join9(profilePath4(name), "approval-pending.json"), { force: true });
6890
+ await ProfileManager.setProfileDurable(name, { ...signedOutProfile, authSignedOut: true, ...legacyCleanup ? { legacyReplicaCleanup: true } : {} });
6891
+ let failed = false;
6892
+ let error;
6696
6893
  try {
6697
- await directory.sync();
6698
- } finally {
6699
- await directory.close();
6894
+ await ProfileManager.removeKey(name);
6895
+ } catch (cause) {
6896
+ failed = true;
6897
+ error = cause;
6700
6898
  }
6701
- }
6899
+ try {
6900
+ await ProfileManager.clearSession(name);
6901
+ } catch (cause) {
6902
+ if (!failed) error = cause;
6903
+ failed = true;
6904
+ }
6905
+ if (failed) throw error;
6906
+ if (syncDirectory) {
6907
+ const directory = await open5(profilePath4(name), "r");
6908
+ try {
6909
+ await directory.sync();
6910
+ } finally {
6911
+ await directory.close();
6912
+ }
6913
+ }
6914
+ }, { requireProfile: true });
6702
6915
  }
6703
6916
  async function finishSignedOutCredentialRemoval(name) {
6704
6917
  const profile = await ProfileManager.getProfile(name).catch((error) => {
@@ -7363,7 +7576,7 @@ var init_host = __esm({
7363
7576
  });
7364
7577
 
7365
7578
  // src/config/profiles.ts
7366
- import { chmod as chmod3, lstat as lstat5, readdir as readdir5, rm as rm4 } from "fs/promises";
7579
+ import { chmod as chmod3, lstat as lstat5, readdir as readdir5, rm as rm5 } from "fs/promises";
7367
7580
  import { CLI_NAME as CLI_NAME11 } from "@tinycloud/operations/cli-name";
7368
7581
  import { join as join10 } from "path";
7369
7582
  import {
@@ -7385,6 +7598,7 @@ var init_profiles = __esm({
7385
7598
  "use strict";
7386
7599
  init_constants();
7387
7600
  init_storage2();
7601
+ init_types();
7388
7602
  init_errors();
7389
7603
  ProfileManager = class _ProfileManager {
7390
7604
  // ── Initialization ──────────────────────────────────────────────────
@@ -7481,7 +7695,7 @@ var init_profiles = __esm({
7481
7695
  }
7482
7696
  /** Removes profile.json under the profile lock (rollback of a profile a failed login created). */
7483
7697
  static async removeProfileConfig(name) {
7484
- await _ProfileManager.withLock(name, () => rm4(join10(profilePath5(name), "profile.json"), { force: true }));
7698
+ await _ProfileManager.withLock(name, () => rm5(join10(profilePath5(name), "profile.json"), { force: true }));
7485
7699
  }
7486
7700
  /**
7487
7701
  * Returns true if a profile directory exists.
@@ -7532,16 +7746,16 @@ var init_profiles = __esm({
7532
7746
  });
7533
7747
  if (kind === "missing") return;
7534
7748
  if (kind === "link") {
7535
- await rm4(profileDir, { force: true });
7749
+ await rm5(profileDir, { force: true });
7536
7750
  return;
7537
7751
  }
7538
7752
  await _ProfileManager.withLock(name, async () => {
7539
7753
  const directory = profilePath5(name);
7540
- for (const file of ["session.json", "key.json"]) await rm4(join10(directory, file), { force: true });
7754
+ for (const file of ["session.json", "key.json"]) await rm5(join10(directory, file), { force: true });
7541
7755
  for (const entry of await readdir5(directory)) {
7542
- if (entry !== ".lock" && entry !== "profile.json") await rm4(join10(directory, entry), { recursive: true, force: true });
7756
+ if (entry !== ".lock" && entry !== "profile.json") await rm5(join10(directory, entry), { recursive: true, force: true });
7543
7757
  }
7544
- await rm4(join10(directory, "profile.json"), { force: true });
7758
+ await rm5(join10(directory, "profile.json"), { force: true });
7545
7759
  await recordProfileDeletion(name);
7546
7760
  });
7547
7761
  }
@@ -7571,7 +7785,7 @@ var init_profiles = __esm({
7571
7785
  }
7572
7786
  /** Removes key.json under the profile lock (rollback of a key a failed login created). */
7573
7787
  static async removeKey(name) {
7574
- await _ProfileManager.withLock(name, () => rm4(join10(profilePath5(name), "key.json"), { force: true }));
7788
+ await _ProfileManager.withLock(name, () => rm5(join10(profilePath5(name), "key.json"), { force: true }));
7575
7789
  }
7576
7790
  // ── Session management ──────────────────────────────────────────────
7577
7791
  /**
@@ -7666,6 +7880,7 @@ var init_profiles = __esm({
7666
7880
  quiet: options.quiet ?? false,
7667
7881
  replication,
7668
7882
  replicationDebug: options.replicationDebug === true || process.env.TC_REPLICATION_DEBUG === "1",
7883
+ ...profileConfig === void 0 ? {} : { posture: resolveProfilePosture(profileConfig) },
7669
7884
  ...localDiscovery === void 0 ? {} : { localDiscovery }
7670
7885
  };
7671
7886
  }
@@ -12787,6 +13002,1097 @@ var init_raw = __esm({
12787
13002
  }
12788
13003
  });
12789
13004
 
13005
+ // ../../node_modules/@noble/curves/esm/abstract/weierstrass.js
13006
+ function _splitEndoScalar(k, basis, n) {
13007
+ const [[a1, b1], [a2, b2]] = basis;
13008
+ const c1 = divNearest(b2 * k, n);
13009
+ const c2 = divNearest(-b1 * k, n);
13010
+ let k1 = k - c1 * a1 - c2 * a2;
13011
+ let k2 = -c1 * b1 - c2 * b2;
13012
+ const k1neg = k1 < _0n6;
13013
+ const k2neg = k2 < _0n6;
13014
+ if (k1neg)
13015
+ k1 = -k1;
13016
+ if (k2neg)
13017
+ k2 = -k2;
13018
+ const MAX_NUM = bitMask(Math.ceil(bitLen(n) / 2)) + _1n6;
13019
+ if (k1 < _0n6 || k1 >= MAX_NUM || k2 < _0n6 || k2 >= MAX_NUM) {
13020
+ throw new Error("splitScalar (endomorphism): failed, k=" + k);
13021
+ }
13022
+ return { k1neg, k1, k2neg, k2 };
13023
+ }
13024
+ function validateSigFormat(format5) {
13025
+ if (!["compact", "recovered", "der"].includes(format5))
13026
+ throw new Error('Signature format must be "compact", "recovered", or "der"');
13027
+ return format5;
13028
+ }
13029
+ function validateSigOpts(opts, def) {
13030
+ const optsn = {};
13031
+ for (let optName of Object.keys(def)) {
13032
+ optsn[optName] = opts[optName] === void 0 ? def[optName] : opts[optName];
13033
+ }
13034
+ _abool2(optsn.lowS, "lowS");
13035
+ _abool2(optsn.prehash, "prehash");
13036
+ if (optsn.format !== void 0)
13037
+ validateSigFormat(optsn.format);
13038
+ return optsn;
13039
+ }
13040
+ function _normFnElement(Fn2, key) {
13041
+ const { BYTES: expected } = Fn2;
13042
+ let num;
13043
+ if (typeof key === "bigint") {
13044
+ num = key;
13045
+ } else {
13046
+ let bytes = ensureBytes("private key", key);
13047
+ try {
13048
+ num = Fn2.fromBytes(bytes);
13049
+ } catch (error) {
13050
+ throw new Error(`invalid private key: expected ui8a of size ${expected}, got ${typeof key}`);
13051
+ }
13052
+ }
13053
+ if (!Fn2.isValidNot0(num))
13054
+ throw new Error("invalid private key: out of range [1..N-1]");
13055
+ return num;
13056
+ }
13057
+ function weierstrassN(params, extraOpts = {}) {
13058
+ const validated = _createCurveFields("weierstrass", params, extraOpts);
13059
+ const { Fp: Fp2, Fn: Fn2 } = validated;
13060
+ let CURVE = validated.CURVE;
13061
+ const { h: cofactor, n: CURVE_ORDER } = CURVE;
13062
+ _validateObject(extraOpts, {}, {
13063
+ allowInfinityPoint: "boolean",
13064
+ clearCofactor: "function",
13065
+ isTorsionFree: "function",
13066
+ fromBytes: "function",
13067
+ toBytes: "function",
13068
+ endo: "object",
13069
+ wrapPrivateKey: "boolean"
13070
+ });
13071
+ const { endo } = extraOpts;
13072
+ if (endo) {
13073
+ if (!Fp2.is0(CURVE.a) || typeof endo.beta !== "bigint" || !Array.isArray(endo.basises)) {
13074
+ throw new Error('invalid endo: expected "beta": bigint and "basises": array');
13075
+ }
13076
+ }
13077
+ const lengths = getWLengths(Fp2, Fn2);
13078
+ function assertCompressionIsSupported() {
13079
+ if (!Fp2.isOdd)
13080
+ throw new Error("compression is not supported: Field does not have .isOdd()");
13081
+ }
13082
+ function pointToBytes(_c, point, isCompressed) {
13083
+ const { x, y } = point.toAffine();
13084
+ const bx = Fp2.toBytes(x);
13085
+ _abool2(isCompressed, "isCompressed");
13086
+ if (isCompressed) {
13087
+ assertCompressionIsSupported();
13088
+ const hasEvenY = !Fp2.isOdd(y);
13089
+ return concatBytes(pprefix(hasEvenY), bx);
13090
+ } else {
13091
+ return concatBytes(Uint8Array.of(4), bx, Fp2.toBytes(y));
13092
+ }
13093
+ }
13094
+ function pointFromBytes(bytes) {
13095
+ _abytes2(bytes, void 0, "Point");
13096
+ const { publicKey: comp, publicKeyUncompressed: uncomp } = lengths;
13097
+ const length5 = bytes.length;
13098
+ const head = bytes[0];
13099
+ const tail = bytes.subarray(1);
13100
+ if (length5 === comp && (head === 2 || head === 3)) {
13101
+ const x = Fp2.fromBytes(tail);
13102
+ if (!Fp2.isValid(x))
13103
+ throw new Error("bad point: is not on curve, wrong x");
13104
+ const y2 = weierstrassEquation(x);
13105
+ let y;
13106
+ try {
13107
+ y = Fp2.sqrt(y2);
13108
+ } catch (sqrtError) {
13109
+ const err = sqrtError instanceof Error ? ": " + sqrtError.message : "";
13110
+ throw new Error("bad point: is not on curve, sqrt error" + err);
13111
+ }
13112
+ assertCompressionIsSupported();
13113
+ const isYOdd = Fp2.isOdd(y);
13114
+ const isHeadOdd = (head & 1) === 1;
13115
+ if (isHeadOdd !== isYOdd)
13116
+ y = Fp2.neg(y);
13117
+ return { x, y };
13118
+ } else if (length5 === uncomp && head === 4) {
13119
+ const L = Fp2.BYTES;
13120
+ const x = Fp2.fromBytes(tail.subarray(0, L));
13121
+ const y = Fp2.fromBytes(tail.subarray(L, L * 2));
13122
+ if (!isValidXY(x, y))
13123
+ throw new Error("bad point: is not on curve");
13124
+ return { x, y };
13125
+ } else {
13126
+ throw new Error(`bad point: got length ${length5}, expected compressed=${comp} or uncompressed=${uncomp}`);
13127
+ }
13128
+ }
13129
+ const encodePoint = extraOpts.toBytes || pointToBytes;
13130
+ const decodePoint2 = extraOpts.fromBytes || pointFromBytes;
13131
+ function weierstrassEquation(x) {
13132
+ const x2 = Fp2.sqr(x);
13133
+ const x3 = Fp2.mul(x2, x);
13134
+ return Fp2.add(Fp2.add(x3, Fp2.mul(x, CURVE.a)), CURVE.b);
13135
+ }
13136
+ function isValidXY(x, y) {
13137
+ const left = Fp2.sqr(y);
13138
+ const right = weierstrassEquation(x);
13139
+ return Fp2.eql(left, right);
13140
+ }
13141
+ if (!isValidXY(CURVE.Gx, CURVE.Gy))
13142
+ throw new Error("bad curve params: generator point");
13143
+ const _4a3 = Fp2.mul(Fp2.pow(CURVE.a, _3n3), _4n2);
13144
+ const _27b2 = Fp2.mul(Fp2.sqr(CURVE.b), BigInt(27));
13145
+ if (Fp2.is0(Fp2.add(_4a3, _27b2)))
13146
+ throw new Error("bad curve params: a or b");
13147
+ function acoord(title, n, banZero = false) {
13148
+ if (!Fp2.isValid(n) || banZero && Fp2.is0(n))
13149
+ throw new Error(`bad point coordinate ${title}`);
13150
+ return n;
13151
+ }
13152
+ function aprjpoint(other) {
13153
+ if (!(other instanceof Point))
13154
+ throw new Error("ProjectivePoint expected");
13155
+ }
13156
+ function splitEndoScalarN(k) {
13157
+ if (!endo || !endo.basises)
13158
+ throw new Error("no endo");
13159
+ return _splitEndoScalar(k, endo.basises, Fn2.ORDER);
13160
+ }
13161
+ const toAffineMemo = memoized((p, iz) => {
13162
+ const { X, Y, Z } = p;
13163
+ if (Fp2.eql(Z, Fp2.ONE))
13164
+ return { x: X, y: Y };
13165
+ const is0 = p.is0();
13166
+ if (iz == null)
13167
+ iz = is0 ? Fp2.ONE : Fp2.inv(Z);
13168
+ const x = Fp2.mul(X, iz);
13169
+ const y = Fp2.mul(Y, iz);
13170
+ const zz = Fp2.mul(Z, iz);
13171
+ if (is0)
13172
+ return { x: Fp2.ZERO, y: Fp2.ZERO };
13173
+ if (!Fp2.eql(zz, Fp2.ONE))
13174
+ throw new Error("invZ was invalid");
13175
+ return { x, y };
13176
+ });
13177
+ const assertValidMemo = memoized((p) => {
13178
+ if (p.is0()) {
13179
+ if (extraOpts.allowInfinityPoint && !Fp2.is0(p.Y))
13180
+ return;
13181
+ throw new Error("bad point: ZERO");
13182
+ }
13183
+ const { x, y } = p.toAffine();
13184
+ if (!Fp2.isValid(x) || !Fp2.isValid(y))
13185
+ throw new Error("bad point: x or y not field elements");
13186
+ if (!isValidXY(x, y))
13187
+ throw new Error("bad point: equation left != right");
13188
+ if (!p.isTorsionFree())
13189
+ throw new Error("bad point: not in prime-order subgroup");
13190
+ return true;
13191
+ });
13192
+ function finishEndo(endoBeta, k1p, k2p, k1neg, k2neg) {
13193
+ k2p = new Point(Fp2.mul(k2p.X, endoBeta), k2p.Y, k2p.Z);
13194
+ k1p = negateCt(k1neg, k1p);
13195
+ k2p = negateCt(k2neg, k2p);
13196
+ return k1p.add(k2p);
13197
+ }
13198
+ class Point {
13199
+ /** Does NOT validate if the point is valid. Use `.assertValidity()`. */
13200
+ constructor(X, Y, Z) {
13201
+ this.X = acoord("x", X);
13202
+ this.Y = acoord("y", Y, true);
13203
+ this.Z = acoord("z", Z);
13204
+ Object.freeze(this);
13205
+ }
13206
+ static CURVE() {
13207
+ return CURVE;
13208
+ }
13209
+ /** Does NOT validate if the point is valid. Use `.assertValidity()`. */
13210
+ static fromAffine(p) {
13211
+ const { x, y } = p || {};
13212
+ if (!p || !Fp2.isValid(x) || !Fp2.isValid(y))
13213
+ throw new Error("invalid affine point");
13214
+ if (p instanceof Point)
13215
+ throw new Error("projective point not allowed");
13216
+ if (Fp2.is0(x) && Fp2.is0(y))
13217
+ return Point.ZERO;
13218
+ return new Point(x, y, Fp2.ONE);
13219
+ }
13220
+ static fromBytes(bytes) {
13221
+ const P = Point.fromAffine(decodePoint2(_abytes2(bytes, void 0, "point")));
13222
+ P.assertValidity();
13223
+ return P;
13224
+ }
13225
+ static fromHex(hex3) {
13226
+ return Point.fromBytes(ensureBytes("pointHex", hex3));
13227
+ }
13228
+ get x() {
13229
+ return this.toAffine().x;
13230
+ }
13231
+ get y() {
13232
+ return this.toAffine().y;
13233
+ }
13234
+ /**
13235
+ *
13236
+ * @param windowSize
13237
+ * @param isLazy true will defer table computation until the first multiplication
13238
+ * @returns
13239
+ */
13240
+ precompute(windowSize = 8, isLazy = true) {
13241
+ wnaf.createCache(this, windowSize);
13242
+ if (!isLazy)
13243
+ this.multiply(_3n3);
13244
+ return this;
13245
+ }
13246
+ // TODO: return `this`
13247
+ /** A point on curve is valid if it conforms to equation. */
13248
+ assertValidity() {
13249
+ assertValidMemo(this);
13250
+ }
13251
+ hasEvenY() {
13252
+ const { y } = this.toAffine();
13253
+ if (!Fp2.isOdd)
13254
+ throw new Error("Field doesn't support isOdd");
13255
+ return !Fp2.isOdd(y);
13256
+ }
13257
+ /** Compare one point to another. */
13258
+ equals(other) {
13259
+ aprjpoint(other);
13260
+ const { X: X1, Y: Y1, Z: Z1 } = this;
13261
+ const { X: X2, Y: Y2, Z: Z2 } = other;
13262
+ const U1 = Fp2.eql(Fp2.mul(X1, Z2), Fp2.mul(X2, Z1));
13263
+ const U2 = Fp2.eql(Fp2.mul(Y1, Z2), Fp2.mul(Y2, Z1));
13264
+ return U1 && U2;
13265
+ }
13266
+ /** Flips point to one corresponding to (x, -y) in Affine coordinates. */
13267
+ negate() {
13268
+ return new Point(this.X, Fp2.neg(this.Y), this.Z);
13269
+ }
13270
+ // Renes-Costello-Batina exception-free doubling formula.
13271
+ // There is 30% faster Jacobian formula, but it is not complete.
13272
+ // https://eprint.iacr.org/2015/1060, algorithm 3
13273
+ // Cost: 8M + 3S + 3*a + 2*b3 + 15add.
13274
+ double() {
13275
+ const { a, b } = CURVE;
13276
+ const b3 = Fp2.mul(b, _3n3);
13277
+ const { X: X1, Y: Y1, Z: Z1 } = this;
13278
+ let X3 = Fp2.ZERO, Y3 = Fp2.ZERO, Z3 = Fp2.ZERO;
13279
+ let t0 = Fp2.mul(X1, X1);
13280
+ let t1 = Fp2.mul(Y1, Y1);
13281
+ let t2 = Fp2.mul(Z1, Z1);
13282
+ let t3 = Fp2.mul(X1, Y1);
13283
+ t3 = Fp2.add(t3, t3);
13284
+ Z3 = Fp2.mul(X1, Z1);
13285
+ Z3 = Fp2.add(Z3, Z3);
13286
+ X3 = Fp2.mul(a, Z3);
13287
+ Y3 = Fp2.mul(b3, t2);
13288
+ Y3 = Fp2.add(X3, Y3);
13289
+ X3 = Fp2.sub(t1, Y3);
13290
+ Y3 = Fp2.add(t1, Y3);
13291
+ Y3 = Fp2.mul(X3, Y3);
13292
+ X3 = Fp2.mul(t3, X3);
13293
+ Z3 = Fp2.mul(b3, Z3);
13294
+ t2 = Fp2.mul(a, t2);
13295
+ t3 = Fp2.sub(t0, t2);
13296
+ t3 = Fp2.mul(a, t3);
13297
+ t3 = Fp2.add(t3, Z3);
13298
+ Z3 = Fp2.add(t0, t0);
13299
+ t0 = Fp2.add(Z3, t0);
13300
+ t0 = Fp2.add(t0, t2);
13301
+ t0 = Fp2.mul(t0, t3);
13302
+ Y3 = Fp2.add(Y3, t0);
13303
+ t2 = Fp2.mul(Y1, Z1);
13304
+ t2 = Fp2.add(t2, t2);
13305
+ t0 = Fp2.mul(t2, t3);
13306
+ X3 = Fp2.sub(X3, t0);
13307
+ Z3 = Fp2.mul(t2, t1);
13308
+ Z3 = Fp2.add(Z3, Z3);
13309
+ Z3 = Fp2.add(Z3, Z3);
13310
+ return new Point(X3, Y3, Z3);
13311
+ }
13312
+ // Renes-Costello-Batina exception-free addition formula.
13313
+ // There is 30% faster Jacobian formula, but it is not complete.
13314
+ // https://eprint.iacr.org/2015/1060, algorithm 1
13315
+ // Cost: 12M + 0S + 3*a + 3*b3 + 23add.
13316
+ add(other) {
13317
+ aprjpoint(other);
13318
+ const { X: X1, Y: Y1, Z: Z1 } = this;
13319
+ const { X: X2, Y: Y2, Z: Z2 } = other;
13320
+ let X3 = Fp2.ZERO, Y3 = Fp2.ZERO, Z3 = Fp2.ZERO;
13321
+ const a = CURVE.a;
13322
+ const b3 = Fp2.mul(CURVE.b, _3n3);
13323
+ let t0 = Fp2.mul(X1, X2);
13324
+ let t1 = Fp2.mul(Y1, Y2);
13325
+ let t2 = Fp2.mul(Z1, Z2);
13326
+ let t3 = Fp2.add(X1, Y1);
13327
+ let t4 = Fp2.add(X2, Y2);
13328
+ t3 = Fp2.mul(t3, t4);
13329
+ t4 = Fp2.add(t0, t1);
13330
+ t3 = Fp2.sub(t3, t4);
13331
+ t4 = Fp2.add(X1, Z1);
13332
+ let t5 = Fp2.add(X2, Z2);
13333
+ t4 = Fp2.mul(t4, t5);
13334
+ t5 = Fp2.add(t0, t2);
13335
+ t4 = Fp2.sub(t4, t5);
13336
+ t5 = Fp2.add(Y1, Z1);
13337
+ X3 = Fp2.add(Y2, Z2);
13338
+ t5 = Fp2.mul(t5, X3);
13339
+ X3 = Fp2.add(t1, t2);
13340
+ t5 = Fp2.sub(t5, X3);
13341
+ Z3 = Fp2.mul(a, t4);
13342
+ X3 = Fp2.mul(b3, t2);
13343
+ Z3 = Fp2.add(X3, Z3);
13344
+ X3 = Fp2.sub(t1, Z3);
13345
+ Z3 = Fp2.add(t1, Z3);
13346
+ Y3 = Fp2.mul(X3, Z3);
13347
+ t1 = Fp2.add(t0, t0);
13348
+ t1 = Fp2.add(t1, t0);
13349
+ t2 = Fp2.mul(a, t2);
13350
+ t4 = Fp2.mul(b3, t4);
13351
+ t1 = Fp2.add(t1, t2);
13352
+ t2 = Fp2.sub(t0, t2);
13353
+ t2 = Fp2.mul(a, t2);
13354
+ t4 = Fp2.add(t4, t2);
13355
+ t0 = Fp2.mul(t1, t4);
13356
+ Y3 = Fp2.add(Y3, t0);
13357
+ t0 = Fp2.mul(t5, t4);
13358
+ X3 = Fp2.mul(t3, X3);
13359
+ X3 = Fp2.sub(X3, t0);
13360
+ t0 = Fp2.mul(t3, t1);
13361
+ Z3 = Fp2.mul(t5, Z3);
13362
+ Z3 = Fp2.add(Z3, t0);
13363
+ return new Point(X3, Y3, Z3);
13364
+ }
13365
+ subtract(other) {
13366
+ return this.add(other.negate());
13367
+ }
13368
+ is0() {
13369
+ return this.equals(Point.ZERO);
13370
+ }
13371
+ /**
13372
+ * Constant time multiplication.
13373
+ * Uses wNAF method. Windowed method may be 10% faster,
13374
+ * but takes 2x longer to generate and consumes 2x memory.
13375
+ * Uses precomputes when available.
13376
+ * Uses endomorphism for Koblitz curves.
13377
+ * @param scalar by which the point would be multiplied
13378
+ * @returns New point
13379
+ */
13380
+ multiply(scalar) {
13381
+ const { endo: endo2 } = extraOpts;
13382
+ if (!Fn2.isValidNot0(scalar))
13383
+ throw new Error("invalid scalar: out of range");
13384
+ let point, fake;
13385
+ const mul = (n) => wnaf.cached(this, n, (p) => normalizeZ(Point, p));
13386
+ if (endo2) {
13387
+ const { k1neg, k1, k2neg, k2 } = splitEndoScalarN(scalar);
13388
+ const { p: k1p, f: k1f } = mul(k1);
13389
+ const { p: k2p, f: k2f } = mul(k2);
13390
+ fake = k1f.add(k2f);
13391
+ point = finishEndo(endo2.beta, k1p, k2p, k1neg, k2neg);
13392
+ } else {
13393
+ const { p, f } = mul(scalar);
13394
+ point = p;
13395
+ fake = f;
13396
+ }
13397
+ return normalizeZ(Point, [point, fake])[0];
13398
+ }
13399
+ /**
13400
+ * Non-constant-time multiplication. Uses double-and-add algorithm.
13401
+ * It's faster, but should only be used when you don't care about
13402
+ * an exposed secret key e.g. sig verification, which works over *public* keys.
13403
+ */
13404
+ multiplyUnsafe(sc) {
13405
+ const { endo: endo2 } = extraOpts;
13406
+ const p = this;
13407
+ if (!Fn2.isValid(sc))
13408
+ throw new Error("invalid scalar: out of range");
13409
+ if (sc === _0n6 || p.is0())
13410
+ return Point.ZERO;
13411
+ if (sc === _1n6)
13412
+ return p;
13413
+ if (wnaf.hasCache(this))
13414
+ return this.multiply(sc);
13415
+ if (endo2) {
13416
+ const { k1neg, k1, k2neg, k2 } = splitEndoScalarN(sc);
13417
+ const { p1, p2 } = mulEndoUnsafe(Point, p, k1, k2);
13418
+ return finishEndo(endo2.beta, p1, p2, k1neg, k2neg);
13419
+ } else {
13420
+ return wnaf.unsafe(p, sc);
13421
+ }
13422
+ }
13423
+ multiplyAndAddUnsafe(Q, a, b) {
13424
+ const sum = this.multiplyUnsafe(a).add(Q.multiplyUnsafe(b));
13425
+ return sum.is0() ? void 0 : sum;
13426
+ }
13427
+ /**
13428
+ * Converts Projective point to affine (x, y) coordinates.
13429
+ * @param invertedZ Z^-1 (inverted zero) - optional, precomputation is useful for invertBatch
13430
+ */
13431
+ toAffine(invertedZ) {
13432
+ return toAffineMemo(this, invertedZ);
13433
+ }
13434
+ /**
13435
+ * Checks whether Point is free of torsion elements (is in prime subgroup).
13436
+ * Always torsion-free for cofactor=1 curves.
13437
+ */
13438
+ isTorsionFree() {
13439
+ const { isTorsionFree } = extraOpts;
13440
+ if (cofactor === _1n6)
13441
+ return true;
13442
+ if (isTorsionFree)
13443
+ return isTorsionFree(Point, this);
13444
+ return wnaf.unsafe(this, CURVE_ORDER).is0();
13445
+ }
13446
+ clearCofactor() {
13447
+ const { clearCofactor } = extraOpts;
13448
+ if (cofactor === _1n6)
13449
+ return this;
13450
+ if (clearCofactor)
13451
+ return clearCofactor(Point, this);
13452
+ return this.multiplyUnsafe(cofactor);
13453
+ }
13454
+ isSmallOrder() {
13455
+ return this.multiplyUnsafe(cofactor).is0();
13456
+ }
13457
+ toBytes(isCompressed = true) {
13458
+ _abool2(isCompressed, "isCompressed");
13459
+ this.assertValidity();
13460
+ return encodePoint(Point, this, isCompressed);
13461
+ }
13462
+ toHex(isCompressed = true) {
13463
+ return bytesToHex(this.toBytes(isCompressed));
13464
+ }
13465
+ toString() {
13466
+ return `<Point ${this.is0() ? "ZERO" : this.toHex()}>`;
13467
+ }
13468
+ // TODO: remove
13469
+ get px() {
13470
+ return this.X;
13471
+ }
13472
+ get py() {
13473
+ return this.X;
13474
+ }
13475
+ get pz() {
13476
+ return this.Z;
13477
+ }
13478
+ toRawBytes(isCompressed = true) {
13479
+ return this.toBytes(isCompressed);
13480
+ }
13481
+ _setWindowSize(windowSize) {
13482
+ this.precompute(windowSize);
13483
+ }
13484
+ static normalizeZ(points) {
13485
+ return normalizeZ(Point, points);
13486
+ }
13487
+ static msm(points, scalars) {
13488
+ return pippenger(Point, Fn2, points, scalars);
13489
+ }
13490
+ static fromPrivateKey(privateKey) {
13491
+ return Point.BASE.multiply(_normFnElement(Fn2, privateKey));
13492
+ }
13493
+ }
13494
+ Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp2.ONE);
13495
+ Point.ZERO = new Point(Fp2.ZERO, Fp2.ONE, Fp2.ZERO);
13496
+ Point.Fp = Fp2;
13497
+ Point.Fn = Fn2;
13498
+ const bits = Fn2.BITS;
13499
+ const wnaf = new wNAF(Point, extraOpts.endo ? Math.ceil(bits / 2) : bits);
13500
+ Point.BASE.precompute(8);
13501
+ return Point;
13502
+ }
13503
+ function pprefix(hasEvenY) {
13504
+ return Uint8Array.of(hasEvenY ? 2 : 3);
13505
+ }
13506
+ function getWLengths(Fp2, Fn2) {
13507
+ return {
13508
+ secretKey: Fn2.BYTES,
13509
+ publicKey: 1 + Fp2.BYTES,
13510
+ publicKeyUncompressed: 1 + 2 * Fp2.BYTES,
13511
+ publicKeyHasPrefix: true,
13512
+ signature: 2 * Fn2.BYTES
13513
+ };
13514
+ }
13515
+ function ecdh(Point, ecdhOpts = {}) {
13516
+ const { Fn: Fn2 } = Point;
13517
+ const randomBytes_ = ecdhOpts.randomBytes || randomBytes;
13518
+ const lengths = Object.assign(getWLengths(Point.Fp, Fn2), { seed: getMinHashLength(Fn2.ORDER) });
13519
+ function isValidSecretKey(secretKey) {
13520
+ try {
13521
+ return !!_normFnElement(Fn2, secretKey);
13522
+ } catch (error) {
13523
+ return false;
13524
+ }
13525
+ }
13526
+ function isValidPublicKey(publicKey, isCompressed) {
13527
+ const { publicKey: comp, publicKeyUncompressed } = lengths;
13528
+ try {
13529
+ const l = publicKey.length;
13530
+ if (isCompressed === true && l !== comp)
13531
+ return false;
13532
+ if (isCompressed === false && l !== publicKeyUncompressed)
13533
+ return false;
13534
+ return !!Point.fromBytes(publicKey);
13535
+ } catch (error) {
13536
+ return false;
13537
+ }
13538
+ }
13539
+ function randomSecretKey(seed = randomBytes_(lengths.seed)) {
13540
+ return mapHashToField(_abytes2(seed, lengths.seed, "seed"), Fn2.ORDER);
13541
+ }
13542
+ function getPublicKey(secretKey, isCompressed = true) {
13543
+ return Point.BASE.multiply(_normFnElement(Fn2, secretKey)).toBytes(isCompressed);
13544
+ }
13545
+ function keygen(seed) {
13546
+ const secretKey = randomSecretKey(seed);
13547
+ return { secretKey, publicKey: getPublicKey(secretKey) };
13548
+ }
13549
+ function isProbPub(item) {
13550
+ if (typeof item === "bigint")
13551
+ return false;
13552
+ if (item instanceof Point)
13553
+ return true;
13554
+ const { secretKey, publicKey, publicKeyUncompressed } = lengths;
13555
+ if (Fn2.allowedLengths || secretKey === publicKey)
13556
+ return void 0;
13557
+ const l = ensureBytes("key", item).length;
13558
+ return l === publicKey || l === publicKeyUncompressed;
13559
+ }
13560
+ function getSharedSecret(secretKeyA, publicKeyB, isCompressed = true) {
13561
+ if (isProbPub(secretKeyA) === true)
13562
+ throw new Error("first arg must be private key");
13563
+ if (isProbPub(publicKeyB) === false)
13564
+ throw new Error("second arg must be public key");
13565
+ const s = _normFnElement(Fn2, secretKeyA);
13566
+ const b = Point.fromHex(publicKeyB);
13567
+ return b.multiply(s).toBytes(isCompressed);
13568
+ }
13569
+ const utils = {
13570
+ isValidSecretKey,
13571
+ isValidPublicKey,
13572
+ randomSecretKey,
13573
+ // TODO: remove
13574
+ isValidPrivateKey: isValidSecretKey,
13575
+ randomPrivateKey: randomSecretKey,
13576
+ normPrivateKeyToScalar: (key) => _normFnElement(Fn2, key),
13577
+ precompute(windowSize = 8, point = Point.BASE) {
13578
+ return point.precompute(windowSize, false);
13579
+ }
13580
+ };
13581
+ return Object.freeze({ getPublicKey, getSharedSecret, keygen, Point, utils, lengths });
13582
+ }
13583
+ function ecdsa(Point, hash, ecdsaOpts = {}) {
13584
+ ahash(hash);
13585
+ _validateObject(ecdsaOpts, {}, {
13586
+ hmac: "function",
13587
+ lowS: "boolean",
13588
+ randomBytes: "function",
13589
+ bits2int: "function",
13590
+ bits2int_modN: "function"
13591
+ });
13592
+ const randomBytes4 = ecdsaOpts.randomBytes || randomBytes;
13593
+ const hmac2 = ecdsaOpts.hmac || ((key, ...msgs) => hmac(hash, key, concatBytes(...msgs)));
13594
+ const { Fp: Fp2, Fn: Fn2 } = Point;
13595
+ const { ORDER: CURVE_ORDER, BITS: fnBits } = Fn2;
13596
+ const { keygen, getPublicKey, getSharedSecret, utils, lengths } = ecdh(Point, ecdsaOpts);
13597
+ const defaultSigOpts = {
13598
+ prehash: false,
13599
+ lowS: typeof ecdsaOpts.lowS === "boolean" ? ecdsaOpts.lowS : false,
13600
+ format: void 0,
13601
+ //'compact' as ECDSASigFormat,
13602
+ extraEntropy: false
13603
+ };
13604
+ const defaultSigOpts_format = "compact";
13605
+ function isBiggerThanHalfOrder(number) {
13606
+ const HALF = CURVE_ORDER >> _1n6;
13607
+ return number > HALF;
13608
+ }
13609
+ function validateRS(title, num) {
13610
+ if (!Fn2.isValidNot0(num))
13611
+ throw new Error(`invalid signature ${title}: out of range 1..Point.Fn.ORDER`);
13612
+ return num;
13613
+ }
13614
+ function validateSigLength(bytes, format5) {
13615
+ validateSigFormat(format5);
13616
+ const size = lengths.signature;
13617
+ const sizer = format5 === "compact" ? size : format5 === "recovered" ? size + 1 : void 0;
13618
+ return _abytes2(bytes, sizer, `${format5} signature`);
13619
+ }
13620
+ class Signature {
13621
+ constructor(r, s, recovery) {
13622
+ this.r = validateRS("r", r);
13623
+ this.s = validateRS("s", s);
13624
+ if (recovery != null)
13625
+ this.recovery = recovery;
13626
+ Object.freeze(this);
13627
+ }
13628
+ static fromBytes(bytes, format5 = defaultSigOpts_format) {
13629
+ validateSigLength(bytes, format5);
13630
+ let recid;
13631
+ if (format5 === "der") {
13632
+ const { r: r2, s: s2 } = DER.toSig(_abytes2(bytes));
13633
+ return new Signature(r2, s2);
13634
+ }
13635
+ if (format5 === "recovered") {
13636
+ recid = bytes[0];
13637
+ format5 = "compact";
13638
+ bytes = bytes.subarray(1);
13639
+ }
13640
+ const L = Fn2.BYTES;
13641
+ const r = bytes.subarray(0, L);
13642
+ const s = bytes.subarray(L, L * 2);
13643
+ return new Signature(Fn2.fromBytes(r), Fn2.fromBytes(s), recid);
13644
+ }
13645
+ static fromHex(hex3, format5) {
13646
+ return this.fromBytes(hexToBytes(hex3), format5);
13647
+ }
13648
+ addRecoveryBit(recovery) {
13649
+ return new Signature(this.r, this.s, recovery);
13650
+ }
13651
+ recoverPublicKey(messageHash) {
13652
+ const FIELD_ORDER = Fp2.ORDER;
13653
+ const { r, s, recovery: rec } = this;
13654
+ if (rec == null || ![0, 1, 2, 3].includes(rec))
13655
+ throw new Error("recovery id invalid");
13656
+ const hasCofactor = CURVE_ORDER * _2n4 < FIELD_ORDER;
13657
+ if (hasCofactor && rec > 1)
13658
+ throw new Error("recovery id is ambiguous for h>1 curve");
13659
+ const radj = rec === 2 || rec === 3 ? r + CURVE_ORDER : r;
13660
+ if (!Fp2.isValid(radj))
13661
+ throw new Error("recovery id 2 or 3 invalid");
13662
+ const x = Fp2.toBytes(radj);
13663
+ const R = Point.fromBytes(concatBytes(pprefix((rec & 1) === 0), x));
13664
+ const ir = Fn2.inv(radj);
13665
+ const h = bits2int_modN(ensureBytes("msgHash", messageHash));
13666
+ const u1 = Fn2.create(-h * ir);
13667
+ const u2 = Fn2.create(s * ir);
13668
+ const Q = Point.BASE.multiplyUnsafe(u1).add(R.multiplyUnsafe(u2));
13669
+ if (Q.is0())
13670
+ throw new Error("point at infinify");
13671
+ Q.assertValidity();
13672
+ return Q;
13673
+ }
13674
+ // Signatures should be low-s, to prevent malleability.
13675
+ hasHighS() {
13676
+ return isBiggerThanHalfOrder(this.s);
13677
+ }
13678
+ toBytes(format5 = defaultSigOpts_format) {
13679
+ validateSigFormat(format5);
13680
+ if (format5 === "der")
13681
+ return hexToBytes(DER.hexFromSig(this));
13682
+ const r = Fn2.toBytes(this.r);
13683
+ const s = Fn2.toBytes(this.s);
13684
+ if (format5 === "recovered") {
13685
+ if (this.recovery == null)
13686
+ throw new Error("recovery bit must be present");
13687
+ return concatBytes(Uint8Array.of(this.recovery), r, s);
13688
+ }
13689
+ return concatBytes(r, s);
13690
+ }
13691
+ toHex(format5) {
13692
+ return bytesToHex(this.toBytes(format5));
13693
+ }
13694
+ // TODO: remove
13695
+ assertValidity() {
13696
+ }
13697
+ static fromCompact(hex3) {
13698
+ return Signature.fromBytes(ensureBytes("sig", hex3), "compact");
13699
+ }
13700
+ static fromDER(hex3) {
13701
+ return Signature.fromBytes(ensureBytes("sig", hex3), "der");
13702
+ }
13703
+ normalizeS() {
13704
+ return this.hasHighS() ? new Signature(this.r, Fn2.neg(this.s), this.recovery) : this;
13705
+ }
13706
+ toDERRawBytes() {
13707
+ return this.toBytes("der");
13708
+ }
13709
+ toDERHex() {
13710
+ return bytesToHex(this.toBytes("der"));
13711
+ }
13712
+ toCompactRawBytes() {
13713
+ return this.toBytes("compact");
13714
+ }
13715
+ toCompactHex() {
13716
+ return bytesToHex(this.toBytes("compact"));
13717
+ }
13718
+ }
13719
+ const bits2int = ecdsaOpts.bits2int || function bits2int_def(bytes) {
13720
+ if (bytes.length > 8192)
13721
+ throw new Error("input is too large");
13722
+ const num = bytesToNumberBE(bytes);
13723
+ const delta = bytes.length * 8 - fnBits;
13724
+ return delta > 0 ? num >> BigInt(delta) : num;
13725
+ };
13726
+ const bits2int_modN = ecdsaOpts.bits2int_modN || function bits2int_modN_def(bytes) {
13727
+ return Fn2.create(bits2int(bytes));
13728
+ };
13729
+ const ORDER_MASK = bitMask(fnBits);
13730
+ function int2octets(num) {
13731
+ aInRange("num < 2^" + fnBits, num, _0n6, ORDER_MASK);
13732
+ return Fn2.toBytes(num);
13733
+ }
13734
+ function validateMsgAndHash(message, prehash) {
13735
+ _abytes2(message, void 0, "message");
13736
+ return prehash ? _abytes2(hash(message), void 0, "prehashed message") : message;
13737
+ }
13738
+ function prepSig(message, privateKey, opts) {
13739
+ if (["recovered", "canonical"].some((k) => k in opts))
13740
+ throw new Error("sign() legacy options not supported");
13741
+ const { lowS, prehash, extraEntropy } = validateSigOpts(opts, defaultSigOpts);
13742
+ message = validateMsgAndHash(message, prehash);
13743
+ const h1int = bits2int_modN(message);
13744
+ const d = _normFnElement(Fn2, privateKey);
13745
+ const seedArgs = [int2octets(d), int2octets(h1int)];
13746
+ if (extraEntropy != null && extraEntropy !== false) {
13747
+ const e = extraEntropy === true ? randomBytes4(lengths.secretKey) : extraEntropy;
13748
+ seedArgs.push(ensureBytes("extraEntropy", e));
13749
+ }
13750
+ const seed = concatBytes(...seedArgs);
13751
+ const m = h1int;
13752
+ function k2sig(kBytes) {
13753
+ const k = bits2int(kBytes);
13754
+ if (!Fn2.isValidNot0(k))
13755
+ return;
13756
+ const ik = Fn2.inv(k);
13757
+ const q = Point.BASE.multiply(k).toAffine();
13758
+ const r = Fn2.create(q.x);
13759
+ if (r === _0n6)
13760
+ return;
13761
+ const s = Fn2.create(ik * Fn2.create(m + r * d));
13762
+ if (s === _0n6)
13763
+ return;
13764
+ let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n6);
13765
+ let normS = s;
13766
+ if (lowS && isBiggerThanHalfOrder(s)) {
13767
+ normS = Fn2.neg(s);
13768
+ recovery ^= 1;
13769
+ }
13770
+ return new Signature(r, normS, recovery);
13771
+ }
13772
+ return { seed, k2sig };
13773
+ }
13774
+ function sign(message, secretKey, opts = {}) {
13775
+ message = ensureBytes("message", message);
13776
+ const { seed, k2sig } = prepSig(message, secretKey, opts);
13777
+ const drbg = createHmacDrbg(hash.outputLen, Fn2.BYTES, hmac2);
13778
+ const sig = drbg(seed, k2sig);
13779
+ return sig;
13780
+ }
13781
+ function tryParsingSig(sg) {
13782
+ let sig = void 0;
13783
+ const isHex = typeof sg === "string" || isBytes(sg);
13784
+ const isObj = !isHex && sg !== null && typeof sg === "object" && typeof sg.r === "bigint" && typeof sg.s === "bigint";
13785
+ if (!isHex && !isObj)
13786
+ throw new Error("invalid signature, expected Uint8Array, hex string or Signature instance");
13787
+ if (isObj) {
13788
+ sig = new Signature(sg.r, sg.s);
13789
+ } else if (isHex) {
13790
+ try {
13791
+ sig = Signature.fromBytes(ensureBytes("sig", sg), "der");
13792
+ } catch (derError) {
13793
+ if (!(derError instanceof DER.Err))
13794
+ throw derError;
13795
+ }
13796
+ if (!sig) {
13797
+ try {
13798
+ sig = Signature.fromBytes(ensureBytes("sig", sg), "compact");
13799
+ } catch (error) {
13800
+ return false;
13801
+ }
13802
+ }
13803
+ }
13804
+ if (!sig)
13805
+ return false;
13806
+ return sig;
13807
+ }
13808
+ function verify(signature, message, publicKey, opts = {}) {
13809
+ const { lowS, prehash, format: format5 } = validateSigOpts(opts, defaultSigOpts);
13810
+ publicKey = ensureBytes("publicKey", publicKey);
13811
+ message = validateMsgAndHash(ensureBytes("message", message), prehash);
13812
+ if ("strict" in opts)
13813
+ throw new Error("options.strict was renamed to lowS");
13814
+ const sig = format5 === void 0 ? tryParsingSig(signature) : Signature.fromBytes(ensureBytes("sig", signature), format5);
13815
+ if (sig === false)
13816
+ return false;
13817
+ try {
13818
+ const P = Point.fromBytes(publicKey);
13819
+ if (lowS && sig.hasHighS())
13820
+ return false;
13821
+ const { r, s } = sig;
13822
+ const h = bits2int_modN(message);
13823
+ const is = Fn2.inv(s);
13824
+ const u1 = Fn2.create(h * is);
13825
+ const u2 = Fn2.create(r * is);
13826
+ const R = Point.BASE.multiplyUnsafe(u1).add(P.multiplyUnsafe(u2));
13827
+ if (R.is0())
13828
+ return false;
13829
+ const v = Fn2.create(R.x);
13830
+ return v === r;
13831
+ } catch (e) {
13832
+ return false;
13833
+ }
13834
+ }
13835
+ function recoverPublicKey(signature, message, opts = {}) {
13836
+ const { prehash } = validateSigOpts(opts, defaultSigOpts);
13837
+ message = validateMsgAndHash(message, prehash);
13838
+ return Signature.fromBytes(signature, "recovered").recoverPublicKey(message).toBytes();
13839
+ }
13840
+ return Object.freeze({
13841
+ keygen,
13842
+ getPublicKey,
13843
+ getSharedSecret,
13844
+ utils,
13845
+ lengths,
13846
+ Point,
13847
+ sign,
13848
+ verify,
13849
+ recoverPublicKey,
13850
+ Signature,
13851
+ hash
13852
+ });
13853
+ }
13854
+ function _weierstrass_legacy_opts_to_new(c) {
13855
+ const CURVE = {
13856
+ a: c.a,
13857
+ b: c.b,
13858
+ p: c.Fp.ORDER,
13859
+ n: c.n,
13860
+ h: c.h,
13861
+ Gx: c.Gx,
13862
+ Gy: c.Gy
13863
+ };
13864
+ const Fp2 = c.Fp;
13865
+ let allowedLengths = c.allowedPrivateKeyLengths ? Array.from(new Set(c.allowedPrivateKeyLengths.map((l) => Math.ceil(l / 2)))) : void 0;
13866
+ const Fn2 = Field(CURVE.n, {
13867
+ BITS: c.nBitLength,
13868
+ allowedLengths,
13869
+ modFromBytes: c.wrapPrivateKey
13870
+ });
13871
+ const curveOpts = {
13872
+ Fp: Fp2,
13873
+ Fn: Fn2,
13874
+ allowInfinityPoint: c.allowInfinityPoint,
13875
+ endo: c.endo,
13876
+ isTorsionFree: c.isTorsionFree,
13877
+ clearCofactor: c.clearCofactor,
13878
+ fromBytes: c.fromBytes,
13879
+ toBytes: c.toBytes
13880
+ };
13881
+ return { CURVE, curveOpts };
13882
+ }
13883
+ function _ecdsa_legacy_opts_to_new(c) {
13884
+ const { CURVE, curveOpts } = _weierstrass_legacy_opts_to_new(c);
13885
+ const ecdsaOpts = {
13886
+ hmac: c.hmac,
13887
+ randomBytes: c.randomBytes,
13888
+ lowS: c.lowS,
13889
+ bits2int: c.bits2int,
13890
+ bits2int_modN: c.bits2int_modN
13891
+ };
13892
+ return { CURVE, curveOpts, hash: c.hash, ecdsaOpts };
13893
+ }
13894
+ function _ecdsa_new_output_to_legacy(c, _ecdsa) {
13895
+ const Point = _ecdsa.Point;
13896
+ return Object.assign({}, _ecdsa, {
13897
+ ProjectivePoint: Point,
13898
+ CURVE: Object.assign({}, c, nLength(Point.Fn.ORDER, Point.Fn.BITS))
13899
+ });
13900
+ }
13901
+ function weierstrass(c) {
13902
+ const { CURVE, curveOpts, hash, ecdsaOpts } = _ecdsa_legacy_opts_to_new(c);
13903
+ const Point = weierstrassN(CURVE, curveOpts);
13904
+ const signs = ecdsa(Point, hash, ecdsaOpts);
13905
+ return _ecdsa_new_output_to_legacy(c, signs);
13906
+ }
13907
+ var divNearest, DERErr, DER, _0n6, _1n6, _2n4, _3n3, _4n2;
13908
+ var init_weierstrass = __esm({
13909
+ "../../node_modules/@noble/curves/esm/abstract/weierstrass.js"() {
13910
+ "use strict";
13911
+ init_hmac();
13912
+ init_utils();
13913
+ init_utils2();
13914
+ init_curve();
13915
+ init_modular();
13916
+ divNearest = (num, den) => (num + (num >= 0 ? den : -den) / _2n4) / den;
13917
+ DERErr = class extends Error {
13918
+ constructor(m = "") {
13919
+ super(m);
13920
+ }
13921
+ };
13922
+ DER = {
13923
+ // asn.1 DER encoding utils
13924
+ Err: DERErr,
13925
+ // Basic building block is TLV (Tag-Length-Value)
13926
+ _tlv: {
13927
+ encode: (tag, data) => {
13928
+ const { Err: E } = DER;
13929
+ if (tag < 0 || tag > 256)
13930
+ throw new E("tlv.encode: wrong tag");
13931
+ if (data.length & 1)
13932
+ throw new E("tlv.encode: unpadded data");
13933
+ const dataLen = data.length / 2;
13934
+ const len = numberToHexUnpadded(dataLen);
13935
+ if (len.length / 2 & 128)
13936
+ throw new E("tlv.encode: long form length too big");
13937
+ const lenLen = dataLen > 127 ? numberToHexUnpadded(len.length / 2 | 128) : "";
13938
+ const t = numberToHexUnpadded(tag);
13939
+ return t + lenLen + len + data;
13940
+ },
13941
+ // v - value, l - left bytes (unparsed)
13942
+ decode(tag, data) {
13943
+ const { Err: E } = DER;
13944
+ let pos = 0;
13945
+ if (tag < 0 || tag > 256)
13946
+ throw new E("tlv.encode: wrong tag");
13947
+ if (data.length < 2 || data[pos++] !== tag)
13948
+ throw new E("tlv.decode: wrong tlv");
13949
+ const first = data[pos++];
13950
+ const isLong = !!(first & 128);
13951
+ let length5 = 0;
13952
+ if (!isLong)
13953
+ length5 = first;
13954
+ else {
13955
+ const lenLen = first & 127;
13956
+ if (!lenLen)
13957
+ throw new E("tlv.decode(long): indefinite length not supported");
13958
+ if (lenLen > 4)
13959
+ throw new E("tlv.decode(long): byte length is too big");
13960
+ const lengthBytes = data.subarray(pos, pos + lenLen);
13961
+ if (lengthBytes.length !== lenLen)
13962
+ throw new E("tlv.decode: length bytes not complete");
13963
+ if (lengthBytes[0] === 0)
13964
+ throw new E("tlv.decode(long): zero leftmost byte");
13965
+ for (const b of lengthBytes)
13966
+ length5 = length5 << 8 | b;
13967
+ pos += lenLen;
13968
+ if (length5 < 128)
13969
+ throw new E("tlv.decode(long): not minimal encoding");
13970
+ }
13971
+ const v = data.subarray(pos, pos + length5);
13972
+ if (v.length !== length5)
13973
+ throw new E("tlv.decode: wrong value length");
13974
+ return { v, l: data.subarray(pos + length5) };
13975
+ }
13976
+ },
13977
+ // https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,
13978
+ // since we always use positive integers here. It must always be empty:
13979
+ // - add zero byte if exists
13980
+ // - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)
13981
+ _int: {
13982
+ encode(num) {
13983
+ const { Err: E } = DER;
13984
+ if (num < _0n6)
13985
+ throw new E("integer: negative integers are not allowed");
13986
+ let hex3 = numberToHexUnpadded(num);
13987
+ if (Number.parseInt(hex3[0], 16) & 8)
13988
+ hex3 = "00" + hex3;
13989
+ if (hex3.length & 1)
13990
+ throw new E("unexpected DER parsing assertion: unpadded hex");
13991
+ return hex3;
13992
+ },
13993
+ decode(data) {
13994
+ const { Err: E } = DER;
13995
+ if (data[0] & 128)
13996
+ throw new E("invalid signature integer: negative");
13997
+ if (data[0] === 0 && !(data[1] & 128))
13998
+ throw new E("invalid signature integer: unnecessary leading zero");
13999
+ return bytesToNumberBE(data);
14000
+ }
14001
+ },
14002
+ toSig(hex3) {
14003
+ const { Err: E, _int: int, _tlv: tlv } = DER;
14004
+ const data = ensureBytes("signature", hex3);
14005
+ const { v: seqBytes, l: seqLeftBytes } = tlv.decode(48, data);
14006
+ if (seqLeftBytes.length)
14007
+ throw new E("invalid signature: left bytes after parsing");
14008
+ const { v: rBytes, l: rLeftBytes } = tlv.decode(2, seqBytes);
14009
+ const { v: sBytes, l: sLeftBytes } = tlv.decode(2, rLeftBytes);
14010
+ if (sLeftBytes.length)
14011
+ throw new E("invalid signature: left bytes after parsing");
14012
+ return { r: int.decode(rBytes), s: int.decode(sBytes) };
14013
+ },
14014
+ hexFromSig(sig) {
14015
+ const { _tlv: tlv, _int: int } = DER;
14016
+ const rs = tlv.encode(2, int.encode(sig.r));
14017
+ const ss = tlv.encode(2, int.encode(sig.s));
14018
+ const seq = rs + ss;
14019
+ return tlv.encode(48, seq);
14020
+ }
14021
+ };
14022
+ _0n6 = BigInt(0);
14023
+ _1n6 = BigInt(1);
14024
+ _2n4 = BigInt(2);
14025
+ _3n3 = BigInt(3);
14026
+ _4n2 = BigInt(4);
14027
+ }
14028
+ });
14029
+
14030
+ // ../../node_modules/@noble/curves/esm/_shortw_utils.js
14031
+ function createCurve(curveDef, defHash) {
14032
+ const create5 = (hash) => weierstrass({ ...curveDef, hash });
14033
+ return { ...create5(defHash), create: create5 };
14034
+ }
14035
+ var init_shortw_utils = __esm({
14036
+ "../../node_modules/@noble/curves/esm/_shortw_utils.js"() {
14037
+ "use strict";
14038
+ init_weierstrass();
14039
+ }
14040
+ });
14041
+
14042
+ // ../../node_modules/@noble/curves/esm/nist.js
14043
+ var p256_CURVE, p384_CURVE, p521_CURVE, Fp256, Fp384, Fp521, p256, p384, p521;
14044
+ var init_nist = __esm({
14045
+ "../../node_modules/@noble/curves/esm/nist.js"() {
14046
+ "use strict";
14047
+ init_sha2();
14048
+ init_shortw_utils();
14049
+ init_modular();
14050
+ p256_CURVE = {
14051
+ p: BigInt("0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff"),
14052
+ n: BigInt("0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"),
14053
+ h: BigInt(1),
14054
+ a: BigInt("0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc"),
14055
+ b: BigInt("0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b"),
14056
+ Gx: BigInt("0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296"),
14057
+ Gy: BigInt("0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5")
14058
+ };
14059
+ p384_CURVE = {
14060
+ p: BigInt("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff"),
14061
+ n: BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973"),
14062
+ h: BigInt(1),
14063
+ a: BigInt("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc"),
14064
+ b: BigInt("0xb3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef"),
14065
+ Gx: BigInt("0xaa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7"),
14066
+ Gy: BigInt("0x3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f")
14067
+ };
14068
+ p521_CURVE = {
14069
+ p: BigInt("0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
14070
+ n: BigInt("0x01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409"),
14071
+ h: BigInt(1),
14072
+ a: BigInt("0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc"),
14073
+ b: BigInt("0x0051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00"),
14074
+ Gx: BigInt("0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66"),
14075
+ Gy: BigInt("0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650")
14076
+ };
14077
+ Fp256 = Field(p256_CURVE.p);
14078
+ Fp384 = Field(p384_CURVE.p);
14079
+ Fp521 = Field(p521_CURVE.p);
14080
+ p256 = createCurve({ ...p256_CURVE, Fp: Fp256, lowS: false }, sha256);
14081
+ p384 = createCurve({ ...p384_CURVE, Fp: Fp384, lowS: false }, sha384);
14082
+ p521 = createCurve({ ...p521_CURVE, Fp: Fp521, lowS: false, allowedPrivateKeyLengths: [130, 131, 132] }, sha512);
14083
+ }
14084
+ });
14085
+
14086
+ // ../../node_modules/@noble/curves/esm/p256.js
14087
+ var p2562;
14088
+ var init_p256 = __esm({
14089
+ "../../node_modules/@noble/curves/esm/p256.js"() {
14090
+ "use strict";
14091
+ init_nist();
14092
+ p2562 = p256;
14093
+ }
14094
+ });
14095
+
12790
14096
  // ../share-envelope/dist/links.js
12791
14097
  var links_exports = {};
12792
14098
  __export(links_exports, {
@@ -12813,6 +14119,7 @@ __export(links_exports, {
12813
14119
  checkLinkBody: () => checkLinkBody,
12814
14120
  checkLinkHeaderLife: () => checkLinkHeaderLife,
12815
14121
  checkLinkRecord: () => checkLinkRecord,
14122
+ createApprovalRequest: () => createApprovalRequest,
12816
14123
  createLink: () => createLink,
12817
14124
  deleteLink: () => deleteLink,
12818
14125
  ed25519KeyProblem: () => ed25519KeyProblem,
@@ -12826,11 +14133,13 @@ __export(links_exports, {
12826
14133
  linkTypeSchema: () => linkTypeSchema,
12827
14134
  normalizeLinkId: () => normalizeLinkId,
12828
14135
  openLinkRecord: () => openLinkRecord,
14136
+ parseApprovalRequest: () => parseApprovalRequest,
12829
14137
  parseLink: () => parseLink,
12830
14138
  parseLinkTimestamp: () => parseLinkTimestamp,
12831
14139
  prepareLinkRecord: () => prepareLinkRecord,
12832
14140
  randomLinkNonce: () => randomLinkNonce,
12833
14141
  redactLink: () => redactLink,
14142
+ resolveApprovalRequest: () => resolveApprovalRequest,
12834
14143
  resolveLink: () => resolveLink,
12835
14144
  shortShareLinkCid: () => shortShareLinkCid,
12836
14145
  signDelete: () => signDelete,
@@ -13205,14 +14514,14 @@ function linkTypeForPathLetter(letter) {
13205
14514
  function normalizeLinkId(id) {
13206
14515
  return /^[A-Za-z2-7]{26}$/.test(id) ? id.toLowerCase() : null;
13207
14516
  }
13208
- function canonicalHttpsOrigin(origin) {
14517
+ function canonicalHttpsOrigin(origin2) {
13209
14518
  let url;
13210
14519
  try {
13211
- url = new URL(origin);
14520
+ url = new URL(origin2);
13212
14521
  } catch {
13213
14522
  return false;
13214
14523
  }
13215
- return url.protocol === "https:" && url.username === "" && url.password === "" && url.origin === origin;
14524
+ return url.protocol === "https:" && url.username === "" && url.password === "" && url.origin === origin2;
13216
14525
  }
13217
14526
  function assertKey2(key) {
13218
14527
  if (key.length !== 32) throw new LinkError("invalid_argument", "a link key is 32 bytes");
@@ -13345,9 +14654,19 @@ async function openLinkRecord(record2, key, options = {}) {
13345
14654
  await runBodyValidator(opened, options.validateBody);
13346
14655
  return opened;
13347
14656
  }
13348
- function checkApiOrigin(origin) {
13349
- if (!AUDIENCE_ORIGIN.test(origin)) throw new LinkError("invalid_argument", "the API origin is not a canonical https origin");
13350
- return origin;
14657
+ function parseApprovalRequest(value, options = {}) {
14658
+ const parsed = requestSchema.safeParse(value);
14659
+ if (!parsed.success) throw new LinkError("body_validation_failed", "invalid approval request");
14660
+ const request = parsed.data;
14661
+ const publicKey = decodeStrictBase64Url(request.targetPublicJwk.x);
14662
+ if (ed25519KeyProblem(publicKey) !== null || didKeyFromEd25519PublicKey(publicKey) !== request.targetDid || request.issuer !== request.targetDid || options.issuer !== void 0 && request.issuer !== options.issuer) {
14663
+ throw new LinkError("issuer_binding_mismatch");
14664
+ }
14665
+ return request;
14666
+ }
14667
+ function checkApiOrigin(origin2) {
14668
+ if (!AUDIENCE_ORIGIN.test(origin2)) throw new LinkError("invalid_argument", "the API origin is not a canonical https origin");
14669
+ return origin2;
13351
14670
  }
13352
14671
  function requestSignal(options) {
13353
14672
  const timeout = AbortSignal.timeout(options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
@@ -13419,7 +14738,7 @@ async function refusal(response) {
13419
14738
  async function prepareLinkRecord(input) {
13420
14739
  const apiOrigin = checkApiOrigin(input.apiOrigin);
13421
14740
  const nowMs = toEpochMs(input.now);
13422
- const expiresMs = input.expiresAt.getTime();
14741
+ const expiresMs = Math.floor(input.expiresAt.getTime() / 1e3) * 1e3;
13423
14742
  if (!Number.isFinite(nowMs) || !Number.isFinite(expiresMs)) throw new LinkError("invalid_argument", "now and expiresAt must be valid dates");
13424
14743
  let blob;
13425
14744
  let key;
@@ -13460,6 +14779,34 @@ async function createLink(input) {
13460
14779
  const { id } = created.data;
13461
14780
  return { link: buildShortLink({ origin: input.linkOrigin, type: input.type, id, key, bodyCid }), id, expiresAt: record2.header.expiresAt, bodyCid };
13462
14781
  }
14782
+ async function createApprovalRequest(input) {
14783
+ const request = parseApprovalRequest(input.request, { issuer: input.issuerKey.did });
14784
+ const now = toEpochMs(input.now);
14785
+ const prepared = await prepareLinkRecord({
14786
+ type: "openkey-approval-request",
14787
+ issuerKey: input.issuerKey,
14788
+ apiOrigin: input.apiOrigin,
14789
+ now,
14790
+ expiresAt: input.expiresAt ?? new Date(now + LINK_TYPE_SPECS["openkey-approval-request"].defaultLifeSeconds * 1e3),
14791
+ plaintext: new TextEncoder().encode(canonicalize2(request))
14792
+ });
14793
+ const response = await send(
14794
+ `${checkApiOrigin(input.apiOrigin)}/v1/links`,
14795
+ { method: "POST", body: JSON.stringify(prepared.record) },
14796
+ input,
14797
+ "application/json"
14798
+ );
14799
+ if (response.status !== 201) throw await refusal(response);
14800
+ const created = createdSchema.safeParse(await readJson2(response));
14801
+ if (!created.success || !LINK_ID_PATTERN.test(created.data.id) || created.data.expiresAt !== prepared.record.header.expiresAt) throw new LinkError("invalid_response");
14802
+ return {
14803
+ id: created.data.id,
14804
+ expiresAt: prepared.record.header.expiresAt,
14805
+ bodyCid: prepared.bodyCid,
14806
+ record: prepared.record,
14807
+ link: buildShortLink({ origin: input.openkeyOrigin, type: "openkey-approval-request", id: created.data.id, key: prepared.key, bodyCid: prepared.bodyCid })
14808
+ };
14809
+ }
13463
14810
  async function deleteLink(input) {
13464
14811
  const apiOrigin = checkApiOrigin(input.apiOrigin);
13465
14812
  const id = normalizeLinkId(input.id);
@@ -13524,9 +14871,20 @@ async function resolveLink(link4, input) {
13524
14871
  } else if (opened.type !== "share") {
13525
14872
  throw new LinkError("full_non_share");
13526
14873
  }
14874
+ if (opened.type === "openkey-approval-request") {
14875
+ if (opened.header.audience !== input.apiOrigin) throw new LinkError("audience_mismatch");
14876
+ parseApprovalRequest(opened.value, { issuer: opened.header.issuer });
14877
+ }
13527
14878
  await runBodyValidator(opened, input.validateBody);
13528
14879
  return { ...opened, form: parsed.form, id: parsed.form === "short" ? parsed.id : void 0 };
13529
14880
  }
14881
+ async function resolveApprovalRequest(link4, input) {
14882
+ const opened = await resolveLink(link4, input);
14883
+ if (opened.type !== "openkey-approval-request") throw new LinkError("type_path_mismatch");
14884
+ if (opened.header.audience !== input.apiOrigin) throw new LinkError("audience_mismatch");
14885
+ const request = parseApprovalRequest(opened.value, { issuer: opened.header.issuer });
14886
+ return { ...opened, request };
14887
+ }
13530
14888
  function shortShareLinkCid(href, options) {
13531
14889
  try {
13532
14890
  const parsed = parseLink(href, { trustedOrigins: options.trustedOrigins });
@@ -13569,7 +14927,7 @@ function signerFromJwk(jwk) {
13569
14927
  if (signer.did !== didKeyFromEd25519PublicKey(publicKey)) throw new LinkError("invalid_argument", "the JWK public key does not match its private key");
13570
14928
  return signer;
13571
14929
  }
13572
- var SHA256_CODE2, ENVELOPE_AAD_LABEL2, SEALED_BLOB_VERSION, AAD2, KEY_LENGTH, NONCE_LENGTH, TAG_LENGTH, HEADER_LENGTH, LINK_TYPES, MAX_LINK_BODY_BYTES, MAX_LINK_REQUEST_BYTES, LINK_TYPE_SPECS, LINK_HEADER_DOMAIN, LINK_DELETE_DOMAIN, LINK_WINDOW_SECONDS, LINK_MIN_LIFE_SECONDS, LINK_MIN_BODY_BYTES, LINK_SEAL_OVERHEAD_BYTES, LINK_MAX_RECORD_HEADER_BYTES, DEFAULT_LINKS_API_ORIGIN, FULL_LINK_PATH, LINK_ID_PATTERN, LinkError, ED25519_MULTICODEC_PREFIX2, PUBLIC_KEY_LENGTH, ExtendedPoint, GROUP_ORDER, FIELD_PRIME, DID_KEY_PATTERN, SERVICE_ISSUER_PATTERN, AUDIENCE_PATTERN, TIMESTAMP_PATTERN, NONCE_PATTERN, CID_PATTERN, HEADER_KEYS, DELETE_KEYS, ed25519DidKey, linkTypeSchema, linkHeaderV1Schema, linkSignatureV1Schema, linkDeleteRequestV1Schema, LINK_FRAGMENT_VERSION, SHORT_PATH, SHORT_FRAGMENT, FULL_FRAGMENT, REMOVED_FRAGMENT, MAX_FULL_RECORD_JSON_BYTES, jsonObject, DEFAULT_TIMEOUT_MS, MAX_JSON_RESPONSE_BYTES, AUDIENCE_ORIGIN, createdSchema, errorBodySchema, KEY_PARAMETER, DEFAULT_SHARE_ORIGINS;
14930
+ var SHA256_CODE2, ENVELOPE_AAD_LABEL2, SEALED_BLOB_VERSION, AAD2, KEY_LENGTH, NONCE_LENGTH, TAG_LENGTH, HEADER_LENGTH, LINK_TYPES, MAX_LINK_BODY_BYTES, MAX_LINK_REQUEST_BYTES, LINK_TYPE_SPECS, LINK_HEADER_DOMAIN, LINK_DELETE_DOMAIN, LINK_WINDOW_SECONDS, LINK_MIN_LIFE_SECONDS, LINK_MIN_BODY_BYTES, LINK_SEAL_OVERHEAD_BYTES, LINK_MAX_RECORD_HEADER_BYTES, DEFAULT_LINKS_API_ORIGIN, FULL_LINK_PATH, LINK_ID_PATTERN, LinkError, ED25519_MULTICODEC_PREFIX2, PUBLIC_KEY_LENGTH, ExtendedPoint, GROUP_ORDER, FIELD_PRIME, DID_KEY_PATTERN, SERVICE_ISSUER_PATTERN, AUDIENCE_PATTERN, TIMESTAMP_PATTERN, NONCE_PATTERN, CID_PATTERN, HEADER_KEYS, DELETE_KEYS, ed25519DidKey, linkTypeSchema, linkHeaderV1Schema, linkSignatureV1Schema, linkDeleteRequestV1Schema, LINK_FRAGMENT_VERSION, SHORT_PATH, SHORT_FRAGMENT, FULL_FRAGMENT, REMOVED_FRAGMENT, MAX_FULL_RECORD_JSON_BYTES, jsonObject, bytes32, ed25519Jwk, p256Jwk, origin, permission, requestSchema, DEFAULT_TIMEOUT_MS, MAX_JSON_RESPONSE_BYTES, AUDIENCE_ORIGIN, createdSchema, errorBodySchema, KEY_PARAMETER, DEFAULT_SHARE_ORIGINS;
13573
14931
  var init_links = __esm({
13574
14932
  "../share-envelope/dist/links.js"() {
13575
14933
  "use strict";
@@ -13584,6 +14942,8 @@ var init_links = __esm({
13584
14942
  init_base58();
13585
14943
  init_ed25519();
13586
14944
  init_zod();
14945
+ init_p256();
14946
+ init_zod();
13587
14947
  init_ed25519();
13588
14948
  SHA256_CODE2 = 18;
13589
14949
  ENVELOPE_AAD_LABEL2 = "tinycloud-share-envelope-v1";
@@ -13593,11 +14953,12 @@ var init_links = __esm({
13593
14953
  NONCE_LENGTH = 12;
13594
14954
  TAG_LENGTH = 16;
13595
14955
  HEADER_LENGTH = 1;
13596
- LINK_TYPES = ["openkey-login", "courier", "share"];
14956
+ LINK_TYPES = ["openkey-login", "openkey-approval-request", "courier", "share"];
13597
14957
  MAX_LINK_BODY_BYTES = 65536;
13598
14958
  MAX_LINK_REQUEST_BYTES = Math.ceil(MAX_LINK_BODY_BYTES * 4 / 3) + 3072;
13599
14959
  LINK_TYPE_SPECS = {
13600
14960
  "openkey-login": { maxLifeSeconds: 600, defaultLifeSeconds: 600, pathLetter: "l", readOnce: true },
14961
+ "openkey-approval-request": { maxLifeSeconds: 86400, defaultLifeSeconds: 3600, pathLetter: "a", readOnce: false },
13601
14962
  courier: { maxLifeSeconds: 604800, defaultLifeSeconds: 86400, pathLetter: "c", readOnce: false },
13602
14963
  share: { maxLifeSeconds: 2592e3, defaultLifeSeconds: 2592e3, pathLetter: "s", readOnce: false }
13603
14964
  };
@@ -13668,12 +15029,52 @@ var init_links = __esm({
13668
15029
  nonce: external_exports2.string()
13669
15030
  }).strict();
13670
15031
  LINK_FRAGMENT_VERSION = 4;
13671
- SHORT_PATH = /^\/(s|c|l)\/([A-Za-z2-7]{26})$/;
15032
+ SHORT_PATH = /^\/(s|c|l|a)\/([A-Za-z2-7]{26})$/;
13672
15033
  SHORT_FRAGMENT = /^#v=4&k=([A-Za-z0-9_-]{43})&c=(bafkrei[a-z2-7]{52})$/;
13673
15034
  FULL_FRAGMENT = /^#v=4&k=([A-Za-z0-9_-]{43})&r=([A-Za-z0-9_-]+)$/;
13674
15035
  REMOVED_FRAGMENT = /^#v=[23](&|$)/;
13675
15036
  MAX_FULL_RECORD_JSON_BYTES = MAX_LINK_REQUEST_BYTES;
13676
15037
  jsonObject = external_exports2.record(external_exports2.unknown());
15038
+ bytes32 = external_exports2.string().refine((value) => decodeStrictBase64Url(value)?.length === 32);
15039
+ ed25519Jwk = external_exports2.object({ kty: external_exports2.literal("OKP"), crv: external_exports2.literal("Ed25519"), x: bytes32 }).strict();
15040
+ p256Jwk = external_exports2.object({ kty: external_exports2.literal("EC"), crv: external_exports2.literal("P-256"), x: bytes32, y: bytes32 }).strict().refine((key) => {
15041
+ try {
15042
+ const point = new Uint8Array(65);
15043
+ point[0] = 4;
15044
+ point.set(decodeStrictBase64Url(key.x), 1);
15045
+ point.set(decodeStrictBase64Url(key.y), 33);
15046
+ p2562.ProjectivePoint.fromHex(point).assertValidity();
15047
+ return true;
15048
+ } catch {
15049
+ return false;
15050
+ }
15051
+ });
15052
+ origin = external_exports2.string().refine((value) => {
15053
+ try {
15054
+ const url = new URL(value);
15055
+ return url.origin === value && (url.protocol === "https:" || url.protocol === "http:" && ["127.0.0.1", "localhost", "[::1]"].includes(url.hostname));
15056
+ } catch {
15057
+ return false;
15058
+ }
15059
+ });
15060
+ permission = external_exports2.object({
15061
+ service: external_exports2.string().min(1),
15062
+ space: external_exports2.string().min(1),
15063
+ path: external_exports2.string(),
15064
+ actions: external_exports2.array(external_exports2.string().min(1)).min(1),
15065
+ caveats: external_exports2.array(external_exports2.unknown()).optional()
15066
+ }).strict();
15067
+ requestSchema = external_exports2.object({
15068
+ issuer: external_exports2.string(),
15069
+ requestVersion: external_exports2.literal(1),
15070
+ targetDid: external_exports2.string(),
15071
+ targetPublicJwk: ed25519Jwk,
15072
+ nodeOrigin: origin,
15073
+ permissions: external_exports2.array(permission).min(1),
15074
+ reason: external_exports2.string().optional(),
15075
+ grantLifetimeSeconds: external_exports2.number().int().positive(),
15076
+ resultEncryptionPublicJwk: p256Jwk
15077
+ }).strict();
13677
15078
  DEFAULT_TIMEOUT_MS = 1e4;
13678
15079
  MAX_JSON_RESPONSE_BYTES = 4096;
13679
15080
  AUDIENCE_ORIGIN = /^https:\/\/[a-z0-9]([a-z0-9.-]*[a-z0-9])?(:[0-9]{1,5})?$/;
@@ -13798,6 +15199,7 @@ init_profiles();
13798
15199
 
13799
15200
  // src/commands/share.ts
13800
15201
  import { Option } from "commander";
15202
+ import { readFile as readFile8 } from "fs/promises";
13801
15203
  import { CLI_NAME as CLI_NAME12 } from "@tinycloud/operations/cli-name";
13802
15204
 
13803
15205
  // ../share-sdk/dist/artifact.js
@@ -18984,6 +20386,23 @@ var unifiedEncryptionNetworkSchema = external_exports.string().refine((value) =>
18984
20386
  const network = separator < 0 ? "" : rest.slice(separator + 1);
18985
20387
  return owner.startsWith("did:") && owner.length > 4 && network.length > 0 && !/[:/%?#\s]/.test(network);
18986
20388
  }, { message: "expected canonical TinyCloud encryption network" });
20389
+ var unifiedEncryptionResourceSchema = external_exports.string().refine((value) => {
20390
+ const prefix = "urn:tinycloud:encryption:";
20391
+ if (!value.startsWith(prefix)) return false;
20392
+ const match = /^(did:.+):([^/:?#\s]+)(?:\/(.+))?$/.exec(value.slice(prefix.length));
20393
+ if (match === null) return false;
20394
+ const path = match[3];
20395
+ return path === void 0 || path.split("/").every(
20396
+ (segment) => segment.length > 0 && segment !== "." && segment !== ".." && !/[\\:%?#\s]/.test(segment)
20397
+ );
20398
+ }, { message: "expected a canonical TinyCloud encryption resource" });
20399
+ var unifiedEncryptionKeyPathSchema = external_exports.string().regex(/^share\/[^/]+$/).refine(
20400
+ (value) => {
20401
+ const segment = value.slice("share/".length);
20402
+ return segment !== "." && segment !== ".." && !/[\\:%?#\s]/.test(segment);
20403
+ },
20404
+ { message: "expected an exact share key path" }
20405
+ );
18987
20406
  var unifiedKvCapabilitySchema = external_exports.object({
18988
20407
  kind: external_exports.literal("kv"),
18989
20408
  resource: unifiedResourceSchema,
@@ -18997,7 +20416,7 @@ var unifiedKvCapabilitySchema = external_exports.object({
18997
20416
  }).strict();
18998
20417
  var unifiedEncryptionCapabilitySchema = external_exports.object({
18999
20418
  kind: external_exports.literal("encryption"),
19000
- resource: unifiedEncryptionNetworkSchema,
20419
+ resource: unifiedEncryptionResourceSchema,
19001
20420
  action: external_exports.literal("tinycloud.encryption/decrypt")
19002
20421
  }).strict();
19003
20422
  var unifiedCapabilitySchema = external_exports.union([unifiedKvCapabilitySchema, unifiedEncryptionCapabilitySchema]);
@@ -19006,6 +20425,7 @@ var unifiedContentSourceSchema = external_exports.object({
19006
20425
  kvResource: unifiedResourceSchema,
19007
20426
  selector: external_exports.union([external_exports.literal("exact"), external_exports.literal("prefix")]),
19008
20427
  encryptionNetwork: unifiedEncryptionNetworkSchema,
20428
+ encryptionKeyPath: unifiedEncryptionKeyPathSchema.optional(),
19009
20429
  encryptedSymmetricKeyDigestHex: external_exports.string().regex(/^[0-9a-f]{64}$/),
19010
20430
  keyVersion: external_exports.number().int().positive(),
19011
20431
  mode: external_exports.union([external_exports.literal("mutable"), external_exports.literal("immutable")]),
@@ -19123,16 +20543,21 @@ function validateV3Invariants(value, ctx) {
19123
20543
  if (value.attestedEnforcerBinding.nodeAudience !== value.target.nodeAudience || value.attestedEnforcerBinding.signature.signerDid !== value.attestedEnforcerBinding.nodeAudience || Date.parse(value.attestedEnforcerBinding.expiresAt) < Date.parse(value.expiry)) {
19124
20544
  ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["attestedEnforcerBinding"], message: "enforcer binding does not cover the target and share lifetime" });
19125
20545
  }
19126
- if (value.policy.contentSource.shareId !== value.contentSource.shareId || value.policy.contentSource.kvResource !== value.contentSource.kvResource || value.policy.contentSource.selector !== value.contentSource.selector || value.policy.contentSource.encryptionNetwork !== value.encryptionNetwork || value.policy.contentSource.encryptedSymmetricKeyDigestHex !== value.contentSource.encryptedSymmetricKeyDigestHex || value.policy.contentSource.keyVersion !== value.contentSource.keyVersion || value.policy.contentSource.mode !== value.contentSource.mode || value.policy.contentSource.initialCiphertextDigestHex !== value.contentSource.initialCiphertextDigestHex) {
20546
+ const encryptionKeyPath = value.contentSource.encryptionKeyPath;
20547
+ if (encryptionKeyPath !== void 0 && encryptionKeyPath !== `share/${value.contentSource.shareId}`) {
20548
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["contentSource", "encryptionKeyPath"], message: "share key path must name this share" });
20549
+ }
20550
+ if (value.policy.contentSource.shareId !== value.contentSource.shareId || value.policy.contentSource.kvResource !== value.contentSource.kvResource || value.policy.contentSource.selector !== value.contentSource.selector || value.policy.contentSource.encryptionNetwork !== value.encryptionNetwork || value.policy.contentSource.encryptionKeyPath !== encryptionKeyPath || value.policy.contentSource.encryptedSymmetricKeyDigestHex !== value.contentSource.encryptedSymmetricKeyDigestHex || value.policy.contentSource.keyVersion !== value.contentSource.keyVersion || value.policy.contentSource.mode !== value.contentSource.mode || value.policy.contentSource.initialCiphertextDigestHex !== value.contentSource.initialCiphertextDigestHex) {
19127
20551
  ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["contentSource"], message: "content source is not bound to policy" });
19128
20552
  }
19129
20553
  if (value.policy.signature.suite !== "Ed25519" || value.policy.signature.signerDid !== value.policy.ownerDid) {
19130
20554
  ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["policy", "signature"], message: "policy must be signed by its owner" });
19131
20555
  }
19132
20556
  const kvCapabilities = value.policy.capabilityCeiling.filter((capability) => capability.kind === "kv");
19133
- const decryptCapabilities = value.policy.capabilityCeiling.filter((capability) => capability.kind === "encryption" && capability.resource === value.encryptionNetwork && capability.action === "tinycloud.encryption/decrypt");
20557
+ const expectedEncryptionResource = encryptionKeyPath === void 0 ? value.encryptionNetwork : `${value.encryptionNetwork}/${encryptionKeyPath}`;
20558
+ const decryptCapabilities = value.policy.capabilityCeiling.filter((capability) => capability.kind === "encryption" && capability.resource === expectedEncryptionResource && capability.action === "tinycloud.encryption/decrypt");
19134
20559
  if (value.policy.capabilityCeiling.length !== 2 || kvCapabilities.length !== 1 || decryptCapabilities.length !== 1 || kvCapabilities[0]?.resource !== value.contentSource.kvResource || kvCapabilities[0]?.selector !== value.contentSource.selector) {
19135
- ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["policy", "capabilityCeiling"], message: "policy ceiling must contain exact decrypt network" });
20560
+ ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["policy", "capabilityCeiling"], message: "policy ceiling must contain the exact decrypt resource" });
19136
20561
  }
19137
20562
  }
19138
20563
  var unsignedShareEnvelopeV3Schema = unsignedShareEnvelopeV3BaseSchema.superRefine(validateV3Invariants);
@@ -24635,6 +26060,23 @@ var unifiedEncryptionNetworkSchema2 = external_exports3.string().refine((value)
24635
26060
  const network = separator < 0 ? "" : rest.slice(separator + 1);
24636
26061
  return owner.startsWith("did:") && owner.length > 4 && network.length > 0 && !/[:/%?#\s]/.test(network);
24637
26062
  }, { message: "expected canonical TinyCloud encryption network" });
26063
+ var unifiedEncryptionResourceSchema2 = external_exports3.string().refine((value) => {
26064
+ const prefix = "urn:tinycloud:encryption:";
26065
+ if (!value.startsWith(prefix)) return false;
26066
+ const match = /^(did:.+):([^/:?#\s]+)(?:\/(.+))?$/.exec(value.slice(prefix.length));
26067
+ if (match === null) return false;
26068
+ const path = match[3];
26069
+ return path === void 0 || path.split("/").every(
26070
+ (segment) => segment.length > 0 && segment !== "." && segment !== ".." && !/[\\:%?#\s]/.test(segment)
26071
+ );
26072
+ }, { message: "expected a canonical TinyCloud encryption resource" });
26073
+ var unifiedEncryptionKeyPathSchema2 = external_exports3.string().regex(/^share\/[^/]+$/).refine(
26074
+ (value) => {
26075
+ const segment = value.slice("share/".length);
26076
+ return segment !== "." && segment !== ".." && !/[\\:%?#\s]/.test(segment);
26077
+ },
26078
+ { message: "expected an exact share key path" }
26079
+ );
24638
26080
  var unifiedKvCapabilitySchema2 = external_exports3.object({
24639
26081
  kind: external_exports3.literal("kv"),
24640
26082
  resource: unifiedResourceSchema2,
@@ -24648,7 +26090,7 @@ var unifiedKvCapabilitySchema2 = external_exports3.object({
24648
26090
  }).strict();
24649
26091
  var unifiedEncryptionCapabilitySchema2 = external_exports3.object({
24650
26092
  kind: external_exports3.literal("encryption"),
24651
- resource: unifiedEncryptionNetworkSchema2,
26093
+ resource: unifiedEncryptionResourceSchema2,
24652
26094
  action: external_exports3.literal("tinycloud.encryption/decrypt")
24653
26095
  }).strict();
24654
26096
  var unifiedCapabilitySchema2 = external_exports3.union([unifiedKvCapabilitySchema2, unifiedEncryptionCapabilitySchema2]);
@@ -24657,6 +26099,7 @@ var unifiedContentSourceSchema2 = external_exports3.object({
24657
26099
  kvResource: unifiedResourceSchema2,
24658
26100
  selector: external_exports3.union([external_exports3.literal("exact"), external_exports3.literal("prefix")]),
24659
26101
  encryptionNetwork: unifiedEncryptionNetworkSchema2,
26102
+ encryptionKeyPath: unifiedEncryptionKeyPathSchema2.optional(),
24660
26103
  encryptedSymmetricKeyDigestHex: external_exports3.string().regex(/^[0-9a-f]{64}$/),
24661
26104
  keyVersion: external_exports3.number().int().positive(),
24662
26105
  mode: external_exports3.union([external_exports3.literal("mutable"), external_exports3.literal("immutable")]),
@@ -24774,16 +26217,21 @@ function validateV3Invariants2(value, ctx) {
24774
26217
  if (value.attestedEnforcerBinding.nodeAudience !== value.target.nodeAudience || value.attestedEnforcerBinding.signature.signerDid !== value.attestedEnforcerBinding.nodeAudience || Date.parse(value.attestedEnforcerBinding.expiresAt) < Date.parse(value.expiry)) {
24775
26218
  ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["attestedEnforcerBinding"], message: "enforcer binding does not cover the target and share lifetime" });
24776
26219
  }
24777
- if (value.policy.contentSource.shareId !== value.contentSource.shareId || value.policy.contentSource.kvResource !== value.contentSource.kvResource || value.policy.contentSource.selector !== value.contentSource.selector || value.policy.contentSource.encryptionNetwork !== value.encryptionNetwork || value.policy.contentSource.encryptedSymmetricKeyDigestHex !== value.contentSource.encryptedSymmetricKeyDigestHex || value.policy.contentSource.keyVersion !== value.contentSource.keyVersion || value.policy.contentSource.mode !== value.contentSource.mode || value.policy.contentSource.initialCiphertextDigestHex !== value.contentSource.initialCiphertextDigestHex) {
26220
+ const encryptionKeyPath = value.contentSource.encryptionKeyPath;
26221
+ if (encryptionKeyPath !== void 0 && encryptionKeyPath !== `share/${value.contentSource.shareId}`) {
26222
+ ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["contentSource", "encryptionKeyPath"], message: "share key path must name this share" });
26223
+ }
26224
+ if (value.policy.contentSource.shareId !== value.contentSource.shareId || value.policy.contentSource.kvResource !== value.contentSource.kvResource || value.policy.contentSource.selector !== value.contentSource.selector || value.policy.contentSource.encryptionNetwork !== value.encryptionNetwork || value.policy.contentSource.encryptionKeyPath !== encryptionKeyPath || value.policy.contentSource.encryptedSymmetricKeyDigestHex !== value.contentSource.encryptedSymmetricKeyDigestHex || value.policy.contentSource.keyVersion !== value.contentSource.keyVersion || value.policy.contentSource.mode !== value.contentSource.mode || value.policy.contentSource.initialCiphertextDigestHex !== value.contentSource.initialCiphertextDigestHex) {
24778
26225
  ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["contentSource"], message: "content source is not bound to policy" });
24779
26226
  }
24780
26227
  if (value.policy.signature.suite !== "Ed25519" || value.policy.signature.signerDid !== value.policy.ownerDid) {
24781
26228
  ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["policy", "signature"], message: "policy must be signed by its owner" });
24782
26229
  }
24783
26230
  const kvCapabilities = value.policy.capabilityCeiling.filter((capability) => capability.kind === "kv");
24784
- const decryptCapabilities = value.policy.capabilityCeiling.filter((capability) => capability.kind === "encryption" && capability.resource === value.encryptionNetwork && capability.action === "tinycloud.encryption/decrypt");
26231
+ const expectedEncryptionResource = encryptionKeyPath === void 0 ? value.encryptionNetwork : `${value.encryptionNetwork}/${encryptionKeyPath}`;
26232
+ const decryptCapabilities = value.policy.capabilityCeiling.filter((capability) => capability.kind === "encryption" && capability.resource === expectedEncryptionResource && capability.action === "tinycloud.encryption/decrypt");
24785
26233
  if (value.policy.capabilityCeiling.length !== 2 || kvCapabilities.length !== 1 || decryptCapabilities.length !== 1 || kvCapabilities[0]?.resource !== value.contentSource.kvResource || kvCapabilities[0]?.selector !== value.contentSource.selector) {
24786
- ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["policy", "capabilityCeiling"], message: "policy ceiling must contain exact decrypt network" });
26234
+ ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["policy", "capabilityCeiling"], message: "policy ceiling must contain the exact decrypt resource" });
24787
26235
  }
24788
26236
  }
24789
26237
  var unsignedShareEnvelopeV3Schema2 = unsignedShareEnvelopeV3BaseSchema2.superRefine(validateV3Invariants2);
@@ -24793,6 +26241,7 @@ var SEALED_BLOB_VERSION2 = 1;
24793
26241
  var AAD3 = utf8Bytes3(ENVELOPE_AAD_LABEL3);
24794
26242
  var KEY_LENGTH2 = 32;
24795
26243
  var NONCE_LENGTH2 = 12;
26244
+ var TAG_LENGTH2 = 16;
24796
26245
  var HEADER_LENGTH2 = 1;
24797
26246
  function assertKey3(key32) {
24798
26247
  if (key32.length !== KEY_LENGTH2) {
@@ -24820,6 +26269,17 @@ async function seal2(plaintextBytes, key32) {
24820
26269
  blob.set(ciphertext, HEADER_LENGTH2 + nonce.length);
24821
26270
  return { blob, cid: await computeCid2(blob) };
24822
26271
  }
26272
+ async function open7(blob, key32) {
26273
+ if (blob.length < HEADER_LENGTH2 + NONCE_LENGTH2 + TAG_LENGTH2) {
26274
+ throw new TypeError(`sealed blob too short: ${blob.length} bytes`);
26275
+ }
26276
+ if (blob[0] !== SEALED_BLOB_VERSION2) {
26277
+ throw new TypeError(`unknown sealed blob version: ${blob[0]}`);
26278
+ }
26279
+ const nonce = blob.subarray(HEADER_LENGTH2, HEADER_LENGTH2 + NONCE_LENGTH2);
26280
+ const ciphertext = blob.subarray(HEADER_LENGTH2 + NONCE_LENGTH2);
26281
+ return decryptEnvelope2(nonce, ciphertext, key32);
26282
+ }
24823
26283
  async function encryptEnvelope2(plaintextBytes, key32) {
24824
26284
  const key = await importAesKey2(key32, "encrypt");
24825
26285
  const nonce = globalThis.crypto.getRandomValues(new Uint8Array(NONCE_LENGTH2));
@@ -24832,6 +26292,19 @@ async function encryptEnvelope2(plaintextBytes, key32) {
24832
26292
  );
24833
26293
  return { nonce, ciphertext };
24834
26294
  }
26295
+ async function decryptEnvelope2(nonce, ciphertext, key32) {
26296
+ if (nonce.length !== NONCE_LENGTH2) {
26297
+ throw new TypeError(`nonce must be ${NONCE_LENGTH2} bytes, got ${nonce.length}`);
26298
+ }
26299
+ const key = await importAesKey2(key32, "decrypt");
26300
+ return new Uint8Array(
26301
+ await globalThis.crypto.subtle.decrypt(
26302
+ { name: "AES-GCM", iv: nonce, additionalData: AAD3 },
26303
+ key,
26304
+ ciphertext
26305
+ )
26306
+ );
26307
+ }
24835
26308
  function isPlainRecord3(value) {
24836
26309
  const proto = Object.getPrototypeOf(value);
24837
26310
  return proto === Object.prototype || proto === null;
@@ -24946,6 +26419,7 @@ function equal(left, right) {
24946
26419
  return left.length === right.length && left.every((byte, index) => byte === right[index]);
24947
26420
  }
24948
26421
  var ED25519_VERIFY_OPTS2 = { zip215: false };
26422
+ var ENVELOPE_V2_SIGNATURE_DOMAIN = "xyz.tinycloud.share/envelope/v2\0";
24949
26423
  var ENVELOPE_V3_SIGNATURE_DOMAIN = "xyz.tinycloud.share/envelope/v3\0";
24950
26424
  var POLICY_V1_SIGNATURE_DOMAIN = "xyz.tinycloud.policy/policy/v1\0";
24951
26425
  var POLICY_V2_SIGNATURE_DOMAIN = "xyz.tinycloud.policy/policy/v2\0";
@@ -24953,6 +26427,14 @@ var CONTENT_SOURCE_V1_DOMAIN = "xyz.tinycloud.policy/ContentSource/v1\0";
24953
26427
  var POLICY_CAPABILITY_V1_DOMAIN = "xyz.tinycloud.policy/PolicyCapability/v1\0";
24954
26428
  var NATIVE_PROJECTION_V1_DOMAIN = "xyz.tinycloud.policy/NativeProjection/v1\0";
24955
26429
  var ATTESTED_ENFORCER_V2_DOMAIN = "xyz.tinycloud.policy/AttestedEnforcerBinding/v2\0";
26430
+ function signingBytesV2(unsigned) {
26431
+ const domain = utf8Bytes3(ENVELOPE_V2_SIGNATURE_DOMAIN);
26432
+ const body = utf8Bytes3(canonicalize3(unsigned));
26433
+ const bytes3 = new Uint8Array(domain.length + body.length);
26434
+ bytes3.set(domain);
26435
+ bytes3.set(body, domain.length);
26436
+ return bytes3;
26437
+ }
24956
26438
  function signingBytesV3(unsigned) {
24957
26439
  const domain = utf8Bytes3(ENVELOPE_V3_SIGNATURE_DOMAIN);
24958
26440
  const body = utf8Bytes3(canonicalize3(unsigned));
@@ -24961,6 +26443,17 @@ function signingBytesV3(unsigned) {
24961
26443
  bytes3.set(body, domain.length);
24962
26444
  return bytes3;
24963
26445
  }
26446
+ function verifyEnvelopeV2SignatureOnly(envelope) {
26447
+ const parsed = shareEnvelopeV2Schema2.parse(envelope);
26448
+ const { signature, ...unsigned } = parsed;
26449
+ return ed25519.verify(fromBase64Url3(signature.value), signingBytesV2(unsigned), ed25519PublicKeyFromDidKey2(signature.signerDid), ED25519_VERIFY_OPTS2);
26450
+ }
26451
+ async function verifyEnvelopeV2(envelope, options) {
26452
+ const parsed = shareEnvelopeV2Schema2.parse(envelope);
26453
+ if (parsed.signature.signerDid !== options.expectedSignerDid || !verifyEnvelopeV2SignatureOnly(parsed)) return false;
26454
+ if (parsed.authorizationTarget.kind === "policy") return await computeCid2(fromBase64Url3(parsed.authorizationTarget.policyBytes)) === parsed.authorizationTarget.policyCid;
26455
+ return true;
26456
+ }
24964
26457
  function verifyEnvelopeV3SignatureOnly(envelope) {
24965
26458
  const parsed = shareEnvelopeV3Schema2.parse(envelope);
24966
26459
  const { signature, ...unsigned } = parsed;
@@ -25047,6 +26540,52 @@ function base32Lower(bytes3) {
25047
26540
  if (bits > 0) output += alphabet[buffer << 5 - bits & 31];
25048
26541
  return output;
25049
26542
  }
26543
+ var KEY_LENGTH22 = 32;
26544
+ function assertCanonicalCid(cidString) {
26545
+ const cid2 = CID3.parse(cidString);
26546
+ if (cid2.version !== 1 || cid2.code !== code3 || cid2.multihash.code !== 18 || // sha2-256 (0x12) only, at the link layer too
26547
+ cid2.toString() !== cidString) {
26548
+ throw new TypeError(`not a canonical CIDv1 raw sha2-256 base32 CID: ${cidString}`);
26549
+ }
26550
+ }
26551
+ function parseShareUrl(url, options = {}) {
26552
+ const parsed = new URL(url);
26553
+ if (parsed.protocol !== "https:") {
26554
+ throw new TypeError(`share URL must be https, got ${parsed.protocol}`);
26555
+ }
26556
+ if (parsed.username !== "" || parsed.password !== "") {
26557
+ throw new TypeError("share URL must not carry userinfo");
26558
+ }
26559
+ if (parsed.search !== "") {
26560
+ throw new TypeError("share URL must not have a query string");
26561
+ }
26562
+ if (options.expectedOrigin !== void 0) {
26563
+ if (!isCanonicalHttpsOrigin2(options.expectedOrigin)) {
26564
+ throw new TypeError(
26565
+ `expectedOrigin must be a canonical https origin, got ${options.expectedOrigin}`
26566
+ );
26567
+ }
26568
+ if (parsed.origin !== options.expectedOrigin) {
26569
+ throw new TypeError(
26570
+ `share URL origin ${parsed.origin} does not match expected ${options.expectedOrigin}`
26571
+ );
26572
+ }
26573
+ }
26574
+ const match = /^\/s\/([a-z2-7]+)$/.exec(parsed.pathname);
26575
+ if (!match || match[1] === void 0) {
26576
+ throw new TypeError(`not a share URL path: ${parsed.pathname}`);
26577
+ }
26578
+ const ciphertextCid = match[1];
26579
+ assertCanonicalCid(ciphertextCid);
26580
+ if (!parsed.hash.startsWith("#k=")) {
26581
+ throw new TypeError("share URL is missing the #k= key fragment");
26582
+ }
26583
+ const key32 = fromBase64Url3(parsed.hash.slice("#k=".length));
26584
+ if (key32.length !== KEY_LENGTH22) {
26585
+ throw new TypeError(`fragment key must be ${KEY_LENGTH22} bytes, got ${key32.length}`);
26586
+ }
26587
+ return { ciphertextCid, key32 };
26588
+ }
25050
26589
  var ARTIFACT_ROOT2 = "artifacts";
25051
26590
  function parseArtifactVersionPath2(path) {
25052
26591
  const match = /^artifacts\/([a-z0-9][a-z0-9_-]{2,62})\/versions\/([1-9][0-9]{0,14})\/([^/]+)$/.exec(path);
@@ -25123,6 +26662,7 @@ function verifyArtifactShare(envelope, options) {
25123
26662
  }
25124
26663
  var SHARE_RESULT_VERSION = 1;
25125
26664
  var DEFAULT_MAX_SEALED_BLOB_BYTES = 100 * 1024 * 1024 + 29;
26665
+ var DEFAULT_MAX_CONTENT_BLOB_BYTES = DEFAULT_MAX_SEALED_BLOB_BYTES;
25126
26666
  var ShareReceiveError = class extends Error {
25127
26667
  code;
25128
26668
  details;
@@ -25136,13 +26676,13 @@ var ShareReceiveError = class extends Error {
25136
26676
  return { protocol: "tinycloud-share", version: SHARE_RESULT_VERSION, error: { code: this.code } };
25137
26677
  }
25138
26678
  };
25139
- function metadataFor(envelope, origin) {
25140
- const kind = envelope.recipientMatcher.kind === "recipientDid" ? "recipientDid" : envelope.recipientMatcher.kind === "exactEmail" ? "email" : "emailDomain";
26679
+ function metadataFor(envelope, origin2) {
26680
+ const kind = envelope.recipientMatcher.kind === "recipientDid" ? "recipientDid" : envelope.recipientMatcher.kind === "exactEmail" ? "email" : envelope.recipientMatcher.kind === "emailDomain" ? "emailDomain" : "bearer";
25141
26681
  return {
25142
26682
  protocol: "tinycloud-share",
25143
26683
  version: 1,
25144
26684
  shareId: envelope.shareId,
25145
- origin,
26685
+ origin: origin2,
25146
26686
  target: { ...envelope.target, kind },
25147
26687
  resource: { ...envelope.resource },
25148
26688
  actions: [...envelope.actions],
@@ -25152,7 +26692,7 @@ function metadataFor(envelope, origin) {
25152
26692
  ...envelope.display.filename === void 0 ? {} : { filename: envelope.display.filename },
25153
26693
  ...envelope.display.mode === void 0 ? {} : { mode: envelope.display.mode }
25154
26694
  },
25155
- ...envelope.artifactPin === void 0 ? {} : { artifact: { id: envelope.artifactPin.artifactId, version: envelope.artifactPin.version } }
26695
+ ...envelope.version === 3 && envelope.artifactPin !== void 0 ? { artifact: { id: envelope.artifactPin.artifactId, version: envelope.artifactPin.version } } : {}
25156
26696
  };
25157
26697
  }
25158
26698
  function receiveErrorFor(error) {
@@ -25250,14 +26790,165 @@ async function resolvePolicyShare(link4, options) {
25250
26790
  options.onResolvedAddressedEnvelope?.(envelope, cid2);
25251
26791
  return { envelope, origin: url.origin, cid: cid2 };
25252
26792
  }
26793
+ async function resolveLegacyV2(link4, options) {
26794
+ let parsed;
26795
+ try {
26796
+ parsed = parseShareUrl(link4, { ...options.expectedOrigin === void 0 ? {} : { expectedOrigin: options.expectedOrigin } });
26797
+ } catch {
26798
+ throw new ShareReceiveError("invalid-link", "legacy share link format is invalid");
26799
+ }
26800
+ try {
26801
+ options.signal?.throwIfAborted();
26802
+ const origin2 = new URL(link4).origin;
26803
+ const limit = options.maxSealedBlobBytes ?? DEFAULT_MAX_SEALED_BLOB_BYTES;
26804
+ if (!Number.isSafeInteger(limit) || limit <= 0) throw new ShareReceiveError("max-bytes-exceeded", "sealed envelope limit is invalid");
26805
+ let sealed;
26806
+ if (options.fetchBlob !== void 0) {
26807
+ try {
26808
+ sealed = await options.fetchBlob({ origin: origin2, cid: parsed.ciphertextCid, ...options.signal === void 0 ? {} : { signal: options.signal } });
26809
+ } catch {
26810
+ throw new ShareReceiveError("fetch-failed", "legacy registry unavailable");
26811
+ }
26812
+ } else {
26813
+ if (options.registryBaseUrl === void 0) throw new ShareReceiveError("fetch-failed", "legacy registry is required");
26814
+ const response = await (options.fetch ?? globalThis.fetch)(`${options.registryBaseUrl.replace(/\/+$/, "")}/ipfs/${parsed.ciphertextCid}?format=raw`, {
26815
+ headers: { accept: "application/vnd.ipld.raw" },
26816
+ redirect: "error",
26817
+ ...options.signal === void 0 ? {} : { signal: options.signal }
26818
+ });
26819
+ if (!response.ok) throw new ShareReceiveError("fetch-failed", "legacy registry unavailable");
26820
+ if (Number(response.headers.get("content-length")) > limit) throw new ShareReceiveError("max-bytes-exceeded", "sealed envelope exceeds the size limit");
26821
+ const reader = response.body?.getReader();
26822
+ if (reader === void 0) throw new ShareReceiveError("fetch-failed", "legacy registry returned no body");
26823
+ const chunks = [];
26824
+ let length32 = 0;
26825
+ for (; ; ) {
26826
+ const part = await reader.read();
26827
+ if (part.done) break;
26828
+ length32 += part.value.length;
26829
+ if (length32 > limit) {
26830
+ await reader.cancel();
26831
+ throw new ShareReceiveError("max-bytes-exceeded", "sealed envelope exceeds the size limit");
26832
+ }
26833
+ chunks.push(part.value);
26834
+ }
26835
+ sealed = new Uint8Array(length32);
26836
+ let offset = 0;
26837
+ for (const chunk of chunks) {
26838
+ sealed.set(chunk, offset);
26839
+ offset += chunk.length;
26840
+ }
26841
+ }
26842
+ options.signal?.throwIfAborted();
26843
+ if (!(sealed instanceof Uint8Array) || sealed.length > limit) throw new ShareReceiveError("max-bytes-exceeded", "sealed envelope exceeds the size limit");
26844
+ if (await computeCid2(sealed) !== parsed.ciphertextCid) throw new ShareReceiveError("cid-mismatch", "legacy envelope CID does not match");
26845
+ let plaintext;
26846
+ try {
26847
+ plaintext = await open7(sealed, parsed.key32);
26848
+ } catch {
26849
+ throw new ShareReceiveError("decrypt-failed", "legacy envelope could not be opened");
26850
+ }
26851
+ let envelope;
26852
+ try {
26853
+ const encoded = new TextDecoder("utf-8", { fatal: true }).decode(plaintext);
26854
+ const value = JSON.parse(encoded);
26855
+ if (canonicalize3(value) !== encoded) throw new Error("non-canonical envelope");
26856
+ envelope = shareEnvelopeV2Schema2.parse(value);
26857
+ } catch {
26858
+ throw new ShareReceiveError("envelope-invalid", "legacy envelope is invalid");
26859
+ }
26860
+ return { envelope, origin: origin2, cid: parsed.ciphertextCid };
26861
+ } finally {
26862
+ parsed.key32.fill(0);
26863
+ }
26864
+ }
26865
+ function evidenceMatchesV2(envelope, evidence) {
26866
+ const actions = new Set(evidence.actions.map((action) => action === "read" ? "tinycloud.kv/get" : action === "list" ? "tinycloud.kv/list" : action === "edit" ? "tinycloud.kv/put" : action));
26867
+ const resourceCovers = evidence.resource.kind === "exact" ? envelope.resource.kind === "exact" && evidence.resource.path === envelope.resource.path : envelope.resource.path === evidence.resource.path || envelope.resource.path.startsWith(evidence.resource.path.endsWith("/") ? evidence.resource.path : `${evidence.resource.path}/`);
26868
+ return envelope.authorizationTarget.kind === "policy" && evidence.policyCid === envelope.authorizationTarget.policyCid && evidence.signerDid === envelope.signature.signerDid && evidence.registrationCid.length > 0 && evidence.shareId === envelope.shareId && canonicalize3(evidence.recipientMatcher) === canonicalize3(envelope.recipientMatcher) && canonicalize3(evidence.target) === canonicalize3(envelope.target) && resourceCovers && envelope.actions.every((action) => actions.has(action === "read" ? "tinycloud.kv/get" : action === "list" ? "tinycloud.kv/list" : "tinycloud.kv/put")) && canonicalize3(evidence.contentSource) === canonicalize3(envelope.contentSource) && evidence.contentSourceDigest === envelope.contentSourceDigest && evidence.delegationCid === envelope.delegationCid && evidence.authorityMaterialHandle === envelope.authorityMaterialHandle && evidence.authorityMaterialDigest === envelope.authorityMaterialDigest && evidence.expiresAt === envelope.expiry && Number.isFinite(Date.parse(evidence.expiresAt)) && Date.parse(evidence.expiresAt) === Date.parse(envelope.expiry);
26869
+ }
26870
+ async function verifyLegacyV2(envelope, options) {
26871
+ try {
26872
+ if (!await verifyEnvelopeV2(envelope, { expectedSignerDid: envelope.signature.signerDid })) throw new Error("signature");
26873
+ } catch {
26874
+ throw new ShareReceiveError("signature-invalid", "legacy envelope signature is invalid");
26875
+ }
26876
+ const expiry = Date.parse(envelope.expiry);
26877
+ if (!Number.isFinite(expiry)) throw new ShareReceiveError("envelope-invalid", "legacy share expiry is invalid");
26878
+ if (expiry <= (options.now?.() ?? Date.now())) throw new ShareReceiveError("expired", "legacy share has expired", { expiresAt: envelope.expiry });
26879
+ if (envelope.authorizationTarget.kind === "policy") {
26880
+ if (options.trustedPolicyAuthority === void 0) throw new ShareReceiveError("envelope-invalid", "a legacy policy authority is required");
26881
+ let evidence;
26882
+ try {
26883
+ evidence = await options.trustedPolicyAuthority.resolve({ policyCid: envelope.authorizationTarget.policyCid, envelope });
26884
+ } catch {
26885
+ }
26886
+ if (evidence === void 0 || !evidenceMatchesV2(envelope, evidence)) throw new ShareReceiveError("capability-invalid", "legacy policy evidence does not match");
26887
+ if (options.trustedSignerDid !== void 0 && options.trustedSignerDid !== evidence.signerDid) throw new ShareReceiveError("signature-invalid", "legacy signer is not trusted");
26888
+ } else if (options.trustedSignerDid === void 0 || options.trustedSignerDid !== envelope.signature.signerDid || envelope.authorizationTarget.kind === "recipientDid" && envelope.recipientMatcher.kind === "recipientDid" && envelope.authorizationTarget.did !== envelope.recipientMatcher.value) {
26889
+ throw new ShareReceiveError("capability-invalid", "legacy recipient authority does not match");
26890
+ }
26891
+ }
25253
26892
  async function inspectShare(link4, options = {}) {
26893
+ if (isLegacyV2Link(link4)) {
26894
+ const legacy = await resolveLegacyV2(link4, options);
26895
+ await verifyLegacyV2(legacy.envelope, options);
26896
+ options.onResolvedAddressedEnvelope?.(legacy.envelope, legacy.cid);
26897
+ return { metadata: metadataFor(legacy.envelope, legacy.origin), link: { origin: legacy.origin, cid: legacy.cid, kind: "compact" } };
26898
+ }
25254
26899
  const resolved = await resolvePolicyShare(link4, options);
25255
26900
  return { metadata: metadataFor(resolved.envelope, resolved.origin), link: { origin: resolved.origin, cid: resolved.cid, kind: "policy" } };
25256
26901
  }
25257
26902
  async function receiveShare(link4, options = {}) {
26903
+ if (isLegacyV2Link(link4)) return receiveLegacyV2(link4, options);
25258
26904
  const resolved = await resolvePolicyShare(link4, options);
25259
26905
  return { state: "authorization-required", method: resolved.envelope.recipientMatcher.kind === "recipientDid" ? "openkey-device" : "email-claim" };
25260
26906
  }
26907
+ function isLegacyV2Link(link4) {
26908
+ try {
26909
+ const url = new URL(link4);
26910
+ return /^\/s\/bafkrei[a-z2-7]{52}$/.test(url.pathname) && url.hash.startsWith("#k=");
26911
+ } catch {
26912
+ return false;
26913
+ }
26914
+ }
26915
+ async function receiveLegacyV2(link4, options) {
26916
+ const resolved = await resolveLegacyV2(link4, options);
26917
+ const { envelope } = resolved;
26918
+ await verifyLegacyV2(envelope, options);
26919
+ options.onResolvedAddressedEnvelope?.(envelope, resolved.cid);
26920
+ const method = envelope.recipientMatcher.kind === "recipientDid" ? "openkey-device" : "email-claim";
26921
+ if (options.authorization === void 0) return { state: "authorization-required", method };
26922
+ const result = options.authorizationResumeToken === void 0 ? await options.authorization.begin({ envelope, method }) : await options.authorization.resume({
26923
+ envelope,
26924
+ method,
26925
+ resumeToken: options.authorizationResumeToken,
26926
+ ...options.authorizationProof === void 0 ? {} : { proof: options.authorizationProof }
26927
+ });
26928
+ if (result.state === "authorization-required") return result;
26929
+ if (result.state === "denied") throw new ShareReceiveError("authorization-denied", "legacy share authorization was denied");
26930
+ if (result.value === null || typeof result.value !== "object" || !(result.value.bytes instanceof Uint8Array) || result.value.proof === void 0 || options.authorization.verifyResult === void 0) {
26931
+ throw new ShareReceiveError("content-integrity-failed", "legacy content lacks a verifiable proof");
26932
+ }
26933
+ const authorized = result.value;
26934
+ try {
26935
+ if (!await options.authorization.verifyResult({ envelope, value: authorized, proof: authorized.proof })) throw new Error("proof");
26936
+ } catch {
26937
+ throw new ShareReceiveError("content-integrity-failed", "legacy content proof is invalid");
26938
+ }
26939
+ const bytes3 = authorized.bytes.slice();
26940
+ if (bytes3.length > (options.maxContentBlobBytes ?? DEFAULT_MAX_CONTENT_BLOB_BYTES)) throw new ShareReceiveError("max-bytes-exceeded", "legacy content exceeds the size limit");
26941
+ const bodyDigest = toBase64Url2(new Uint8Array(await crypto.subtle.digest("SHA-256", bytes3)));
26942
+ if (authorized.bodyDigest !== bodyDigest || authorized.contentSourceDigest !== envelope.contentSourceDigest || authorized.binding.shareId !== envelope.shareId || authorized.binding.delegationCid !== envelope.delegationCid || authorized.binding.authorityMaterialHandle !== envelope.authorityMaterialHandle || authorized.binding.authorityMaterialDigest !== envelope.authorityMaterialDigest || authorized.binding.resource.kind !== envelope.resource.kind || authorized.binding.resource.path !== envelope.resource.path || authorized.binding.action !== void 0 && !envelope.actions.some((action) => action === authorized.binding.action || `tinycloud.kv/${action}` === authorized.binding.action) || envelope.metadata.byteLength !== void 0 && envelope.metadata.byteLength !== bytes3.length) {
26943
+ throw new ShareReceiveError("content-integrity-failed", "legacy content binding does not match");
26944
+ }
26945
+ let text;
26946
+ try {
26947
+ text = new TextDecoder("utf-8", { fatal: true }).decode(bytes3);
26948
+ } catch {
26949
+ }
26950
+ return { metadata: metadataFor(envelope, resolved.origin), link: { origin: resolved.origin, cid: resolved.cid, kind: "compact" }, bytes: bytes3, ...text === void 0 ? {} : { text } };
26951
+ }
25261
26952
  var SHARE_CONTENT_LIMIT = 100 * 1024 * 1024;
25262
26953
  var SHARE_PUBLISH_RESULT_VERSION = 1;
25263
26954
  var DEFAULT_SHARE_LIFETIME_MS = 7 * 24 * 60 * 60 * 1e3;
@@ -25745,7 +27436,10 @@ async function publishTargetShare(input) {
25745
27436
  expiresAt,
25746
27437
  expiryWasExplicit: input.expiryWasExplicit ?? input.expiresAt !== void 0,
25747
27438
  origin: input.origin,
25748
- ...input.notify === void 0 ? {} : { notify: input.notify }
27439
+ ...input.notify === void 0 ? {} : { notify: input.notify },
27440
+ ...input.credentialDescriptor === void 0 ? {} : { credentialDescriptor: input.credentialDescriptor },
27441
+ ...input.issuerDid === void 0 ? {} : { issuerDid: input.issuerDid },
27442
+ ...input.issuerKid === void 0 ? {} : { issuerKid: input.issuerKid }
25749
27443
  });
25750
27444
  }
25751
27445
  var POLICY_V1_DOMAIN = "xyz.tinycloud.policy/policy/v1\0";
@@ -25831,7 +27525,7 @@ async function createPolicy(options, capabilities) {
25831
27525
  function addressedPlan(options) {
25832
27526
  const capabilities = sortCanonical([
25833
27527
  { kind: "kv", resource: options.contentSource.kvResource, selector: options.resource.kind, actions: [...options.policyActions] },
25834
- { kind: "encryption", resource: options.contentSource.encryptionNetwork, action: "tinycloud.encryption/decrypt" }
27528
+ { kind: "encryption", resource: options.contentSource.encryptionKeyPath === void 0 ? options.contentSource.encryptionNetwork : `${options.contentSource.encryptionNetwork}/${options.contentSource.encryptionKeyPath}`, action: "tinycloud.encryption/decrypt" }
25835
27529
  ]);
25836
27530
  return {
25837
27531
  expiry: rfc3339Seconds(options.expiresAt),
@@ -26156,6 +27850,7 @@ async function addressedShareBodyUpperBound(input) {
26156
27850
  kvResource: `${input.spaceId}/kv/${path}`,
26157
27851
  selector: input.resource.kind,
26158
27852
  encryptionNetwork: input.encryptionNetwork,
27853
+ ...input.encryptionKeyPath === void 0 ? {} : { encryptionKeyPath: input.encryptionKeyPath },
26159
27854
  encryptedSymmetricKeyDigestHex: "f".repeat(64),
26160
27855
  keyVersion: Number.MAX_SAFE_INTEGER,
26161
27856
  mode: "immutable",
@@ -26875,9 +28570,9 @@ async function validateReceipt(receipt, shareUrl) {
26875
28570
  }
26876
28571
  const links = await Promise.resolve().then(() => (init_links(), links_exports));
26877
28572
  try {
26878
- const origin = new URL(shareUrl).origin;
26879
- const parsed = links.parseLink(shareUrl, { trustedOrigins: [origin] });
26880
- if (parsed.form !== "short" || parsed.pathType !== "share" || shareUrl.length > MAX_INVITATION_LINK_BYTES || shareUrl !== links.buildShortLink({ origin, type: "share", id: parsed.id, key: parsed.key, bodyCid: parsed.c })) {
28573
+ const origin2 = new URL(shareUrl).origin;
28574
+ const parsed = links.parseLink(shareUrl, { trustedOrigins: [origin2] });
28575
+ if (parsed.form !== "short" || parsed.pathType !== "share" || shareUrl.length > MAX_INVITATION_LINK_BYTES || shareUrl !== links.buildShortLink({ origin: origin2, type: "share", id: parsed.id, key: parsed.key, bodyCid: parsed.c })) {
26881
28576
  throw new Error("not a short share link");
26882
28577
  }
26883
28578
  } catch {
@@ -28200,6 +29895,23 @@ var unifiedEncryptionNetworkSchema3 = external_exports2.string().refine((value)
28200
29895
  const network = separator < 0 ? "" : rest.slice(separator + 1);
28201
29896
  return owner.startsWith("did:") && owner.length > 4 && network.length > 0 && !/[:/%?#\s]/.test(network);
28202
29897
  }, { message: "expected canonical TinyCloud encryption network" });
29898
+ var unifiedEncryptionResourceSchema3 = external_exports2.string().refine((value) => {
29899
+ const prefix = "urn:tinycloud:encryption:";
29900
+ if (!value.startsWith(prefix)) return false;
29901
+ const match = /^(did:.+):([^/:?#\s]+)(?:\/(.+))?$/.exec(value.slice(prefix.length));
29902
+ if (match === null) return false;
29903
+ const path = match[3];
29904
+ return path === void 0 || path.split("/").every(
29905
+ (segment) => segment.length > 0 && segment !== "." && segment !== ".." && !/[\\:%?#\s]/.test(segment)
29906
+ );
29907
+ }, { message: "expected a canonical TinyCloud encryption resource" });
29908
+ var unifiedEncryptionKeyPathSchema3 = external_exports2.string().regex(/^share\/[^/]+$/).refine(
29909
+ (value) => {
29910
+ const segment = value.slice("share/".length);
29911
+ return segment !== "." && segment !== ".." && !/[\\:%?#\s]/.test(segment);
29912
+ },
29913
+ { message: "expected an exact share key path" }
29914
+ );
28203
29915
  var unifiedKvCapabilitySchema3 = external_exports2.object({
28204
29916
  kind: external_exports2.literal("kv"),
28205
29917
  resource: unifiedResourceSchema3,
@@ -28213,7 +29925,7 @@ var unifiedKvCapabilitySchema3 = external_exports2.object({
28213
29925
  }).strict();
28214
29926
  var unifiedEncryptionCapabilitySchema3 = external_exports2.object({
28215
29927
  kind: external_exports2.literal("encryption"),
28216
- resource: unifiedEncryptionNetworkSchema3,
29928
+ resource: unifiedEncryptionResourceSchema3,
28217
29929
  action: external_exports2.literal("tinycloud.encryption/decrypt")
28218
29930
  }).strict();
28219
29931
  var unifiedCapabilitySchema3 = external_exports2.union([unifiedKvCapabilitySchema3, unifiedEncryptionCapabilitySchema3]);
@@ -28222,6 +29934,7 @@ var unifiedContentSourceSchema3 = external_exports2.object({
28222
29934
  kvResource: unifiedResourceSchema3,
28223
29935
  selector: external_exports2.union([external_exports2.literal("exact"), external_exports2.literal("prefix")]),
28224
29936
  encryptionNetwork: unifiedEncryptionNetworkSchema3,
29937
+ encryptionKeyPath: unifiedEncryptionKeyPathSchema3.optional(),
28225
29938
  encryptedSymmetricKeyDigestHex: external_exports2.string().regex(/^[0-9a-f]{64}$/),
28226
29939
  keyVersion: external_exports2.number().int().positive(),
28227
29940
  mode: external_exports2.union([external_exports2.literal("mutable"), external_exports2.literal("immutable")]),
@@ -28339,16 +30052,21 @@ function validateV3Invariants3(value, ctx) {
28339
30052
  if (value.attestedEnforcerBinding.nodeAudience !== value.target.nodeAudience || value.attestedEnforcerBinding.signature.signerDid !== value.attestedEnforcerBinding.nodeAudience || Date.parse(value.attestedEnforcerBinding.expiresAt) < Date.parse(value.expiry)) {
28340
30053
  ctx.addIssue({ code: external_exports2.ZodIssueCode.custom, path: ["attestedEnforcerBinding"], message: "enforcer binding does not cover the target and share lifetime" });
28341
30054
  }
28342
- if (value.policy.contentSource.shareId !== value.contentSource.shareId || value.policy.contentSource.kvResource !== value.contentSource.kvResource || value.policy.contentSource.selector !== value.contentSource.selector || value.policy.contentSource.encryptionNetwork !== value.encryptionNetwork || value.policy.contentSource.encryptedSymmetricKeyDigestHex !== value.contentSource.encryptedSymmetricKeyDigestHex || value.policy.contentSource.keyVersion !== value.contentSource.keyVersion || value.policy.contentSource.mode !== value.contentSource.mode || value.policy.contentSource.initialCiphertextDigestHex !== value.contentSource.initialCiphertextDigestHex) {
30055
+ const encryptionKeyPath = value.contentSource.encryptionKeyPath;
30056
+ if (encryptionKeyPath !== void 0 && encryptionKeyPath !== `share/${value.contentSource.shareId}`) {
30057
+ ctx.addIssue({ code: external_exports2.ZodIssueCode.custom, path: ["contentSource", "encryptionKeyPath"], message: "share key path must name this share" });
30058
+ }
30059
+ if (value.policy.contentSource.shareId !== value.contentSource.shareId || value.policy.contentSource.kvResource !== value.contentSource.kvResource || value.policy.contentSource.selector !== value.contentSource.selector || value.policy.contentSource.encryptionNetwork !== value.encryptionNetwork || value.policy.contentSource.encryptionKeyPath !== encryptionKeyPath || value.policy.contentSource.encryptedSymmetricKeyDigestHex !== value.contentSource.encryptedSymmetricKeyDigestHex || value.policy.contentSource.keyVersion !== value.contentSource.keyVersion || value.policy.contentSource.mode !== value.contentSource.mode || value.policy.contentSource.initialCiphertextDigestHex !== value.contentSource.initialCiphertextDigestHex) {
28343
30060
  ctx.addIssue({ code: external_exports2.ZodIssueCode.custom, path: ["contentSource"], message: "content source is not bound to policy" });
28344
30061
  }
28345
30062
  if (value.policy.signature.suite !== "Ed25519" || value.policy.signature.signerDid !== value.policy.ownerDid) {
28346
30063
  ctx.addIssue({ code: external_exports2.ZodIssueCode.custom, path: ["policy", "signature"], message: "policy must be signed by its owner" });
28347
30064
  }
28348
30065
  const kvCapabilities = value.policy.capabilityCeiling.filter((capability) => capability.kind === "kv");
28349
- const decryptCapabilities = value.policy.capabilityCeiling.filter((capability) => capability.kind === "encryption" && capability.resource === value.encryptionNetwork && capability.action === "tinycloud.encryption/decrypt");
30066
+ const expectedEncryptionResource = encryptionKeyPath === void 0 ? value.encryptionNetwork : `${value.encryptionNetwork}/${encryptionKeyPath}`;
30067
+ const decryptCapabilities = value.policy.capabilityCeiling.filter((capability) => capability.kind === "encryption" && capability.resource === expectedEncryptionResource && capability.action === "tinycloud.encryption/decrypt");
28350
30068
  if (value.policy.capabilityCeiling.length !== 2 || kvCapabilities.length !== 1 || decryptCapabilities.length !== 1 || kvCapabilities[0]?.resource !== value.contentSource.kvResource || kvCapabilities[0]?.selector !== value.contentSource.selector) {
28351
- ctx.addIssue({ code: external_exports2.ZodIssueCode.custom, path: ["policy", "capabilityCeiling"], message: "policy ceiling must contain exact decrypt network" });
30069
+ ctx.addIssue({ code: external_exports2.ZodIssueCode.custom, path: ["policy", "capabilityCeiling"], message: "policy ceiling must contain the exact decrypt resource" });
28352
30070
  }
28353
30071
  }
28354
30072
  var unsignedShareEnvelopeV3Schema3 = unsignedShareEnvelopeV3BaseSchema3.superRefine(validateV3Invariants3);
@@ -28555,7 +30273,7 @@ function receiveJson(result, path) {
28555
30273
 
28556
30274
  // src/share/io.ts
28557
30275
  import { constants } from "fs";
28558
- import { lstat as lstat6, mkdir as mkdir4, mkdtemp, open as open7, readFile as readFile6, realpath as realpath2, stat as stat4, link as link2, rename as rename3, rm as rm5, unlink as unlink4 } from "fs/promises";
30276
+ import { lstat as lstat6, mkdir as mkdir4, mkdtemp, open as open8, readFile as readFile6, realpath as realpath2, stat as stat4, link as link2, rename as rename3, rm as rm6, unlink as unlink4 } from "fs/promises";
28559
30277
  import { randomBytes as randomBytes3 } from "crypto";
28560
30278
  import { basename as basename2, join as join11, resolve as resolve4, sep as sep3 } from "path";
28561
30279
  init_errors();
@@ -28631,7 +30349,7 @@ async function writeShareOutput(directory, filename, bytes, force) {
28631
30349
  const outputDirectory = resolve4(directory);
28632
30350
  await assertDirectory(outputDirectory);
28633
30351
  const safeName = safeFilename(filename);
28634
- const directoryHandle = await open7(outputDirectory, constants.O_RDONLY | (constants.O_DIRECTORY ?? 0) | (constants.O_NOFOLLOW ?? 0));
30352
+ const directoryHandle = await open8(outputDirectory, constants.O_RDONLY | (constants.O_DIRECTORY ?? 0) | (constants.O_NOFOLLOW ?? 0));
28635
30353
  const stableDirectory = await realpath2(outputDirectory);
28636
30354
  const outputPath = join11(stableDirectory, safeName);
28637
30355
  const directoryIdentity = await directoryHandle.stat();
@@ -28655,7 +30373,7 @@ async function writeShareOutput(directory, filename, bytes, force) {
28655
30373
  if (error.code !== "ENOENT") throw error;
28656
30374
  }
28657
30375
  temporaryPath = stagingPath;
28658
- handle = await open7(temporaryPath, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0), 384);
30376
+ handle = await open8(temporaryPath, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0), 384);
28659
30377
  await handle.writeFile(bytes);
28660
30378
  await handle.close();
28661
30379
  handle = void 0;
@@ -28677,7 +30395,7 @@ async function writeShareOutput(directory, filename, bytes, force) {
28677
30395
  if (temporaryPath !== void 0) await unlink4(temporaryPath);
28678
30396
  } catch {
28679
30397
  }
28680
- await rm5(stagingDirectory, { recursive: true, force: true });
30398
+ await rm6(stagingDirectory, { recursive: true, force: true });
28681
30399
  await directoryHandle.close();
28682
30400
  }
28683
30401
  return join11(outputDirectory, safeName);
@@ -28764,17 +30482,30 @@ function createShareLinks(input) {
28764
30482
  return {
28765
30483
  async show(published, options) {
28766
30484
  const material = published.deliveryMaterial;
28767
- if (published.link.kind !== "policy" || material === void 0) return { url: published.url, short: false };
30485
+ if (published.link.kind !== "policy") return { url: published.url, short: false };
28768
30486
  if (options.fullLink) return { url: published.url, short: false };
28769
30487
  const now = options.now ?? /* @__PURE__ */ new Date();
28770
30488
  const expiresAt = new Date(published.metadata.expiresAt);
28771
30489
  const choice = linkFormForLifetime((expiresAt.getTime() - now.getTime()) / 1e3);
28772
30490
  if (choice.form === "full") return { url: published.url, short: false, ...choice.warning ? { notice: LINK_EXPIRY_WARNING } : {} };
28773
30491
  try {
30492
+ const issuerKey = await input.signer();
30493
+ let sealed;
30494
+ if (material !== void 0) {
30495
+ sealed = { blob: fromBase64Url4(material.sealedEnvelope), key: fromBase64Url4(material.envelopeKey) };
30496
+ } else {
30497
+ const parsed = parseLink(published.url, { trustedOrigins: [published.metadata.origin] });
30498
+ if (parsed.form !== "full") throw new LinkError("invalid_argument");
30499
+ const opened = await openLinkRecord(parsed.record, parsed.key, { now });
30500
+ if (opened.type !== "share" || opened.header.issuer !== issuerKey.did || opened.header.bodyCid !== published.link.cid || opened.header.expiresAt !== published.metadata.expiresAt) {
30501
+ throw new LinkError("invalid_argument");
30502
+ }
30503
+ sealed = { blob: opened.body, key: parsed.key };
30504
+ }
28774
30505
  const created = await createLink({
28775
30506
  type: "share",
28776
- sealed: { blob: fromBase64Url4(material.sealedEnvelope), key: fromBase64Url4(material.envelopeKey) },
28777
- issuerKey: await input.signer(),
30507
+ sealed,
30508
+ issuerKey,
28778
30509
  apiOrigin,
28779
30510
  linkOrigin: new URL(published.url).origin,
28780
30511
  expiresAt,
@@ -28792,6 +30523,38 @@ function createShareLinks(input) {
28792
30523
  };
28793
30524
  }
28794
30525
 
30526
+ // src/share/email-publish-v3.ts
30527
+ import {
30528
+ canonicalDigest,
30529
+ createEmailCredentialRequirement,
30530
+ credentialRequirementDigest,
30531
+ validateCredentialFlowDescriptor
30532
+ } from "@tinycloud/sdk-core";
30533
+ async function publishEmailShareV3(input) {
30534
+ const { contentSource } = input;
30535
+ if (input.resource.kind !== "exact" || contentSource.encryptionKeyPath !== `share/${input.shareId}` || !/^urn:tinycloud:encryption:did:pkh:eip155:\d+:0x[0-9a-fA-F]{40}:default$/.test(contentSource.encryptionNetwork)) {
30536
+ throw new TypeError("email share binding is invalid");
30537
+ }
30538
+ const descriptor = validateCredentialFlowDescriptor(input.credentialDescriptor);
30539
+ if (descriptor.issuer.did !== input.issuerDid || descriptor.issuer.kid !== input.issuerKid || !descriptor.claims.some((claim) => claim.name === "email" && claim.matching === "normalized_exact")) {
30540
+ throw new TypeError("email credential issuer or claim is invalid");
30541
+ }
30542
+ const profile = { id: descriptor.profile, version: 1 };
30543
+ const credentialType = { id: descriptor.format.vct, version: 1 };
30544
+ const requirement = createEmailCredentialRequirement({ email: input.target.address, profile, credentialType });
30545
+ const credentialRequirement = {
30546
+ type: "TinyCloudPolicyCredentialRequirement",
30547
+ version: 1,
30548
+ requirementDigest: await credentialRequirementDigest(requirement),
30549
+ descriptorDigest: await canonicalDigest(descriptor),
30550
+ issuerDid: input.issuerDid,
30551
+ issuerKid: input.issuerKid,
30552
+ profile,
30553
+ credentialType
30554
+ };
30555
+ return publishAddressedShare({ ...input, credentialRequirement });
30556
+ }
30557
+
28795
30558
  // src/share/errors.ts
28796
30559
  var SharePublishAuthorityError = class extends Error {
28797
30560
  constructor(failure, options) {
@@ -28853,7 +30616,7 @@ init_profiles();
28853
30616
  init_constants();
28854
30617
  init_errors();
28855
30618
  init_session_expired();
28856
- import { chmod as chmod4, link as link3, open as open8, readFile as readFile7, stat as stat5, unlink as unlink5 } from "fs/promises";
30619
+ import { chmod as chmod4, link as link3, open as open9, readFile as readFile7, stat as stat5, unlink as unlink5 } from "fs/promises";
28857
30620
  import { dirname as dirname5, join as join12 } from "path";
28858
30621
  import { createHash } from "crypto";
28859
30622
  import { writeJsonAtomic as writeJsonAtomic2 } from "@tinycloud/operations/state";
@@ -29210,7 +30973,7 @@ function createEncryptedProfileHistory(profileName, sessionSigner) {
29210
30973
  await link3(found.file, target);
29211
30974
  await chmod4(target, PRIVATE_HISTORY_MODE);
29212
30975
  await unlink5(found.file);
29213
- const directory = await open8(dirname5(found.file), "r");
30976
+ const directory = await open9(dirname5(found.file), "r");
29214
30977
  try {
29215
30978
  await directory.sync();
29216
30979
  } finally {
@@ -29258,7 +31021,7 @@ function quarantineUnreadableProfileHistory(profileName) {
29258
31021
  return createEncryptedProfileHistory(async () => profileName, signShareHistoryBytes).quarantineUnreadable();
29259
31022
  }
29260
31023
  function createShareAuthorityAdapters(input = {}) {
29261
- const origin = input.origin ?? DEFAULT_SHARE_ORIGIN;
31024
+ const origin2 = input.origin ?? DEFAULT_SHARE_ORIGIN;
29262
31025
  const fetchFn = input.fetchFn ?? globalThis.fetch;
29263
31026
  let selectedProfile;
29264
31027
  const profileName = () => selectedProfile ??= input.profileName?.() ?? selectedProfileName();
@@ -29273,7 +31036,7 @@ function createShareAuthorityAdapters(input = {}) {
29273
31036
  const publicConfig = async () => configPromise ??= (async () => {
29274
31037
  let response;
29275
31038
  try {
29276
- response = await fetchFn(`${origin}/.well-known/tinycloud-share/config.json`, {
31039
+ response = await fetchFn(`${origin2}/.well-known/tinycloud-share/config.json`, {
29277
31040
  headers: { accept: "application/json" },
29278
31041
  credentials: "omit",
29279
31042
  redirect: "error",
@@ -29281,9 +31044,9 @@ function createShareAuthorityAdapters(input = {}) {
29281
31044
  signal: AbortSignal.timeout(1e4)
29282
31045
  });
29283
31046
  } catch (error) {
29284
- throw new SharePublishAuthorityError({ kind: "share-service-unavailable", origin }, { cause: error });
31047
+ throw new SharePublishAuthorityError({ kind: "share-service-unavailable", origin: origin2 }, { cause: error });
29285
31048
  }
29286
- if (!response.ok) throw new SharePublishAuthorityError({ kind: "share-service-unavailable", origin });
31049
+ if (!response.ok) throw new SharePublishAuthorityError({ kind: "share-service-unavailable", origin: origin2 });
29287
31050
  const value = await response.json();
29288
31051
  if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("share public config is invalid");
29289
31052
  const object3 = value;
@@ -29413,8 +31176,15 @@ function createShareAuthorityAdapters(input = {}) {
29413
31176
  profileName: activeProfileName2
29414
31177
  });
29415
31178
  }
29416
- const addressedEncryptionNetwork = targetInput.target.kind === "bearer" ? void 0 : node.getEncryptionNetworkIdForSpace(ownerSpaceId);
29417
- if (addressedEncryptionNetwork !== void 0 && node.isSessionOnly && !sessionHoldsEncryptionDecrypt(node, addressedEncryptionNetwork)) {
31179
+ if (targetInput.target.kind === "email" && (targetInput.credentialDescriptor === void 0 || targetInput.issuerDid === void 0 || targetInput.issuerKid === void 0)) {
31180
+ throw new TypeError("email credential descriptor and issuer are required");
31181
+ }
31182
+ const addressedEncryptionNetwork = targetInput.target.kind === "bearer" ? void 0 : targetInput.target.kind === "email" ? node.getDefaultEncryptionNetworkId() : node.getEncryptionNetworkIdForSpace(ownerSpaceId);
31183
+ const emailKeyPath = targetInput.target.kind === "email" ? `share/${crypto.randomUUID().replaceAll("-", "")}` : void 0;
31184
+ if (addressedEncryptionNetwork !== void 0 && node.isSessionOnly && !sessionHoldsEncryptionDecrypt(
31185
+ node,
31186
+ emailKeyPath === void 0 ? addressedEncryptionNetwork : `${addressedEncryptionNetwork}/${emailKeyPath}`
31187
+ )) {
29418
31188
  throw new SharePublishAuthorityError({ kind: "decrypt-not-held" });
29419
31189
  }
29420
31190
  const config = await publicConfig();
@@ -29423,7 +31193,7 @@ function createShareAuthorityAdapters(input = {}) {
29423
31193
  if (targetInput.notify === true && targetInput.target.kind === "emailDomain") {
29424
31194
  await assertDomainDeliveryForOrigin(activeNode.origin, "publish");
29425
31195
  }
29426
- const shareId = crypto.randomUUID().replaceAll("-", "");
31196
+ const shareId = emailKeyPath?.slice("share/".length) ?? crypto.randomUUID().replaceAll("-", "");
29427
31197
  const files = targetInput.files === void 0 || targetInput.files.length === 0 ? [{ bytes: targetInput.source, filename: targetInput.filename, mediaType: targetInput.mediaType }] : targetInput.files;
29428
31198
  const resourceKind = targetInput.resourceKind ?? "exact";
29429
31199
  if (targetInput.target.kind === "bearer") {
@@ -29545,6 +31315,7 @@ function createShareAuthorityAdapters(input = {}) {
29545
31315
  resource: { kind: resourceKind },
29546
31316
  storage: artifact === void 0 ? { path: resourcePath } : { artifactId: artifact.id, storageName },
29547
31317
  encryptionNetwork: addressedEncryptionNetwork,
31318
+ ...emailKeyPath === void 0 ? {} : { encryptionKeyPath: emailKeyPath },
29548
31319
  actions,
29549
31320
  policyActions,
29550
31321
  ...deliveryEmail === void 0 ? {} : { deliveryEmail },
@@ -29560,8 +31331,14 @@ function createShareAuthorityAdapters(input = {}) {
29560
31331
  throw new SharePublishAuthorityError({ kind: rejected ? "registry-rejected" : "registry-unavailable" });
29561
31332
  }
29562
31333
  const encryptionNetwork = addressedEncryptionNetwork;
29563
- const encrypted = await node.encryption.encryptToNetwork(encryptionNetwork, file.bytes, { metadata: { contentType: mediaType } });
31334
+ const encrypted = await node.encryption.encryptToNetwork(encryptionNetwork, file.bytes, {
31335
+ ...emailKeyPath === void 0 ? {} : { keyPath: emailKeyPath },
31336
+ metadata: { contentType: mediaType }
31337
+ });
29564
31338
  if (!encrypted.ok) throw new Error("addressed source encryption was rejected");
31339
+ if (emailKeyPath !== void 0 && (encrypted.data.networkId !== encryptionNetwork || encrypted.data.keyPath !== emailKeyPath)) {
31340
+ throw new Error("email share encryption was rejected");
31341
+ }
29565
31342
  const storedBytes = new TextEncoder().encode(canonicalize4(encrypted.data));
29566
31343
  let artifactVersion;
29567
31344
  if (artifact !== void 0) {
@@ -29594,6 +31371,7 @@ function createShareAuthorityAdapters(input = {}) {
29594
31371
  kvResource: `${ownerSpaceId}/kv/${resourcePath}`,
29595
31372
  selector: resourceKind,
29596
31373
  encryptionNetwork: encrypted.data.networkId,
31374
+ ...emailKeyPath === void 0 ? {} : { encryptionKeyPath: emailKeyPath },
29597
31375
  encryptedSymmetricKeyDigestHex: encrypted.data.encryptedSymmetricKeyHash,
29598
31376
  keyVersion: encrypted.data.keyVersion,
29599
31377
  mode: "immutable",
@@ -29635,7 +31413,13 @@ function createShareAuthorityAdapters(input = {}) {
29635
31413
  };
29636
31414
  let published;
29637
31415
  try {
29638
- published = await publishAddressedShare(addressedOptions);
31416
+ published = prepared.target.kind === "email" ? await publishEmailShareV3({
31417
+ ...addressedOptions,
31418
+ target: prepared.target,
31419
+ credentialDescriptor: targetInput.credentialDescriptor,
31420
+ issuerDid: targetInput.issuerDid,
31421
+ issuerKid: targetInput.issuerKid
31422
+ }) : await publishAddressedShare(addressedOptions);
29639
31423
  } catch (error) {
29640
31424
  if (!(error instanceof AddressedShareOverLimitError)) throw error;
29641
31425
  const remaining = await removeOverLimitShare({
@@ -29828,7 +31612,7 @@ init_profiles();
29828
31612
 
29829
31613
  // src/share/html-folder.ts
29830
31614
  import { constants as constants2, existsSync } from "fs";
29831
- import { lstat as lstat7, open as open9, readdir as readdir6, realpath as realpath3, stat as stat6 } from "fs/promises";
31615
+ import { lstat as lstat7, open as open10, readdir as readdir6, realpath as realpath3, stat as stat6 } from "fs/promises";
29832
31616
  import { basename as basename3, dirname as dirname6, isAbsolute, join as join13, relative as relativePath, resolve as resolve5, sep as sep4 } from "path";
29833
31617
 
29834
31618
  // ../share-sdk/dist/html-bundle.js
@@ -30183,9 +31967,9 @@ function scanMarkup(html, options) {
30183
31967
  if (comments > MAX_ARTIFACT_COMMENTS) fail("limit", "artifact page has too many comments");
30184
31968
  };
30185
31969
  while (index < length5) {
30186
- const open10 = html.indexOf("<", index);
30187
- if (open10 === -1) return;
30188
- index = open10 + 1;
31970
+ const open11 = html.indexOf("<", index);
31971
+ if (open11 === -1) return;
31972
+ index = open11 + 1;
30189
31973
  const next = html[index] ?? "";
30190
31974
  if (html.startsWith("!--", index)) {
30191
31975
  countComment();
@@ -30786,7 +32570,7 @@ async function readRegularFile(root, path, relative, remaining, limit, hooks = {
30786
32570
  await hooks.beforeOpen?.();
30787
32571
  before = await lstat7(path);
30788
32572
  await hooks.afterLstat?.();
30789
- handle = await open9(path, constants2.O_RDONLY | (constants2.O_NOFOLLOW ?? 0) | (constants2.O_NONBLOCK ?? 0));
32573
+ handle = await open10(path, constants2.O_RDONLY | (constants2.O_NOFOLLOW ?? 0) | (constants2.O_NONBLOCK ?? 0));
30790
32574
  } catch (error) {
30791
32575
  if (error.code === "ELOOP") return problem("symbolic link");
30792
32576
  if (isRaceError(error)) return problem(CHANGED);
@@ -30845,7 +32629,7 @@ async function listFolderDirectory(root, absolute, relative, hooks = {}) {
30845
32629
  if (before.isSymbolicLink()) return problem("symbolic link");
30846
32630
  if (!before.isDirectory()) return problem(CHANGED);
30847
32631
  await hooks.afterLstat?.();
30848
- const handle = await open9(absolute, constants2.O_RDONLY | (constants2.O_DIRECTORY ?? 0) | (constants2.O_NOFOLLOW ?? 0));
32632
+ const handle = await open10(absolute, constants2.O_RDONLY | (constants2.O_DIRECTORY ?? 0) | (constants2.O_NOFOLLOW ?? 0));
30849
32633
  try {
30850
32634
  await hooks.afterOpen?.();
30851
32635
  const info = await handle.stat();
@@ -31137,12 +32921,7 @@ function shareCliError(error, operation = "publish") {
31137
32921
  return new CLIError("UPLOAD_FAILED", "share source upload failed; nothing was shared", 4);
31138
32922
  }
31139
32923
  if (failure.kind === "decrypt-not-held") {
31140
- return new CLIError(
31141
- "PERMISSION_DENIED",
31142
- "this sign-in can't create email-addressed shares: it has no permission to decrypt with the account's key. Nothing was shared.",
31143
- 5,
31144
- { hint: "Share it from https://share.tinycloud.xyz while signed in as the account owner, or ask the owner to share it. A link anyone can open works from this sign-in: --to anyone." }
31145
- );
32924
+ return new CLIError("PERMISSION_DENIED", `Email shares need a paste sign-in: run ${CLI_NAME12} auth login --paste --manifest builtin:share-publishing`, 5);
31146
32925
  }
31147
32926
  if (failure.kind === "over-limit") {
31148
32927
  return new CLIError("MAX_BYTES_EXCEEDED", ADDRESSED_SHARE_TOO_LARGE_MESSAGE, 7, { hint: `What stays behind: ${failure.remaining.join("; ")}.` });
@@ -31277,7 +33056,7 @@ function assertAggregateInputLimit(inputs, maxBytes) {
31277
33056
  }
31278
33057
  function registerShareCommand(program2) {
31279
33058
  const share = program2.command("share").description("Publish and consume TinyCloud Share links");
31280
- share.command("publish <files...>").description("Publish one or more bounded files as a Share, or a folder with an index.html as one self-contained page (anyone links only)").option("--name <filename>", "Filename for stdin input, or the published .html name of a folder").option("--to <target>", "Share target", "anyone").option("--notify", "Email an exact-email recipient, or a domain mailbox on node 1.17.3+").option("--notify-to <address>", "Mailbox to invite for --to domain:<name> --notify (node 1.17.3+)").option("--expires <duration>", "Share lifetime").option("--max-bytes <bytes>", "Bound input bytes").option("--media-type <type>", "Media type for a single input").option("--action <actions...>", "Addressed permission: read, list, or edit").option("--prefix", "Publish multiple inputs beneath one addressed prefix").option("--binary", "Allow non-UTF-8 bearer content").option("--artifact <id>", 'Publish as the next write-once version of an artifact ("new" starts one); the share is pinned to that version').addOption(new Option("--ongoing").hideHelp()).option("--note <text>", "Note stored with the artifact version").option("--json", "Print versioned redacted JSON").option("--full-link", "Print the full self-contained link instead of a short link (addressed shares)").option("--viewer-origin <origin>", "Canonical HTTPS viewer origin", SHARE_ORIGIN).action(async (files, options, command) => {
33059
+ share.command("publish <files...>").description("Publish one or more bounded files as a Share, or a folder with an index.html as one self-contained page (anyone links only)").option("--name <filename>", "Filename for stdin input, or the published .html name of a folder").option("--to <target>", "Share target", "anyone").option("--credential-descriptor <path>", "Email credential flow descriptor JSON").option("--issuer-did <did>", "Trusted email credential issuer DID").option("--issuer-kid <kid>", "Trusted email credential issuer key ID").option("--notify", "Email an exact-email recipient, or a domain mailbox on node 1.17.3+").option("--notify-to <address>", "Mailbox to invite for --to domain:<name> --notify (node 1.17.3+)").option("--expires <duration>", "Share lifetime").option("--max-bytes <bytes>", "Bound input bytes").option("--media-type <type>", "Media type for a single input").option("--action <actions...>", "Addressed permission: read, list, or edit").option("--prefix", "Publish multiple inputs beneath one addressed prefix").option("--binary", "Allow non-UTF-8 bearer content").option("--artifact <id>", 'Publish as the next write-once version of an artifact ("new" starts one); the share is pinned to that version').addOption(new Option("--ongoing").hideHelp()).option("--note <text>", "Note stored with the artifact version").option("--json", "Print versioned redacted JSON").option("--full-link", "Print the full self-contained link instead of a short link (addressed shares)").option("--viewer-origin <origin>", "Canonical HTTPS viewer origin", SHARE_ORIGIN).action(async (files, options, command) => {
31281
33060
  try {
31282
33061
  const json = jsonOutput(options, command);
31283
33062
  if (options.ongoing === true) throw new CLIError("UNSUPPORTED_TARGET", ONGOING_UNAVAILABLE, 2);
@@ -31285,6 +33064,15 @@ function registerShareCommand(program2) {
31285
33064
  if (files.length === 0 || files.includes("-") && files.length > 1) throw new CLIError("INVALID_ARGUMENT", "stdin must be the only publish input", 2);
31286
33065
  const name = files.length === 1 ? options.name : void 0;
31287
33066
  const target = parseShareTarget(options.to);
33067
+ const actions = requestedActions(options.action);
33068
+ if (options.notify === true && !actions.includes("read")) throw new CLIError("INVALID_ARGUMENT", "--notify requires the read action; nothing was shared", 2);
33069
+ if (target.kind === "email" && (!options.credentialDescriptor || !options.issuerDid || !options.issuerKid)) {
33070
+ throw new CLIError("INVALID_ARGUMENT", "email publication requires --credential-descriptor, --issuer-did, and --issuer-kid", 2);
33071
+ }
33072
+ if (target.kind !== "email" && (options.credentialDescriptor || options.issuerDid || options.issuerKid)) {
33073
+ throw new CLIError("INVALID_ARGUMENT", "credential options require an exact email target", 2);
33074
+ }
33075
+ const credentialDescriptor = target.kind === "email" ? JSON.parse(await readFile8(options.credentialDescriptor, "utf8")) : void 0;
31288
33076
  const folder = files.length === 1 && target.kind === "bearer" && options.prefix !== true && await isDirectoryInput(files[0]);
31289
33077
  let inputs;
31290
33078
  if (folder) {
@@ -31301,13 +33089,11 @@ function registerShareCommand(program2) {
31301
33089
  inputs = await Promise.all(files.map((file) => readShareInput(file, name, maxBytes)));
31302
33090
  }
31303
33091
  assertAggregateInputLimit(inputs, maxBytes);
31304
- const actions = requestedActions(options.action);
31305
33092
  if (options.prefix && target.kind === "bearer") throw new CLIError("INVALID_ARGUMENT", "--prefix requires an addressed target", 2);
31306
33093
  if (target.kind === "bearer" && actions.includes("edit")) throw new CLIError("INVALID_ARGUMENT", `--action edit is not available with --to ${options.to}: a link can only be read; address a recipient to allow edits`, 2);
31307
33094
  if (inputs.length > 1 && target.kind === "bearer") throw new CLIError("UNSUPPORTED_LINK", "multiple files require an addressed target", 2);
31308
33095
  const artifact = artifactRequest(options, actions, inputs.length);
31309
33096
  if (inputs.length > 1 && !options.prefix) throw new CLIError("INVALID_ARGUMENT", "multiple files require --prefix", 2);
31310
- if (options.notify === true && !actions.includes("read")) throw new CLIError("INVALID_ARGUMENT", "--notify requires the read action; nothing was shared", 2);
31311
33097
  if (options.notifyTo !== void 0 && (options.notify !== true || target.kind !== "emailDomain")) {
31312
33098
  throw new CLIError("INVALID_ARGUMENT", "--notify-to requires --to domain:<name> --notify", 2);
31313
33099
  }
@@ -31337,6 +33123,7 @@ function registerShareCommand(program2) {
31337
33123
  origin: options.viewerOrigin,
31338
33124
  ...maxBytes === void 0 ? {} : { maxBytes },
31339
33125
  notify: options.notify === true,
33126
+ ...credentialDescriptor === void 0 ? {} : { credentialDescriptor, issuerDid: options.issuerDid, issuerKid: options.issuerKid },
31340
33127
  // The artifact request rides on the adapter call rather than through `publishTargetShare`, whose code is part of
31341
33128
  // the browser bundles (the web-sdk size ceiling counts every byte it carries).
31342
33129
  targetAdapter: artifact === void 0 || shareServices.targetAdapter === void 0 ? shareServices.targetAdapter : { publish: (request) => shareServices.targetAdapter.publish({ ...request, artifact }) }
@@ -31646,7 +33433,8 @@ configureShareCommandServices({
31646
33433
  revocation: shareAuthority.revocation,
31647
33434
  nativeReader: shareAuthority.nativeReader,
31648
33435
  artifactStore: shareAuthority.artifactStore,
31649
- links: shareAuthority.links
33436
+ links: shareAuthority.links,
33437
+ shortLinkInvitations: true
31650
33438
  });
31651
33439
  var argv = process.argv.slice(2);
31652
33440
  var globalLongOptionsWithValues = { "--profile": true, "--host": true };
@@ -31733,6 +33521,10 @@ if (argv[0] === "courier") {
31733
33521
  @noble/curves/esm/abstract/curve.js:
31734
33522
  @noble/curves/esm/abstract/edwards.js:
31735
33523
  @noble/curves/esm/ed25519.js:
33524
+ @noble/curves/esm/abstract/weierstrass.js:
33525
+ @noble/curves/esm/_shortw_utils.js:
33526
+ @noble/curves/esm/nist.js:
33527
+ @noble/curves/esm/p256.js:
31736
33528
  (*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
31737
33529
  */
31738
33530
  //# sourceMappingURL=index.js.map