@tinycloud/cli 1.3.1 → 1.3.2-beta.1

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
@@ -266,11 +266,11 @@ function warningLine(warnings) {
266
266
  const subject = warnings.length === 1 ? "A stored grant was" : `${warnings.length} stored grants were`;
267
267
  return `${subject} not used (${which}). Approve access again when a command needs it; remove the old grant with ${CLI_NAME2} auth grants remove <cid>.`;
268
268
  }
269
- function outputError(code4, message, hint, details = {}) {
269
+ function outputError(code5, message, hint, details = {}) {
270
270
  const { meta, warnings = [], setup, recovery, progress } = details;
271
271
  if (!shouldOutputJson()) {
272
272
  process.stderr.write(
273
- `${theme.error("\u2717")} ${theme.label(safeInline(code4))}: ${safeBlock(message)}
273
+ `${theme.error("\u2717")} ${theme.label(safeInline(code5))}: ${safeBlock(message)}
274
274
  `
275
275
  );
276
276
  if (hint) {
@@ -283,7 +283,7 @@ function outputError(code4, message, hint, details = {}) {
283
283
  `);
284
284
  } else {
285
285
  const payload = {
286
- error: { code: code4, message }
286
+ error: { code: code5, message }
287
287
  };
288
288
  if (hint) payload.error.hint = hint;
289
289
  if (recovery) payload.error.recovery = recovery;
@@ -305,11 +305,11 @@ function operationWarnings(value) {
305
305
  if (!Array.isArray(value)) return [];
306
306
  return value.flatMap((warning) => {
307
307
  if (warning === null || typeof warning !== "object") return [];
308
- const { code: code4, reason, grantCid } = warning;
309
- if (typeof code4 !== "string" || !WARNING_CODE.test(code4) || typeof reason !== "string" || !WARNING_REASON.test(reason)) {
308
+ const { code: code5, reason, grantCid } = warning;
309
+ if (typeof code5 !== "string" || !WARNING_CODE.test(code5) || typeof reason !== "string" || !WARNING_REASON.test(reason)) {
310
310
  return [];
311
311
  }
312
- return [{ code: code4, reason, ...typeof grantCid === "string" && DELEGATION_CID.test(grantCid) ? { grantCid } : {} }];
312
+ return [{ code: code5, reason, ...typeof grantCid === "string" && DELEGATION_CID.test(grantCid) ? { grantCid } : {} }];
313
313
  });
314
314
  }
315
315
  function isInteractive() {
@@ -340,17 +340,17 @@ function storageRejection(error) {
340
340
  let node = error;
341
341
  for (let depth = 0; depth < MAX_CAUSE_DEPTH && typeof node === "object" && node !== null; depth += 1) {
342
342
  const record2 = node;
343
- let code4;
343
+ let code5;
344
344
  if (record2.code === "STORAGE_QUOTA_EXCEEDED" || record2.code === "STORAGE_LIMIT_REACHED") {
345
- code4 = record2.code;
345
+ code5 = record2.code;
346
346
  } else if (record2.code !== void 0) {
347
347
  return void 0;
348
348
  } else if (isStorageStatus(record2)) {
349
- code4 = storageCodeFromText(record2.message);
349
+ code5 = storageCodeFromText(record2.message);
350
350
  }
351
- if (code4) {
351
+ if (code5) {
352
352
  const account = accountTotals(record2) ?? accountTotals(record2.meta) ?? accountTotals(record2.metadata);
353
- return account ? { code: code4, account } : { code: code4 };
353
+ return account ? { code: code5, account } : { code: code5 };
354
354
  }
355
355
  node = record2.cause;
356
356
  }
@@ -434,22 +434,22 @@ function setActiveProfileName(name) {
434
434
  }
435
435
  function nodeRetryError(error) {
436
436
  if (typeof error !== "object" || error === null) return void 0;
437
- const { code: code4, meta, metadata } = error;
438
- if (code4 !== "NODE_BUSY" && code4 !== "REQUEST_TIMEOUT" && code4 !== "OUTCOME_UNKNOWN") return void 0;
437
+ const { code: code5, meta, metadata } = error;
438
+ if (code5 !== "NODE_BUSY" && code5 !== "REQUEST_TIMEOUT" && code5 !== "OUTCOME_UNKNOWN") return void 0;
439
439
  const details = typeof meta === "object" && meta !== null ? meta : typeof metadata === "object" && metadata !== null ? metadata : {};
440
440
  const retryAfterMs = details.retryAfterMs;
441
441
  const wait = typeof retryAfterMs === "number" && Number.isFinite(retryAfterMs) && retryAfterMs >= 0 ? `in ${Math.max(1, Math.ceil(retryAfterMs / 1e3))} s` : "shortly";
442
- if (code4 === "OUTCOME_UNKNOWN") {
442
+ if (code5 === "OUTCOME_UNKNOWN") {
443
443
  return new CLIError(
444
- code4,
444
+ code5,
445
445
  "Outcome unknown: the node may have applied the write. Check before retrying.",
446
446
  ExitCode.NODE_ERROR,
447
447
  { ...details, hint: "Read the data back before running the command again; repeating a write that already applied can duplicate it." }
448
448
  );
449
449
  }
450
450
  return new CLIError(
451
- code4,
452
- code4 === "NODE_BUSY" ? `The node is busy, try again ${wait}.` : `The node timed out before applying anything, try again ${wait}.`,
451
+ code5,
452
+ code5 === "NODE_BUSY" ? `The node is busy, try again ${wait}.` : `The node timed out before applying anything, try again ${wait}.`,
453
453
  ExitCode.NODE_ERROR,
454
454
  details
455
455
  );
@@ -661,9 +661,9 @@ var init_errors = __esm({
661
661
  init_warnings();
662
662
  GRANT_REVOKED_EXIT_CODE = ExitCode.PERMISSION_DENIED;
663
663
  CLIError = class extends Error {
664
- constructor(code4, message, exitCode = ExitCode.ERROR, metadata) {
664
+ constructor(code5, message, exitCode = ExitCode.ERROR, metadata) {
665
665
  super(message);
666
- this.code = code4;
666
+ this.code = code5;
667
667
  this.exitCode = exitCode;
668
668
  this.metadata = metadata;
669
669
  this.name = "CLIError";
@@ -1182,12 +1182,12 @@ var init_md = __esm({
1182
1182
  _cloneInto(to) {
1183
1183
  to || (to = new this.constructor());
1184
1184
  to.set(...this.get());
1185
- const { blockLen, buffer, length: length4, finished, destroyed, pos } = this;
1185
+ const { blockLen, buffer, length: length5, finished, destroyed, pos } = this;
1186
1186
  to.destroyed = destroyed;
1187
1187
  to.finished = finished;
1188
- to.length = length4;
1188
+ to.length = length5;
1189
1189
  to.pos = pos;
1190
- if (length4 % blockLen)
1190
+ if (length5 % blockLen)
1191
1191
  to.buffer.set(buffer);
1192
1192
  return to;
1193
1193
  }
@@ -1924,13 +1924,13 @@ var init_blake2 = __esm({
1924
1924
  return res;
1925
1925
  }
1926
1926
  _cloneInto(to) {
1927
- const { buffer, length: length4, finished, destroyed, outputLen, pos } = this;
1927
+ const { buffer, length: length5, finished, destroyed, outputLen, pos } = this;
1928
1928
  to || (to = new this.constructor({ dkLen: outputLen }));
1929
1929
  to.set(...this.get());
1930
1930
  to.buffer.set(buffer);
1931
1931
  to.destroyed = destroyed;
1932
1932
  to.finished = finished;
1933
- to.length = length4;
1933
+ to.length = length5;
1934
1934
  to.pos = pos;
1935
1935
  to.outputLen = outputLen;
1936
1936
  return to;
@@ -2165,13 +2165,13 @@ function _abool2(value, title = "") {
2165
2165
  }
2166
2166
  return value;
2167
2167
  }
2168
- function _abytes2(value, length4, title = "") {
2168
+ function _abytes2(value, length5, title = "") {
2169
2169
  const bytes = isBytes(value);
2170
2170
  const len = value?.length;
2171
- const needsLen = length4 !== void 0;
2172
- if (!bytes || needsLen && len !== length4) {
2171
+ const needsLen = length5 !== void 0;
2172
+ if (!bytes || needsLen && len !== length5) {
2173
2173
  const prefix = title && `"${title}" `;
2174
- const ofLen = needsLen ? ` of length ${length4}` : "";
2174
+ const ofLen = needsLen ? ` of length ${length5}` : "";
2175
2175
  const got = bytes ? `length=${len}` : `type=${typeof value}`;
2176
2176
  throw new Error(prefix + "expected Uint8Array" + ofLen + ", got " + got);
2177
2177
  }
@@ -2787,15 +2787,15 @@ var init_curve = __esm({
2787
2787
  const { windows, windowSize } = calcWOpts(W, this.bits);
2788
2788
  const points = [];
2789
2789
  let p = point;
2790
- let base4 = p;
2790
+ let base5 = p;
2791
2791
  for (let window = 0; window < windows; window++) {
2792
- base4 = p;
2793
- points.push(base4);
2792
+ base5 = p;
2793
+ points.push(base5);
2794
2794
  for (let i = 1; i < windowSize; i++) {
2795
- base4 = base4.add(p);
2796
- points.push(base4);
2795
+ base5 = base5.add(p);
2796
+ points.push(base5);
2797
2797
  }
2798
- p = base4.double();
2798
+ p = base5.double();
2799
2799
  }
2800
2800
  return points;
2801
2801
  }
@@ -3770,10 +3770,10 @@ var init_dist = __esm({
3770
3770
  [REPLICA_ERROR] = true;
3771
3771
  code;
3772
3772
  detail;
3773
- constructor(code4, message, detail, options) {
3773
+ constructor(code5, message, detail, options) {
3774
3774
  super(message, options);
3775
3775
  this.name = "ReplicaError";
3776
- this.code = code4;
3776
+ this.code = code5;
3777
3777
  if (detail !== void 0) this.detail = detail;
3778
3778
  }
3779
3779
  };
@@ -4059,10 +4059,10 @@ var init_profile_gate = __esm({
4059
4059
  [REPLICA_ERROR2] = true;
4060
4060
  code;
4061
4061
  detail;
4062
- constructor(code4, message, detail, options) {
4062
+ constructor(code5, message, detail, options) {
4063
4063
  super(message, options);
4064
4064
  this.name = "ReplicaError";
4065
- this.code = code4;
4065
+ this.code = code5;
4066
4066
  if (detail !== void 0) this.detail = detail;
4067
4067
  }
4068
4068
  };
@@ -4083,8 +4083,8 @@ import { dirname as dirname3, join as join22, resolve as resolve2 } from "path";
4083
4083
  import { constants as fsConstants3 } from "fs";
4084
4084
  import { lstat, open as open3, readdir as readdir3, rmdir, unlink } from "fs/promises";
4085
4085
  import { join as join7, parse, resolve, sep } from "path";
4086
- function isReplicaError(error, code4) {
4087
- return typeof error === "object" && error !== null && error[REPLICA_ERROR3] === true && (code4 === void 0 || error.code === code4);
4086
+ function isReplicaError(error, code5) {
4087
+ return typeof error === "object" && error !== null && error[REPLICA_ERROR3] === true && (code5 === void 0 || error.code === code5);
4088
4088
  }
4089
4089
  function assertFolderPrefix3(prefix) {
4090
4090
  const validFolder = typeof prefix === "string" && prefix.length > 0 && !prefix.startsWith("/") && !prefix.includes("//") && prefix.endsWith("/");
@@ -4572,9 +4572,9 @@ function entryOf(row) {
4572
4572
  }
4573
4573
  function storageError(error, action) {
4574
4574
  if (isReplicaError(error)) return error;
4575
- const code4 = errnoOf(error);
4575
+ const code5 = errnoOf(error);
4576
4576
  const message = error instanceof Error ? error.message : String(error);
4577
- if (code4 === "ENOSPC" || code4 === "EDQUOT" || /SQLITE_FULL|database or disk is full/i.test(`${String(code4)} ${message}`)) {
4577
+ if (code5 === "ENOSPC" || code5 === "EDQUOT" || /SQLITE_FULL|database or disk is full/i.test(`${String(code5)} ${message}`)) {
4578
4578
  return new ReplicaError3(ReplicaErrorCode3.STORAGE_FULL, `${action}: the local disk is full.`, void 0, { cause: error });
4579
4579
  }
4580
4580
  return new ReplicaError3(ReplicaErrorCode3.STORAGE_ERROR, `${action}: ${message}`, void 0, { cause: error });
@@ -4748,10 +4748,10 @@ var init_sqlite = __esm({
4748
4748
  [REPLICA_ERROR3] = true;
4749
4749
  code;
4750
4750
  detail;
4751
- constructor(code4, message, detail, options) {
4751
+ constructor(code5, message, detail, options) {
4752
4752
  super(message, options);
4753
4753
  this.name = "ReplicaError";
4754
- this.code = code4;
4754
+ this.code = code5;
4755
4755
  if (detail !== void 0) this.detail = detail;
4756
4756
  }
4757
4757
  };
@@ -5327,8 +5327,8 @@ CREATE TABLE IF NOT EXISTS grant_install (
5327
5327
  if (this.#readonlySnapshot) {
5328
5328
  throw new ReplicaError3(ReplicaErrorCode3.STORAGE_ERROR, "A read-only replica snapshot cannot mutate the shared database.");
5329
5329
  }
5330
- const read4 = activeReadSection.getStore();
5331
- if (read4?.active && read4.controller === this) {
5330
+ const read5 = activeReadSection.getStore();
5331
+ if (read5?.active && read5.controller === this) {
5332
5332
  throw new ReplicaError3(
5333
5333
  ReplicaErrorCode3.STORAGE_ERROR,
5334
5334
  "mutation attempted on the same controller while its readTransaction section is active; this would deadlock"
@@ -6325,7 +6325,7 @@ function assertApprovedEntry(profile, path, actual, recorded) {
6325
6325
  throw refuseUnsafeReplicaPath(profile, `legacy path "${path}" changed since the recorded inventory`);
6326
6326
  }
6327
6327
  }
6328
- function assertRecordedChild(profile, name, layout, inventory, empty4) {
6328
+ function assertRecordedChild(profile, name, layout, inventory, empty5) {
6329
6329
  const prefix = `replicas/${name}/`;
6330
6330
  const root = inventory.roots.get(`replicas/${name}`);
6331
6331
  if (!root || root.dev !== layout.rootIdentity.dev || root.ino !== layout.rootIdentity.ino) {
@@ -6344,7 +6344,7 @@ function assertRecordedChild(profile, name, layout, inventory, empty4) {
6344
6344
  }
6345
6345
  const database = [...layout.knownEntries, ...layout.unknownEntries].some((entry) => entry.path === "replica.db");
6346
6346
  const missingWasApproved = inventory.missingDatabases.has(prefix + "replica.db");
6347
- if (missingWasApproved && database || !database && !empty4 && !missingWasApproved) {
6347
+ if (missingWasApproved && database || !database && !empty5 && !missingWasApproved) {
6348
6348
  throw refuseUnsafeReplicaPath(profile, `replica entry "${name}" has a different database than was approved`);
6349
6349
  }
6350
6350
  }
@@ -6426,8 +6426,8 @@ async function removeProfileReplicas(profile, options = {}) {
6426
6426
  const removed = [];
6427
6427
  const opened = [];
6428
6428
  try {
6429
- for (const { entry, identity, empty: empty4 } of checked) {
6430
- if (!empty4) continue;
6429
+ for (const { entry, identity, empty: empty5 } of checked) {
6430
+ if (!empty5) continue;
6431
6431
  await pinned.assertNamed();
6432
6432
  const current = await safeReplicaEntry(profile, root, entry);
6433
6433
  if (current.identity.dev !== identity.dev || current.identity.ino !== identity.ino) {
@@ -6454,8 +6454,8 @@ async function removeProfileReplicas(profile, options = {}) {
6454
6454
  await removeEmptyRoot(removed);
6455
6455
  return removed;
6456
6456
  }
6457
- for (const { entry, empty: empty4, identity, layout } of checked) {
6458
- if (empty4 || !layout?.knownEntries.some((item) => item.path === "replica.db")) continue;
6457
+ for (const { entry, empty: empty5, identity, layout } of checked) {
6458
+ if (empty5 || !layout?.knownEntries.some((item) => item.path === "replica.db")) continue;
6459
6459
  await pinned.assertNamed();
6460
6460
  const { path: entryPath, identity: expectedDirectory } = await safeReplicaEntry(profile, root, entry);
6461
6461
  if (expectedDirectory.dev !== identity.dev || expectedDirectory.ino !== identity.ino) {
@@ -6488,8 +6488,8 @@ async function removeProfileReplicas(profile, options = {}) {
6488
6488
  }
6489
6489
  opened[opened.length - 1].lease = lease;
6490
6490
  }
6491
- for (const { entry, empty: empty4, path, layout } of checked) {
6492
- if (empty4) continue;
6491
+ for (const { entry, empty: empty5, path, layout } of checked) {
6492
+ if (empty5) continue;
6493
6493
  await pinned.assertNamed();
6494
6494
  const replica = opened.find(({ name }) => name === entry.name);
6495
6495
  try {
@@ -6811,14 +6811,14 @@ async function recoverPendingLogout(name) {
6811
6811
  if (report.failed.length || report.remaining) {
6812
6812
  throw new CLIError(
6813
6813
  "REPLICA_PURGE_FAILED",
6814
- `A durable logout is pending (${report.failed.map(({ code: code4 }) => code4).join(", ") || `${report.remaining} intents remaining`}). Network restore and replica reads remain blocked; retry this command to complete credential and replica cleanup.`,
6814
+ `A durable logout is pending (${report.failed.map(({ code: code5 }) => code5).join(", ") || `${report.remaining} intents remaining`}). Network restore and replica reads remain blocked; retry this command to complete credential and replica cleanup.`,
6815
6815
  ExitCode.ERROR,
6816
6816
  { failed: report.failed, remaining: report.remaining }
6817
6817
  );
6818
6818
  }
6819
6819
  }
6820
6820
  function refuseRestoredGate(report) {
6821
- if (report.failed.some(({ code: code4 }) => code4 === "gate_restored")) {
6821
+ if (report.failed.some(({ code: code5 }) => code5 === "gate_restored")) {
6822
6822
  throw new CLIError("REPLICA_GATED", RESTORED_GATE_MESSAGE, ExitCode.ERROR, { failed: report.failed });
6823
6823
  }
6824
6824
  }
@@ -19891,19 +19891,19 @@ function mailboxCredentialCommitment(target) {
19891
19891
  credentialType: EMAIL_CREDENTIAL_TYPE
19892
19892
  };
19893
19893
  }
19894
- function prepareAddressedShare(request) {
19894
+ function prepareAddressedShare(request2) {
19895
19895
  try {
19896
- canonicalShareFilename2(request.filename);
19896
+ canonicalShareFilename2(request2.filename);
19897
19897
  } catch {
19898
19898
  throw new TypeError("addressed filename is invalid");
19899
19899
  }
19900
- if (request.actions.length === 0 || request.policyActions.length === 0) throw new TypeError("addressed share actions are empty");
19901
- if (request.policyActions.some((action) => !OWNER_SHARE_ACTIONS.has(action))) throw new TypeError("addressed share action is not supported");
19902
- if (request.deliveryEmail !== void 0 && !isEnvelopeDeliveryEmail(request.deliveryEmail)) throw new TypeError("delivery email is not a valid envelope address");
19903
- const target = normalizeShareTarget(request.target);
19900
+ if (request2.actions.length === 0 || request2.policyActions.length === 0) throw new TypeError("addressed share actions are empty");
19901
+ if (request2.policyActions.some((action) => !OWNER_SHARE_ACTIONS.has(action))) throw new TypeError("addressed share action is not supported");
19902
+ if (request2.deliveryEmail !== void 0 && !isEnvelopeDeliveryEmail(request2.deliveryEmail)) throw new TypeError("delivery email is not a valid envelope address");
19903
+ const target = normalizeShareTarget(request2.target);
19904
19904
  if (target.kind === "bearer") throw new TypeError("addressed target is required");
19905
19905
  if (target.kind === "recipientDid") return { target };
19906
- if (target.kind === "emailDomain" && request.deliveryEmail !== void 0 && (request.deliveryEmail !== request.deliveryEmail.toLowerCase() || !request.deliveryEmail.endsWith(`@${target.domain}`))) {
19906
+ if (target.kind === "emailDomain" && request2.deliveryEmail !== void 0 && (request2.deliveryEmail !== request2.deliveryEmail.toLowerCase() || !request2.deliveryEmail.endsWith(`@${target.domain}`))) {
19907
19907
  throw new TypeError("email-domain delivery address must be a lowercase mailbox at the domain");
19908
19908
  }
19909
19909
  return { target, credentialRequirement: mailboxCredentialCommitment(target) };
@@ -20217,9 +20217,9 @@ var cache22 = /* @__PURE__ */ new WeakMap();
20217
20217
  function baseCache22(cid2) {
20218
20218
  const baseCache32 = cache22.get(cid2);
20219
20219
  if (baseCache32 == null) {
20220
- const baseCache4 = /* @__PURE__ */ new Map();
20221
- cache22.set(cid2, baseCache4);
20222
- return baseCache4;
20220
+ const baseCache42 = /* @__PURE__ */ new Map();
20221
+ cache22.set(cid2, baseCache42);
20222
+ return baseCache42;
20223
20223
  }
20224
20224
  return baseCache32;
20225
20225
  }
@@ -20887,6 +20887,9 @@ function parseNativeShareUrl(value) {
20887
20887
  return token;
20888
20888
  }
20889
20889
 
20890
+ // ../share-envelope/dist/index.js
20891
+ init_sha2();
20892
+
20890
20893
  // ../../node_modules/zod/v3/external.js
20891
20894
  var external_exports3 = {};
20892
20895
  __export(external_exports3, {
@@ -21881,8 +21884,8 @@ function isValidJWT3(jwt, alg) {
21881
21884
  const [header] = jwt.split(".");
21882
21885
  if (!header)
21883
21886
  return false;
21884
- const base644 = header.replace(/-/g, "+").replace(/_/g, "/").padEnd(header.length + (4 - header.length % 4) % 4, "=");
21885
- const decoded = JSON.parse(atob(base644));
21887
+ const base645 = header.replace(/-/g, "+").replace(/_/g, "/").padEnd(header.length + (4 - header.length % 4) % 4, "=");
21888
+ const decoded = JSON.parse(atob(base645));
21886
21889
  if (typeof decoded !== "object" || decoded === null)
21887
21890
  return false;
21888
21891
  if ("typ" in decoded && decoded?.typ !== "JWT")
@@ -24536,23 +24539,23 @@ var ZodEffects3 = class extends ZodType3 {
24536
24539
  }
24537
24540
  if (effect.type === "transform") {
24538
24541
  if (ctx.common.async === false) {
24539
- const base4 = this._def.schema._parseSync({
24542
+ const base5 = this._def.schema._parseSync({
24540
24543
  data: ctx.data,
24541
24544
  path: ctx.path,
24542
24545
  parent: ctx
24543
24546
  });
24544
- if (!isValid3(base4))
24547
+ if (!isValid3(base5))
24545
24548
  return INVALID3;
24546
- const result = effect.transform(base4.value, checkCtx);
24549
+ const result = effect.transform(base5.value, checkCtx);
24547
24550
  if (result instanceof Promise) {
24548
24551
  throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);
24549
24552
  }
24550
24553
  return { status: status.value, value: result };
24551
24554
  } else {
24552
- return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base4) => {
24553
- if (!isValid3(base4))
24555
+ return this._def.schema._parseAsync({ data: ctx.data, path: ctx.path, parent: ctx }).then((base5) => {
24556
+ if (!isValid3(base5))
24554
24557
  return INVALID3;
24555
- return Promise.resolve(effect.transform(base4.value, checkCtx)).then((result) => ({
24558
+ return Promise.resolve(effect.transform(base5.value, checkCtx)).then((result) => ({
24556
24559
  status: status.value,
24557
24560
  value: result
24558
24561
  }));
@@ -25785,6 +25788,10 @@ function encodeCID3(version2, code22, multihash) {
25785
25788
  var cidSymbol3 = /* @__PURE__ */ Symbol.for("@ipld/js-cid/CID");
25786
25789
  var code3 = 85;
25787
25790
  var SHA256_CODE3 = 18;
25791
+ async function computeCid2(bytes) {
25792
+ const digest = create3(SHA256_CODE3, sha256(new Uint8Array(bytes)));
25793
+ return CID3.create(1, code3, digest).toString();
25794
+ }
25788
25795
  function isCanonicalRawCid3(cidString) {
25789
25796
  let cid;
25790
25797
  try {
@@ -25818,6 +25825,9 @@ var base64urlpad3 = rfc46483({
25818
25825
  alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=",
25819
25826
  bitsPerChar: 6
25820
25827
  });
25828
+ function toBase64Url2(bytes) {
25829
+ return base64url3.baseEncode(bytes);
25830
+ }
25821
25831
  function fromBase64Url3(text) {
25822
25832
  const bytes = base64url3.baseDecode(text);
25823
25833
  if (base64url3.baseEncode(bytes) !== text) {
@@ -26315,7 +26325,71 @@ function canonicalMailbox2(value) {
26315
26325
  if (local.length > 64 || !/^[a-z0-9#$&'*+/=?^_`{|}~-]+(?:\.[a-z0-9#$&'*+/=?^_`{|}~-]+)*$/.test(local) || !isCanonicalEmailDomain2(domain)) return void 0;
26316
26326
  return Object.freeze({ email, domain });
26317
26327
  }
26328
+ var KEY_LENGTH22 = 32;
26318
26329
  var MAX_INLINE_BYTES3 = 256 * 1024;
26330
+ function assertCanonicalCid2(cidString) {
26331
+ const cid = CID3.parse(cidString);
26332
+ if (cid.version !== 1 || cid.code !== code3 || cid.multihash.code !== 18 || // sha2-256 (0x12) only, at the link layer too
26333
+ cid.toString() !== cidString) {
26334
+ throw new TypeError(`not a canonical CIDv1 raw sha2-256 base32 CID: ${cidString}`);
26335
+ }
26336
+ }
26337
+ async function encodeSealedInlineShareUrl2(parts) {
26338
+ if (!isCanonicalHttpsOrigin3(parts.origin)) throw new TypeError("origin must be a canonical https origin");
26339
+ if (parts.ciphertext.byteLength === 0 || parts.ciphertext.byteLength > MAX_INLINE_BYTES3) throw new RangeError("inline ciphertext is outside the allowed size");
26340
+ if (parts.key32.byteLength !== KEY_LENGTH22) throw new TypeError("inline key must be 32 bytes");
26341
+ const ciphertextCid = await computeCid2(parts.ciphertext);
26342
+ const payload = canonicalize3({
26343
+ v: 2,
26344
+ c: toBase64Url2(parts.ciphertext),
26345
+ cid: ciphertextCid,
26346
+ k: toBase64Url2(parts.key32)
26347
+ });
26348
+ const payloadBytes = new TextEncoder().encode(payload);
26349
+ if (payloadBytes.byteLength > MAX_INLINE_BYTES3 * 2) throw new RangeError("inline URL is too large");
26350
+ return `${parts.origin}/s/inline#v=2&p=${toBase64Url2(payloadBytes)}`;
26351
+ }
26352
+ async function parseSealedInlineShareUrl2(url, options = {}) {
26353
+ const parsed = new URL(url);
26354
+ if (parsed.protocol !== "https:" || parsed.username !== "" || parsed.password !== "") throw new TypeError("sealed inline share URL must be canonical HTTPS without userinfo");
26355
+ if (!isCanonicalHttpsOrigin3(parsed.origin) || options.expectedOrigin !== void 0 && parsed.origin !== options.expectedOrigin) throw new TypeError("sealed inline share URL origin is not trusted");
26356
+ if (parsed.pathname !== "/s/inline" || parsed.search !== "") throw new TypeError("not a Node sealed-inline share URL");
26357
+ if (url !== `${parsed.origin}/s/inline${parsed.hash}`) throw new TypeError("sealed inline share URL is not lexically canonical");
26358
+ const prefix = "#v=2&p=";
26359
+ if (!parsed.hash.startsWith(prefix)) throw new TypeError("sealed inline URL is missing its canonical fragment");
26360
+ const encoded = parsed.hash.slice(prefix.length);
26361
+ if (encoded.length === 0 || parsed.hash !== `${prefix}${encoded}`) throw new TypeError("sealed inline URL fragment is not canonical");
26362
+ let payloadBytes;
26363
+ try {
26364
+ payloadBytes = fromBase64Url3(encoded);
26365
+ } catch {
26366
+ throw new TypeError("sealed inline payload is not canonical base64url");
26367
+ }
26368
+ if (payloadBytes.byteLength === 0 || payloadBytes.byteLength > MAX_INLINE_BYTES3 * 2) throw new TypeError("sealed inline payload is too large");
26369
+ const payloadText = new TextDecoder("utf-8", { fatal: true }).decode(payloadBytes);
26370
+ let value;
26371
+ try {
26372
+ value = JSON.parse(payloadText);
26373
+ } catch {
26374
+ throw new TypeError("sealed inline payload is not valid JSON");
26375
+ }
26376
+ if (typeof value !== "object" || value === null || Array.isArray(value) || canonicalize3(value) !== payloadText) throw new TypeError("sealed inline payload is not canonical JSON");
26377
+ const record2 = value;
26378
+ if (Object.keys(record2).length !== 4 || record2.v !== 2 || typeof record2.c !== "string" || typeof record2.cid !== "string" || typeof record2.k !== "string") throw new TypeError("sealed inline payload has invalid fields");
26379
+ let ciphertext;
26380
+ let key32;
26381
+ try {
26382
+ ciphertext = fromBase64Url3(record2.c);
26383
+ key32 = fromBase64Url3(record2.k);
26384
+ } catch {
26385
+ throw new TypeError("sealed inline payload has invalid base64url material");
26386
+ }
26387
+ if (ciphertext.byteLength === 0 || ciphertext.byteLength > MAX_INLINE_BYTES3) throw new TypeError("sealed inline ciphertext is outside the allowed size");
26388
+ if (key32.byteLength !== KEY_LENGTH22) throw new TypeError("sealed inline key must be 32 bytes");
26389
+ assertCanonicalCid2(record2.cid);
26390
+ if (await computeCid2(ciphertext) !== record2.cid) throw new TypeError("sealed inline ciphertext does not match its CID");
26391
+ return { kind: "inline", ciphertextCid: record2.cid, ciphertext, key32 };
26392
+ }
26319
26393
 
26320
26394
  // src/commands/share.ts
26321
26395
  import { ProfileLockTimeoutError as ProfileLockTimeoutError2 } from "@tinycloud/operations/state";
@@ -26366,16 +26440,16 @@ function statusOf(error, depth = 0) {
26366
26440
  return direct ?? (depth === 0 ? statusOf(fields.cause, 1) : void 0);
26367
26441
  }
26368
26442
  function codeOf(error) {
26369
- const code4 = record(error)?.code;
26370
- return typeof code4 === "string" && /^[A-Z][A-Z0-9_]{2,63}$/.test(code4) ? code4 : void 0;
26443
+ const code5 = record(error)?.code;
26444
+ return typeof code5 === "string" && /^[A-Z][A-Z0-9_]{2,63}$/.test(code5) ? code5 : void 0;
26371
26445
  }
26372
26446
  function classifyShareFailure(error, loginHint) {
26373
26447
  const status = statusOf(error);
26374
26448
  const verdict = authorizationVerdictOf2(error);
26375
26449
  const message = error instanceof Error ? error.message : "";
26376
- const code4 = codeOf(error);
26450
+ const code5 = codeOf(error);
26377
26451
  const detail = (text) => {
26378
- const parts = [status === void 0 ? void 0 : `HTTP ${status}`, code4].filter((part) => part !== void 0);
26452
+ const parts = [status === void 0 ? void 0 : `HTTP ${status}`, code5].filter((part) => part !== void 0);
26379
26453
  return parts.length === 0 ? text : `${text} (${parts.join(", ")})`;
26380
26454
  };
26381
26455
  if (verdict === "unauthenticated" || status === 401) {
@@ -26414,8 +26488,8 @@ function authorizationRequiredJson(result) {
26414
26488
  next: "complete authorization through the configured authority adapter, then retry with the required proof"
26415
26489
  };
26416
26490
  }
26417
- function publishHuman(result) {
26418
- process.stdout.write(`${result.url}
26491
+ function publishHuman(url) {
26492
+ process.stdout.write(`${url}
26419
26493
  `);
26420
26494
  }
26421
26495
  function inspectHuman(result) {
@@ -26584,10 +26658,10 @@ function kvArtifactStore(kv) {
26584
26658
  throw new ArtifactError("storage", `could not write ${key}: ${errorCode(written.error) ?? "unknown error"}`, { cause: written.error });
26585
26659
  },
26586
26660
  async get(key) {
26587
- const read4 = await kv.get(key, { binary: true });
26588
- if (read4.ok) return new Uint8Array(read4.data.data);
26589
- if (errorCode(read4.error) === "KV_NOT_FOUND") return void 0;
26590
- throw new ArtifactError("storage", `could not read ${key}: ${errorCode(read4.error) ?? "unknown error"}`, { cause: read4.error });
26661
+ const read5 = await kv.get(key, { binary: true });
26662
+ if (read5.ok) return new Uint8Array(read5.data.data);
26663
+ if (errorCode(read5.error) === "KV_NOT_FOUND") return void 0;
26664
+ throw new ArtifactError("storage", `could not read ${key}: ${errorCode(read5.error) ?? "unknown error"}`, { cause: read5.error });
26591
26665
  },
26592
26666
  async list(prefix) {
26593
26667
  const keys = [];
@@ -26605,206 +26679,1907 @@ function kvArtifactStore(kv) {
26605
26679
  };
26606
26680
  }
26607
26681
 
26608
- // src/share/errors.ts
26609
- var SharePublishAuthorityError = class extends Error {
26610
- constructor(failure, options) {
26611
- super(failure.kind, options);
26612
- this.failure = failure;
26613
- this.name = "SharePublishAuthorityError";
26614
- }
26615
- };
26616
- var ShareHistoryRetryError = class extends Error {
26617
- constructor(profile) {
26618
- super("sender history changed during the operation");
26619
- this.profile = profile;
26620
- this.name = "ShareHistoryRetryError";
26682
+ // ../share-envelope/dist/short-link.js
26683
+ init_sha2();
26684
+ var empty4 = new Uint8Array(0);
26685
+ function equals6(aa, bb) {
26686
+ if (aa === bb) {
26687
+ return true;
26621
26688
  }
26622
- code = "SHARE_HISTORY_RETRY";
26623
- };
26624
- var ShareHistoryUnreadableError = class extends Error {
26625
- constructor() {
26626
- super("share history is unavailable");
26627
- this.name = "ShareHistoryUnreadableError";
26689
+ if (aa.byteLength !== bb.byteLength) {
26690
+ return false;
26628
26691
  }
26629
- };
26630
- var ShareHistoryReadError = class extends Error {
26631
- constructor() {
26632
- super("share history could not be read");
26633
- this.name = "ShareHistoryReadError";
26692
+ for (let ii = 0; ii < aa.byteLength; ii++) {
26693
+ if (aa[ii] !== bb[ii]) {
26694
+ return false;
26695
+ }
26634
26696
  }
26635
- };
26636
- var HISTORY_WRITE_ERROR_CODES = { EACCES: true, EPERM: true, EROFS: true, ENOSPC: true, EDQUOT: true, EIO: true };
26637
- function shareHistoryReason(error) {
26638
- if (error instanceof ShareHistoryUnreadableError) return "HISTORY_UNREADABLE";
26639
- if (error instanceof ShareHistoryReadError) return "HISTORY_READ_FAILED";
26640
- const code4 = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
26641
- return typeof code4 === "string" && HISTORY_WRITE_ERROR_CODES[code4] === true ? "HISTORY_WRITE_FAILED" : "HISTORY_UNAVAILABLE";
26642
- }
26643
-
26644
- // src/share/space-not-ready.ts
26645
- function isSpaceNotFound(error) {
26646
- if (typeof error !== "object" || error === null) return false;
26647
- const message = "message" in error && typeof error.message === "string" ? error.message : "";
26648
- if (!/space not found/i.test(message)) return false;
26649
- const meta = "meta" in error && typeof error.meta === "object" && error.meta !== null ? error.meta : void 0;
26650
- const status = meta !== void 0 && "status" in meta ? meta.status : void 0;
26651
- return status === 404 || /\b404\b/.test(message);
26652
- }
26653
- function spaceNotReadyFailure(cause) {
26654
- return new SharePublishAuthorityError({ kind: "space-not-ready" }, { cause });
26655
- }
26656
- function failIfSpaceNotReady(result) {
26657
- if (!result.ok && isSpaceNotFound(result.error)) throw spaceNotReadyFailure(result.error);
26658
- }
26659
- function artifactSpaceNotReady(error) {
26660
- return error instanceof ArtifactError && isSpaceNotFound(error.cause) ? spaceNotReadyFailure(error.cause) : error;
26661
- }
26662
-
26663
- // src/share/adapters.ts
26664
- init_storage();
26665
- init_profiles();
26666
- init_constants();
26667
- init_errors();
26668
- init_session_expired();
26669
- import { chmod as chmod4, link as link3, open as open8, readFile as readFile7, stat as stat5, unlink as unlink5 } from "fs/promises";
26670
- import { dirname as dirname5, join as join12 } from "path";
26671
- import { createHash } from "crypto";
26672
- import { writeJsonAtomic as writeJsonAtomic2 } from "@tinycloud/operations/state";
26673
- import { withoutBearer } from "@tinycloud/operations/delegation-binding";
26674
- import {
26675
- LocationRecordValidationError,
26676
- LocationRegistryHttpError,
26677
- parseSignedCompactUcanAttenuation,
26678
- parseSignedSiweCacao,
26679
- revokePolicyRootV3,
26680
- signCompactUcanAuthorization
26681
- } from "@tinycloud/sdk-core";
26682
- import { extractSiweExpiration, InvalidRestoredSessionError } from "@tinycloud/node-sdk";
26683
- function requiredKvAction(meta) {
26684
- if (meta === null || typeof meta !== "object" || !("requiredAction" in meta)) return void 0;
26685
- const action = meta.requiredAction;
26686
- return action === "tinycloud.kv/put" || action === "tinycloud.kv/get" || action === "tinycloud.kv/list" ? action : void 0;
26687
- }
26688
- function throwKvUploadFailure(error) {
26689
- const rejection = storageRejection(error);
26690
- if (rejection) throw new SharePublishAuthorityError({ kind: "storage-full", ...rejection });
26691
- throw new SharePublishAuthorityError({ kind: "upload-failed" });
26692
- }
26693
- var DEFAULT_SHARE_ORIGIN = "https://share.tinycloud.xyz";
26694
- var MIN_DOMAIN_DELIVERY_VERSION = "1.17.3";
26695
- function supportsDomainDelivery(version2) {
26696
- if (typeof version2 !== "string") return false;
26697
- const normalized = version2.trim();
26698
- if (normalized.length > 128) return false;
26699
- const match = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/.exec(normalized);
26700
- if (match === null) return false;
26701
- if (match[4] !== void 0 && /(?:^|\.)0[0-9]+(?:\.|$)/.test(match[4])) return false;
26702
- const major = Number(match[1]);
26703
- const minor = Number(match[2]);
26704
- const patch = Number(match[3]);
26705
- if (!Number.isSafeInteger(major) || !Number.isSafeInteger(minor) || !Number.isSafeInteger(patch)) return false;
26706
- if (major !== 1) return major > 1;
26707
- if (minor !== 17) return minor > 17;
26708
- if (patch !== 3) return patch > 3;
26709
- return match[4] === void 0;
26710
- }
26711
- function displayedNodeVersion(version2) {
26712
- if (typeof version2 !== "string") return "(unrecognized)";
26713
- const trimmed = version2.trim();
26714
- return /^[A-Za-z0-9.+_-]{1,64}$/.test(trimmed) ? trimmed : "(unrecognized)";
26715
- }
26716
- var URI_SAFE_FILENAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
26717
- function safeStorageFilename(filename) {
26718
- if (URI_SAFE_FILENAME.test(filename) && !filename.includes("..")) return filename;
26719
- const dot = filename.lastIndexOf(".");
26720
- const extension = dot >= 0 && /^[A-Za-z0-9]{1,16}$/.test(filename.slice(dot + 1)) ? filename.slice(dot + 1) : "";
26721
- const stem = (extension === "" ? filename : filename.slice(0, dot)).normalize("NFKD").replace(/[\u0300-\u036f]/g, "").replace(extension === "" ? /[^A-Za-z0-9_-]+/g : /[^A-Za-z0-9._-]+/g, "-").replace(/\.{2,}/g, ".").replace(/-{2,}/g, "-").slice(0, 100).replace(/^[^A-Za-z0-9]+|[-.]+$/g, "");
26722
- return `${stem === "" ? "share" : stem}${extension === "" ? "" : `.${extension}`}`;
26723
- }
26724
- function scopeDeniedFromArtifactError(error, capability, authority) {
26725
- const cause = error instanceof ArtifactError ? error.cause : void 0;
26726
- const code4 = typeof cause === "object" && cause !== null && "code" in cause ? cause.code : void 0;
26727
- if (code4 !== "AUTH_UNAUTHORIZED" && code4 !== "PERMISSION_DENIED") return void 0;
26728
- const meta = typeof cause === "object" && cause !== null && "meta" in cause ? cause.meta : void 0;
26729
- const requiredAction = requiredKvAction(meta);
26730
- return new SharePublishAuthorityError({
26731
- kind: "scope-denied",
26732
- capability,
26733
- ...requiredAction === void 0 ? {} : { requiredAction },
26734
- localKey: authority.localKey,
26735
- profileName: authority.profileName
26736
- });
26697
+ return true;
26737
26698
  }
26738
- async function storeArtifactVersion(kv, version2, authority) {
26739
- try {
26740
- return await publishArtifactVersion(kvArtifactStore(kv), version2);
26741
- } catch (error) {
26742
- throw scopeDeniedFromArtifactError(error, "KV upload", authority) ?? artifactSpaceNotReady(error);
26699
+ function coerce6(o) {
26700
+ if (o instanceof Uint8Array && o.constructor.name === "Uint8Array") {
26701
+ return o;
26702
+ }
26703
+ if (o instanceof ArrayBuffer) {
26704
+ return new Uint8Array(o);
26705
+ }
26706
+ if (ArrayBuffer.isView(o)) {
26707
+ return new Uint8Array(o.buffer, o.byteOffset, o.byteLength);
26743
26708
  }
26709
+ throw new Error("Unknown type, must be binary type");
26744
26710
  }
26745
- function createEncryptedSessionHistory() {
26746
- const records = /* @__PURE__ */ new Map();
26747
- let operation = Promise.resolve();
26748
- const serial = (action) => {
26749
- const next = operation.then(action, action);
26750
- operation = next.then(() => void 0, () => void 0);
26751
- return next;
26752
- };
26753
- let keyPromise;
26754
- const key = async () => keyPromise ??= crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
26755
- const encode6 = async (record2) => {
26756
- const secret = new TextEncoder().encode(JSON.stringify(record2));
26757
- const iv = crypto.getRandomValues(new Uint8Array(12));
26758
- const encrypted = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-GCM", iv }, await key(), secret));
26759
- const value = new Uint8Array(iv.length + encrypted.length);
26760
- value.set(iv);
26761
- value.set(encrypted, iv.length);
26762
- return value;
26763
- };
26764
- const decode10 = async (value) => JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await crypto.subtle.decrypt({ name: "AES-GCM", iv: value.slice(0, 12) }, await key(), value.slice(12))));
26765
- return {
26766
- async put(record2) {
26767
- return serial(async () => {
26768
- records.set(record2.shareId, await encode6(record2));
26769
- });
26770
- },
26771
- async update(shareId, change) {
26772
- return serial(async () => {
26773
- const value = records.get(shareId);
26774
- if (value === void 0) return void 0;
26775
- const updated = await change(await decode10(value));
26776
- records.set(shareId, await encode6(updated));
26777
- return updated;
26778
- });
26779
- },
26780
- async list() {
26781
- return serial(() => Promise.all([...records.values()].map(decode10)));
26782
- },
26783
- async get(shareId) {
26784
- return serial(async () => {
26785
- const value = records.get(shareId);
26786
- return value === void 0 ? void 0 : decode10(value);
26787
- });
26788
- },
26789
- async delete(shareId) {
26790
- return serial(async () => {
26791
- records.delete(shareId);
26792
- });
26711
+ function base4(ALPHABET, name) {
26712
+ if (ALPHABET.length >= 255) {
26713
+ throw new TypeError("Alphabet too long");
26714
+ }
26715
+ var BASE_MAP = new Uint8Array(256);
26716
+ for (var j = 0; j < BASE_MAP.length; j++) {
26717
+ BASE_MAP[j] = 255;
26718
+ }
26719
+ for (var i = 0; i < ALPHABET.length; i++) {
26720
+ var x = ALPHABET.charAt(i);
26721
+ var xc = x.charCodeAt(0);
26722
+ if (BASE_MAP[xc] !== 255) {
26723
+ throw new TypeError(x + " is ambiguous");
26793
26724
  }
26794
- };
26795
- }
26796
- var SHARE_HISTORY_FILE = "share-history-v2.json";
26797
- var SHARE_HISTORY_LEGACY_FILE = "share-history-v1.bin";
26798
- var PRIVATE_HISTORY_MODE = 384;
26799
- async function signShareHistoryBytes(bytes, profile) {
26800
- const context = await ProfileManager.resolveContext({ profile });
26801
- if (context.profile !== profile) throw new ShareHistoryRetryError(profile);
26802
- const { ensureAuthenticated: ensureAuthenticated2 } = await Promise.resolve().then(() => (init_sdk(), sdk_exports));
26803
- const signer = await ensureAuthenticated2(context);
26804
- return signer.signSessionBytes(bytes);
26805
- }
26806
- function createEncryptedProfileHistory(profileName, sessionSigner) {
26807
- const HISTORY_VERSION = 2;
26725
+ BASE_MAP[xc] = i;
26726
+ }
26727
+ var BASE = ALPHABET.length;
26728
+ var LEADER = ALPHABET.charAt(0);
26729
+ var FACTOR = Math.log(BASE) / Math.log(256);
26730
+ var iFACTOR = Math.log(256) / Math.log(BASE);
26731
+ function encode33(source) {
26732
+ if (source instanceof Uint8Array)
26733
+ ;
26734
+ else if (ArrayBuffer.isView(source)) {
26735
+ source = new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
26736
+ } else if (Array.isArray(source)) {
26737
+ source = Uint8Array.from(source);
26738
+ }
26739
+ if (!(source instanceof Uint8Array)) {
26740
+ throw new TypeError("Expected Uint8Array");
26741
+ }
26742
+ if (source.length === 0) {
26743
+ return "";
26744
+ }
26745
+ var zeroes = 0;
26746
+ var length23 = 0;
26747
+ var pbegin = 0;
26748
+ var pend = source.length;
26749
+ while (pbegin !== pend && source[pbegin] === 0) {
26750
+ pbegin++;
26751
+ zeroes++;
26752
+ }
26753
+ var size = (pend - pbegin) * iFACTOR + 1 >>> 0;
26754
+ var b58 = new Uint8Array(size);
26755
+ while (pbegin !== pend) {
26756
+ var carry = source[pbegin];
26757
+ var i2 = 0;
26758
+ for (var it1 = size - 1; (carry !== 0 || i2 < length23) && it1 !== -1; it1--, i2++) {
26759
+ carry += 256 * b58[it1] >>> 0;
26760
+ b58[it1] = carry % BASE >>> 0;
26761
+ carry = carry / BASE >>> 0;
26762
+ }
26763
+ if (carry !== 0) {
26764
+ throw new Error("Non-zero carry");
26765
+ }
26766
+ length23 = i2;
26767
+ pbegin++;
26768
+ }
26769
+ var it2 = size - length23;
26770
+ while (it2 !== size && b58[it2] === 0) {
26771
+ it2++;
26772
+ }
26773
+ var str = LEADER.repeat(zeroes);
26774
+ for (; it2 < size; ++it2) {
26775
+ str += ALPHABET.charAt(b58[it2]);
26776
+ }
26777
+ return str;
26778
+ }
26779
+ function decodeUnsafe(source) {
26780
+ if (typeof source !== "string") {
26781
+ throw new TypeError("Expected String");
26782
+ }
26783
+ if (source.length === 0) {
26784
+ return new Uint8Array();
26785
+ }
26786
+ var psz = 0;
26787
+ if (source[psz] === " ") {
26788
+ return;
26789
+ }
26790
+ var zeroes = 0;
26791
+ var length23 = 0;
26792
+ while (source[psz] === LEADER) {
26793
+ zeroes++;
26794
+ psz++;
26795
+ }
26796
+ var size = (source.length - psz) * FACTOR + 1 >>> 0;
26797
+ var b256 = new Uint8Array(size);
26798
+ while (source[psz]) {
26799
+ var carry = BASE_MAP[source.charCodeAt(psz)];
26800
+ if (carry === 255) {
26801
+ return;
26802
+ }
26803
+ var i2 = 0;
26804
+ for (var it3 = size - 1; (carry !== 0 || i2 < length23) && it3 !== -1; it3--, i2++) {
26805
+ carry += BASE * b256[it3] >>> 0;
26806
+ b256[it3] = carry % 256 >>> 0;
26807
+ carry = carry / 256 >>> 0;
26808
+ }
26809
+ if (carry !== 0) {
26810
+ throw new Error("Non-zero carry");
26811
+ }
26812
+ length23 = i2;
26813
+ psz++;
26814
+ }
26815
+ if (source[psz] === " ") {
26816
+ return;
26817
+ }
26818
+ var it4 = size - length23;
26819
+ while (it4 !== size && b256[it4] === 0) {
26820
+ it4++;
26821
+ }
26822
+ var vch = new Uint8Array(zeroes + (size - it4));
26823
+ var j2 = zeroes;
26824
+ while (it4 !== size) {
26825
+ vch[j2++] = b256[it4++];
26826
+ }
26827
+ return vch;
26828
+ }
26829
+ function decode53(string) {
26830
+ var buffer = decodeUnsafe(string);
26831
+ if (buffer) {
26832
+ return buffer;
26833
+ }
26834
+ throw new Error(`Non-${name} character`);
26835
+ }
26836
+ return {
26837
+ encode: encode33,
26838
+ decodeUnsafe,
26839
+ decode: decode53
26840
+ };
26841
+ }
26842
+ var src4 = base4;
26843
+ var _brrp__multiformats_scope_baseX4 = src4;
26844
+ var base_x_default4 = _brrp__multiformats_scope_baseX4;
26845
+ var Encoder4 = class {
26846
+ name;
26847
+ prefix;
26848
+ baseEncode;
26849
+ constructor(name, prefix, baseEncode) {
26850
+ this.name = name;
26851
+ this.prefix = prefix;
26852
+ this.baseEncode = baseEncode;
26853
+ }
26854
+ encode(bytes) {
26855
+ if (bytes instanceof Uint8Array) {
26856
+ return `${this.prefix}${this.baseEncode(bytes)}`;
26857
+ } else {
26858
+ throw Error("Unknown type, must be binary type");
26859
+ }
26860
+ }
26861
+ };
26862
+ var Decoder4 = class {
26863
+ name;
26864
+ prefix;
26865
+ baseDecode;
26866
+ prefixCodePoint;
26867
+ constructor(name, prefix, baseDecode) {
26868
+ this.name = name;
26869
+ this.prefix = prefix;
26870
+ const prefixCodePoint = prefix.codePointAt(0);
26871
+ if (prefixCodePoint === void 0) {
26872
+ throw new Error("Invalid prefix character");
26873
+ }
26874
+ this.prefixCodePoint = prefixCodePoint;
26875
+ this.baseDecode = baseDecode;
26876
+ }
26877
+ decode(text) {
26878
+ if (typeof text === "string") {
26879
+ if (text.codePointAt(0) !== this.prefixCodePoint) {
26880
+ throw Error(`Unable to decode multibase string ${JSON.stringify(text)}, ${this.name} decoder only supports inputs prefixed with ${this.prefix}`);
26881
+ }
26882
+ return this.baseDecode(text.slice(this.prefix.length));
26883
+ } else {
26884
+ throw Error("Can only multibase decode strings");
26885
+ }
26886
+ }
26887
+ or(decoder) {
26888
+ return or4(this, decoder);
26889
+ }
26890
+ };
26891
+ var ComposedDecoder4 = class {
26892
+ decoders;
26893
+ constructor(decoders) {
26894
+ this.decoders = decoders;
26895
+ }
26896
+ or(decoder) {
26897
+ return or4(this, decoder);
26898
+ }
26899
+ decode(input) {
26900
+ const prefix = input[0];
26901
+ const decoder = this.decoders[prefix];
26902
+ if (decoder != null) {
26903
+ return decoder.decode(input);
26904
+ } else {
26905
+ throw RangeError(`Unable to decode multibase string ${JSON.stringify(input)}, only inputs prefixed with ${Object.keys(this.decoders)} are supported`);
26906
+ }
26907
+ }
26908
+ };
26909
+ function or4(left, right) {
26910
+ return new ComposedDecoder4({
26911
+ ...left.decoders ?? { [left.prefix]: left },
26912
+ ...right.decoders ?? { [right.prefix]: right }
26913
+ });
26914
+ }
26915
+ var Codec4 = class {
26916
+ name;
26917
+ prefix;
26918
+ baseEncode;
26919
+ baseDecode;
26920
+ encoder;
26921
+ decoder;
26922
+ constructor(name, prefix, baseEncode, baseDecode) {
26923
+ this.name = name;
26924
+ this.prefix = prefix;
26925
+ this.baseEncode = baseEncode;
26926
+ this.baseDecode = baseDecode;
26927
+ this.encoder = new Encoder4(name, prefix, baseEncode);
26928
+ this.decoder = new Decoder4(name, prefix, baseDecode);
26929
+ }
26930
+ encode(input) {
26931
+ return this.encoder.encode(input);
26932
+ }
26933
+ decode(input) {
26934
+ return this.decoder.decode(input);
26935
+ }
26936
+ };
26937
+ function from4({ name, prefix, encode: encode33, decode: decode53 }) {
26938
+ return new Codec4(name, prefix, encode33, decode53);
26939
+ }
26940
+ function baseX4({ name, prefix, alphabet }) {
26941
+ const { encode: encode33, decode: decode53 } = base_x_default4(alphabet, name);
26942
+ return from4({
26943
+ prefix,
26944
+ name,
26945
+ encode: encode33,
26946
+ decode: (text) => coerce6(decode53(text))
26947
+ });
26948
+ }
26949
+ function decode10(string, alphabetIdx, bitsPerChar, name) {
26950
+ let end = string.length;
26951
+ while (string[end - 1] === "=") {
26952
+ --end;
26953
+ }
26954
+ const out = new Uint8Array(end * bitsPerChar / 8 | 0);
26955
+ let bits = 0;
26956
+ let buffer = 0;
26957
+ let written = 0;
26958
+ for (let i = 0; i < end; ++i) {
26959
+ const value = alphabetIdx[string[i]];
26960
+ if (value === void 0) {
26961
+ throw new SyntaxError(`Non-${name} character`);
26962
+ }
26963
+ buffer = buffer << bitsPerChar | value;
26964
+ bits += bitsPerChar;
26965
+ if (bits >= 8) {
26966
+ bits -= 8;
26967
+ out[written++] = 255 & buffer >> bits;
26968
+ }
26969
+ }
26970
+ if (bits >= bitsPerChar || (255 & buffer << 8 - bits) !== 0) {
26971
+ throw new SyntaxError("Unexpected end of data");
26972
+ }
26973
+ return out;
26974
+ }
26975
+ function encode6(data, alphabet, bitsPerChar) {
26976
+ const pad = alphabet[alphabet.length - 1] === "=";
26977
+ const mask = (1 << bitsPerChar) - 1;
26978
+ let out = "";
26979
+ let bits = 0;
26980
+ let buffer = 0;
26981
+ for (let i = 0; i < data.length; ++i) {
26982
+ buffer = buffer << 8 | data[i];
26983
+ bits += 8;
26984
+ while (bits > bitsPerChar) {
26985
+ bits -= bitsPerChar;
26986
+ out += alphabet[mask & buffer >> bits];
26987
+ }
26988
+ }
26989
+ if (bits !== 0) {
26990
+ out += alphabet[mask & buffer << bitsPerChar - bits];
26991
+ }
26992
+ if (pad) {
26993
+ while ((out.length * bitsPerChar & 7) !== 0) {
26994
+ out += "=";
26995
+ }
26996
+ }
26997
+ return out;
26998
+ }
26999
+ function createAlphabetIdx4(alphabet) {
27000
+ const alphabetIdx = {};
27001
+ for (let i = 0; i < alphabet.length; ++i) {
27002
+ alphabetIdx[alphabet[i]] = i;
27003
+ }
27004
+ return alphabetIdx;
27005
+ }
27006
+ function rfc46484({ name, prefix, bitsPerChar, alphabet }) {
27007
+ const alphabetIdx = createAlphabetIdx4(alphabet);
27008
+ return from4({
27009
+ prefix,
27010
+ name,
27011
+ encode(input) {
27012
+ return encode6(input, alphabet, bitsPerChar);
27013
+ },
27014
+ decode(input) {
27015
+ return decode10(input, alphabetIdx, bitsPerChar, name);
27016
+ }
27017
+ });
27018
+ }
27019
+ var base644 = rfc46484({
27020
+ prefix: "m",
27021
+ name: "base64",
27022
+ alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
27023
+ bitsPerChar: 6
27024
+ });
27025
+ var base64pad4 = rfc46484({
27026
+ prefix: "M",
27027
+ name: "base64pad",
27028
+ alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
27029
+ bitsPerChar: 6
27030
+ });
27031
+ var base64url4 = rfc46484({
27032
+ prefix: "u",
27033
+ name: "base64url",
27034
+ alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
27035
+ bitsPerChar: 6
27036
+ });
27037
+ var base64urlpad4 = rfc46484({
27038
+ prefix: "U",
27039
+ name: "base64urlpad",
27040
+ alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=",
27041
+ bitsPerChar: 6
27042
+ });
27043
+ function toBase64Url3(bytes) {
27044
+ return base64url4.baseEncode(bytes);
27045
+ }
27046
+ function fromBase64Url4(text) {
27047
+ const bytes = base64url4.baseDecode(text);
27048
+ if (base64url4.baseEncode(bytes) !== text) {
27049
+ throw new TypeError("non-canonical base64url input");
27050
+ }
27051
+ return bytes;
27052
+ }
27053
+ var base324 = rfc46484({
27054
+ prefix: "b",
27055
+ name: "base32",
27056
+ alphabet: "abcdefghijklmnopqrstuvwxyz234567",
27057
+ bitsPerChar: 5
27058
+ });
27059
+ var base32upper4 = rfc46484({
27060
+ prefix: "B",
27061
+ name: "base32upper",
27062
+ alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567",
27063
+ bitsPerChar: 5
27064
+ });
27065
+ var base32pad4 = rfc46484({
27066
+ prefix: "c",
27067
+ name: "base32pad",
27068
+ alphabet: "abcdefghijklmnopqrstuvwxyz234567=",
27069
+ bitsPerChar: 5
27070
+ });
27071
+ var base32padupper4 = rfc46484({
27072
+ prefix: "C",
27073
+ name: "base32padupper",
27074
+ alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=",
27075
+ bitsPerChar: 5
27076
+ });
27077
+ var base32hex4 = rfc46484({
27078
+ prefix: "v",
27079
+ name: "base32hex",
27080
+ alphabet: "0123456789abcdefghijklmnopqrstuv",
27081
+ bitsPerChar: 5
27082
+ });
27083
+ var base32hexupper4 = rfc46484({
27084
+ prefix: "V",
27085
+ name: "base32hexupper",
27086
+ alphabet: "0123456789ABCDEFGHIJKLMNOPQRSTUV",
27087
+ bitsPerChar: 5
27088
+ });
27089
+ var base32hexpad4 = rfc46484({
27090
+ prefix: "t",
27091
+ name: "base32hexpad",
27092
+ alphabet: "0123456789abcdefghijklmnopqrstuv=",
27093
+ bitsPerChar: 5
27094
+ });
27095
+ var base32hexpadupper4 = rfc46484({
27096
+ prefix: "T",
27097
+ name: "base32hexpadupper",
27098
+ alphabet: "0123456789ABCDEFGHIJKLMNOPQRSTUV=",
27099
+ bitsPerChar: 5
27100
+ });
27101
+ var base32z4 = rfc46484({
27102
+ prefix: "h",
27103
+ name: "base32z",
27104
+ alphabet: "ybndrfg8ejkmcpqxot1uwisza345h769",
27105
+ bitsPerChar: 5
27106
+ });
27107
+ var base364 = baseX4({
27108
+ prefix: "k",
27109
+ name: "base36",
27110
+ alphabet: "0123456789abcdefghijklmnopqrstuvwxyz"
27111
+ });
27112
+ var base36upper4 = baseX4({
27113
+ prefix: "K",
27114
+ name: "base36upper",
27115
+ alphabet: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
27116
+ });
27117
+ var base58btc4 = baseX4({
27118
+ name: "base58btc",
27119
+ prefix: "z",
27120
+ alphabet: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
27121
+ });
27122
+ var base58flickr4 = baseX4({
27123
+ name: "base58flickr",
27124
+ prefix: "Z",
27125
+ alphabet: "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
27126
+ });
27127
+ var encode_14 = encode24;
27128
+ var MSB4 = 128;
27129
+ var REST4 = 127;
27130
+ var MSBALL4 = ~REST4;
27131
+ var INT4 = Math.pow(2, 31);
27132
+ function encode24(num, out, offset) {
27133
+ out = out || [];
27134
+ offset = offset || 0;
27135
+ var oldOffset = offset;
27136
+ while (num >= INT4) {
27137
+ out[offset++] = num & 255 | MSB4;
27138
+ num /= 128;
27139
+ }
27140
+ while (num & MSBALL4) {
27141
+ out[offset++] = num & 255 | MSB4;
27142
+ num >>>= 7;
27143
+ }
27144
+ out[offset] = num | 0;
27145
+ encode24.bytes = offset - oldOffset + 1;
27146
+ return out;
27147
+ }
27148
+ var decode24 = read4;
27149
+ var MSB$14 = 128;
27150
+ var REST$14 = 127;
27151
+ function read4(buf, offset) {
27152
+ var res = 0, offset = offset || 0, shift = 0, counter = offset, b, l = buf.length;
27153
+ do {
27154
+ if (counter >= l) {
27155
+ read4.bytes = 0;
27156
+ throw new RangeError("Could not decode varint");
27157
+ }
27158
+ b = buf[counter++];
27159
+ res += shift < 28 ? (b & REST$14) << shift : (b & REST$14) * Math.pow(2, shift);
27160
+ shift += 7;
27161
+ } while (b >= MSB$14);
27162
+ read4.bytes = counter - offset;
27163
+ return res;
27164
+ }
27165
+ var N14 = Math.pow(2, 7);
27166
+ var N24 = Math.pow(2, 14);
27167
+ var N34 = Math.pow(2, 21);
27168
+ var N44 = Math.pow(2, 28);
27169
+ var N54 = Math.pow(2, 35);
27170
+ var N64 = Math.pow(2, 42);
27171
+ var N74 = Math.pow(2, 49);
27172
+ var N84 = Math.pow(2, 56);
27173
+ var N94 = Math.pow(2, 63);
27174
+ var length4 = function(value) {
27175
+ return value < N14 ? 1 : value < N24 ? 2 : value < N34 ? 3 : value < N44 ? 4 : value < N54 ? 5 : value < N64 ? 6 : value < N74 ? 7 : value < N84 ? 8 : value < N94 ? 9 : 10;
27176
+ };
27177
+ var varint4 = {
27178
+ encode: encode_14,
27179
+ decode: decode24,
27180
+ encodingLength: length4
27181
+ };
27182
+ var _brrp_varint4 = varint4;
27183
+ var varint_default4 = _brrp_varint4;
27184
+ function decode34(data, offset = 0) {
27185
+ const code22 = varint_default4.decode(data, offset);
27186
+ return [code22, varint_default4.decode.bytes];
27187
+ }
27188
+ function encodeTo4(int, target, offset = 0) {
27189
+ varint_default4.encode(int, target, offset);
27190
+ return target;
27191
+ }
27192
+ function encodingLength4(int) {
27193
+ return varint_default4.encodingLength(int);
27194
+ }
27195
+ function create4(code22, digest) {
27196
+ const size = digest.byteLength;
27197
+ const sizeOffset = encodingLength4(code22);
27198
+ const digestOffset = sizeOffset + encodingLength4(size);
27199
+ const bytes = new Uint8Array(digestOffset + size);
27200
+ encodeTo4(code22, bytes, 0);
27201
+ encodeTo4(size, bytes, sizeOffset);
27202
+ bytes.set(digest, digestOffset);
27203
+ return new Digest4(code22, size, digest, bytes);
27204
+ }
27205
+ function decode44(multihash) {
27206
+ const bytes = coerce6(multihash);
27207
+ const [code22, sizeOffset] = decode34(bytes);
27208
+ const [size, digestOffset] = decode34(bytes.subarray(sizeOffset));
27209
+ const digest = bytes.subarray(sizeOffset + digestOffset);
27210
+ if (digest.byteLength !== size) {
27211
+ throw new Error("Incorrect length");
27212
+ }
27213
+ return new Digest4(code22, size, digest, bytes);
27214
+ }
27215
+ function equals24(a, b) {
27216
+ if (a === b) {
27217
+ return true;
27218
+ } else {
27219
+ const data = b;
27220
+ return a.code === data.code && a.size === data.size && data.bytes instanceof Uint8Array && equals6(a.bytes, data.bytes);
27221
+ }
27222
+ }
27223
+ var Digest4 = class {
27224
+ code;
27225
+ size;
27226
+ digest;
27227
+ bytes;
27228
+ /**
27229
+ * Creates a multihash digest.
27230
+ */
27231
+ constructor(code22, size, digest, bytes) {
27232
+ this.code = code22;
27233
+ this.size = size;
27234
+ this.digest = digest;
27235
+ this.bytes = bytes;
27236
+ }
27237
+ };
27238
+ function format4(link4, base23) {
27239
+ const { bytes, version: version2 } = link4;
27240
+ switch (version2) {
27241
+ case 0:
27242
+ return toStringV04(bytes, baseCache4(link4), base23 ?? base58btc4.encoder);
27243
+ default:
27244
+ return toStringV14(bytes, baseCache4(link4), base23 ?? base324.encoder);
27245
+ }
27246
+ }
27247
+ var cache4 = /* @__PURE__ */ new WeakMap();
27248
+ function baseCache4(cid) {
27249
+ const baseCache23 = cache4.get(cid);
27250
+ if (baseCache23 == null) {
27251
+ const baseCache32 = /* @__PURE__ */ new Map();
27252
+ cache4.set(cid, baseCache32);
27253
+ return baseCache32;
27254
+ }
27255
+ return baseCache23;
27256
+ }
27257
+ var CID4 = class _CID4 {
27258
+ code;
27259
+ version;
27260
+ multihash;
27261
+ bytes;
27262
+ "/";
27263
+ /**
27264
+ * @param version - Version of the CID
27265
+ * @param code - Code of the codec content is encoded in, see https://github.com/multiformats/multicodec/blob/master/table.csv
27266
+ * @param multihash - (Multi)hash of the of the content.
27267
+ */
27268
+ constructor(version2, code22, multihash, bytes) {
27269
+ this.code = code22;
27270
+ this.version = version2;
27271
+ this.multihash = multihash;
27272
+ this.bytes = bytes;
27273
+ this["/"] = bytes;
27274
+ }
27275
+ /**
27276
+ * Signalling `cid.asCID === cid` has been replaced with `cid['/'] === cid.bytes`
27277
+ * please either use `CID.asCID(cid)` or switch to new signalling mechanism
27278
+ *
27279
+ * @deprecated
27280
+ */
27281
+ get asCID() {
27282
+ return this;
27283
+ }
27284
+ // ArrayBufferView
27285
+ get byteOffset() {
27286
+ return this.bytes.byteOffset;
27287
+ }
27288
+ // ArrayBufferView
27289
+ get byteLength() {
27290
+ return this.bytes.byteLength;
27291
+ }
27292
+ toV0() {
27293
+ switch (this.version) {
27294
+ case 0: {
27295
+ return this;
27296
+ }
27297
+ case 1: {
27298
+ const { code: code22, multihash } = this;
27299
+ if (code22 !== DAG_PB_CODE4) {
27300
+ throw new Error("Cannot convert a non dag-pb CID to CIDv0");
27301
+ }
27302
+ if (multihash.code !== SHA_256_CODE4) {
27303
+ throw new Error("Cannot convert non sha2-256 multihash CID to CIDv0");
27304
+ }
27305
+ return _CID4.createV0(multihash);
27306
+ }
27307
+ default: {
27308
+ throw Error(`Can not convert CID version ${this.version} to version 0. This is a bug please report`);
27309
+ }
27310
+ }
27311
+ }
27312
+ toV1() {
27313
+ switch (this.version) {
27314
+ case 0: {
27315
+ const { code: code22, digest } = this.multihash;
27316
+ const multihash = create4(code22, digest);
27317
+ return _CID4.createV1(this.code, multihash);
27318
+ }
27319
+ case 1: {
27320
+ return this;
27321
+ }
27322
+ default: {
27323
+ throw Error(`Can not convert CID version ${this.version} to version 1. This is a bug please report`);
27324
+ }
27325
+ }
27326
+ }
27327
+ equals(other) {
27328
+ return _CID4.equals(this, other);
27329
+ }
27330
+ static equals(self, other) {
27331
+ const unknown = other;
27332
+ return unknown != null && self.code === unknown.code && self.version === unknown.version && equals24(self.multihash, unknown.multihash);
27333
+ }
27334
+ toString(base23) {
27335
+ return format4(this, base23);
27336
+ }
27337
+ toJSON() {
27338
+ return { "/": format4(this) };
27339
+ }
27340
+ link() {
27341
+ return this;
27342
+ }
27343
+ [Symbol.toStringTag] = "CID";
27344
+ // Legacy
27345
+ [/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
27346
+ return `CID(${this.toString()})`;
27347
+ }
27348
+ /**
27349
+ * Takes any input `value` and returns a `CID` instance if it was
27350
+ * a `CID` otherwise returns `null`. If `value` is instanceof `CID`
27351
+ * it will return value back. If `value` is not instance of this CID
27352
+ * class, but is compatible CID it will return new instance of this
27353
+ * `CID` class. Otherwise returns null.
27354
+ *
27355
+ * This allows two different incompatible versions of CID library to
27356
+ * co-exist and interop as long as binary interface is compatible.
27357
+ */
27358
+ static asCID(input) {
27359
+ if (input == null) {
27360
+ return null;
27361
+ }
27362
+ const value = input;
27363
+ if (value instanceof _CID4) {
27364
+ return value;
27365
+ } else if (value["/"] != null && value["/"] === value.bytes || value.asCID === value) {
27366
+ const { version: version2, code: code22, multihash, bytes } = value;
27367
+ return new _CID4(version2, code22, multihash, bytes ?? encodeCID4(version2, code22, multihash.bytes));
27368
+ } else if (value[cidSymbol4] === true) {
27369
+ const { version: version2, multihash, code: code22 } = value;
27370
+ const digest = decode44(multihash);
27371
+ return _CID4.create(version2, code22, digest);
27372
+ } else {
27373
+ return null;
27374
+ }
27375
+ }
27376
+ /**
27377
+ * @param version - Version of the CID
27378
+ * @param code - Code of the codec content is encoded in, see https://github.com/multiformats/multicodec/blob/master/table.csv
27379
+ * @param digest - (Multi)hash of the of the content.
27380
+ */
27381
+ static create(version2, code22, digest) {
27382
+ if (typeof code22 !== "number") {
27383
+ throw new Error("String codecs are no longer supported");
27384
+ }
27385
+ if (!(digest.bytes instanceof Uint8Array)) {
27386
+ throw new Error("Invalid digest");
27387
+ }
27388
+ switch (version2) {
27389
+ case 0: {
27390
+ if (code22 !== DAG_PB_CODE4) {
27391
+ throw new Error(`Version 0 CID must use dag-pb (code: ${DAG_PB_CODE4}) block encoding`);
27392
+ } else {
27393
+ return new _CID4(version2, code22, digest, digest.bytes);
27394
+ }
27395
+ }
27396
+ case 1: {
27397
+ const bytes = encodeCID4(version2, code22, digest.bytes);
27398
+ return new _CID4(version2, code22, digest, bytes);
27399
+ }
27400
+ default: {
27401
+ throw new Error("Invalid version");
27402
+ }
27403
+ }
27404
+ }
27405
+ /**
27406
+ * Simplified version of `create` for CIDv0.
27407
+ */
27408
+ static createV0(digest) {
27409
+ return _CID4.create(0, DAG_PB_CODE4, digest);
27410
+ }
27411
+ /**
27412
+ * Simplified version of `create` for CIDv1.
27413
+ *
27414
+ * @param code - Content encoding format code.
27415
+ * @param digest - Multihash of the content.
27416
+ */
27417
+ static createV1(code22, digest) {
27418
+ return _CID4.create(1, code22, digest);
27419
+ }
27420
+ /**
27421
+ * Decoded a CID from its binary representation. The byte array must contain
27422
+ * only the CID with no additional bytes.
27423
+ *
27424
+ * An error will be thrown if the bytes provided do not contain a valid
27425
+ * binary representation of a CID.
27426
+ */
27427
+ static decode(bytes) {
27428
+ const [cid, remainder] = _CID4.decodeFirst(bytes);
27429
+ if (remainder.length !== 0) {
27430
+ throw new Error("Incorrect length");
27431
+ }
27432
+ return cid;
27433
+ }
27434
+ /**
27435
+ * Decoded a CID from its binary representation at the beginning of a byte
27436
+ * array.
27437
+ *
27438
+ * Returns an array with the first element containing the CID and the second
27439
+ * element containing the remainder of the original byte array. The remainder
27440
+ * will be a zero-length byte array if the provided bytes only contained a
27441
+ * binary CID representation.
27442
+ */
27443
+ static decodeFirst(bytes) {
27444
+ const specs = _CID4.inspectBytes(bytes);
27445
+ const prefixSize = specs.size - specs.multihashSize;
27446
+ const multihashBytes = coerce6(bytes.subarray(prefixSize, prefixSize + specs.multihashSize));
27447
+ if (multihashBytes.byteLength !== specs.multihashSize) {
27448
+ throw new Error("Incorrect length");
27449
+ }
27450
+ const digestBytes = multihashBytes.subarray(specs.multihashSize - specs.digestSize);
27451
+ const digest = new Digest4(specs.multihashCode, specs.digestSize, digestBytes, multihashBytes);
27452
+ const cid = specs.version === 0 ? _CID4.createV0(digest) : _CID4.createV1(specs.codec, digest);
27453
+ return [cid, bytes.subarray(specs.size)];
27454
+ }
27455
+ /**
27456
+ * Inspect the initial bytes of a CID to determine its properties.
27457
+ *
27458
+ * Involves decoding up to 4 varints. Typically this will require only 4 to 6
27459
+ * bytes but for larger multicodec code values and larger multihash digest
27460
+ * lengths these varints can be quite large. It is recommended that at least
27461
+ * 10 bytes be made available in the `initialBytes` argument for a complete
27462
+ * inspection.
27463
+ */
27464
+ static inspectBytes(initialBytes) {
27465
+ let offset = 0;
27466
+ const next = () => {
27467
+ const [i, length23] = decode34(initialBytes.subarray(offset));
27468
+ offset += length23;
27469
+ return i;
27470
+ };
27471
+ let version2 = next();
27472
+ let codec = DAG_PB_CODE4;
27473
+ if (version2 === 18) {
27474
+ version2 = 0;
27475
+ offset = 0;
27476
+ } else {
27477
+ codec = next();
27478
+ }
27479
+ if (version2 !== 0 && version2 !== 1) {
27480
+ throw new RangeError(`Invalid CID version ${version2}`);
27481
+ }
27482
+ const prefixSize = offset;
27483
+ const multihashCode = next();
27484
+ const digestSize = next();
27485
+ const size = offset + digestSize;
27486
+ const multihashSize = size - prefixSize;
27487
+ return { version: version2, codec, multihashCode, digestSize, multihashSize, size };
27488
+ }
27489
+ /**
27490
+ * Takes cid in a string representation and creates an instance. If `base`
27491
+ * decoder is not provided will use a default from the configuration. It will
27492
+ * throw an error if encoding of the CID is not compatible with supplied (or
27493
+ * a default decoder).
27494
+ */
27495
+ static parse(source, base23) {
27496
+ const [prefix, bytes] = parseCIDtoBytes4(source, base23);
27497
+ const cid = _CID4.decode(bytes);
27498
+ if (cid.version === 0 && source[0] !== "Q") {
27499
+ throw Error("Version 0 CID string must not include multibase prefix");
27500
+ }
27501
+ baseCache4(cid).set(prefix, source);
27502
+ return cid;
27503
+ }
27504
+ };
27505
+ function parseCIDtoBytes4(source, base23) {
27506
+ switch (source[0]) {
27507
+ // CIDv0 is parsed differently
27508
+ case "Q": {
27509
+ const decoder = base23 ?? base58btc4;
27510
+ return [
27511
+ base58btc4.prefix,
27512
+ decoder.decode(`${base58btc4.prefix}${source}`)
27513
+ ];
27514
+ }
27515
+ case base58btc4.prefix: {
27516
+ const decoder = base23 ?? base58btc4;
27517
+ return [base58btc4.prefix, decoder.decode(source)];
27518
+ }
27519
+ case base324.prefix: {
27520
+ const decoder = base23 ?? base324;
27521
+ return [base324.prefix, decoder.decode(source)];
27522
+ }
27523
+ case base364.prefix: {
27524
+ const decoder = base23 ?? base364;
27525
+ return [base364.prefix, decoder.decode(source)];
27526
+ }
27527
+ default: {
27528
+ if (base23 == null) {
27529
+ throw Error("To parse non base32, base36 or base58btc encoded CID multibase decoder must be provided");
27530
+ }
27531
+ return [source[0], base23.decode(source)];
27532
+ }
27533
+ }
27534
+ }
27535
+ function toStringV04(bytes, cache23, base23) {
27536
+ const { prefix } = base23;
27537
+ if (prefix !== base58btc4.prefix) {
27538
+ throw Error(`Cannot string encode V0 in ${base23.name} encoding`);
27539
+ }
27540
+ const cid = cache23.get(prefix);
27541
+ if (cid == null) {
27542
+ const cid2 = base23.encode(bytes).slice(1);
27543
+ cache23.set(prefix, cid2);
27544
+ return cid2;
27545
+ } else {
27546
+ return cid;
27547
+ }
27548
+ }
27549
+ function toStringV14(bytes, cache23, base23) {
27550
+ const { prefix } = base23;
27551
+ const cid = cache23.get(prefix);
27552
+ if (cid == null) {
27553
+ const cid2 = base23.encode(bytes);
27554
+ cache23.set(prefix, cid2);
27555
+ return cid2;
27556
+ } else {
27557
+ return cid;
27558
+ }
27559
+ }
27560
+ var DAG_PB_CODE4 = 112;
27561
+ var SHA_256_CODE4 = 18;
27562
+ function encodeCID4(version2, code22, multihash) {
27563
+ const codeOffset = encodingLength4(version2);
27564
+ const hashOffset = codeOffset + encodingLength4(code22);
27565
+ const bytes = new Uint8Array(hashOffset + multihash.byteLength);
27566
+ encodeTo4(version2, bytes, 0);
27567
+ encodeTo4(code22, bytes, codeOffset);
27568
+ bytes.set(multihash, hashOffset);
27569
+ return bytes;
27570
+ }
27571
+ var cidSymbol4 = /* @__PURE__ */ Symbol.for("@ipld/js-cid/CID");
27572
+ var code4 = 85;
27573
+ var SHA256_CODE4 = 18;
27574
+ async function computeCid3(bytes) {
27575
+ const digest = create4(SHA256_CODE4, sha256(new Uint8Array(bytes)));
27576
+ return CID4.create(1, code4, digest).toString();
27577
+ }
27578
+ function isCanonicalRawCid4(cidString) {
27579
+ let cid;
27580
+ try {
27581
+ cid = CID4.parse(cidString);
27582
+ } catch {
27583
+ return false;
27584
+ }
27585
+ return cid.version === 1 && cid.code === code4 && cid.multihash.code === SHA256_CODE4 && cid.toString() === cidString;
27586
+ }
27587
+ function isPlainRecord4(value) {
27588
+ const proto = Object.getPrototypeOf(value);
27589
+ return proto === Object.prototype || proto === null;
27590
+ }
27591
+ function assertNoLoneSurrogates4(text) {
27592
+ for (let i = 0; i < text.length; i++) {
27593
+ const unit = text.charCodeAt(i);
27594
+ if (unit >= 56320 && unit <= 57343) {
27595
+ throw new TypeError(
27596
+ `cannot canonicalize string with unpaired low surrogate at index ${i}`
27597
+ );
27598
+ }
27599
+ if (unit >= 55296 && unit <= 56319) {
27600
+ const next = text.charCodeAt(i + 1);
27601
+ if (!(next >= 56320 && next <= 57343)) {
27602
+ throw new TypeError(
27603
+ `cannot canonicalize string with unpaired high surrogate at index ${i}`
27604
+ );
27605
+ }
27606
+ i++;
27607
+ }
27608
+ }
27609
+ }
27610
+ function serializeString4(text) {
27611
+ assertNoLoneSurrogates4(text);
27612
+ return JSON.stringify(text);
27613
+ }
27614
+ function serialize4(value) {
27615
+ if (value === null) return "null";
27616
+ switch (typeof value) {
27617
+ case "boolean":
27618
+ return JSON.stringify(value);
27619
+ case "string":
27620
+ return serializeString4(value);
27621
+ case "number":
27622
+ if (!Number.isFinite(value)) {
27623
+ throw new TypeError(`cannot canonicalize non-finite number: ${value}`);
27624
+ }
27625
+ return JSON.stringify(value);
27626
+ case "object":
27627
+ break;
27628
+ default:
27629
+ throw new TypeError(`cannot canonicalize value of type ${typeof value}`);
27630
+ }
27631
+ if (Array.isArray(value)) {
27632
+ return `[${value.map((item) => serialize4(item)).join(",")}]`;
27633
+ }
27634
+ if (!isPlainRecord4(value)) {
27635
+ throw new TypeError("cannot canonicalize non-plain object");
27636
+ }
27637
+ const keys = Object.keys(value).sort();
27638
+ const members = [];
27639
+ for (const key of keys) {
27640
+ const member = value[key];
27641
+ if (member === void 0) continue;
27642
+ members.push(`${serializeString4(key)}:${serialize4(member)}`);
27643
+ }
27644
+ return `{${members.join(",")}}`;
27645
+ }
27646
+ function canonicalize4(value) {
27647
+ return serialize4(value);
27648
+ }
27649
+ function decodeBase64UrlOrNull4(value) {
27650
+ try {
27651
+ return fromBase64Url4(value);
27652
+ } catch {
27653
+ return null;
27654
+ }
27655
+ }
27656
+ var base64UrlString4 = () => external_exports3.string().refine((value) => decodeBase64UrlOrNull4(value) !== null, {
27657
+ message: "expected strictly-decodable unpadded base64url"
27658
+ });
27659
+ function isCanonicalHttpsOrigin4(value) {
27660
+ let url;
27661
+ try {
27662
+ url = new URL(value);
27663
+ } catch {
27664
+ return false;
27665
+ }
27666
+ return url.protocol === "https:" && url.origin === value;
27667
+ }
27668
+ var sessionJwkCommonFields4 = {
27669
+ alg: external_exports3.string().min(1).optional(),
27670
+ use: external_exports3.string().min(1).optional(),
27671
+ key_ops: external_exports3.array(external_exports3.string().min(1)).optional(),
27672
+ kid: external_exports3.string().min(1).optional(),
27673
+ ext: external_exports3.boolean().optional()
27674
+ };
27675
+ var okpPrivateJwkSchema4 = external_exports3.object({
27676
+ kty: external_exports3.literal("OKP"),
27677
+ crv: external_exports3.string().min(1),
27678
+ x: base64UrlString4(),
27679
+ d: base64UrlString4(),
27680
+ ...sessionJwkCommonFields4
27681
+ }).strict();
27682
+ var ecPrivateJwkSchema4 = external_exports3.object({
27683
+ kty: external_exports3.literal("EC"),
27684
+ crv: external_exports3.string().min(1),
27685
+ x: base64UrlString4(),
27686
+ y: base64UrlString4(),
27687
+ d: base64UrlString4(),
27688
+ ...sessionJwkCommonFields4
27689
+ }).strict();
27690
+ var sessionJwkSchema4 = external_exports3.discriminatedUnion("kty", [
27691
+ okpPrivateJwkSchema4,
27692
+ ecPrivateJwkSchema4
27693
+ ]);
27694
+ var policyTargetSchema4 = external_exports3.object({
27695
+ kind: external_exports3.literal("policy"),
27696
+ policyCid: external_exports3.string().min(1),
27697
+ /** Canonical policy bytes, base64url-encoded (bytes are not JSON). */
27698
+ policyBytes: base64UrlString4()
27699
+ }).strict();
27700
+ var bearerKeyTargetSchema4 = external_exports3.object({
27701
+ kind: external_exports3.literal("bearerKey"),
27702
+ sessionJwk: sessionJwkSchema4
27703
+ }).strict();
27704
+ var recipientDidTargetSchema4 = external_exports3.object({
27705
+ kind: external_exports3.literal("recipientDid"),
27706
+ did: external_exports3.string().regex(/^did:[a-z0-9]+:.+$/, "expected a DID")
27707
+ }).strict();
27708
+ var authorizationTargetSchema4 = external_exports3.discriminatedUnion("kind", [
27709
+ policyTargetSchema4,
27710
+ bearerKeyTargetSchema4,
27711
+ recipientDidTargetSchema4
27712
+ ]);
27713
+ function isCanonicalResourcePath4(value) {
27714
+ if (value.length === 0) return false;
27715
+ if (/[\u0000-\u001f\u007f\\]/.test(value)) return false;
27716
+ if (/%2f|%5c|%2e/i.test(value)) return false;
27717
+ return value.split("/").every((segment) => segment.length > 0 && segment !== "." && segment !== "..");
27718
+ }
27719
+ function isCanonicalPathSegment4(value) {
27720
+ return isCanonicalResourcePath4(value) && !value.includes("/");
27721
+ }
27722
+ var resourceSelectorSchema4 = external_exports3.object({
27723
+ kind: external_exports3.union([external_exports3.literal("exact"), external_exports3.literal("prefix")]),
27724
+ path: external_exports3.string().min(1)
27725
+ }).strict().superRefine((selector, ctx) => {
27726
+ const body = selector.kind === "prefix" && selector.path.endsWith("/") ? selector.path.slice(0, -1) : selector.path;
27727
+ if (!isCanonicalResourcePath4(body)) {
27728
+ ctx.addIssue({
27729
+ code: external_exports3.ZodIssueCode.custom,
27730
+ path: ["path"],
27731
+ message: "expected a canonical resource path (non-empty segments, no . or .. segments, no //, no backslash, no %2f/%5c/%2e, no control chars)"
27732
+ });
27733
+ }
27734
+ });
27735
+ var targetSchema4 = external_exports3.object({
27736
+ origin: external_exports3.string().refine(isCanonicalHttpsOrigin4, {
27737
+ message: "expected a canonical https origin (https://host[:port], nothing else)"
27738
+ }),
27739
+ nodeAudience: external_exports3.string().min(1),
27740
+ spaceId: external_exports3.string().refine(isCanonicalPathSegment4, {
27741
+ message: "expected a single canonical path segment (spaceId joins the resource URI; separators/traversal would alias grants)"
27742
+ }),
27743
+ resource: resourceSelectorSchema4
27744
+ }).strict();
27745
+ var displaySchema4 = external_exports3.object({
27746
+ senderName: external_exports3.string().optional(),
27747
+ filename: external_exports3.string().optional(),
27748
+ recipientHint: external_exports3.string().optional(),
27749
+ /**
27750
+ * Presentation preference only (viewer spec §1): may narrow, never widen;
27751
+ * capabilities always win.
27752
+ */
27753
+ mode: external_exports3.union([external_exports3.literal("document"), external_exports3.literal("source"), external_exports3.literal("folder")]).optional()
27754
+ }).strict();
27755
+ var contentPointerSchema4 = external_exports3.object({
27756
+ cid: external_exports3.string().refine(isCanonicalRawCid4, {
27757
+ message: "expected a canonical CIDv1 raw sha2-256 base32 CID"
27758
+ }),
27759
+ key: external_exports3.string().refine((value) => decodeBase64UrlOrNull4(value)?.length === 32, {
27760
+ message: "expected base64url decoding to exactly 32 bytes"
27761
+ })
27762
+ }).strict();
27763
+ var signatureSchema4 = external_exports3.object({
27764
+ /** did:key of the sender's ed25519 signing key. */
27765
+ signerDid: external_exports3.string().regex(/^did:key:z[1-9A-HJ-NP-Za-km-z]+$/, "expected a did:key"),
27766
+ algorithm: external_exports3.literal("Ed25519"),
27767
+ /** base64url-encoded ed25519 signature over the JCS bytes of all other fields. */
27768
+ value: external_exports3.string().refine((value) => decodeBase64UrlOrNull4(value)?.length === 64, {
27769
+ message: "expected base64url decoding to exactly 64 bytes"
27770
+ })
27771
+ }).strict();
27772
+ var unsignedShareEnvelopeSchema4 = external_exports3.object({
27773
+ version: external_exports3.literal(1),
27774
+ shareId: external_exports3.string().min(1),
27775
+ /** Full signed delegation chain, opaque serialized form. */
27776
+ delegation: external_exports3.string().min(1),
27777
+ authorizationTarget: authorizationTargetSchema4,
27778
+ target: targetSchema4,
27779
+ display: displaySchema4,
27780
+ /** ISO 8601 UTC datetime. Advisory here; enforcement is the delegation's. */
27781
+ expiry: external_exports3.string().datetime(),
27782
+ /** Bearer-slice sealed-content pointer (see contentPointerSchema). */
27783
+ content: contentPointerSchema4.optional()
27784
+ }).strict();
27785
+ var shareEnvelopeSchema4 = unsignedShareEnvelopeSchema4.extend({ signature: signatureSchema4 }).strict();
27786
+ var recipientMatcherSchema4 = external_exports3.discriminatedUnion("kind", [
27787
+ external_exports3.object({ kind: external_exports3.literal("exactEmail"), value: external_exports3.string().min(3).regex(/^[^@\s]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/) }).strict(),
27788
+ external_exports3.object({ kind: external_exports3.literal("emailDomain"), value: external_exports3.string().regex(/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/) }).strict(),
27789
+ external_exports3.object({ kind: external_exports3.literal("recipientDid"), value: external_exports3.string().regex(/^did:[a-z0-9]+:.+$/) }).strict(),
27790
+ external_exports3.object({ kind: external_exports3.literal("policyDigest"), value: external_exports3.string().regex(/^[A-Za-z0-9_-]{43}$/) }).strict(),
27791
+ external_exports3.object({ kind: external_exports3.literal("bearer") }).strict()
27792
+ ]);
27793
+ var shareActionSchema4 = external_exports3.union([external_exports3.literal("read"), external_exports3.literal("list"), external_exports3.literal("edit")]);
27794
+ var kvContentSourceSchema4 = external_exports3.object({
27795
+ kind: external_exports3.literal("kv"),
27796
+ space: external_exports3.string().min(1),
27797
+ path: external_exports3.string().min(1),
27798
+ action: external_exports3.literal("tinycloud.kv/get")
27799
+ }).strict();
27800
+ var sqlContentSourceSchema4 = external_exports3.object({
27801
+ kind: external_exports3.literal("sql"),
27802
+ space: external_exports3.string().min(1),
27803
+ database: external_exports3.string().min(1),
27804
+ path: external_exports3.string().min(1),
27805
+ statement: external_exports3.string().min(1),
27806
+ arguments: external_exports3.record(external_exports3.string(), external_exports3.number().int()),
27807
+ argumentsDigest: external_exports3.string().regex(/^[A-Za-z0-9_-]{43}$/),
27808
+ action: external_exports3.literal("tinycloud.sql/read")
27809
+ }).strict();
27810
+ var contentSourceSchema4 = external_exports3.discriminatedUnion("kind", [kvContentSourceSchema4, sqlContentSourceSchema4]);
27811
+ var v2TargetSchema4 = external_exports3.object({
27812
+ origin: external_exports3.string().refine(isCanonicalHttpsOrigin4, { message: "expected a canonical https origin" }),
27813
+ nodeAudience: external_exports3.string().min(1),
27814
+ spaceId: external_exports3.string().refine(isCanonicalPathSegment4, { message: "expected a canonical space id" })
27815
+ }).strict();
27816
+ var shareDecryptionSchema4 = external_exports3.object({
27817
+ networkId: external_exports3.string().min(1),
27818
+ action: external_exports3.literal("tinycloud.encryption/decrypt")
27819
+ }).strict();
27820
+ var ownerAuthoritySchema4 = external_exports3.object({
27821
+ registrationCid: external_exports3.string().min(1),
27822
+ shareCid: external_exports3.string().min(1),
27823
+ envelopeCid: external_exports3.string().min(1),
27824
+ enforcementDelegation: external_exports3.record(external_exports3.string(), external_exports3.unknown()),
27825
+ outerEnvelope: external_exports3.record(external_exports3.string(), external_exports3.unknown()),
27826
+ /** Node-signed registration evidence; required by trusted policy adapters. */
27827
+ registrationReceipt: external_exports3.object({
27828
+ registration: external_exports3.record(external_exports3.string(), external_exports3.unknown()),
27829
+ proof: external_exports3.record(external_exports3.string(), external_exports3.unknown())
27830
+ }).strict().optional()
27831
+ }).strict();
27832
+ var contentMetadataSchema4 = external_exports3.object({
27833
+ mediaType: external_exports3.string().min(1).max(128).optional(),
27834
+ byteLength: external_exports3.number().int().nonnegative().max(100 * 1024 * 1024).optional(),
27835
+ filename: external_exports3.string().min(1).max(255).optional(),
27836
+ encoding: external_exports3.literal("utf-8").optional(),
27837
+ /** Encrypted presentation discriminator. The fixed entry point is index.html. */
27838
+ artifact: external_exports3.literal("html").optional()
27839
+ }).strict();
27840
+ var deliveryEmailSchema4 = external_exports3.string().email();
27841
+ var unsignedShareEnvelopeV2BaseSchema4 = external_exports3.object({
27842
+ version: external_exports3.literal(2),
27843
+ shareId: external_exports3.string().min(1),
27844
+ recipientMatcher: recipientMatcherSchema4,
27845
+ deliveryEmail: deliveryEmailSchema4.optional(),
27846
+ actions: external_exports3.array(shareActionSchema4).min(1).max(3),
27847
+ resource: resourceSelectorSchema4,
27848
+ target: v2TargetSchema4,
27849
+ delegationCid: external_exports3.string().min(1),
27850
+ authorityMaterialHandle: external_exports3.string().min(1),
27851
+ authorityMaterialDigest: external_exports3.string().regex(/^[A-Za-z0-9_-]{43}$/),
27852
+ decryption: shareDecryptionSchema4.optional(),
27853
+ contentSource: contentSourceSchema4,
27854
+ contentSourceDigest: external_exports3.string().regex(/^[A-Za-z0-9_-]{43}$/),
27855
+ authorizationTarget: authorizationTargetSchema4,
27856
+ display: displaySchema4,
27857
+ expiry: external_exports3.string().datetime(),
27858
+ encrypted: external_exports3.boolean(),
27859
+ content: contentPointerSchema4.optional(),
27860
+ metadata: contentMetadataSchema4,
27861
+ ownerAuthority: ownerAuthoritySchema4.optional()
27862
+ }).strict();
27863
+ function validateV2Invariants4(value, ctx) {
27864
+ const actions = [...value.actions];
27865
+ if (new Set(actions).size !== actions.length) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["actions"], message: "actions must be unique" });
27866
+ if (actions.some((action, index) => action !== ["read", "list", "edit"].filter((candidate) => actions.includes(candidate))[index])) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["actions"], message: "actions must be canonically ordered" });
27867
+ if (!value.encrypted && value.recipientMatcher.kind !== "policyDigest") ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["recipientMatcher"], message: "safe plaintext must carry only a matcher digest" });
27868
+ if (!value.encrypted && value.authorizationTarget.kind !== "policy") ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["encrypted"], message: "unencrypted content requires a policy target" });
27869
+ if (!value.encrypted && value.content !== void 0) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["content"], message: "policy-only plaintext cannot carry content" });
27870
+ if (value.encrypted && (value.metadata.mediaType === void 0 || value.metadata.filename === void 0 || value.metadata.byteLength === void 0)) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["metadata"], message: "encrypted shares must describe their content" });
27871
+ if (!value.encrypted && Object.keys(value.metadata).length !== 0) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["metadata"], message: "policy-only plaintext cannot describe content" });
27872
+ if (!value.encrypted && value.metadata.encoding !== void 0) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["metadata", "encoding"], message: "policy-only plaintext cannot carry content encoding" });
27873
+ if (value.metadata.artifact === "html" && (!value.encrypted || value.resource.kind !== "prefix" || !value.actions.includes("read") || !value.actions.includes("list"))) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["metadata", "artifact"], message: "html artifacts require an encrypted readable prefix" });
27874
+ if (!value.encrypted && (value.display.senderName !== void 0 || value.display.filename !== void 0 || value.display.recipientHint !== void 0)) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["display"], message: "policy-only plaintext cannot carry display metadata" });
27875
+ if (!value.encrypted && value.deliveryEmail !== void 0) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["deliveryEmail"], message: "policy-only plaintext cannot carry delivery metadata" });
27876
+ if (value.recipientMatcher.kind === "exactEmail" && value.deliveryEmail !== void 0 && value.deliveryEmail !== value.recipientMatcher.value) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["deliveryEmail"], message: "delivery email must match the exact matcher" });
27877
+ if (value.recipientMatcher.kind === "emailDomain" && value.deliveryEmail !== void 0 && value.deliveryEmail.toLowerCase().endsWith(`@${value.recipientMatcher.value}`) === false) ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["deliveryEmail"], message: "delivery email must belong to the matcher domain" });
27878
+ if (value.contentSource.kind === "kv" && value.contentSource.action !== "tinycloud.kv/get") ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["contentSource"], message: "source action mismatch" });
27879
+ if (value.contentSource.kind === "sql" && value.contentSource.action !== "tinycloud.sql/read") ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["contentSource"], message: "source action mismatch" });
27880
+ }
27881
+ var unsignedShareEnvelopeV2Schema4 = unsignedShareEnvelopeV2BaseSchema4.superRefine(validateV2Invariants4);
27882
+ var shareEnvelopeV2Schema4 = unsignedShareEnvelopeV2BaseSchema4.extend({ signature: signatureSchema4 }).strict().superRefine(validateV2Invariants4);
27883
+ var unifiedResourceSchema4 = external_exports3.string().refine((value) => {
27884
+ const marker = value.indexOf("/kv/");
27885
+ if (marker < 1) return false;
27886
+ const space = value.slice(0, marker);
27887
+ const legacy = space.startsWith("tinycloud://");
27888
+ if (legacy ? /[:/?#%]/.test(space.slice("tinycloud://".length)) : !space.startsWith("tinycloud:") || /[/?#%]/.test(space)) return false;
27889
+ const path = value.slice(marker + 4);
27890
+ return !path.startsWith("/") && !path.endsWith("/") && !path.includes("//") && path.split("/").every((segment) => segment.length > 0 && segment !== "." && segment !== "..");
27891
+ }, { message: "expected canonical TinyCloud KV resource" });
27892
+ var unifiedEncryptionNetworkSchema4 = external_exports3.string().refine((value) => {
27893
+ if (!value.startsWith("urn:tinycloud:encryption:")) return false;
27894
+ const rest = value.slice("urn:tinycloud:encryption:".length);
27895
+ const separator = rest.lastIndexOf(":");
27896
+ const owner = separator < 0 ? "" : rest.slice(0, separator);
27897
+ const network = separator < 0 ? "" : rest.slice(separator + 1);
27898
+ return owner.startsWith("did:") && owner.length > 4 && network.length > 0 && !/[:/%?#\s]/.test(network);
27899
+ }, { message: "expected canonical TinyCloud encryption network" });
27900
+ var unifiedKvCapabilitySchema4 = external_exports3.object({
27901
+ kind: external_exports3.literal("kv"),
27902
+ resource: unifiedResourceSchema4,
27903
+ selector: external_exports3.union([external_exports3.literal("exact"), external_exports3.literal("prefix")]),
27904
+ actions: external_exports3.array(external_exports3.union([
27905
+ external_exports3.literal("tinycloud.kv/get"),
27906
+ external_exports3.literal("tinycloud.kv/list"),
27907
+ external_exports3.literal("tinycloud.kv/metadata"),
27908
+ external_exports3.literal("tinycloud.kv/put")
27909
+ ])).min(1)
27910
+ }).strict();
27911
+ var unifiedEncryptionCapabilitySchema4 = external_exports3.object({
27912
+ kind: external_exports3.literal("encryption"),
27913
+ resource: unifiedEncryptionNetworkSchema4,
27914
+ action: external_exports3.literal("tinycloud.encryption/decrypt")
27915
+ }).strict();
27916
+ var unifiedCapabilitySchema4 = external_exports3.union([unifiedKvCapabilitySchema4, unifiedEncryptionCapabilitySchema4]);
27917
+ var unifiedContentSourceSchema4 = external_exports3.object({
27918
+ shareId: external_exports3.string().min(1),
27919
+ kvResource: unifiedResourceSchema4,
27920
+ selector: external_exports3.union([external_exports3.literal("exact"), external_exports3.literal("prefix")]),
27921
+ encryptionNetwork: unifiedEncryptionNetworkSchema4,
27922
+ encryptedSymmetricKeyDigestHex: external_exports3.string().regex(/^[0-9a-f]{64}$/),
27923
+ keyVersion: external_exports3.number().int().positive(),
27924
+ mode: external_exports3.union([external_exports3.literal("mutable"), external_exports3.literal("immutable")]),
27925
+ initialCiphertextDigestHex: external_exports3.string().regex(/^[0-9a-f]{64}$/).optional()
27926
+ }).strict();
27927
+ var unifiedPolicyV1Schema4 = external_exports3.object({
27928
+ schema: external_exports3.literal("xyz.tinycloud.policy/policy/v1"),
27929
+ policyId: external_exports3.string().regex(/^pol_[a-z2-7]+$/),
27930
+ ownerDid: external_exports3.string().min(1),
27931
+ createdAt: external_exports3.string().datetime({ offset: true }),
27932
+ expiresAt: external_exports3.string().datetime({ offset: true }).optional(),
27933
+ contentSource: unifiedContentSourceSchema4,
27934
+ capabilityCeiling: external_exports3.array(unifiedCapabilitySchema4).min(2),
27935
+ signature: external_exports3.object({ suite: external_exports3.string().min(1), signerDid: external_exports3.string().min(1), value: external_exports3.string().min(1) }).strict()
27936
+ }).strict();
27937
+ var policyCredentialRequirementV1Schema4 = external_exports3.object({
27938
+ type: external_exports3.literal("TinyCloudPolicyCredentialRequirement"),
27939
+ version: external_exports3.literal(1),
27940
+ requirementDigest: external_exports3.string().regex(/^[A-Za-z0-9_-]{43}$/),
27941
+ descriptorDigest: external_exports3.string().regex(/^[A-Za-z0-9_-]{43}$/),
27942
+ issuerDid: external_exports3.string().min(1),
27943
+ issuerKid: external_exports3.string().min(1),
27944
+ profile: external_exports3.object({ id: external_exports3.string().min(1), version: external_exports3.literal(1) }).strict(),
27945
+ credentialType: external_exports3.object({ id: external_exports3.string().min(1), version: external_exports3.literal(1) }).strict()
27946
+ }).strict();
27947
+ var unifiedPolicyV2Schema4 = external_exports3.object({
27948
+ schema: external_exports3.literal("xyz.tinycloud.policy/policy/v2"),
27949
+ policyId: external_exports3.string().regex(/^pol_[a-z2-7]+$/),
27950
+ ownerDid: external_exports3.string().min(1),
27951
+ createdAt: external_exports3.string().datetime({ offset: true }),
27952
+ expiresAt: external_exports3.string().datetime({ offset: true }).optional(),
27953
+ contentSource: unifiedContentSourceSchema4,
27954
+ capabilityCeiling: external_exports3.array(unifiedCapabilitySchema4).min(2),
27955
+ credentialRequirement: policyCredentialRequirementV1Schema4,
27956
+ signature: external_exports3.object({ suite: external_exports3.literal("Ed25519"), signerDid: external_exports3.string().min(1), value: external_exports3.string().min(1) }).strict()
27957
+ }).strict();
27958
+ var unifiedPolicySchema4 = external_exports3.discriminatedUnion("schema", [
27959
+ unifiedPolicyV1Schema4,
27960
+ unifiedPolicyV2Schema4
27961
+ ]);
27962
+ var unifiedRootSchema4 = external_exports3.object({
27963
+ cid: external_exports3.string().min(1),
27964
+ authorization: external_exports3.string().regex(/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/),
27965
+ role: external_exports3.union([external_exports3.literal("policy-authority"), external_exports3.literal("policy-enforcement")])
27966
+ }).strict();
27967
+ var attestedEnforcerBindingV2Schema4 = external_exports3.object({
27968
+ schema: external_exports3.literal("xyz.tinycloud.policy/attested-enforcer/v2"),
27969
+ enforcerDid: external_exports3.string().regex(/^did:key:z[1-9A-HJ-NP-Za-km-z]+$/),
27970
+ nodeAudience: external_exports3.string().min(1),
27971
+ attestationBindingDigestHex: external_exports3.string().regex(/^[0-9a-f]{64}$/),
27972
+ issuedAt: external_exports3.string().datetime({ offset: true }),
27973
+ expiresAt: external_exports3.string().datetime({ offset: true }),
27974
+ signature: external_exports3.object({ suite: external_exports3.literal("Ed25519"), signerDid: external_exports3.string().min(1), value: base64UrlString4() }).strict()
27975
+ }).strict();
27976
+ var v3TargetSchema4 = external_exports3.object({
27977
+ origin: external_exports3.string().refine(isCanonicalHttpsOrigin4, { message: "expected a canonical https origin" }),
27978
+ nodeAudience: external_exports3.string().min(1),
27979
+ spaceId: external_exports3.string().refine(isCanonicalPathSegment4, { message: "expected a canonical space id" })
27980
+ }).strict();
27981
+ var ARTIFACT_ID_PATTERN4 = /^[a-z0-9][a-z0-9_-]{2,62}$/;
27982
+ var artifactPinSchema4 = external_exports3.object({
27983
+ v: external_exports3.literal(1),
27984
+ artifactId: external_exports3.string().regex(ARTIFACT_ID_PATTERN4),
27985
+ version: external_exports3.number().int().min(1).max(Number.MAX_SAFE_INTEGER),
27986
+ /** SHA-256 (lowercase hex) of the exact `manifest.json` bytes. The manifest itself stays an owner-side record. */
27987
+ manifestSha256: external_exports3.string().regex(/^[0-9a-f]{64}$/),
27988
+ /** An addressed share reads one exact file, so exactly one entry: the stored bytes (ciphertext) it will fetch. */
27989
+ files: external_exports3.array(external_exports3.object({
27990
+ path: external_exports3.string().min(1).max(255),
27991
+ sha256: external_exports3.string().regex(/^[0-9a-f]{64}$/),
27992
+ bytes: external_exports3.number().int().nonnegative()
27993
+ }).strict()).length(1)
27994
+ }).strict();
27995
+ var unsignedShareEnvelopeV3BaseSchema4 = external_exports3.object({
27996
+ version: external_exports3.literal(3),
27997
+ shareId: external_exports3.string().min(1),
27998
+ recipientMatcher: recipientMatcherSchema4,
27999
+ deliveryEmail: deliveryEmailSchema4.optional(),
28000
+ actions: external_exports3.array(shareActionSchema4).min(1).max(3),
28001
+ resource: resourceSelectorSchema4,
28002
+ target: v3TargetSchema4,
28003
+ policy: unifiedPolicySchema4,
28004
+ policyCid: external_exports3.string().min(1),
28005
+ policyRoot: unifiedRootSchema4,
28006
+ enforcementRoot: unifiedRootSchema4,
28007
+ attestedEnforcerBinding: attestedEnforcerBindingV2Schema4,
28008
+ contentSource: unifiedContentSourceSchema4,
28009
+ contentSourceDigestHex: external_exports3.string().regex(/^[0-9a-f]{64}$/),
28010
+ encryptionNetwork: unifiedEncryptionNetworkSchema4,
28011
+ expiry: external_exports3.string().datetime({ offset: true }),
28012
+ display: displaySchema4,
28013
+ encrypted: external_exports3.literal(true),
28014
+ metadata: contentMetadataSchema4,
28015
+ /**
28016
+ * TC-1428: an owner-signed statement that this share reads one write-once artifact version. Additive: absent on
28017
+ * every other share, and covered by the envelope signature because the signature spans the whole unsigned object.
28018
+ * The shape is checked here; its binding to the content source is `verifyArtifactShare` in share-sdk.
28019
+ */
28020
+ artifactPin: artifactPinSchema4.optional()
28021
+ }).strict();
28022
+ function validateV3Invariants4(value, ctx) {
28023
+ const actions = [...value.actions];
28024
+ if (new Set(actions).size !== actions.length || actions.some((action, index) => action !== ["read", "list", "edit"].filter((candidate) => actions.includes(candidate))[index])) {
28025
+ ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["actions"], message: "actions must be unique and canonically ordered" });
28026
+ }
28027
+ if (value.policyRoot.role !== "policy-authority" || value.enforcementRoot.role !== "policy-enforcement") {
28028
+ ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["policyRoot", "role"], message: "root roles are fixed" });
28029
+ }
28030
+ if (value.policyCid.length === 0 || value.policyCid === value.policyRoot.cid || value.policyCid === value.enforcementRoot.cid) {
28031
+ ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["policyCid"], message: "policy CID must be distinct from both roots" });
28032
+ }
28033
+ if (value.contentSource.encryptionNetwork !== value.encryptionNetwork) {
28034
+ ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["encryptionNetwork"], message: "encryption network is not bound to the source" });
28035
+ }
28036
+ if (value.attestedEnforcerBinding.nodeAudience !== value.target.nodeAudience || value.attestedEnforcerBinding.signature.signerDid !== value.attestedEnforcerBinding.nodeAudience || Date.parse(value.attestedEnforcerBinding.expiresAt) < Date.parse(value.expiry)) {
28037
+ ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["attestedEnforcerBinding"], message: "enforcer binding does not cover the target and share lifetime" });
28038
+ }
28039
+ 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) {
28040
+ ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["contentSource"], message: "content source is not bound to policy" });
28041
+ }
28042
+ if (value.policy.signature.suite !== "Ed25519" || value.policy.signature.signerDid !== value.policy.ownerDid) {
28043
+ ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["policy", "signature"], message: "policy must be signed by its owner" });
28044
+ }
28045
+ const kvCapabilities = value.policy.capabilityCeiling.filter((capability) => capability.kind === "kv");
28046
+ const decryptCapabilities = value.policy.capabilityCeiling.filter((capability) => capability.kind === "encryption" && capability.resource === value.encryptionNetwork && capability.action === "tinycloud.encryption/decrypt");
28047
+ if (value.policy.capabilityCeiling.length !== 2 || kvCapabilities.length !== 1 || decryptCapabilities.length !== 1 || kvCapabilities[0]?.resource !== value.contentSource.kvResource || kvCapabilities[0]?.selector !== value.contentSource.selector) {
28048
+ ctx.addIssue({ code: external_exports3.ZodIssueCode.custom, path: ["policy", "capabilityCeiling"], message: "policy ceiling must contain exact decrypt network" });
28049
+ }
28050
+ }
28051
+ var unsignedShareEnvelopeV3Schema4 = unsignedShareEnvelopeV3BaseSchema4.superRefine(validateV3Invariants4);
28052
+ var shareEnvelopeV3Schema4 = unsignedShareEnvelopeV3BaseSchema4.extend({ signature: signatureSchema4 }).strict().superRefine(validateV3Invariants4);
28053
+ var KEY_LENGTH3 = 32;
28054
+ var MAX_INLINE_BYTES4 = 256 * 1024;
28055
+ function assertCanonicalCid3(cidString) {
28056
+ const cid = CID4.parse(cidString);
28057
+ if (cid.version !== 1 || cid.code !== code4 || cid.multihash.code !== 18 || // sha2-256 (0x12) only, at the link layer too
28058
+ cid.toString() !== cidString) {
28059
+ throw new TypeError(`not a canonical CIDv1 raw sha2-256 base32 CID: ${cidString}`);
28060
+ }
28061
+ }
28062
+ async function parseSealedInlineShareUrl3(url, options = {}) {
28063
+ const parsed = new URL(url);
28064
+ if (parsed.protocol !== "https:" || parsed.username !== "" || parsed.password !== "") throw new TypeError("sealed inline share URL must be canonical HTTPS without userinfo");
28065
+ if (!isCanonicalHttpsOrigin4(parsed.origin) || options.expectedOrigin !== void 0 && parsed.origin !== options.expectedOrigin) throw new TypeError("sealed inline share URL origin is not trusted");
28066
+ if (parsed.pathname !== "/s/inline" || parsed.search !== "") throw new TypeError("not a Node sealed-inline share URL");
28067
+ if (url !== `${parsed.origin}/s/inline${parsed.hash}`) throw new TypeError("sealed inline share URL is not lexically canonical");
28068
+ const prefix = "#v=2&p=";
28069
+ if (!parsed.hash.startsWith(prefix)) throw new TypeError("sealed inline URL is missing its canonical fragment");
28070
+ const encoded = parsed.hash.slice(prefix.length);
28071
+ if (encoded.length === 0 || parsed.hash !== `${prefix}${encoded}`) throw new TypeError("sealed inline URL fragment is not canonical");
28072
+ let payloadBytes;
28073
+ try {
28074
+ payloadBytes = fromBase64Url4(encoded);
28075
+ } catch {
28076
+ throw new TypeError("sealed inline payload is not canonical base64url");
28077
+ }
28078
+ if (payloadBytes.byteLength === 0 || payloadBytes.byteLength > MAX_INLINE_BYTES4 * 2) throw new TypeError("sealed inline payload is too large");
28079
+ const payloadText = new TextDecoder("utf-8", { fatal: true }).decode(payloadBytes);
28080
+ let value;
28081
+ try {
28082
+ value = JSON.parse(payloadText);
28083
+ } catch {
28084
+ throw new TypeError("sealed inline payload is not valid JSON");
28085
+ }
28086
+ if (typeof value !== "object" || value === null || Array.isArray(value) || canonicalize4(value) !== payloadText) throw new TypeError("sealed inline payload is not canonical JSON");
28087
+ const record2 = value;
28088
+ if (Object.keys(record2).length !== 4 || record2.v !== 2 || typeof record2.c !== "string" || typeof record2.cid !== "string" || typeof record2.k !== "string") throw new TypeError("sealed inline payload has invalid fields");
28089
+ let ciphertext;
28090
+ let key32;
28091
+ try {
28092
+ ciphertext = fromBase64Url4(record2.c);
28093
+ key32 = fromBase64Url4(record2.k);
28094
+ } catch {
28095
+ throw new TypeError("sealed inline payload has invalid base64url material");
28096
+ }
28097
+ if (ciphertext.byteLength === 0 || ciphertext.byteLength > MAX_INLINE_BYTES4) throw new TypeError("sealed inline ciphertext is outside the allowed size");
28098
+ if (key32.byteLength !== KEY_LENGTH3) throw new TypeError("sealed inline key must be 32 bytes");
28099
+ assertCanonicalCid3(record2.cid);
28100
+ if (await computeCid3(ciphertext) !== record2.cid) throw new TypeError("sealed inline ciphertext does not match its CID");
28101
+ return { kind: "inline", ciphertextCid: record2.cid, ciphertext, key32 };
28102
+ }
28103
+ var SHORT_LINK_ID_PATTERN = /^[a-z2-7]{26}$/;
28104
+ function assertShortLinkId(id) {
28105
+ if (!SHORT_LINK_ID_PATTERN.test(id)) throw new TypeError("short link id must be 26 lowercase base32 characters");
28106
+ }
28107
+ function parseShortShareUrl(url, options = {}) {
28108
+ let parsed;
28109
+ try {
28110
+ parsed = new URL(url);
28111
+ } catch {
28112
+ throw new TypeError("short share URL is not a URL");
28113
+ }
28114
+ if (parsed.protocol !== "https:" || parsed.username !== "" || parsed.password !== "") throw new TypeError("short share URL must be canonical HTTPS without userinfo");
28115
+ if (!isCanonicalHttpsOrigin4(parsed.origin) || options.expectedOrigin !== void 0 && parsed.origin !== options.expectedOrigin) throw new TypeError("short share URL origin is not trusted");
28116
+ if (parsed.search !== "") throw new TypeError("short share URL must not have a query string");
28117
+ const match = /^\/s\/([A-Za-z2-7]{26})$/.exec(parsed.pathname);
28118
+ if (match === null) throw new TypeError("not a short share URL path");
28119
+ const id = match[1].toLowerCase();
28120
+ const fragment = /^#v=3&k=([A-Za-z0-9_-]{43})&c=([a-z2-7]+)$/.exec(parsed.hash);
28121
+ if (fragment === null) throw new TypeError("short share URL fragment is not canonical");
28122
+ const k = fragment[1];
28123
+ const ciphertextCid = fragment[2];
28124
+ if (url !== `${parsed.origin}${parsed.pathname}${parsed.hash}`) throw new TypeError("short share URL is not lexically canonical");
28125
+ let key32;
28126
+ try {
28127
+ key32 = fromBase64Url4(k);
28128
+ } catch {
28129
+ throw new TypeError("short share URL key is not canonical base64url");
28130
+ }
28131
+ if (key32.byteLength !== KEY_LENGTH3) throw new TypeError("short share URL key must be 32 bytes");
28132
+ try {
28133
+ assertCanonicalCid3(ciphertextCid);
28134
+ } catch {
28135
+ throw new TypeError("short share URL CID is not canonical");
28136
+ }
28137
+ return { kind: "short", origin: parsed.origin, id, k, key32, ciphertextCid };
28138
+ }
28139
+ async function splitInlineToShort(inlineUrl, id) {
28140
+ assertShortLinkId(id);
28141
+ const inline = await parseSealedInlineShareUrl3(inlineUrl);
28142
+ const origin = new URL(inlineUrl).origin;
28143
+ return `${origin}/s/${id}#v=3&k=${toBase64Url3(inline.key32)}&c=${inline.ciphertextCid}`;
28144
+ }
28145
+ async function rebuildInlineFromShort(shortUrl, ciphertextB64Url) {
28146
+ const short = parseShortShareUrl(shortUrl);
28147
+ let ciphertext;
28148
+ try {
28149
+ ciphertext = fromBase64Url4(ciphertextB64Url);
28150
+ } catch {
28151
+ throw new TypeError("short link ciphertext is not canonical base64url");
28152
+ }
28153
+ if (ciphertext.byteLength === 0 || ciphertext.byteLength > MAX_INLINE_BYTES4) throw new TypeError("short link ciphertext is outside the allowed size");
28154
+ if (await computeCid3(ciphertext) !== short.ciphertextCid) throw new TypeError("short link ciphertext does not match the link's CID");
28155
+ return { v: 2, c: ciphertextB64Url, cid: short.ciphertextCid, k: short.k };
28156
+ }
28157
+
28158
+ // src/share/short-links.ts
28159
+ var MAX_SHORT_LINK_BYTES = 128 * 1024;
28160
+ var REQUEST_TIMEOUT_MS = 1e4;
28161
+ var DELETE_TOKEN = /^[A-Za-z0-9_-]{43}$/;
28162
+ var ShortLinkError = class extends Error {
28163
+ constructor(code5, message, options) {
28164
+ super(message, options);
28165
+ this.code = code5;
28166
+ this.name = "ShortLinkError";
28167
+ }
28168
+ };
28169
+ function shortLinkTokenKey(shareId) {
28170
+ return `xyz.tinycloud.share/shares/${shareId}/.short-link.json`;
28171
+ }
28172
+ async function readCapped(response, max) {
28173
+ if (response.body === null) return new Uint8Array(0);
28174
+ const reader = response.body.getReader();
28175
+ const chunks = [];
28176
+ let total = 0;
28177
+ for (; ; ) {
28178
+ const { done, value } = await reader.read();
28179
+ if (done) break;
28180
+ total += value.byteLength;
28181
+ if (total > max) {
28182
+ await reader.cancel().catch(() => void 0);
28183
+ throw new ShortLinkError("too-large", "the short-link service returned too many bytes");
28184
+ }
28185
+ chunks.push(value);
28186
+ }
28187
+ const bytes = new Uint8Array(total);
28188
+ let offset = 0;
28189
+ for (const chunk of chunks) {
28190
+ bytes.set(chunk, offset);
28191
+ offset += chunk.byteLength;
28192
+ }
28193
+ return bytes;
28194
+ }
28195
+ function parseShortLinkRecord(bytes) {
28196
+ let value;
28197
+ try {
28198
+ value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
28199
+ } catch {
28200
+ return void 0;
28201
+ }
28202
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
28203
+ const record2 = value;
28204
+ if (typeof record2.id !== "string" || !SHORT_LINK_ID_PATTERN.test(record2.id)) return void 0;
28205
+ if (typeof record2.deleteToken !== "string" || !DELETE_TOKEN.test(record2.deleteToken)) return void 0;
28206
+ return { id: record2.id, deleteToken: record2.deleteToken };
28207
+ }
28208
+ function serializeShortLinkRecord(record2) {
28209
+ return new TextEncoder().encode(JSON.stringify({ id: record2.id, deleteToken: record2.deleteToken }));
28210
+ }
28211
+ function request(init, timeoutMs) {
28212
+ return { ...init, credentials: "omit", redirect: "error", referrerPolicy: "no-referrer", signal: AbortSignal.timeout(timeoutMs) };
28213
+ }
28214
+ async function send(fetchFn, url, init, timeoutMs) {
28215
+ try {
28216
+ return await fetchFn(url, request(init, timeoutMs));
28217
+ } catch (error) {
28218
+ throw new ShortLinkError("unavailable", "the short-link service could not be reached", { cause: error });
28219
+ }
28220
+ }
28221
+ function statusError(response) {
28222
+ if (response.status === 429) return new ShortLinkError("rate-limited", "the short-link service is rate limiting this client");
28223
+ if (response.status === 503) return new ShortLinkError("capacity", "the short-link service is at capacity");
28224
+ if (response.status === 404) return new ShortLinkError("not-found", "the short link has expired, was revoked, or never existed");
28225
+ if (response.status >= 400 && response.status < 500) return new ShortLinkError("rejected", `the short-link service rejected the request (HTTP ${response.status})`);
28226
+ return new ShortLinkError("unavailable", `the short-link service failed (HTTP ${response.status})`);
28227
+ }
28228
+ function createShortLinkClient(origin, fetchFn = globalThis.fetch, timeoutMs = REQUEST_TIMEOUT_MS) {
28229
+ const base5 = `${origin}/api/share-links`;
28230
+ return {
28231
+ async create(ciphertext, expiresAt) {
28232
+ if (ciphertext.byteLength === 0 || ciphertext.byteLength > MAX_SHORT_LINK_BYTES) throw new ShortLinkError("too-large", "the sealed share is too large for a short link");
28233
+ const expectedCid = await computeCid2(ciphertext);
28234
+ const response = await send(fetchFn, base5, {
28235
+ method: "POST",
28236
+ headers: { "content-type": "application/json", accept: "application/json" },
28237
+ body: JSON.stringify({ ciphertext: toBase64Url2(ciphertext), expiresAt: expiresAt.toISOString() })
28238
+ }, timeoutMs);
28239
+ if (response.status !== 201) throw statusError(response);
28240
+ let value;
28241
+ try {
28242
+ value = await response.json();
28243
+ } catch {
28244
+ throw new ShortLinkError("invalid-response", "the short-link service returned an unreadable response");
28245
+ }
28246
+ const body = typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
28247
+ if (typeof body.id !== "string" || !SHORT_LINK_ID_PATTERN.test(body.id)) throw new ShortLinkError("invalid-response", "the short-link service returned an invalid id");
28248
+ if (typeof body.deleteToken !== "string" || !DELETE_TOKEN.test(body.deleteToken) || fromBase64Url3(body.deleteToken).byteLength !== 32) {
28249
+ throw new ShortLinkError("invalid-response", "the short-link service returned an invalid delete token");
28250
+ }
28251
+ if (body.cid !== expectedCid) throw new ShortLinkError("invalid-response", "the short-link service stored different bytes than were sent");
28252
+ return { id: body.id, deleteToken: body.deleteToken };
28253
+ },
28254
+ async fetchCiphertext(id) {
28255
+ if (!SHORT_LINK_ID_PATTERN.test(id)) throw new ShortLinkError("not-found", "the short link has expired, was revoked, or never existed");
28256
+ const response = await send(fetchFn, `${base5}/${id}`, { method: "GET", headers: { accept: "application/octet-stream" } }, timeoutMs);
28257
+ if (response.status !== 200) throw statusError(response);
28258
+ if ((response.headers.get("content-type") ?? "").split(";", 1)[0].trim().toLowerCase() !== "application/octet-stream") {
28259
+ await response.body?.cancel().catch(() => void 0);
28260
+ throw new ShortLinkError("invalid-response", "the short-link service did not return sealed bytes");
28261
+ }
28262
+ const declared = Number(response.headers.get("content-length") ?? "0");
28263
+ if (declared > MAX_SHORT_LINK_BYTES) {
28264
+ await response.body?.cancel().catch(() => void 0);
28265
+ throw new ShortLinkError("too-large", "the short-link service returned too many bytes");
28266
+ }
28267
+ const bytes = await readCapped(response, MAX_SHORT_LINK_BYTES);
28268
+ if (bytes.byteLength === 0) throw new ShortLinkError("invalid-response", "the short-link service returned no bytes");
28269
+ return bytes;
28270
+ },
28271
+ async delete(record2) {
28272
+ const response = await send(fetchFn, `${base5}/${record2.id}`, { method: "DELETE", headers: { authorization: `Bearer ${record2.deleteToken}` } }, timeoutMs);
28273
+ if (response.status === 204) return "deleted";
28274
+ if (response.status === 404) return "absent";
28275
+ throw statusError(response);
28276
+ }
28277
+ };
28278
+ }
28279
+ async function shortenInlineLink(input) {
28280
+ const inline = await parseSealedInlineShareUrl2(input.inlineUrl);
28281
+ const record2 = await input.client.create(inline.ciphertext, input.expiresAt);
28282
+ try {
28283
+ await input.tokens.write(input.shareId, record2);
28284
+ } catch (error) {
28285
+ await input.client.delete(record2).catch(() => void 0);
28286
+ throw new ShortLinkError("token-store-failed", "the short link's delete token could not be saved", { cause: error });
28287
+ }
28288
+ return splitInlineToShort(input.inlineUrl, record2.id);
28289
+ }
28290
+ async function resolveShortLink(link4, options) {
28291
+ let short;
28292
+ try {
28293
+ short = parseShortShareUrl(link4);
28294
+ } catch {
28295
+ return link4;
28296
+ }
28297
+ if (short.origin !== options.expectedOrigin) throw new ShortLinkError("rejected", "the short link is not from the trusted Share origin");
28298
+ const ciphertext = await createShortLinkClient(options.expectedOrigin, options.fetchFn).fetchCiphertext(short.id);
28299
+ let payload;
28300
+ try {
28301
+ payload = await rebuildInlineFromShort(link4, toBase64Url2(ciphertext));
28302
+ } catch (error) {
28303
+ throw new ShortLinkError("invalid-response", "the short-link service returned bytes that do not match the link", { cause: error });
28304
+ }
28305
+ return encodeSealedInlineShareUrl2({ origin: short.origin, ciphertext: fromBase64Url3(payload.c), key32: fromBase64Url3(payload.k) });
28306
+ }
28307
+ function kvErrorCode(error) {
28308
+ return typeof error === "object" && error !== null && "code" in error && typeof error.code === "string" ? error.code : void 0;
28309
+ }
28310
+ function kvShortLinkTokenStore(kv) {
28311
+ return {
28312
+ async read(shareId) {
28313
+ const read5 = await (await kv()).get(shortLinkTokenKey(shareId), { binary: true });
28314
+ if (read5.ok) return parseShortLinkRecord(new Uint8Array(read5.data.data));
28315
+ if (kvErrorCode(read5.error) === "KV_NOT_FOUND") return void 0;
28316
+ throw new Error(`could not read the short-link token (${kvErrorCode(read5.error) ?? "unknown error"})`);
28317
+ },
28318
+ async write(shareId, record2) {
28319
+ const written = await (await kv()).put(shortLinkTokenKey(shareId), serializeShortLinkRecord(record2), { contentType: "application/json" });
28320
+ if (!written.ok) throw new Error(`could not write the short-link token (${kvErrorCode(written.error) ?? "unknown error"})`);
28321
+ },
28322
+ async remove(shareId) {
28323
+ const removed = await (await kv()).delete(shortLinkTokenKey(shareId));
28324
+ if (!removed.ok && kvErrorCode(removed.error) !== "KV_NOT_FOUND") throw new Error(`could not remove the short-link token (${kvErrorCode(removed.error) ?? "unknown error"})`);
28325
+ }
28326
+ };
28327
+ }
28328
+ function isInlineLink(link4) {
28329
+ if (link4 === void 0) return false;
28330
+ try {
28331
+ return new URL(link4).pathname === "/s/inline";
28332
+ } catch {
28333
+ return false;
28334
+ }
28335
+ }
28336
+ function createShareShortLinks(input) {
28337
+ const tokens = (spaceId) => kvShortLinkTokenStore(() => input.kvForSpace(spaceId));
28338
+ const client = (inlineUrl) => createShortLinkClient(new URL(inlineUrl).origin, input.fetchFn, input.timeoutMs);
28339
+ return {
28340
+ async shorten(published) {
28341
+ if (published.link.kind !== "policy" || !isInlineLink(published.url)) throw new ShortLinkError("rejected", "only addressed shares get a short link");
28342
+ return shortenInlineLink({
28343
+ inlineUrl: published.url,
28344
+ shareId: published.metadata.shareId,
28345
+ expiresAt: new Date(published.metadata.expiresAt),
28346
+ client: client(published.url),
28347
+ tokens: tokens(published.metadata.target.spaceId)
28348
+ });
28349
+ },
28350
+ async linkFor(record2) {
28351
+ if (!isInlineLink(record2.link)) return void 0;
28352
+ const inlineUrl = record2.link;
28353
+ const stored = await tokens(record2.target.spaceId).read(record2.shareId).catch(() => void 0);
28354
+ return stored === void 0 ? void 0 : splitInlineToShort(inlineUrl, stored.id).catch(() => void 0);
28355
+ },
28356
+ async discard(record2) {
28357
+ if (!isInlineLink(record2.link)) return "none";
28358
+ return discardShortLink(record2.shareId, client(record2.link), tokens(record2.target.spaceId));
28359
+ },
28360
+ resolve: (link4, expectedOrigin) => resolveShortLink(link4, { expectedOrigin, ...input.fetchFn === void 0 ? {} : { fetchFn: input.fetchFn } })
28361
+ };
28362
+ }
28363
+ async function discardShortLink(shareId, client, tokens) {
28364
+ let record2;
28365
+ try {
28366
+ record2 = await tokens.read(shareId);
28367
+ } catch {
28368
+ return "failed";
28369
+ }
28370
+ if (record2 === void 0) return "none";
28371
+ try {
28372
+ await client.delete(record2);
28373
+ } catch {
28374
+ return "failed";
28375
+ }
28376
+ await tokens.remove(shareId).catch(() => void 0);
28377
+ return "deleted";
28378
+ }
28379
+
28380
+ // src/share/errors.ts
28381
+ var SharePublishAuthorityError = class extends Error {
28382
+ constructor(failure, options) {
28383
+ super(failure.kind, options);
28384
+ this.failure = failure;
28385
+ this.name = "SharePublishAuthorityError";
28386
+ }
28387
+ };
28388
+ var ShareHistoryRetryError = class extends Error {
28389
+ constructor(profile) {
28390
+ super("sender history changed during the operation");
28391
+ this.profile = profile;
28392
+ this.name = "ShareHistoryRetryError";
28393
+ }
28394
+ code = "SHARE_HISTORY_RETRY";
28395
+ };
28396
+ var ShareHistoryUnreadableError = class extends Error {
28397
+ constructor() {
28398
+ super("share history is unavailable");
28399
+ this.name = "ShareHistoryUnreadableError";
28400
+ }
28401
+ };
28402
+ var ShareHistoryReadError = class extends Error {
28403
+ constructor() {
28404
+ super("share history could not be read");
28405
+ this.name = "ShareHistoryReadError";
28406
+ }
28407
+ };
28408
+ var HISTORY_WRITE_ERROR_CODES = { EACCES: true, EPERM: true, EROFS: true, ENOSPC: true, EDQUOT: true, EIO: true };
28409
+ function shareHistoryReason(error) {
28410
+ if (error instanceof ShareHistoryUnreadableError) return "HISTORY_UNREADABLE";
28411
+ if (error instanceof ShareHistoryReadError) return "HISTORY_READ_FAILED";
28412
+ const code5 = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
28413
+ return typeof code5 === "string" && HISTORY_WRITE_ERROR_CODES[code5] === true ? "HISTORY_WRITE_FAILED" : "HISTORY_UNAVAILABLE";
28414
+ }
28415
+
28416
+ // src/share/space-not-ready.ts
28417
+ function isSpaceNotFound(error) {
28418
+ if (typeof error !== "object" || error === null) return false;
28419
+ const message = "message" in error && typeof error.message === "string" ? error.message : "";
28420
+ if (!/space not found/i.test(message)) return false;
28421
+ const meta = "meta" in error && typeof error.meta === "object" && error.meta !== null ? error.meta : void 0;
28422
+ const status = meta !== void 0 && "status" in meta ? meta.status : void 0;
28423
+ return status === 404 || /\b404\b/.test(message);
28424
+ }
28425
+ function spaceNotReadyFailure(cause) {
28426
+ return new SharePublishAuthorityError({ kind: "space-not-ready" }, { cause });
28427
+ }
28428
+ function failIfSpaceNotReady(result) {
28429
+ if (!result.ok && isSpaceNotFound(result.error)) throw spaceNotReadyFailure(result.error);
28430
+ }
28431
+ function artifactSpaceNotReady(error) {
28432
+ return error instanceof ArtifactError && isSpaceNotFound(error.cause) ? spaceNotReadyFailure(error.cause) : error;
28433
+ }
28434
+
28435
+ // src/share/adapters.ts
28436
+ init_storage();
28437
+ init_profiles();
28438
+ init_constants();
28439
+ init_errors();
28440
+ init_session_expired();
28441
+ import { chmod as chmod4, link as link3, open as open8, readFile as readFile7, stat as stat5, unlink as unlink5 } from "fs/promises";
28442
+ import { dirname as dirname5, join as join12 } from "path";
28443
+ import { createHash } from "crypto";
28444
+ import { writeJsonAtomic as writeJsonAtomic2 } from "@tinycloud/operations/state";
28445
+ import { withoutBearer } from "@tinycloud/operations/delegation-binding";
28446
+ import {
28447
+ LocationRecordValidationError,
28448
+ LocationRegistryHttpError,
28449
+ parseSignedCompactUcanAttenuation,
28450
+ parseSignedSiweCacao,
28451
+ revokePolicyRootV3,
28452
+ signCompactUcanAuthorization
28453
+ } from "@tinycloud/sdk-core";
28454
+ import { extractSiweExpiration, InvalidRestoredSessionError } from "@tinycloud/node-sdk";
28455
+ function requiredKvAction(meta) {
28456
+ if (meta === null || typeof meta !== "object" || !("requiredAction" in meta)) return void 0;
28457
+ const action = meta.requiredAction;
28458
+ return action === "tinycloud.kv/put" || action === "tinycloud.kv/get" || action === "tinycloud.kv/list" ? action : void 0;
28459
+ }
28460
+ function throwKvUploadFailure(error) {
28461
+ const rejection = storageRejection(error);
28462
+ if (rejection) throw new SharePublishAuthorityError({ kind: "storage-full", ...rejection });
28463
+ throw new SharePublishAuthorityError({ kind: "upload-failed" });
28464
+ }
28465
+ function sessionHoldsEncryptionDecrypt(node, networkId) {
28466
+ return node.hasRuntimePermissions([{ service: "tinycloud.encryption", path: networkId, actions: ["tinycloud.encryption/decrypt"] }]);
28467
+ }
28468
+ var DEFAULT_SHARE_ORIGIN = "https://share.tinycloud.xyz";
28469
+ var MIN_DOMAIN_DELIVERY_VERSION = "1.17.3";
28470
+ function supportsDomainDelivery(version2) {
28471
+ if (typeof version2 !== "string") return false;
28472
+ const normalized = version2.trim();
28473
+ if (normalized.length > 128) return false;
28474
+ const match = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/.exec(normalized);
28475
+ if (match === null) return false;
28476
+ if (match[4] !== void 0 && /(?:^|\.)0[0-9]+(?:\.|$)/.test(match[4])) return false;
28477
+ const major = Number(match[1]);
28478
+ const minor = Number(match[2]);
28479
+ const patch = Number(match[3]);
28480
+ if (!Number.isSafeInteger(major) || !Number.isSafeInteger(minor) || !Number.isSafeInteger(patch)) return false;
28481
+ if (major !== 1) return major > 1;
28482
+ if (minor !== 17) return minor > 17;
28483
+ if (patch !== 3) return patch > 3;
28484
+ return match[4] === void 0;
28485
+ }
28486
+ function displayedNodeVersion(version2) {
28487
+ if (typeof version2 !== "string") return "(unrecognized)";
28488
+ const trimmed = version2.trim();
28489
+ return /^[A-Za-z0-9.+_-]{1,64}$/.test(trimmed) ? trimmed : "(unrecognized)";
28490
+ }
28491
+ var URI_SAFE_FILENAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
28492
+ function safeStorageFilename(filename) {
28493
+ if (URI_SAFE_FILENAME.test(filename) && !filename.includes("..")) return filename;
28494
+ const dot = filename.lastIndexOf(".");
28495
+ const extension = dot >= 0 && /^[A-Za-z0-9]{1,16}$/.test(filename.slice(dot + 1)) ? filename.slice(dot + 1) : "";
28496
+ const stem = (extension === "" ? filename : filename.slice(0, dot)).normalize("NFKD").replace(/[\u0300-\u036f]/g, "").replace(extension === "" ? /[^A-Za-z0-9_-]+/g : /[^A-Za-z0-9._-]+/g, "-").replace(/\.{2,}/g, ".").replace(/-{2,}/g, "-").slice(0, 100).replace(/^[^A-Za-z0-9]+|[-.]+$/g, "");
28497
+ return `${stem === "" ? "share" : stem}${extension === "" ? "" : `.${extension}`}`;
28498
+ }
28499
+ function scopeDeniedFromArtifactError(error, capability, authority) {
28500
+ const cause = error instanceof ArtifactError ? error.cause : void 0;
28501
+ const code5 = typeof cause === "object" && cause !== null && "code" in cause ? cause.code : void 0;
28502
+ if (code5 !== "AUTH_UNAUTHORIZED" && code5 !== "PERMISSION_DENIED") return void 0;
28503
+ const meta = typeof cause === "object" && cause !== null && "meta" in cause ? cause.meta : void 0;
28504
+ const requiredAction = requiredKvAction(meta);
28505
+ return new SharePublishAuthorityError({
28506
+ kind: "scope-denied",
28507
+ capability,
28508
+ ...requiredAction === void 0 ? {} : { requiredAction },
28509
+ localKey: authority.localKey,
28510
+ profileName: authority.profileName
28511
+ });
28512
+ }
28513
+ async function storeArtifactVersion(kv, version2, authority) {
28514
+ try {
28515
+ return await publishArtifactVersion(kvArtifactStore(kv), version2);
28516
+ } catch (error) {
28517
+ throw scopeDeniedFromArtifactError(error, "KV upload", authority) ?? artifactSpaceNotReady(error);
28518
+ }
28519
+ }
28520
+ function createEncryptedSessionHistory() {
28521
+ const records = /* @__PURE__ */ new Map();
28522
+ let operation = Promise.resolve();
28523
+ const serial = (action) => {
28524
+ const next = operation.then(action, action);
28525
+ operation = next.then(() => void 0, () => void 0);
28526
+ return next;
28527
+ };
28528
+ let keyPromise;
28529
+ const key = async () => keyPromise ??= crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
28530
+ const encode7 = async (record2) => {
28531
+ const secret = new TextEncoder().encode(JSON.stringify(record2));
28532
+ const iv = crypto.getRandomValues(new Uint8Array(12));
28533
+ const encrypted = new Uint8Array(await crypto.subtle.encrypt({ name: "AES-GCM", iv }, await key(), secret));
28534
+ const value = new Uint8Array(iv.length + encrypted.length);
28535
+ value.set(iv);
28536
+ value.set(encrypted, iv.length);
28537
+ return value;
28538
+ };
28539
+ const decode11 = async (value) => JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await crypto.subtle.decrypt({ name: "AES-GCM", iv: value.slice(0, 12) }, await key(), value.slice(12))));
28540
+ return {
28541
+ async put(record2) {
28542
+ return serial(async () => {
28543
+ records.set(record2.shareId, await encode7(record2));
28544
+ });
28545
+ },
28546
+ async update(shareId, change) {
28547
+ return serial(async () => {
28548
+ const value = records.get(shareId);
28549
+ if (value === void 0) return void 0;
28550
+ const updated = await change(await decode11(value));
28551
+ records.set(shareId, await encode7(updated));
28552
+ return updated;
28553
+ });
28554
+ },
28555
+ async list() {
28556
+ return serial(() => Promise.all([...records.values()].map(decode11)));
28557
+ },
28558
+ async get(shareId) {
28559
+ return serial(async () => {
28560
+ const value = records.get(shareId);
28561
+ return value === void 0 ? void 0 : decode11(value);
28562
+ });
28563
+ },
28564
+ async delete(shareId) {
28565
+ return serial(async () => {
28566
+ records.delete(shareId);
28567
+ });
28568
+ }
28569
+ };
28570
+ }
28571
+ var SHARE_HISTORY_FILE = "share-history-v2.json";
28572
+ var SHARE_HISTORY_LEGACY_FILE = "share-history-v1.bin";
28573
+ var PRIVATE_HISTORY_MODE = 384;
28574
+ async function signShareHistoryBytes(bytes, profile) {
28575
+ const context = await ProfileManager.resolveContext({ profile });
28576
+ if (context.profile !== profile) throw new ShareHistoryRetryError(profile);
28577
+ const { ensureAuthenticated: ensureAuthenticated2 } = await Promise.resolve().then(() => (init_sdk(), sdk_exports));
28578
+ const signer = await ensureAuthenticated2(context);
28579
+ return signer.signSessionBytes(bytes);
28580
+ }
28581
+ function createEncryptedProfileHistory(profileName, sessionSigner) {
28582
+ const HISTORY_VERSION = 2;
26808
28583
  const identityChanged = new Error("share history profile or key changed");
26809
28584
  const saltChanged = new Error("share history salt changed");
26810
28585
  let operation = Promise.resolve();
@@ -26880,7 +28655,7 @@ function createEncryptedProfileHistory(profileName, sessionSigner) {
26880
28655
  if (salt.length < 16) throw new ShareHistoryUnreadableError();
26881
28656
  return salt;
26882
28657
  };
26883
- const read4 = async (profile, ready) => {
28658
+ const read5 = async (profile, ready) => {
26884
28659
  const file = await readIfPresent(await path(profile));
26885
28660
  if (file === void 0) {
26886
28661
  const legacy = await readIfPresent(await legacyPath(profile));
@@ -26969,7 +28744,7 @@ function createEncryptedProfileHistory(profileName, sessionSigner) {
26969
28744
  false,
26970
28745
  ["encrypt", "decrypt"]
26971
28746
  );
26972
- await read4(profile, { salt, key, legacyKey: keys.legacyKey });
28747
+ await read5(profile, { salt, key, legacyKey: keys.legacyKey });
26973
28748
  return true;
26974
28749
  } catch (error) {
26975
28750
  if (error instanceof ShareHistoryUnreadableError) return false;
@@ -27008,7 +28783,7 @@ function createEncryptedProfileHistory(profileName, sessionSigner) {
27008
28783
  return {
27009
28784
  async put(record2) {
27010
28785
  return locked(async (profile, ready) => {
27011
- const values = await read4(profile, ready);
28786
+ const values = await read5(profile, ready);
27012
28787
  const index = values.findIndex((value) => value.shareId === record2.shareId);
27013
28788
  if (index >= 0) values[index] = record2;
27014
28789
  else values.push(record2);
@@ -27017,7 +28792,7 @@ function createEncryptedProfileHistory(profileName, sessionSigner) {
27017
28792
  },
27018
28793
  async update(shareId, change) {
27019
28794
  return locked(async (profile, ready) => {
27020
- const values = await read4(profile, ready);
28795
+ const values = await read5(profile, ready);
27021
28796
  const index = values.findIndex((record2) => record2.shareId === shareId);
27022
28797
  if (index < 0) return void 0;
27023
28798
  const updated = await change(values[index]);
@@ -27027,14 +28802,14 @@ function createEncryptedProfileHistory(profileName, sessionSigner) {
27027
28802
  }, true);
27028
28803
  },
27029
28804
  async list() {
27030
- return locked((profile, ready) => read4(profile, ready));
28805
+ return locked((profile, ready) => read5(profile, ready));
27031
28806
  },
27032
28807
  async get(shareId) {
27033
- return locked(async (profile, ready) => (await read4(profile, ready)).find((record2) => record2.shareId === shareId));
28808
+ return locked(async (profile, ready) => (await read5(profile, ready)).find((record2) => record2.shareId === shareId));
27034
28809
  },
27035
28810
  async delete(shareId) {
27036
28811
  return locked(async (profile, ready) => {
27037
- await write(profile, (await read4(profile, ready)).filter((record2) => record2.shareId !== shareId), ready);
28812
+ await write(profile, (await read5(profile, ready)).filter((record2) => record2.shareId !== shareId), ready);
27038
28813
  }, true);
27039
28814
  },
27040
28815
  quarantineUnreadable
@@ -27057,13 +28832,19 @@ function createShareAuthorityAdapters(input = {}) {
27057
28832
  };
27058
28833
  let configPromise;
27059
28834
  const publicConfig = async () => configPromise ??= (async () => {
27060
- const response = await fetchFn(`${origin}/.well-known/tinycloud-share/config.json`, {
27061
- headers: { accept: "application/json" },
27062
- credentials: "omit",
27063
- redirect: "error",
27064
- referrerPolicy: "no-referrer"
27065
- });
27066
- if (!response.ok) throw new Error("share public config is unavailable");
28835
+ let response;
28836
+ try {
28837
+ response = await fetchFn(`${origin}/.well-known/tinycloud-share/config.json`, {
28838
+ headers: { accept: "application/json" },
28839
+ credentials: "omit",
28840
+ redirect: "error",
28841
+ referrerPolicy: "no-referrer",
28842
+ signal: AbortSignal.timeout(1e4)
28843
+ });
28844
+ } catch (error) {
28845
+ throw new SharePublishAuthorityError({ kind: "share-service-unavailable", origin }, { cause: error });
28846
+ }
28847
+ if (!response.ok) throw new SharePublishAuthorityError({ kind: "share-service-unavailable", origin });
27067
28848
  const value = await response.json();
27068
28849
  if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error("share public config is invalid");
27069
28850
  const object3 = value;
@@ -27085,8 +28866,8 @@ function createShareAuthorityAdapters(input = {}) {
27085
28866
  return await ensureAuthenticated2(context);
27086
28867
  } catch (error) {
27087
28868
  const profileConfig = await ProfileManager.getProfile(profile).catch(() => void 0);
27088
- const code4 = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
27089
- if (error instanceof InvalidRestoredSessionError || code4 === "AUTH_EXPIRED" || isSessionExpiredError(error)) {
28869
+ const code5 = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
28870
+ if (error instanceof InvalidRestoredSessionError || code5 === "AUTH_EXPIRED" || isSessionExpiredError(error)) {
27090
28871
  throw new SharePublishAuthorityError({
27091
28872
  kind: "owner-space-unresolved",
27092
28873
  localKey: profileConfig?.authMethod === "local",
@@ -27130,7 +28911,7 @@ function createShareAuthorityAdapters(input = {}) {
27130
28911
  };
27131
28912
  const targetAdapter = { async publish(targetInput) {
27132
28913
  if (input.publishTarget !== void 0) return input.publishTarget(targetInput);
27133
- const [config, node] = await Promise.all([publicConfig(), authenticatedNode()]);
28914
+ const node = await authenticatedNode();
27134
28915
  const session = node.restorableSession;
27135
28916
  const ownerSpaceId = session?.spaceId;
27136
28917
  const localKey = !node.isSessionOnly;
@@ -27143,7 +28924,6 @@ function createShareAuthorityAdapters(input = {}) {
27143
28924
  if (ownerSpaceId === void 0 || node.isSessionOnly && (!session?.siwe || !session.signature || sessionExpiresAt === void 0)) {
27144
28925
  throw new SharePublishAuthorityError({ kind: "owner-space-unresolved", localKey, profileName: activeProfileName2 });
27145
28926
  }
27146
- if (targetInput.origin !== config.shareOrigin) throw new SharePublishAuthorityError({ kind: "origin-mismatch" });
27147
28927
  if (node.isSessionOnly && sessionExpiresAt !== void 0) {
27148
28928
  const roundedSessionExpiry = new Date(Math.floor(sessionExpiresAt.getTime() / 1e3) * 1e3);
27149
28929
  if (roundedSessionExpiry.getTime() <= Date.now() + 6e4) {
@@ -27177,6 +28957,12 @@ function createShareAuthorityAdapters(input = {}) {
27177
28957
  profileName: activeProfileName2
27178
28958
  });
27179
28959
  }
28960
+ const addressedEncryptionNetwork = targetInput.target.kind === "bearer" ? void 0 : node.getEncryptionNetworkIdForSpace(ownerSpaceId);
28961
+ if (addressedEncryptionNetwork !== void 0 && node.isSessionOnly && !sessionHoldsEncryptionDecrypt(node, addressedEncryptionNetwork)) {
28962
+ throw new SharePublishAuthorityError({ kind: "decrypt-not-held" });
28963
+ }
28964
+ const config = await publicConfig();
28965
+ if (targetInput.origin !== config.shareOrigin) throw new SharePublishAuthorityError({ kind: "origin-mismatch" });
27180
28966
  const activeNode = await node.activeNodeIdentity();
27181
28967
  if (targetInput.notify === true && targetInput.target.kind === "emailDomain") {
27182
28968
  await assertDomainDeliveryForOrigin(activeNode.origin, "publish");
@@ -27213,8 +28999,8 @@ function createShareAuthorityAdapters(input = {}) {
27213
28999
  });
27214
29000
  failIfSpaceNotReady(written);
27215
29001
  if (!written.ok) {
27216
- const code4 = typeof written.error === "object" && written.error !== null && "code" in written.error ? written.error.code : void 0;
27217
- if (code4 === "AUTH_UNAUTHORIZED" || code4 === "PERMISSION_DENIED") {
29002
+ const code5 = typeof written.error === "object" && written.error !== null && "code" in written.error ? written.error.code : void 0;
29003
+ if (code5 === "AUTH_UNAUTHORIZED" || code5 === "PERMISSION_DENIED") {
27218
29004
  const requiredAction = requiredKvAction(written.error.meta);
27219
29005
  throw new SharePublishAuthorityError({
27220
29006
  kind: "scope-denied",
@@ -27235,8 +29021,8 @@ function createShareAuthorityAdapters(input = {}) {
27235
29021
  viewerOrigin: config.shareOrigin
27236
29022
  });
27237
29023
  } catch (error) {
27238
- const code4 = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
27239
- if (code4 === "AUTH_UNAUTHORIZED" || code4 === "PERMISSION_DENIED") {
29024
+ const code5 = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
29025
+ if (code5 === "AUTH_UNAUTHORIZED" || code5 === "PERMISSION_DENIED") {
27240
29026
  throw new SharePublishAuthorityError({
27241
29027
  kind: "scope-denied",
27242
29028
  capability: "sharing delegation",
@@ -27297,7 +29083,7 @@ function createShareAuthorityAdapters(input = {}) {
27297
29083
  const rejected = error instanceof LocationRecordValidationError || error instanceof LocationRegistryHttpError && error.status >= 400 && error.status < 500 && error.status !== 408 && error.status !== 429;
27298
29084
  throw new SharePublishAuthorityError({ kind: rejected ? "registry-rejected" : "registry-unavailable" });
27299
29085
  }
27300
- const encryptionNetwork = node.getEncryptionNetworkIdForSpace(ownerSpaceId);
29086
+ const encryptionNetwork = addressedEncryptionNetwork;
27301
29087
  const encrypted = await node.encryption.encryptToNetwork(encryptionNetwork, file.bytes, { metadata: { contentType: mediaType } });
27302
29088
  if (!encrypted.ok) throw new Error("addressed source encryption was rejected");
27303
29089
  const storedBytes = new TextEncoder().encode(canonicalize3(encrypted.data));
@@ -27313,8 +29099,8 @@ function createShareAuthorityAdapters(input = {}) {
27313
29099
  const stored = await node.kvForSpace(ownerSpaceId).put(resourcePath, storedBytes, { contentType: "application/vnd.tinycloud.encrypted-envelope+json" });
27314
29100
  failIfSpaceNotReady(stored);
27315
29101
  if (!stored.ok) {
27316
- const code4 = typeof stored.error === "object" && stored.error !== null && "code" in stored.error ? stored.error.code : void 0;
27317
- if (code4 === "AUTH_UNAUTHORIZED" || code4 === "PERMISSION_DENIED") {
29102
+ const code5 = typeof stored.error === "object" && stored.error !== null && "code" in stored.error ? stored.error.code : void 0;
29103
+ if (code5 === "AUTH_UNAUTHORIZED" || code5 === "PERMISSION_DENIED") {
27318
29104
  const requiredAction = requiredKvAction(stored.error.meta);
27319
29105
  throw new SharePublishAuthorityError({
27320
29106
  kind: "scope-denied",
@@ -27366,9 +29152,9 @@ function createShareAuthorityAdapters(input = {}) {
27366
29152
  // transport hop, so the CLI supplies only owner signing material.
27367
29153
  authority: {
27368
29154
  ownerDid: node.credentialHolderDid,
27369
- createOwnerRoot: (request) => node.createUnifiedOwnerRoot(request),
29155
+ createOwnerRoot: (request2) => node.createUnifiedOwnerRoot(request2),
27370
29156
  sign: (bytes) => node.signSessionBytes(bytes),
27371
- registerPolicy: (request) => node.registerPolicy(request)
29157
+ registerPolicy: (request2) => node.registerPolicy(request2)
27372
29158
  }
27373
29159
  });
27374
29160
  if (expiryClamped) Object.defineProperty(published.metadata, "expiryClamped", { value: true, enumerable: true });
@@ -27377,9 +29163,9 @@ function createShareAuthorityAdapters(input = {}) {
27377
29163
  }
27378
29164
  return published;
27379
29165
  } };
27380
- const delivery = { deliver: input.deliver ?? (async (request) => {
27381
- const record2 = request.record;
27382
- if (record2 === void 0 || record2.link === void 0 || record2.deliveryMaterial === void 0 || request.idempotencyKey === void 0) throw new Error("share delivery history is incomplete");
29166
+ const delivery = { deliver: input.deliver ?? (async (request2) => {
29167
+ const record2 = request2.record;
29168
+ if (record2 === void 0 || record2.link === void 0 || record2.deliveryMaterial === void 0 || request2.idempotencyKey === void 0) throw new Error("share delivery history is incomplete");
27383
29169
  const expiry = shareDeliveryWindowExpiresAt(record2);
27384
29170
  if (expiry <= Date.now()) throw new ShareNotifyError("share delivery authorization window has expired", "delivery-window-expired");
27385
29171
  const authorizationExpiresAt = new Date(expiry).toISOString();
@@ -27390,19 +29176,19 @@ function createShareAuthorityAdapters(input = {}) {
27390
29176
  envelopeKey: record2.deliveryMaterial.envelopeKey,
27391
29177
  shareCid: record2.deliveryMaterial.shareCid,
27392
29178
  resourcePath: record2.resource.path,
27393
- recipientEmail: request.recipient,
29179
+ recipientEmail: request2.recipient,
27394
29180
  shareUrl: record2.link,
27395
29181
  documentName: record2.filename ?? "share.md",
27396
29182
  expiresAt: authorizationExpiresAt,
27397
29183
  deliveryAudience: config.credentialsOrigin,
27398
- idempotencyKey: request.idempotencyKey
29184
+ idempotencyKey: request2.idempotencyKey
27399
29185
  });
27400
29186
  await deliverCredentialInvitation({
27401
29187
  credentialsOrigin: config.credentialsOrigin,
27402
29188
  receipt,
27403
29189
  shareUrl: record2.link,
27404
29190
  fetchFn,
27405
- signal: request.signal
29191
+ signal: request2.signal
27406
29192
  });
27407
29193
  return "delivered";
27408
29194
  }) };
@@ -27482,16 +29268,16 @@ function createShareAuthorityAdapters(input = {}) {
27482
29268
  { status: response.status }
27483
29269
  );
27484
29270
  }),
27485
- revokePolicyRoot: input.revokePolicyRoot ?? (async (request) => {
29271
+ revokePolicyRoot: input.revokePolicyRoot ?? (async (request2) => {
27486
29272
  const node = await authenticatedNode();
27487
29273
  const activeNode = await node.activeNodeIdentity();
27488
- if (request.nodeOrigin !== activeNode.origin || request.nodeAudience !== activeNode.nodeDid || request.ownerDid !== node.credentialHolderDid) {
29274
+ if (request2.nodeOrigin !== activeNode.origin || request2.nodeAudience !== activeNode.nodeDid || request2.ownerDid !== node.credentialHolderDid) {
27489
29275
  throw new Error("share Policy/v3 revocation is not bound to the active owner node");
27490
29276
  }
27491
29277
  await revokePolicyRootV3({
27492
29278
  nodeOrigin: activeNode.origin,
27493
- rootCid: request.rootCid,
27494
- targetRole: request.targetRole,
29279
+ rootCid: request2.rootCid,
29280
+ targetRole: request2.targetRole,
27495
29281
  ownerDid: node.credentialHolderDid,
27496
29282
  issuerDid: node.credentialHolderDid,
27497
29283
  nodeAudience: activeNode.nodeDid,
@@ -27535,6 +29321,10 @@ function createShareAuthorityAdapters(input = {}) {
27535
29321
  list: (prefix) => mapped(() => store.list(prefix))
27536
29322
  };
27537
29323
  };
29324
+ const shortLinks = createShareShortLinks({
29325
+ kvForSpace: async (spaceId) => (await authenticatedNode()).kvForSpace(spaceId),
29326
+ fetchFn
29327
+ });
27538
29328
  return {
27539
29329
  targetAdapter,
27540
29330
  records: input.profileName === void 0 ? createEncryptedSessionHistory() : createEncryptedProfileHistory(profileName, signShareHistoryBytes),
@@ -27542,7 +29332,8 @@ function createShareAuthorityAdapters(input = {}) {
27542
29332
  revocation,
27543
29333
  assertDomainDelivery,
27544
29334
  nativeReader,
27545
- artifactStore
29335
+ artifactStore,
29336
+ shortLinks
27546
29337
  };
27547
29338
  }
27548
29339
  async function selectedProfileName() {
@@ -27898,7 +29689,7 @@ var SCRIPT_END = /<\/script/gi;
27898
29689
  var STYLE_END = /<\/style/gi;
27899
29690
  function scanMarkup(html, options) {
27900
29691
  const checkReferences = options.references;
27901
- const length4 = html.length;
29692
+ const length5 = html.length;
27902
29693
  let index = 0;
27903
29694
  let comments = 0;
27904
29695
  const malformed = (detail) => {
@@ -27909,7 +29700,7 @@ function scanMarkup(html, options) {
27909
29700
  comments += 1;
27910
29701
  if (comments > MAX_ARTIFACT_COMMENTS) fail("limit", "artifact page has too many comments");
27911
29702
  };
27912
- while (index < length4) {
29703
+ while (index < length5) {
27913
29704
  const open10 = html.indexOf("<", index);
27914
29705
  if (open10 === -1) return;
27915
29706
  index = open10 + 1;
@@ -27953,8 +29744,8 @@ function scanMarkup(html, options) {
27953
29744
  const attributes = /* @__PURE__ */ new Map();
27954
29745
  let attributeCount = 0;
27955
29746
  for (; ; ) {
27956
- while (index < length4 && SKIPPED.test(html[index])) index += 1;
27957
- if (index >= length4) {
29747
+ while (index < length5 && SKIPPED.test(html[index])) index += 1;
29748
+ if (index >= length5) {
27958
29749
  if (malformed("artifact output has an unterminated tag")) return;
27959
29750
  return;
27960
29751
  }
@@ -27965,11 +29756,11 @@ function scanMarkup(html, options) {
27965
29756
  ATTRIBUTE_NAME.lastIndex = index;
27966
29757
  const rawName = ATTRIBUTE_NAME.exec(html)[0];
27967
29758
  index = ATTRIBUTE_NAME.lastIndex;
27968
- while (index < length4 && SPACE.test(html[index])) index += 1;
29759
+ while (index < length5 && SPACE.test(html[index])) index += 1;
27969
29760
  let rawValue = "";
27970
29761
  if (html[index] === "=") {
27971
29762
  index += 1;
27972
- while (index < length4 && SPACE.test(html[index])) index += 1;
29763
+ while (index < length5 && SPACE.test(html[index])) index += 1;
27973
29764
  const quote = html[index];
27974
29765
  if (quote === '"' || quote === "'") {
27975
29766
  const close = html.indexOf(quote, index + 1);
@@ -27994,7 +29785,7 @@ function scanMarkup(html, options) {
27994
29785
  checkAttribute(name, decoded);
27995
29786
  if (isHrefAnimation(tag, name, decoded)) unsupportedOutput("artifact svg animates a resource reference");
27996
29787
  if (!attributes.has(name)) attributes.set(name, decoded);
27997
- } else if (index < length4 && html[index] !== ">" && !SKIPPED.test(html[index])) {
29788
+ } else if (index < length5 && html[index] !== ">" && !SKIPPED.test(html[index])) {
27998
29789
  index += 1;
27999
29790
  }
28000
29791
  }
@@ -28017,7 +29808,7 @@ function scanMarkup(html, options) {
28017
29808
  } else if (tag === "style" && checkReferences) {
28018
29809
  STYLE_END.lastIndex = index;
28019
29810
  const close = STYLE_END.exec(html);
28020
- assertOnlyInlineCssReferences(html.slice(index, close === null ? length4 : close.index));
29811
+ assertOnlyInlineCssReferences(html.slice(index, close === null ? length5 : close.index));
28021
29812
  }
28022
29813
  }
28023
29814
  }
@@ -28121,26 +29912,26 @@ function requiredFile(context, basePath, reference) {
28121
29912
  return { file, resolved };
28122
29913
  }
28123
29914
  var CSS_REFERENCE_NAMES = /* @__PURE__ */ new Set(["url", "image-set", "-webkit-image-set", "src", "import"]);
28124
- function isCssIdentifierCode(code4) {
28125
- return code4 >= 128 || code4 >= 48 && code4 <= 57 || code4 >= 65 && code4 <= 90 || code4 >= 97 && code4 <= 122 || code4 === 95 || code4 === 45;
29915
+ function isCssIdentifierCode(code5) {
29916
+ return code5 >= 128 || code5 >= 48 && code5 <= 57 || code5 >= 65 && code5 <= 90 || code5 >= 97 && code5 <= 122 || code5 === 95 || code5 === 45;
28126
29917
  }
28127
29918
  function normalizeCssEscapes(source) {
28128
29919
  let output = "";
28129
29920
  let index = 0;
28130
- const length4 = source.length;
28131
- while (index < length4) {
29921
+ const length5 = source.length;
29922
+ while (index < length5) {
28132
29923
  const char = source[index];
28133
29924
  if (char === "/" && source[index + 1] === "*") {
28134
29925
  const end = source.indexOf("*/", index + 2);
28135
- const stop = end === -1 ? length4 : end + 2;
29926
+ const stop = end === -1 ? length5 : end + 2;
28136
29927
  output += source.slice(index, stop);
28137
29928
  index = stop;
28138
29929
  continue;
28139
29930
  }
28140
29931
  if (char === '"' || char === "'") {
28141
29932
  let cursor = index + 1;
28142
- while (cursor < length4 && source[cursor] !== char && source[cursor] !== "\n") cursor += source[cursor] === "\\" ? 2 : 1;
28143
- const stop = Math.min(source[cursor] === char ? cursor + 1 : cursor, length4);
29933
+ while (cursor < length5 && source[cursor] !== char && source[cursor] !== "\n") cursor += source[cursor] === "\\" ? 2 : 1;
29934
+ const stop = Math.min(source[cursor] === char ? cursor + 1 : cursor, length5);
28144
29935
  output += source.slice(index, stop);
28145
29936
  index = stop;
28146
29937
  continue;
@@ -28149,7 +29940,7 @@ function normalizeCssEscapes(source) {
28149
29940
  let cursor = index;
28150
29941
  let decoded = "";
28151
29942
  let escaped = false;
28152
- while (cursor < length4) {
29943
+ while (cursor < length5) {
28153
29944
  if (source[cursor] === "\\") {
28154
29945
  const next = source[cursor + 1];
28155
29946
  if (next === void 0) {
@@ -28193,15 +29984,15 @@ function assertOnlyInlineCssReferences(css) {
28193
29984
  if (/@import/i.test(text)) fail("unsupported", "artifact css still imports a stylesheet");
28194
29985
  if (/(?:^|[^\w-])(?:-webkit-)?image-set\s*\(/i.test(text) || /(?:^|[^\w-])src\s*\(/i.test(text)) fail("unsupported", "artifact css uses an unsupported resource function");
28195
29986
  const opened = text.match(/url\(/gi)?.length ?? 0;
28196
- let read4 = 0;
29987
+ let read5 = 0;
28197
29988
  for (const match of text.matchAll(/url\([ \t\n\r\f]*(?:"([^"]*)"|'([^']*)'|([^)"' \t\n\r\f]*))[ \t\n\r\f]*\)/gi)) {
28198
- read4 += 1;
29989
+ read5 += 1;
28199
29990
  const value = match[1] ?? match[2] ?? match[3] ?? "";
28200
29991
  if (!isInlineReference(value) || value.includes("\\")) {
28201
29992
  throw new ArtifactBundleError("unsupported", "artifact css references a resource", void 0, value);
28202
29993
  }
28203
29994
  }
28204
- if (read4 !== opened) fail("unsupported", "artifact css has a url() that cannot be read");
29995
+ if (read5 !== opened) fail("unsupported", "artifact css has a url() that cannot be read");
28205
29996
  }
28206
29997
  async function transformCss(sourceText, basePath, context) {
28207
29998
  if (context.cssStack.length > MAX_ARTIFACT_CSS_IMPORT_DEPTH) fail("limit", "artifact stylesheet import depth exceeded");
@@ -28487,8 +30278,8 @@ function isWithinFolder(root, candidate) {
28487
30278
  }
28488
30279
  var CHANGED = "changed while it was read";
28489
30280
  function isRaceError(error) {
28490
- const code4 = error?.code;
28491
- return code4 === "ENOENT" || code4 === "ENOTDIR" || code4 === "ELOOP";
30281
+ const code5 = error?.code;
30282
+ return code5 === "ENOENT" || code5 === "ENOTDIR" || code5 === "ELOOP";
28492
30283
  }
28493
30284
  var PROC_FD = "/proc/self/fd";
28494
30285
  async function linuxDescriptorPath(fd) {
@@ -28645,11 +30436,11 @@ async function readHtmlFolder(directory, limit) {
28645
30436
  continue;
28646
30437
  }
28647
30438
  if (files.length >= MAX_ARTIFACT_FILES) throw limitError(`folder has more than ${MAX_ARTIFACT_FILES} files`);
28648
- const read4 = await readRegularFile(root, child, path, limit - total, limit);
28649
- if (read4 instanceof Uint8Array) {
28650
- total += read4.byteLength;
28651
- files.push({ path: path.normalize("NFC"), bytes: read4 });
28652
- } else problems.push(read4);
30439
+ const read5 = await readRegularFile(root, child, path, limit - total, limit);
30440
+ if (read5 instanceof Uint8Array) {
30441
+ total += read5.byteLength;
30442
+ files.push({ path: path.normalize("NFC"), bytes: read5 });
30443
+ } else problems.push(read5);
28653
30444
  }
28654
30445
  }
28655
30446
  };
@@ -28762,9 +30553,9 @@ function shareHistoryRecoverError(error) {
28762
30553
  if (error instanceof ShareHistoryReadError) {
28763
30554
  return new CLIError("SHARE_HISTORY_RECOVER_FAILED", "could not read the unreadable sender history to move it aside", 1, { hint: "The original history file was not deleted. Check read permission on the history file, then retry." });
28764
30555
  }
28765
- const code4 = error instanceof Error ? error.code : void 0;
28766
- if (code4 !== void 0 && SHARE_HISTORY_RECOVER_FS_ERRNO[code4] === true) {
28767
- return new CLIError("SHARE_HISTORY_RECOVER_FAILED", `could not move the unreadable sender history aside (${code4})`, 1, { hint: "The original history file was not deleted. Check write permission on the profile directory, then retry." });
30556
+ const code5 = error instanceof Error ? error.code : void 0;
30557
+ if (code5 !== void 0 && SHARE_HISTORY_RECOVER_FS_ERRNO[code5] === true) {
30558
+ return new CLIError("SHARE_HISTORY_RECOVER_FAILED", `could not move the unreadable sender history aside (${code5})`, 1, { hint: "The original history file was not deleted. Check write permission on the profile directory, then retry." });
28768
30559
  }
28769
30560
  return shareCliError(error);
28770
30561
  }
@@ -28833,6 +30624,10 @@ function shareCliError(error, operation = "publish") {
28833
30624
  if (failure.kind === "registry-unavailable") {
28834
30625
  return new CLIError("UNAVAILABLE", "the TinyCloud location registry could not be reached, so nothing was shared; try again shortly", 4);
28835
30626
  }
30627
+ if (failure.kind === "share-service-unavailable") {
30628
+ const outcome = operation === "publish" ? "nothing was shared" : "no invitation was sent";
30629
+ return new CLIError("SHARE_SERVICE_UNAVAILABLE", `the Share service at ${failure.origin} could not be reached, so ${outcome}; try again shortly`, 4);
30630
+ }
28836
30631
  if (failure.kind === "node-info-unavailable") {
28837
30632
  const outcome = operation === "publish" ? "nothing was shared and no invitation was sent" : "no invitation was sent";
28838
30633
  return new CLIError("UNAVAILABLE", `could not verify TinyCloud node 1.17.3 domain delivery support; ${outcome}. Check the node and retry`, 4);
@@ -28857,20 +30652,35 @@ function shareCliError(error, operation = "publish") {
28857
30652
  if (failure.kind === "upload-failed") {
28858
30653
  return new CLIError("UPLOAD_FAILED", "share source upload failed; nothing was shared", 4);
28859
30654
  }
30655
+ if (failure.kind === "decrypt-not-held") {
30656
+ return new CLIError(
30657
+ "PERMISSION_DENIED",
30658
+ "this sign-in can't create email-addressed shares: it has no permission to decrypt with the account's key. Nothing was shared.",
30659
+ 5,
30660
+ { 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." }
30661
+ );
30662
+ }
30663
+ }
30664
+ if (error instanceof ShortLinkError) {
30665
+ if (error.code === "not-found") return new CLIError("NOT_FOUND", "this short link has expired, was revoked, or never existed", 4);
30666
+ if (error.code === "rejected") return new CLIError("ORIGIN_MISMATCH", "this short link is not from the trusted Share origin", 5);
30667
+ if (error.code === "too-large") return new CLIError("MAX_BYTES_EXCEEDED", "the Share short-link service returned too many bytes", 7);
30668
+ if (error.code === "invalid-response") return new CLIError("CID_MISMATCH", "the Share short-link service returned content that does not match the link", 5);
30669
+ return new CLIError("UNAVAILABLE", "the Share short-link service is unavailable; try again shortly", 4);
28860
30670
  }
28861
30671
  if (error instanceof ShareNotifyError) {
28862
30672
  return new CLIError("INVALID_ARGUMENT", error.message, 2);
28863
30673
  }
28864
30674
  if (error instanceof SharePublishError) {
28865
30675
  const exit = error.code === "authority-required" ? 3 : error.code === "max-bytes-exceeded" ? 7 : 2;
28866
- const code4 = error.code === "authority-required" ? "AUTH_REQUIRED" : error.code === "max-bytes-exceeded" ? "MAX_BYTES_EXCEEDED" : "INVALID_ARGUMENT";
28867
- return new CLIError(code4, error.message, exit);
30676
+ const code5 = error.code === "authority-required" ? "AUTH_REQUIRED" : error.code === "max-bytes-exceeded" ? "MAX_BYTES_EXCEEDED" : "INVALID_ARGUMENT";
30677
+ return new CLIError(code5, error.message, exit);
28868
30678
  }
28869
30679
  if (error instanceof ShareReceiveError) {
28870
30680
  const verification = /* @__PURE__ */ new Set(["cid-mismatch", "decrypt-failed", "envelope-invalid", "origin-mismatch", "signature-invalid", "capability-invalid", "content-integrity-failed"]);
28871
30681
  const exit = error.code === "max-bytes-exceeded" ? 7 : verification.has(error.code) ? 5 : error.code === "expired" || error.code === "fetch-failed" ? 4 : error.code === "invalid-link" || error.code === "unsupported-target" ? 2 : 2;
28872
- const code4 = error.code === "fetch-failed" ? "NOT_FOUND" : error.code.replaceAll("-", "_").toUpperCase();
28873
- return new CLIError(code4, error.message, exit);
30682
+ const code5 = error.code === "fetch-failed" ? "NOT_FOUND" : error.code.replaceAll("-", "_").toUpperCase();
30683
+ return new CLIError(code5, error.message, exit);
28874
30684
  }
28875
30685
  const storageFull = storageFullError(error);
28876
30686
  if (storageFull) return storageFull;
@@ -28898,13 +30708,45 @@ function inputUrl(value, stdin) {
28898
30708
  if (value === void 0 || value.length === 0) throw new CLIError("INVALID_ARGUMENT", "a share URL or - is required", 2);
28899
30709
  return Promise.resolve(value);
28900
30710
  }
30711
+ function resolveLink(link4, expectedOrigin) {
30712
+ return shareServices.shortLinks?.resolve(link4, expectedOrigin) ?? resolveShortLink(link4, { expectedOrigin });
30713
+ }
30714
+ function assertTrustedShareOrigin(link4, expectedOrigin) {
30715
+ if (URL.canParse(link4) && new URL(link4).origin !== expectedOrigin) {
30716
+ throw new ShareReceiveError("origin-mismatch", "share link origin is not the trusted Share origin");
30717
+ }
30718
+ }
30719
+ var SHORT_LINK_WARNING = {
30720
+ "rate-limited": "the short-link service is rate limiting this client",
30721
+ capacity: "the short-link service is at capacity",
30722
+ rejected: "the short-link service refused this share",
30723
+ unavailable: "the short-link service could not be reached",
30724
+ "invalid-response": "the short-link service answered incorrectly",
30725
+ "not-found": "the short-link service lost the link",
30726
+ "too-large": "this share is too large for a short link",
30727
+ "token-store-failed": "the short link's delete token could not be saved"
30728
+ };
30729
+ async function linkToShow(result, longLink) {
30730
+ if (longLink || result.link.kind !== "policy" || shareServices.shortLinks === void 0) return { url: result.url };
30731
+ try {
30732
+ return { url: await shareServices.shortLinks.shorten(result) };
30733
+ } catch (error) {
30734
+ const code5 = error instanceof ShortLinkError ? error.code : "unavailable";
30735
+ process.stderr.write(`Warning: no short link (${SHORT_LINK_WARNING[code5]}); printing the long link instead. It works, but it is long and some mail clients may break it.
30736
+ `);
30737
+ return { url: result.url, shortLinkError: code5 };
30738
+ }
30739
+ }
28901
30740
  async function inspectShareInputOnce(value, stdin, expectedOrigin, dependencies = {}) {
28902
30741
  const link4 = stdin || value === "-" ? await (dependencies.read ?? readBoundedUrlStdin)() : await inputUrl(value, false);
28903
30742
  try {
28904
30743
  parseNativeShareUrl(link4);
28905
30744
  } catch {
28906
- return (dependencies.inspect ?? inspectShare)(link4, { expectedOrigin });
30745
+ const resolved = await resolveLink(link4, expectedOrigin);
30746
+ assertTrustedShareOrigin(resolved, expectedOrigin);
30747
+ return (dependencies.inspect ?? inspectShare)(resolved, { expectedOrigin });
28907
30748
  }
30749
+ assertTrustedShareOrigin(link4, expectedOrigin);
28908
30750
  throw new CLIError("UNSUPPORTED_LINK", "native bearer links are opaque; receive the link to verify access", 2);
28909
30751
  }
28910
30752
  function jsonOutput(options, command) {
@@ -28977,7 +30819,7 @@ function assertAggregateInputLimit(inputs, maxBytes) {
28977
30819
  }
28978
30820
  function registerShareCommand(program2) {
28979
30821
  const share = program2.command("share").description("Publish and consume TinyCloud Share links");
28980
- 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("--viewer-origin <origin>", "Canonical HTTPS viewer origin", SHARE_ORIGIN).action(async (files, options, command) => {
30822
+ 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("--long-link", "Print the long 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) => {
28981
30823
  try {
28982
30824
  const json = jsonOutput(options, command);
28983
30825
  if (options.ongoing === true) throw new CLIError("UNSUPPORTED_TARGET", ONGOING_UNAVAILABLE, 2);
@@ -29038,7 +30880,7 @@ function registerShareCommand(program2) {
29038
30880
  notify: options.notify === true,
29039
30881
  // The artifact request rides on the adapter call rather than through `publishTargetShare`, whose code is part of
29040
30882
  // the browser bundles (the web-sdk size ceiling counts every byte it carries).
29041
- targetAdapter: artifact === void 0 || shareServices.targetAdapter === void 0 ? shareServices.targetAdapter : { publish: (request) => shareServices.targetAdapter.publish({ ...request, artifact }) }
30883
+ targetAdapter: artifact === void 0 || shareServices.targetAdapter === void 0 ? shareServices.targetAdapter : { publish: (request2) => shareServices.targetAdapter.publish({ ...request2, artifact }) }
29042
30884
  });
29043
30885
  if ("state" in result) {
29044
30886
  if (json) {
@@ -29058,11 +30900,12 @@ function registerShareCommand(program2) {
29058
30900
  }
29059
30901
  if (result.metadata.expiryClamped === true) process.stderr.write(`Share expiry clamped to session expiry (${result.metadata.expiresAt}).
29060
30902
  `);
29061
- if (json) writeJson2({ ...redactPublishedShare(result), history: history2, expiryClamped: result.metadata.expiryClamped === true, ...artifact === void 0 || result.metadata.artifact === void 0 ? {} : { artifactId: result.metadata.artifact.id, version: result.metadata.artifact.version, mode: result.metadata.artifact.mode }, ...notification === void 0 ? {} : { notification } });
30903
+ const shown = await linkToShow(result, options.longLink === true);
30904
+ if (json) writeJson2({ ...redactPublishedShare(result), history: history2, expiryClamped: result.metadata.expiryClamped === true, ...artifact === void 0 || result.metadata.artifact === void 0 ? {} : { artifactId: result.metadata.artifact.id, version: result.metadata.artifact.version, mode: result.metadata.artifact.mode }, ...notification === void 0 ? {} : { notification }, ...shown.shortLinkError === void 0 ? {} : { shortLinkError: shown.shortLinkError } });
29062
30905
  else {
29063
30906
  if (result.metadata.artifact !== void 0) process.stderr.write(`Artifact ${result.metadata.artifact.id} v${result.metadata.artifact.version} (${result.metadata.artifact.mode})
29064
30907
  `);
29065
- publishHuman(result);
30908
+ publishHuman(shown.url);
29066
30909
  }
29067
30910
  } catch (error) {
29068
30911
  return handleError(shareCliError(error));
@@ -29126,6 +30969,7 @@ function registerShareCommand(program2) {
29126
30969
  } catch {
29127
30970
  }
29128
30971
  if (nativeLink) {
30972
+ assertTrustedShareOrigin(link4, options.viewerOrigin);
29129
30973
  if (shareServices.nativeReader === void 0) throw new CLIError("AUTH_REQUIRED", "native TinyCloud receive is not configured", 3);
29130
30974
  const native = await shareServices.nativeReader(link4);
29131
30975
  if (maxBytes !== void 0 && native.bytes.byteLength > maxBytes) throw new CLIError("MAX_BYTES_EXCEEDED", "shared content exceeds max-bytes", 7);
@@ -29138,7 +30982,9 @@ function registerShareCommand(program2) {
29138
30982
  else receiveHuman(output2);
29139
30983
  return;
29140
30984
  }
29141
- const result = await receiveShare(link4, {
30985
+ const resolved = await resolveLink(link4, options.viewerOrigin);
30986
+ assertTrustedShareOrigin(resolved, options.viewerOrigin);
30987
+ const result = await receiveShare(resolved, {
29142
30988
  expectedOrigin: options.viewerOrigin,
29143
30989
  ...maxBytes === void 0 ? {} : { maxContentBlobBytes: maxBytes }
29144
30990
  });
@@ -29167,7 +31013,7 @@ function registerShareCommand(program2) {
29167
31013
  if (shareServices.records === void 0) throw new CLIError("AUTH_REQUIRED", "sender history storage is not configured", 3);
29168
31014
  const result = await listShares(shareServices.records);
29169
31015
  if (json) writeJson2({ protocol: "tinycloud-share", version: 1, shares: result });
29170
- else process.stdout.write(result.map((item) => `${item.shareId} ${item.target} ${item.expiresAt}`).join("\n") + (result.length ? "\n" : ""));
31016
+ else process.stdout.write(result.map((item) => `${item.shareId} ${item.target} ${item.expiresAt} ${item.revoked ? "revoked" : Date.parse(item.expiresAt) < Date.now() ? "expired" : "active"}`).join("\n") + (result.length ? "\n" : ""));
29171
31017
  } catch (error) {
29172
31018
  return handleError(shareCliError(error));
29173
31019
  }
@@ -29177,7 +31023,9 @@ function registerShareCommand(program2) {
29177
31023
  const json = jsonOutput(options, command);
29178
31024
  if (options.revealLink && json) throw new CLIError("INVALID_ARGUMENT", "--reveal-link cannot be combined with --json", 2);
29179
31025
  if (shareServices.records === void 0) throw new CLIError("AUTH_REQUIRED", "sender history storage is not configured", 3);
29180
- const result = await showShare({ storage: shareServices.records, shareId: id, revealLink: options.revealLink === true, link: options.revealLink ? await shareServices.linkFor?.(id) : void 0 });
31026
+ const record2 = options.revealLink === true ? await shareServices.records.get(id) : void 0;
31027
+ const link4 = record2 === void 0 ? void 0 : await shareServices.shortLinks?.linkFor(record2);
31028
+ const result = await showShare({ storage: shareServices.records, shareId: id, revealLink: options.revealLink === true, ...link4 === void 0 ? {} : { link: link4 } });
29181
31029
  if (json) writeJson2({ protocol: "tinycloud-share", version: 1, share: result });
29182
31030
  else writeJson2(result);
29183
31031
  } catch (error) {
@@ -29221,7 +31069,9 @@ function registerShareCommand(program2) {
29221
31069
  if (result.state === "unsupported") {
29222
31070
  throw new CLIError("UNSUPPORTED_TARGET", result.reason, 2);
29223
31071
  }
29224
- if (json) writeJson2({ protocol: "tinycloud-share", version: 1, result });
31072
+ const shortLink = await shareServices.shortLinks?.discard(record2) ?? "none";
31073
+ if (shortLink === "failed") process.stderr.write("Warning: the share is revoked, but its short link could not be removed; it stops resolving when the share expires.\n");
31074
+ if (json) writeJson2({ protocol: "tinycloud-share", version: 1, result, ...shortLink === "none" ? {} : { shortLink } });
29225
31075
  else process.stdout.write(`${result.state}
29226
31076
  `);
29227
31077
  } catch (error) {
@@ -29309,7 +31159,8 @@ configureShareCommandServices({
29309
31159
  assertDomainDelivery: shareAuthority.assertDomainDelivery,
29310
31160
  revocation: shareAuthority.revocation,
29311
31161
  nativeReader: shareAuthority.nativeReader,
29312
- artifactStore: shareAuthority.artifactStore
31162
+ artifactStore: shareAuthority.artifactStore,
31163
+ shortLinks: shareAuthority.shortLinks
29313
31164
  });
29314
31165
  var argv = process.argv.slice(2);
29315
31166
  var globalLongOptionsWithValues = { "--profile": true, "--host": true };
@@ -29355,8 +31206,8 @@ ${theme.muted("Repo:")} ${theme.accent("https://github.com/tinycloudlabs/web-sdk
29355
31206
  });
29356
31207
  var commandToken = firstCommandToken(argv);
29357
31208
  if (argv[0] === "courier") {
29358
- const code4 = await (await loadCourierEntry()).runCourier(argv.slice(1));
29359
- if (code4 !== 0) process.exit(code4);
31209
+ const code5 = await (await loadCourierEntry()).runCourier(argv.slice(1));
31210
+ if (code5 !== 0) process.exit(code5);
29360
31211
  } else if (commandToken === "courier") {
29361
31212
  process.stderr.write(`${TC_OPTIONS_BEFORE_COURIER}
29362
31213
  `);