FabricFabricPlatform
Getting started

Production adoption

Ownership, approved composition, durability, contract evolution, migration, and release gates for a Fabric application.

Production adoption is a sequence of proofs. Installing packages is only the first step.

Ownership stays explicit

ConcernOwner
Governed action, event, policy, state-machine, adapter, and projection contractsFabric Platform
Durable invocation, recovery, idempotency, approval, and event ledgerPlatform Host
Authorized replay, snapshots, freshness, and read evidenceProjectionHost
Business vocabulary, domain transactions, module composition, and providersThe application
Experience documents, signed promotion, scoped render plans, and Host routingFabric experience-tier packages configured by the application
SaaS shell, authentication UI, organizations, billing, navigation, and deploymentThe Supastarter-derived application shell
Family tokens and visual primitives@fabricorg/ui
Product-domain components and brand mappingThe application
Durable cross-action orchestrationTemporal

Platform does not ship a business capability catalog, application shell, authentication system, database operations model, provider credentials, or a replacement design system.

Build one immutable composition

  1. Author each FabricModule and export its manifest.
  2. Compile each published module independently. Put that compiler digest and package version on the module registered at runtime.
  3. Generate and review usage contracts.
  4. Bind shared capability roles and intents to application-owned component packs.
  5. Resolve an Assembly v2 lockfile. Its digest covers exact capabilities, generated contract documents, component-pack artifacts, and adoption bindings. Federated packs also lock their remote entry, subresource integrity, and exposed modules.
  6. Validate and promote experience releases against that lockfile and explicit view and intent grants. Enumerate every selectable document variant and use fragment grants when a subtree needs narrower access.
  7. Start Platform Host with the approved lockfile. Host compares the actual registered modules with the lockfile before accepting submissions.
  8. Promote exact routes and effective fragment grants with @fabricorg/sdui-composer. The server runtime verifies the signed release and issues a scoped render plan.
  9. Put @fabricorg/experience-gateway behind the authenticated application boundary. Never expose either Host to browser code.

The examples/governed-portfolio implements this sequence for two materially different applications.

Add the integration files to an existing Supastarter-derived application:

fabric-gen init experience portfolio --directory apps/saas/modules/portfolio

This creates only Fabric integration files. It does not create or replace the shell, authentication, organizations, billing, routes, or navigation.

Client checks are not authorization

A browser is controlled by its user. It can skip a local digest check, modify JavaScript, or call the gateway without rendering the document. Client checks remain useful because they catch stale caches, CDN corruption, incompatible packs, and bad deployments.

Security comes from the server path:

  1. The server runtime admits a signed release and stores the trusted plan state.
  2. The browser submits (planId, fragmentId, eventName) or a named read binding, never an action ID or capability reference.
  3. The gateway resolves that handle against server-held grants and derives actor and scope through IdentityPort.
  4. ProjectionHost authorizes every read. PlatformHost independently authorizes every mutation at its configured governing moment.

Check before deployment

Create fabric.application.json beside the resolved build artifacts:

{
  "formatVersion": 1,
  "assembly": "./fabric.assembly.lock.json",
  "runtimeCapabilities": "./fabric.runtime.json",
  "releases": ["./releases/web.json"]
}

Then run:

fabric-gen check-application --config fabric.application.json

The check fails on lockfile tampering; missing, extra, duplicate, version- or digest-mismatched runtime modules; malformed promoted releases; release digest drift; or a release bound to another assembly.

This is a deployment gate, not runtime discovery. The runtime-capability file must come from the same application composition root that builds the explicit module registry.

Use the production storage profile

Use PostgresPlatformHostStore and the PostgreSQL ProjectionHost adapters with PostgreSQL 16 or a compatible Lakebase client. Run ensureSchema() through a controlled migration step.

If a handler writes application tables, provide a PostgresPlatformHostTransactionProvider<TDb> that binds the application database client and Host ledger to the same database transaction. Without that provider, do not claim atomic domain writes plus event/outbox persistence.

Memory stores are for deterministic tests and explicit local development.

Trust identity only at the server seam

Use IdentityPort at the gateway to turn a presented OAuth2/OIDC credential into verified ActorClaims. Then derive actor, tenant, space, roles, and entitlements from authenticated server context. Do not accept them as authoritative action or projection parameters. External APIs, agents, Temporal activities, webhooks, support tools, and recovery workers all submit through the same Host.

import { actorContextFromClaims } from "@fabricorg/ports";

const claims = await identity.verify(credential);
if (!claims) throw new Error("unauthenticated");

const actor = actorContextFromClaims(claims, { tenantId, spaceId });

actorContextFromClaims rejects expired, not-yet-valid, malformed, cross-tenant, and out-of-space claims before they reach Host submission or projection authorization. Run identityPortChecks() against every identity adapter.

Redact sensitive parameters before durable invocation creation. Store secrets in tenant-bound encrypted storage and submit opaque references.

Evolve contracts deliberately

Treat action schemas, event envelopes, view shapes, usage contracts, assembly documents, and durable invocation records as public contracts.

  • Add optional fields when possible.
  • A required field, removal, type narrowing, lifecycle semantic change, or changed event truth requires compatibility analysis and normally a major package release.
  • Increase an event schema version when its wire shape changes.
  • Keep consumers able to read every event version listed in ViewContract.consumes.
  • Upcast old events at the consumer seam before applying the current reducer. Never rewrite the historical event ledger.
  • Use compatibleSnapshotVersions and upgradeSnapshot for compatible projection snapshots. Cold-rebuild snapshots that are not declared compatible.
  • Regenerate contracts and resolve a new assembly. An old assembly digest must never silently identify new artifacts.

Run compiler compatibility classification and generated conformance suites in CI. Pack changed packages and test clean ESM and CommonJS consumers before release.

Migrate Host 5 to Host 6

Host 6 requires explicit recovery fencing on custom durable stores and adds optional verified composition.

  1. Install a compatible @fabricorg/assembly peer.
  2. Implement lease renewal, monotonic claim tokens, and fenced writes on custom stores and dispatchers.
  3. Run Host schema migrations before starting new workers.
  4. Set version and compiler manifestDigest on every registered module.
  5. Pass the approved lockfile as composition.assembly.
  6. Resolve the initiating promoted release digest from trusted gateway or release-registry context, never from action parameters.

See the packaged MIGRATION-6-PRODUCTION.md for the exact interface changes.

Certify and roll out

Before cutover:

  • run unit, lifecycle, recovery, conformance, family-boundary, and clean-package consumer tests;
  • run PostgreSQL migration, concurrency, failover, backup, and restore tests in the target environment;
  • run Temporal integration tests if workflows are present;
  • verify policy deny/outage, tenant isolation, redaction, adapter failure, idempotent replay, and recovery;
  • retain the previous package set, assembly, promoted releases, and database rollback procedure.

Roll back code and release selection together. Never point an old runtime at a new assembly unless the compatibility matrix explicitly certifies that pair.

On this page