@fabricorg/platform 0.2.0 → 0.2.1
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/README.md +105 -61
- package/package.json +1 -1
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.1",
|
|
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",
|