FabricFabricPlatform
Platform referenceReference

Examples

Runnable code examples for each pattern, cross-linked to their concept pages.

Snippets you can read top-to-bottom. Each example is grounded in real types from @fabricorg/platform. Vertical-specific bits use placeholder names.


Example 1 — Defining a vertical action

import { z } from "zod";
import type { ActionDefinition } from "@fabricorg/platform/actions";
import type { Prisma } from "@example/database";

const acceptOfferSchema = z.object({
  planId: z.string(),
  acceptanceSource: z.enum(["consultant_ui", "member_portal_token"]),
  acceptedByPartyId: z.string(),
});

export const acceptOfferAction: ActionDefinition<Prisma.TransactionClient> = {
  actionId: "orders.submit",
  namespace: "orders",
  version: 1,
  schema: acceptOfferSchema,
  handler: async (ctx, params) => {
    const parsed = acceptOfferSchema.parse(params);
    const plan = await ctx.db.plan.findUniqueOrThrow({ where: { id: parsed.planId } });

    // Domain write + event append in the same transaction.
    await ctx.db.plan.update({
      where: { id: plan.id },
      data: {
        status: "accepted",
        acceptedAt: new Date(),
        properties: { ...plan.properties, acceptanceSource: parsed.acceptanceSource },
      },
    });

    await ctx.db.assetEvent.create({
      data: {
        eventType: "PlanAccepted",
        subjectType: "Plan",
        subjectId: plan.id,
        eventSchemaVersion: 1,
        payload: { acceptanceSource: parsed.acceptanceSource, acceptedBy: parsed.acceptedByPartyId },
        actionInvocationId: ctx.actionInvocationId,
        correlationId: ctx.correlationId,
        // …other envelope fields stamped by the platform helper
      },
    });

    return { success: true, data: { planId: plan.id } };
  },
  policies: ["orders.customer_consent.v1"],
  emitsEvents: ["PlanAccepted"],
  idempotent: false,
  mutatesDomain: true,
  stateMachine: {
    entityType: "Plan",
    targetState: "accepted",
    getEntityId: (params) => (params as any).planId,
  },
};
using FabricOrg.Platform.Actions;
using FluentValidation;

public record AcceptOfferParams(
    string PlanId,
    string AcceptanceSource,
    string AcceptedByPartyId);

public class AcceptOfferParamsValidator : AbstractValidator<AcceptOfferParams>
{
    public AcceptOfferParamsValidator()
    {
        RuleFor(x => x.PlanId).NotEmpty();
        RuleFor(x => x.AcceptanceSource)
            .Must(s => s is "consultant_ui" or "member_portal_token");
        RuleFor(x => x.AcceptedByPartyId).NotEmpty();
    }
}

public class AcceptOfferAction : ActionDefinition<AcceptOfferParams>
{
    public AcceptOfferAction()
    {
        ActionId = new ActionId("orders", "submit");
        Namespace = "orders";
        Version = 1;
        Schema = new FluentValidationSchemaValidator<AcceptOfferParams>(
            new AcceptOfferParamsValidator());
        Policies = [new PolicyId("orders", "customer_consent", 1)];
        EmitsEvents = ["PlanAccepted"];
        Idempotent = false;
        MutatesDomain = true;
        StateMachine = new StateMachineBinding
        {
            EntityType = "Plan",
            TargetState = "accepted",
            GetEntityId = (p) => p.PlanId,
        };
    }

    public override async Task<ActionResult> HandlerAsync(
        IActionContext ctx,
        AcceptOfferParams params,
        CancellationToken ct)
    {
        var plan = await ctx.Db.Plans.FindAsync(params.PlanId)
            ?? throw new InvalidOperationException("Plan not found");

        plan.Status = "accepted";
        plan.AcceptedAt = DateTime.UtcNow;
        plan.Properties["acceptanceSource"] = params.AcceptanceSource;

        ctx.Db.AssetEvents.Add(new AssetEvent
        {
            EventType = "PlanAccepted",
            SubjectType = "Plan",
            SubjectId = plan.Id,
            EventSchemaVersion = 1,
            Payload = new Dictionary<string, object?>
            {
                ["acceptanceSource"] = params.AcceptanceSource,
                ["acceptedBy"] = params.AcceptedByPartyId,
            },
            ActionInvocationId = ctx.ActionInvocationId,
            CorrelationId = ctx.CorrelationId,
        });

        return ActionResult.Success(new { plan.Id });
    }
}

See: vertical extensions, stages.


Example 2 — A code policy

import type { PolicyEvaluator } from "@fabricorg/platform/policies";
import type { Prisma } from "@example/database";

export const memberConsentPolicy: PolicyEvaluator<Prisma.TransactionClient> = {
  policyId: "orders.customer_consent.v1",
  version: 1,
  previewSafe: true,
  evaluate: async (ctx) => {
    const params = ctx.parameters as { planId: string };
    const plan = await ctx.db.plan.findUniqueOrThrow({
      where: { id: params.planId },
      include: { external user: true },
    });

    const consent = await ctx.db.consentRecord.findFirst({
      where: { partyId: plan.external user.id, type: "offer_acceptance" },
      orderBy: { signedAt: "desc" },
    });

    if (!consent) {
      return {
        policyId: "orders.customer_consent.v1",
        policyVersion: 1,
        result: "block",
        reason: "No plan-acceptance consent on file for this external user.",
      };
    }

    return { policyId: "orders.customer_consent.v1", policyVersion: 1, result: "pass" };
  },
};
using FabricOrg.Platform.Policies;

public class MemberConsentPolicy : IPolicyEvaluator
{
    public PolicyId PolicyId => new PolicyId("orders", "customer_consent", 1);
    public int Version => 1;
    public bool PreviewSafe => true;

    public async Task<PolicyEvaluationResult> EvaluateAsync(
        IPolicyContext ctx, CancellationToken ct)
    {
        var planId = (string)(ctx.Parameters["planId"] ?? "");
        var plan = await ctx.Db.Plans
            .Include(p => p.ExternalUser)
            .FirstAsync(p => p.Id == planId, ct);

        var consent = await ctx.Db.ConsentRecords
            .Where(c => c.PartyId == plan.ExternalUser.Id && c.Type == "offer_acceptance")
            .OrderByDescending(c => c.SignedAt)
            .FirstOrDefaultAsync(ct);

        if (consent is null)
        {
            return new PolicyEvaluationResult(
                new PolicyId("orders", "customer_consent", 1),
                1,
                PolicyOutcome.Block,
                reason: "No plan-acceptance consent on file for this external user.");
        }

        return new PolicyEvaluationResult(
            new PolicyId("orders", "customer_consent", 1),
            1,
            PolicyOutcome.Pass);
    }
}

See: policy model, enforcement.


Example 3 — A data policy

import type { RuntimePolicyDefinition } from "@fabricorg/platform/policies";

const offerAmountCapPolicy: RuntimePolicyDefinition = {
  policyId: "orders.amount_cap.v1",
  policyVersion: 1,
  kind: "data",
  dataDefinition: {
    conditions: [
      {
        conditionId: "amount_under_cap",
        type: "parameter",
        path: "amount",
        operator: "lte",
        value: 100_000,
        onPass: "pass",
        onFail: "block",
        reason: "Plan amount exceeds the $100,000 cap.",
      },
    ],
    defaultResult: "block",
  },
};
using FabricOrg.Platform.Policies;

var offerAmountCapPolicy = new RuntimePolicyDefinition
{
    PolicyId = new PolicyId("orders", "amount_cap", 1),
    PolicyVersion = 1,
    Kind = PolicyKind.Data,
    DataDefinition = new DataPolicyDefinition
    {
        Conditions = new List<DataPolicyCondition>
        {
            new DataPolicyCondition
            {
                ConditionId = "amount_under_cap",
                Type = DataPolicyConditionType.Parameter,
                Path = "amount",
                Operator = DataPolicyComparisonOperator.LessThanOrEqual,
                Value = 100_000,
                OnPass = PolicyOutcome.Pass,
                OnFail = PolicyOutcome.Block,
                Reason = "Plan amount exceeds the $100,000 cap.",
            }
        },
        DefaultResult = PolicyOutcome.Block,
    }
};

See: policy model.


Example 4 — A state machine

import type { StateMachineDefinition } from "@fabricorg/platform/state-machines";

export const offerStateMachine: StateMachineDefinition = {
  entityType: "Plan",
  states: {
    drafted:   { id: "drafted",   label: "Drafted",   stateClass: "initial" },
    presented: { id: "presented", label: "Presented", stateClass: "active" },
    accepted:  { id: "accepted",  label: "Accepted",  stateClass: "terminal" },
    declined:  { id: "declined",  label: "Declined",  stateClass: "terminal" },
    expired:   { id: "expired",   label: "Expired",   stateClass: "terminal" },
  },
  transitions: [
    { from: "drafted",   to: "presented", causedByAction: "orders.send_quote" },
    { from: "presented", to: "accepted",  causedByAction: "orders.submit" },
    { from: "presented", to: "declined",  causedByAction: "orders.cancel" },
    { from: "presented", to: "expired",   causedByAction: "orders.expire_stale" },
  ],
};
using FabricOrg.Platform.StateMachines;

var offerStateMachine = new StateMachineDefinition
{
    EntityType = "Plan",
    States = new Dictionary<string, StateDefinition>
    {
        ["drafted"] = new StateDefinition("drafted", "Drafted", StateClass.Initial),
        ["presented"] = new StateDefinition("presented", "Presented", StateClass.Active),
        ["accepted"] = new StateDefinition("accepted", "Accepted", StateClass.Terminal),
        ["declined"] = new StateDefinition("declined", "Declined", StateClass.Terminal),
        ["expired"] = new StateDefinition("expired", "Expired", StateClass.Terminal),
    },
    Transitions = new List<StateTransition>
    {
        new StateTransition("drafted", "presented", new ActionId("orders", "send_quote")),
        new StateTransition("presented", "accepted", new ActionId("orders", "submit")),
        new StateTransition("presented", "declined", new ActionId("orders", "cancel")),
        new StateTransition("presented", "expired", new ActionId("orders", "expire_stale")),
    }
};

See: entity overview, invariants.


Example 5 — A FabricModule manifest

import type { FabricModule } from "@fabricorg/platform/modules";
import type { Prisma } from "@example/database";

export const ordersModule: FabricModule<Prisma.TransactionClient> = {
  namespace: "orders",
  version: "1.0.0",
  objectTypes: ["Plan", "Customer", "Order", "Document"],
  eventTypes: [
    { eventType: "PlanAccepted", schema: offerAcceptedSchema, version: 1 },
    { eventType: "PlanDeclined", schema: offerDeclinedSchema, version: 1 },
  ],
  actions: [acceptOfferAction, declineOfferAction, sendOfferAction],
  policies: [memberConsentPolicy, offerAmountCapPolicy],
  stateMachines: [offerStateMachine],
};

Register at startup:

import { registerFabricModules } from "@fabricorg/platform/modules";
import { messagingModule } from "@example/messaging";
import { ordersModule } from "@example/orders";

registerFabricModules([messagingModule, ordersModule]);
using FabricOrg.Platform.Modules;

var ordersModule = new FabricModule
{
    Namespace = "orders",
    Version = "1.0.0",
    ObjectTypes = ["Plan", "Customer", "Order", "Document"],
    EventTypes = new List<EventTypeRegistration>
    {
        new EventTypeRegistration("PlanAccepted", offerAcceptedSchema, 1),
        new EventTypeRegistration("PlanDeclined", offerDeclinedSchema, 1),
    },
    Actions = new List<IActionDefinition>
    {
        new AcceptOfferAction(),
        new DeclineOfferAction(),
        new SendOfferAction(),
    },
    Policies = new List<IPolicyEvaluator>
    {
        new MemberConsentPolicy(),
        new OfferAmountCapPolicy(),
    },
    StateMachines = new List<StateMachineDefinition> { offerStateMachine },
};

Register at startup:

using FabricOrg.Platform.Registries;

var registry = new ModuleRegistry();
registry.Register(messagingModule);
registry.Register(ordersModule);

See: extending entities, vertical extensions pattern.


Example 6 — A projection reducer

import { replayEvents, type ReplayableAssetEvent } from "@fabricorg/platform/projections";

interface PlanProjection {
  status: "drafted" | "presented" | "accepted" | "declined" | "expired";
  acceptedAt?: string;
  declineReason?: string;
}

const initialState: PlanProjection = { status: "drafted" };

const result = await replayEvents<PlanProjection>({
  events: eventStream,
  scope: { tenantId, spaceId, subjectType: "Plan", subjectId: planId },
  initialState,
  applyEvent: (state, event) => {
    switch (event.eventType) {
      case "PlanPresented":
        return { ...state, status: "presented" };
      case "PlanAccepted":
        return { ...state, status: "accepted", acceptedAt: String(event.recordedAt) };
      case "PlanDeclined":
        return { ...state, status: "declined", declineReason: (event.payload as any).reason };
      default:
        return state;
    }
  },
});

console.log(result.state, result.warnings);
using FabricOrg.Platform.Projections;

record PlanProjection(
    string Status,
    string? AcceptedAt = null,
    string? DeclineReason = null);

var initialState = new PlanProjection("drafted");

var result = await ProjectionEngine.ReplayEventsAsync(
    events: eventStream,
    scope: new ReplayScope(tenantId, spaceId, "Plan", planId),
    initialState: initialState,
    applyEvent: (state, @event) => @event.EventType switch
    {
        "PlanPresented" => state with { Status = "presented" },
        "PlanAccepted" => state with
        {
            Status = "accepted",
            AcceptedAt = @event.RecordedAt.ToString("O"),
        },
        "PlanDeclined" => state with
        {
            Status = "declined",
            DeclineReason = (@event.Payload as Dictionary<string, object?>)?["reason"]?.ToString(),
        },
        _ => state,
    });

Console.WriteLine($"{result.State} {result.Warnings}");

See: projection mechanics.


Example 7 — Invoking from an external token holder

// packages/api/modules/external-portal/procedures/accept-plan.ts
import { publicProcedure } from "../../../orpc/procedures";
import { invokeAction } from "../../platform/lib/invoke-action";
import { resolveOfferFromToken } from "../lib/tokens";

export const acceptOfferProcedure = publicProcedure
  .input(acceptOfferTokenSchema)
  .handler(async ({ input }) => {
    // 1. Verify token BEFORE invokeAction.
    const tokenPayload = await resolveOfferFromToken(input.token);
    if (!tokenPayload) throw new Error("Invalid token");

    // 2. Invoke with actorType: external_system.
    return await invokeAction({
      actionId: "orders.submit",
      actorType: "external_system",
      actorId: tokenPayload.partyId,
      tenantId: tokenPayload.tenantId,
      spaceId: tokenPayload.spaceId,
      parameters: {
        planId: tokenPayload.planId,
        acceptanceSource: "member_portal_token",
        acceptedByPartyId: tokenPayload.partyId,
      },
    });
  });
// ExternalPortal.Procedures.AcceptPlan
using FabricOrg.Platform.Runtime;

public class AcceptPlanProcedure
{
    private readonly IActionRuntime _runtime;
    private readonly ITokenResolver _tokenResolver;

    public AcceptPlanProcedure(IActionRuntime runtime, ITokenResolver tokenResolver)
    {
        _runtime = runtime;
        _tokenResolver = tokenResolver;
    }

    public async Task<InvokeActionResult> HandleAsync(AcceptPlanRequest input)
    {
        // 1. Verify token BEFORE invokeAction.
        var tokenPayload = await _tokenResolver.ResolveAsync(input.Token);
        if (tokenPayload is null) throw new InvalidOperationException("Invalid token");

        // 2. Invoke with actorType: external_system.
        return await _runtime.InvokeActionAsync(new InvokeActionRequest
        {
            ActionId = new ActionId("orders", "submit"),
            ActorType = ActorType.ExternalSystem,
            ActorId = tokenPayload.PartyId,
            TenantId = tokenPayload.TenantId,
            SpaceId = tokenPayload.SpaceId,
            Parameters = new Dictionary<string, object?>
            {
                ["planId"] = tokenPayload.PlanId,
                ["acceptanceSource"] = "member_portal_token",
                ["acceptedByPartyId"] = tokenPayload.PartyId,
            },
        });
    }
}

See: integrations → external actor calls, triggers.


See also

On this page