@tinycloud/share-sdk 1.3.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
@@ -1,6 +1,6 @@
1
- import { a as SenderShareRecordStorage, S as SenderShareRecord } from './history-ZJFHV-IU.cjs';
2
- export { f as SenderShareRecordProofs } from './history-ZJFHV-IU.cjs';
3
- import { P as PublishedShareDeliveryMaterial, S as SignedDelegation, k as OwnerSharePolicyRegistration } from './owner-policy-CRFeEC98.cjs';
1
+ import { a as SenderShareRecordStorage, S as SenderShareRecord } from './history-Bg25JIsi.cjs';
2
+ export { f as SenderShareRecordProofs } from './history-Bg25JIsi.cjs';
3
+ import { P as PublishedShareDeliveryMaterial, S as SignedDelegation, l as OwnerSharePolicyRegistration } from './owner-policy-aPmXIR3e.cjs';
4
4
  import { ShareEnvelopeV3 } from '@tinycloud/share-envelope';
5
5
 
6
6
  /**
@@ -61,13 +61,14 @@ declare function classifyRecordKey(key: string): ClassifiedRecordKey;
61
61
  * accepted only when it is https on a configured share origin and has one of
62
62
  * the share link shapes:
63
63
  * - `/s/<cid>#k=<key>`: registry envelope link;
64
- * - `/s/inline#v=2&p=<payload>`: Node Policy/v3 sealed-inline link (what
65
- * `publishAddressedShare` emits);
64
+ * - `/s/<id>#v=4&k=<key>&c=<cid>` or `/s/full#v=4&k=<key>&r=<record>`: the
65
+ * short or full link of a Policy/v3 share (what `publishAddressedShare`
66
+ * emits and the links service stores);
66
67
  * - `/viewer#tc1=<token>`: native bearer link (`createNativeShare`).
67
68
  *
68
69
  * The result names the shape only; the link itself is never copied into it.
69
70
  */
70
- type ShareLinkShape = "envelope" | "inline" | "native";
71
+ type ShareLinkShape = "envelope" | "link" | "native";
71
72
  type ShareLinkCheck = {
72
73
  readonly ok: true;
73
74
  readonly shape: ShareLinkShape;
@@ -436,12 +437,6 @@ interface AgentShareRecordStoreOptions {
436
437
  /** KEK_a from the same key; absent for a remote-signer-only profile (records are then owner-readable only). */
437
438
  readonly agentKey?: AgentKeyMaterial;
438
439
  readonly cas?: CasPolicy;
439
- /**
440
- * The share origin on which records read back get their Policy/v3
441
- * `/s/inline` link rebuilt (the stored form keeps no link; see
442
- * `delivery.ts`). Absent: records read back carry no v3 link.
443
- */
444
- readonly shareOrigin?: string;
445
440
  }
446
441
  declare class AgentShareRecordStore implements SenderShareRecordStorage {
447
442
  private readonly options;
@@ -470,14 +465,13 @@ declare class AgentShareRecordStore implements SenderShareRecordStorage {
470
465
  *
471
466
  * A Policy/v3 record's `deliveryMaterial.envelope` is exactly what
472
467
  * `sealedEnvelope` decrypts to under `envelopeKey` (`publishAddressedShare`
473
- * seals `canonicalize(envelope)`), and its `/s/inline` link is
474
- * `sealedEnvelope`, its CID and `envelopeKey` encoded again. Both are
475
- * dropped before an agent record is sealed and rebuilt when needed:
476
- * {@link openDeliveryEnvelope} for the verifier and a delivery retry,
477
- * {@link shareLinkForRecord} at Open/Copy. `sealedEnvelope` stays (the node
478
- * reopens that exact value and its nonce is random) and so does the session
479
- * CACAO (it proves the chain). A bearer record keeps its `link`, which is
480
- * not derivable.
468
+ * seals `canonicalize(envelope)`). It is omitted before an agent record is
469
+ * sealed and rebuilt when needed by {@link openDeliveryEnvelope}, for the
470
+ * verifier and a delivery retry. `sealedEnvelope` stays (the node reopens that
471
+ * exact value and its nonce is random) and so does the session CACAO (it
472
+ * proves the chain). A short `v=4` link the sender printed is kept (it is not
473
+ * derivable: it carries an id only the links service knows) and must be the
474
+ * link of this material; a full link is not kept (see {@link compactShareRecord}).
481
475
  *
482
476
  * Security-sensitive: the sealed bytes are checked against `shareCid` before
483
477
  * they are opened, and the plaintext must be the canonical JSON of the
@@ -497,24 +491,28 @@ declare class DeliveryMaterialError extends Error {
497
491
  /** The signed envelope inside `sealedEnvelope`; throws {@link DeliveryMaterialError} unless it is exactly that. */
498
492
  declare function openDeliveryEnvelope(material: StoredDeliveryMaterial): Promise<Record<string, unknown>>;
499
493
  /**
500
- * The link to show at Open/Copy: a bearer record's stored `link`, or a
501
- * Policy/v3 record's `/s/inline` link rebuilt on `shareOrigin` (the
502
- * viewer's configured share origin) from `sealedEnvelope` and `envelopeKey`.
494
+ * A `v=4` link names its content key and body: a short link by the key `k` and
495
+ * the body CID `c`, a full link by `k` and the record whose body it carries.
496
+ * Either must be exactly this delivery material's key and sealed envelope.
497
+ * Returns the link's form.
503
498
  */
504
- declare function shareLinkForRecord(record: Pick<StoredShareRecord, "link" | "deliveryMaterial">, shareOrigin: string): Promise<string | undefined>;
499
+ declare function assertLinkBoundToMaterial(link: string, material: StoredDeliveryMaterial): "short" | "full";
505
500
  /**
506
501
  * The stored form of `record`. For a Policy/v3 record (one with
507
- * `deliveryMaterial`), drops `deliveryMaterial.envelope` and `link` after
508
- * checking they are exactly what the sealed material rebuilds, so nothing is
509
- * lost. Throws {@link DeliveryMaterialError} otherwise.
502
+ * `deliveryMaterial`), omits `deliveryMaterial.envelope` after checking it is
503
+ * exactly what the sealed material opens to, and checks that a `link` is the
504
+ * link of that material. A short link is kept. A full link is not: it embeds
505
+ * the sealed envelope a second time, which the record size cap does not leave
506
+ * room for, so the sender's own history holds it. Throws
507
+ * {@link DeliveryMaterialError} otherwise.
510
508
  */
511
509
  declare function compactShareRecord(record: SenderShareRecord | StoredShareRecord): Promise<StoredShareRecord>;
512
510
  /**
513
511
  * The full record again (for a delivery retry or a caller that wants the
514
512
  * {@link SenderShareRecord} shape): the envelope reopened from the sealed
515
- * material and, when `shareOrigin` is given, the `/s/inline` link rebuilt.
513
+ * material. The stored `link` is returned as it was stored.
516
514
  */
517
- declare function expandShareRecord(record: StoredShareRecord, shareOrigin?: string): Promise<SenderShareRecord>;
515
+ declare function expandShareRecord(record: StoredShareRecord): Promise<SenderShareRecord>;
518
516
 
519
517
  /**
520
518
  * Index document schema v1, rows, `project()`, and the versioned agent-record
@@ -1060,4 +1058,4 @@ declare function checkRegistrationReceipt(value: unknown, expected: {
1060
1058
 
1061
1059
  declare function verifyEnvelopeV3At(envelope: ShareEnvelopeV3, expectedSignerDid: string, now: number): Promise<boolean>;
1062
1060
 
1063
- export { AGENT_ID_LENGTH, AGENT_RECORD_VERSION, type AgentKeyMaterial, AgentRecordError, type AgentRecordFailure, type AgentRecordHeader, type AgentRejectReason, AgentShareRecordStore, type AgentShareRecordStoreOptions, type Attenuation, type CasPolicy, type ChainContext, type ChainVerdict, type CheckedRegistration, type ClaimDecision, type ClassifiedRecordKey, DEFAULT_CAS_POLICY, DEFAULT_SHARE_INDEX_LIMITS, DeliveryMaterialError, INDEX_MAIN_KEY, INDEX_SCHEMA_VERSION, INVALID_ETAG_MESSAGE, MAX_AGENT_RECORD_BYTES, MemoryShareIndexOutbox, type OwnerNetworkUnwrap, type OwnerNetworkWrap, OwnerUnwrapUnavailableError, type ParsedSiweCacao, type RegistrationKey, SHARE_RECORDS_VAULT_PREFIX, STORED_DELIVERY_MATERIAL_KEYS, SUPPORTED_AGENT_RECORD_V, SenderShareIndex, type SenderShareIndexOptions, SenderShareRecord, type ShareDocumentRead, type ShareIndexAgentEntry, type ShareIndexArchiveDocument, type ShareIndexBackend, ShareIndexCasError, type ShareIndexCasErrorCode, type ShareIndexDocument, type ShareIndexFlushResult, type ShareIndexLimits, type ShareIndexLoad, type ShareIndexOp, type ShareIndexOutbox, type ShareIndexReconcileReport, type ShareIndexRow, type ShareIndexWriteOutcome, type ShareIndexWriteStatus, type ShareLinkCheck, type ShareLinkShape, type ShareListResult, type ShareProofState, type ShareRawRead, ShareRecordSchemaError, type ShareRegistrationKey, type ShareStatusPort, type ShareWriteCondition, type ShareWriteResult, type SignedUcanDelegation, type SiweCacaoParser, type StoredAgentRecord, type StoredDeliveryMaterial, type StoredShareRecord, type TinyCloudShareIndexBackendOptions, type TinyCloudShareIndexClient, type VaultNetworkRead, WebShareRecordStore, agentIdFromDid, agentRecordBinding, agentRecordKey, agentRecordPrefix, attenuationCovers, checkRegistrationReceipt, claimRank, classifyRecordKey, compactShareRecord, createTinyCloudShareIndexBackend, decideClaim, deriveAgentKeyMaterial, displayName, expandShareRecord, headerBytes, isAgentId, isShareId, isSpaceOwnedBy, openAgentRecordAsAgent, openAgentRecordAsOwner, openDeliveryEnvelope, parseIndexDocument, parseSignedUcan, parseStoredAgentRecord, project, sealAgentRecord, shareLinkForRecord, validateShareLink, verifyAgentRecordChain, verifyEnvelopeV3At, verifyOwnerSessionDelegation, verifyPolicyEnforcementDelegation };
1061
+ export { AGENT_ID_LENGTH, AGENT_RECORD_VERSION, type AgentKeyMaterial, AgentRecordError, type AgentRecordFailure, type AgentRecordHeader, type AgentRejectReason, AgentShareRecordStore, type AgentShareRecordStoreOptions, type Attenuation, type CasPolicy, type ChainContext, type ChainVerdict, type CheckedRegistration, type ClaimDecision, type ClassifiedRecordKey, DEFAULT_CAS_POLICY, DEFAULT_SHARE_INDEX_LIMITS, DeliveryMaterialError, INDEX_MAIN_KEY, INDEX_SCHEMA_VERSION, INVALID_ETAG_MESSAGE, MAX_AGENT_RECORD_BYTES, MemoryShareIndexOutbox, type OwnerNetworkUnwrap, type OwnerNetworkWrap, OwnerUnwrapUnavailableError, type ParsedSiweCacao, type RegistrationKey, SHARE_RECORDS_VAULT_PREFIX, STORED_DELIVERY_MATERIAL_KEYS, SUPPORTED_AGENT_RECORD_V, SenderShareIndex, type SenderShareIndexOptions, SenderShareRecord, type ShareDocumentRead, type ShareIndexAgentEntry, type ShareIndexArchiveDocument, type ShareIndexBackend, ShareIndexCasError, type ShareIndexCasErrorCode, type ShareIndexDocument, type ShareIndexFlushResult, type ShareIndexLimits, type ShareIndexLoad, type ShareIndexOp, type ShareIndexOutbox, type ShareIndexReconcileReport, type ShareIndexRow, type ShareIndexWriteOutcome, type ShareIndexWriteStatus, type ShareLinkCheck, type ShareLinkShape, type ShareListResult, type ShareProofState, type ShareRawRead, ShareRecordSchemaError, type ShareRegistrationKey, type ShareStatusPort, type ShareWriteCondition, type ShareWriteResult, type SignedUcanDelegation, type SiweCacaoParser, type StoredAgentRecord, type StoredDeliveryMaterial, type StoredShareRecord, type TinyCloudShareIndexBackendOptions, type TinyCloudShareIndexClient, type VaultNetworkRead, WebShareRecordStore, agentIdFromDid, agentRecordBinding, agentRecordKey, agentRecordPrefix, assertLinkBoundToMaterial, attenuationCovers, checkRegistrationReceipt, claimRank, classifyRecordKey, compactShareRecord, createTinyCloudShareIndexBackend, decideClaim, deriveAgentKeyMaterial, displayName, expandShareRecord, headerBytes, isAgentId, isShareId, isSpaceOwnedBy, openAgentRecordAsAgent, openAgentRecordAsOwner, openDeliveryEnvelope, parseIndexDocument, parseSignedUcan, parseStoredAgentRecord, project, sealAgentRecord, validateShareLink, verifyAgentRecordChain, verifyEnvelopeV3At, verifyOwnerSessionDelegation, verifyPolicyEnforcementDelegation };
@@ -1,6 +1,6 @@
1
- import { a as SenderShareRecordStorage, S as SenderShareRecord } from './history-q0ALXTv7.js';
2
- export { f as SenderShareRecordProofs } from './history-q0ALXTv7.js';
3
- import { P as PublishedShareDeliveryMaterial, S as SignedDelegation, k as OwnerSharePolicyRegistration } from './owner-policy-CRFeEC98.js';
1
+ import { a as SenderShareRecordStorage, S as SenderShareRecord } from './history-kwJxrZgq.js';
2
+ export { f as SenderShareRecordProofs } from './history-kwJxrZgq.js';
3
+ import { P as PublishedShareDeliveryMaterial, S as SignedDelegation, l as OwnerSharePolicyRegistration } from './owner-policy-aPmXIR3e.js';
4
4
  import { ShareEnvelopeV3 } from '@tinycloud/share-envelope';
5
5
 
6
6
  /**
@@ -61,13 +61,14 @@ declare function classifyRecordKey(key: string): ClassifiedRecordKey;
61
61
  * accepted only when it is https on a configured share origin and has one of
62
62
  * the share link shapes:
63
63
  * - `/s/<cid>#k=<key>`: registry envelope link;
64
- * - `/s/inline#v=2&p=<payload>`: Node Policy/v3 sealed-inline link (what
65
- * `publishAddressedShare` emits);
64
+ * - `/s/<id>#v=4&k=<key>&c=<cid>` or `/s/full#v=4&k=<key>&r=<record>`: the
65
+ * short or full link of a Policy/v3 share (what `publishAddressedShare`
66
+ * emits and the links service stores);
66
67
  * - `/viewer#tc1=<token>`: native bearer link (`createNativeShare`).
67
68
  *
68
69
  * The result names the shape only; the link itself is never copied into it.
69
70
  */
70
- type ShareLinkShape = "envelope" | "inline" | "native";
71
+ type ShareLinkShape = "envelope" | "link" | "native";
71
72
  type ShareLinkCheck = {
72
73
  readonly ok: true;
73
74
  readonly shape: ShareLinkShape;
@@ -436,12 +437,6 @@ interface AgentShareRecordStoreOptions {
436
437
  /** KEK_a from the same key; absent for a remote-signer-only profile (records are then owner-readable only). */
437
438
  readonly agentKey?: AgentKeyMaterial;
438
439
  readonly cas?: CasPolicy;
439
- /**
440
- * The share origin on which records read back get their Policy/v3
441
- * `/s/inline` link rebuilt (the stored form keeps no link; see
442
- * `delivery.ts`). Absent: records read back carry no v3 link.
443
- */
444
- readonly shareOrigin?: string;
445
440
  }
446
441
  declare class AgentShareRecordStore implements SenderShareRecordStorage {
447
442
  private readonly options;
@@ -470,14 +465,13 @@ declare class AgentShareRecordStore implements SenderShareRecordStorage {
470
465
  *
471
466
  * A Policy/v3 record's `deliveryMaterial.envelope` is exactly what
472
467
  * `sealedEnvelope` decrypts to under `envelopeKey` (`publishAddressedShare`
473
- * seals `canonicalize(envelope)`), and its `/s/inline` link is
474
- * `sealedEnvelope`, its CID and `envelopeKey` encoded again. Both are
475
- * dropped before an agent record is sealed and rebuilt when needed:
476
- * {@link openDeliveryEnvelope} for the verifier and a delivery retry,
477
- * {@link shareLinkForRecord} at Open/Copy. `sealedEnvelope` stays (the node
478
- * reopens that exact value and its nonce is random) and so does the session
479
- * CACAO (it proves the chain). A bearer record keeps its `link`, which is
480
- * not derivable.
468
+ * seals `canonicalize(envelope)`). It is omitted before an agent record is
469
+ * sealed and rebuilt when needed by {@link openDeliveryEnvelope}, for the
470
+ * verifier and a delivery retry. `sealedEnvelope` stays (the node reopens that
471
+ * exact value and its nonce is random) and so does the session CACAO (it
472
+ * proves the chain). A short `v=4` link the sender printed is kept (it is not
473
+ * derivable: it carries an id only the links service knows) and must be the
474
+ * link of this material; a full link is not kept (see {@link compactShareRecord}).
481
475
  *
482
476
  * Security-sensitive: the sealed bytes are checked against `shareCid` before
483
477
  * they are opened, and the plaintext must be the canonical JSON of the
@@ -497,24 +491,28 @@ declare class DeliveryMaterialError extends Error {
497
491
  /** The signed envelope inside `sealedEnvelope`; throws {@link DeliveryMaterialError} unless it is exactly that. */
498
492
  declare function openDeliveryEnvelope(material: StoredDeliveryMaterial): Promise<Record<string, unknown>>;
499
493
  /**
500
- * The link to show at Open/Copy: a bearer record's stored `link`, or a
501
- * Policy/v3 record's `/s/inline` link rebuilt on `shareOrigin` (the
502
- * viewer's configured share origin) from `sealedEnvelope` and `envelopeKey`.
494
+ * A `v=4` link names its content key and body: a short link by the key `k` and
495
+ * the body CID `c`, a full link by `k` and the record whose body it carries.
496
+ * Either must be exactly this delivery material's key and sealed envelope.
497
+ * Returns the link's form.
503
498
  */
504
- declare function shareLinkForRecord(record: Pick<StoredShareRecord, "link" | "deliveryMaterial">, shareOrigin: string): Promise<string | undefined>;
499
+ declare function assertLinkBoundToMaterial(link: string, material: StoredDeliveryMaterial): "short" | "full";
505
500
  /**
506
501
  * The stored form of `record`. For a Policy/v3 record (one with
507
- * `deliveryMaterial`), drops `deliveryMaterial.envelope` and `link` after
508
- * checking they are exactly what the sealed material rebuilds, so nothing is
509
- * lost. Throws {@link DeliveryMaterialError} otherwise.
502
+ * `deliveryMaterial`), omits `deliveryMaterial.envelope` after checking it is
503
+ * exactly what the sealed material opens to, and checks that a `link` is the
504
+ * link of that material. A short link is kept. A full link is not: it embeds
505
+ * the sealed envelope a second time, which the record size cap does not leave
506
+ * room for, so the sender's own history holds it. Throws
507
+ * {@link DeliveryMaterialError} otherwise.
510
508
  */
511
509
  declare function compactShareRecord(record: SenderShareRecord | StoredShareRecord): Promise<StoredShareRecord>;
512
510
  /**
513
511
  * The full record again (for a delivery retry or a caller that wants the
514
512
  * {@link SenderShareRecord} shape): the envelope reopened from the sealed
515
- * material and, when `shareOrigin` is given, the `/s/inline` link rebuilt.
513
+ * material. The stored `link` is returned as it was stored.
516
514
  */
517
- declare function expandShareRecord(record: StoredShareRecord, shareOrigin?: string): Promise<SenderShareRecord>;
515
+ declare function expandShareRecord(record: StoredShareRecord): Promise<SenderShareRecord>;
518
516
 
519
517
  /**
520
518
  * Index document schema v1, rows, `project()`, and the versioned agent-record
@@ -1060,4 +1058,4 @@ declare function checkRegistrationReceipt(value: unknown, expected: {
1060
1058
 
1061
1059
  declare function verifyEnvelopeV3At(envelope: ShareEnvelopeV3, expectedSignerDid: string, now: number): Promise<boolean>;
1062
1060
 
1063
- export { AGENT_ID_LENGTH, AGENT_RECORD_VERSION, type AgentKeyMaterial, AgentRecordError, type AgentRecordFailure, type AgentRecordHeader, type AgentRejectReason, AgentShareRecordStore, type AgentShareRecordStoreOptions, type Attenuation, type CasPolicy, type ChainContext, type ChainVerdict, type CheckedRegistration, type ClaimDecision, type ClassifiedRecordKey, DEFAULT_CAS_POLICY, DEFAULT_SHARE_INDEX_LIMITS, DeliveryMaterialError, INDEX_MAIN_KEY, INDEX_SCHEMA_VERSION, INVALID_ETAG_MESSAGE, MAX_AGENT_RECORD_BYTES, MemoryShareIndexOutbox, type OwnerNetworkUnwrap, type OwnerNetworkWrap, OwnerUnwrapUnavailableError, type ParsedSiweCacao, type RegistrationKey, SHARE_RECORDS_VAULT_PREFIX, STORED_DELIVERY_MATERIAL_KEYS, SUPPORTED_AGENT_RECORD_V, SenderShareIndex, type SenderShareIndexOptions, SenderShareRecord, type ShareDocumentRead, type ShareIndexAgentEntry, type ShareIndexArchiveDocument, type ShareIndexBackend, ShareIndexCasError, type ShareIndexCasErrorCode, type ShareIndexDocument, type ShareIndexFlushResult, type ShareIndexLimits, type ShareIndexLoad, type ShareIndexOp, type ShareIndexOutbox, type ShareIndexReconcileReport, type ShareIndexRow, type ShareIndexWriteOutcome, type ShareIndexWriteStatus, type ShareLinkCheck, type ShareLinkShape, type ShareListResult, type ShareProofState, type ShareRawRead, ShareRecordSchemaError, type ShareRegistrationKey, type ShareStatusPort, type ShareWriteCondition, type ShareWriteResult, type SignedUcanDelegation, type SiweCacaoParser, type StoredAgentRecord, type StoredDeliveryMaterial, type StoredShareRecord, type TinyCloudShareIndexBackendOptions, type TinyCloudShareIndexClient, type VaultNetworkRead, WebShareRecordStore, agentIdFromDid, agentRecordBinding, agentRecordKey, agentRecordPrefix, attenuationCovers, checkRegistrationReceipt, claimRank, classifyRecordKey, compactShareRecord, createTinyCloudShareIndexBackend, decideClaim, deriveAgentKeyMaterial, displayName, expandShareRecord, headerBytes, isAgentId, isShareId, isSpaceOwnedBy, openAgentRecordAsAgent, openAgentRecordAsOwner, openDeliveryEnvelope, parseIndexDocument, parseSignedUcan, parseStoredAgentRecord, project, sealAgentRecord, shareLinkForRecord, validateShareLink, verifyAgentRecordChain, verifyEnvelopeV3At, verifyOwnerSessionDelegation, verifyPolicyEnforcementDelegation };
1061
+ export { AGENT_ID_LENGTH, AGENT_RECORD_VERSION, type AgentKeyMaterial, AgentRecordError, type AgentRecordFailure, type AgentRecordHeader, type AgentRejectReason, AgentShareRecordStore, type AgentShareRecordStoreOptions, type Attenuation, type CasPolicy, type ChainContext, type ChainVerdict, type CheckedRegistration, type ClaimDecision, type ClassifiedRecordKey, DEFAULT_CAS_POLICY, DEFAULT_SHARE_INDEX_LIMITS, DeliveryMaterialError, INDEX_MAIN_KEY, INDEX_SCHEMA_VERSION, INVALID_ETAG_MESSAGE, MAX_AGENT_RECORD_BYTES, MemoryShareIndexOutbox, type OwnerNetworkUnwrap, type OwnerNetworkWrap, OwnerUnwrapUnavailableError, type ParsedSiweCacao, type RegistrationKey, SHARE_RECORDS_VAULT_PREFIX, STORED_DELIVERY_MATERIAL_KEYS, SUPPORTED_AGENT_RECORD_V, SenderShareIndex, type SenderShareIndexOptions, SenderShareRecord, type ShareDocumentRead, type ShareIndexAgentEntry, type ShareIndexArchiveDocument, type ShareIndexBackend, ShareIndexCasError, type ShareIndexCasErrorCode, type ShareIndexDocument, type ShareIndexFlushResult, type ShareIndexLimits, type ShareIndexLoad, type ShareIndexOp, type ShareIndexOutbox, type ShareIndexReconcileReport, type ShareIndexRow, type ShareIndexWriteOutcome, type ShareIndexWriteStatus, type ShareLinkCheck, type ShareLinkShape, type ShareListResult, type ShareProofState, type ShareRawRead, ShareRecordSchemaError, type ShareRegistrationKey, type ShareStatusPort, type ShareWriteCondition, type ShareWriteResult, type SignedUcanDelegation, type SiweCacaoParser, type StoredAgentRecord, type StoredDeliveryMaterial, type StoredShareRecord, type TinyCloudShareIndexBackendOptions, type TinyCloudShareIndexClient, type VaultNetworkRead, WebShareRecordStore, agentIdFromDid, agentRecordBinding, agentRecordKey, agentRecordPrefix, assertLinkBoundToMaterial, attenuationCovers, checkRegistrationReceipt, claimRank, classifyRecordKey, compactShareRecord, createTinyCloudShareIndexBackend, decideClaim, deriveAgentKeyMaterial, displayName, expandShareRecord, headerBytes, isAgentId, isShareId, isSpaceOwnedBy, openAgentRecordAsAgent, openAgentRecordAsOwner, openDeliveryEnvelope, parseIndexDocument, parseSignedUcan, parseStoredAgentRecord, project, sealAgentRecord, validateShareLink, verifyAgentRecordChain, verifyEnvelopeV3At, verifyOwnerSessionDelegation, verifyPolicyEnforcementDelegation };
@@ -4924,7 +4924,8 @@ function isCanonicalRawCid(cidString) {
4924
4924
  } catch {
4925
4925
  return false;
4926
4926
  }
4927
- return cid2.version === 1 && cid2.code === code && cid2.multihash.code === SHA256_CODE && cid2.toString() === cidString;
4927
+ 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.
4928
+ CID.createV1(cid2.code, cid2.multihash).toString() === cidString;
4928
4929
  }
4929
4930
  var base64 = rfc4648({
4930
4931
  prefix: "m",
@@ -5540,7 +5541,6 @@ function verifyEnvelopeV3SignatureOnly(envelope) {
5540
5541
  return ed255193.verify(fromBase64Url(signature.value), sha2562(signingBytesV3(unsigned)), ed25519PublicKeyFromDidKey(signature.signerDid), ED25519_VERIFY_OPTS2);
5541
5542
  }
5542
5543
  var KEY_LENGTH2 = 32;
5543
- var MAX_INLINE_BYTES = 256 * 1024;
5544
5544
  function assertCanonicalCid(cidString) {
5545
5545
  const cid2 = CID.parse(cidString);
5546
5546
  if (cid2.version !== 1 || cid2.code !== code || cid2.multihash.code !== 18 || // sha2-256 (0x12) only, at the link layer too
@@ -5548,21 +5548,6 @@ function assertCanonicalCid(cidString) {
5548
5548
  throw new TypeError(`not a canonical CIDv1 raw sha2-256 base32 CID: ${cidString}`);
5549
5549
  }
5550
5550
  }
5551
- async function encodeSealedInlineShareUrl(parts) {
5552
- if (!isCanonicalHttpsOrigin(parts.origin)) throw new TypeError("origin must be a canonical https origin");
5553
- if (parts.ciphertext.byteLength === 0 || parts.ciphertext.byteLength > MAX_INLINE_BYTES) throw new RangeError("inline ciphertext is outside the allowed size");
5554
- if (parts.key32.byteLength !== KEY_LENGTH2) throw new TypeError("inline key must be 32 bytes");
5555
- const ciphertextCid = await computeCid(parts.ciphertext);
5556
- const payload = canonicalize({
5557
- v: 2,
5558
- c: toBase64Url(parts.ciphertext),
5559
- cid: ciphertextCid,
5560
- k: toBase64Url(parts.key32)
5561
- });
5562
- const payloadBytes = new TextEncoder().encode(payload);
5563
- if (payloadBytes.byteLength > MAX_INLINE_BYTES * 2) throw new RangeError("inline URL is too large");
5564
- return `${parts.origin}/s/inline#v=2&p=${toBase64Url(payloadBytes)}`;
5565
- }
5566
5551
  function parseShareUrl(url, options = {}) {
5567
5552
  const parsed = new URL(url);
5568
5553
  if (parsed.protocol !== "https:") {
@@ -5601,47 +5586,6 @@ function parseShareUrl(url, options = {}) {
5601
5586
  }
5602
5587
  return { ciphertextCid, key32 };
5603
5588
  }
5604
- async function parseSealedInlineShareUrl(url, options = {}) {
5605
- const parsed = new URL(url);
5606
- if (parsed.protocol !== "https:" || parsed.username !== "" || parsed.password !== "") throw new TypeError("sealed inline share URL must be canonical HTTPS without userinfo");
5607
- if (!isCanonicalHttpsOrigin(parsed.origin) || options.expectedOrigin !== void 0 && parsed.origin !== options.expectedOrigin) throw new TypeError("sealed inline share URL origin is not trusted");
5608
- if (parsed.pathname !== "/s/inline" || parsed.search !== "") throw new TypeError("not a Node sealed-inline share URL");
5609
- if (url !== `${parsed.origin}/s/inline${parsed.hash}`) throw new TypeError("sealed inline share URL is not lexically canonical");
5610
- const prefix = "#v=2&p=";
5611
- if (!parsed.hash.startsWith(prefix)) throw new TypeError("sealed inline URL is missing its canonical fragment");
5612
- const encoded = parsed.hash.slice(prefix.length);
5613
- if (encoded.length === 0 || parsed.hash !== `${prefix}${encoded}`) throw new TypeError("sealed inline URL fragment is not canonical");
5614
- let payloadBytes;
5615
- try {
5616
- payloadBytes = fromBase64Url(encoded);
5617
- } catch {
5618
- throw new TypeError("sealed inline payload is not canonical base64url");
5619
- }
5620
- if (payloadBytes.byteLength === 0 || payloadBytes.byteLength > MAX_INLINE_BYTES * 2) throw new TypeError("sealed inline payload is too large");
5621
- const payloadText = new TextDecoder("utf-8", { fatal: true }).decode(payloadBytes);
5622
- let value;
5623
- try {
5624
- value = JSON.parse(payloadText);
5625
- } catch {
5626
- throw new TypeError("sealed inline payload is not valid JSON");
5627
- }
5628
- if (typeof value !== "object" || value === null || Array.isArray(value) || canonicalize(value) !== payloadText) throw new TypeError("sealed inline payload is not canonical JSON");
5629
- const record2 = value;
5630
- 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");
5631
- let ciphertext;
5632
- let key32;
5633
- try {
5634
- ciphertext = fromBase64Url(record2.c);
5635
- key32 = fromBase64Url(record2.k);
5636
- } catch {
5637
- throw new TypeError("sealed inline payload has invalid base64url material");
5638
- }
5639
- if (ciphertext.byteLength === 0 || ciphertext.byteLength > MAX_INLINE_BYTES) throw new TypeError("sealed inline ciphertext is outside the allowed size");
5640
- if (key32.byteLength !== KEY_LENGTH2) throw new TypeError("sealed inline key must be 32 bytes");
5641
- assertCanonicalCid(record2.cid);
5642
- if (await computeCid(ciphertext) !== record2.cid) throw new TypeError("sealed inline ciphertext does not match its CID");
5643
- return { kind: "inline", ciphertextCid: record2.cid, ciphertext, key32 };
5644
- }
5645
5589
 
5646
5590
  // src/share-index/ids.ts
5647
5591
  var SHARE_RECORDS_VAULT_PREFIX = "sender-history/v2/records/";
@@ -5694,6 +5638,9 @@ function classifyRecordKey(key) {
5694
5638
  return { kind: "rejected", ...owner };
5695
5639
  }
5696
5640
 
5641
+ // src/share-index/link.ts
5642
+ import { MAX_LINK_REQUEST_BYTES, parseLink } from "@tinycloud/share-envelope/links";
5643
+
5697
5644
  // src/native.ts
5698
5645
  var NATIVE_SHARE_FRAGMENT_PARAMETER = "tc1";
5699
5646
  function parseNativeShareUrl(value) {
@@ -5707,14 +5654,17 @@ function parseNativeShareUrl(value) {
5707
5654
 
5708
5655
  // src/share-index/link.ts
5709
5656
  var MAX_LINK_LENGTH = 12 * 1024;
5657
+ var MAX_FULL_LINK_LENGTH = Math.ceil(MAX_LINK_REQUEST_BYTES * 4 / 3) + 512;
5658
+ var V4_SHARE_PATH = /^\/s\/([A-Za-z2-7]{26}|full)$/;
5710
5659
  function validateShareLink(link, shareOrigins) {
5711
- if (typeof link !== "string" || link.length === 0 || link.length > MAX_LINK_LENGTH || /[\s\u0000-\u001f\u007f]/.test(link)) return { ok: false };
5660
+ if (typeof link !== "string" || link.length === 0 || link.length > MAX_FULL_LINK_LENGTH || /[\s\u0000-\u001f\u007f]/.test(link)) return { ok: false };
5712
5661
  let url;
5713
5662
  try {
5714
5663
  url = new URL(link);
5715
5664
  } catch {
5716
5665
  return { ok: false };
5717
5666
  }
5667
+ if (link.length > MAX_LINK_LENGTH && url.pathname !== "/s/full") return { ok: false };
5718
5668
  if (url.protocol !== "https:" || url.username !== "" || url.password !== "" || url.search !== "") return { ok: false };
5719
5669
  if (!isCanonicalHttpsOrigin(url.origin) || !shareOrigins.includes(url.origin)) return { ok: false };
5720
5670
  try {
@@ -5722,8 +5672,9 @@ function validateShareLink(link, shareOrigins) {
5722
5672
  parseNativeShareUrl(link);
5723
5673
  return link === `${url.origin}/viewer${url.hash}` ? { ok: true, shape: "native" } : { ok: false };
5724
5674
  }
5725
- if (url.pathname === "/s/inline") {
5726
- return link === `${url.origin}/s/inline${url.hash}` && /^#v=2&p=[A-Za-z0-9_-]+$/.test(url.hash) ? { ok: true, shape: "inline" } : { ok: false };
5675
+ if (V4_SHARE_PATH.test(url.pathname)) {
5676
+ const parsed = parseLink(link, { trustedOrigins: shareOrigins });
5677
+ return parsed.form === "full" || parsed.pathType === "share" ? { ok: true, shape: "link" } : { ok: false };
5727
5678
  }
5728
5679
  parseShareUrl(link, { expectedOrigin: url.origin });
5729
5680
  return { ok: true, shape: "envelope" };
@@ -6084,6 +6035,7 @@ async function runCas(key, policy, attempt) {
6084
6035
  }
6085
6036
 
6086
6037
  // src/share-index/delivery.ts
6038
+ import { parseLink as parseLink2 } from "@tinycloud/share-envelope/links";
6087
6039
  var STORED_DELIVERY_MATERIAL_KEYS = ["shareCid", "sealedEnvelope", "envelopeKey"];
6088
6040
  var DeliveryMaterialError = class extends Error {
6089
6041
  constructor(message) {
@@ -6121,13 +6073,17 @@ async function openDeliveryEnvelope(material) {
6121
6073
  if (value === null || typeof value !== "object" || Array.isArray(value) || canonicalize(value) !== text) throw new DeliveryMaterialError("sealed envelope is not canonical JSON");
6122
6074
  return value;
6123
6075
  }
6124
- async function shareLinkForRecord(record2, shareOrigin) {
6125
- if (record2.link !== void 0) return record2.link;
6126
- const material = record2.deliveryMaterial;
6127
- if (material === void 0) return void 0;
6076
+ function assertLinkBoundToMaterial(link, material) {
6128
6077
  const { sealed, key } = sealedParts(material);
6129
- if (await computeCid(sealed) !== material.shareCid) throw new DeliveryMaterialError("sealed envelope does not match shareCid");
6130
- return encodeSealedInlineShareUrl({ origin: shareOrigin, ciphertext: sealed, key32: key });
6078
+ let parsed;
6079
+ try {
6080
+ parsed = parseLink2(link, { trustedOrigins: [new URL(link).origin] });
6081
+ } catch {
6082
+ throw new DeliveryMaterialError("link is not a v=4 share link");
6083
+ }
6084
+ 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);
6085
+ if (!sameBody || !equalBytes(parsed.key, key)) throw new DeliveryMaterialError("link is not the link of this delivery material");
6086
+ return parsed.form;
6131
6087
  }
6132
6088
  async function compactShareRecord(record2) {
6133
6089
  const material = record2.deliveryMaterial;
@@ -6137,29 +6093,17 @@ async function compactShareRecord(record2) {
6137
6093
  const opened = await openDeliveryEnvelope(stored);
6138
6094
  if (material.envelope !== void 0 && canonicalize(opened) !== canonicalize(material.envelope)) throw new DeliveryMaterialError("envelope is not the sealed envelope");
6139
6095
  const { link, deliveryMaterial: _material, ...rest } = record2;
6140
- if (link !== void 0) {
6141
- const { sealed, key } = sealedParts(stored);
6142
- let parsed;
6143
- try {
6144
- parsed = await parseSealedInlineShareUrl(link);
6145
- } catch {
6146
- parsed = void 0;
6147
- }
6148
- if (parsed === void 0 || parsed.ciphertextCid !== stored.shareCid || !equalBytes(parsed.ciphertext, sealed) || !equalBytes(parsed.key32, key)) {
6149
- throw new DeliveryMaterialError("link is not the sealed-inline link of this delivery material");
6150
- }
6151
- }
6152
- return { ...rest, deliveryMaterial: stored };
6096
+ const keptLink = link !== void 0 && assertLinkBoundToMaterial(link, stored) === "short" ? link : void 0;
6097
+ return { ...rest, ...keptLink === void 0 ? {} : { link: keptLink }, deliveryMaterial: stored };
6153
6098
  }
6154
6099
  function equalBytes(left, right) {
6155
6100
  return left.length === right.length && left.every((byte, index) => byte === right[index]);
6156
6101
  }
6157
- async function expandShareRecord(record2, shareOrigin) {
6102
+ async function expandShareRecord(record2) {
6158
6103
  const material = record2.deliveryMaterial;
6159
6104
  if (material === void 0) return record2;
6160
6105
  const envelope = await openDeliveryEnvelope(material);
6161
- const link = shareOrigin === void 0 ? record2.link : await shareLinkForRecord(record2, shareOrigin);
6162
- return { ...record2, ...link === void 0 ? {} : { link }, deliveryMaterial: { ...material, envelope } };
6106
+ return { ...record2, deliveryMaterial: { ...material, envelope } };
6163
6107
  }
6164
6108
 
6165
6109
  // src/share-index/record-store.ts
@@ -6266,7 +6210,7 @@ var AgentShareRecordStore = class {
6266
6210
  }
6267
6211
  if (!isRecordShape(value) || value.shareId !== shareId) throw new AgentRecordError("shape");
6268
6212
  try {
6269
- return await expandShareRecord(value, this.options.shareOrigin);
6213
+ return await expandShareRecord(value);
6270
6214
  } catch {
6271
6215
  throw new AgentRecordError("shape");
6272
6216
  }
@@ -6457,6 +6401,15 @@ var ShareRecordSchemaError = class extends Error {
6457
6401
  this.name = "ShareRecordSchemaError";
6458
6402
  }
6459
6403
  };
6404
+ function carriesSealedRecord(link) {
6405
+ try {
6406
+ const url = new URL(link);
6407
+ const fragment = new URLSearchParams(url.hash.slice(1));
6408
+ return url.pathname === "/s/full" || fragment.has("r") || fragment.has("p");
6409
+ } catch {
6410
+ return false;
6411
+ }
6412
+ }
6460
6413
  function checkAgentRecordSchema(value, context) {
6461
6414
  const fail2 = () => {
6462
6415
  throw new ShareRecordSchemaError("schema");
@@ -6493,7 +6446,7 @@ function checkAgentRecordSchema(value, context) {
6493
6446
  if (record2.deliveryMaterial !== void 0) {
6494
6447
  const material = record2.deliveryMaterial;
6495
6448
  if (!isObject(material) || Object.keys(material).length !== STORED_DELIVERY_MATERIAL_KEYS.length || !STORED_DELIVERY_MATERIAL_KEYS.every((key) => typeof material[key] === "string")) return fail2();
6496
- if (record2.link !== void 0) return fail2();
6449
+ if (typeof record2.link === "string" && carriesSealedRecord(record2.link)) return fail2();
6497
6450
  }
6498
6451
  if (record2.deliveredRecipients !== void 0 && (!Array.isArray(record2.deliveredRecipients) || !record2.deliveredRecipients.every((item) => typeof item === "string"))) return fail2();
6499
6452
  if (record2.proofs !== void 0) {
@@ -8231,6 +8184,13 @@ var SenderShareIndex = class {
8231
8184
  return { kind: "reject", reason: error instanceof ShareRecordSchemaError && error.reason === "provenance" ? "provenance" : "schema" };
8232
8185
  }
8233
8186
  if (record2.link !== void 0 && !validateShareLink(record2.link, this.options.shareOrigins).ok) return { kind: "reject", reason: "link" };
8187
+ if (record2.link !== void 0 && record2.deliveryMaterial !== void 0) {
8188
+ try {
8189
+ assertLinkBoundToMaterial(record2.link, record2.deliveryMaterial);
8190
+ } catch {
8191
+ return { kind: "reject", reason: "link" };
8192
+ }
8193
+ }
8234
8194
  const verdict = await verifyAgentRecordChain(record2, {
8235
8195
  accountOwnerDid: this.options.ownerDid,
8236
8196
  agentDid: input.agentDid,
@@ -8610,6 +8570,7 @@ export {
8610
8570
  agentRecordBinding,
8611
8571
  agentRecordKey,
8612
8572
  agentRecordPrefix,
8573
+ assertLinkBoundToMaterial,
8613
8574
  attenuationCovers,
8614
8575
  checkRegistrationReceipt,
8615
8576
  claimRank,
@@ -8632,7 +8593,6 @@ export {
8632
8593
  parseStoredAgentRecord,
8633
8594
  project,
8634
8595
  sealAgentRecord,
8635
- shareLinkForRecord,
8636
8596
  validateShareLink,
8637
8597
  verifyAgentRecordChain,
8638
8598
  verifyEnvelopeV3At,