@openlup/platform 0.24.0 → 0.25.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 +109 -210
- package/README.md +40 -11
- package/dist/communications/contracts/subscriptionPaymentExpired.d.ts +3 -2
- package/dist/communications/contracts/subscriptionPaymentExpired.js +1 -1
- package/dist/communications/contracts/subscriptionPaymentFailed.d.ts +4 -3
- package/dist/communications/contracts/subscriptionPaymentFailed.js +4 -5
- package/dist/composition/index.d.ts +1 -0
- package/dist/composition/index.js +1 -0
- package/dist/composition/subscriptionContribution.d.ts +18 -0
- package/dist/composition/subscriptionContribution.js +19 -0
- package/dist/inventory/index.d.ts +2 -0
- package/dist/inventory/index.js +1 -0
- package/dist/inventory/postgresStockAvailability.d.ts +24 -0
- package/dist/inventory/postgresStockAvailability.js +48 -0
- package/dist/subscriptions/commandExamples.d.ts +6 -0
- package/dist/subscriptions/commandExamples.js +20 -0
- package/dist/subscriptions/contracts/commands.d.ts +8 -1
- package/dist/subscriptions/contracts/index.d.ts +2 -2
- package/dist/subscriptions/contracts/stockWait.d.ts +12 -1
- package/dist/subscriptions/index.d.ts +22 -4
- package/dist/subscriptions/index.js +22 -3
- package/dist/subscriptions/lifecycleMessages.d.ts +9 -0
- package/dist/subscriptions/lifecycleMessages.js +38 -0
- package/dist/subscriptions/paymentOutcomes.js +1 -1
- package/dist/subscriptions/postgresCommandStore.d.ts +44 -0
- package/dist/subscriptions/postgresCommandStore.js +172 -0
- package/dist/subscriptions/postgresRetryStore.d.ts +6 -0
- package/dist/subscriptions/postgresRetryStore.js +11 -0
- package/dist/subscriptions/postgresStockWaitStore.d.ts +62 -0
- package/dist/subscriptions/postgresStockWaitStore.js +174 -0
- package/dist/subscriptions/services.d.ts +31 -0
- package/dist/subscriptions/services.js +15 -0
- package/package.json +2 -2
- package/release-gates.json +2 -2
- package/sql/20261024170000_subscription_command_lifecycle.sql +404 -0
- package/sql/20261024180000_subscription_stock_wait.sql +330 -0
- package/sql/20261024183000_inventory_available_to_promise.sql +70 -0
- package/sql/20261024184000_subscription_renewal_reserve_uses_seam.sql +147 -0
- package/sql/20261024184500_subscription_retry_late_positive_stock.sql +59 -0
- package/sql/20261024184600_subscription_retry_candidate_payment_filter.sql +22 -0
- package/src/communications/contracts/subscriptionPaymentExpired.ts +4 -3
- package/src/communications/contracts/subscriptionPaymentFailed.ts +8 -8
- package/src/composition/index.ts +1 -0
- package/src/composition/subscriptionContribution.ts +25 -0
- package/src/inventory/index.ts +2 -0
- package/src/inventory/postgresStockAvailability.ts +54 -0
- package/src/subscriptions/commandExamples.ts +19 -0
- package/src/subscriptions/contracts/commands.ts +35 -2
- package/src/subscriptions/contracts/index.ts +2 -2
- package/src/subscriptions/contracts/stockWait.ts +14 -2
- package/src/subscriptions/index.ts +30 -3
- package/src/subscriptions/lifecycleMessages.ts +37 -0
- package/src/subscriptions/paymentOutcomes.ts +1 -1
- package/src/subscriptions/postgresCommandStore.ts +183 -0
- package/src/subscriptions/postgresRetryStore.ts +11 -0
- package/src/subscriptions/postgresStockWaitStore.ts +170 -0
- package/src/subscriptions/services.ts +21 -0
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,115 @@ in the source repository.
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [0.25.0]
|
|
14
|
+
|
|
15
|
+
- Publishable on the npm `latest` dist-tag as `0.25.0`, from tag
|
|
16
|
+
`openlup-platform-v0.25.0`.
|
|
17
|
+
|
|
18
|
+
- Re-pin the pending M10/F17 control fixtures after landed M08/M09 without
|
|
19
|
+
changing either installation rail, the migration manifest or landed N1. The
|
|
20
|
+
16-entry packet has seven native and nine managed pins. Native X restores
|
|
21
|
+
ATP-counted late-positive stock recovery; Y filters paid retry candidates
|
|
22
|
+
before LIMIT. Fold command-preview receipt replay into uninstalled N2, keeping
|
|
23
|
+
apply unchanged. Preserve the historical 14-pin approval reader and exact
|
|
24
|
+
prefix, definition, statement, ACL and catalog controls. Real PostgreSQL
|
|
25
|
+
witnesses cover ATP, starvation, all 43 fresh command scenarios and raw preview
|
|
26
|
+
replay with no counts/columns/xmin delta.
|
|
27
|
+
|
|
28
|
+
No package SQL asset, export, runtime activation or external CI dependency is
|
|
29
|
+
introduced. The development-preview boundary remains.
|
|
30
|
+
|
|
31
|
+
- Fix uninstalled N3 normal_due pagination to exclude waiting/stock_secured cases before LIMIT, preventing normal-renewal starvation.
|
|
32
|
+
|
|
33
|
+
- Repair uninstalled N2 donor no-op truth for native bundle/resize, plan, package, add-on and same-UTC-day slide commands before repricing: preserve locked prices after catalogue changes, writing only the command receipt, with no quote, event or version increment. Native resize compares lines/cadence; portion mode/factor remain host-owned without native storage. Predicate-removal mutants cover every mapped donor action; apply stays unchanged.
|
|
34
|
+
|
|
35
|
+
- Audit pending M10 donor change and no-op semantics together. N2 plan edits
|
|
36
|
+
apply requested core lines; new add-ons normalize quantity, preserve cadence
|
|
37
|
+
and compare UUIDs by value. N3 preserves paused waits, filters eligible recovery
|
|
38
|
+
before LIMIT, binds frozen reads to the current active schedule, reports free
|
|
39
|
+
stock separately from own holds, and ignores closed/unpaid realization notices.
|
|
40
|
+
Real PostgreSQL tables cover applied state, no-op/refusal/replay and rolled-back
|
|
41
|
+
assignment mutants. Installed rails and N2 apply remain unchanged; channel
|
|
42
|
+
exposure/admission parity stays outside the frozen stock-seam claim.
|
|
43
|
+
|
|
44
|
+
- Close the 0.24.0 known limitation that managed dunning exhaustion still pauses active subscriptions.
|
|
45
|
+
- Land the reviewed managed M1/M2 prefix: refunds preserve subscription lifecycle and paid history; exhausted dunning stays open with NULL retry and active service until authorized same-cycle repair.
|
|
46
|
+
- Folded scope E-gate-replay-loop-landed-untested: retain the existing interleaving-aware catalog replay and add the Docker-free landed N1/M1/M2 witness.
|
|
47
|
+
- Folded scope D-earlier-pin-digest-unplanted: prove CI and release refuse changed earlier M1 bytes beneath landed M2.
|
|
48
|
+
|
|
49
|
+
Migration notes: Apply M1 then M2. Existing paused, expired and refund-cancelled history is not rewritten or reactivated. The existing first-cycle refund stock-release guard remains; later refund-evidence parity and stock-wait/winback changes are separate. No runner is activated.
|
|
50
|
+
|
|
51
|
+
- Add native N2 command preview/apply stores and a P1 command adapter with atomic future terms, actor/key/actual-command receipts and applied/replayed/noop/refused outcomes; preserve frozen current obligations and existing native callers.
|
|
52
|
+
- Type-level flip for dev-preview consumers: `NATIVE_SUBSCRIPTION_CAPABILITIES.genericBundleCommands.supported` and `.commandBoundReceipts.supported` change from `false` to `true`; command results now include `SubscriptionCommandRefusal`.
|
|
53
|
+
|
|
54
|
+
Migration: install N1 then N2 through the complete native manifest; preserve receipts on rollback. Accepted future prices use lock_until_edit, proration none. Address mutation and private introductory/graduation policy stay host-owned; native activation continues to require captured payment evidence.
|
|
55
|
+
|
|
56
|
+
Migration (C73, temporary limitation): managed `subscription_create_provisional_for_checkout` stamps an explicit timezone literal equal to today's `subscriptions.timezone` column DEFAULT. Adopters changing that DEFAULT must also replace the function until the scheduled follow-up forward follows the DEFAULT; no managed SQL changes here.
|
|
57
|
+
|
|
58
|
+
Migration: `SubscriptionCommandPort.apply()` may now return `SubscriptionCommandRefusal` (`outcome: "refused"`), so callers must handle it.
|
|
59
|
+
|
|
60
|
+
- Type-level change visible to dev-preview consumers: `RenewalPaymentRail.execute` adds an optional `failure` field for explicit failure evidence.
|
|
61
|
+
- A host or driver skips `openCase` after a replayed `applyFailure` receipt only when that rung's case propagation already committed; otherwise recovery must complete propagation. The P8 retry driver must add a replay/case-advanced signal and a zero-delta witness for replay after committed propagation.
|
|
62
|
+
- N2 preview follows the supplied core lines for plan-length changes (omitted lines retain stored expansion); new add-ons normalize missing/nonpositive quantity to one, add-on actions preserve cadence, and quantity updates/removals compare variant UUIDs case-insensitively.
|
|
63
|
+
|
|
64
|
+
Land the seven reviewed managed stock-wait/ATP and F17 refund-parity forwards.
|
|
65
|
+
Managed hosts can use the service-role SQL functions and pgTAP witnesses; the
|
|
66
|
+
package declares the SQL surface and keeps TypeScript stock recovery unavailable
|
|
67
|
+
because no managed adapter implements the stock-wait/availability ports.
|
|
68
|
+
|
|
69
|
+
Migration: apply the complete managed prefix through `20261024185100` before
|
|
70
|
+
calling stock-wait or refund-evidence functions. M4 extends M2's active/open
|
|
71
|
+
continuity with wait exclusion before LIMIT. M5 makes positive customer
|
|
72
|
+
cancellations immediately winback-eligible within 120 days, retaining episode
|
|
73
|
+
dedupe, and maps started/resumed notices. F17 accepts cumulative provider snapshots,
|
|
74
|
+
emits one refunded event on transition, and preserves M1 refund/lifecycle
|
|
75
|
+
independence. Keep captured obligations and receipts on rollback and disable the
|
|
76
|
+
host stock-wait driver first. SQL installs no scheduler or payment executor.
|
|
77
|
+
|
|
78
|
+
ATP protects active upcoming demand within 14 days plus live provider hard holds.
|
|
79
|
+
The exposure hook remains zero; current donor channel admission is deferred.
|
|
80
|
+
This is a development-preview SQL surface, not a composed managed TypeScript port
|
|
81
|
+
or a claim of advance future-cycle reservations or stable installation support.
|
|
82
|
+
|
|
83
|
+
Native stock-wait persistence, frozen discovery and stock-only refusal recovery
|
|
84
|
+
now have transaction-bound adapters. The native ATP/new-purchase read protects
|
|
85
|
+
hard holds and fixed 14-day soft subscription demand; the renewal allocator uses
|
|
86
|
+
the same seam. X restores late-paid released stock once, and Y filters paid and
|
|
87
|
+
settled retry obligations before LIMIT. Managed stock wait and runner composition
|
|
88
|
+
remain separate; native selection still requires passing real-PostgreSQL proof.
|
|
89
|
+
|
|
90
|
+
Migration: install the native N3, ATP seam, allocator, X and Y prefix in filename
|
|
91
|
+
order, with their package twins and regenerated selected-catalog-v2 inventory.
|
|
92
|
+
Migration: upgrading hosts must grant their native inventory-reserving runtime
|
|
93
|
+
role EXECUTE on public.inventory_available_to_promise(text,text,timestamptz,boolean)
|
|
94
|
+
and public.inventory_channel_exposure_quantity(text,text), plus SELECT on the
|
|
95
|
+
seam's underlying relations as listed in Data and migrations, before using the
|
|
96
|
+
updated allocator or N3 stock-wait paths.
|
|
97
|
+
`StockWaitStorePort.listCandidates` now returns `StockWaitFrozenCase[]`: discovery
|
|
98
|
+
may have no durable case yet. Hosts must retain its frozen snapshot and binding.
|
|
99
|
+
Frozen discovery requires the active current schedule; paused current waits remain open.
|
|
100
|
+
Deficits separate own reserved units from free ATP and subtract both for missing
|
|
101
|
+
units. Closed or pending-payment resume callbacks return null without writes; paid
|
|
102
|
+
fulfillment-pending orders can complete realization admission.
|
|
103
|
+
No advance reservation, physical coverage guarantee or one-time checkout writer
|
|
104
|
+
is introduced. No pause, payment execution or parcel-arrival fact is added.
|
|
105
|
+
Uncaptured stock refusals rotate on the operation selection timestamp even when
|
|
106
|
+
missing or stale stock prevents case creation, allowing replenished work through
|
|
107
|
+
a bounded candidate page.
|
|
108
|
+
|
|
109
|
+
M10 P6 + P8: composed subscriptions (development preview)
|
|
110
|
+
|
|
111
|
+
Migration: Additive `./subscriptions` facades are `createSubscriptionServices`, `createSubscriptionCommandExamples`, `createSubscriptionLifecycleMessages` and `subscriptionLifecycleTemplate`; hosts explicitly supply readiness, execution, commands and M04 delivery. No factory activates serving work. `SubscriptionLifecycleFact` is exported from this entry; `subscriptionLifecycleTemplate(kind, retryAttempt?)` preserves the installed payment-failure rungs (1, 2, otherwise 3). `runRenewalBatchRows` exposes the existing per-row error-result isolation for composed hosts.
|
|
112
|
+
Migration: Additive `./composition` entry `createSubscriptionContribution` describes exactly one selected subscription schedule; off supplies none. Hosts bind its callable to their existing population lease and observe the complete installed schema.
|
|
113
|
+
Migration: `createPostgresRetryStore` adds `failureProgress(operationId,key)`, returning receipt replay and committed case progression. The native retry driver completes interrupted propagation and skips already advanced cases; existing applyFailure/openCase signatures remain unchanged.
|
|
114
|
+
|
|
115
|
+
The inert native reference binding composes mandatory G23, dunning and stock wait.
|
|
116
|
+
Captured alignment cases retain authority under off. Prepared attempts reconcile
|
|
117
|
+
without re-execution; ordinary retries bind the frozen mandate and logical cycle.
|
|
118
|
+
M04 owns delivery; M12 owns aggregation. No SQL asset, serving swap, release or
|
|
119
|
+
managed TypeScript recovery is introduced. Native multi-cycle prepaid and M07
|
|
120
|
+
prepared-attempt-store capabilities retain their named unsupported boundaries.
|
|
121
|
+
|
|
13
122
|
## [0.24.0]
|
|
14
123
|
|
|
15
124
|
- Publishable on the npm `latest` dist-tag as `0.24.0`, from tag
|
|
@@ -449,213 +558,3 @@ Native parity remains host-owned at these seams. Missing native bindings use the
|
|
|
449
558
|
- M08 parity D2 KEEP-GAP: native dispatch finish still loses rejected/unknown error detail.
|
|
450
559
|
- M08 parity KEEP-GAP: immutable stock snapshot/alert evidence storage is absent; cursor JSON is overwritten. Hosts retain referenced evidence.
|
|
451
560
|
- Stock-evidence replay/reopen is CLOSED by native position 76; legacy `0.22.0` alert fingerprints still conflict with `23505`, including after resolution.
|
|
452
|
-
|
|
453
|
-
## [0.22.0]
|
|
454
|
-
|
|
455
|
-
- Publishable on the npm `latest` dist-tag as `0.22.0`, from tag
|
|
456
|
-
`openlup-platform-v0.22.0`.
|
|
457
|
-
|
|
458
|
-
- Add eleven experimental reference-application support exports on the existing payment vendor subpaths. Reuse contributed execution, readback, mapping and diagnostic helpers; preserve the no-charge error class identity. Neutral payment exports and default activation remain unchanged.
|
|
459
|
-
|
|
460
|
-
Migration: none.
|
|
461
|
-
|
|
462
|
-
### Opt-in warehouse fulfillment example
|
|
463
|
-
|
|
464
|
-
Add the experimental, opt-in warehouse fulfillment entry described in the README behind the frozen neutral fulfillment ports: explicit injected I/O, prepared-byte binding, closed evidence, token observations and positive readback. Default-off; account readiness is host-owned. Exact absence, label create/void and cancellation remain unsupported.
|
|
465
|
-
|
|
466
|
-
Missing or malformed evidence refuses before credential resolution or HTTP.
|
|
467
|
-
|
|
468
|
-
Migration: none
|
|
469
|
-
|
|
470
|
-
### Offline warehouse fulfillment conformance
|
|
471
|
-
|
|
472
|
-
Prove the opt-in warehouse fulfillment entry described in the README with M08's offline conformance runner using injected
|
|
473
|
-
HTTP and synthetic fixtures. Cover dispatch replay and refusals, observation,
|
|
474
|
-
readback, stock and product sync, plus real-worker host-ledger fences after
|
|
475
|
-
restart and retention eviction. No provider-account or activation proof is claimed.
|
|
476
|
-
|
|
477
|
-
Migration: none
|
|
478
|
-
|
|
479
|
-
### Fulfillment contracts and status canon
|
|
480
|
-
|
|
481
|
-
Add experimental `fulfillment` and type-only `fulfillment/contracts` entries with
|
|
482
|
-
contributed status decisions, strict core parser bindings, concrete provider/store
|
|
483
|
-
ports and injected default-off capabilities. No adapter, executor, route or default
|
|
484
|
-
profile is activated; existing reference integrations remain unchanged.
|
|
485
|
-
|
|
486
|
-
Declared adaptation: empty or absent provider selection is a typed refusal in the
|
|
487
|
-
new package, rather than the donor host's implicit simulator alias. The donor alias
|
|
488
|
-
remains an open owner follow-up; this contribution does not change donor logic.
|
|
489
|
-
Private provider trace columns and registry/environment values are excluded from
|
|
490
|
-
the neutral package; persisted command fingerprints and opaque host keys are retained.
|
|
491
|
-
|
|
492
|
-
Migration: none (new surface; no existing reference behavior changes).
|
|
493
|
-
|
|
494
|
-
### Fulfillment paid handoff and fenced dispatch
|
|
495
|
-
|
|
496
|
-
Add the paid outbox handler/recovery classifier, injected dispatch worker and
|
|
497
|
-
separate durable command-ledger protocol through the new fulfillment entry.
|
|
498
|
-
Preserve one contact remap, opaque host keys, actual-command fingerprints,
|
|
499
|
-
readback/attempt/begin order and local accepted-proof repair without another POST.
|
|
500
|
-
Provider/money/inventory authority remains injected; no SQL, route or activation.
|
|
501
|
-
|
|
502
|
-
Approved port amendment G14 adds recordProviderAttempt to the new
|
|
503
|
-
FulfillmentStorePort. It records only sanitized prepared DispatchEvidence plus
|
|
504
|
-
mode/recorded status and opaque references, after authoritative claim readback;
|
|
505
|
-
same-key replay writes no second attempt and contact remap retains its own key.
|
|
506
|
-
No new named export or subpath is added by this method. Other contracts are unchanged.
|
|
507
|
-
|
|
508
|
-
Correctable draft re-claim must refresh fingerprint and evidence atomically.
|
|
509
|
-
Store conformance and native durability/fencing and SQL proofs remain later work.
|
|
510
|
-
|
|
511
|
-
Migration: none (new surface; contracts and orchestration land in one release).
|
|
512
|
-
|
|
513
|
-
### Fulfillment observation and sync workers
|
|
514
|
-
|
|
515
|
-
Add neutral observation effects, verified ingress, observation reconciliation,
|
|
516
|
-
tracking, stock/product sync, read-only evidence handlers and the offline
|
|
517
|
-
runFulfillmentAdapterConformance at the existing fulfillment entry.
|
|
518
|
-
|
|
519
|
-
Migration: approved G15 extends the unreleased SyncCursor with optional
|
|
520
|
-
coverageGapSkus (legacy absence reads as []). Only consecutive succeeded runs
|
|
521
|
-
confirm a reservation coverage gap; running/failed cursors clear the set.
|
|
522
|
-
Migration: approved G16 changes readLocalInventoryStock(requestedAt) to typed
|
|
523
|
-
unaggregated lines with skuRef, quantity balances, fulfillable, locationStatus,
|
|
524
|
-
lotStatus and expiresAt. The worker filters/sums at the captured clock; expiry
|
|
525
|
-
exactly then is excluded. Inventory authority and the provider stock-sync shape
|
|
526
|
-
are unchanged.
|
|
527
|
-
Migration: approved G17 adds inline localPersistence: ingress records eventKey
|
|
528
|
-
receipts preserving firstReceivedAt and marks processing idempotently;
|
|
529
|
-
reconciliation reads local status/latestStatusOccurredAt/handedOverAt. No named
|
|
530
|
-
persistence type is exported. Durable replay and processing remain host obligations.
|
|
531
|
-
A superseding conflict returns superseded but persists only processed status,
|
|
532
|
-
without a dedicated superseded-reason field.
|
|
533
|
-
|
|
534
|
-
Correlated ingress requires a nonblank observation or dispatch external reference
|
|
535
|
-
before acceptance/status/effects/processed mark; failure leaves the receipt
|
|
536
|
-
unprocessed. Stock-contention annotation is best-effort before the original stock
|
|
537
|
-
failure is rethrown; recovered-picked receipt diagnostics remain typed. Effects
|
|
538
|
-
retain stock → handover → tracking → invoice and callback/throw order.
|
|
539
|
-
Reconciliation fails the run on unknown readback and projects unmapped correlation
|
|
540
|
-
evidence before host calls. Product evidence reads retain safe authorization/read
|
|
541
|
-
refusal detail. Private codecs, keys, carrier URLs and provider errors stay
|
|
542
|
-
host-owned; typed evidence replaces raw payload pass-through. The conformance
|
|
543
|
-
runner accepts adapter-owned offline subjects and returns sanitized evidence;
|
|
544
|
-
fixture checks do not establish durable store atomicity or arrival alignment.
|
|
545
|
-
|
|
546
|
-
### Fulfillment native persistence and delivery alignment
|
|
547
|
-
|
|
548
|
-
Add native shipment, evidence, stock, recovery, dispatch, paid-handoff and
|
|
549
|
-
alignment stores through the existing fulfillment entry. Sparse migration
|
|
550
|
-
projections bind native units 5/27/51/73/74; install the complete catalogue.
|
|
551
|
-
Coverage-gap cursor state and received/status/processed evidence are
|
|
552
|
-
durable, while local inventory lines and contact preparation remain explicit
|
|
553
|
-
host inputs. Native 3pl acceptance uses a dispatch evidence receipt and preserves
|
|
554
|
-
the cancellation fence without inventing an owned label or physical packing.
|
|
555
|
-
|
|
556
|
-
Native admission: overdue-delivery admission guards only NEW cycle
|
|
557
|
-
admission/insert, matching the donor's guard_cycle_insert. Existing-cycle retries
|
|
558
|
-
through renewal operations and dunning bypass admission and neither mint nor
|
|
559
|
-
consume a one-use receipt. No retry_scheduled state or payments lifecycle change is
|
|
560
|
-
introduced. Native continuity requires the complete canonical migration graph,
|
|
561
|
-
real-PostgreSQL installation, replay and access-control checks.
|
|
562
|
-
|
|
563
|
-
### Fulfillment operator lifecycle and customer delay projection
|
|
564
|
-
|
|
565
|
-
Add host-owned operator and replacement handlers through the fulfillment entry.
|
|
566
|
-
Mutation callbacks require actor attribution and idempotency keys; the host owns
|
|
567
|
-
atomic replay receipts and replacement eligibility, reservation and hold effects.
|
|
568
|
-
Native bindings return a shared typed unsupported refusal without writing.
|
|
569
|
-
Customer delay projection keeps absent cases distinct, hides aligned history
|
|
570
|
-
when the schedule advances and never presents manual review as protection.
|
|
571
|
-
Label helpers preserve transient downloads and cleanup uncertainty. Current
|
|
572
|
-
parcel helpers retain sequence selection and companion attribution. These
|
|
573
|
-
exports mount no route, dispatch no parcel and attest no replacement arrival.
|
|
574
|
-
|
|
575
|
-
### Fulfillment commerce reads and recorded progress
|
|
576
|
-
|
|
577
|
-
Add host-owned commerce list/detail projections, a shipments overview handler and
|
|
578
|
-
typed read callbacks. Projected payment status passes through unchanged and
|
|
579
|
-
native reads return the shared unsupported refusal. Preserve opaque host overview
|
|
580
|
-
buckets and the legacy shipment-status facade. Progress completion requires
|
|
581
|
-
recorded milestones and uses the host-resolved customer step.
|
|
582
|
-
|
|
583
|
-
### Fulfillment internal simplification
|
|
584
|
-
|
|
585
|
-
Reuse the empty stock-balance constructor in aggregation and sync, and append to
|
|
586
|
-
private recovery groups without copying each growing array. Fulfillment results,
|
|
587
|
-
public contracts, key bytes and effect order remain unchanged.
|
|
588
|
-
|
|
589
|
-
### Fulfillment service composition and preparation
|
|
590
|
-
|
|
591
|
-
Add explicit default-off fulfillment services, a structural contribution and an
|
|
592
|
-
inert reference preparation binding. Authoritative source edits and redacted
|
|
593
|
-
context synchronization share the native dispatch and shipment locks. Missing
|
|
594
|
-
preparation refuses readiness. No route, schedule, renewal wrapper or automatic
|
|
595
|
-
dispatch is activated.
|
|
596
|
-
|
|
597
|
-
### Fulfillment presentation ownership
|
|
598
|
-
|
|
599
|
-
The status canon, actual-evidence tracking progress, current-parcel selection and
|
|
600
|
-
canonical fact parsers belong to `@openlup/core/fulfillment`. Platform keeps thin
|
|
601
|
-
compatibility re-exports and preserves its existing narrowed fact type names.
|
|
602
|
-
Fulfillment contracts re-export the shared status and progress types from core.
|
|
603
|
-
Server orchestration remains in platform. Browser code, including the host
|
|
604
|
-
status, fact and current-parcel facades and the account order views, imports
|
|
605
|
-
these helpers from core, so no browser graph loads the platform fulfillment
|
|
606
|
-
runtime.
|
|
607
|
-
|
|
608
|
-
Migration: existing platform imports remain valid; no application or schema
|
|
609
|
-
migration is required. Core exposes narrowed fact aliases with a `Canonical`
|
|
610
|
-
prefix while its generic fact exports retain their names.
|
|
611
|
-
|
|
612
|
-
Migration: upgrade core, outbox and platform together from `0.21.0` to `0.22.0` for exact peer pins. Install the complete canonical native migration chain through units 73/74 (`20261022080000_fulfillment_command_ledger.sql` and `20261022090000_fulfillment_delivery_alignment.sql`), never the sparse package projections alone. Before, these fulfillment services were host-owned; after, explicitly compose selected ports and default-off services. Nothing mounts routes, schedules dispatch or composes the native renewal runner automatically. Keep native alignment off or shadow until the G23 decorator is composed. Arrival alignment remains once and later-only; undelivered replacements remain outstanding, and replacement confirmation must only record actual customer arrival. Preserve G15–G17 cursor, receipt and local-status persistence when implementing host stores. An application rollback does not reverse the forward migrations; older runners refuse the extended ledger.
|
|
613
|
-
|
|
614
|
-
### Known limitations
|
|
615
|
-
|
|
616
|
-
- Portable dunning repair has no managed twin: exhaustion still pauses active subscriptions there; retaining active status needs a managed forward.
|
|
617
|
-
- D8-1: native advisory v2 promo-code candidates/rejection details unavailable.
|
|
618
|
-
- D8-2: native mounted v2 issue/honor/fallback unavailable.
|
|
619
|
-
- D8-3: native acquisition-only mounted issuance/honor unavailable.
|
|
620
|
-
- D8-4: full native/managed eligibility equivalence unavailable.
|
|
621
|
-
- Bundle-1: independent DB human-only actor-kind enforcement absent natively; first in the native-backend parity round.
|
|
622
|
-
- Bundle-2: managed-equivalent actor-kind/email history absent natively.
|
|
623
|
-
- Bundle-3 closes injected-reader M05 mounted admin/feed readback only. Native new-purchase stock read absent despite P5a installed-store proof; deferred second after bundle-1 (owner 2026-10-21); readiness refuses.
|
|
624
|
-
- Bundle-4: incumbent real-PostgreSQL contention only; no exactly-once guarantee.
|
|
625
|
-
- Managed schema/pgTAP retain `44.404`; removal needs owner decision/forward; reference composition supplies it to app code.
|
|
626
|
-
- A1 offline only; account/hosted-time/owner TEST evidence unclaimed; `communications/klaviyo` verification-pending.
|
|
627
|
-
- M05 omitted opt-ins preserve defaults/outputs/read order/schedules/refusals/acceptance-token bytes/SQL.
|
|
628
|
-
- Native inventory adjustment unavailable; address writes refuse readiness. Flat-rate save needs selected port/Core readiness/applied-seed observation.
|
|
629
|
-
- Native shipping audit unavailable; handler swallows best-effort audit failure.
|
|
630
|
-
- Native flat-rate integer bounds (0 through host maximum; reference 100,000 minor units) use request schema, not DB CHECK.
|
|
631
|
-
- Managed ATP/forecast/dated-supply/pagination readback unproved/pending M06.
|
|
632
|
-
- Managed two-session locks/concurrency/uncovered compensation unproved/pending M06.
|
|
633
|
-
- Managed exact-prefix upgrade/ledger unproved/pending M06.
|
|
634
|
-
- Managed address idempotency/conflict/readback unproved/pending M06.
|
|
635
|
-
- Managed successful flat-rate read/save unproved/pending host authority.
|
|
636
|
-
- M06 stock-wait lifecycle/durable timing/staging controls retain C5/C6; busy/try-gate, continuity/flag/TTL transfers are dispositions, not PASS.
|
|
637
|
-
- Shipping national-registry fields/locale-specific `canonicalAddressKey` fold await M16 host market pack/key migration; reference shipping copy stays locale-specific until M16.
|
|
638
|
-
- Native durable prepared storage, method setup, absence reopen and cumulative refunds unavailable; no production installation parity claimed.
|
|
639
|
-
- Typed refusal-envelope forwarding unavailable (`failureReason` only); reusable registration needs host ownership resolution.
|
|
640
|
-
- Incomplete chargebacks stay refunds/unapplied: reclassification bypasses evidence validation into dispute apply; limited operator recovery.
|
|
641
|
-
- Audit compatibility still detects `chargeId`; refund operation identity/original money supply no typed charge identity.
|
|
642
|
-
- M07 follow-up: repair poll can clear host redirect; post-timeout verify never restarts polling; unlocalized poller; fixture builds/never calls handler.
|
|
643
|
-
- M07 follow-up: reference status route wrong-rail witness.
|
|
644
|
-
- M07 follow-up: explicit reference-route refusal for unsupported method setup.
|
|
645
|
-
- M07 follow-up: deployment-neutral disabled-verify reason.
|
|
646
|
-
- M07 follow-up: reference card normalizer missing-amount path; package settling evidence already requires positive money.
|
|
647
|
-
|
|
648
|
-
- Native delivery alignment stays off or shadow until a host composes the native automatic-renewal runner with the G23 renewal admission decorator. The decorator alone neither composes nor activates the runner.
|
|
649
|
-
- The core fulfillment status map carries localized adopter labels; replace them with host-injected labels or internationalization keys before any stable-framework claim.
|
|
650
|
-
- The warehouse adapter example is opt-in and has offline conformance only; no provider-account proof or activation is established. Exact absence, label create/void and cancellation remain unsupported.
|
|
651
|
-
- After an alignment extension, a deferred renewal operation at the old schedule remains claimed with no reader or reservation effect. Changed terms snapshots conflict under the existing snapshot-conflict rules.
|
|
652
|
-
|
|
653
|
-
Native parity remains host-owned at these seams. Missing native bindings use the shared `FULFILLMENT_NATIVE_UNSUPPORTED` refusal; no partial write or parity claim is implied.
|
|
654
|
-
|
|
655
|
-
| Amendment | Host-owned seam and native boundary |
|
|
656
|
-
| --- | --- |
|
|
657
|
-
| G18 | Replacement creation and atomic eligibility/replay receipts; native replacement callback refuses. |
|
|
658
|
-
| G19 | Operator mutations, actor attribution and replay receipts; native mutation callbacks refuse. |
|
|
659
|
-
| G20 | Customer alignment rows; native reader refuses, while the pure delay projection remains callable. |
|
|
660
|
-
| G21 | Commerce list/detail and shipments overview; native read callbacks refuse. |
|
|
661
|
-
| G22 | Authoritative preparation edits, authorization and replay receipts; missing preparation binding refuses before dispatch, after disabled/selection/readiness checks. |
|
package/README.md
CHANGED
|
@@ -10,16 +10,21 @@ Development preview. This package is part of the publishable set with core and o
|
|
|
10
10
|
|
|
11
11
|
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`.
|
|
12
12
|
|
|
13
|
-
For the prepared `0.
|
|
14
|
-
limitations](CHANGELOG.md#
|
|
15
|
-
Install the complete native chain through position
|
|
16
|
-
|
|
17
|
-
are not an install chain.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
For the prepared `0.25.0` set, read the [adjacent-release migration and known
|
|
14
|
+
limitations](CHANGELOG.md#0250) before selecting optional services.
|
|
15
|
+
Install the complete native chain through position 86, including N2 commands,
|
|
16
|
+
N3 stock wait, the ATP seam/allocator and late-payment/retry-selection forwards;
|
|
17
|
+
sparse SQL projections are not an install chain. Native runtime roles need the
|
|
18
|
+
ATP/exposure EXECUTE and underlying SELECT grants described in the release notes.
|
|
19
|
+
Managed hosts apply the complete prefix through `20261024185100` for stock-wait
|
|
20
|
+
and refund-evidence functions. Preserve captured obligations and receipts on rollback.
|
|
21
|
+
M10 subscription services and contributions remain **EXPERIMENTAL and DEFAULT-OFF**.
|
|
22
|
+
Hosts explicitly supply readiness, execution, commands, mandatory G23 admission,
|
|
23
|
+
a population lease and M04 delivery. Factories activate no serving work. The inert
|
|
24
|
+
native reference composes renewal, dunning and stock wait; managed TypeScript
|
|
25
|
+
stock recovery, native multi-cycle prepaid and M07 prepared-attempt-store
|
|
26
|
+
capabilities retain their named unsupported boundaries. Follow the older native-row
|
|
27
|
+
migration precautions when upgrading `0.22.0` data.
|
|
23
28
|
M09 invoicing remains **EXPERIMENTAL and DEFAULT-OFF**, available for explicit
|
|
24
29
|
provider/capability selection and ready host composition, including issue,
|
|
25
30
|
correction, independent duties, delivery/read-side and seller revision helpers.
|
|
@@ -27,7 +32,7 @@ Adopters must not activate unselected or unready invoicing; installation and
|
|
|
27
32
|
inert contributions register no runner, worker, route or schedule.
|
|
28
33
|
M06 managed-host proof classes remain pending in the
|
|
29
34
|
[M06 parity ledger](../../docs/platform/plans/oss-m06-stock-reservations-delivery.md#parity-pending-rows).
|
|
30
|
-
Size comparison uses the published `0.
|
|
35
|
+
Size comparison uses the published `0.24.0` tarball. Preparation and offline
|
|
31
36
|
adapter evidence grant no publication or provider-account certification.
|
|
32
37
|
|
|
33
38
|
Longer module recipes live in the [platform package reference](../../docs/platform/PLATFORM_PACKAGE_REFERENCE.md).
|
|
@@ -724,6 +729,30 @@ The initial binding preserves case-before-outcome ordering with atomic bookkeepi
|
|
|
724
729
|
N1's same-obligation recovery repairs the native decline stall (F16); it does not
|
|
725
730
|
supply M07 prepared-store parity or activate a runner.
|
|
726
731
|
|
|
732
|
+
With N1 then N2 installed, `createPostgresSubscriptionCommandStore` and
|
|
733
|
+
`createPostgresSubscriptionCommands` support native generic bundle commands and
|
|
734
|
+
command-bound receipts. Preview persists a quote; apply atomically updates future
|
|
735
|
+
terms, event and receipt with no proration or current-cycle repricing. Hosts own
|
|
736
|
+
authorization, address validation, SKU/composition translation and the transaction
|
|
737
|
+
connection. Prepaid remains unsupported; the serving adapter refuses pause.
|
|
738
|
+
|
|
739
|
+
Native N3 plus the ATP seam/allocator and X/Y suffix provide
|
|
740
|
+
`createPostgresStockWaitStore` and `createPostgresStockAvailability` (the latter
|
|
741
|
+
at `./inventory`). Hosts supply transactions, clock, source and the existing
|
|
742
|
+
wire codec. Candidate discovery preserves uncaptured frozen operations; shortage
|
|
743
|
+
creates a durable wait, and elapsed stock-only refusals may reacquire on the same
|
|
744
|
+
identity with a new claim generation. Resumed means paid realization admitted.
|
|
745
|
+
The fixed 14-day soft priority is distinct from durable advance reservations.
|
|
746
|
+
The unbound descriptor keeps stock recovery unavailable. The opt-in native M10
|
|
747
|
+
reference composition selects it after composed PostgreSQL proof; managed
|
|
748
|
+
TypeScript recovery remains unavailable.
|
|
749
|
+
|
|
750
|
+
`createSubscriptionServices`, lifecycle-message and neutral command facades are
|
|
751
|
+
in `./subscriptions`; `createSubscriptionContribution` is in `./composition`.
|
|
752
|
+
They are default-off and describe one host executor/job. The
|
|
753
|
+
[composed module recipe](../../docs/platform/ARCHITECTURE_AND_EXTENSIONS.md#composed-subscription-module)
|
|
754
|
+
owns explicit selection, frozen mandate/replay, M04 delivery and M12 boundaries.
|
|
755
|
+
|
|
727
756
|
## Invoicing contracts
|
|
728
757
|
|
|
729
758
|
Experimental `@openlup/platform/invoicing` exposes `readInvoiceCapabilities`;
|
|
@@ -14,8 +14,9 @@ export interface SubscriptionPaymentExpiredEmailVars {
|
|
|
14
14
|
*/
|
|
15
15
|
cause?: PaymentFailureCustomerCause | null;
|
|
16
16
|
/**
|
|
17
|
-
* Recovery-link URL for the case's
|
|
18
|
-
*
|
|
17
|
+
* Recovery-link URL for the case's payment-recovery token. Current exhaustion
|
|
18
|
+
* uses `repair_payment`; legacy expired cases may carry `resume_subscription`.
|
|
19
|
+
* When present the template renders the recovery CTA; otherwise it keeps the support-led
|
|
19
20
|
* wording, because a button with no destination is worse than no button.
|
|
20
21
|
*/
|
|
21
22
|
recoveryUrl?: string | null;
|
|
@@ -8,7 +8,7 @@ export function createSubscriptionPaymentExpiredContentFactory(input) {
|
|
|
8
8
|
const causeSentence = subscriptionPaymentCauseSentence(locale, vars.cause ?? "unknown");
|
|
9
9
|
const detail = [
|
|
10
10
|
// Leads the box for the same reason as in the failed notice: it answers the
|
|
11
|
-
// question the
|
|
11
|
+
// question the unsuccessful payment raises, before the figures.
|
|
12
12
|
...(causeSentence ? [causeSentence] : []),
|
|
13
13
|
...(recoveryUrl
|
|
14
14
|
? [
|
|
@@ -12,9 +12,10 @@ export interface SubscriptionPaymentFailedEmailVars {
|
|
|
12
12
|
recoveryUrl?: string | null;
|
|
13
13
|
/**
|
|
14
14
|
* Pre-formatted calendar day of the scheduled next charge, in the merchant's
|
|
15
|
-
* zone (e.g. "11.08.2026").
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* zone (e.g. "11.08.2026"). Present only when a retry is actually scheduled:
|
|
16
|
+
* a first-rung hard decline selects this template with no next retry, and
|
|
17
|
+
* `retryScheduled: false` renders the no-retry copy. null/absent keeps the
|
|
18
|
+
* sentence without a date rather than printing a placeholder date.
|
|
18
19
|
*/
|
|
19
20
|
nextRetryDateLabel?: string | null;
|
|
20
21
|
/** Card scheme as stored on the method's consent snapshot, e.g. "visa". */
|
|
@@ -14,11 +14,10 @@ export function createSubscriptionPaymentFailedContentFactory(input) {
|
|
|
14
14
|
// also why it is PREPENDED and never appended — the retry sentence must stay
|
|
15
15
|
// last (see below).
|
|
16
16
|
const causeSentence = subscriptionPaymentCauseSentence(locale, vars.cause ?? "unknown");
|
|
17
|
-
// Only an explicit `false` turns the promises off.
|
|
18
|
-
//
|
|
19
|
-
// must
|
|
20
|
-
//
|
|
21
|
-
// cancel a subscription that was about to recover on its own.
|
|
17
|
+
// Only an explicit `false` turns the retry promises off. Absence preserves
|
|
18
|
+
// the legacy rendering default; it does not prove a retry is scheduled.
|
|
19
|
+
// Producers must pass the actual schedule fact when retries have stopped,
|
|
20
|
+
// including class termination or exhaustion.
|
|
22
21
|
const retryScheduled = vars.retryScheduled !== false;
|
|
23
22
|
const detail = [
|
|
24
23
|
...(causeSentence ? [causeSentence] : []),
|
|
@@ -5,3 +5,4 @@ export { createCatalogContribution, type CatalogContributionInput } from "./cata
|
|
|
5
5
|
export { createInventoryContribution } from "./inventoryContribution.js";
|
|
6
6
|
export { createShippingContribution } from "./shippingContribution.js";
|
|
7
7
|
export { createFulfillmentContribution } from "./fulfillmentContribution.js";
|
|
8
|
+
export { createSubscriptionContribution } from "./subscriptionContribution.js";
|
|
@@ -6,3 +6,4 @@ export { createCatalogContribution } from "./catalogContribution.js";
|
|
|
6
6
|
export { createInventoryContribution } from "./inventoryContribution.js";
|
|
7
7
|
export { createShippingContribution } from "./shippingContribution.js";
|
|
8
8
|
export { createFulfillmentContribution } from "./fulfillmentContribution.js";
|
|
9
|
+
export { createSubscriptionContribution } from "./subscriptionContribution.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Contribution, RequiredSchema } from "@openlup/core/readiness";
|
|
2
|
+
/** One selected subscription job; no second scheduler or automatic registration. */
|
|
3
|
+
export declare function createSubscriptionContribution(input: {
|
|
4
|
+
version: string;
|
|
5
|
+
requiredSchema: RequiredSchema;
|
|
6
|
+
run: (() => Promise<unknown>) | null;
|
|
7
|
+
cadenceSeconds: number;
|
|
8
|
+
}): {
|
|
9
|
+
contributions: Contribution[];
|
|
10
|
+
ports: {
|
|
11
|
+
"@openlup/platform/subscriptions:run": () => Promise<unknown>;
|
|
12
|
+
} | {
|
|
13
|
+
"@openlup/platform/subscriptions:run"?: undefined;
|
|
14
|
+
};
|
|
15
|
+
triggers: {
|
|
16
|
+
[k: string]: () => Promise<unknown>;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/** One selected subscription job; no second scheduler or automatic registration. */
|
|
2
|
+
export function createSubscriptionContribution(input) {
|
|
3
|
+
if (!Number.isFinite(input.cadenceSeconds) || input.cadenceSeconds <= 0)
|
|
4
|
+
throw new Error("subscription_cadence_invalid");
|
|
5
|
+
const schedules = input.run ? [{ id: "subscriptions-renewal", cadenceSeconds: input.cadenceSeconds, run: input.run }] : [];
|
|
6
|
+
const contribution = {
|
|
7
|
+
manifest: {
|
|
8
|
+
name: "@openlup/platform", version: input.version, kind: "rail",
|
|
9
|
+
module: { id: "subscriptions", kind: "capability", provides: ["./subscriptions", "./subscriptions/contracts"], dependsOn: [] },
|
|
10
|
+
emits: [], handles: [], schedules: schedules.map(({ id, cadenceSeconds }) => ({ id, cadenceSeconds })),
|
|
11
|
+
env: [], requiredPorts: ["run"], routes: [], requiredSchema: input.requiredSchema,
|
|
12
|
+
}, handlers: [], schedules, routes: [],
|
|
13
|
+
};
|
|
14
|
+
return {
|
|
15
|
+
contributions: [contribution],
|
|
16
|
+
ports: input.run ? { "@openlup/platform/subscriptions:run": input.run } : {},
|
|
17
|
+
triggers: Object.fromEntries(schedules.map(schedule => [`@openlup/platform/subscriptions:${schedule.id}`, schedule.run])),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -12,3 +12,5 @@ export { forecastSubscriptionInventoryShortages, buildSubscriptionInventoryForec
|
|
|
12
12
|
export { calculateSubscriptionForecastSkus, calculateSubscriptionForecastTotals } from "./subscriptionForecastCalculation.js";
|
|
13
13
|
export { INVENTORY_MIGRATIONS } from "./sql.js";
|
|
14
14
|
export { createInventoryBindings, type InventoryBindingDependencies, type InventoryBindings } from "./bindings.js";
|
|
15
|
+
export { createPostgresStockAvailability } from "./postgresStockAvailability.js";
|
|
16
|
+
export type { NativeStockPromise } from "./postgresStockAvailability.js";
|
package/dist/inventory/index.js
CHANGED
|
@@ -9,3 +9,4 @@ export { forecastSubscriptionInventoryShortages, buildSubscriptionInventoryForec
|
|
|
9
9
|
export { calculateSubscriptionForecastSkus, calculateSubscriptionForecastTotals } from "./subscriptionForecastCalculation.js";
|
|
10
10
|
export { INVENTORY_MIGRATIONS } from "./sql.js";
|
|
11
11
|
export { createInventoryBindings } from "./bindings.js";
|
|
12
|
+
export { createPostgresStockAvailability } from "./postgresStockAvailability.js";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { NewPurchaseStockReadPort } from "./newPurchaseStockAvailability.js";
|
|
2
|
+
interface StockQueryExecutor {
|
|
3
|
+
query(text: string, values?: unknown[]): Promise<{
|
|
4
|
+
rows: Record<string, unknown>[];
|
|
5
|
+
}>;
|
|
6
|
+
}
|
|
7
|
+
export interface NativeStockPromise {
|
|
8
|
+
availableQuantity: number;
|
|
9
|
+
forSaleQuantity: number;
|
|
10
|
+
hardHoldQuantity: number;
|
|
11
|
+
safetyQuantity: number;
|
|
12
|
+
softSubscriptionDemandQuantity: number;
|
|
13
|
+
channelExposureQuantity: number;
|
|
14
|
+
}
|
|
15
|
+
/** Native read-only ATP. The fixed 14-day priority cannot be waived by a new
|
|
16
|
+
* purchase caller. Only the fenced native SQL allocator uses the renewal exemption. */
|
|
17
|
+
export declare function createPostgresStockAvailability(executor: StockQueryExecutor, options: {
|
|
18
|
+
sourceKey: string;
|
|
19
|
+
now: () => string;
|
|
20
|
+
}): {
|
|
21
|
+
readPort: NewPurchaseStockReadPort;
|
|
22
|
+
availableToPromise(sku: string, asOf: string): Promise<NativeStockPromise>;
|
|
23
|
+
};
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
function object(value) {
|
|
2
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
3
|
+
throw new Error("inventory_stock_response_invalid");
|
|
4
|
+
return value;
|
|
5
|
+
}
|
|
6
|
+
function quantity(value) {
|
|
7
|
+
if ((typeof value !== "number" && typeof value !== "string") || String(value).trim() === "")
|
|
8
|
+
throw new Error("inventory_stock_quantity_invalid");
|
|
9
|
+
const n = Number(value);
|
|
10
|
+
if (!Number.isSafeInteger(n) || n < 0)
|
|
11
|
+
throw new Error("inventory_stock_quantity_invalid");
|
|
12
|
+
return n;
|
|
13
|
+
}
|
|
14
|
+
/** Native read-only ATP. The fixed 14-day priority cannot be waived by a new
|
|
15
|
+
* purchase caller. Only the fenced native SQL allocator uses the renewal exemption. */
|
|
16
|
+
export function createPostgresStockAvailability(executor, options) {
|
|
17
|
+
return {
|
|
18
|
+
async availableToPromise(sku, asOf) {
|
|
19
|
+
const row = object((await executor.query(`SELECT public.inventory_available_to_promise(
|
|
20
|
+
$1::text,$2::text,$3::timestamptz,false) AS response`, [options.sourceKey, sku, asOf])).rows[0]?.response);
|
|
21
|
+
return { availableQuantity: quantity(row.available_quantity), forSaleQuantity: quantity(row.for_sale_quantity),
|
|
22
|
+
hardHoldQuantity: quantity(row.hard_hold_quantity), safetyQuantity: quantity(row.safety_quantity),
|
|
23
|
+
softSubscriptionDemandQuantity: quantity(row.soft_subscription_demand_quantity), channelExposureQuantity: quantity(row.channel_exposure_quantity) };
|
|
24
|
+
},
|
|
25
|
+
readPort: {
|
|
26
|
+
async read(input) {
|
|
27
|
+
if (input.horizonDays !== 14 || input.excludeOrderId !== null)
|
|
28
|
+
throw new Error("native_stock_read_options_unsupported");
|
|
29
|
+
if (!input.skus.length)
|
|
30
|
+
return new Map();
|
|
31
|
+
const value = (await executor.query(`SELECT public.inventory_new_purchase_stock_read(
|
|
32
|
+
$1::text,$2::jsonb,$3::timestamptz) AS response`, [options.sourceKey, JSON.stringify(input.skus), options.now()])).rows[0]?.response;
|
|
33
|
+
if (!Array.isArray(value))
|
|
34
|
+
throw new Error("inventory_stock_response_invalid");
|
|
35
|
+
return new Map(value.map(value => {
|
|
36
|
+
const row = object(value);
|
|
37
|
+
if (typeof row.sku !== "string" || !["provider", "missing"].includes(String(row.source)) || typeof row.stale !== "boolean")
|
|
38
|
+
throw new Error("inventory_stock_response_invalid");
|
|
39
|
+
const result = { sku: row.sku, catalogSkuId: row.catalogSkuId == null ? null : String(row.catalogSkuId),
|
|
40
|
+
source: row.source, providerForSale: row.providerForSale == null ? null : quantity(row.providerForSale),
|
|
41
|
+
activeHolds: quantity(row.activeHolds), safetyStock: quantity(row.safetyStock), available: quantity(row.available), stale: row.stale,
|
|
42
|
+
renewalDemand: quantity(row.renewalDemand), availableForNewPurchases: quantity(row.availableForNewPurchases), excludedOrderHolds: quantity(row.excludedOrderHolds) };
|
|
43
|
+
return [result.sku, result];
|
|
44
|
+
}));
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SubscriptionCommandContext, SubscriptionCommandPort } from "./contracts/commands.js";
|
|
2
|
+
/** Neutral examples. The host authenticates and authorizes actor/client ownership first. */
|
|
3
|
+
export declare function createSubscriptionCommandExamples(commands: SubscriptionCommandPort): {
|
|
4
|
+
customerSkip(context: SubscriptionCommandContext): Promise<import("./contracts/commands.js").SubscriptionCommandReceipt | import("./contracts/commands.js").SubscriptionCommandRefusal | import("./contracts/commands.js").SubscriptionUnsupported>;
|
|
5
|
+
operatorSlide(context: SubscriptionCommandContext, newNextCycleAt: string): Promise<import("./contracts/commands.js").SubscriptionCommandReceipt | import("./contracts/commands.js").SubscriptionCommandRefusal | import("./contracts/commands.js").SubscriptionUnsupported>;
|
|
6
|
+
};
|