@openlup/core 0.11.0 → 0.13.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.
Files changed (40) hide show
  1. package/AGENTS.md +103 -0
  2. package/CHANGELOG.md +64 -8
  3. package/CONTRIBUTING.md +4 -2
  4. package/MAINTAINERS.md +2 -1
  5. package/README.md +59 -21
  6. package/SECURITY.md +4 -4
  7. package/dist/outbox/index.d.ts +55 -0
  8. package/dist/outbox/index.js +1 -0
  9. package/dist/outbox/vocabulary.d.ts +7 -0
  10. package/dist/outbox/vocabulary.js +36 -0
  11. package/dist/platform-runtime/index.d.ts +1 -0
  12. package/dist/platform-runtime/ports.d.ts +24 -0
  13. package/dist/readiness/contracts.d.ts +121 -0
  14. package/dist/readiness/contracts.js +2 -0
  15. package/dist/readiness/declarations.d.ts +45 -0
  16. package/dist/readiness/declarations.js +58 -0
  17. package/dist/readiness/index.d.ts +5 -0
  18. package/dist/readiness/index.js +147 -0
  19. package/dist/readiness/schemaProbe.d.ts +13 -0
  20. package/dist/readiness/schemaProbe.js +25 -0
  21. package/dist/standard-schema/index.d.ts +26 -0
  22. package/dist/standard-schema/index.js +1 -0
  23. package/docs/SUBSCRIPTION_ENGINE.md +235 -0
  24. package/package.json +33 -11
  25. package/release-gates.json +91 -29
  26. package/src/outbox/index.ts +44 -0
  27. package/src/outbox/vocabulary.ts +38 -0
  28. package/src/platform-runtime/index.ts +2 -0
  29. package/src/platform-runtime/ports.ts +43 -0
  30. package/src/readiness/contracts.ts +57 -0
  31. package/src/readiness/declarations.ts +38 -0
  32. package/src/readiness/index.ts +97 -0
  33. package/src/readiness/schemaProbe.ts +24 -0
  34. package/src/standard-schema/index.ts +17 -0
  35. package/dist/checkout/idempotency.d.ts +0 -29
  36. package/dist/checkout/idempotency.js +0 -37
  37. package/dist/checkout/index.d.ts +0 -2
  38. package/dist/checkout/index.js +0 -2
  39. package/src/checkout/idempotency.ts +0 -49
  40. package/src/checkout/index.ts +0 -2
package/AGENTS.md ADDED
@@ -0,0 +1,103 @@
1
+ # `@openlup/core` for agents
2
+
3
+ ## Purpose and kind
4
+
5
+ Kind: `kernel`.
6
+
7
+ `@openlup/core` holds the I/O-free contracts and logic that more than one
8
+ `@openlup/*` package, or an application's composition, reads. Its only runtime
9
+ dependency is `zod`. It performs no I/O, reads no environment and starts no
10
+ process: an application binds its ports and composes it.
11
+
12
+ ## Subpath maturity
13
+
14
+ | Export | Role | Maturity |
15
+ | --- | --- | --- |
16
+ | `./bundle` | kernel | candidate |
17
+ | `./catalog` | kernel | candidate |
18
+ | `./company-identity` | kernel | experimental |
19
+ | `./fulfillment` | kernel | experimental |
20
+ | `./inventory` | kernel | candidate |
21
+ | `./marketing/research` | kernel | experimental |
22
+ | `./partners` | kernel | experimental |
23
+ | `./payment` | kernel | experimental |
24
+ | `./platform-runtime` | kernel | experimental |
25
+ | `./pricing` | kernel | candidate |
26
+ | `./promo` | kernel | candidate |
27
+ | `./risk` | kernel | candidate |
28
+ | `./shipping` | kernel | candidate |
29
+ | `./subscription` | kernel | candidate |
30
+ | `./outbox` | kernel | experimental |
31
+ | `./readiness` | kernel | experimental |
32
+ | `./standard-schema` | kernel | experimental |
33
+ | `./testing` | testing | testing |
34
+
35
+ Any version may change an export, and each change is recorded in
36
+ [the changelog](CHANGELOG.md).
37
+
38
+ ## Wiring example
39
+
40
+ The application owns its composition. This example compiles in OpenLup's CI:
41
+
42
+ ```ts
43
+ import {
44
+ createPlatformBundleRegistry,
45
+ platformEnvSchema,
46
+ type PlatformBundleReadiness,
47
+ type PlatformEnvInput,
48
+ } from "@openlup/core/platform-runtime";
49
+
50
+ // Application composition: the application, not the package, owns its bundles.
51
+ const registry = createPlatformBundleRegistry({
52
+ defaultBundleId: "self-host",
53
+ descriptors: [
54
+ {
55
+ id: "self-host",
56
+ capabilities: {
57
+ http: "node-http",
58
+ scheduler: "cron",
59
+ blob: "filesystem",
60
+ data: "postgres",
61
+ migrations: "sql-files",
62
+ analytics: "none",
63
+ transactional: "smtp",
64
+ },
65
+ readReadiness: (env) =>
66
+ env.APP_BASE_URL ? { ok: true } : { ok: false, error: "APP_BASE_URL is not set" },
67
+ },
68
+ ] as const,
69
+ });
70
+
71
+ export function readPlatformReadiness(input: PlatformEnvInput): PlatformBundleReadiness {
72
+ const env = platformEnvSchema.parse(input);
73
+ return registry.getBundleDescriptor(registry.resolveBundleId(env)).readReadiness(input);
74
+ }
75
+ ```
76
+
77
+ ## Sources and declarations
78
+
79
+ The tarball ships its TypeScript sources under `src/` and its JavaScript and
80
+ declarations under `dist/`. Each export's `types` condition names its
81
+ declaration file, and its `core-source` condition names its source file. Read
82
+ those before guessing at a contract.
83
+
84
+ ## Readiness codes
85
+
86
+ The checker reports `OPENLUP_E_PORT_MISSING`, `OPENLUP_E_EVENT_UNHANDLED`,
87
+ `OPENLUP_E_EVENT_DUPLICATE`, `OPENLUP_E_SCHEDULE_UNBOUND`, `OPENLUP_E_SCHEMA_BEHIND`,
88
+ `OPENLUP_E_SET_MISMATCH` and `OPENLUP_E_ENV_MISSING`. Only a `ready` report admits
89
+ its exact candidate. A host must provide complete installed metadata and selected-adapter
90
+ observations; a report does not prove ACL, function bodies or recovery.
91
+
92
+ ## Using this package in an application
93
+
94
+ - **Do not edit the installed package.** Do not change files under `node_modules/@openlup/`, and
95
+ do not patch it with `patch-package`, `overrides` or a fork.
96
+ - **Change behaviour through seams.** Use this package's ports and options and your application's
97
+ own composition. If a seam is missing, raise an upstream issue.
98
+ - **Copying source is ejection.** Copying this package's source into your application makes the
99
+ copy yours, including its upgrades.
100
+ - **Upgrade every `@openlup/*` package together,** after reading each changelog's `Migration:`
101
+ blocks.
102
+ - **Inside the OpenLup monorepo,** where this package is a workspace, the repository's root
103
+ `AGENTS.md` governs instead.
package/CHANGELOG.md CHANGED
@@ -6,13 +6,41 @@ source previews may already ship some changes, and their release notes say
6
6
  which. Declaration snapshots track candidate drift, not a stable API or
7
7
  SemVer promise.
8
8
 
9
- ## Unreleased — checkout recovery contracts
9
+ ## [Unreleased]
10
10
 
11
- - Add neutral checkout recovery evidence, method, operation and action contracts
12
- to the existing payment surface. They describe guidance only and do not change
13
- payment admission, renewal classification or enabled payment methods.
11
+ ## [0.13.0]
14
12
 
15
- ## [Unreleased]
13
+ - Publishable on the npm `latest` dist-tag as `0.13.0`, from tag
14
+ `openlup-core-v0.13.0`.
15
+
16
+ - Add experimental outbox envelope/handler descriptors, structural validation, job lease and candidate readiness contracts.
17
+ - Check package inventory, event ownership/coverage, actual bindings and qualified schema observations before admitting a new candidate.
18
+
19
+ Migration: existing exports remain; compose the selected rail and bind its schema probe before activation. Unknown observations refuse the new candidate and do not stop a serving version.
20
+
21
+
22
+ ### Changed
23
+
24
+ - `AGENTS.md` gains a required "Using this package in an application" section: do not edit or
25
+ patch the installed package, change behaviour through its seams, and upgrade every
26
+ `@openlup/*` package together. `docs:check` refuses a guide without it.
27
+
28
+ ## [0.12.0]
29
+
30
+ ### Removed
31
+
32
+ - **API REMOVAL: the `./checkout` subpath.** It held only an
33
+ `Idempotency-Key` header-shape helper that no checkout path used.
34
+
35
+ Migration: replace
36
+
37
+ ```ts
38
+ import { validateCheckoutIdempotencyHeader } from "@openlup/core/checkout";
39
+ ```
40
+
41
+ with an application-owned validator, or delete the call if, like the
42
+ reference checkout, your checkout carries its idempotency key in the
43
+ request body.
16
44
 
17
45
  ### Changed
18
46
 
@@ -36,6 +64,15 @@ SemVer promise.
36
64
  `dunning_not_exhausted`. An exhaustive `switch` over the union must handle
37
65
  both.
38
66
 
67
+ - `release-gates.json` sets `packageRelease.versionRule` to `0.N.P`. Below
68
+ 1.0 every `@openlup/*` package carries one set version: a minor set for any
69
+ API, behaviour or schema change, a patch set for a fix only.
70
+
71
+ Migration: a tool that reads `versionRule` expects the set rule. Before:
72
+ `"versionRule": "0.<n>.0"`. After: `"versionRule": "0.N.P"`.
73
+
74
+ - Publishable on the npm `latest` dist-tag as `0.12.0`, from tag
75
+ `openlup-core-v0.12.0`.
39
76
  - Publishable on the npm `preview` dist-tag as `0.11.0`, for source preview
40
77
  `openlup-source-preview/11`.
41
78
  - Publishable on the npm `preview` dist-tag as `0.10.0`, for source preview
@@ -65,6 +102,22 @@ SemVer promise.
65
102
 
66
103
  ### Added
67
104
 
105
+ - `AGENTS.md` ships in the tarball. It states the package's kind and each
106
+ subpath's maturity, gives one wiring example that compiles in CI, points to
107
+ the shipped sources and declarations, and lists the readiness codes the
108
+ package raises (none yet).
109
+ - `release-gates.json` schema 5 declares the package kind (`"kind": "kernel"`)
110
+ and splits the pack budget. Code files (dist JavaScript, declarations and
111
+ shipped sources) and root documentation and metadata files each have their
112
+ own caps on packed bytes and files; the tarball total stays as a backstop.
113
+
114
+ Migration: a tool that reads `release-gates.json` checks `schemaVersion: 5`.
115
+ Before: `"pack": { "maxPackedBytes": …, "maxFiles": … }`. After: `"pack": {
116
+ "code": { "maxPackedBytes": …, "maxFiles": … }, "docs": { … },
117
+ "maxPackedBytes": …, "maxFiles": … }`.
118
+ - Add neutral checkout recovery evidence, method, operation and action contracts
119
+ to the existing payment surface. They describe guidance only and do not change
120
+ payment admission, renewal classification or enabled payment methods.
68
121
  - Export neutral lookup normalization from `./company-identity` for extensions.
69
122
 
70
123
  - `SUBSCRIPTION_STATUS_TRANSITIONS`, the frozen status matrix, and
@@ -226,6 +279,9 @@ SemVer promise.
226
279
 
227
280
  ## Release Status
228
281
 
229
- No npm version has been released yet. A `preview` version establishes no
230
- stable package API or supported upgrade channel. Add a dated section only
231
- after a version is published.
282
+ Versions up to `0.11.0` were published on the npm `preview` dist-tag without
283
+ sections of their own, so the `0.12.0` section also lists the changes they
284
+ carried. A release-preparation pull request turns the Unreleased section into
285
+ the next version's section; its release tag and npm record when it is
286
+ published. No version establishes a stable package API or supported upgrade
287
+ channel.
package/CONTRIBUTING.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # Contributing
2
2
 
3
3
  Commerce Core is public source for framework-independent commerce kernels.
4
- Its npm versions ride on the source previews (`preview` dist-tag only) and
5
- activate no separate package product or stable API.
4
+ Below 1.0 its npm versions are set versions `0.N.P`, shared by every
5
+ `@openlup/*` package and published on the `latest` dist-tag; versions up to
6
+ `0.11.0` rode on the source previews (`preview` dist-tag only). No version
7
+ activates a separate package product or stable API.
6
8
 
7
9
  ## Set up and verify
8
10
 
package/MAINTAINERS.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # Maintainers
2
2
 
3
3
  `@openlup/core` is maintained in the phase-5 platform monorepo. It is not an
4
- independent product; its versions ride on the source previews.
4
+ independent product. Below 1.0 its versions are set versions `0.N.P`, shared by
5
+ every `@openlup/*` package; versions up to `0.11.0` rode on the source previews.
5
6
 
6
7
  ## Responsibilities
7
8
 
package/README.md CHANGED
@@ -1,14 +1,27 @@
1
1
  # Commerce Core
2
2
 
3
- `@openlup/core` is a framework-independent TypeScript workspace package of
4
- subscription and bundle commerce kernels, not a separate library product.
5
-
6
- > [!IMPORTANT]
7
- > Version `0.<n>.0` is packed from source preview `openlup-source-preview/<n>`,
8
- > staged with provenance and approved with 2FA, on the `preview` dist-tag only.
9
- > `npm publish` from this directory is refused. No version implies a stable
10
- > API or supported consumer path. Build, pack, and isolated-import checks are
11
- > package smoke evidence only.
3
+ `@openlup/core` is the kernel of the `@openlup/*` package family: the
4
+ framework-independent TypeScript contracts and logic for subscription and
5
+ bundle commerce that the other packages and an application's composition read.
6
+ Agents start with [AGENTS.md](AGENTS.md). Its "Using this package in an
7
+ application" section, which `docs:check` requires, tells an application's agent
8
+ not to edit or patch the installed package and to upgrade every `@openlup/*`
9
+ package together.
10
+
11
+ ## Channel and stability
12
+
13
+ - **Channel:** npm, on the `latest` dist-tag. Each version is published with
14
+ provenance from its release tag `openlup-core-v<version>` after a protected
15
+ release approval. Versions up to `0.11.0` were published on the `preview`
16
+ dist-tag only. `npm publish` from this directory is refused.
17
+ - **Versions:** below 1.0 every `@openlup/*` package shares one set version
18
+ `0.N.P`: a minor set for any API, behaviour or schema change, a patch set for
19
+ a fix only.
20
+ - **Stability:** development preview. Any version may change an export, and
21
+ each change is recorded in [the changelog](CHANGELOG.md). Pin an exact
22
+ version and read the changelog when you upgrade.
23
+
24
+ The experimental `./outbox`, `./standard-schema` and `./readiness` subpaths provide shared infrastructure contracts. `checkReadiness` evaluates inert contribution descriptors, the complete host-observed package set, actual host bindings (schedule/route function identity must match the contribution) and a bounded schema probe. It never migrates, leases or sends. Only `ready` admits a new candidate; `unknown` and `unsatisfied` leave the serving candidate in place. The host owns inventory completeness, immutable artifact/configuration/schema identity and admission at every work entrance. Catalog existence does not prove SQL bodies, permissions or provider recovery.
12
25
 
13
26
  ## Package Surface Maturity
14
27
 
@@ -20,7 +33,6 @@ promise.
20
33
  | --- | --- | --- | --- |
21
34
  | `./bundle` | kernel | candidate | `smoke/subscriptionBundleStandalone.test.ts` |
22
35
  | `./catalog` | kernel | candidate | `smoke/catalogStandalone.test.ts` |
23
- | `./checkout` | kernel | experimental | `smoke/checkoutStandalone.test.ts` |
24
36
  | `./company-identity` | kernel | experimental | `smoke/companyIdentityStandalone.test.ts` |
25
37
  | `./fulfillment` | kernel | experimental | `smoke/fulfillmentStandalone.test.ts` |
26
38
  | `./inventory` | kernel | candidate | `smoke/inventoryStandalone.test.ts` |
@@ -33,6 +45,9 @@ promise.
33
45
  | `./risk` | kernel | candidate | `smoke/riskStandalone.test.ts` |
34
46
  | `./shipping` | kernel | candidate | `smoke/shippingStandalone.test.ts` |
35
47
  | `./subscription` | kernel | candidate | `smoke/subscriptionBundleStandalone.test.ts` |
48
+ | `./outbox` | kernel | experimental | `smoke/outboxStandalone.test.ts` |
49
+ | `./readiness` | kernel | experimental | `smoke/readinessStandalone.test.ts` |
50
+ | `./standard-schema` | kernel | experimental | `smoke/standardSchemaStandalone.test.ts` |
36
51
  | `./testing` | testing | testing | `smoke/testingStandalone.test.ts` |
37
52
 
38
53
  `release-gates.json` records four distinct evidence classes:
@@ -45,9 +60,26 @@ promise.
45
60
  - `externalConsumerEvidence`: not yet evaluated; a first-party packed consumer
46
61
  remains package smoke, not external adoption.
47
62
 
48
- ## Local verification
63
+ ## Use in an application
64
+
65
+ From your application's root, with Node 24 and npm 11.19.0:
66
+
67
+ ```sh
68
+ npm install --save-exact @openlup/core@0.12.0
69
+ ```
70
+
71
+ Read the installed `AGENTS.md`, then compose the [typed wiring example](AGENTS.md#wiring-example)
72
+ with your application's own ports and options. Inspect the shipped sources and
73
+ declarations for the exact version you installed. A missing seam needs an
74
+ upstream proposal under your application's submission authority; the dependency
75
+ guide grants no permission to publish an issue or change your application.
76
+ Keep every installed `@openlup/*` package on the same exact set version.
77
+
78
+ ## Local verification from source
49
79
 
50
- From this package directory:
80
+ The following developer commands require a source checkout of this package;
81
+ the npm tarball omits its development scripts and tests. From the source package
82
+ directory:
51
83
 
52
84
  ```sh
53
85
  npm ci
@@ -55,12 +87,18 @@ npm run ci
55
87
  ```
56
88
 
57
89
  Focused proofs are `npm run api:check`, `npm run release:check`, and
58
- `npm run test:consumer`. The root test script skips this suite. A `preview`
59
- install is evaluation, not a supported install.
60
-
61
- Repository neutrality checks reuse the existing source scanner through
62
- [the tree counting interface](./scripts/neutrality-tree-counts.ts). This
63
- process interface reads JSON containing source paths, contents and a policy
90
+ `npm run test:consumer`. The root test script skips this suite.
91
+ `npm run docs:check` requires relative links in shipped Markdown to resolve to
92
+ files actually packed in the tarball; a target present only in source refuses.
93
+ Ambiguous destinations refuse explicitly: use literal punctuation or
94
+ percent-encoded filenames, with ASCII whitespace before an optional title.
95
+ Raw ampersands, angle characters and Unicode whitespace in local destinations
96
+ require a canonical rewrite rather than passing an incomplete link check.
97
+
98
+ The [repository neutrality checks](https://github.com/openlup/openlup/blob/openlup-core-v0.12.0/CONTRIBUTING.md#development-preview-checks)
99
+ reuse the source scanner through `./scripts/neutrality-tree-counts.ts` relative
100
+ to this source package. This process interface reads JSON containing source paths,
101
+ contents and a policy
64
102
  from standard input, then emits finding counts for each path. Shell sources
65
103
  retain the scanner's existing shell handling. The interface adds no package
66
104
  export and changes no matcher or kernel behavior.
@@ -68,7 +106,7 @@ export and changes no matcher or kernel behavior.
68
106
  Repository lint keeps this package's production source independent of configured
69
107
  provider SDKs and explicit industry contract names. Adopter adapters compose
70
108
  providers; generic ports can forward opaque extension data. See the
71
- [syntax scope and exceptions](https://github.com/openlup/openlup/blob/main/CONTRIBUTING.md#development-preview-checks).
109
+ [syntax scope and exceptions](https://github.com/openlup/openlup/blob/openlup-core-v0.12.0/CONTRIBUTING.md#development-preview-checks).
72
110
 
73
111
  The repository checker also calls the UI neutrality counting process with
74
112
  `--counts-json` to count its existing patterns over the supplied sources. Running that checker without
@@ -84,9 +122,9 @@ neutrality evidence, not package activation or consumer compatibility evidence.
84
122
 
85
123
  ## Kernel Documentation
86
124
 
125
+ <!-- openlup-doc-impact {"unit":"core","digest":"sha256-bf338e121135843e55d78dab92d8620fd1dcd67be34e9302aef01ea893d361ba","reason":"Release preparation changes only the core manifest and its lockfile version from 0.12.0 to 0.13.0. Exports, dependencies, API snapshots, implementation, package gates and the installation and verification guidance remain unchanged; the changelog identifies the prepared set."} -->
126
+
87
127
  - [`docs/SUBSCRIPTION_ENGINE.md`](docs/SUBSCRIPTION_ENGINE.md) — what the
88
128
  `./subscription` kernel owns, its deterministic-clock contract, the
89
129
  late-payment cycle-shift rule and its monotonic clamp, and how a host
90
130
  application consumes it.
91
-
92
- <!-- openlup-doc-impact {"unit":"core","digest":"sha256-fbf1589b7a2c49f656a295c102b1076d8beaa5180bdc369ba575c462f39ec96f","reason":"The core manifest and lockfile advance only the lockstep version from 0.10.0 to 0.11.0. Exports, dependencies, package smoke, publication settings, and development-preview maturity remain unchanged."} -->
package/SECURITY.md CHANGED
@@ -2,10 +2,10 @@
2
2
 
3
3
  ## Release Support
4
4
 
5
- No package version is supported. A `0.<n>.0` version on the `preview`
6
- dist-tag is development-preview evaluation, not a supported public release. A
7
- future support policy belongs to phase-5 public platform governance, not to a
8
- separate package release channel.
5
+ No package version is supported. A `0.N.P` version, on the `preview` dist-tag
6
+ up to `0.11.0` or on `latest` after it, is development-preview evaluation, not a
7
+ supported public release. A future support policy belongs to phase-5 public
8
+ platform governance, not to a separate package release channel.
9
9
 
10
10
  ## Vulnerability Reporting
11
11
 
@@ -0,0 +1,55 @@
1
+ /** @beta Shared event envelope. Storage and execution policy belong to the rail. */
2
+ export interface OutboxEventRow {
3
+ id: string;
4
+ created_at: string;
5
+ available_at: string;
6
+ processed_at: string | null;
7
+ aggregate_type: string;
8
+ aggregate_id: string;
9
+ event_type: string;
10
+ idempotency_key: string;
11
+ status: string;
12
+ attempts: number;
13
+ payload: Record<string, unknown>;
14
+ error: string | null;
15
+ metadata: Record<string, unknown>;
16
+ }
17
+ /** @beta */
18
+ export type OutboxHandlerOutcome = {
19
+ kind: "processed";
20
+ detail?: Record<string, unknown>;
21
+ } | {
22
+ kind: "retry";
23
+ reason: string;
24
+ } | {
25
+ kind: "discard";
26
+ reason: string;
27
+ benign?: boolean;
28
+ } | {
29
+ kind: "snooze";
30
+ reason: string;
31
+ };
32
+ /** @beta Phase observations are transient; never put payloads or credentials here. */
33
+ export interface OutboxHandlerExecutionContext {
34
+ setPhase(phase: string): void;
35
+ }
36
+ /** @beta Inert registration shared by preflight and the run-bound builder. */
37
+ export interface OutboxHandlerDescriptor {
38
+ readonly eventType: string;
39
+ readonly timeoutMs: number;
40
+ }
41
+ /** @beta Structural abort signal, shared by browser and server implementations. */
42
+ export interface OutboxAbortSignal {
43
+ readonly aborted: boolean;
44
+ readonly reason: unknown;
45
+ addEventListener(type: "abort", listener: () => void, options?: {
46
+ once?: boolean;
47
+ }): void;
48
+ removeEventListener(type: "abort", listener: () => void): void;
49
+ }
50
+ /** @beta Effects must be idempotent and honor the abort signal. */
51
+ export interface OutboxHandler<Signal extends OutboxAbortSignal = OutboxAbortSignal> extends OutboxHandlerDescriptor {
52
+ handle(row: OutboxEventRow, signal: Signal, execution?: OutboxHandlerExecutionContext): Promise<OutboxHandlerOutcome>;
53
+ }
54
+ export { PLATFORM_EVENT_VOCABULARY } from "./vocabulary.js";
55
+ export type { EventVocabularyEntry } from "./vocabulary.js";
@@ -0,0 +1 @@
1
+ export { PLATFORM_EVENT_VOCABULARY } from "./vocabulary.js";
@@ -0,0 +1,7 @@
1
+ /** @beta Vocabulary ownership is separate from consumer registration. */
2
+ export interface EventVocabularyEntry {
3
+ eventType: string;
4
+ owner: string;
5
+ }
6
+ /** @beta Applications supply their complete ordered persisted vocabulary separately. */
7
+ export declare const PLATFORM_EVENT_VOCABULARY: readonly EventVocabularyEntry[];
@@ -0,0 +1,36 @@
1
+ /** @beta Applications supply their complete ordered persisted vocabulary separately. */
2
+ export const PLATFORM_EVENT_VOCABULARY = [
3
+ { eventType: "commerce.order_draft.created", owner: "@openlup/core" },
4
+ { eventType: "commerce.order.paid", owner: "@openlup/core" },
5
+ { eventType: "commerce.order.paid.email", owner: "@openlup/core" },
6
+ { eventType: "commerce.payment.failed", owner: "@openlup/core" },
7
+ { eventType: "commerce.checkout.expired", owner: "@openlup/core" },
8
+ { eventType: "commerce.order.canceled", owner: "@openlup/core" },
9
+ { eventType: "commerce.order.refunded", owner: "@openlup/core" },
10
+ { eventType: "commerce.shipment.dispatched", owner: "@openlup/core" },
11
+ { eventType: "commerce.shipment.delivered", owner: "@openlup/core" },
12
+ { eventType: "commerce.shipment.exception", owner: "@openlup/core" },
13
+ { eventType: "commerce.return.approved", owner: "@openlup/core" },
14
+ { eventType: "commerce.return.rejected", owner: "@openlup/core" },
15
+ { eventType: "commerce.order.review_request", owner: "@openlup/core" },
16
+ { eventType: "commerce.order.review_effects", owner: "@openlup/core" },
17
+ { eventType: "commerce.product.back_in_stock", owner: "@openlup/core" },
18
+ { eventType: "commerce.order_draft.abandoned.1h", owner: "@openlup/core" },
19
+ { eventType: "commerce.order_draft.abandoned.24h", owner: "@openlup/core" },
20
+ { eventType: "commerce.order_draft.abandoned.72h", owner: "@openlup/core" },
21
+ { eventType: "commerce.order.reorder_reminder", owner: "@openlup/core" },
22
+ { eventType: "commerce.checkout_recovery", owner: "@openlup/core" },
23
+ { eventType: "subscription.cancelled", owner: "@openlup/core" },
24
+ { eventType: "subscription.created", owner: "@openlup/core" },
25
+ { eventType: "subscription.activation_action_required", owner: "@openlup/core" },
26
+ { eventType: "subscription.pause_reminder_due", owner: "@openlup/core" },
27
+ { eventType: "subscription.paused", owner: "@openlup/core" },
28
+ { eventType: "subscription.resumed", owner: "@openlup/core" },
29
+ { eventType: "subscription.delivery_rescheduled", owner: "@openlup/core" },
30
+ { eventType: "subscription.cycle_skipped", owner: "@openlup/core" },
31
+ { eventType: "subscription.address_changed", owner: "@openlup/core" },
32
+ { eventType: "subscription.package_changed", owner: "@openlup/core" },
33
+ { eventType: "subscription.renewal_upcoming", owner: "@openlup/core" },
34
+ { eventType: "accounting.order.reversal_requested", owner: "@openlup/core" },
35
+ { eventType: "commerce.fulfillment.handed_over", owner: "@openlup/core" },
36
+ ];
@@ -8,3 +8,4 @@ export { createPlatformBundleRegistry, platformEnvSchema, } from "./platformKern
8
8
  export type { CreatePlatformBundleRegistryInput, PlatformBundleDescriptor, PlatformBundleRegistry, PlatformBundleReadiness, PlatformEnv, PlatformEnvInput, } from "./platformKernel.js";
9
9
  /** @beta */
10
10
  export type { AnalyticsPort, BlobStoragePort, DataGatewayPort, HttpRuntimePort, MigrationRunnerPort, PlatformHttpRequest, PlatformHttpResponse, SchedulerPort, TransactionalRuntimePort, } from "./ports.js";
11
+ export type { JobLeasePort, PlatformJobTriggerKind, PlatformJobInvocation, PlatformJobClaim, PlatformJobFinishStatus, PlatformJobFinishSummary } from "./ports.js";
@@ -98,3 +98,27 @@ export interface TransactionalRuntimePort {
98
98
  status: number;
99
99
  }>;
100
100
  }
101
+ /** @beta Invocation evidence and claim/finish contract shared by infrastructure rails. */
102
+ export type PlatformJobTriggerKind = "worker" | "scheduler" | "operator";
103
+ export type PlatformJobInvocation = {
104
+ triggerKind: PlatformJobTriggerKind;
105
+ /** Observational adapter evidence; it never grants execution authority. */
106
+ invocationSource: string;
107
+ };
108
+ export type PlatformJobClaim = {
109
+ acquired: boolean;
110
+ runId: string | null;
111
+ reason: string;
112
+ };
113
+ export type PlatformJobFinishStatus = "success" | "failed";
114
+ export type PlatformJobFinishSummary = {
115
+ checked: number;
116
+ updated: number;
117
+ failures: number;
118
+ skipped: boolean;
119
+ reason?: string;
120
+ };
121
+ export interface JobLeasePort {
122
+ claimJobRun(jobName: string, invocation: PlatformJobInvocation, leaseSeconds?: number): Promise<PlatformJobClaim>;
123
+ finishJobRun(jobName: string, runId: string, invocation: PlatformJobInvocation, status: PlatformJobFinishStatus, result: PlatformJobFinishSummary, extraMetadata?: Record<string, unknown>): Promise<boolean>;
124
+ }
@@ -0,0 +1,121 @@
1
+ import type { OutboxHandlerDescriptor } from "../outbox/index.js";
2
+ import type { EventVocabularyEntry } from "../outbox/vocabulary.js";
3
+ /** @beta */
4
+ export declare const READINESS_CODES: readonly ["OPENLUP_E_PORT_MISSING", "OPENLUP_E_EVENT_UNHANDLED", "OPENLUP_E_EVENT_DUPLICATE", "OPENLUP_E_SCHEDULE_UNBOUND", "OPENLUP_E_SCHEMA_BEHIND", "OPENLUP_E_SET_MISMATCH", "OPENLUP_E_ENV_MISSING"];
5
+ /** @beta */
6
+ export type ReadinessCode = typeof READINESS_CODES[number];
7
+ /** @beta */
8
+ export interface ReadinessIssue {
9
+ code: ReadinessCode;
10
+ package: string;
11
+ subject: string;
12
+ fix: string;
13
+ observation?: string;
14
+ }
15
+ /** @beta */
16
+ export interface SchemaObject {
17
+ kind: "table" | "column" | "function";
18
+ name: string;
19
+ signature?: string;
20
+ }
21
+ /** @beta Version is an adapter-specific migration identity, not inferred from object existence. */
22
+ export interface RequiredSchema {
23
+ version: string;
24
+ migration: string;
25
+ objects: readonly SchemaObject[];
26
+ }
27
+ /** @beta */
28
+ export interface PackageManifest {
29
+ name: string;
30
+ version: string;
31
+ kind: "kernel" | "rail" | "capability" | "implementation";
32
+ emits: readonly string[];
33
+ handles: readonly string[];
34
+ schedules: readonly {
35
+ id: string;
36
+ cadenceSeconds: number;
37
+ }[];
38
+ routes: readonly string[];
39
+ requiredPorts: readonly string[];
40
+ env: readonly string[];
41
+ requiredSchema?: RequiredSchema;
42
+ }
43
+ /** @beta Run-bound handlers are represented by their shared inert descriptors. */
44
+ export interface Contribution {
45
+ manifest: PackageManifest;
46
+ handlers: readonly OutboxHandlerDescriptor[];
47
+ schedules: readonly {
48
+ id: string;
49
+ cadenceSeconds: number;
50
+ run: (...args: never[]) => unknown;
51
+ }[];
52
+ routes: readonly {
53
+ id: string;
54
+ handle: (...args: never[]) => unknown;
55
+ }[];
56
+ }
57
+ /** @beta Host-observed inventory, including core. The loader owns completeness. */
58
+ export interface LoadedPackage {
59
+ name: string;
60
+ version: string;
61
+ kind: PackageManifest["kind"];
62
+ }
63
+ /** @beta Candidate identity must change when configuration, schema or artifact changes. */
64
+ export interface CandidateIdentity {
65
+ artifact: string;
66
+ configuration: string;
67
+ environment: string;
68
+ database: string;
69
+ schema: string;
70
+ }
71
+ /** @beta */
72
+ export interface EventExemption {
73
+ pattern: string;
74
+ prefix: boolean;
75
+ owner: string;
76
+ reason: string;
77
+ state: "ignored" | "dormant";
78
+ }
79
+ /** @beta */
80
+ export interface ReadinessInput {
81
+ candidate: CandidateIdentity;
82
+ inventoryComplete: boolean;
83
+ loadedPackages: readonly LoadedPackage[];
84
+ contributions: readonly Contribution[];
85
+ vocabulary: readonly EventVocabularyEntry[];
86
+ exemptions: readonly EventExemption[];
87
+ bindings: {
88
+ ports: Readonly<Record<string, unknown>>;
89
+ triggers: Readonly<Record<string, unknown>>;
90
+ routes: Readonly<Record<string, unknown>>;
91
+ env: Readonly<Record<string, string | undefined>>;
92
+ };
93
+ schemaProbe: SchemaProbePort;
94
+ probeTimeoutMs?: number;
95
+ }
96
+ /** @beta A bounded catalog observation, not proof of SQL bodies, ACL or recovery. */
97
+ export interface SchemaObservation {
98
+ database: string;
99
+ version: string | null;
100
+ objects: readonly {
101
+ object: SchemaObject;
102
+ present: boolean | null;
103
+ }[];
104
+ }
105
+ /** @beta */
106
+ export interface SchemaProbePort {
107
+ observe(requirement: RequiredSchema): Promise<SchemaObservation>;
108
+ }
109
+ /** @beta Each operation commits before resolving; never lend a producer transaction to dispatch. */
110
+ export interface SqlExecutor {
111
+ query<Row extends Record<string, unknown> = Record<string, unknown>>(text: string, values?: readonly unknown[]): Promise<{
112
+ rows: Row[];
113
+ }>;
114
+ }
115
+ /** @beta */
116
+ export interface ReadinessReport {
117
+ state: "ready" | "unsatisfied" | "unknown";
118
+ candidate: CandidateIdentity;
119
+ loadedPackages: readonly LoadedPackage[];
120
+ issues: readonly ReadinessIssue[];
121
+ }
@@ -0,0 +1,2 @@
1
+ /** @beta */
2
+ export const READINESS_CODES = ["OPENLUP_E_PORT_MISSING", "OPENLUP_E_EVENT_UNHANDLED", "OPENLUP_E_EVENT_DUPLICATE", "OPENLUP_E_SCHEDULE_UNBOUND", "OPENLUP_E_SCHEMA_BEHIND", "OPENLUP_E_SET_MISMATCH", "OPENLUP_E_ENV_MISSING"];