@01.software/sdk 0.71.0 → 0.73.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/README.md +71 -1
  3. package/dist/client.cjs +83 -9
  4. package/dist/client.cjs.map +1 -1
  5. package/dist/client.d.cts +6 -6
  6. package/dist/client.d.ts +6 -6
  7. package/dist/client.js +83 -9
  8. package/dist/client.js.map +1 -1
  9. package/dist/{collection-client-D18xyUq_.d.cts → collection-client-BH4dIZ6c.d.cts} +4 -4
  10. package/dist/{collection-client-CUGJcTpl.d.ts → collection-client-lLAl3xCZ.d.ts} +4 -4
  11. package/dist/{const-oGEoxCXZ.d.cts → const-BS2EaIp4.d.cts} +1 -1
  12. package/dist/{const-Dlu0mXmj.d.ts → const-CCvoknRY.d.ts} +1 -1
  13. package/dist/{index-HHVtIKXs.d.cts → index-CHdrzJ8-.d.cts} +3 -3
  14. package/dist/{index-Ccd4NYTL.d.ts → index-DVqNpmsc.d.ts} +3 -3
  15. package/dist/index.cjs +84 -10
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +14 -11
  18. package/dist/index.d.ts +14 -11
  19. package/dist/index.js +84 -10
  20. package/dist/index.js.map +1 -1
  21. package/dist/{payload-types-BgOEk6Y9.d.cts → payload-types-PXkmefhZ.d.cts} +267 -185
  22. package/dist/{payload-types-BgOEk6Y9.d.ts → payload-types-PXkmefhZ.d.ts} +267 -185
  23. package/dist/query.d.cts +5 -5
  24. package/dist/query.d.ts +5 -5
  25. package/dist/realtime.d.cts +2 -2
  26. package/dist/realtime.d.ts +2 -2
  27. package/dist/server.cjs +113 -17
  28. package/dist/server.cjs.map +1 -1
  29. package/dist/server.d.cts +8 -7
  30. package/dist/server.d.ts +8 -7
  31. package/dist/server.js +113 -17
  32. package/dist/server.js.map +1 -1
  33. package/dist/{types-CSvp2fJ_.d.ts → types-CQRsG6sA.d.ts} +2 -2
  34. package/dist/{types-DLHEIsAx.d.cts → types-Chwgg4CQ.d.cts} +63 -7
  35. package/dist/{types-BzG3NO7R.d.cts → types-CyMz0Kzc.d.cts} +2 -2
  36. package/dist/{types-nyOvcO0K.d.ts → types-lbzbJSZh.d.ts} +63 -7
  37. package/dist/ui/form.d.cts +1 -1
  38. package/dist/ui/form.d.ts +1 -1
  39. package/dist/ui/video.d.cts +1 -1
  40. package/dist/ui/video.d.ts +1 -1
  41. package/dist/webhook.d.cts +5 -5
  42. package/dist/webhook.d.ts +5 -5
  43. package/package.json +2 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,123 @@
1
1
  # @01.software/sdk
2
2
 
3
+ ## 0.73.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 57e6e15: Sort product options and option values by their orderable `_order` keys in Payload's fractional-indexing (code-unit) order instead of the runtime-locale-dependent `localeCompare` order. For current-format keys this is the order the Admin Panel shows.
8
+ - 623b7e8: Update the generated field descriptions for the tenant base currency and the market exchange rate.
9
+ - 265ad09: Synchronize generated storage types for internal Project invitations and private
10
+ current-email verification evidence. No invitation SDK API or collection access
11
+ is added.
12
+
13
+ ## 0.73.0
14
+
15
+ ### Minor Changes
16
+
17
+ - b271588: Add optional market selection to events.getAdmissionAvailability so callers can display the same market price used by Cart and Checkout. Omitted market uses the catalog default; the public price response keeps its existing fields. Resolved-market reads, including default-market calls, omit admission types whose same-tenant products are not assigned to that market.
18
+ - 41c7d41: Add server-only `memberships.billingCustodyContext` to obtain the Console-owned
19
+ restore generation through the existing delegated HMAC custody boundary. Keep
20
+ legacy ciphertext requests and responses compatible. Deploy Console support
21
+ before publishing the SDK or using the updated Membership and CLUB templates.
22
+ The bundled starters obtain the generation from Console without a storefront
23
+ environment variable and retain the generation across custody read/CAS updates.
24
+
25
+ ### Patch Changes
26
+
27
+ - 163b450: Clarify that form submission email settings are retained for compatibility and do not send notifications, without changing field keys or types.
28
+ - ae622d1: Refresh generated workspace sender, credential, and webhook field descriptions. Public types and API behavior are unchanged.
29
+ - f8a25e1: Clarify that tenant administrators obtain the billing custody restore generation from the authenticated Console delegated billing connection panel.
30
+ - 9cfcc4e: Update generated User membership guidance to point Project workspace member management to Settings > Workspace > Project environments. No SDK type shape or runtime behavior changes.
31
+ - b8a447c: Clarify generated transaction kind and shipping policy descriptions without changing field keys or types.
32
+ - 4781438: Clarify the generated customer address description. Field types and API response shapes are unchanged.
33
+ - 3d0665d: Clarify the generated preview destination description without changing its schema or behavior.
34
+ - 668102b: Webhook.url 필드 설명의 민감정보 경고를 복원합니다. 타입 구조는 변경하지 않습니다.
35
+ - 5ef9bc6: Format the numbers in the `Monthly API usage limit exceeded (current/limit)` error message with a fixed `en-US` locale so the message no longer depends on the runtime's default locale.
36
+
37
+ ## 0.72.1
38
+
39
+ ### Patch Changes
40
+
41
+ - bbcdc03: Clarify generated event occurrence identity and community comment-setting descriptions in operator-facing wording. Types, field access, and response shapes are unchanged.
42
+ - 327779c: Clarify generated JSDoc for event admission sale windows and usage rate card effective windows after adding date and time pickers in the Admin Panel. Stored instants, SDK runtime behavior, and public API shape remain unchanged.
43
+ - 2075d27: Clarify the generated event registration-list description with operator-facing wording. Types, field access, and response shapes are unchanged.
44
+ - 2990468: Correct the generated event `externalSource` description comment: provider, source ID, and URL can all appear in public read responses. Field access and response shapes are unchanged.
45
+ - 055671d: Clarify generated commerce field descriptions in operator-facing wording. Types, field access, and response shapes are unchanged.
46
+ - 5581c60: Clarify generated event field descriptions for admission quantity limits, attendee privacy, and public API visibility.
47
+ - 5138b42: Clarify generated customer and membership field descriptions without changing field keys or types.
48
+ - 269db8b: Refresh generated Payload type descriptions for workspace and platform operator guidance.
49
+ - 9ec8504: Update generated type description comments without changing request or response shapes. The server applies the calendar timezone when a non-duplicate event create omits timezone.
50
+ - 15e5dc6: Restore privacy, entitlement lifecycle and validation, usage aggregation, and webhook idempotency details in generated field descriptions.
51
+ - 1c23d29: Document the membership delegated billing connection in generated payment credential types.
52
+ - 3b47cff: Clarify generated Product `markets` JSDoc: new products without markets receive the active default market if one exists, and removing every market from an existing product excludes it from market catalogs. Runtime behavior and public API shape remain unchanged.
53
+
54
+ ## 0.72.0
55
+
56
+ ### Minor Changes
57
+
58
+ - 756ca0b: Document the owner-approved multi-currency reporting correction for server-only
59
+ customer `lifetimeValue`: retain `number | null`, sum only a verified single
60
+ currency, and return `null` for mixed or unavailable currencies (zero orders
61
+ remain `0`). No new SDK field or webhook envelope is introduced and persisted
62
+ webhook bytes are unchanged. This minor records the public behavior correction
63
+ under [the #7859 owner decision](https://github.com/01-office/01-software/issues/7859#issuecomment-6540676116),
64
+ even though the generated property type is unchanged.
65
+ - 181d5ee: **Additive response arms (0.x minor).** `server.commerce.cancelOrder()` can now
66
+ return the registered managed Toss outcome (ADR 0073). When the paid order was
67
+ captured through a Console payment connection, Console refunds it after the
68
+ local cancel commits and the response carries
69
+ `managedRefund: { outcome: 'completed' | 'convergence_pending' | 'operator_required' }`
70
+ with `providerRefunded` and the refunded amount, never `refundPending`. Do not
71
+ run a storefront or BFF provider refund for these responses: retries read or
72
+ resume the same Console refund. An exhaustive check over `CancelOrderResponse`
73
+ needs the two new arms (`CancelOrderManagedCommittedResponse`,
74
+ `CancelOrderManagedAlreadyCanceledResponse`).
75
+
76
+ Import both response arms and `ManagedCancelRefundOutcome` as types from
77
+ `@01.software/sdk`, alongside `CancelOrderResponse`.
78
+
79
+ Custom bridge, legacy, PortOne, and credit-funded orders keep the existing
80
+ `refundPending` handoff unchanged.
81
+
82
+ - cf8e6d5: **BREAKING (0.x minor).** Prepare strict readers for the reserved `'stripe'`
83
+ managed provider before the server can emit it.
84
+ `CheckoutPaymentSessionRef['provider']` widens to
85
+ `'toss' | 'portone' | 'stripe'`, so an exhaustive `switch` over it needs a
86
+ `'stripe'` case. Earlier SDK versions reject a `'stripe'` reference as an
87
+ invalid canonical response; upgrade every consumer that reads Checkouts before
88
+ Stripe becomes available.
89
+
90
+ Checkout references accept `provider: 'stripe'`. PaymentSession methods
91
+ (`create`, `createPortOne`, `retrieve`, `retrievePortOne`, `cancel`,
92
+ `cancelPortOne` and server `confirm`) reject a Stripe session after validating
93
+ it completely, including the strict Stripe Payment Element action
94
+ (`stripe_payment_element` with `clientSecret`, `publishableKey` and a
95
+ credential-free HTTPS or loopback `returnUrl`), and report a generic invalid response with
96
+ `details.expected` and `details.actual`. Partial or unknown action fields are
97
+ rejected. Stripe is not available yet and the SDK adds no Stripe PaymentSession
98
+ method. Toss, PortOne and custom bridge behavior, including custom provider
99
+ names, is unchanged.
100
+
101
+ ### Patch Changes
102
+
103
+ - 88bee51: Clarify the generated admission type price-reference guidance: the reference is optional when saving and required for sales. The generated field type and public API behavior are unchanged.
104
+ - 9f326b5: Synchronize generated collection and calendar field descriptions with neutral Console copy for workspace menu display names. Type shapes, runtime behavior, and API titles are unchanged.
105
+ - 1d03497: Clarify the generated documentation for membership payment results that were not applied at the time they were received.
106
+ - 931d8a0: Clarify generated Discount type descriptions for code usage counts, pending checkout reservations, and unsupported allocation repair guidance.
107
+ - 1a6e310: Restore the read-only note in the generated Discount `usesCount` type description.
108
+ - 2f4989e: Synchronize generated EventRegistration types with the reordered registration fields (status, attendance, and quantity now come first). Only property order changes; SDK runtime behavior, collection buckets, request inputs, and public responses remain unchanged. Separately, Console now reads `event-occurrences` newest `startsAt` first when a request omits `sort`; pass `sort` explicitly if you depend on a specific order.
109
+ - 4db606a: Clarify the generated membership plan description comment to reflect its inclusion in public query responses for active plans. Field access and response shapes are unchanged.
110
+ - b43cb9c: Synchronize generated Order and Checkout types with the internal Checkout `source` field and the internal `in_person` Order source value. SDK runtime behavior, collection buckets, request inputs, and public responses remain unchanged.
111
+ - ba3ffc2: Synchronize generated FulfillmentOrder and Fulfillment types with the internal, access-closed `method` field. SDK runtime behavior, collection buckets, request inputs, and public responses remain unchanged.
112
+ - c246a93: Clarify generated Customer field descriptions for linked sign-in providers and password change times. Types and runtime behavior are unchanged.
113
+ - 6b9d1ab: Use neutral short-summary comments in generated Payload types without prescribing where tenant apps display descriptions.
114
+ - 8ae95f0: Give the SDK declaration build a bounded 4 GiB heap so release preparation can complete on hosted runners.
115
+ - 2be5e90: Remove unused package-local prerelease publishing commands. Package publication continues through the owner-dispatched trusted publishing workflow.
116
+ - f776ca2: Clarify the generated Return field descriptions for return details, cancellation actors, refund receipts, and original shipping refunds.
117
+ - e1ba296: Synchronize generated PaymentSession types with the private, nullable Standard long-tail detection history field. SDK runtime behavior, collection buckets, and public projections remain unchanged.
118
+ - 9159e72: Clarify the generated customer type documentation for server-recorded hosted consent history. Runtime behavior and public type shapes are unchanged.
119
+ - 9a92a2d: Update generated collection descriptions to match the Console coupon navigation and explain checkout discounts and redemption coupon definitions. Public types and runtime behavior are unchanged.
120
+
3
121
  ## 0.71.0
4
122
 
5
123
  ### Minor Changes
package/README.md CHANGED
@@ -933,6 +933,32 @@ request UUID and the current version; exact retries retain the original values.
933
933
  A privacy-erased snapshot has state `erased`, null `externalCustomerId`, and
934
934
  null `previousState`. Keep these calls and snapshots in trusted server code.
935
935
 
936
+ ### Delegated billing ciphertext
937
+
938
+ The server client obtains the Console-owned restore generation through the
939
+ existing custody endpoint, using its server key and delegated connection HMAC:
940
+
941
+ ```ts
942
+ const { generation } = await server.memberships.billingCustodyContext({
943
+ membershipId,
944
+ webhookSecret,
945
+ })
946
+ const stored = await server.memberships.billingCustody({
947
+ action: 'read',
948
+ membershipId,
949
+ webhookSecret,
950
+ generation,
951
+ })
952
+ ```
953
+
954
+ Keep that generation and `stored.version` for mutations based on this read.
955
+ Obtain a context immediately before a fresh initial upload (`expectedVersion: 0`).
956
+ Generation mismatch stops execution; never fetch a new context to retry an old
957
+ mutation or charge. After recovery, provider re-authorization and a fresh encrypted
958
+ upload/readback are required. Existing explicit-generation requests remain
959
+ supported. Deploy Console support before SDK publication and upgraded template
960
+ use; unsupported servers and malformed contexts fail without fallback.
961
+
936
962
  ## Storefront performance defaults
937
963
 
938
964
  - **PLP:** prefer `commerce.product.listingPage()` or `useProductListingPage()` (GET `/api/products/listing-groups/query/catalog`, CDN-cacheable, card-ready). Use `listingGroupsCatalog({ productIds })` only when IDs are already known. Treat the full listing-groups response shape as a server-auth escape hatch because it can include operational stock fields. Avoid fetching a product list and then calling `detail()` per card.
@@ -959,6 +985,12 @@ Refund and refund-line-item collection reads remain server-only. Their public
959
985
  types and native reads omit private funding fields, including populated refund
960
986
  relationships. Generated storage types do not grant access to those fields.
961
987
 
988
+ Server-only customer documents and customer-update webhooks retain
989
+ `lifetimeValue?: number | null`. The scalar sums original order totals only
990
+ for one verified registry currency with a numeric exponent; mixed or unavailable
991
+ currencies yield `null`, and no contributing orders yield `0`. Currency bucket
992
+ fields are not added. Existing webhook bodies and replay bytes stay unchanged.
993
+
962
994
  ### `depth` — how deep to populate relationship fields
963
995
 
964
996
  `depth` is the primary control for populating relationships like `category`, `images`, `brand`. Browser publishable-key raw collection reads are constrained to `depth: 0` with `joins: false` and no `populate`; relationship-rich storefront reads should use shaped helpers such as `commerce.product.detail()` / `listingPage()`, or a `createServerClient()` raw query when server credentials are appropriate. Browser SDK raw reads add those safe defaults automatically and reject relationship-expanded raw read options before making a request.
@@ -1623,7 +1655,11 @@ Cart add/update/remove/clear/discount/attribute mutations additionally require
1623
1655
  the last observed `cart.revision` as `expectedRevision`. A
1624
1656
  `cart_revision_conflict` means refetch the Cart and start a new logical mutation
1625
1657
  with a new idempotency key. Cart merge requires the key but not a single revision
1626
- because it atomically resolves two current Cart states.
1658
+ because it atomically resolves two current Cart states. Merging a Cart the
1659
+ customer already owns returns `resolution: 'unchanged'` and writes nothing, so
1660
+ the revision you last observed stays valid for the next mutation. Because it
1661
+ writes nothing, such a merge does not count as Cart activity for stale-Cart
1662
+ cleanup.
1627
1663
  Treat a replayed Cart result as an operation receipt: never replace a newer
1628
1664
  cached Cart with a lower `revision`; retrieve when response ordering is unclear.
1629
1665
 
@@ -1779,6 +1815,16 @@ authoritative API response or signed webhook, then report the exact captured
1779
1815
  identity and Money. The create response is intentionally limited to
1780
1816
  `{ id, provider, providerSessionId, money }`.
1781
1817
 
1818
+ The closed managed provider vocabulary is `'toss' | 'portone' | 'stripe'`.
1819
+ `'stripe'` is reserved so that consumers upgrade before the server can emit it:
1820
+ Checkout references accept `provider: 'stripe'`, while the PaymentSession
1821
+ methods (`create`, `createPortOne`, `retrieve`, `retrievePortOne`, `cancel`,
1822
+ `cancelPortOne`, and server `confirm`) reject a Stripe session after validating
1823
+ it completely, with a generic invalid-response error carrying
1824
+ `details.expected` and `details.actual`. Stripe is not available yet, and the
1825
+ SDK has no Stripe PaymentSession method. Custom bridge provider names are a
1826
+ separate namespace and are unaffected.
1827
+
1782
1828
  Custom bridge sessions intentionally remain `null` in
1783
1829
  `checkout.paymentState.activePaymentSession`: Checkout exposes only managed
1784
1830
  adapters from its closed provider vocabulary. Persist the `providerSessionId`
@@ -1926,6 +1972,16 @@ Do not infer the external lane from a defaulted `sessionOrigin`, an
1926
1972
  captures must use Console's refund operation; `resolveCancelRefund` remains
1927
1973
  only for the two external-drain rows above.
1928
1974
 
1975
+ For a registered managed Toss capture without customer credit, `cancelOrder()`
1976
+ no longer returns `refundPending`: Console refunds the payment after the local
1977
+ cancel commits and returns `managedRefund.outcome`. `completed` means the
1978
+ provider refund and the cancel refund ledger are committed;
1979
+ `convergence_pending` means Console still owns the refund and continues it;
1980
+ `operator_required` means it needs operator review in Console. Treat all three
1981
+ as a committed cancellation and never start a provider refund from your
1982
+ storefront or BFF. A retry reads or resumes the same Console refund. Registered
1983
+ PortOne and credit-funded managed orders still return the pending marker.
1984
+
1929
1985
  Managed ownership follows the captured Transaction's exact tenant-bound
1930
1986
  PaymentSession and historical registered account. Order/provider/environment
1931
1987
  drift remains Console-owned corruption. Unresolved or cross-tenant identity
@@ -2298,6 +2354,20 @@ replacement API. Pass an empty list to clear codes. Singular `admission`,
2298
2354
  Browser `mine()`/`merge({ guestCartToken })` derive customer identity from the
2299
2355
  JWT; server calls require an explicit `customerToken`.
2300
2356
 
2357
+ ### Event admission availability
2358
+
2359
+ For paid admission choices, call
2360
+ `client.events.getAdmissionAvailability({ occurrence, market: 'kr' })` with an
2361
+ active market handle or id. Omit `market` for the catalog default. The public
2362
+ price includes `amount`, `compareAtPrice`, `currency`, and `marketId` resolved
2363
+ from fixed market prices or the market calculation; an unknown market returns
2364
+ `404 not_found`. Use the same market for the Cart. Checkout re-reads current
2365
+ pricing and eligibility. When a market resolves, admission types are returned
2366
+ only when their same-tenant product is assigned to that market. This filter also
2367
+ applies to existing calls that omit `market` and use the default market; missing
2368
+ products and empty assignments are omitted. With no active market, base pricing
2369
+ and the existing unfiltered behavior remain.
2370
+
2301
2371
  ### Customer event registration history
2302
2372
 
2303
2373
  After customer sign-in, `client.events.listMyRegistrations({ page: 1, limit: 10 })`
package/dist/client.cjs CHANGED
@@ -896,7 +896,7 @@ async function httpFetch(url, options) {
896
896
  );
897
897
  const usageError = attachRequestId(
898
898
  createUsageLimitError(
899
- `Monthly API usage limit exceeded (${current.toLocaleString()}/${limit.toLocaleString()})`,
899
+ `Monthly API usage limit exceeded (${current.toLocaleString("en-US")}/${limit.toLocaleString("en-US")})`,
900
900
  { limit, current, remaining },
901
901
  {
902
902
  url,
@@ -2613,7 +2613,18 @@ var ABANDONED_REASONS = ["expired", "customer", "operator"];
2613
2613
  function managedPaymentProviders(providers) {
2614
2614
  return providers;
2615
2615
  }
2616
- var PAYMENT_PROVIDERS = managedPaymentProviders(["toss", "portone"]);
2616
+ var PAYMENT_PROVIDERS = managedPaymentProviders([
2617
+ "toss",
2618
+ "portone",
2619
+ "stripe"
2620
+ ]);
2621
+ var CANCEL_RECOVERY_METHODS = {
2622
+ toss: "cancel()",
2623
+ portone: "cancelPortOne()",
2624
+ stripe: null
2625
+ };
2626
+ var STRIPE_RETURN_URL_RAW_CHARACTERS = /^[^\s\u0000-\u001F\u007F\\]+$/;
2627
+ var STRIPE_RETURN_URL_AUTHORITY = /^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^/?#@]+(?:[/?#]|$)/;
2617
2628
  var PAYMENT_PROVIDER_STATUSES = [
2618
2629
  "requires_payment_method",
2619
2630
  "requires_action",
@@ -2662,11 +2673,8 @@ function fail(resource, path, expected) {
2662
2673
  invalidCanonicalResponse(resource, { path, expected });
2663
2674
  }
2664
2675
  function providerMismatch(resource, expected, actual, operation2) {
2665
- if (operation2 === "cancel") {
2666
- const method = {
2667
- toss: "cancel()",
2668
- portone: "cancelPortOne()"
2669
- }[actual];
2676
+ const method = CANCEL_RECOVERY_METHODS[actual];
2677
+ if (operation2 === "cancel" && method !== null) {
2670
2678
  throw createApiError(
2671
2679
  `Canonical ${resource} response provider mismatch: expected ${expected}, received ${actual}.`,
2672
2680
  502,
@@ -3910,6 +3918,65 @@ function validateRequiredReconciliation(value, allowed, resource, path) {
3910
3918
  }
3911
3919
  function validateNextAction(value, provider, resource, path) {
3912
3920
  const action = record(value, resource, path);
3921
+ if (provider === "stripe") {
3922
+ exact(
3923
+ action,
3924
+ ["type", "clientSecret", "publishableKey", "returnUrl"],
3925
+ [],
3926
+ resource,
3927
+ path
3928
+ );
3929
+ if (action.type !== "stripe_payment_element")
3930
+ fail(resource, `${path}.type`, "stripe_payment_element");
3931
+ const clientSecret = boundedString(
3932
+ action.clientSecret,
3933
+ 255,
3934
+ resource,
3935
+ `${path}.clientSecret`
3936
+ );
3937
+ if (!/^pi_[A-Za-z0-9]+_secret_[A-Za-z0-9]+$/.test(clientSecret)) {
3938
+ fail(
3939
+ resource,
3940
+ `${path}.clientSecret`,
3941
+ "Stripe PaymentIntent client secret"
3942
+ );
3943
+ }
3944
+ const publishableKey = boundedString(
3945
+ action.publishableKey,
3946
+ 255,
3947
+ resource,
3948
+ `${path}.publishableKey`
3949
+ );
3950
+ if (!/^pk_(?:test|live)_[A-Za-z0-9]+$/.test(publishableKey)) {
3951
+ fail(resource, `${path}.publishableKey`, "Stripe publishable key");
3952
+ }
3953
+ const returnUrl = boundedString(
3954
+ action.returnUrl,
3955
+ 2048,
3956
+ resource,
3957
+ `${path}.returnUrl`
3958
+ );
3959
+ if (!STRIPE_RETURN_URL_RAW_CHARACTERS.test(returnUrl) || !STRIPE_RETURN_URL_AUTHORITY.test(returnUrl)) {
3960
+ fail(
3961
+ resource,
3962
+ `${path}.returnUrl`,
3963
+ "HTTPS or loopback URL without embedded credentials"
3964
+ );
3965
+ }
3966
+ try {
3967
+ const parsed = new URL(returnUrl);
3968
+ const loopback = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1");
3969
+ if (!loopback && parsed.protocol !== "https:" || parsed.username || parsed.password)
3970
+ throw new Error("unsafe return URL");
3971
+ } catch {
3972
+ fail(
3973
+ resource,
3974
+ `${path}.returnUrl`,
3975
+ "HTTPS or loopback URL without embedded credentials"
3976
+ );
3977
+ }
3978
+ return;
3979
+ }
3913
3980
  if (provider === "portone") {
3914
3981
  if (action.type === "portone_sdk") {
3915
3982
  const hasCancelable = "cancelable" in action;
@@ -4285,7 +4352,7 @@ function validatePublicPaymentSession(value, expectedProvider, operation2) {
4285
4352
  );
4286
4353
  }
4287
4354
  if (expectedProvider !== void 0 && provider !== expectedProvider) {
4288
- if (operation2 === "cancel" && status !== "canceling" && status !== "canceled") {
4355
+ if (operation2 === "cancel" && CANCEL_RECOVERY_METHODS[provider] !== null && status !== "canceling" && status !== "canceled") {
4289
4356
  fail(
4290
4357
  resource,
4291
4358
  "$.providerStatus",
@@ -5546,6 +5613,11 @@ function getRelationID(value) {
5546
5613
  }
5547
5614
  return void 0;
5548
5615
  }
5616
+ function compareOrdinal(left, right) {
5617
+ if (left < right) return -1;
5618
+ if (left > right) return 1;
5619
+ return 0;
5620
+ }
5549
5621
  function extractEntityId(value) {
5550
5622
  if (typeof value === "string") return value;
5551
5623
  if (typeof value === "number") return String(value);
@@ -6158,7 +6230,7 @@ function compareVariantOrder(a, b) {
6158
6230
  }
6159
6231
  const aId = String(getRelationID(a.id) ?? "");
6160
6232
  const bId = String(getRelationID(b.id) ?? "");
6161
- return aId.localeCompare(bId);
6233
+ return compareOrdinal(aId, bId);
6162
6234
  }
6163
6235
  function getVariantAvailableForSale(variant) {
6164
6236
  if (variant.isActive === false) return false;
@@ -6763,6 +6835,8 @@ function buildRangeEndpoint(params) {
6763
6835
  function buildAdmissionAvailabilityEndpoint(params) {
6764
6836
  const urlParams = new URLSearchParams();
6765
6837
  urlParams.set("occurrence", params.occurrence);
6838
+ const normalizedMarket2 = params.market?.trim();
6839
+ if (normalizedMarket2) urlParams.set("market", normalizedMarket2);
6766
6840
  return resolveOperationPath(
6767
6841
  EVENTS_ENDPOINT_OPERATIONS.occurrences.admissionAvailability,
6768
6842
  { query: urlParams }