@tinycloud/share-sdk 1.0.0 → 1.1.0-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.d.cts CHANGED
@@ -707,6 +707,8 @@ interface SenderShareRecord {
707
707
  readonly filename?: string;
708
708
  /** Policy/v3 delivery material. The containing history record must remain encrypted at rest. */
709
709
  readonly deliveryMaterial?: PublishedShareDeliveryMaterial;
710
+ /** Canonical mailboxes whose invitation delivery was confirmed; history is encrypted at rest. */
711
+ readonly deliveredRecipients?: readonly string[];
710
712
  }
711
713
  /** Create the durable encrypted-history shape from canonical publication receipts. */
712
714
  declare function historyRecordForPublishedShare(result: PublishedShare, now?: Date): SenderShareRecord;
@@ -720,6 +722,9 @@ declare function historyRecordForPublishedShare(result: PublishedShare, now?: Da
720
722
  type SenderShareRevocationScope = "direct" | "ancestor";
721
723
  interface SenderShareRecordStorage {
722
724
  put(record: SenderShareRecord): Promise<void>;
725
+ /** Atomically transform the latest record, if present. Implementations that
726
+ * provide this must serialize the read and write with every other writer. */
727
+ update?(shareId: string, change: (record: SenderShareRecord) => SenderShareRecord | Promise<SenderShareRecord>): Promise<SenderShareRecord | undefined>;
723
728
  list(): Promise<readonly SenderShareRecord[]>;
724
729
  get(shareId: string): Promise<SenderShareRecord | undefined>;
725
730
  delete(shareId: string): Promise<void>;
@@ -737,7 +742,10 @@ interface SenderShareKeyStorage {
737
742
  /** In-memory reference implementation. Real deployments back these with IndexedDB so the non-extractable `CryptoKey` survives a reload via structured clone. */
738
743
  declare class MemorySenderShareRecordStorage implements SenderShareRecordStorage {
739
744
  private readonly records;
745
+ private operation;
746
+ private serialize;
740
747
  put(record: SenderShareRecord): Promise<void>;
748
+ update(shareId: string, change: (record: SenderShareRecord) => SenderShareRecord | Promise<SenderShareRecord>): Promise<SenderShareRecord | undefined>;
741
749
  list(): Promise<readonly SenderShareRecord[]>;
742
750
  get(shareId: string): Promise<SenderShareRecord | undefined>;
743
751
  delete(shareId: string): Promise<void>;
@@ -809,6 +817,7 @@ interface ShareNotifyResult {
809
817
  readonly idempotencyKey: string;
810
818
  readonly attempts: number;
811
819
  readonly retryable?: boolean;
820
+ readonly reason?: "delivery-window-expired";
812
821
  }
813
822
  interface ShareNotifyInput {
814
823
  readonly shareId: string;
@@ -822,8 +831,9 @@ interface ShareDeliveryAdapter {
822
831
  deliver(input: ShareNotifyInput): Promise<"delivered" | "already-delivered">;
823
832
  }
824
833
  declare class ShareNotifyError extends Error {
834
+ readonly reason?: "delivery-window-expired" | undefined;
825
835
  readonly code: "delivery-failed";
826
- constructor(message?: string);
836
+ constructor(message?: string, reason?: "delivery-window-expired" | undefined);
827
837
  }
828
838
  /**
829
839
  * Match a delivery address against the recipient constraint recorded when the
@@ -831,6 +841,8 @@ declare class ShareNotifyError extends Error {
831
841
  * the only form the credential issuer accepts.
832
842
  */
833
843
  declare function recipientMatchesShareRecord(record: SenderShareRecord, recipient: string): boolean;
844
+ /** The sender can authorize a fresh invitation only until this persisted deadline. */
845
+ declare function shareDeliveryWindowExpiresAt(record: SenderShareRecord): number;
834
846
  /**
835
847
  * Delivery is deliberately separate from publication. A failed notification
836
848
  * never causes a second envelope or link to be minted.
@@ -843,6 +855,8 @@ declare function notifyShare(input: {
843
855
  readonly idempotencyKey?: string;
844
856
  readonly maxAttempts?: number;
845
857
  readonly signal?: AbortSignal;
858
+ /** Check the persisted delivery window locally before calling the adapter. */
859
+ readonly checkDeliveryWindow?: boolean;
846
860
  }): Promise<ShareNotifyResult>;
847
861
 
848
862
  /** The signed, app-neutral receipt accepted by OpenCredentials' invitation endpoint. */
@@ -1133,4 +1147,4 @@ declare function parseNativeShareUrl(value: string): string;
1133
1147
  /** Receive through the public SDK without creating another transport protocol. */
1134
1148
  declare function openNativeShare(sharing: NativeSharingService, link: string): Promise<unknown>;
1135
1149
 
1136
- export { type AddressedOwnerRootInput, type AddressedOwnerRootReceipt, type AddressedPolicyRegistrationInput, type AddressedPolicyRegistrationReceipt, type AddressedPublishAuthority, type AddressedSharePublishOptions, type AddressedShareRequest, type CreateOwnerDelegationParams, CredentialInvitationError, type CredentialInvitationErrorCode, type CredentialInvitationReceipt, type CredentialInvitationResult, DEFAULT_MAX_CONTENT_BLOB_BYTES, DEFAULT_MAX_SEALED_BLOB_BYTES, DEFAULT_SHARE_LIFETIME_MS, type DelegatedShareKey, EncryptedSenderShareHistory, type EncryptedShareHistoryStorage, MAX_CONTENT_BYTES, MemoryEncryptedShareHistoryStorage, MemorySenderShareKeyStorage, MemorySenderShareRecordStorage, MemoryShareCache, NATIVE_SHARE_FRAGMENT_PARAMETER, type NativeShareResult, type NativeSharingService, OWNER_SHARE_REGISTRATION_DOMAIN, type OwnerDelegationPermission, type OwnerDelegationReceipt, type OwnerShareAction, type OwnerShareDecryption, type OwnerShareMatcher, type OwnerSharePolicyRegistration, type OwnerSharePolicyRegistrationReceipt, type OwnerSharePolicyV2, type ParsedAddressedEnvelope, type PreparedAddressedShare, type PublishedShare, type PublishedShareDeliveryMaterial, type PublishedShareMetadata, type RegisterOwnerSharePolicyParams, SHARE_CONTENT_LIMIT, SHARE_PUBLISH_RESULT_VERSION, SHARE_RESULT_VERSION, SHARE_V2_PROTOCOL, type SenderShareKeyStorage, type SenderShareRecord, type SenderShareRecordStorage, type SenderShareRevocationScope, SenderShareStore, type ShareAuthorizationAdapter, type ShareAuthorizationDenied, type ShareAuthorizationMethod, type ShareAuthorizationReady, type ShareAuthorizationRequired, type ShareAuthorizationResult, type ShareAuthorizedContent, type ShareCache, type ShareCacheEntry, type ShareCacheKey, type ShareCacheMetadata, type ShareDeliveryAdapter, type ShareErrorCode, type ShareErrorInfo, type ShareFetchOptions, type ShareHistoryView, type ShareInspection, type ShareMetadata, type ShareNodeTrust, ShareNotifyError, type ShareNotifyInput, type ShareNotifyResult, type ShareNotifyState, type SharePolicyChallenge, type SharePolicyDelegationLink, type SharePolicyPublishAdapter, type SharePolicyRootRevocation, type SharePolicySession, type SharePresentationMaterial, SharePublishError, type SharePublishErrorCode, type SharePublishOptions, type SharePublishTarget, type ShareReceiveAuthorizationRequired, ShareReceiveError, type ShareReceiveOutcome, type ShareReceiveResult, ShareRecipientClient, type ShareRecipientClientOptions, type ShareRevocationAdapter, type ShareRevocationResult, type ShareTarget, type SignedDelegation, type TargetPublishAdapter, type TargetPublishInput, type TargetPublishOutcome, addressedCredentialRequirement, authorizationMethodForTarget, authorizeShare, canonicalOwnerSharePolicy, canonicalShareFilename, claimShare, computeOwnerShareRegistrationCid, createAddressedAuthorization, createDelegatedShareKey, createNativeShare, createPolicyEnforcementDelegation, createShareV2HolderBindingArtifact, deliverCredentialInvitation, hasUnsafeFilenameCodePoint, historyRecordForPublishedShare, inspectShare, listShares, normalizeShareTarget, notifyShare, openNativeShare, parseAddressedEnvelope, parseNativeShareUrl, prepareAddressedShare, publishAddressedShare, publishPolicyShare, publishTargetShare, receiveShare, recipientMatchesShareRecord, redactPublishedShare, restoreDelegatedShareKey, resumeShareAuthorization, revokeShare, showShare, targetAuthorizationMethod, toShareErrorInfo, validateOwnerSharePolicyRegistration, validateOwnerSharePolicyRegistrationBytes };
1150
+ export { type AddressedOwnerRootInput, type AddressedOwnerRootReceipt, type AddressedPolicyRegistrationInput, type AddressedPolicyRegistrationReceipt, type AddressedPublishAuthority, type AddressedSharePublishOptions, type AddressedShareRequest, type CreateOwnerDelegationParams, CredentialInvitationError, type CredentialInvitationErrorCode, type CredentialInvitationReceipt, type CredentialInvitationResult, DEFAULT_MAX_CONTENT_BLOB_BYTES, DEFAULT_MAX_SEALED_BLOB_BYTES, DEFAULT_SHARE_LIFETIME_MS, type DelegatedShareKey, EncryptedSenderShareHistory, type EncryptedShareHistoryStorage, MAX_CONTENT_BYTES, MemoryEncryptedShareHistoryStorage, MemorySenderShareKeyStorage, MemorySenderShareRecordStorage, MemoryShareCache, NATIVE_SHARE_FRAGMENT_PARAMETER, type NativeShareResult, type NativeSharingService, OWNER_SHARE_REGISTRATION_DOMAIN, type OwnerDelegationPermission, type OwnerDelegationReceipt, type OwnerShareAction, type OwnerShareDecryption, type OwnerShareMatcher, type OwnerSharePolicyRegistration, type OwnerSharePolicyRegistrationReceipt, type OwnerSharePolicyV2, type ParsedAddressedEnvelope, type PreparedAddressedShare, type PublishedShare, type PublishedShareDeliveryMaterial, type PublishedShareMetadata, type RegisterOwnerSharePolicyParams, SHARE_CONTENT_LIMIT, SHARE_PUBLISH_RESULT_VERSION, SHARE_RESULT_VERSION, SHARE_V2_PROTOCOL, type SenderShareKeyStorage, type SenderShareRecord, type SenderShareRecordStorage, type SenderShareRevocationScope, SenderShareStore, type ShareAuthorizationAdapter, type ShareAuthorizationDenied, type ShareAuthorizationMethod, type ShareAuthorizationReady, type ShareAuthorizationRequired, type ShareAuthorizationResult, type ShareAuthorizedContent, type ShareCache, type ShareCacheEntry, type ShareCacheKey, type ShareCacheMetadata, type ShareDeliveryAdapter, type ShareErrorCode, type ShareErrorInfo, type ShareFetchOptions, type ShareHistoryView, type ShareInspection, type ShareMetadata, type ShareNodeTrust, ShareNotifyError, type ShareNotifyInput, type ShareNotifyResult, type ShareNotifyState, type SharePolicyChallenge, type SharePolicyDelegationLink, type SharePolicyPublishAdapter, type SharePolicyRootRevocation, type SharePolicySession, type SharePresentationMaterial, SharePublishError, type SharePublishErrorCode, type SharePublishOptions, type SharePublishTarget, type ShareReceiveAuthorizationRequired, ShareReceiveError, type ShareReceiveOutcome, type ShareReceiveResult, ShareRecipientClient, type ShareRecipientClientOptions, type ShareRevocationAdapter, type ShareRevocationResult, type ShareTarget, type SignedDelegation, type TargetPublishAdapter, type TargetPublishInput, type TargetPublishOutcome, addressedCredentialRequirement, authorizationMethodForTarget, authorizeShare, canonicalOwnerSharePolicy, canonicalShareFilename, claimShare, computeOwnerShareRegistrationCid, createAddressedAuthorization, createDelegatedShareKey, createNativeShare, createPolicyEnforcementDelegation, createShareV2HolderBindingArtifact, deliverCredentialInvitation, hasUnsafeFilenameCodePoint, historyRecordForPublishedShare, inspectShare, listShares, normalizeShareTarget, notifyShare, openNativeShare, parseAddressedEnvelope, parseNativeShareUrl, prepareAddressedShare, publishAddressedShare, publishPolicyShare, publishTargetShare, receiveShare, recipientMatchesShareRecord, redactPublishedShare, restoreDelegatedShareKey, resumeShareAuthorization, revokeShare, shareDeliveryWindowExpiresAt, showShare, targetAuthorizationMethod, toShareErrorInfo, validateOwnerSharePolicyRegistration, validateOwnerSharePolicyRegistrationBytes };
package/dist/index.d.ts CHANGED
@@ -707,6 +707,8 @@ interface SenderShareRecord {
707
707
  readonly filename?: string;
708
708
  /** Policy/v3 delivery material. The containing history record must remain encrypted at rest. */
709
709
  readonly deliveryMaterial?: PublishedShareDeliveryMaterial;
710
+ /** Canonical mailboxes whose invitation delivery was confirmed; history is encrypted at rest. */
711
+ readonly deliveredRecipients?: readonly string[];
710
712
  }
711
713
  /** Create the durable encrypted-history shape from canonical publication receipts. */
712
714
  declare function historyRecordForPublishedShare(result: PublishedShare, now?: Date): SenderShareRecord;
@@ -720,6 +722,9 @@ declare function historyRecordForPublishedShare(result: PublishedShare, now?: Da
720
722
  type SenderShareRevocationScope = "direct" | "ancestor";
721
723
  interface SenderShareRecordStorage {
722
724
  put(record: SenderShareRecord): Promise<void>;
725
+ /** Atomically transform the latest record, if present. Implementations that
726
+ * provide this must serialize the read and write with every other writer. */
727
+ update?(shareId: string, change: (record: SenderShareRecord) => SenderShareRecord | Promise<SenderShareRecord>): Promise<SenderShareRecord | undefined>;
723
728
  list(): Promise<readonly SenderShareRecord[]>;
724
729
  get(shareId: string): Promise<SenderShareRecord | undefined>;
725
730
  delete(shareId: string): Promise<void>;
@@ -737,7 +742,10 @@ interface SenderShareKeyStorage {
737
742
  /** In-memory reference implementation. Real deployments back these with IndexedDB so the non-extractable `CryptoKey` survives a reload via structured clone. */
738
743
  declare class MemorySenderShareRecordStorage implements SenderShareRecordStorage {
739
744
  private readonly records;
745
+ private operation;
746
+ private serialize;
740
747
  put(record: SenderShareRecord): Promise<void>;
748
+ update(shareId: string, change: (record: SenderShareRecord) => SenderShareRecord | Promise<SenderShareRecord>): Promise<SenderShareRecord | undefined>;
741
749
  list(): Promise<readonly SenderShareRecord[]>;
742
750
  get(shareId: string): Promise<SenderShareRecord | undefined>;
743
751
  delete(shareId: string): Promise<void>;
@@ -809,6 +817,7 @@ interface ShareNotifyResult {
809
817
  readonly idempotencyKey: string;
810
818
  readonly attempts: number;
811
819
  readonly retryable?: boolean;
820
+ readonly reason?: "delivery-window-expired";
812
821
  }
813
822
  interface ShareNotifyInput {
814
823
  readonly shareId: string;
@@ -822,8 +831,9 @@ interface ShareDeliveryAdapter {
822
831
  deliver(input: ShareNotifyInput): Promise<"delivered" | "already-delivered">;
823
832
  }
824
833
  declare class ShareNotifyError extends Error {
834
+ readonly reason?: "delivery-window-expired" | undefined;
825
835
  readonly code: "delivery-failed";
826
- constructor(message?: string);
836
+ constructor(message?: string, reason?: "delivery-window-expired" | undefined);
827
837
  }
828
838
  /**
829
839
  * Match a delivery address against the recipient constraint recorded when the
@@ -831,6 +841,8 @@ declare class ShareNotifyError extends Error {
831
841
  * the only form the credential issuer accepts.
832
842
  */
833
843
  declare function recipientMatchesShareRecord(record: SenderShareRecord, recipient: string): boolean;
844
+ /** The sender can authorize a fresh invitation only until this persisted deadline. */
845
+ declare function shareDeliveryWindowExpiresAt(record: SenderShareRecord): number;
834
846
  /**
835
847
  * Delivery is deliberately separate from publication. A failed notification
836
848
  * never causes a second envelope or link to be minted.
@@ -843,6 +855,8 @@ declare function notifyShare(input: {
843
855
  readonly idempotencyKey?: string;
844
856
  readonly maxAttempts?: number;
845
857
  readonly signal?: AbortSignal;
858
+ /** Check the persisted delivery window locally before calling the adapter. */
859
+ readonly checkDeliveryWindow?: boolean;
846
860
  }): Promise<ShareNotifyResult>;
847
861
 
848
862
  /** The signed, app-neutral receipt accepted by OpenCredentials' invitation endpoint. */
@@ -1133,4 +1147,4 @@ declare function parseNativeShareUrl(value: string): string;
1133
1147
  /** Receive through the public SDK without creating another transport protocol. */
1134
1148
  declare function openNativeShare(sharing: NativeSharingService, link: string): Promise<unknown>;
1135
1149
 
1136
- export { type AddressedOwnerRootInput, type AddressedOwnerRootReceipt, type AddressedPolicyRegistrationInput, type AddressedPolicyRegistrationReceipt, type AddressedPublishAuthority, type AddressedSharePublishOptions, type AddressedShareRequest, type CreateOwnerDelegationParams, CredentialInvitationError, type CredentialInvitationErrorCode, type CredentialInvitationReceipt, type CredentialInvitationResult, DEFAULT_MAX_CONTENT_BLOB_BYTES, DEFAULT_MAX_SEALED_BLOB_BYTES, DEFAULT_SHARE_LIFETIME_MS, type DelegatedShareKey, EncryptedSenderShareHistory, type EncryptedShareHistoryStorage, MAX_CONTENT_BYTES, MemoryEncryptedShareHistoryStorage, MemorySenderShareKeyStorage, MemorySenderShareRecordStorage, MemoryShareCache, NATIVE_SHARE_FRAGMENT_PARAMETER, type NativeShareResult, type NativeSharingService, OWNER_SHARE_REGISTRATION_DOMAIN, type OwnerDelegationPermission, type OwnerDelegationReceipt, type OwnerShareAction, type OwnerShareDecryption, type OwnerShareMatcher, type OwnerSharePolicyRegistration, type OwnerSharePolicyRegistrationReceipt, type OwnerSharePolicyV2, type ParsedAddressedEnvelope, type PreparedAddressedShare, type PublishedShare, type PublishedShareDeliveryMaterial, type PublishedShareMetadata, type RegisterOwnerSharePolicyParams, SHARE_CONTENT_LIMIT, SHARE_PUBLISH_RESULT_VERSION, SHARE_RESULT_VERSION, SHARE_V2_PROTOCOL, type SenderShareKeyStorage, type SenderShareRecord, type SenderShareRecordStorage, type SenderShareRevocationScope, SenderShareStore, type ShareAuthorizationAdapter, type ShareAuthorizationDenied, type ShareAuthorizationMethod, type ShareAuthorizationReady, type ShareAuthorizationRequired, type ShareAuthorizationResult, type ShareAuthorizedContent, type ShareCache, type ShareCacheEntry, type ShareCacheKey, type ShareCacheMetadata, type ShareDeliveryAdapter, type ShareErrorCode, type ShareErrorInfo, type ShareFetchOptions, type ShareHistoryView, type ShareInspection, type ShareMetadata, type ShareNodeTrust, ShareNotifyError, type ShareNotifyInput, type ShareNotifyResult, type ShareNotifyState, type SharePolicyChallenge, type SharePolicyDelegationLink, type SharePolicyPublishAdapter, type SharePolicyRootRevocation, type SharePolicySession, type SharePresentationMaterial, SharePublishError, type SharePublishErrorCode, type SharePublishOptions, type SharePublishTarget, type ShareReceiveAuthorizationRequired, ShareReceiveError, type ShareReceiveOutcome, type ShareReceiveResult, ShareRecipientClient, type ShareRecipientClientOptions, type ShareRevocationAdapter, type ShareRevocationResult, type ShareTarget, type SignedDelegation, type TargetPublishAdapter, type TargetPublishInput, type TargetPublishOutcome, addressedCredentialRequirement, authorizationMethodForTarget, authorizeShare, canonicalOwnerSharePolicy, canonicalShareFilename, claimShare, computeOwnerShareRegistrationCid, createAddressedAuthorization, createDelegatedShareKey, createNativeShare, createPolicyEnforcementDelegation, createShareV2HolderBindingArtifact, deliverCredentialInvitation, hasUnsafeFilenameCodePoint, historyRecordForPublishedShare, inspectShare, listShares, normalizeShareTarget, notifyShare, openNativeShare, parseAddressedEnvelope, parseNativeShareUrl, prepareAddressedShare, publishAddressedShare, publishPolicyShare, publishTargetShare, receiveShare, recipientMatchesShareRecord, redactPublishedShare, restoreDelegatedShareKey, resumeShareAuthorization, revokeShare, showShare, targetAuthorizationMethod, toShareErrorInfo, validateOwnerSharePolicyRegistration, validateOwnerSharePolicyRegistrationBytes };
1150
+ export { type AddressedOwnerRootInput, type AddressedOwnerRootReceipt, type AddressedPolicyRegistrationInput, type AddressedPolicyRegistrationReceipt, type AddressedPublishAuthority, type AddressedSharePublishOptions, type AddressedShareRequest, type CreateOwnerDelegationParams, CredentialInvitationError, type CredentialInvitationErrorCode, type CredentialInvitationReceipt, type CredentialInvitationResult, DEFAULT_MAX_CONTENT_BLOB_BYTES, DEFAULT_MAX_SEALED_BLOB_BYTES, DEFAULT_SHARE_LIFETIME_MS, type DelegatedShareKey, EncryptedSenderShareHistory, type EncryptedShareHistoryStorage, MAX_CONTENT_BYTES, MemoryEncryptedShareHistoryStorage, MemorySenderShareKeyStorage, MemorySenderShareRecordStorage, MemoryShareCache, NATIVE_SHARE_FRAGMENT_PARAMETER, type NativeShareResult, type NativeSharingService, OWNER_SHARE_REGISTRATION_DOMAIN, type OwnerDelegationPermission, type OwnerDelegationReceipt, type OwnerShareAction, type OwnerShareDecryption, type OwnerShareMatcher, type OwnerSharePolicyRegistration, type OwnerSharePolicyRegistrationReceipt, type OwnerSharePolicyV2, type ParsedAddressedEnvelope, type PreparedAddressedShare, type PublishedShare, type PublishedShareDeliveryMaterial, type PublishedShareMetadata, type RegisterOwnerSharePolicyParams, SHARE_CONTENT_LIMIT, SHARE_PUBLISH_RESULT_VERSION, SHARE_RESULT_VERSION, SHARE_V2_PROTOCOL, type SenderShareKeyStorage, type SenderShareRecord, type SenderShareRecordStorage, type SenderShareRevocationScope, SenderShareStore, type ShareAuthorizationAdapter, type ShareAuthorizationDenied, type ShareAuthorizationMethod, type ShareAuthorizationReady, type ShareAuthorizationRequired, type ShareAuthorizationResult, type ShareAuthorizedContent, type ShareCache, type ShareCacheEntry, type ShareCacheKey, type ShareCacheMetadata, type ShareDeliveryAdapter, type ShareErrorCode, type ShareErrorInfo, type ShareFetchOptions, type ShareHistoryView, type ShareInspection, type ShareMetadata, type ShareNodeTrust, ShareNotifyError, type ShareNotifyInput, type ShareNotifyResult, type ShareNotifyState, type SharePolicyChallenge, type SharePolicyDelegationLink, type SharePolicyPublishAdapter, type SharePolicyRootRevocation, type SharePolicySession, type SharePresentationMaterial, SharePublishError, type SharePublishErrorCode, type SharePublishOptions, type SharePublishTarget, type ShareReceiveAuthorizationRequired, ShareReceiveError, type ShareReceiveOutcome, type ShareReceiveResult, ShareRecipientClient, type ShareRecipientClientOptions, type ShareRevocationAdapter, type ShareRevocationResult, type ShareTarget, type SignedDelegation, type TargetPublishAdapter, type TargetPublishInput, type TargetPublishOutcome, addressedCredentialRequirement, authorizationMethodForTarget, authorizeShare, canonicalOwnerSharePolicy, canonicalShareFilename, claimShare, computeOwnerShareRegistrationCid, createAddressedAuthorization, createDelegatedShareKey, createNativeShare, createPolicyEnforcementDelegation, createShareV2HolderBindingArtifact, deliverCredentialInvitation, hasUnsafeFilenameCodePoint, historyRecordForPublishedShare, inspectShare, listShares, normalizeShareTarget, notifyShare, openNativeShare, parseAddressedEnvelope, parseNativeShareUrl, prepareAddressedShare, publishAddressedShare, publishPolicyShare, publishTargetShare, receiveShare, recipientMatchesShareRecord, redactPublishedShare, restoreDelegatedShareKey, resumeShareAuthorization, revokeShare, shareDeliveryWindowExpiresAt, showShare, targetAuthorizationMethod, toShareErrorInfo, validateOwnerSharePolicyRegistration, validateOwnerSharePolicyRegistrationBytes };
package/dist/index.js CHANGED
@@ -5197,11 +5197,15 @@ var contentMetadataSchema = external_exports.object({
5197
5197
  /** Encrypted presentation discriminator. The fixed entry point is index.html. */
5198
5198
  artifact: external_exports.literal("html").optional()
5199
5199
  }).strict();
5200
+ var deliveryEmailSchema = external_exports.string().email();
5201
+ function isEnvelopeDeliveryEmail(value) {
5202
+ return deliveryEmailSchema.safeParse(value).success;
5203
+ }
5200
5204
  var unsignedShareEnvelopeV2BaseSchema = external_exports.object({
5201
5205
  version: external_exports.literal(2),
5202
5206
  shareId: external_exports.string().min(1),
5203
5207
  recipientMatcher: recipientMatcherSchema,
5204
- deliveryEmail: external_exports.string().email().optional(),
5208
+ deliveryEmail: deliveryEmailSchema.optional(),
5205
5209
  actions: external_exports.array(shareActionSchema).min(1).max(3),
5206
5210
  resource: resourceSelectorSchema,
5207
5211
  target: v2TargetSchema,
@@ -5341,7 +5345,7 @@ var unsignedShareEnvelopeV3BaseSchema = external_exports.object({
5341
5345
  version: external_exports.literal(3),
5342
5346
  shareId: external_exports.string().min(1),
5343
5347
  recipientMatcher: recipientMatcherSchema,
5344
- deliveryEmail: external_exports.string().email().optional(),
5348
+ deliveryEmail: deliveryEmailSchema.optional(),
5345
5349
  actions: external_exports.array(shareActionSchema).min(1).max(3),
5346
5350
  resource: resourceSelectorSchema,
5347
5351
  target: v3TargetSchema,
@@ -6714,6 +6718,7 @@ function prepareAddressedShare(request) {
6714
6718
  }
6715
6719
  if (request.actions.length === 0 || request.policyActions.length === 0) throw new TypeError("addressed share actions are empty");
6716
6720
  if (request.policyActions.some((action) => !OWNER_SHARE_ACTIONS.has(action))) throw new TypeError("addressed share action is not supported");
6721
+ if (request.deliveryEmail !== void 0 && !isEnvelopeDeliveryEmail(request.deliveryEmail)) throw new TypeError("delivery email is not a valid envelope address");
6717
6722
  const target = normalizeShareTarget(request.target);
6718
6723
  if (target.kind === "bearer") throw new TypeError("addressed target is required");
6719
6724
  if (target.kind === "recipientDid") return { target };
@@ -7695,8 +7700,25 @@ function historyRecordForPublishedShare(result, now = /* @__PURE__ */ new Date()
7695
7700
  }
7696
7701
  var MemorySenderShareRecordStorage = class {
7697
7702
  records = /* @__PURE__ */ new Map();
7703
+ operation = Promise.resolve();
7704
+ serialize(action) {
7705
+ const next = this.operation.then(action, action);
7706
+ this.operation = next.then(() => void 0, () => void 0);
7707
+ return next;
7708
+ }
7698
7709
  async put(record) {
7699
- this.records.set(record.shareId, record);
7710
+ return this.serialize(async () => {
7711
+ this.records.set(record.shareId, record);
7712
+ });
7713
+ }
7714
+ async update(shareId, change) {
7715
+ return this.serialize(async () => {
7716
+ const current = this.records.get(shareId);
7717
+ if (current === void 0) return void 0;
7718
+ const updated = await change(current);
7719
+ this.records.set(shareId, updated);
7720
+ return updated;
7721
+ });
7700
7722
  }
7701
7723
  async list() {
7702
7724
  return [...this.records.values()];
@@ -7705,7 +7727,9 @@ var MemorySenderShareRecordStorage = class {
7705
7727
  return this.records.get(shareId);
7706
7728
  }
7707
7729
  async delete(shareId) {
7708
- this.records.delete(shareId);
7730
+ return this.serialize(async () => {
7731
+ this.records.delete(shareId);
7732
+ });
7709
7733
  }
7710
7734
  };
7711
7735
  var MemorySenderShareKeyStorage = class {
@@ -7789,6 +7813,11 @@ var SenderShareStore = class {
7789
7813
  }
7790
7814
  /** Mark a share revoked locally after the caller's node-side revoke call succeeds. */
7791
7815
  async markRevoked(shareId, revokedAt = this.now().toISOString()) {
7816
+ if (this.records.update !== void 0) {
7817
+ const updated = await this.records.update(shareId, (record2) => ({ ...record2, revokedAt }));
7818
+ if (updated === void 0) throw new Error(`Unknown share: ${shareId}`);
7819
+ return updated;
7820
+ }
7792
7821
  const record = await this.records.get(shareId);
7793
7822
  if (record === void 0) throw new Error(`Unknown share: ${shareId}`);
7794
7823
  const revoked = { ...record, revokedAt };
@@ -7836,11 +7865,12 @@ var EncryptedSenderShareHistory = class {
7836
7865
 
7837
7866
  // src/notify.ts
7838
7867
  var ShareNotifyError = class extends Error {
7839
- code = "delivery-failed";
7840
- constructor(message = "share delivery did not complete") {
7868
+ constructor(message = "share delivery did not complete", reason) {
7841
7869
  super(message);
7870
+ this.reason = reason;
7842
7871
  this.name = "ShareNotifyError";
7843
7872
  }
7873
+ code = "delivery-failed";
7844
7874
  };
7845
7875
  function recipientMatchesShareRecord(record, recipient) {
7846
7876
  const matcher = record.recipientMatcher;
@@ -7850,6 +7880,11 @@ function recipientMatchesShareRecord(record, recipient) {
7850
7880
  if (matcher.kind === "emailDomain") return mailbox.domain === matcher.value;
7851
7881
  return false;
7852
7882
  }
7883
+ function shareDeliveryWindowExpiresAt(record) {
7884
+ const expiresAt = Math.min(Date.parse(record.expiresAt), Date.parse(record.registeredAt) + 5 * 60 * 1e3);
7885
+ if (!Number.isFinite(expiresAt)) throw new ShareNotifyError("share delivery history has invalid timestamps");
7886
+ return expiresAt;
7887
+ }
7853
7888
  async function notifyShare(input) {
7854
7889
  const mailbox = canonicalMailbox(input.recipient);
7855
7890
  if (!input.shareId || mailbox === void 0) throw new ShareNotifyError("recipient is invalid");
@@ -7860,6 +7895,19 @@ async function notifyShare(input) {
7860
7895
  const idempotencyKey = input.idempotencyKey ?? await defaultIdempotencyKey(input.shareId, recipient);
7861
7896
  const attemptsLimit = input.maxAttempts ?? 3;
7862
7897
  if (!Number.isSafeInteger(attemptsLimit) || attemptsLimit < 1 || attemptsLimit > 8) throw new ShareNotifyError("maxAttempts is invalid");
7898
+ if (input.signal?.aborted) throw new ShareNotifyError("share delivery was cancelled");
7899
+ if (input.checkDeliveryWindow && input.record !== void 0 && shareDeliveryWindowExpiresAt(input.record) <= Date.now()) {
7900
+ return {
7901
+ protocol: "tinycloud-share",
7902
+ version: 1,
7903
+ shareId: input.shareId,
7904
+ state: "partial-failure",
7905
+ idempotencyKey,
7906
+ attempts: 1,
7907
+ retryable: false,
7908
+ reason: "delivery-window-expired"
7909
+ };
7910
+ }
7863
7911
  let attempts = 0;
7864
7912
  let lastError;
7865
7913
  while (attempts < attemptsLimit) {
@@ -7867,8 +7915,27 @@ async function notifyShare(input) {
7867
7915
  attempts += 1;
7868
7916
  try {
7869
7917
  const state = await input.adapter.deliver({ shareId: input.shareId, recipient, idempotencyKey, ...input.record === void 0 ? {} : { record: input.record }, ...input.signal === void 0 ? {} : { signal: input.signal } });
7870
- return { protocol: "tinycloud-share", version: 1, shareId: input.shareId, state, idempotencyKey, attempts };
7918
+ return {
7919
+ protocol: "tinycloud-share",
7920
+ version: 1,
7921
+ shareId: input.shareId,
7922
+ state: state === "delivered" && input.record?.deliveredRecipients?.includes(recipient) ? "already-delivered" : state,
7923
+ idempotencyKey,
7924
+ attempts
7925
+ };
7871
7926
  } catch (error) {
7927
+ if (error instanceof ShareNotifyError && error.reason === "delivery-window-expired") {
7928
+ return {
7929
+ protocol: "tinycloud-share",
7930
+ version: 1,
7931
+ shareId: input.shareId,
7932
+ state: "partial-failure",
7933
+ idempotencyKey,
7934
+ attempts,
7935
+ retryable: false,
7936
+ reason: "delivery-window-expired"
7937
+ };
7938
+ }
7872
7939
  lastError = error;
7873
7940
  }
7874
7941
  }
@@ -8031,7 +8098,11 @@ async function revokeShare(input) {
8031
8098
  });
8032
8099
  }
8033
8100
  const revokedAt = (input.now?.() ?? /* @__PURE__ */ new Date()).toISOString();
8034
- if (input.records !== void 0) await input.records.put({ ...input.record, revokedAt });
8101
+ if (input.records?.update !== void 0) {
8102
+ await input.records.update(input.record.shareId, (record) => ({ ...record, revokedAt }));
8103
+ } else if (input.records !== void 0) {
8104
+ await input.records.put({ ...input.record, revokedAt });
8105
+ }
8035
8106
  return { state: "revoked", target, delegationCid, revokedAt };
8036
8107
  }
8037
8108
  function redactRecord(record, revealLink, link) {
@@ -8657,6 +8728,7 @@ export {
8657
8728
  restoreDelegatedShareKey,
8658
8729
  resumeShareAuthorization,
8659
8730
  revokeShare,
8731
+ shareDeliveryWindowExpiresAt,
8660
8732
  showShare,
8661
8733
  targetAuthorizationMethod,
8662
8734
  toBase64Url,