@fabricorg/platform-host 5.0.0 → 7.0.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 +91 -0
- package/MIGRATION-6-PRODUCTION.md +59 -0
- package/README.md +89 -11
- package/dist/index.cjs +1154 -98
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +377 -13
- package/dist/index.d.ts +377 -13
- package/dist/index.js +1150 -100
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,96 @@
|
|
|
1
1
|
# @fabricorg/platform-host
|
|
2
2
|
|
|
3
|
+
## 7.0.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [274d948]
|
|
8
|
+
- @fabricorg/assembly@0.4.0
|
|
9
|
+
|
|
10
|
+
## 6.0.0
|
|
11
|
+
|
|
12
|
+
### Major Changes
|
|
13
|
+
|
|
14
|
+
- fb14d67: Add versioned PostgreSQL migrations and live PostgreSQL 16 certification. Fence and renew invocation
|
|
15
|
+
and outbox leases, bound publisher calls, reject stale finalization, and add deterministic Temporal
|
|
16
|
+
saga workflow binding with explicit parent lifecycle activities.
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
- ef4e3eb: Classify adapter outcomes: add additive `AdapterOutcomeKind` (`success`, `transient_failure`,
|
|
21
|
+
`permanent_failure`, `timeout`, `ambiguous`) and `AdapterOutcomeEvidence` to the portable adapter
|
|
22
|
+
contract. The retry layer now retries only transient idempotent outcomes; permanent failures,
|
|
23
|
+
timeouts, and ambiguous results are never retried. Ambiguous outcomes are routed to
|
|
24
|
+
`reconciliation_required` with durable `ExternalReconciliation` evidence and an
|
|
25
|
+
`AdapterInvocationAmbiguous` lifecycle event. Add deadline and cancellation context to
|
|
26
|
+
`AdapterExecutionContext`. Backward compatible: adapters that omit `outcome` behave as before.
|
|
27
|
+
- 293561d: Close adapter and saga correctness gaps: deliver actual deadline and AbortSignal context to adapters, require the governed Host to classify thrown adapter failures before retrying, reject contradictory successful ambiguous outcomes, reserve parent lifecycle identity prefixes, and provide a durable Platform Host parent lifecycle adapter tested through public store seams.
|
|
28
|
+
- 9a145a3: Add assembly and initiating SDUI release digests to durable governance runtime
|
|
29
|
+
evidence. Hosts can attach both through trusted configuration, including a
|
|
30
|
+
per-submission release resolver, and validate digest shape before creating the
|
|
31
|
+
invocation. Composition-bound hosts verify their assembly lockfile against the
|
|
32
|
+
exact loaded capability artifacts before accepting submissions.
|
|
33
|
+
- 4e585a4: Close final production-maturity correctness gaps: expired leases can no longer be renewed,
|
|
34
|
+
saga parent transitions are serialized, atomic, terminal-safe, and retry-idempotent by lifecycle identity, hydrated
|
|
35
|
+
projections must meet requested checkpoints, and SDUI releases accept components only from
|
|
36
|
+
resolved document packs. The release gate now verifies every package and public subpath in
|
|
37
|
+
isolated ESM, CommonJS, and TypeScript consumers.
|
|
38
|
+
- 12ffe62: Add vendor-neutral lifecycle telemetry and tenant-safe health/readiness snapshots for workers,
|
|
39
|
+
leases, outbox delivery, reconciliation-required work, and approval waits. Health output contains
|
|
40
|
+
aggregate counts only and does not expose invocation parameters or secrets.
|
|
41
|
+
- fb14d67: Execute state guards with trusted Host context, correct filtered-ledger replay semantics, make
|
|
42
|
+
dispatcher failure retryable, fail closed for unsafe saga and non-idempotent recovery paths, preserve
|
|
43
|
+
outbox consistency, and bound and redact OPA HTTP failures.
|
|
44
|
+
- 5b6ccd5: Certification evidence now invokes real public Host/store/worker/outbox APIs instead of toy simulations. Fault and load certification exercises `createGovernedActionHost`, `MemoryPlatformHostStore`, `runPlatformActionWorkerCycle`, and `runOutboxRelayCycle` through their public seams. The machine-readable report includes a `pendingGates` section that distinguishes local passes from required external evidence. Publish and verify scripts include `@fabricorg/assembly` and `@fabricorg/sdui-release` in dependency-safe order. A new `pnpm verify:packed` script packs all public packages and installs them into clean ESM and CommonJS consumers using only declared dependencies.
|
|
45
|
+
|
|
46
|
+
### Patch Changes
|
|
47
|
+
|
|
48
|
+
- Updated dependencies [62dd1ca]
|
|
49
|
+
- @fabricorg/assembly@0.2.0
|
|
50
|
+
|
|
51
|
+
### Additional release notes
|
|
52
|
+
|
|
53
|
+
### Major Changes
|
|
54
|
+
|
|
55
|
+
- Add checksummed forward-only PostgreSQL migrations, live PostgreSQL 16 CI certification, renewable
|
|
56
|
+
fenced invocation and outbox leases, transaction-scoped fenced finalization, and bounded outbox
|
|
57
|
+
publishing. Recoverable stores now implement lease renewal and fenced update operations, and
|
|
58
|
+
dispatch inputs include the action ID required for deterministic workflow binding. Host also
|
|
59
|
+
declares `@fabricorg/assembly` as a peer used to verify composition-bound module artifacts; see
|
|
60
|
+
`MIGRATION-6-PRODUCTION.md`.
|
|
61
|
+
|
|
62
|
+
### Minor Changes
|
|
63
|
+
|
|
64
|
+
- Add vendor-neutral lifecycle telemetry and tenant-safe health/readiness snapshots for workers,
|
|
65
|
+
invocation and outbox leases, backlog, dead letters, reconciliation-required work, and approval
|
|
66
|
+
waits. Health output contains aggregate counts only and reports unavailable sources as unhealthy.
|
|
67
|
+
- Classify adapter outcomes: route ambiguous adapter results to `reconciliation_required` with
|
|
68
|
+
durable `ExternalReconciliation` evidence and an `AdapterInvocationAmbiguous` lifecycle event.
|
|
69
|
+
Permanent failures and timeouts are not retried. Add `adapter_reconciliation` column to the
|
|
70
|
+
PostgreSQL action invocations table.
|
|
71
|
+
- Deliver actual deadline and `AbortSignal` context to adapters via `adapterDeadlineMs` host option.
|
|
72
|
+
The governed Host explicitly classifies thrown adapter failures before retrying (`classifyThrownError`).
|
|
73
|
+
Reject contradictory successful ambiguous outcomes via `assertAdapterOutcomeConsistency`.
|
|
74
|
+
- Add `createDurableSagaParentLifecycle` adapter: a Platform Host store-backed implementation of
|
|
75
|
+
the saga parent lifecycle contract (progress, approval, cancellation, completion, failure) that
|
|
76
|
+
survives worker rollover through durable store seams.
|
|
77
|
+
- Refuse invocation and outbox lease renewal after expiry. Make saga parent lifecycle events and
|
|
78
|
+
parent status transitions atomic, idempotent by stable lifecycle identity, and contradictory-evidence
|
|
79
|
+
safe. Serialize concurrent transitions with a transaction-scoped parent lock and prevent distinct
|
|
80
|
+
transitions from rewriting terminal parent state.
|
|
81
|
+
- Evaluate state-machine guards with authoritative state and trusted context inside the mutation
|
|
82
|
+
unit of work, with an optional transaction-scoped state reader for custom stores.
|
|
83
|
+
- Keep failed dispatcher submissions pending and allow idempotent resubmission to retry the stable
|
|
84
|
+
workflow ID.
|
|
85
|
+
- Fail closed for direct saga execution and interrupted inline non-idempotent actions.
|
|
86
|
+
- Workers no longer claim unleased `running` rows created by inline execution, saga lifecycle retries
|
|
87
|
+
use an identity-scoped event lookup while holding the parent lock, and completed adapters clear
|
|
88
|
+
their deadline timers.
|
|
89
|
+
- Preserve provisional consistency when PostgreSQL outbox rows are hydrated.
|
|
90
|
+
- Persist verified assembly and initiating promoted-release digests with every
|
|
91
|
+
composition-bound invocation. Registry module artifacts are checked against
|
|
92
|
+
the approved lockfile before Host accepts submissions.
|
|
93
|
+
|
|
3
94
|
## 5.0.0
|
|
4
95
|
|
|
5
96
|
### Major Changes
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Migrating `@fabricorg/platform-host` 5.x to 6.x
|
|
2
|
+
|
|
3
|
+
Host 6 makes production recovery fencing explicit and adds optional,
|
|
4
|
+
assembly-verified runtime composition.
|
|
5
|
+
|
|
6
|
+
## Install the composition peer
|
|
7
|
+
|
|
8
|
+
Host now imports `@fabricorg/assembly` for lockfile and runtime artifact
|
|
9
|
+
verification. Install a compatible release beside Host:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
pnpm add @fabricorg/platform-host@^6 @fabricorg/assembly@^0.3 @fabricorg/platform@^1.2
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Update recoverable stores and dispatchers
|
|
16
|
+
|
|
17
|
+
- Implement the new invocation and outbox lease-renewal and fenced-update
|
|
18
|
+
methods on custom recoverable stores.
|
|
19
|
+
- Implement `getEvent()` on custom atomic mutation transactions so saga
|
|
20
|
+
lifecycle retries perform an identity-scoped lookup instead of scanning the
|
|
21
|
+
tenant event ledger.
|
|
22
|
+
- Preserve monotonic lease tokens and reject writes from expired or superseded
|
|
23
|
+
claims.
|
|
24
|
+
- Include `actionId` in custom dispatcher inputs so workflow identity remains
|
|
25
|
+
deterministic.
|
|
26
|
+
- Run `PostgresPlatformHostStore.ensureSchema()` through your controlled
|
|
27
|
+
migration process before starting Host 6 workers.
|
|
28
|
+
- Treat applied migration checksums as immutable. Add a new migration version
|
|
29
|
+
for every schema change instead of editing the version 1 baseline.
|
|
30
|
+
|
|
31
|
+
Memory and PostgreSQL adapters included with Host already satisfy these
|
|
32
|
+
contracts.
|
|
33
|
+
|
|
34
|
+
## Opt into verified composition
|
|
35
|
+
|
|
36
|
+
Existing hosts can omit `composition`. To bind runtime execution to an approved
|
|
37
|
+
application assembly:
|
|
38
|
+
|
|
39
|
+
1. Set `version` and `manifestDigest` on every registered `FabricModule`.
|
|
40
|
+
2. Pass the integrity-checked `AssemblyLockfile` through `composition.assembly`.
|
|
41
|
+
3. Resolve an initiating promoted release digest from trusted gateway or release
|
|
42
|
+
registry context, never from action parameters.
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
const host = createGovernedActionHost({
|
|
46
|
+
registry,
|
|
47
|
+
store,
|
|
48
|
+
authorization,
|
|
49
|
+
composition: {
|
|
50
|
+
assembly,
|
|
51
|
+
resolveInitiatingReleaseDigest: (submission) =>
|
|
52
|
+
releaseRegistry.resolveTrustedDigest(submission.provenance),
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Host refuses to start when a registered module's namespace, version, or
|
|
58
|
+
compiler manifest digest differs from the approved lockfile. Resolver failures
|
|
59
|
+
and invalid release digests fail before durable invocation creation.
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
The canonical host for the `@fabricorg/platform` mutation pipeline.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
|
-
pnpm add @fabricorg/platform@^1.
|
|
6
|
+
pnpm add @fabricorg/platform@^1.2.0 @fabricorg/platform-host@^6.0.0 @fabricorg/assembly@^0.3.0
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
## AI agent integration boundary
|
|
@@ -15,7 +15,7 @@ registration, and submit stable idempotent commands. The gateway derives tenant
|
|
|
15
15
|
calls `submitAction()`; an agent must never call handlers, adapters, workflow internals, or database
|
|
16
16
|
writes directly.
|
|
17
17
|
|
|
18
|
-
See the [Platform Host
|
|
18
|
+
See the [Platform Host 6.x agent integration
|
|
19
19
|
guide](https://platform.fabric.pro/docs/platform/reference/platform-host) for application wiring,
|
|
20
20
|
execution-time authorization, the PostgreSQL transaction binder, recovery semantics, and the external
|
|
21
21
|
gateway contract.
|
|
@@ -41,8 +41,10 @@ injected `now` clock is also passed to ordinary policy evaluation.
|
|
|
41
41
|
|
|
42
42
|
Production polling workers can use `createStoreBackedActionDispatcher()` plus
|
|
43
43
|
`runPlatformActionWorker()`. The pending invocation row is the durable queue item; workers claim
|
|
44
|
-
bounded batches with an atomic lease and `FOR UPDATE SKIP LOCKED
|
|
45
|
-
|
|
44
|
+
bounded batches with an atomic, renewable lease and `FOR UPDATE SKIP LOCKED`. Every claim advances a
|
|
45
|
+
fencing token. A heartbeat may renew only a lease that has not expired; after expiry, the work must be
|
|
46
|
+
reclaimed so its token advances. An expired worker cannot finalize after another worker takes ownership. Pass a stable
|
|
47
|
+
`idempotencyKey` to `submitAction()` so retries resolve
|
|
46
48
|
to the original tenant-scoped invocation instead of creating another mutation.
|
|
47
49
|
|
|
48
50
|
New rows bind that key to the action version, actor/authority binding, and a versioned canonical
|
|
@@ -56,6 +58,13 @@ adapter that already reached `succeeded`, and event, policy, and adapter writes
|
|
|
56
58
|
stale action that was not declared idempotent fails terminally for manual reconciliation instead of
|
|
57
59
|
silently rerunning unknown side effects.
|
|
58
60
|
|
|
61
|
+
Adapters may classify outcomes as `success`, `transient_failure`, `permanent_failure`, `timeout`,
|
|
62
|
+
or `ambiguous`. The retry layer retries only transient idempotent outcomes; permanent failures,
|
|
63
|
+
timeouts, and ambiguous results are never retried. An ambiguous outcome — where the external effect
|
|
64
|
+
may or may not have been applied — is routed to `reconciliation_required` with durable
|
|
65
|
+
`ExternalReconciliation` evidence and an `AdapterInvocationAmbiguous` lifecycle event rather than
|
|
66
|
+
blindly retrying an unsafe effect.
|
|
67
|
+
|
|
59
68
|
## Execution authorization
|
|
60
69
|
|
|
61
70
|
Submission authorization proves that a caller may create an invocation. Applications that delegate
|
|
@@ -121,6 +130,13 @@ application knows how its `TDb` is rebound to the transaction's SQL client.
|
|
|
121
130
|
Stores without this additive capability retain the legacy boundary for compatibility and must not
|
|
122
131
|
claim atomic domain-write/event persistence.
|
|
123
132
|
|
|
133
|
+
`createDurableSagaParentLifecycle()` requires this capability. Each parent lifecycle transition uses a
|
|
134
|
+
stable `lifecycleId` as its causation identity, appends its audit event, and updates the parent invocation
|
|
135
|
+
in the same transaction. The transaction locks the parent invocation row before checking prior
|
|
136
|
+
evidence, so concurrent transitions serialize. Retrying the same identity and evidence is a no-op;
|
|
137
|
+
reusing it with contradictory evidence fails closed, and a distinct transition cannot rewrite a
|
|
138
|
+
terminal parent. `createSagaParentActivities()` supplies deterministic identities for Temporal callers.
|
|
139
|
+
|
|
124
140
|
Actions can optionally declare `resultSchema`. The Host validates public handler result data after
|
|
125
141
|
the handler and before canonical event append or adapter execution. Invalid results fail the invocation,
|
|
126
142
|
emit no domain/completion event, invoke no adapter, and persist only a sanitized validation failure.
|
|
@@ -191,9 +207,18 @@ observations. Provider-specific authentication and clients do not belong here. F
|
|
|
191
207
|
the optional Platform integration exported by `@fabric-harness/databricks`.
|
|
192
208
|
|
|
193
209
|
Every newly submitted invocation also records `runtimeEvidence`. The host always supplies the
|
|
194
|
-
portable governance and host contract generations; applications should add the
|
|
195
|
-
package version, policy ruleset version, and provider bridge
|
|
196
|
-
|
|
210
|
+
portable governance and host contract generations; applications should add the
|
|
211
|
+
deployed host package version, policy ruleset version, and provider bridge
|
|
212
|
+
identity. A trusted `composition` configuration attaches the verified assembly
|
|
213
|
+
digest and can resolve the promoted SDUI release that initiated each submission.
|
|
214
|
+
Neither identity is accepted directly from caller input. This makes an audit
|
|
215
|
+
record explain which composition, release, contract, and provider adapter
|
|
216
|
+
governed a mutation after dependencies have moved on.
|
|
217
|
+
|
|
218
|
+
Composition-bound hosts require an explicit module registry. Every registered
|
|
219
|
+
module must carry its published `version` and compiler `manifestDigest`; Host
|
|
220
|
+
compares those identities directly with the integrity-checked assembly lockfile
|
|
221
|
+
before accepting any submission.
|
|
197
222
|
|
|
198
223
|
```ts
|
|
199
224
|
const host = createGovernedActionHost({
|
|
@@ -203,19 +228,72 @@ const host = createGovernedActionHost({
|
|
|
203
228
|
policyRulesetVersion: "gtm-rules.v8",
|
|
204
229
|
providerBridge: { name: "@fabric-harness/databricks", version: "1" },
|
|
205
230
|
},
|
|
231
|
+
composition: {
|
|
232
|
+
assembly: assemblyLockfile,
|
|
233
|
+
resolveInitiatingReleaseDigest: (submission) =>
|
|
234
|
+
releaseRegistry.resolveTrustedDigest(submission.provenance),
|
|
235
|
+
},
|
|
206
236
|
});
|
|
207
237
|
```
|
|
208
238
|
|
|
209
239
|
`MemoryPlatformHostStore` is for tests and local demos. Production control planes use
|
|
210
|
-
`PostgresPlatformHostStore` with Databricks Lakebase (or standard Postgres),
|
|
211
|
-
|
|
240
|
+
`PostgresPlatformHostStore` with Databricks Lakebase (or standard Postgres), run `ensureSchema()` in a
|
|
241
|
+
controlled deployment migration step, and hydrate projections from `listEvents()`. `ensureSchema()`
|
|
242
|
+
uses ordered immutable checksums, a migration ledger, and a transaction-scoped advisory lock. It
|
|
243
|
+
remains safe to call at startup, but deployment-owned migrations are preferred.
|
|
244
|
+
|
|
245
|
+
State-machine transition checks run inside the Host mutation unit of work. Transaction-capable
|
|
246
|
+
stores should expose transaction-scoped `getEntityState()` so the guard reads the same database
|
|
247
|
+
snapshot used by the handler and event append. Existing custom stores without that optional
|
|
248
|
+
transaction method fall back to the store-level authoritative read.
|
|
249
|
+
|
|
250
|
+
## Runtime observability and health
|
|
251
|
+
|
|
252
|
+
Platform Host exposes vendor-neutral lifecycle telemetry through the optional `telemetry` sink on
|
|
253
|
+
`createGovernedActionHost()`, `runPlatformActionWorkerCycle()`, and `runOutboxRelayCycle()`. A sink can
|
|
254
|
+
be a callback or `{ record }`; it receives stable event and metric names from
|
|
255
|
+
`PLATFORM_HOST_METRIC_NAMES`. Telemetry is best effort and never changes mutation or checkpoint
|
|
256
|
+
behavior.
|
|
257
|
+
|
|
258
|
+
```ts
|
|
259
|
+
import {
|
|
260
|
+
getPlatformHostHealthSnapshot,
|
|
261
|
+
PLATFORM_HOST_METRIC_NAMES,
|
|
262
|
+
} from "@fabricorg/platform-host";
|
|
263
|
+
|
|
264
|
+
const health = await getPlatformHostHealthSnapshot({
|
|
265
|
+
store,
|
|
266
|
+
tenantId,
|
|
267
|
+
spaceId,
|
|
268
|
+
workers: [{ lastHeartbeatAt, staleAfterMs: 30_000 }],
|
|
269
|
+
telemetry: (record) => { metrics.record(record); },
|
|
270
|
+
});
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
The snapshot contains only scoped aggregate counts for invocation backlog, running and expired
|
|
274
|
+
leases, approval waits, reconciliation-required work, outbox backlog, expired leases, and dead
|
|
275
|
+
letters. It never returns invocation parameters, results, actor data, payloads, or errors. An
|
|
276
|
+
unavailable health source is reported as `unhealthy` and not ready; stale workers and operational
|
|
277
|
+
lease/dead-letter/reconciliation findings are represented by readiness reason codes.
|
|
278
|
+
|
|
279
|
+
Dispatcher submission failures leave the durable invocation `pending`. Re-submit the same
|
|
280
|
+
idempotency key to retry the stable workflow ID, or use a store-backed worker. The Host never marks
|
|
281
|
+
a logical mutation failed merely because a queue or workflow service was temporarily unavailable.
|
|
282
|
+
|
|
283
|
+
Saga actions require a durable workflow dispatcher and a worker-side `SagaImplementation` mapping.
|
|
284
|
+
Calling `executeInvocation()` for a saga through the atomic Host path fails closed. Interrupted
|
|
285
|
+
inline actions that are not declared idempotent also fail closed and require manual reconciliation.
|
|
286
|
+
|
|
287
|
+
CI certifies concurrent migrations, command idempotency, and schema behavior against PostgreSQL 16.
|
|
288
|
+
Lakebase failover, backup, and restore remain adopter certification gates and are not implied by the
|
|
289
|
+
PostgreSQL CI result.
|
|
212
290
|
|
|
213
291
|
## Durable outbox egress
|
|
214
292
|
|
|
215
293
|
Configure `outbox` on `createGovernedActionHost()` only with an `OutboxPlatformHostStore`.
|
|
216
294
|
The Host then uses `appendEventWithOutbox` so the canonical event and delivery record share
|
|
217
|
-
the proven event transaction. `runOutboxRelayCycle()`
|
|
218
|
-
and dead-letter handling. Delivery is at least once: consumers deduplicate on immutable
|
|
295
|
+
the proven event transaction. `runOutboxRelayCycle()` uses renewable fenced leases, a bounded
|
|
296
|
+
publisher deadline, retry, and dead-letter handling. Delivery is at least once: consumers deduplicate on immutable
|
|
219
297
|
`eventId`. Payload classification is metadata, not a redaction mechanism; event payloads must
|
|
220
298
|
already be audit-safe.
|
|
221
299
|
|