npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fabricorg/platform

v1.1.0

Published

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 data

Downloads

15,083

Readme

@fabricorg/platform

A portable runtime for ontology-based, agent-native business applications. Zero dependencies. Bring your own database client.

npm install @fabricorg/platform

Hello, action

import { z } from "zod";
import type { ActionDefinition, ActionContext } from "@fabricorg/platform/actions";

const greet: ActionDefinition<unknown> = {
  id: "demo.greet",
  schema: z.object({ name: z.string() }),
  handler: async (ctx: ActionContext<unknown>, params: { name: string }) => {
    return { greeting: `Hello, ${params.name}!` };
  },
};

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.

For a complete walkthrough see https://platform.fabric.pro/docs/getting-started/quickstart.

Why use this

You're building a governed business application — not a CRUD app. You need:

  • A single, auditable entry point for every mutation
  • Policies that gate every change before it happens
  • Events as evidence (not retrofitted logs)
  • Agents and humans treated identically by policy
  • A vertical-specific ontology layered on a portable runtime

That's what this package gives you. Nothing more.

What's in the box

| Subpath | What you get | |---|---| | @fabricorg/platform | Re-exports everything below | | @fabricorg/platform/actions | ActionDefinition, ActionContext, SagaImplementation | | @fabricorg/platform/policies | PolicyEvaluator, PolicyContext, code/data/hybrid evaluation | | @fabricorg/platform/state-machines | StateMachineDefinition, validateTransition | | @fabricorg/platform/events | AssetEventEnvelope, EventTypeRegistry | | @fabricorg/platform/projections | Replay/snapshot framework | | @fabricorg/platform/adapters | AdapterRegistry, retry + circuit-breaker | | @fabricorg/platform/modules | FabricModule<TDb>, createModuleRegistry | | @fabricorg/platform/manifest | exportModuleManifest, exportModuleManifestBundle, ModuleManifest | | @fabricorg/platform/ids | createFabricId, FABRIC_ID_PREFIXES | | @fabricorg/platform/privacy | Redaction + data classification | | @fabricorg/platform/evidence | Compliance evidence packets | | @fabricorg/platform/governance | External footprints, delegated principals, obligations, attestations, and reconciliation | | @fabricorg/platform/objects | Shared object-type contracts | | @fabricorg/platform/testing | In-memory adapter registry, fake ActionContext, deterministic IDs |

Modules may publish versioned ViewContracts. replayView filters declared event schema versions and requires an explicit upgrade function before resuming an older compatible snapshot; manifests serialize the logical shape and metadata but never executable functions or initial state. Physical stores remain adapter concerns.

Composing a vertical

Verticals declare a FabricModule<TDb> that registers their actions, policies, state machines, events, and adapters with the platform:

import type { FabricModule } from "@fabricorg/platform/modules";
import { createModuleRegistry } from "@fabricorg/platform/modules";

const myModule: FabricModule<MyDbClient> = {
  namespace: "demo",
  version: "1.0.0",
  objectTypes: ["Widget"],
  actions: [greet, /* ... */],
  policies: [/* ... */],
  stateMachines: [/* ... */],
};

// At app startup:
const registry = createModuleRegistry([myModule]);

The platform never auto-loads a module. The host app composes an instance-scoped registry and injects it into its hosts. Experience roles, slots, action intents, and display rendering live in @fabricorg/experience-contracts, carried through the namespaced fabric.experience/v1 extension.

Exporting a module manifest

Downstream tooling — semantics exporters, docs generators, tool generators — often needs a module's ontology as data rather than live code. @fabricorg/platform/manifest exports a stable, JSON-serializable, versioned description of any FabricModule:

import { exportModuleManifest } from "@fabricorg/platform/manifest";

const manifest = exportModuleManifest(myModule);
const json = JSON.stringify(manifest, null, 2);

exportModuleManifest is a pure function of the module object: it does not touch the registries and the module does not need to be registered first. Declaration order is preserved everywhere, so the same module always produces byte-identical JSON. Function fields (handler, policy evaluate, transition guard, dynamic targetState, adapter getInput) are never serialized — the manifest contains definitions only, never raw parameter values, secrets, or runtime data. Manifest v2 object registrations may include PortableJsonSchema, qualified relations, namespaced semantic annotations, and enforcement-owned invariants. Actions whose validators expose toJSONSchema() include parameterSchema and optional resultSchema definitions. normalizeModuleManifest and normalizeModuleManifestBundle let v2 readers accept v1 input without promising down-conversion.

An entity schema does not validate arbitrary writes through TDb. Persisted-record validation requires an explicit Host/database adapter. When an action declares resultSchema, Platform Host validates the public result after the handler and before events or adapters; failure rolls back domain writes only when the Host store has a transaction provider that includes them.

The action lifecycle

Every invokeAction(id, params) call goes through:

  1. evaluatePolicies — every policy registered for the action runs (code/data/hybrid). A single block halts the invocation. Policies may return guidance (factsUsed + typed correctiveActions) so hosts can show exactly why a block happened and what the operator can do next. Corrective actions declare kind: "invoke_action" | "navigate" | "manual" so UIs do not guess whether a remediation is executable.
  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.
  3. HandleractionDef.handler(ctx, params) runs inside a single TDb transaction. Handler parses its own input via its schema (single source of truth).
  4. Adapters — for each actionDef.adapterSteps, the registered implementation runs via executeWithAdapterRetry (idempotent retry, exponential backoff, circuit breaker).
  5. Events — domain events are appended; projections derive read models on next replay.
  6. Completion — invocation status is marked, telemetry emitted.

validateActionParameters is also exposed for preview/dry-run paths but is not part of the execute pipeline.

Saga actions

Multi-step orchestrations declare kind: "saga" on the ActionDefinition and ship a SagaImplementation:

import type { SagaImplementation } from "@fabricorg/platform/actions";

export const ingestSaga: SagaImplementation = async (ctx, runChild) => {
  const step1 = await runChild({
    suffix: "step-1",
    actionId: "demo.receive_payload",
    parameters: { /* ... */ },
  });
  // orchestrate further child actions...
  return {
    resultData: { /* ... */ },
    event: { eventType: "...", subjectType: "...", subjectId: "...", payload: {} },
  };
};

Your worker maps action IDs to implementations. The platform dispatches generically — no platform code references vertical action IDs.

Portability boundary

The repository Boundary Guard scans source and packed artifacts and fails CI if any of these leak in:

  • Concrete database/ORM imports — the literal Prisma, the field name prisma:, or the type default TDb = any
  • Vertical vocabulary from the governed denylist
  • "Register default" hooks (registerDefaultPolicies, etc.) — the platform never auto-loads anything
  • Module-scope mutable registries, import-time environment reads, or unapproved infrastructure imports

This is what keeps the platform portable across verticals and consumers. If you fork or add new patterns specific to your domain, extend the list in boundary.test.ts.

Compatibility

  • Runtime: Node 20+
  • Module formats: ESM and CommonJS (dual format from v0.2.0+)
  • TypeScript: 5.0+, moduleResolution: node or node16/nodenext

Versioning

0.x while contracts evolve. 1.0 only after at least two materially different verticals validate the API.

See CHANGELOG.md for release history.

Documentation

Full reference docs at https://platform.fabric.pro

License

MIT