@openlup/platform 0.19.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +99 -0
- package/README.md +14 -6
- package/dist/shipping/bindings.d.ts +5 -0
- package/dist/shipping/bindings.js +12 -2
- package/dist/shipping/index.d.ts +14 -0
- package/dist/shipping/index.js +5 -0
- package/package.json +2 -2
- package/release-gates.json +2 -2
- package/sql/20261021200000_shipping_flat_rate_seed.sql +1 -0
- package/src/shipping/bindings.ts +18 -2
- package/src/shipping/index.ts +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,105 @@ SemVer promise.
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [0.20.0]
|
|
12
|
+
|
|
13
|
+
- Publishable on the npm `latest` dist-tag as `0.20.0`, from tag
|
|
14
|
+
`openlup-platform-v0.20.0`.
|
|
15
|
+
|
|
16
|
+
- Refresh release size-gate baselines from the published `0.19.0` tarballs; all caps remain unchanged.
|
|
17
|
+
|
|
18
|
+
- Keep active subscriptions active on portable dunning exhaustion (invariant repair).
|
|
19
|
+
|
|
20
|
+
Migration: apply the complete portable catalogue through
|
|
21
|
+
`20261021120000_dunning_lifecycle_active_repair.sql` at position 71. Previously,
|
|
22
|
+
NULL next retry expired the case and paused an active subscription; it now leaves
|
|
23
|
+
the case open and repairable, retains the final notice and exhaustion event, and
|
|
24
|
+
changes no subscription or cycle dates. Existing rows are not rewritten. Pass
|
|
25
|
+
NULL only when `isDunningLadderExhausted` holds; a class-terminated rung-one refusal
|
|
26
|
+
still must not be passed as NULL. There is no managed twin yet; the managed
|
|
27
|
+
baseline still needs a separate forward.
|
|
28
|
+
|
|
29
|
+
- Add the readiness-gated native flat-rate binding; the host supplies the named
|
|
30
|
+
role-free lane and fixed-key rate port, as in the reference composition.
|
|
31
|
+
- Require the native port and Core readiness for the shipping seed migration.
|
|
32
|
+
- Refuse missing-row saves; native audit remains explicitly unsupported and best effort.
|
|
33
|
+
|
|
34
|
+
Migration:
|
|
35
|
+
Apply the complete portable chain through 20261021200000_shipping_flat_rate_seed.
|
|
36
|
+
The seed preserves an existing rate and inserts zero only when absent; no ACL or
|
|
37
|
+
role changes are made. New code on an unmigrated schema keeps refusing. Older code
|
|
38
|
+
reads the seeded zero as it read an absent row. An application rollback does not reverse either forward
|
|
39
|
+
(positions 71 and 72), and older runners refuse the extended ledger.
|
|
40
|
+
Managed host-save authority remains pending.
|
|
41
|
+
|
|
42
|
+
- Add the shipping `SHIPPING_MIGRATIONS` export and the optional
|
|
43
|
+
`nativeRateReadiness` / `nativeRateSchema` binding dependencies.
|
|
44
|
+
|
|
45
|
+
Migration: upgrade the complete `@openlup/*` set from `0.19.0` to `0.20.0`
|
|
46
|
+
for exact internal pins. Native rate bindings require the selected port plus
|
|
47
|
+
Core readiness and a same-database schema observation of the applied seed.
|
|
48
|
+
Install the complete canonical migration catalogue, never sparse package
|
|
49
|
+
projections as an installation chain.
|
|
50
|
+
|
|
51
|
+
### Cumulative M06 status
|
|
52
|
+
|
|
53
|
+
- M06 remains incomplete: inventory and shipping are development-preview
|
|
54
|
+
surfaces, with managed-host proof classes pending.
|
|
55
|
+
- Inventory and shipping contracts, stock/ATP reads, reserve/release/expire
|
|
56
|
+
operations, subscription forecasts, delivery selection, address and flat-rate
|
|
57
|
+
handlers first shipped in `0.18.0`. Opt-in inventory/shipping/composition
|
|
58
|
+
bindings (P5a/P5b) first shipped in `0.19.0`. M06's only new behaviour in
|
|
59
|
+
`0.20.0` is native flat-rate save behind readiness; the portable dunning
|
|
60
|
+
invariant repair is separate from M06. Host-owned policy and unsupported
|
|
61
|
+
operations retain their explicit boundaries.
|
|
62
|
+
|
|
63
|
+
### Known limitations
|
|
64
|
+
|
|
65
|
+
- The portable dunning invariant repair has no managed twin in this set. The
|
|
66
|
+
managed baseline pauses active subscriptions on exhaustion; keeping them active
|
|
67
|
+
requires a separate managed forward. Portable proof does not establish managed parity.
|
|
68
|
+
|
|
69
|
+
- D8-1: native advisory v2 promo-code candidates and rejection details are not supported on the native backend.
|
|
70
|
+
- D8-2: native mounted v2 code issue/honor/fallback is not supported on the native backend.
|
|
71
|
+
- D8-3: acquisition-only mounted issuance/honor is not supported on the native backend.
|
|
72
|
+
- D8-4: full native/managed eligibility equivalence is not supported on the native backend.
|
|
73
|
+
- Bundle-1: independent database human-only actor-kind enforcement is not supported on the native backend and is the first item of a future native-backend parity round.
|
|
74
|
+
- Bundle-2: managed-equivalent actor-kind/email history is not supported on the native backend.
|
|
75
|
+
- Bundle-3 remains closed for M05 mounted admin/feed readback with an injected stock reader, while native new-purchase stock reads remain unsupported despite P5a's installed native inventory-store read proof.
|
|
76
|
+
- Bundle-4 establishes only incumbent real-PostgreSQL contention characterization and provides no exactly-once guarantee.
|
|
77
|
+
- The managed baseline schema and its pgTAP tests retain the incumbent legacy value `44.404`; removing it needs a forward migration and an owner decision, while reference composition supplies that value to application code.
|
|
78
|
+
- A1 evidence is offline only: account verification, hosted-time behaviour and owner TEST certification are not claimed, and the `communications/klaviyo` adapter's capabilities stay verification-pending.
|
|
79
|
+
- M05 parity seams are opt-in and omitted bindings preserve incumbent defaults, outputs, read order, scheduling, refusals, acceptance-token bytes and exported SQL.
|
|
80
|
+
- Native inventory adjustment remains unsupported; native address writes refuse
|
|
81
|
+
required-capability readiness. Native flat-rate save is supported only behind
|
|
82
|
+
the selected port, Core readiness and applied-seed schema observation.
|
|
83
|
+
- Native new-purchase stock read is deferred to the native-backend parity round
|
|
84
|
+
(owner 2026-10-21), second after M05 bundle-1; required readiness still refuses
|
|
85
|
+
honestly.
|
|
86
|
+
- Native shipping-rate save has no durable audit: audit is explicitly unsupported,
|
|
87
|
+
and the incumbent handler swallows the best-effort audit failure.
|
|
88
|
+
- Native flat-rate value bounds (integer, 0 <= value <= the host request schema's
|
|
89
|
+
maximum) are enforced by that schema, not a database CHECK; the reference
|
|
90
|
+
maximum is 100,000 minor units.
|
|
91
|
+
- Managed host ATP/forecast/dated-supply/pagination readback is not proved and
|
|
92
|
+
remains pending in the M06 ledger; no managed-host parity is claimed.
|
|
93
|
+
- Managed two-session lock order/concurrency and uncovered compensation paths
|
|
94
|
+
are not proved on a managed host and remain pending; no equivalence is claimed.
|
|
95
|
+
- Managed exact-prefix upgrade/ledger is not proved on a managed host and remains
|
|
96
|
+
pending; no managed installation equivalence is claimed.
|
|
97
|
+
- Managed address adapter idempotency/conflict/readback is not proved on a managed
|
|
98
|
+
host and remains pending; no fixture-to-host equivalence is claimed.
|
|
99
|
+
- Managed successful flat-rate read/save remains pending host authority and is
|
|
100
|
+
not proved on a managed host; no successful managed host-save claim is made.
|
|
101
|
+
- M06 adopter stock-wait lifecycle, durable subscription timing and staging
|
|
102
|
+
control observations retain their separate C5/C6 evidence gates. Busy/try-gate
|
|
103
|
+
protocol, durable stock-wait continuity and staging flag/TTL rows transferred
|
|
104
|
+
to C5 adopter evidence are dispositions, not PASS.
|
|
105
|
+
- Shipping contracts retain national-registry address fields and
|
|
106
|
+
`canonicalAddressKey` retains a locale-specific character fold. M16 owns their
|
|
107
|
+
move behind a host-supplied market pack with a canonical-key migration plan.
|
|
108
|
+
- Reference shipping UI copy remains locale-specific until M16.
|
|
109
|
+
|
|
11
110
|
## [0.19.0]
|
|
12
111
|
|
|
13
112
|
- Publishable on the npm `latest` dist-tag as `0.19.0`, from tag
|
package/README.md
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# @openlup/platform
|
|
2
2
|
|
|
3
|
-
Development preview. This package
|
|
3
|
+
Development preview. This package is part of the publishable set with core and outbox; preparation does not establish a registry release or a stable API. Its repository-directory publish command refuses publication; the authorized package-release workflow owns publication.
|
|
4
4
|
|
|
5
5
|
It holds the runnable server substrate an OpenLup application composes: the Node HTTP runtime, BFF dispatch, scheduling and job leases, blob storage, data gateways, the node-postgres migration runner and bundle composition. Ports and their contracts stay in `@openlup/core/platform-runtime`.
|
|
6
6
|
|
|
7
|
-
For the prepared `0.
|
|
8
|
-
limitations](CHANGELOG.md#
|
|
9
|
-
M06 composition bindings. M06
|
|
10
|
-
|
|
7
|
+
For the prepared `0.20.0` set, read the [adjacent-release migration and known
|
|
8
|
+
limitations](CHANGELOG.md#0200) before selecting the opt-in M05 parity seams or
|
|
9
|
+
M06 composition bindings. M06 remains incomplete: inventory and shipping entries
|
|
10
|
+
are development-preview surfaces, with managed-host proof classes pending in the
|
|
11
|
+
[M06 parity ledger](../../docs/platform/plans/oss-m06-stock-reservations-delivery.md#parity-pending-rows).
|
|
12
|
+
The size gate compares the prepared `0.20.0` set with the published `0.19.0` tarball;
|
|
11
13
|
preparation, offline adapter evidence and a passing size cap grant no publication
|
|
12
14
|
or provider-account certification.
|
|
13
15
|
|
|
@@ -37,13 +39,19 @@ or provider-account certification.
|
|
|
37
39
|
| `./pricing/contracts` | Dependency-free authority, money, quote and offer DTOs and version constants |
|
|
38
40
|
| `./promotions` | Experimental promotion application, admin handlers, native read/sweep, SQL projections and acceptance |
|
|
39
41
|
| `./promotions/contracts` | Dependency-free preview and admin DTOs |
|
|
40
|
-
| `./shipping` | Experimental delivery ports, injected-schema handlers, summary
|
|
42
|
+
| `./shipping` | Experimental delivery ports, injected-schema handlers, summary/evidence; native flat-rate port + Core schema readiness |
|
|
41
43
|
| `./shipping/contracts` | Type-only delivery, pickup-point, summary and evidence DTOs |
|
|
42
44
|
|
|
43
45
|
## Shipping
|
|
44
46
|
|
|
45
47
|
Shipping handlers require injected host schemas; contracts are type-only with opaque provider/carrier strings.
|
|
46
48
|
No vendor code, inventory import, activation or parity claim.
|
|
49
|
+
Native flat-rate save requires the rate port, a ready Core report and
|
|
50
|
+
`nativeRateSchema`, a same-database Core `SchemaObservation` proving the applied
|
|
51
|
+
seed identity and settings objects. A candidate schema label is not proof;
|
|
52
|
+
later forwards do not invalidate an applied seed. The reference host exposes
|
|
53
|
+
`observeNativeRateSchema()` for this ledger/object observation and retains
|
|
54
|
+
caller-declared schema requirements. Missing proof keeps the named refusal.
|
|
47
55
|
|
|
48
56
|
## Inventory
|
|
49
57
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ReadinessReport, SchemaObservation } from "@openlup/core/readiness";
|
|
1
2
|
import type { BffResponder } from "../bff/index.js";
|
|
2
3
|
import type { CustomerAddressBookPort, CustomerAddressMutationPort, CustomerAddressesDeps } from "./addressPorts.js";
|
|
3
4
|
import type { CustomerAddressSchemas } from "./addressSchemas.js";
|
|
@@ -16,6 +17,10 @@ type Store = {
|
|
|
16
17
|
export interface ShippingBindingDependencies {
|
|
17
18
|
dataKind: string;
|
|
18
19
|
createManagedStore?: () => Store | null;
|
|
20
|
+
/** Core report for the selected shipping contribution, observed by the host. */
|
|
21
|
+
nativeRateReadiness?: ReadinessReport;
|
|
22
|
+
/** Same-database Core observation of the applied shipping seed and required objects. */
|
|
23
|
+
nativeRateSchema?: SchemaObservation;
|
|
19
24
|
nativeStore?: Omit<Store, "addressMutationPort"> | null;
|
|
20
25
|
responder: BffResponder;
|
|
21
26
|
selection?: {
|
|
@@ -5,7 +5,17 @@ import { createDeliveryOptionsHandler, createPickupPointSearchHandler, createPic
|
|
|
5
5
|
export function createShippingBindings(deps) {
|
|
6
6
|
const native = deps.dataKind === "postgres";
|
|
7
7
|
const addressWrites = native ? "shipping_native_address_writes_unsupported" : null;
|
|
8
|
-
const
|
|
8
|
+
const nativeRateReady = typeof deps.nativeStore?.shippingRateDataPort?.getShippingFlatMinor === "function"
|
|
9
|
+
&& typeof deps.nativeStore?.shippingRateDataPort?.setShippingFlatMinor === "function"
|
|
10
|
+
&& typeof deps.nativeStore?.shippingRateDataPort?.recordPromotionAudit === "function"
|
|
11
|
+
&& deps.nativeRateReadiness?.state === "ready"
|
|
12
|
+
&& typeof deps.nativeRateReadiness.candidate?.database === "string"
|
|
13
|
+
&& deps.nativeRateReadiness.candidate.database.length > 0
|
|
14
|
+
&& deps.nativeRateSchema?.database === deps.nativeRateReadiness.candidate.database
|
|
15
|
+
&& deps.nativeRateSchema.version === "20261021200000_shipping_flat_rate_seed"
|
|
16
|
+
&& ["public.commerce_settings", "public.commerce_settings.value_minor", "public.commerce_settings.updated_at"].every(name => deps.nativeRateSchema?.objects?.some(entry => entry.present === true && entry.object?.name === name
|
|
17
|
+
&& entry.object.kind === (name === "public.commerce_settings" ? "table" : "column")));
|
|
18
|
+
const flatRateSave = native && !nativeRateReady ? "shipping_native_flat_rate_save_unsupported" : null;
|
|
9
19
|
const refused = (reason) => ({
|
|
10
20
|
store: {}, handlers: { options: null, search: null, validate: null, addresses: null, rate: null },
|
|
11
21
|
readiness: { ready: false, reason }, unsupported: { addressWrites, flatRateSave },
|
|
@@ -14,7 +24,7 @@ export function createShippingBindings(deps) {
|
|
|
14
24
|
return refused("shipping_store_incompatible");
|
|
15
25
|
if (native && deps.addresses?.requireWrites)
|
|
16
26
|
return refused(addressWrites);
|
|
17
|
-
if (native && deps.rate)
|
|
27
|
+
if (native && deps.rate && flatRateSave)
|
|
18
28
|
return refused(flatRateSave);
|
|
19
29
|
const selected = native ? deps.nativeStore : deps.createManagedStore?.();
|
|
20
30
|
if ((deps.addresses || deps.rate) && !selected)
|
package/dist/shipping/index.d.ts
CHANGED
|
@@ -18,3 +18,17 @@ export type { AdminShippingRateHandlerDeps, ShippingRateDataPort, ShippingRateHa
|
|
|
18
18
|
export { createShippingBindings, type ShippingBindingDependencies, type ShippingBindings } from "./bindings.js";
|
|
19
19
|
export type { ShippingTerms, ShippingPolicyEntry, ShippingPolicy, ShippingSettings } from "./contracts/threshold.js";
|
|
20
20
|
export { shippingTermsSchema, shippingPolicySchema, parseShippingTerms, hasShippingTerms, normalizeShippingPolicy, resolveShippingPolicy, resolveThresholdShipping } from "./thresholdPolicy.js";
|
|
21
|
+
/** Sparse canonical projections, never an install chain. */
|
|
22
|
+
export declare const SHIPPING_MIGRATIONS: readonly [{
|
|
23
|
+
readonly id: "20260807140000_read_parity_catalog";
|
|
24
|
+
readonly catalogPath: "db/platform/migrations/20260807140000_read_parity_catalog.sql";
|
|
25
|
+
readonly position: 1;
|
|
26
|
+
readonly sha256: "fcf3827028c1651ae42a7c7d7472153825a3121c936d58a3d105befc7dece9ea";
|
|
27
|
+
readonly url: URL;
|
|
28
|
+
}, {
|
|
29
|
+
readonly id: "20261021200000_shipping_flat_rate_seed";
|
|
30
|
+
readonly catalogPath: "db/platform/migrations/20261021200000_shipping_flat_rate_seed.sql";
|
|
31
|
+
readonly position: 72;
|
|
32
|
+
readonly sha256: "34f8696f515a2cc072395db5a3de2d9b09643d13236ee3851d0d78123f907eae";
|
|
33
|
+
readonly url: URL;
|
|
34
|
+
}];
|
package/dist/shipping/index.js
CHANGED
|
@@ -8,3 +8,8 @@ export { readAddresses, readOrdererProfiles, addressUsedByActiveSubscription, ad
|
|
|
8
8
|
export { createAdminShippingRateHandler } from "./adminShippingRateHandler.js";
|
|
9
9
|
export { createShippingBindings } from "./bindings.js";
|
|
10
10
|
export { shippingTermsSchema, shippingPolicySchema, parseShippingTerms, hasShippingTerms, normalizeShippingPolicy, resolveShippingPolicy, resolveThresholdShipping } from "./thresholdPolicy.js";
|
|
11
|
+
/** Sparse canonical projections, never an install chain. */
|
|
12
|
+
export const SHIPPING_MIGRATIONS = [
|
|
13
|
+
{ id: "20260807140000_read_parity_catalog", catalogPath: "db/platform/migrations/20260807140000_read_parity_catalog.sql", position: 1, sha256: "fcf3827028c1651ae42a7c7d7472153825a3121c936d58a3d105befc7dece9ea", url: new URL("../../sql/20260807140000_read_parity_catalog.sql", import.meta.url) },
|
|
14
|
+
{ id: "20261021200000_shipping_flat_rate_seed", catalogPath: "db/platform/migrations/20261021200000_shipping_flat_rate_seed.sql", position: 72, sha256: "34f8696f515a2cc072395db5a3de2d9b09643d13236ee3851d0d78123f907eae", url: new URL("../../sql/20261021200000_shipping_flat_rate_seed.sql", import.meta.url) },
|
|
15
|
+
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openlup/platform",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Runnable server substrate: Node HTTP runtime, BFF dispatch, scheduler, storage, data gateways and bundle composition; development preview.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"api:update": "npm run build && node --experimental-strip-types ./scripts/api-contract.ts --update"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@openlup/core": "0.
|
|
34
|
+
"@openlup/core": "0.20.0",
|
|
35
35
|
"pg": "^8.22.0",
|
|
36
36
|
"@aws-sdk/client-s3": "^3.1144.0",
|
|
37
37
|
"@types/pg": "^8.20.0"
|
package/release-gates.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
INSERT INTO public.commerce_settings (key, value_minor) VALUES ('shipping_flat_minor', 0) ON CONFLICT (key) DO NOTHING;
|
package/src/shipping/bindings.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ReadinessReport, SchemaObservation } from "@openlup/core/readiness";
|
|
1
2
|
import type { BffResponder } from "../bff/index.js";
|
|
2
3
|
import type { CustomerAddressBookPort, CustomerAddressMutationPort, CustomerAddressesDeps } from "./addressPorts.js";
|
|
3
4
|
import type { CustomerAddressSchemas } from "./addressSchemas.js";
|
|
@@ -17,6 +18,10 @@ type Store = {
|
|
|
17
18
|
export interface ShippingBindingDependencies {
|
|
18
19
|
dataKind: string;
|
|
19
20
|
createManagedStore?: () => Store | null;
|
|
21
|
+
/** Core report for the selected shipping contribution, observed by the host. */
|
|
22
|
+
nativeRateReadiness?: ReadinessReport;
|
|
23
|
+
/** Same-database Core observation of the applied shipping seed and required objects. */
|
|
24
|
+
nativeRateSchema?: SchemaObservation;
|
|
20
25
|
nativeStore?: Omit<Store, "addressMutationPort"> | null;
|
|
21
26
|
responder: BffResponder;
|
|
22
27
|
selection?: { port: DeliverySelectionPort; searchPort: PickupPointSearchPort; schemas: DeliverySelectionSchemas };
|
|
@@ -40,14 +45,25 @@ export interface ShippingBindings {
|
|
|
40
45
|
export function createShippingBindings(deps: ShippingBindingDependencies): ShippingBindings {
|
|
41
46
|
const native = deps.dataKind === "postgres";
|
|
42
47
|
const addressWrites = native ? "shipping_native_address_writes_unsupported" : null;
|
|
43
|
-
const
|
|
48
|
+
const nativeRateReady = typeof deps.nativeStore?.shippingRateDataPort?.getShippingFlatMinor === "function"
|
|
49
|
+
&& typeof deps.nativeStore?.shippingRateDataPort?.setShippingFlatMinor === "function"
|
|
50
|
+
&& typeof deps.nativeStore?.shippingRateDataPort?.recordPromotionAudit === "function"
|
|
51
|
+
&& deps.nativeRateReadiness?.state === "ready"
|
|
52
|
+
&& typeof deps.nativeRateReadiness.candidate?.database === "string"
|
|
53
|
+
&& deps.nativeRateReadiness.candidate.database.length > 0
|
|
54
|
+
&& deps.nativeRateSchema?.database === deps.nativeRateReadiness.candidate.database
|
|
55
|
+
&& deps.nativeRateSchema.version === "20261021200000_shipping_flat_rate_seed"
|
|
56
|
+
&& ["public.commerce_settings", "public.commerce_settings.value_minor", "public.commerce_settings.updated_at"].every(name =>
|
|
57
|
+
deps.nativeRateSchema?.objects?.some(entry => entry.present === true && entry.object?.name === name
|
|
58
|
+
&& entry.object.kind === (name === "public.commerce_settings" ? "table" : "column")));
|
|
59
|
+
const flatRateSave = native && !nativeRateReady ? "shipping_native_flat_rate_save_unsupported" : null;
|
|
44
60
|
const refused = (reason: string): ShippingBindings => ({
|
|
45
61
|
store: {}, handlers: { options: null, search: null, validate: null, addresses: null, rate: null },
|
|
46
62
|
readiness: { ready: false, reason }, unsupported: { addressWrites, flatRateSave },
|
|
47
63
|
});
|
|
48
64
|
if (!native && deps.dataKind !== "supabase") return refused("shipping_store_incompatible");
|
|
49
65
|
if (native && deps.addresses?.requireWrites) return refused(addressWrites!);
|
|
50
|
-
if (native && deps.rate) return refused(flatRateSave
|
|
66
|
+
if (native && deps.rate && flatRateSave) return refused(flatRateSave);
|
|
51
67
|
const selected: Store | null | undefined = native ? deps.nativeStore : deps.createManagedStore?.();
|
|
52
68
|
if ((deps.addresses || deps.rate) && !selected) return refused("shipping_store_required");
|
|
53
69
|
// Native address mutations remain unavailable even if an untyped host plants a writer.
|
package/src/shipping/index.ts
CHANGED
|
@@ -24,3 +24,9 @@ export type { AdminShippingRateHandlerDeps, ShippingRateDataPort, ShippingRateHa
|
|
|
24
24
|
export { createShippingBindings, type ShippingBindingDependencies, type ShippingBindings } from "./bindings.js";
|
|
25
25
|
export type { ShippingTerms, ShippingPolicyEntry, ShippingPolicy, ShippingSettings } from "./contracts/threshold.js";
|
|
26
26
|
export { shippingTermsSchema, shippingPolicySchema, parseShippingTerms, hasShippingTerms, normalizeShippingPolicy, resolveShippingPolicy, resolveThresholdShipping } from "./thresholdPolicy.js";
|
|
27
|
+
|
|
28
|
+
/** Sparse canonical projections, never an install chain. */
|
|
29
|
+
export const SHIPPING_MIGRATIONS = [
|
|
30
|
+
{ id: "20260807140000_read_parity_catalog", catalogPath: "db/platform/migrations/20260807140000_read_parity_catalog.sql", position: 1, sha256: "fcf3827028c1651ae42a7c7d7472153825a3121c936d58a3d105befc7dece9ea", url: new URL("../../sql/20260807140000_read_parity_catalog.sql", import.meta.url) },
|
|
31
|
+
{ id: "20261021200000_shipping_flat_rate_seed", catalogPath: "db/platform/migrations/20261021200000_shipping_flat_rate_seed.sql", position: 72, sha256: "34f8696f515a2cc072395db5a3de2d9b09643d13236ee3851d0d78123f907eae", url: new URL("../../sql/20261021200000_shipping_flat_rate_seed.sql", import.meta.url) },
|
|
32
|
+
] as const;
|