@tinycloud/share-sdk 1.3.0-beta.0 → 1.4.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +6 -0
  2. package/dist/{addressed-publish-Db-6rqkA.d.cts → addressed-publish-BP6nsgRq.d.cts} +58 -2
  3. package/dist/{addressed-publish-CAdGCqiX.d.ts → addressed-publish-CpkwV-Au.d.ts} +58 -2
  4. package/dist/artifact.cjs +2 -2
  5. package/dist/artifact.cjs.map +1 -1
  6. package/dist/artifact.js +2 -2
  7. package/dist/artifact.js.map +1 -1
  8. package/dist/{history-ZJFHV-IU.d.cts → history-Bg25JIsi.d.cts} +1 -1
  9. package/dist/{history-q0ALXTv7.d.ts → history-kwJxrZgq.d.ts} +1 -1
  10. package/dist/index.cjs +304 -154
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +6 -6
  13. package/dist/index.d.ts +6 -6
  14. package/dist/index.js +290 -154
  15. package/dist/index.js.map +1 -1
  16. package/dist/{owner-policy-CRFeEC98.d.cts → owner-policy-aPmXIR3e.d.cts} +1 -1
  17. package/dist/{owner-policy-CRFeEC98.d.ts → owner-policy-aPmXIR3e.d.ts} +1 -1
  18. package/dist/share-index.cjs +47 -87
  19. package/dist/share-index.cjs.map +1 -1
  20. package/dist/share-index.d.cts +28 -30
  21. package/dist/share-index.d.ts +28 -30
  22. package/dist/share-index.js +46 -86
  23. package/dist/share-index.js.map +1 -1
  24. package/dist/share-root.cjs +2 -2
  25. package/dist/share-root.cjs.map +1 -1
  26. package/dist/share-root.d.cts +2 -2
  27. package/dist/share-root.d.ts +2 -2
  28. package/dist/share-root.js +2 -2
  29. package/dist/share-root.js.map +1 -1
  30. package/dist/{web-recipient-entry-D9IJEyRA.d.cts → web-recipient-entry-CiUzdSQs.d.cts} +9 -1
  31. package/dist/{web-recipient-entry-CKA_vCi5.d.ts → web-recipient-entry-DVyTQBl0.d.ts} +9 -1
  32. package/dist/web-recipient.cjs +76 -105
  33. package/dist/web-recipient.cjs.map +1 -1
  34. package/dist/web-recipient.d.cts +1 -1
  35. package/dist/web-recipient.d.ts +1 -1
  36. package/dist/web-recipient.js +66 -105
  37. package/dist/web-recipient.js.map +1 -1
  38. package/package.json +2 -2
@@ -294,4 +294,4 @@ declare function validateOwnerSharePolicyRegistration(value: unknown, expected:
294
294
  /** Validate the exact UTF-8 response bytes emitted by the registration route. */
295
295
  declare function validateOwnerSharePolicyRegistrationBytes(bytesValue: Uint8Array, expected: RegisterOwnerSharePolicyParams): OwnerSharePolicyRegistrationReceipt;
296
296
 
297
- export { type CreateOwnerDelegationParams as C, type DelegatedShareKey as D, MAX_CONTENT_BYTES as M, type OwnerShareAction as O, type PublishedShareDeliveryMaterial as P, type RegisterOwnerSharePolicyParams as R, type SignedDelegation as S, type OwnerShareMatcher as a, type OwnerSharePolicyRegistrationReceipt as b, type PublishedShare as c, type SharePublishTarget as d, type SharePublishOptions as e, type OwnerDelegationReceipt as f, DEFAULT_SHARE_LIFETIME_MS as g, OWNER_SHARE_REGISTRATION_DOMAIN as h, type OwnerDelegationPermission as i, type OwnerShareDecryption as j, type OwnerSharePolicyRegistration as k, type OwnerSharePolicyV2 as l, type PublishedShareMetadata as m, SHARE_CONTENT_LIMIT as n, SHARE_PUBLISH_RESULT_VERSION as o, SharePublishError as p, type SharePublishErrorCode as q, canonicalOwnerSharePolicy as r, computeOwnerShareRegistrationCid as s, createDelegatedShareKey as t, createPolicyEnforcementDelegation as u, redactPublishedShare as v, restoreDelegatedShareKey as w, validateOwnerSharePolicyRegistration as x, validateOwnerSharePolicyRegistrationBytes as y };
297
+ export { type CreateOwnerDelegationParams as C, type DelegatedShareKey as D, MAX_CONTENT_BYTES as M, type OwnerShareAction as O, type PublishedShareDeliveryMaterial as P, type RegisterOwnerSharePolicyParams as R, type SignedDelegation as S, type OwnerShareMatcher as a, type OwnerSharePolicyRegistrationReceipt as b, type PublishedShare as c, type SharePublishTarget as d, type SharePublishOptions as e, SharePublishError as f, type OwnerDelegationReceipt as g, DEFAULT_SHARE_LIFETIME_MS as h, OWNER_SHARE_REGISTRATION_DOMAIN as i, type OwnerDelegationPermission as j, type OwnerShareDecryption as k, type OwnerSharePolicyRegistration as l, type OwnerSharePolicyV2 as m, type PublishedShareMetadata as n, SHARE_CONTENT_LIMIT as o, SHARE_PUBLISH_RESULT_VERSION as p, type SharePublishErrorCode as q, canonicalOwnerSharePolicy as r, computeOwnerShareRegistrationCid as s, createDelegatedShareKey as t, createPolicyEnforcementDelegation as u, redactPublishedShare as v, restoreDelegatedShareKey as w, validateOwnerSharePolicyRegistration as x, validateOwnerSharePolicyRegistrationBytes as y };
@@ -294,4 +294,4 @@ declare function validateOwnerSharePolicyRegistration(value: unknown, expected:
294
294
  /** Validate the exact UTF-8 response bytes emitted by the registration route. */
295
295
  declare function validateOwnerSharePolicyRegistrationBytes(bytesValue: Uint8Array, expected: RegisterOwnerSharePolicyParams): OwnerSharePolicyRegistrationReceipt;
296
296
 
297
- export { type CreateOwnerDelegationParams as C, type DelegatedShareKey as D, MAX_CONTENT_BYTES as M, type OwnerShareAction as O, type PublishedShareDeliveryMaterial as P, type RegisterOwnerSharePolicyParams as R, type SignedDelegation as S, type OwnerShareMatcher as a, type OwnerSharePolicyRegistrationReceipt as b, type PublishedShare as c, type SharePublishTarget as d, type SharePublishOptions as e, type OwnerDelegationReceipt as f, DEFAULT_SHARE_LIFETIME_MS as g, OWNER_SHARE_REGISTRATION_DOMAIN as h, type OwnerDelegationPermission as i, type OwnerShareDecryption as j, type OwnerSharePolicyRegistration as k, type OwnerSharePolicyV2 as l, type PublishedShareMetadata as m, SHARE_CONTENT_LIMIT as n, SHARE_PUBLISH_RESULT_VERSION as o, SharePublishError as p, type SharePublishErrorCode as q, canonicalOwnerSharePolicy as r, computeOwnerShareRegistrationCid as s, createDelegatedShareKey as t, createPolicyEnforcementDelegation as u, redactPublishedShare as v, restoreDelegatedShareKey as w, validateOwnerSharePolicyRegistration as x, validateOwnerSharePolicyRegistrationBytes as y };
297
+ export { type CreateOwnerDelegationParams as C, type DelegatedShareKey as D, MAX_CONTENT_BYTES as M, type OwnerShareAction as O, type PublishedShareDeliveryMaterial as P, type RegisterOwnerSharePolicyParams as R, type SignedDelegation as S, type OwnerShareMatcher as a, type OwnerSharePolicyRegistrationReceipt as b, type PublishedShare as c, type SharePublishTarget as d, type SharePublishOptions as e, SharePublishError as f, type OwnerDelegationReceipt as g, DEFAULT_SHARE_LIFETIME_MS as h, OWNER_SHARE_REGISTRATION_DOMAIN as i, type OwnerDelegationPermission as j, type OwnerShareDecryption as k, type OwnerSharePolicyRegistration as l, type OwnerSharePolicyV2 as m, type PublishedShareMetadata as n, SHARE_CONTENT_LIMIT as o, SHARE_PUBLISH_RESULT_VERSION as p, type SharePublishErrorCode as q, canonicalOwnerSharePolicy as r, computeOwnerShareRegistrationCid as s, createDelegatedShareKey as t, createPolicyEnforcementDelegation as u, redactPublishedShare as v, restoreDelegatedShareKey as w, validateOwnerSharePolicyRegistration as x, validateOwnerSharePolicyRegistrationBytes as y };
@@ -44,6 +44,7 @@ __export(share_index_exports, {
44
44
  agentRecordBinding: () => agentRecordBinding,
45
45
  agentRecordKey: () => agentRecordKey,
46
46
  agentRecordPrefix: () => agentRecordPrefix,
47
+ assertLinkBoundToMaterial: () => assertLinkBoundToMaterial,
47
48
  attenuationCovers: () => attenuationCovers,
48
49
  checkRegistrationReceipt: () => checkRegistrationReceipt,
49
50
  claimRank: () => claimRank,
@@ -66,7 +67,6 @@ __export(share_index_exports, {
66
67
  parseStoredAgentRecord: () => parseStoredAgentRecord,
67
68
  project: () => project,
68
69
  sealAgentRecord: () => sealAgentRecord,
69
- shareLinkForRecord: () => shareLinkForRecord,
70
70
  validateShareLink: () => validateShareLink,
71
71
  verifyAgentRecordChain: () => verifyAgentRecordChain,
72
72
  verifyEnvelopeV3At: () => verifyEnvelopeV3At,
@@ -4995,7 +4995,8 @@ function isCanonicalRawCid(cidString) {
4995
4995
  } catch {
4996
4996
  return false;
4997
4997
  }
4998
- return cid2.version === 1 && cid2.code === code && cid2.multihash.code === SHA256_CODE && cid2.toString() === cidString;
4998
+ return cid2.version === 1 && cid2.code === code && cid2.multihash.code === SHA256_CODE && // `toString` of a parsed CID gives back the string it was parsed from; a fresh CID is encoded again.
4999
+ CID.createV1(cid2.code, cid2.multihash).toString() === cidString;
4999
5000
  }
5000
5001
  var base64 = rfc4648({
5001
5002
  prefix: "m",
@@ -5611,7 +5612,6 @@ function verifyEnvelopeV3SignatureOnly(envelope) {
5611
5612
  return import_ed255193.ed25519.verify(fromBase64Url(signature.value), (0, import_sha256.sha256)(signingBytesV3(unsigned)), ed25519PublicKeyFromDidKey(signature.signerDid), ED25519_VERIFY_OPTS2);
5612
5613
  }
5613
5614
  var KEY_LENGTH2 = 32;
5614
- var MAX_INLINE_BYTES = 256 * 1024;
5615
5615
  function assertCanonicalCid(cidString) {
5616
5616
  const cid2 = CID.parse(cidString);
5617
5617
  if (cid2.version !== 1 || cid2.code !== code || cid2.multihash.code !== 18 || // sha2-256 (0x12) only, at the link layer too
@@ -5619,21 +5619,6 @@ function assertCanonicalCid(cidString) {
5619
5619
  throw new TypeError(`not a canonical CIDv1 raw sha2-256 base32 CID: ${cidString}`);
5620
5620
  }
5621
5621
  }
5622
- async function encodeSealedInlineShareUrl(parts) {
5623
- if (!isCanonicalHttpsOrigin(parts.origin)) throw new TypeError("origin must be a canonical https origin");
5624
- if (parts.ciphertext.byteLength === 0 || parts.ciphertext.byteLength > MAX_INLINE_BYTES) throw new RangeError("inline ciphertext is outside the allowed size");
5625
- if (parts.key32.byteLength !== KEY_LENGTH2) throw new TypeError("inline key must be 32 bytes");
5626
- const ciphertextCid = await computeCid(parts.ciphertext);
5627
- const payload = canonicalize({
5628
- v: 2,
5629
- c: toBase64Url(parts.ciphertext),
5630
- cid: ciphertextCid,
5631
- k: toBase64Url(parts.key32)
5632
- });
5633
- const payloadBytes = new TextEncoder().encode(payload);
5634
- if (payloadBytes.byteLength > MAX_INLINE_BYTES * 2) throw new RangeError("inline URL is too large");
5635
- return `${parts.origin}/s/inline#v=2&p=${toBase64Url(payloadBytes)}`;
5636
- }
5637
5622
  function parseShareUrl(url, options = {}) {
5638
5623
  const parsed = new URL(url);
5639
5624
  if (parsed.protocol !== "https:") {
@@ -5672,47 +5657,6 @@ function parseShareUrl(url, options = {}) {
5672
5657
  }
5673
5658
  return { ciphertextCid, key32 };
5674
5659
  }
5675
- async function parseSealedInlineShareUrl(url, options = {}) {
5676
- const parsed = new URL(url);
5677
- if (parsed.protocol !== "https:" || parsed.username !== "" || parsed.password !== "") throw new TypeError("sealed inline share URL must be canonical HTTPS without userinfo");
5678
- if (!isCanonicalHttpsOrigin(parsed.origin) || options.expectedOrigin !== void 0 && parsed.origin !== options.expectedOrigin) throw new TypeError("sealed inline share URL origin is not trusted");
5679
- if (parsed.pathname !== "/s/inline" || parsed.search !== "") throw new TypeError("not a Node sealed-inline share URL");
5680
- if (url !== `${parsed.origin}/s/inline${parsed.hash}`) throw new TypeError("sealed inline share URL is not lexically canonical");
5681
- const prefix = "#v=2&p=";
5682
- if (!parsed.hash.startsWith(prefix)) throw new TypeError("sealed inline URL is missing its canonical fragment");
5683
- const encoded = parsed.hash.slice(prefix.length);
5684
- if (encoded.length === 0 || parsed.hash !== `${prefix}${encoded}`) throw new TypeError("sealed inline URL fragment is not canonical");
5685
- let payloadBytes;
5686
- try {
5687
- payloadBytes = fromBase64Url(encoded);
5688
- } catch {
5689
- throw new TypeError("sealed inline payload is not canonical base64url");
5690
- }
5691
- if (payloadBytes.byteLength === 0 || payloadBytes.byteLength > MAX_INLINE_BYTES * 2) throw new TypeError("sealed inline payload is too large");
5692
- const payloadText = new TextDecoder("utf-8", { fatal: true }).decode(payloadBytes);
5693
- let value;
5694
- try {
5695
- value = JSON.parse(payloadText);
5696
- } catch {
5697
- throw new TypeError("sealed inline payload is not valid JSON");
5698
- }
5699
- if (typeof value !== "object" || value === null || Array.isArray(value) || canonicalize(value) !== payloadText) throw new TypeError("sealed inline payload is not canonical JSON");
5700
- const record2 = value;
5701
- 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");
5702
- let ciphertext;
5703
- let key32;
5704
- try {
5705
- ciphertext = fromBase64Url(record2.c);
5706
- key32 = fromBase64Url(record2.k);
5707
- } catch {
5708
- throw new TypeError("sealed inline payload has invalid base64url material");
5709
- }
5710
- if (ciphertext.byteLength === 0 || ciphertext.byteLength > MAX_INLINE_BYTES) throw new TypeError("sealed inline ciphertext is outside the allowed size");
5711
- if (key32.byteLength !== KEY_LENGTH2) throw new TypeError("sealed inline key must be 32 bytes");
5712
- assertCanonicalCid(record2.cid);
5713
- if (await computeCid(ciphertext) !== record2.cid) throw new TypeError("sealed inline ciphertext does not match its CID");
5714
- return { kind: "inline", ciphertextCid: record2.cid, ciphertext, key32 };
5715
- }
5716
5660
 
5717
5661
  // src/share-index/ids.ts
5718
5662
  var SHARE_RECORDS_VAULT_PREFIX = "sender-history/v2/records/";
@@ -5765,6 +5709,9 @@ function classifyRecordKey(key) {
5765
5709
  return { kind: "rejected", ...owner };
5766
5710
  }
5767
5711
 
5712
+ // src/share-index/link.ts
5713
+ var import_links = require("@tinycloud/share-envelope/links");
5714
+
5768
5715
  // src/native.ts
5769
5716
  var NATIVE_SHARE_FRAGMENT_PARAMETER = "tc1";
5770
5717
  function parseNativeShareUrl(value) {
@@ -5778,14 +5725,17 @@ function parseNativeShareUrl(value) {
5778
5725
 
5779
5726
  // src/share-index/link.ts
5780
5727
  var MAX_LINK_LENGTH = 12 * 1024;
5728
+ var MAX_FULL_LINK_LENGTH = Math.ceil(import_links.MAX_LINK_REQUEST_BYTES * 4 / 3) + 512;
5729
+ var V4_SHARE_PATH = /^\/s\/([A-Za-z2-7]{26}|full)$/;
5781
5730
  function validateShareLink(link, shareOrigins) {
5782
- if (typeof link !== "string" || link.length === 0 || link.length > MAX_LINK_LENGTH || /[\s\u0000-\u001f\u007f]/.test(link)) return { ok: false };
5731
+ if (typeof link !== "string" || link.length === 0 || link.length > MAX_FULL_LINK_LENGTH || /[\s\u0000-\u001f\u007f]/.test(link)) return { ok: false };
5783
5732
  let url;
5784
5733
  try {
5785
5734
  url = new URL(link);
5786
5735
  } catch {
5787
5736
  return { ok: false };
5788
5737
  }
5738
+ if (link.length > MAX_LINK_LENGTH && url.pathname !== "/s/full") return { ok: false };
5789
5739
  if (url.protocol !== "https:" || url.username !== "" || url.password !== "" || url.search !== "") return { ok: false };
5790
5740
  if (!isCanonicalHttpsOrigin(url.origin) || !shareOrigins.includes(url.origin)) return { ok: false };
5791
5741
  try {
@@ -5793,8 +5743,9 @@ function validateShareLink(link, shareOrigins) {
5793
5743
  parseNativeShareUrl(link);
5794
5744
  return link === `${url.origin}/viewer${url.hash}` ? { ok: true, shape: "native" } : { ok: false };
5795
5745
  }
5796
- if (url.pathname === "/s/inline") {
5797
- return link === `${url.origin}/s/inline${url.hash}` && /^#v=2&p=[A-Za-z0-9_-]+$/.test(url.hash) ? { ok: true, shape: "inline" } : { ok: false };
5746
+ if (V4_SHARE_PATH.test(url.pathname)) {
5747
+ const parsed = (0, import_links.parseLink)(link, { trustedOrigins: shareOrigins });
5748
+ return parsed.form === "full" || parsed.pathType === "share" ? { ok: true, shape: "link" } : { ok: false };
5798
5749
  }
5799
5750
  parseShareUrl(link, { expectedOrigin: url.origin });
5800
5751
  return { ok: true, shape: "envelope" };
@@ -6155,6 +6106,7 @@ async function runCas(key, policy, attempt) {
6155
6106
  }
6156
6107
 
6157
6108
  // src/share-index/delivery.ts
6109
+ var import_links2 = require("@tinycloud/share-envelope/links");
6158
6110
  var STORED_DELIVERY_MATERIAL_KEYS = ["shareCid", "sealedEnvelope", "envelopeKey"];
6159
6111
  var DeliveryMaterialError = class extends Error {
6160
6112
  constructor(message) {
@@ -6192,13 +6144,17 @@ async function openDeliveryEnvelope(material) {
6192
6144
  if (value === null || typeof value !== "object" || Array.isArray(value) || canonicalize(value) !== text) throw new DeliveryMaterialError("sealed envelope is not canonical JSON");
6193
6145
  return value;
6194
6146
  }
6195
- async function shareLinkForRecord(record2, shareOrigin) {
6196
- if (record2.link !== void 0) return record2.link;
6197
- const material = record2.deliveryMaterial;
6198
- if (material === void 0) return void 0;
6147
+ function assertLinkBoundToMaterial(link, material) {
6199
6148
  const { sealed, key } = sealedParts(material);
6200
- if (await computeCid(sealed) !== material.shareCid) throw new DeliveryMaterialError("sealed envelope does not match shareCid");
6201
- return encodeSealedInlineShareUrl({ origin: shareOrigin, ciphertext: sealed, key32: key });
6149
+ let parsed;
6150
+ try {
6151
+ parsed = (0, import_links2.parseLink)(link, { trustedOrigins: [new URL(link).origin] });
6152
+ } catch {
6153
+ throw new DeliveryMaterialError("link is not a v=4 share link");
6154
+ }
6155
+ const sameBody = parsed.form === "short" ? parsed.c === material.shareCid : typeof parsed.record === "object" && parsed.record !== null && "body" in parsed.record && parsed.record.body === toBase64Url(sealed);
6156
+ if (!sameBody || !equalBytes(parsed.key, key)) throw new DeliveryMaterialError("link is not the link of this delivery material");
6157
+ return parsed.form;
6202
6158
  }
6203
6159
  async function compactShareRecord(record2) {
6204
6160
  const material = record2.deliveryMaterial;
@@ -6208,29 +6164,17 @@ async function compactShareRecord(record2) {
6208
6164
  const opened = await openDeliveryEnvelope(stored);
6209
6165
  if (material.envelope !== void 0 && canonicalize(opened) !== canonicalize(material.envelope)) throw new DeliveryMaterialError("envelope is not the sealed envelope");
6210
6166
  const { link, deliveryMaterial: _material, ...rest } = record2;
6211
- if (link !== void 0) {
6212
- const { sealed, key } = sealedParts(stored);
6213
- let parsed;
6214
- try {
6215
- parsed = await parseSealedInlineShareUrl(link);
6216
- } catch {
6217
- parsed = void 0;
6218
- }
6219
- if (parsed === void 0 || parsed.ciphertextCid !== stored.shareCid || !equalBytes(parsed.ciphertext, sealed) || !equalBytes(parsed.key32, key)) {
6220
- throw new DeliveryMaterialError("link is not the sealed-inline link of this delivery material");
6221
- }
6222
- }
6223
- return { ...rest, deliveryMaterial: stored };
6167
+ const keptLink = link !== void 0 && assertLinkBoundToMaterial(link, stored) === "short" ? link : void 0;
6168
+ return { ...rest, ...keptLink === void 0 ? {} : { link: keptLink }, deliveryMaterial: stored };
6224
6169
  }
6225
6170
  function equalBytes(left, right) {
6226
6171
  return left.length === right.length && left.every((byte, index) => byte === right[index]);
6227
6172
  }
6228
- async function expandShareRecord(record2, shareOrigin) {
6173
+ async function expandShareRecord(record2) {
6229
6174
  const material = record2.deliveryMaterial;
6230
6175
  if (material === void 0) return record2;
6231
6176
  const envelope = await openDeliveryEnvelope(material);
6232
- const link = shareOrigin === void 0 ? record2.link : await shareLinkForRecord(record2, shareOrigin);
6233
- return { ...record2, ...link === void 0 ? {} : { link }, deliveryMaterial: { ...material, envelope } };
6177
+ return { ...record2, deliveryMaterial: { ...material, envelope } };
6234
6178
  }
6235
6179
 
6236
6180
  // src/share-index/record-store.ts
@@ -6337,7 +6281,7 @@ var AgentShareRecordStore = class {
6337
6281
  }
6338
6282
  if (!isRecordShape(value) || value.shareId !== shareId) throw new AgentRecordError("shape");
6339
6283
  try {
6340
- return await expandShareRecord(value, this.options.shareOrigin);
6284
+ return await expandShareRecord(value);
6341
6285
  } catch {
6342
6286
  throw new AgentRecordError("shape");
6343
6287
  }
@@ -6528,6 +6472,15 @@ var ShareRecordSchemaError = class extends Error {
6528
6472
  this.name = "ShareRecordSchemaError";
6529
6473
  }
6530
6474
  };
6475
+ function carriesSealedRecord(link) {
6476
+ try {
6477
+ const url = new URL(link);
6478
+ const fragment = new URLSearchParams(url.hash.slice(1));
6479
+ return url.pathname === "/s/full" || fragment.has("r") || fragment.has("p");
6480
+ } catch {
6481
+ return false;
6482
+ }
6483
+ }
6531
6484
  function checkAgentRecordSchema(value, context) {
6532
6485
  const fail2 = () => {
6533
6486
  throw new ShareRecordSchemaError("schema");
@@ -6564,7 +6517,7 @@ function checkAgentRecordSchema(value, context) {
6564
6517
  if (record2.deliveryMaterial !== void 0) {
6565
6518
  const material = record2.deliveryMaterial;
6566
6519
  if (!isObject(material) || Object.keys(material).length !== STORED_DELIVERY_MATERIAL_KEYS.length || !STORED_DELIVERY_MATERIAL_KEYS.every((key) => typeof material[key] === "string")) return fail2();
6567
- if (record2.link !== void 0) return fail2();
6520
+ if (typeof record2.link === "string" && carriesSealedRecord(record2.link)) return fail2();
6568
6521
  }
6569
6522
  if (record2.deliveredRecipients !== void 0 && (!Array.isArray(record2.deliveredRecipients) || !record2.deliveredRecipients.every((item) => typeof item === "string"))) return fail2();
6570
6523
  if (record2.proofs !== void 0) {
@@ -8302,6 +8255,13 @@ var SenderShareIndex = class {
8302
8255
  return { kind: "reject", reason: error instanceof ShareRecordSchemaError && error.reason === "provenance" ? "provenance" : "schema" };
8303
8256
  }
8304
8257
  if (record2.link !== void 0 && !validateShareLink(record2.link, this.options.shareOrigins).ok) return { kind: "reject", reason: "link" };
8258
+ if (record2.link !== void 0 && record2.deliveryMaterial !== void 0) {
8259
+ try {
8260
+ assertLinkBoundToMaterial(record2.link, record2.deliveryMaterial);
8261
+ } catch {
8262
+ return { kind: "reject", reason: "link" };
8263
+ }
8264
+ }
8305
8265
  const verdict = await verifyAgentRecordChain(record2, {
8306
8266
  accountOwnerDid: this.options.ownerDid,
8307
8267
  agentDid: input.agentDid,
@@ -8682,6 +8642,7 @@ var SenderShareIndex = class {
8682
8642
  agentRecordBinding,
8683
8643
  agentRecordKey,
8684
8644
  agentRecordPrefix,
8645
+ assertLinkBoundToMaterial,
8685
8646
  attenuationCovers,
8686
8647
  checkRegistrationReceipt,
8687
8648
  claimRank,
@@ -8704,7 +8665,6 @@ var SenderShareIndex = class {
8704
8665
  parseStoredAgentRecord,
8705
8666
  project,
8706
8667
  sealAgentRecord,
8707
- shareLinkForRecord,
8708
8668
  validateShareLink,
8709
8669
  verifyAgentRecordChain,
8710
8670
  verifyEnvelopeV3At,