@fabricorg/platform 0.2.0 → 0.2.2
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 +68 -0
- package/README.md +105 -61
- package/package.json +2 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# @fabricorg/platform
|
|
2
|
+
|
|
3
|
+
## 0.2.2 — 2026-05-06
|
|
4
|
+
|
|
5
|
+
### Patch
|
|
6
|
+
|
|
7
|
+
- Ship `CHANGELOG.md` in the published tarball (added to `files` field).
|
|
8
|
+
- Documentation-only release; no runtime changes.
|
|
9
|
+
|
|
10
|
+
## 0.2.1 — 2026-05-06
|
|
11
|
+
|
|
12
|
+
### Patch
|
|
13
|
+
|
|
14
|
+
- Rewrite `README.md` quickstart-first (was architecture-first).
|
|
15
|
+
- Add 64 unit + integration tests across 9 test files (was 1 test, 1 file). Covers ids, events, state machines, actions, policies, adapters, projections, modules.
|
|
16
|
+
- Add `CHANGELOG.md` (this file).
|
|
17
|
+
- Add GitHub Actions CI workflow (build + test + type-check on PR).
|
|
18
|
+
- Add `examples/minimal-vertical/` runnable end-to-end demo.
|
|
19
|
+
- No runtime changes; same exports as 0.2.0.
|
|
20
|
+
|
|
21
|
+
## 0.2.0 — 2026-05-06
|
|
22
|
+
|
|
23
|
+
### Minor
|
|
24
|
+
|
|
25
|
+
- **Dual ESM + CJS distribution.** The package now ships both formats so it can be consumed by CommonJS projects (`require()`), ESM projects (`import`), Jest without ESM config, ts-node default mode, and `tsx` from a CJS host package. The 0.1.x line was ESM-only and produced `ERR_PACKAGE_PATH_NOT_EXPORTED` for CJS consumers.
|
|
26
|
+
- **Conditional types.** Exports map now uses proper conditional `import` / `require` blocks with separate `.d.ts` and `.d.cts` type declarations so TypeScript resolves correctly under both `moduleResolution: node` and `node16`/`nodenext`.
|
|
27
|
+
|
|
28
|
+
### Internal
|
|
29
|
+
|
|
30
|
+
- `tsup.config.ts`: `format: ["esm", "cjs"]`
|
|
31
|
+
- `package.json`: `main: ./dist/index.cjs`, `exports.*` updated for dual format
|
|
32
|
+
|
|
33
|
+
## 0.1.2 — 2026-05-06
|
|
34
|
+
|
|
35
|
+
### Patch
|
|
36
|
+
|
|
37
|
+
- Republish under `@fabricorg/*` scope. (No code changes.)
|
|
38
|
+
|
|
39
|
+
## 0.1.1 — 2026-05-06
|
|
40
|
+
|
|
41
|
+
### Patch
|
|
42
|
+
|
|
43
|
+
- Republish to confirm scope ownership. (No code changes.)
|
|
44
|
+
|
|
45
|
+
## 0.1.0 — 2026-05-06
|
|
46
|
+
|
|
47
|
+
### Initial release
|
|
48
|
+
|
|
49
|
+
The portable runtime for ontology-based, agent-native business applications.
|
|
50
|
+
|
|
51
|
+
- **Action pipeline** — single mutation entry point (`invokeAction`) with three call paths: authenticated session, verified external token, and system/agent/scheduled.
|
|
52
|
+
- **Policy evaluation** — pluggable policy registry checked at every pipeline checkpoint.
|
|
53
|
+
- **State machines** — declarative entity state transitions with policy-gated guards.
|
|
54
|
+
- **Events** — immutable `AssetEvent` schema; events are evidence, not logs.
|
|
55
|
+
- **Projections** — derive read models from events; replay rebuilds them.
|
|
56
|
+
- **Adapters** — registered side-effects (db writes, external API calls) with retry + circuit-breaker primitives.
|
|
57
|
+
- **Modules** — `FabricModule<TDb>` manifest registers a vertical's actions, policies, state machines, events, and adapters with the platform.
|
|
58
|
+
- **Privacy & evidence** — first-class data-policy + audit-trail contracts.
|
|
59
|
+
- **Testing helpers** — deterministic ID factory, fake action context, in-memory adapter registry.
|
|
60
|
+
|
|
61
|
+
**Subpath exports:** `./actions`, `./adapters`, `./displays`, `./events`, `./evidence`, `./ids`, `./modules`, `./objects`, `./policies`, `./privacy`, `./projections`, `./state-machines`, `./testing`.
|
|
62
|
+
|
|
63
|
+
**Design constraints (boundary-tested in `boundary.test.ts`):**
|
|
64
|
+
|
|
65
|
+
- Zero runtime dependencies.
|
|
66
|
+
- No database client. No ORM.
|
|
67
|
+
- No vertical vocabulary in the core.
|
|
68
|
+
- Every contract parameterized by `TDb` so consumers bind their own persistence client.
|
package/README.md
CHANGED
|
@@ -1,104 +1,148 @@
|
|
|
1
1
|
# @fabricorg/platform
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A portable runtime for ontology-based, agent-native business applications. Zero dependencies. Bring your own database client.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
```bash
|
|
6
|
+
npm install @fabricorg/platform
|
|
7
|
+
```
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
## Hello, action
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
```ts
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
import type { ActionDefinition, ActionContext } from "@fabricorg/platform/actions";
|
|
14
|
+
|
|
15
|
+
const greet: ActionDefinition<unknown> = {
|
|
16
|
+
id: "demo.greet",
|
|
17
|
+
schema: z.object({ name: z.string() }),
|
|
18
|
+
handler: async (ctx: ActionContext<unknown>, params: { name: string }) => {
|
|
19
|
+
return { greeting: `Hello, ${params.name}!` };
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
```
|
|
10
23
|
|
|
11
|
-
|
|
12
|
-
- `@repo/database`, `@repo/ontology`, `@repo/adapters` imports
|
|
13
|
-
- the literal `Prisma`, the field name `prisma:`, and the type default `TDb = any`
|
|
14
|
-
- any vertical vocabulary (`lending.`, `borrower`, `lender`, `LeadApplication`, `Offer`, `Vehicle`, `Party`, `Obligation`, `auto-refi`, etc.)
|
|
15
|
-
- any "register default" hook (`registerDefaultPolicies`, etc.)
|
|
24
|
+
That's the smallest unit. From here, you compose actions into a `FabricModule<TDb>`, register the module at startup, and call `invokeAction("demo.greet", ...)` from any of three call paths (authenticated user, signed token, or system/agent). Every call passes through the same pipeline: **policy → state machine → handler → adapters → events → projections.**
|
|
16
25
|
|
|
17
|
-
|
|
26
|
+
For a complete walkthrough see https://platform.fabric.pro/docs/getting-started/quickstart.
|
|
18
27
|
|
|
19
|
-
|
|
20
|
-
|---|---|
|
|
21
|
-
| `@fabricorg/platform` | re-exports everything below |
|
|
22
|
-
| `@fabricorg/platform/actions` | `ActionDefinition<TDb>`, `ActionContext<TDb>`, `ActorType`, `assertActorType`, `SagaImplementation`, `SchemaValidator` |
|
|
23
|
-
| `@fabricorg/platform/adapters` | `AdapterRegistry`, `AdapterImplementation`, retry/circuit-breaker primitives |
|
|
24
|
-
| `@fabricorg/platform/events` | `AssetEventEnvelope`, `EventTypeRegistry` |
|
|
25
|
-
| `@fabricorg/platform/ids` | `createFabricId`, `FABRIC_ID_PREFIXES`, `parseFabricId` |
|
|
26
|
-
| `@fabricorg/platform/modules` | `FabricModule<TDb>`, `ModuleRegistry`, `createModuleRegistry`, `registerFabricModules` |
|
|
27
|
-
| `@fabricorg/platform/policies` | `PolicyEvaluator<TDb>`, `PolicyContext<TDb>`, code/data/hybrid evaluation engine |
|
|
28
|
-
| `@fabricorg/platform/state-machines` | `StateMachineDefinition`, `validateTransition`, engine |
|
|
29
|
-
| `@fabricorg/platform/projections` | replay/snapshot framework |
|
|
30
|
-
| `@fabricorg/platform/displays` | `DisplayRendererRegistration`, display engine |
|
|
31
|
-
| `@fabricorg/platform/privacy` | redaction, anonymization-pipeline, data-classification contracts |
|
|
32
|
-
| `@fabricorg/platform/evidence` | compliance evidence packet envelope |
|
|
33
|
-
| `@fabricorg/platform/objects` | shared object-type contracts |
|
|
34
|
-
| `@fabricorg/platform/testing` | test fixtures (in-memory adapter registry, fake ActionContext, deterministic IDs) |
|
|
28
|
+
## Why use this
|
|
35
29
|
|
|
36
|
-
|
|
30
|
+
You're building a governed business application — not a CRUD app. You need:
|
|
37
31
|
|
|
38
|
-
|
|
32
|
+
- A single, auditable entry point for every mutation
|
|
33
|
+
- Policies that gate every change before it happens
|
|
34
|
+
- Events as evidence (not retrofitted logs)
|
|
35
|
+
- Agents and humans treated identically by policy
|
|
36
|
+
- A vertical-specific ontology layered on a portable runtime
|
|
39
37
|
|
|
40
|
-
|
|
41
|
-
2. **If `actionDef.kind === "saga"`** — dispatch to a registered saga implementation that orchestrates child actions and returns a `SagaCompletion`.
|
|
42
|
-
3. **Otherwise** — build an `ActionContext<TDb>`, run `actionDef.handler(ctx, params)` inside a single transaction. The handler parses its own input via its declared schema (single source of truth — handlers honor their schema contract). State-machine binding validates transitions before the handler runs. ZodError thrown by handler parsing is translated to `validation_failed` invocation status.
|
|
43
|
-
4. `executeAdapters` — for each `actionDef.adapterSteps`, look up the implementation in the `AdapterRegistry` and run via `executeWithAdapterRetry` (idempotency-aware retry, exponential backoff, circuit breaker, dead-letter queue on terminal failure).
|
|
44
|
-
5. `completeActionInvocation` — mark completed/failed and emit telemetry.
|
|
38
|
+
That's what this package gives you. Nothing more.
|
|
45
39
|
|
|
46
|
-
|
|
40
|
+
## What's in the box
|
|
47
41
|
|
|
48
|
-
|
|
42
|
+
| Subpath | What you get |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `@fabricorg/platform` | Re-exports everything below |
|
|
45
|
+
| `@fabricorg/platform/actions` | `ActionDefinition`, `ActionContext`, `SagaImplementation` |
|
|
46
|
+
| `@fabricorg/platform/policies` | `PolicyEvaluator`, `PolicyContext`, code/data/hybrid evaluation |
|
|
47
|
+
| `@fabricorg/platform/state-machines` | `StateMachineDefinition`, `validateTransition` |
|
|
48
|
+
| `@fabricorg/platform/events` | `AssetEventEnvelope`, `EventTypeRegistry` |
|
|
49
|
+
| `@fabricorg/platform/projections` | Replay/snapshot framework |
|
|
50
|
+
| `@fabricorg/platform/adapters` | `AdapterRegistry`, retry + circuit-breaker |
|
|
51
|
+
| `@fabricorg/platform/modules` | `FabricModule<TDb>`, `registerFabricModules` |
|
|
52
|
+
| `@fabricorg/platform/ids` | `createFabricId`, `FABRIC_ID_PREFIXES` |
|
|
53
|
+
| `@fabricorg/platform/displays` | `DisplayRendererRegistration` |
|
|
54
|
+
| `@fabricorg/platform/privacy` | Redaction + data classification |
|
|
55
|
+
| `@fabricorg/platform/evidence` | Compliance evidence packets |
|
|
56
|
+
| `@fabricorg/platform/objects` | Shared object-type contracts |
|
|
57
|
+
| `@fabricorg/platform/testing` | In-memory adapter registry, fake `ActionContext`, deterministic IDs |
|
|
49
58
|
|
|
50
|
-
|
|
59
|
+
## Composing a vertical
|
|
60
|
+
|
|
61
|
+
Verticals declare a `FabricModule<TDb>` that registers their actions, policies, state machines, events, and adapters with the platform:
|
|
51
62
|
|
|
52
63
|
```ts
|
|
53
64
|
import type { FabricModule } from "@fabricorg/platform/modules";
|
|
54
|
-
import
|
|
65
|
+
import { registerFabricModules } from "@fabricorg/platform/modules";
|
|
55
66
|
|
|
56
|
-
|
|
57
|
-
namespace: "
|
|
67
|
+
const myModule: FabricModule<MyDbClient> = {
|
|
68
|
+
namespace: "demo",
|
|
58
69
|
version: "1.0.0",
|
|
59
|
-
objectTypes: ["
|
|
60
|
-
actions: [...],
|
|
61
|
-
policies: [...],
|
|
62
|
-
stateMachines: [...],
|
|
63
|
-
displayRenderers: [
|
|
70
|
+
objectTypes: ["Widget"],
|
|
71
|
+
actions: [greet, /* ... */],
|
|
72
|
+
policies: [/* ... */],
|
|
73
|
+
stateMachines: [/* ... */],
|
|
74
|
+
displayRenderers: [],
|
|
64
75
|
};
|
|
76
|
+
|
|
77
|
+
// At app startup:
|
|
78
|
+
registerFabricModules([myModule]);
|
|
65
79
|
```
|
|
66
80
|
|
|
67
|
-
|
|
81
|
+
The platform never auto-loads a module. The host app composes them explicitly — no implicit defaults, no globals, no surprises.
|
|
68
82
|
|
|
69
|
-
|
|
70
|
-
import { registerFabricModules } from "@fabricorg/platform/modules";
|
|
71
|
-
import { lendingModule } from "@repo/lending";
|
|
72
|
-
import { messagingModule } from "@repo/messaging";
|
|
83
|
+
## The action lifecycle
|
|
73
84
|
|
|
74
|
-
|
|
75
|
-
|
|
85
|
+
Every `invokeAction(id, params)` call goes through:
|
|
86
|
+
|
|
87
|
+
1. **`evaluatePolicies`** — every policy registered for the action runs (code/data/hybrid). A single `block` halts the invocation.
|
|
88
|
+
2. **State-machine validation** — if the action's target entity is bound to a state machine, the requested transition is validated before the handler runs.
|
|
89
|
+
3. **Handler** — `actionDef.handler(ctx, params)` runs inside a single `TDb` transaction. Handler parses its own input via its `schema` (single source of truth).
|
|
90
|
+
4. **Adapters** — for each `actionDef.adapterSteps`, the registered implementation runs via `executeWithAdapterRetry` (idempotent retry, exponential backoff, circuit breaker).
|
|
91
|
+
5. **Events** — domain events are appended; projections derive read models on next replay.
|
|
92
|
+
6. **Completion** — invocation status is marked, telemetry emitted.
|
|
76
93
|
|
|
77
|
-
|
|
94
|
+
`validateActionParameters` is also exposed for preview/dry-run paths but is **not** part of the execute pipeline.
|
|
78
95
|
|
|
79
|
-
## Saga
|
|
96
|
+
## Saga actions
|
|
80
97
|
|
|
81
|
-
Multi-step orchestrations declare `kind: "saga"` on the `ActionDefinition` and ship a `SagaImplementation
|
|
98
|
+
Multi-step orchestrations declare `kind: "saga"` on the `ActionDefinition` and ship a `SagaImplementation`:
|
|
82
99
|
|
|
83
100
|
```ts
|
|
84
101
|
import type { SagaImplementation } from "@fabricorg/platform/actions";
|
|
85
102
|
|
|
86
103
|
export const ingestSaga: SagaImplementation = async (ctx, runChild) => {
|
|
87
|
-
const
|
|
104
|
+
const step1 = await runChild({
|
|
88
105
|
suffix: "step-1",
|
|
89
|
-
actionId: "
|
|
90
|
-
parameters: { ... },
|
|
106
|
+
actionId: "demo.receive_payload",
|
|
107
|
+
parameters: { /* ... */ },
|
|
91
108
|
});
|
|
92
|
-
//
|
|
109
|
+
// orchestrate further child actions...
|
|
93
110
|
return {
|
|
94
|
-
resultData: { ... },
|
|
95
|
-
event: { eventType: "...", subjectType: "...", subjectId: "...", payload:
|
|
111
|
+
resultData: { /* ... */ },
|
|
112
|
+
event: { eventType: "...", subjectType: "...", subjectId: "...", payload: {} },
|
|
96
113
|
};
|
|
97
114
|
};
|
|
98
115
|
```
|
|
99
116
|
|
|
100
|
-
|
|
117
|
+
Your worker maps action IDs to implementations. The platform dispatches generically — no platform code references vertical action IDs.
|
|
118
|
+
|
|
119
|
+
## Portability boundary
|
|
120
|
+
|
|
121
|
+
The `boundary.test.ts` in this package fails CI if any of these leak in:
|
|
122
|
+
|
|
123
|
+
- `@repo/database`, `@repo/ontology`, `@repo/adapters` imports
|
|
124
|
+
- the literal `Prisma`, the field name `prisma:`, or the type default `TDb = any`
|
|
125
|
+
- vertical vocabulary (`lending.`, `borrower`, `lender`, `Vehicle`, `Party`, `Obligation`, `auto-refi`, etc.)
|
|
126
|
+
- "register default" hooks (`registerDefaultPolicies`, etc.)
|
|
127
|
+
|
|
128
|
+
This is what keeps the platform portable across verticals and consumers.
|
|
129
|
+
|
|
130
|
+
## Compatibility
|
|
131
|
+
|
|
132
|
+
- **Runtime:** Node 20+
|
|
133
|
+
- **Module formats:** ESM and CommonJS (dual format from v0.2.0+)
|
|
134
|
+
- **TypeScript:** 5.0+, `moduleResolution: node` or `node16`/`nodenext`
|
|
101
135
|
|
|
102
136
|
## Versioning
|
|
103
137
|
|
|
104
138
|
`0.x` while contracts evolve. `1.0` only after at least two materially different verticals validate the API.
|
|
139
|
+
|
|
140
|
+
See [`CHANGELOG.md`](./CHANGELOG.md) for release history.
|
|
141
|
+
|
|
142
|
+
## Documentation
|
|
143
|
+
|
|
144
|
+
Full reference docs at https://platform.fabric.pro
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fabricorg/platform",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Generic, vertical-agnostic runtime for ontology-based business applications. Provides actions, modules, events, policies, state machines, adapters, displays, projections, privacy, and evidence contracts. Zero runtime dependencies; portable across any database client and any vertical (lending, insurance, healthcare, legal, etc.).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fabric",
|
|
@@ -172,6 +172,7 @@
|
|
|
172
172
|
"files": [
|
|
173
173
|
"dist",
|
|
174
174
|
"README.md",
|
|
175
|
+
"CHANGELOG.md",
|
|
175
176
|
"LICENSE"
|
|
176
177
|
],
|
|
177
178
|
"scripts": {
|