@tinycloud/share-sdk 1.0.0-beta.5 → 1.0.0-beta.7

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
@@ -185,6 +185,7 @@ interface SharePublishOptions {
185
185
  readonly allowBinary?: boolean;
186
186
  readonly target?: SharePublishTarget;
187
187
  readonly expiresAt?: Date;
188
+ readonly expiryWasExplicit?: boolean;
188
189
  readonly origin: string;
189
190
  readonly maxBytes?: number;
190
191
  readonly now?: () => number;
@@ -205,6 +206,7 @@ interface PublishedShareMetadata {
205
206
  readonly path: string;
206
207
  };
207
208
  readonly actions: readonly string[];
209
+ readonly expiryClamped?: boolean;
208
210
  readonly expiresAt: string;
209
211
  readonly display: {
210
212
  readonly filename?: string;
@@ -274,6 +276,7 @@ type ShareTarget = SharePublishTarget;
274
276
  interface TargetPublishInput {
275
277
  readonly source: Uint8Array;
276
278
  readonly filename: string;
279
+ readonly mediaType?: string;
277
280
  /** Additional files for a prefix resource; source remains the first file for compatibility. */
278
281
  readonly files?: readonly {
279
282
  readonly bytes: Uint8Array;
@@ -282,8 +285,8 @@ interface TargetPublishInput {
282
285
  }[];
283
286
  readonly target: ShareTarget;
284
287
  readonly expiresAt: Date;
288
+ readonly expiryWasExplicit?: boolean;
285
289
  readonly origin: string;
286
- readonly mediaType?: string;
287
290
  readonly resourceKind?: "exact" | "prefix";
288
291
  readonly actions?: readonly ("read" | "list" | "edit")[];
289
292
  readonly notify?: boolean;
@@ -587,6 +590,29 @@ interface AddressedSharePublishOptions {
587
590
  readonly onDeliveryMaterial?: (input: PublishedShareDeliveryMaterial) => void;
588
591
  readonly authority: AddressedPublishAuthority;
589
592
  }
593
+ type MailboxTarget = Extract<ShareTarget, {
594
+ readonly kind: "email" | "emailDomain";
595
+ }>;
596
+ /** The Policy/v2 credential commitment a share addressed to `target` must carry. */
597
+ declare function addressedCredentialRequirement(target: MailboxTarget): PolicyCredentialRequirementV1;
598
+ /** Facts every addressed-share check needs, available before any side effect. */
599
+ type AddressedShareRequest = Pick<AddressedSharePublishOptions, "target" | "actions" | "policyActions" | "filename" | "deliveryEmail">;
600
+ interface PreparedAddressedShare {
601
+ /** The canonical target the envelope's recipient matcher will carry. */
602
+ readonly target: Exclude<ShareTarget, {
603
+ readonly kind: "bearer";
604
+ }>;
605
+ /** Present for mailbox targets: the Policy/v2 commitment to pass to `publishAddressedShare`. */
606
+ readonly credentialRequirement?: PolicyCredentialRequirementV1;
607
+ }
608
+ /**
609
+ * Runs every argument and target check of `publishAddressedShare` that does
610
+ * not depend on stored content, and derives the credential commitment. It has
611
+ * no side effects, so senders call it before uploading content or publishing
612
+ * a location record; a refused share then leaves nothing behind.
613
+ */
614
+ declare function prepareAddressedShare(request: AddressedShareRequest): PreparedAddressedShare;
615
+ /** Canonical application-neutral Policy/v3 addressed publisher shared by browser and CLI. */
590
616
  declare function publishAddressedShare(options: AddressedSharePublishOptions): Promise<PublishedShare>;
591
617
 
592
618
  interface ShareCacheKey {
@@ -795,7 +821,11 @@ declare class ShareNotifyError extends Error {
795
821
  readonly code: "delivery-failed";
796
822
  constructor(message?: string);
797
823
  }
798
- /** Match a delivery address against the recipient constraint recorded when the share was created. */
824
+ /**
825
+ * Match a delivery address against the recipient constraint recorded when the
826
+ * share was created. Both sides compare in canonical mailbox form, which is
827
+ * the only form the credential issuer accepts.
828
+ */
799
829
  declare function recipientMatchesShareRecord(record: SenderShareRecord, recipient: string): boolean;
800
830
  /**
801
831
  * Delivery is deliberately separate from publication. A failed notification
@@ -1058,6 +1088,12 @@ declare function resumeShareAuthorization<T>(input: {
1058
1088
 
1059
1089
  /** Fragment-only adapter for TinyCloud's public SharingService. */
1060
1090
  declare const NATIVE_SHARE_FRAGMENT_PARAMETER = "tc1";
1091
+ interface NativeShareResult {
1092
+ readonly url: string;
1093
+ readonly delegationCid: string;
1094
+ readonly expiresAt: Date;
1095
+ readonly spaceId: string;
1096
+ }
1061
1097
  interface NativeSharingService {
1062
1098
  generate(params: {
1063
1099
  readonly path: string;
@@ -1078,15 +1114,10 @@ declare function createNativeShare(sharing: NativeSharingService, input: {
1078
1114
  readonly path: string;
1079
1115
  readonly expiresAt: Date;
1080
1116
  readonly viewerOrigin: string;
1081
- }): Promise<{
1082
- readonly url: string;
1083
- readonly delegationCid: string;
1084
- readonly expiresAt: Date;
1085
- readonly spaceId: string;
1086
- }>;
1117
+ }): Promise<NativeShareResult>;
1087
1118
  /** Extract only a single tc1 fragment. Path/query/mixed legacy forms are refused. */
1088
1119
  declare function parseNativeShareUrl(value: string): string;
1089
1120
  /** Receive through the public SDK without creating another transport protocol. */
1090
1121
  declare function openNativeShare(sharing: NativeSharingService, link: string): Promise<unknown>;
1091
1122
 
1092
- export { type AddressedOwnerRootInput, type AddressedOwnerRootReceipt, type AddressedPolicyRegistrationInput, type AddressedPolicyRegistrationReceipt, type AddressedPublishAuthority, type AddressedSharePublishOptions, 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 NativeSharingService, OWNER_SHARE_REGISTRATION_DOMAIN, type OwnerDelegationPermission, type OwnerDelegationReceipt, type OwnerShareAction, type OwnerShareDecryption, type OwnerShareMatcher, type OwnerSharePolicyRegistration, type OwnerSharePolicyRegistrationReceipt, type OwnerSharePolicyV2, type ParsedAddressedEnvelope, 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 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, authorizationMethodForTarget, authorizeShare, canonicalOwnerSharePolicy, claimShare, computeOwnerShareRegistrationCid, createAddressedAuthorization, createDelegatedShareKey, createNativeShare, createPolicyEnforcementDelegation, createShareV2HolderBindingArtifact, deliverCredentialInvitation, historyRecordForPublishedShare, inspectShare, listShares, normalizeShareTarget, notifyShare, openNativeShare, parseAddressedEnvelope, parseNativeShareUrl, publishAddressedShare, publishPolicyShare, publishTargetShare, receiveShare, recipientMatchesShareRecord, redactPublishedShare, restoreDelegatedShareKey, resumeShareAuthorization, revokeShare, showShare, targetAuthorizationMethod, toShareErrorInfo, validateOwnerSharePolicyRegistration, validateOwnerSharePolicyRegistrationBytes };
1123
+ 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 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, claimShare, computeOwnerShareRegistrationCid, createAddressedAuthorization, createDelegatedShareKey, createNativeShare, createPolicyEnforcementDelegation, createShareV2HolderBindingArtifact, deliverCredentialInvitation, historyRecordForPublishedShare, inspectShare, listShares, normalizeShareTarget, notifyShare, openNativeShare, parseAddressedEnvelope, parseNativeShareUrl, prepareAddressedShare, publishAddressedShare, publishPolicyShare, publishTargetShare, receiveShare, recipientMatchesShareRecord, redactPublishedShare, restoreDelegatedShareKey, resumeShareAuthorization, revokeShare, showShare, targetAuthorizationMethod, toShareErrorInfo, validateOwnerSharePolicyRegistration, validateOwnerSharePolicyRegistrationBytes };
package/dist/index.d.ts CHANGED
@@ -185,6 +185,7 @@ interface SharePublishOptions {
185
185
  readonly allowBinary?: boolean;
186
186
  readonly target?: SharePublishTarget;
187
187
  readonly expiresAt?: Date;
188
+ readonly expiryWasExplicit?: boolean;
188
189
  readonly origin: string;
189
190
  readonly maxBytes?: number;
190
191
  readonly now?: () => number;
@@ -205,6 +206,7 @@ interface PublishedShareMetadata {
205
206
  readonly path: string;
206
207
  };
207
208
  readonly actions: readonly string[];
209
+ readonly expiryClamped?: boolean;
208
210
  readonly expiresAt: string;
209
211
  readonly display: {
210
212
  readonly filename?: string;
@@ -274,6 +276,7 @@ type ShareTarget = SharePublishTarget;
274
276
  interface TargetPublishInput {
275
277
  readonly source: Uint8Array;
276
278
  readonly filename: string;
279
+ readonly mediaType?: string;
277
280
  /** Additional files for a prefix resource; source remains the first file for compatibility. */
278
281
  readonly files?: readonly {
279
282
  readonly bytes: Uint8Array;
@@ -282,8 +285,8 @@ interface TargetPublishInput {
282
285
  }[];
283
286
  readonly target: ShareTarget;
284
287
  readonly expiresAt: Date;
288
+ readonly expiryWasExplicit?: boolean;
285
289
  readonly origin: string;
286
- readonly mediaType?: string;
287
290
  readonly resourceKind?: "exact" | "prefix";
288
291
  readonly actions?: readonly ("read" | "list" | "edit")[];
289
292
  readonly notify?: boolean;
@@ -587,6 +590,29 @@ interface AddressedSharePublishOptions {
587
590
  readonly onDeliveryMaterial?: (input: PublishedShareDeliveryMaterial) => void;
588
591
  readonly authority: AddressedPublishAuthority;
589
592
  }
593
+ type MailboxTarget = Extract<ShareTarget, {
594
+ readonly kind: "email" | "emailDomain";
595
+ }>;
596
+ /** The Policy/v2 credential commitment a share addressed to `target` must carry. */
597
+ declare function addressedCredentialRequirement(target: MailboxTarget): PolicyCredentialRequirementV1;
598
+ /** Facts every addressed-share check needs, available before any side effect. */
599
+ type AddressedShareRequest = Pick<AddressedSharePublishOptions, "target" | "actions" | "policyActions" | "filename" | "deliveryEmail">;
600
+ interface PreparedAddressedShare {
601
+ /** The canonical target the envelope's recipient matcher will carry. */
602
+ readonly target: Exclude<ShareTarget, {
603
+ readonly kind: "bearer";
604
+ }>;
605
+ /** Present for mailbox targets: the Policy/v2 commitment to pass to `publishAddressedShare`. */
606
+ readonly credentialRequirement?: PolicyCredentialRequirementV1;
607
+ }
608
+ /**
609
+ * Runs every argument and target check of `publishAddressedShare` that does
610
+ * not depend on stored content, and derives the credential commitment. It has
611
+ * no side effects, so senders call it before uploading content or publishing
612
+ * a location record; a refused share then leaves nothing behind.
613
+ */
614
+ declare function prepareAddressedShare(request: AddressedShareRequest): PreparedAddressedShare;
615
+ /** Canonical application-neutral Policy/v3 addressed publisher shared by browser and CLI. */
590
616
  declare function publishAddressedShare(options: AddressedSharePublishOptions): Promise<PublishedShare>;
591
617
 
592
618
  interface ShareCacheKey {
@@ -795,7 +821,11 @@ declare class ShareNotifyError extends Error {
795
821
  readonly code: "delivery-failed";
796
822
  constructor(message?: string);
797
823
  }
798
- /** Match a delivery address against the recipient constraint recorded when the share was created. */
824
+ /**
825
+ * Match a delivery address against the recipient constraint recorded when the
826
+ * share was created. Both sides compare in canonical mailbox form, which is
827
+ * the only form the credential issuer accepts.
828
+ */
799
829
  declare function recipientMatchesShareRecord(record: SenderShareRecord, recipient: string): boolean;
800
830
  /**
801
831
  * Delivery is deliberately separate from publication. A failed notification
@@ -1058,6 +1088,12 @@ declare function resumeShareAuthorization<T>(input: {
1058
1088
 
1059
1089
  /** Fragment-only adapter for TinyCloud's public SharingService. */
1060
1090
  declare const NATIVE_SHARE_FRAGMENT_PARAMETER = "tc1";
1091
+ interface NativeShareResult {
1092
+ readonly url: string;
1093
+ readonly delegationCid: string;
1094
+ readonly expiresAt: Date;
1095
+ readonly spaceId: string;
1096
+ }
1061
1097
  interface NativeSharingService {
1062
1098
  generate(params: {
1063
1099
  readonly path: string;
@@ -1078,15 +1114,10 @@ declare function createNativeShare(sharing: NativeSharingService, input: {
1078
1114
  readonly path: string;
1079
1115
  readonly expiresAt: Date;
1080
1116
  readonly viewerOrigin: string;
1081
- }): Promise<{
1082
- readonly url: string;
1083
- readonly delegationCid: string;
1084
- readonly expiresAt: Date;
1085
- readonly spaceId: string;
1086
- }>;
1117
+ }): Promise<NativeShareResult>;
1087
1118
  /** Extract only a single tc1 fragment. Path/query/mixed legacy forms are refused. */
1088
1119
  declare function parseNativeShareUrl(value: string): string;
1089
1120
  /** Receive through the public SDK without creating another transport protocol. */
1090
1121
  declare function openNativeShare(sharing: NativeSharingService, link: string): Promise<unknown>;
1091
1122
 
1092
- export { type AddressedOwnerRootInput, type AddressedOwnerRootReceipt, type AddressedPolicyRegistrationInput, type AddressedPolicyRegistrationReceipt, type AddressedPublishAuthority, type AddressedSharePublishOptions, 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 NativeSharingService, OWNER_SHARE_REGISTRATION_DOMAIN, type OwnerDelegationPermission, type OwnerDelegationReceipt, type OwnerShareAction, type OwnerShareDecryption, type OwnerShareMatcher, type OwnerSharePolicyRegistration, type OwnerSharePolicyRegistrationReceipt, type OwnerSharePolicyV2, type ParsedAddressedEnvelope, 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 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, authorizationMethodForTarget, authorizeShare, canonicalOwnerSharePolicy, claimShare, computeOwnerShareRegistrationCid, createAddressedAuthorization, createDelegatedShareKey, createNativeShare, createPolicyEnforcementDelegation, createShareV2HolderBindingArtifact, deliverCredentialInvitation, historyRecordForPublishedShare, inspectShare, listShares, normalizeShareTarget, notifyShare, openNativeShare, parseAddressedEnvelope, parseNativeShareUrl, publishAddressedShare, publishPolicyShare, publishTargetShare, receiveShare, recipientMatchesShareRecord, redactPublishedShare, restoreDelegatedShareKey, resumeShareAuthorization, revokeShare, showShare, targetAuthorizationMethod, toShareErrorInfo, validateOwnerSharePolicyRegistration, validateOwnerSharePolicyRegistrationBytes };
1123
+ 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 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, claimShare, computeOwnerShareRegistrationCid, createAddressedAuthorization, createDelegatedShareKey, createNativeShare, createPolicyEnforcementDelegation, createShareV2HolderBindingArtifact, deliverCredentialInvitation, historyRecordForPublishedShare, inspectShare, listShares, normalizeShareTarget, notifyShare, openNativeShare, parseAddressedEnvelope, parseNativeShareUrl, prepareAddressedShare, publishAddressedShare, publishPolicyShare, publishTargetShare, receiveShare, recipientMatchesShareRecord, redactPublishedShare, restoreDelegatedShareKey, resumeShareAuthorization, revokeShare, showShare, targetAuthorizationMethod, toShareErrorInfo, validateOwnerSharePolicyRegistration, validateOwnerSharePolicyRegistrationBytes };
package/dist/index.js CHANGED
@@ -5685,6 +5685,21 @@ function serialize(value) {
5685
5685
  function canonicalize(value) {
5686
5686
  return serialize(value);
5687
5687
  }
5688
+ var LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
5689
+ function isCanonicalEmailDomain(value) {
5690
+ if (value.length === 0 || value.length > 253) return false;
5691
+ const labels = value.split(".");
5692
+ return labels.length >= 2 && labels.every((label) => LABEL.test(label)) && !/^[0-9]+$/.test(labels.at(-1));
5693
+ }
5694
+ function canonicalMailbox(value) {
5695
+ const email = value.trim().toLowerCase();
5696
+ const at = email.indexOf("@");
5697
+ if (at <= 0 || at !== email.lastIndexOf("@")) return void 0;
5698
+ const local = email.slice(0, at);
5699
+ const domain = email.slice(at + 1);
5700
+ if (local.length > 64 || !/^[a-z0-9#$&'*+/=?^_`{|}~-]+(?:\.[a-z0-9#$&'*+/=?^_`{|}~-]+)*$/.test(local) || !isCanonicalEmailDomain(domain)) return void 0;
5701
+ return Object.freeze({ email, domain });
5702
+ }
5688
5703
  async function signCompactUcanAuthorization(input) {
5689
5704
  if (input.notBefore >= input.expiresAt || input.expiresAt - input.notBefore > 60) {
5690
5705
  throw new TypeError("compact invocation lifetime must be between one and 60 seconds");
@@ -6020,6 +6035,7 @@ function redactPublishedShare(result) {
6020
6035
  target: { ...result.metadata.target },
6021
6036
  resource: { ...result.metadata.resource },
6022
6037
  actions: [...result.metadata.actions],
6038
+ ...result.metadata.expiryClamped === void 0 ? {} : { expiryClamped: result.metadata.expiryClamped },
6023
6039
  expiresAt: result.metadata.expiresAt,
6024
6040
  display: { ...result.metadata.display }
6025
6041
  }
@@ -6429,12 +6445,6 @@ var base58flickr2 = baseX2({
6429
6445
  });
6430
6446
 
6431
6447
  // src/targets.ts
6432
- function validEmail(value) {
6433
- return /^[^@\s]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i.test(value);
6434
- }
6435
- function validDomain(value) {
6436
- return /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(?:\.(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?))+$/i.test(value);
6437
- }
6438
6448
  function validRecipientDid(value) {
6439
6449
  if (value.length === 0 || value.length > 2048 || /[\u0000-\u0020\u007f]/.test(value)) return false;
6440
6450
  const parts = value.split(":");
@@ -6464,12 +6474,13 @@ function normalizeShareTarget(target) {
6464
6474
  return { kind: target.kind, did: target.did };
6465
6475
  }
6466
6476
  if (target.kind === "email") {
6467
- if (!validEmail(target.address)) throw new TypeError("recipient email is invalid");
6468
- const at = target.address.lastIndexOf("@");
6469
- return { kind: target.kind, address: `${target.address.slice(0, at)}@${target.address.slice(at + 1).toLowerCase()}` };
6477
+ const mailbox = canonicalMailbox(target.address);
6478
+ if (mailbox === void 0) throw new TypeError("recipient email is invalid");
6479
+ return { kind: target.kind, address: mailbox.email };
6470
6480
  }
6471
- if (!validDomain(target.domain)) throw new TypeError("recipient email domain is invalid");
6472
- return { kind: target.kind, domain: target.domain.toLowerCase() };
6481
+ const domain = target.domain.toLowerCase();
6482
+ if (!isCanonicalEmailDomain(domain)) throw new TypeError("recipient email domain is invalid");
6483
+ return { kind: target.kind, domain };
6473
6484
  }
6474
6485
  function targetAuthorizationMethod(target) {
6475
6486
  return authorizationMethodForTarget(target);
@@ -6532,6 +6543,7 @@ async function publishTargetShare(input) {
6532
6543
  ...input.actions === void 0 ? {} : { actions: input.actions },
6533
6544
  target,
6534
6545
  expiresAt,
6546
+ expiryWasExplicit: input.expiryWasExplicit ?? input.expiresAt !== void 0,
6535
6547
  origin: input.origin,
6536
6548
  ...input.notify === void 0 ? {} : { notify: input.notify }
6537
6549
  });
@@ -6555,9 +6567,7 @@ function targetKind(target) {
6555
6567
  }
6556
6568
  function assertSafeInput(input) {
6557
6569
  if (!/^[A-Za-z0-9_-]{16,128}$/.test(input.shareId)) throw new TypeError("addressed share id is invalid");
6558
- if (input.filename.length === 0 || input.filename === "." || input.filename === ".." || /[/\\\u0000-\u001f\u007f]/.test(input.filename)) throw new TypeError("addressed filename is invalid");
6559
6570
  if (!Number.isSafeInteger(input.byteLength) || input.byteLength < 0 || input.byteLength > SHARE_CONTENT_LIMIT) throw new TypeError("addressed content length is invalid");
6560
- if (input.actions.length === 0 || input.policyActions.length === 0) throw new TypeError("addressed share actions are empty");
6561
6571
  if (!Number.isFinite(input.expiresAt.getTime()) || input.expiresAt.getTime() <= Date.now()) throw new TypeError("addressed share expiry must be in the future");
6562
6572
  if (input.artifact === "html" && (input.resource.kind !== "prefix" || !input.actions.includes("read") || !input.actions.includes("list"))) throw new TypeError("html artifacts require a readable prefix");
6563
6573
  if (input.contentSource.shareId !== input.shareId || input.contentSource.selector !== input.resource.kind) throw new TypeError("addressed content source is not bound to the share");
@@ -6650,23 +6660,55 @@ function publicationResult(input) {
6650
6660
  Object.defineProperty(result, "deliveryMaterial", { enumerable: false, value: input.deliveryMaterial });
6651
6661
  return result;
6652
6662
  }
6663
+ var EMAIL_PROFILE = { id: "tinycloud.email-proof/v1", version: 1 };
6653
6664
  var EMAIL_DOMAIN_PROFILE = { id: "tinycloud.email-domain-proof/v1", version: 1 };
6654
6665
  var EMAIL_CREDENTIAL_TYPE = { id: "opencredentials.email/v1", version: 1 };
6666
+ var EMAIL_DESCRIPTOR_DIGEST = "1tg-qphmKBVtNwzVg9xyz-xxqt_xtMXAsQyXw46m8S0";
6655
6667
  var EMAIL_DOMAIN_DESCRIPTOR_DIGEST = "33X5mAkZZgApdD3xh_T-3KS5moop0J2Nloi2nqWsdWY";
6656
- function assertEmailDomainPolicy(options, domain) {
6657
- if (!options.actions.every((action) => action === "read" || action === "list") || !options.policyActions.every((action) => action === "tinycloud.kv/get" || action === "tinycloud.kv/list" || action === "tinycloud.kv/metadata")) throw new TypeError("email-domain shares are view-only");
6658
- if (options.deliveryEmail !== void 0) throw new TypeError("email-domain shares are not emailed");
6659
- const commitment = options.credentialRequirement;
6660
- if (commitment === void 0) throw new TypeError("email-domain shares require a credential requirement");
6661
- if (canonicalize(commitment.profile) !== canonicalize(EMAIL_DOMAIN_PROFILE) || canonicalize(commitment.credentialType) !== canonicalize(EMAIL_CREDENTIAL_TYPE) || commitment.descriptorDigest !== EMAIL_DOMAIN_DESCRIPTOR_DIGEST) throw new TypeError("email-domain shares require the email-domain credential profile");
6662
- const expected = { type: "TinyCloudCredentialRequirement", version: 1, profile: EMAIL_DOMAIN_PROFILE, credentialType: EMAIL_CREDENTIAL_TYPE, claims: { emailDomain: domain }, maxAgeSeconds: 300 };
6663
- if (toBase64Url(sha2563(textEncoder.encode(canonicalize(expected)))) !== commitment.requirementDigest) throw new TypeError("credential requirement is not bound to the email domain");
6668
+ var EMAIL_CREDENTIAL_ISSUER_DID = "did:web:issuer.credentials.org";
6669
+ var EMAIL_CREDENTIAL_ISSUER_KID = `${EMAIL_CREDENTIAL_ISSUER_DID}#controller`;
6670
+ function mailboxCredentialCommitment(target) {
6671
+ const profile = target.kind === "email" ? EMAIL_PROFILE : EMAIL_DOMAIN_PROFILE;
6672
+ const requirement = target.kind === "email" ? { type: "TinyCloudCredentialRequirement", version: 1, profile, credentialType: EMAIL_CREDENTIAL_TYPE, claims: { email: target.address }, maxAgeSeconds: 3600 } : { type: "TinyCloudCredentialRequirement", version: 1, profile, credentialType: EMAIL_CREDENTIAL_TYPE, claims: { emailDomain: target.domain }, maxAgeSeconds: 300 };
6673
+ return {
6674
+ type: "TinyCloudPolicyCredentialRequirement",
6675
+ version: 1,
6676
+ requirementDigest: toBase64Url(sha2563(textEncoder.encode(canonicalize(requirement)))),
6677
+ descriptorDigest: target.kind === "email" ? EMAIL_DESCRIPTOR_DIGEST : EMAIL_DOMAIN_DESCRIPTOR_DIGEST,
6678
+ issuerDid: EMAIL_CREDENTIAL_ISSUER_DID,
6679
+ issuerKid: EMAIL_CREDENTIAL_ISSUER_KID,
6680
+ profile,
6681
+ credentialType: EMAIL_CREDENTIAL_TYPE
6682
+ };
6683
+ }
6684
+ function addressedCredentialRequirement(target) {
6685
+ const normalized = normalizeShareTarget(target);
6686
+ if (normalized.kind !== "email" && normalized.kind !== "emailDomain") throw new TypeError("a mailbox target is required");
6687
+ return mailboxCredentialCommitment(normalized);
6688
+ }
6689
+ function prepareAddressedShare(request) {
6690
+ if (request.filename.length === 0 || request.filename === "." || request.filename === ".." || /[/\\\u0000-\u001f\u007f]/.test(request.filename)) throw new TypeError("addressed filename is invalid");
6691
+ if (request.actions.length === 0 || request.policyActions.length === 0) throw new TypeError("addressed share actions are empty");
6692
+ const target = normalizeShareTarget(request.target);
6693
+ if (target.kind === "bearer") throw new TypeError("addressed target is required");
6694
+ if (target.kind === "recipientDid") return { target };
6695
+ if (target.kind === "emailDomain") {
6696
+ if (!request.actions.every((action) => action === "read" || action === "list") || !request.policyActions.every((action) => action === "tinycloud.kv/get" || action === "tinycloud.kv/list" || action === "tinycloud.kv/metadata")) throw new TypeError("email-domain shares are view-only");
6697
+ if (request.deliveryEmail !== void 0) throw new TypeError("email-domain shares are not emailed");
6698
+ }
6699
+ return { target, credentialRequirement: mailboxCredentialCommitment(target) };
6700
+ }
6701
+ function assertMailboxCommitment(commitment, target) {
6702
+ const label = target.kind === "email" ? "email" : "email-domain";
6703
+ if (commitment === void 0) throw new TypeError(`${label} shares require a credential requirement`);
6704
+ const expected = mailboxCredentialCommitment(target);
6705
+ if (canonicalize(commitment.profile) !== canonicalize(expected.profile) || canonicalize(commitment.credentialType) !== canonicalize(expected.credentialType) || commitment.descriptorDigest !== expected.descriptorDigest || commitment.issuerDid !== expected.issuerDid || commitment.issuerKid !== expected.issuerKid) throw new TypeError(`${label} shares require the ${label} credential profile`);
6706
+ if (commitment.requirementDigest !== expected.requirementDigest) throw new TypeError(`credential requirement is not bound to the email ${target.kind === "email" ? "address" : "domain"}`);
6664
6707
  }
6665
6708
  async function publishAddressedShare(options) {
6666
6709
  assertSafeInput(options);
6667
- const target = normalizeShareTarget(options.target);
6668
- if (target.kind === "bearer") throw new TypeError("addressed target is required");
6669
- if (target.kind === "emailDomain") assertEmailDomainPolicy(options, target.domain);
6710
+ const { target } = prepareAddressedShare(options);
6711
+ if (target.kind !== "recipientDid") assertMailboxCommitment(options.credentialRequirement, target);
6670
6712
  const expiry = rfc3339Seconds(options.expiresAt);
6671
6713
  const matcher = targetMatcher(target);
6672
6714
  const capabilities = sortCanonical([
@@ -7777,17 +7819,20 @@ var ShareNotifyError = class extends Error {
7777
7819
  };
7778
7820
  function recipientMatchesShareRecord(record, recipient) {
7779
7821
  const matcher = record.recipientMatcher;
7780
- if (matcher.kind === "bearer" || matcher.kind === "recipientDid") return false;
7781
- if (matcher.kind === "exactEmail") return matcher.value === recipient;
7782
- const at = recipient.lastIndexOf("@");
7783
- return at > 0 && recipient.slice(at + 1).toLowerCase() === matcher.value;
7822
+ const mailbox = canonicalMailbox(recipient);
7823
+ if (mailbox === void 0) return false;
7824
+ if (matcher.kind === "exactEmail") return canonicalMailbox(matcher.value)?.email === mailbox.email;
7825
+ if (matcher.kind === "emailDomain") return mailbox.domain === matcher.value;
7826
+ return false;
7784
7827
  }
7785
7828
  async function notifyShare(input) {
7786
- if (!input.shareId || !input.recipient || !input.recipient.includes("@")) throw new ShareNotifyError("recipient is invalid");
7787
- if (input.record !== void 0 && !recipientMatchesShareRecord(input.record, input.recipient)) {
7829
+ const mailbox = canonicalMailbox(input.recipient);
7830
+ if (!input.shareId || mailbox === void 0) throw new ShareNotifyError("recipient is invalid");
7831
+ const recipient = mailbox.email;
7832
+ if (input.record !== void 0 && !recipientMatchesShareRecord(input.record, recipient)) {
7788
7833
  throw new ShareNotifyError("recipient does not match the stored share target");
7789
7834
  }
7790
- const idempotencyKey = input.idempotencyKey ?? await defaultIdempotencyKey(input.shareId, input.recipient);
7835
+ const idempotencyKey = input.idempotencyKey ?? await defaultIdempotencyKey(input.shareId, recipient);
7791
7836
  const attemptsLimit = input.maxAttempts ?? 3;
7792
7837
  if (!Number.isSafeInteger(attemptsLimit) || attemptsLimit < 1 || attemptsLimit > 8) throw new ShareNotifyError("maxAttempts is invalid");
7793
7838
  let attempts = 0;
@@ -7796,7 +7841,7 @@ async function notifyShare(input) {
7796
7841
  if (input.signal?.aborted) throw new ShareNotifyError("share delivery was cancelled");
7797
7842
  attempts += 1;
7798
7843
  try {
7799
- const state = await input.adapter.deliver({ shareId: input.shareId, recipient: input.recipient, idempotencyKey, ...input.record === void 0 ? {} : { record: input.record }, ...input.signal === void 0 ? {} : { signal: input.signal } });
7844
+ 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 } });
7800
7845
  return { protocol: "tinycloud-share", version: 1, shareId: input.shareId, state, idempotencyKey, attempts };
7801
7846
  } catch (error) {
7802
7847
  lastError = error;
@@ -8479,7 +8524,11 @@ function canonicalViewerUrl(viewerOrigin) {
8479
8524
  async function createNativeShare(sharing, input) {
8480
8525
  if (!input.path || input.path.startsWith("/") || input.path.endsWith("/") || input.path.includes("..") || input.path.includes("//")) throw new TypeError("native share path must be one canonical TinyCloud KV key");
8481
8526
  const generated = await sharing.generate({ path: input.path, actions: ["tinycloud.kv/get"], expiry: input.expiresAt });
8482
- if (generated.ok !== true) throw new Error(typeof generated.error?.message === "string" ? generated.error.message : "TinyCloud sharing service rejected delegation generation");
8527
+ if (generated.ok !== true) {
8528
+ const error = new Error(typeof generated.error?.message === "string" ? generated.error.message : "TinyCloud sharing service rejected delegation generation");
8529
+ if (typeof generated.error?.code === "string") Object.assign(error, { code: generated.error.code });
8530
+ throw error;
8531
+ }
8483
8532
  if (typeof generated.data?.token !== "string" || typeof generated.data.delegation?.cid !== "string" || !(generated.data.expiresAt instanceof Date)) throw new Error("TinyCloud sharing service returned incomplete delegation metadata");
8484
8533
  const delegation = sharing.decodeLink(generated.data.token);
8485
8534
  if (typeof delegation.spaceId !== "string" || delegation.spaceId.length === 0 || typeof delegation.path !== "string" || delegation.path.length === 0) throw new Error("TinyCloud sharing service returned a non-canonical delegation authority");
@@ -8520,6 +8569,7 @@ export {
8520
8569
  SharePublishError,
8521
8570
  ShareReceiveError,
8522
8571
  ShareRecipientClient,
8572
+ addressedCredentialRequirement,
8523
8573
  authorizationMethodForTarget,
8524
8574
  authorizeShare,
8525
8575
  canonicalOwnerSharePolicy,
@@ -8542,6 +8592,7 @@ export {
8542
8592
  openNativeShare,
8543
8593
  parseAddressedEnvelope,
8544
8594
  parseNativeShareUrl,
8595
+ prepareAddressedShare,
8545
8596
  publishAddressedShare,
8546
8597
  publishPolicyShare,
8547
8598
  publishTargetShare,