@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.
Files changed (2) hide show
  1. package/README.md +105 -61
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,104 +1,148 @@
1
1
  # @fabricorg/platform
2
2
 
3
- Generic runtime for ontology-based business applications. Provides the action lifecycle, policy dispatch, state machine validation, adapter retry/circuit-breaker, event append, and ID generation that any vertical (lending, legal, healthcare, insurance, etc.) can build on.
3
+ A portable runtime for ontology-based, agent-native business applications. Zero dependencies. Bring your own database client.
4
4
 
5
- ## Portability Scope
5
+ ```bash
6
+ npm install @fabricorg/platform
7
+ ```
6
8
 
7
- **`@fabricorg/platform` is portable.** It has zero runtime dependencies, no database client, no ORM, and no vertical vocabulary. Every contract is parameterized by `TDb` so consumers bind their own persistence client.
9
+ ## Hello, action
8
10
 
9
- **Vertical packages (e.g. `@repo/lending`) are NOT portable.** They bind `TDb` to a concrete client (e.g. `Prisma.TransactionClient`), reference vertical entity types, and assume a specific database schema. To run a vertical against a different ORM, fork the vertical — not the platform.
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
- The platform is enforced clean by `boundary.test.ts`, which forbids:
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
- ## Subpath Exports
26
+ For a complete walkthrough see https://platform.fabric.pro/docs/getting-started/quickstart.
18
27
 
19
- | Path | Contents |
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
- ## Action Lifecycle
30
+ You're building a governed business application — not a CRUD app. You need:
37
31
 
38
- Every domain mutation flows through a single platform pipeline:
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
- 1. `evaluatePolicies` dispatch each policy ID via `evaluatePolicyDefinitions` (code/data/hybrid). Aggregate `block` halts the invocation.
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
- `validateActionParameters` exists as a standalone activity for preview/dry-run paths but is **not** part of the execute pipeline — parameter validation happens once, in the handler, via its own schema.
40
+ ## What's in the box
47
41
 
48
- ## Module Contract
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
- Verticals declare modules as `FabricModule<TDb>`:
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 type { Prisma } from "@repo/database";
65
+ import { registerFabricModules } from "@fabricorg/platform/modules";
55
66
 
56
- export const lendingModule: FabricModule<Prisma.TransactionClient> = {
57
- namespace: "lending",
67
+ const myModule: FabricModule<MyDbClient> = {
68
+ namespace: "demo",
58
69
  version: "1.0.0",
59
- objectTypes: ["Vehicle", "Party", "Location", "Document"],
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
- Apps compose modules explicitly at startup:
81
+ The platform never auto-loads a module. The host app composes them explicitly no implicit defaults, no globals, no surprises.
68
82
 
69
- ```ts
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
- registerFabricModules([messagingModule, lendingModule]);
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
- There are no implicit/default modules. The platform never auto-loads a vertical. Each vertical owns its full domain ontology — there is no "shared core ontology" package; cross-industry governance object types (`AssetEvent`, `ActionInvocation`, `PolicyEvaluation`, `ApprovalRequest`, `ConsentRecord`, `AgentRun`) are pre-registered by the platform itself.
94
+ `validateActionParameters` is also exposed for preview/dry-run paths but is **not** part of the execute pipeline.
78
95
 
79
- ## Saga Actions
96
+ ## Saga actions
80
97
 
81
- Multi-step orchestrations declare `kind: "saga"` on the `ActionDefinition` and ship a `SagaImplementation` alongside:
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 child = await runChild({
104
+ const step1 = await runChild({
88
105
  suffix: "step-1",
89
- actionId: "lending.receive_lead_payload",
90
- parameters: { ... },
106
+ actionId: "demo.receive_payload",
107
+ parameters: { /* ... */ },
91
108
  });
92
- // ... orchestrate further child actions ...
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
- The host app's saga registry maps action IDs to implementations. The worker dispatches generically — no platform code or worker code references vertical action IDs.
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.0",
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",