@tinycloud/share-sdk 1.0.0-beta.6 → 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
@@ -590,6 +590,29 @@ interface AddressedSharePublishOptions {
590
590
  readonly onDeliveryMaterial?: (input: PublishedShareDeliveryMaterial) => void;
591
591
  readonly authority: AddressedPublishAuthority;
592
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. */
593
616
  declare function publishAddressedShare(options: AddressedSharePublishOptions): Promise<PublishedShare>;
594
617
 
595
618
  interface ShareCacheKey {
@@ -798,7 +821,11 @@ declare class ShareNotifyError extends Error {
798
821
  readonly code: "delivery-failed";
799
822
  constructor(message?: string);
800
823
  }
801
- /** 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
+ */
802
829
  declare function recipientMatchesShareRecord(record: SenderShareRecord, recipient: string): boolean;
803
830
  /**
804
831
  * Delivery is deliberately separate from publication. A failed notification
@@ -1093,4 +1120,4 @@ declare function parseNativeShareUrl(value: string): string;
1093
1120
  /** Receive through the public SDK without creating another transport protocol. */
1094
1121
  declare function openNativeShare(sharing: NativeSharingService, link: string): Promise<unknown>;
1095
1122
 
1096
- 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 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 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
@@ -590,6 +590,29 @@ interface AddressedSharePublishOptions {
590
590
  readonly onDeliveryMaterial?: (input: PublishedShareDeliveryMaterial) => void;
591
591
  readonly authority: AddressedPublishAuthority;
592
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. */
593
616
  declare function publishAddressedShare(options: AddressedSharePublishOptions): Promise<PublishedShare>;
594
617
 
595
618
  interface ShareCacheKey {
@@ -798,7 +821,11 @@ declare class ShareNotifyError extends Error {
798
821
  readonly code: "delivery-failed";
799
822
  constructor(message?: string);
800
823
  }
801
- /** 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
+ */
802
829
  declare function recipientMatchesShareRecord(record: SenderShareRecord, recipient: string): boolean;
803
830
  /**
804
831
  * Delivery is deliberately separate from publication. A failed notification
@@ -1093,4 +1120,4 @@ declare function parseNativeShareUrl(value: string): string;
1093
1120
  /** Receive through the public SDK without creating another transport protocol. */
1094
1121
  declare function openNativeShare(sharing: NativeSharingService, link: string): Promise<unknown>;
1095
1122
 
1096
- 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 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 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");
@@ -6430,12 +6445,6 @@ var base58flickr2 = baseX2({
6430
6445
  });
6431
6446
 
6432
6447
  // src/targets.ts
6433
- function validEmail(value) {
6434
- 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);
6435
- }
6436
- function validDomain(value) {
6437
- 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);
6438
- }
6439
6448
  function validRecipientDid(value) {
6440
6449
  if (value.length === 0 || value.length > 2048 || /[\u0000-\u0020\u007f]/.test(value)) return false;
6441
6450
  const parts = value.split(":");
@@ -6465,12 +6474,13 @@ function normalizeShareTarget(target) {
6465
6474
  return { kind: target.kind, did: target.did };
6466
6475
  }
6467
6476
  if (target.kind === "email") {
6468
- if (!validEmail(target.address)) throw new TypeError("recipient email is invalid");
6469
- const at = target.address.lastIndexOf("@");
6470
- 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 };
6471
6480
  }
6472
- if (!validDomain(target.domain)) throw new TypeError("recipient email domain is invalid");
6473
- 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 };
6474
6484
  }
6475
6485
  function targetAuthorizationMethod(target) {
6476
6486
  return authorizationMethodForTarget(target);
@@ -6557,9 +6567,7 @@ function targetKind(target) {
6557
6567
  }
6558
6568
  function assertSafeInput(input) {
6559
6569
  if (!/^[A-Za-z0-9_-]{16,128}$/.test(input.shareId)) throw new TypeError("addressed share id is invalid");
6560
- if (input.filename.length === 0 || input.filename === "." || input.filename === ".." || /[/\\\u0000-\u001f\u007f]/.test(input.filename)) throw new TypeError("addressed filename is invalid");
6561
6570
  if (!Number.isSafeInteger(input.byteLength) || input.byteLength < 0 || input.byteLength > SHARE_CONTENT_LIMIT) throw new TypeError("addressed content length is invalid");
6562
- if (input.actions.length === 0 || input.policyActions.length === 0) throw new TypeError("addressed share actions are empty");
6563
6571
  if (!Number.isFinite(input.expiresAt.getTime()) || input.expiresAt.getTime() <= Date.now()) throw new TypeError("addressed share expiry must be in the future");
6564
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");
6565
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");
@@ -6652,23 +6660,55 @@ function publicationResult(input) {
6652
6660
  Object.defineProperty(result, "deliveryMaterial", { enumerable: false, value: input.deliveryMaterial });
6653
6661
  return result;
6654
6662
  }
6663
+ var EMAIL_PROFILE = { id: "tinycloud.email-proof/v1", version: 1 };
6655
6664
  var EMAIL_DOMAIN_PROFILE = { id: "tinycloud.email-domain-proof/v1", version: 1 };
6656
6665
  var EMAIL_CREDENTIAL_TYPE = { id: "opencredentials.email/v1", version: 1 };
6666
+ var EMAIL_DESCRIPTOR_DIGEST = "1tg-qphmKBVtNwzVg9xyz-xxqt_xtMXAsQyXw46m8S0";
6657
6667
  var EMAIL_DOMAIN_DESCRIPTOR_DIGEST = "33X5mAkZZgApdD3xh_T-3KS5moop0J2Nloi2nqWsdWY";
6658
- function assertEmailDomainPolicy(options, domain) {
6659
- 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");
6660
- if (options.deliveryEmail !== void 0) throw new TypeError("email-domain shares are not emailed");
6661
- const commitment = options.credentialRequirement;
6662
- if (commitment === void 0) throw new TypeError("email-domain shares require a credential requirement");
6663
- 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");
6664
- const expected = { type: "TinyCloudCredentialRequirement", version: 1, profile: EMAIL_DOMAIN_PROFILE, credentialType: EMAIL_CREDENTIAL_TYPE, claims: { emailDomain: domain }, maxAgeSeconds: 300 };
6665
- 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"}`);
6666
6707
  }
6667
6708
  async function publishAddressedShare(options) {
6668
6709
  assertSafeInput(options);
6669
- const target = normalizeShareTarget(options.target);
6670
- if (target.kind === "bearer") throw new TypeError("addressed target is required");
6671
- if (target.kind === "emailDomain") assertEmailDomainPolicy(options, target.domain);
6710
+ const { target } = prepareAddressedShare(options);
6711
+ if (target.kind !== "recipientDid") assertMailboxCommitment(options.credentialRequirement, target);
6672
6712
  const expiry = rfc3339Seconds(options.expiresAt);
6673
6713
  const matcher = targetMatcher(target);
6674
6714
  const capabilities = sortCanonical([
@@ -7779,17 +7819,20 @@ var ShareNotifyError = class extends Error {
7779
7819
  };
7780
7820
  function recipientMatchesShareRecord(record, recipient) {
7781
7821
  const matcher = record.recipientMatcher;
7782
- if (matcher.kind === "bearer" || matcher.kind === "recipientDid") return false;
7783
- if (matcher.kind === "exactEmail") return matcher.value === recipient;
7784
- const at = recipient.lastIndexOf("@");
7785
- 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;
7786
7827
  }
7787
7828
  async function notifyShare(input) {
7788
- if (!input.shareId || !input.recipient || !input.recipient.includes("@")) throw new ShareNotifyError("recipient is invalid");
7789
- 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)) {
7790
7833
  throw new ShareNotifyError("recipient does not match the stored share target");
7791
7834
  }
7792
- const idempotencyKey = input.idempotencyKey ?? await defaultIdempotencyKey(input.shareId, input.recipient);
7835
+ const idempotencyKey = input.idempotencyKey ?? await defaultIdempotencyKey(input.shareId, recipient);
7793
7836
  const attemptsLimit = input.maxAttempts ?? 3;
7794
7837
  if (!Number.isSafeInteger(attemptsLimit) || attemptsLimit < 1 || attemptsLimit > 8) throw new ShareNotifyError("maxAttempts is invalid");
7795
7838
  let attempts = 0;
@@ -7798,7 +7841,7 @@ async function notifyShare(input) {
7798
7841
  if (input.signal?.aborted) throw new ShareNotifyError("share delivery was cancelled");
7799
7842
  attempts += 1;
7800
7843
  try {
7801
- 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 } });
7802
7845
  return { protocol: "tinycloud-share", version: 1, shareId: input.shareId, state, idempotencyKey, attempts };
7803
7846
  } catch (error) {
7804
7847
  lastError = error;
@@ -8526,6 +8569,7 @@ export {
8526
8569
  SharePublishError,
8527
8570
  ShareReceiveError,
8528
8571
  ShareRecipientClient,
8572
+ addressedCredentialRequirement,
8529
8573
  authorizationMethodForTarget,
8530
8574
  authorizeShare,
8531
8575
  canonicalOwnerSharePolicy,
@@ -8548,6 +8592,7 @@ export {
8548
8592
  openNativeShare,
8549
8593
  parseAddressedEnvelope,
8550
8594
  parseNativeShareUrl,
8595
+ prepareAddressedShare,
8551
8596
  publishAddressedShare,
8552
8597
  publishPolicyShare,
8553
8598
  publishTargetShare,