Examples

Every snippet here is lifted from real, maintained sources — synthetic recipe fixtures under recipes/, component READMEs, or conformance tests — and cites where it lives. An example that was never executed is documentation that lies.

Full composition recipes are synthetic on purpose (fictional product shapes). Machine-readable metadata lives in catalog.json. Agents should fetch the catalog rather than inventing package sets — these examples assume your agent has the assembly skill and catalog installed; the get-started page covers that setup. One-shot environment runbooks for the Bench Ticket demo live at /runbooks.

Recipe index

Recipes with green fixtures are CI-tested and safe to quote. Pending intents stay metadata-only until a fixture lands.

Pending / deferred recipe intents
  • durable-auth-rate-limits — pending
  • health-public-liveness — pending
  • logger-tee-composition — pending
  • inbound-webhook-receipts — none (awaits package publication)

Accounts on a Cloudflare-shaped host

Northshelf Branch (synthetic): first-party Identity with passkeys and email codes, Sessions, durable rate limits, and Authorization claims projection. Production hosts inject @pegma/storage-cloudflare-d1; the fixture tests with memory.

export function createNorthshelfComposition(
  options: NorthshelfCompositionOptions,
): NorthshelfComposition {
  const store = options.store;
  // Live clock by default so production-shaped hosts expire challenges/sessions.
  // Tests inject fixedClock when they need deterministic timestamps.
  const clock = options.clock ?? systemClock;
  const emailCodeProtector = createHmacEmailCodeProtector(
    decodeEmailCodeSecret(options.emailCodeSecretBase64),
  );

  const registrationLimiter = durableLimiter(
    store,
    'northshelf-passkey-registration',
    10,
    5 * 60_000,
  );
  const authenticationLimiter = durableLimiter(
    store,
    'northshelf-passkey-authentication',
    30,
    5 * 60_000,
  );
  const emailCodeRequestLimiter = durableLimiter(
    store,
    'northshelf-email-code-request',
    5,
    10 * 60_000,
  );
  const emailCodeVerificationLimiter = durableLimiter(
    store,
    'northshelf-email-code-verification',
    10,
    10 * 60_000,
  );

  const identity = createIdentity({
    store,
    issuer: NORTHSHELF_RP.issuer,
    rpName: NORTHSHELF_RP.rpName,
    rpID: NORTHSHELF_RP.rpID,
    origins: [...NORTHSHELF_RP.origins],
    registrationLimiter,
    authenticationLimiter,
    emailCodeProtector,
    emailCodeRequestLimiter,
    emailCodeVerificationLimiter,
    clock,
  });

  const sessions = createSessionStore(store, {
    clock,
    ...(options.logger === undefined ? {} : { logger: options.logger }),
  });

  const mailWorker = identity.createMailWorker({
    workerId: options.mailDelivery.workerId ?? 'northshelf-identity-mail',
    provider: options.mailDelivery.provider,
    reconciliation: options.mailDelivery.reconciliation,
    renderer: options.mailDelivery.renderer,
    leaseMilliseconds: 30_000,
    acceptedCallbackMilliseconds: 5 * 60_000,
  });

  return Object.freeze({
    store,
    identity,
    sessions,
    mailWorker,
    registrationLimiter,
    authenticationLimiter,
    emailCodeRequestLimiter,
    emailCodeVerificationLimiter,
    emailCodeProtector,
    clock,
    identityLinkFromClaims: identityLinkKeyFromVerifiedIdentityClaims,
  });
}

Source: recipes/cf-passkey-accounts/composition.ts

Storage + audit + mail outbox in one transaction

Yard Loan (synthetic): inventory mutation, audit row, and mail job commit together in a single-partition transact. Audit and Mail own no store — the host collection is the atomic boundary.

export async function checkoutEquipment(
  composition: YardLoanComposition,
  input: CheckoutInput,
): Promise<CheckoutResult> {
  const { deskId, partition, records, audit, mail } = composition;

  const outcome = await records.transact(partition, [
    {
      action: 'insert',
      value: {
        kind: 'loan',
        deskId,
        itemId: input.itemId,
        borrowerPrincipalId: input.borrowerPrincipalId,
        status: 'checked_out',
      },
    },
    audit.action({
      id: input.auditEventId,
      occurredAt: input.occurredAt,
      actor: {
        kind: 'principal',
        principalId: input.actorPrincipalId,
      },
      action: 'yard_loan.item.checked_out',
      subject: input.itemId,
      details: {
        borrower: input.borrowerPrincipalId,
      },
    }),
    mail.action({
      partition,
      id: input.mailJobId,
      recipientRef: input.borrowerPrincipalId,
      contentRef: `yard_loan.checkout:${input.itemId}`,
      createdAt: input.occurredAt,
    }),
  ]);

  if (!outcome.committed) {
    return { committed: false, reason: outcome.reason };
  }
  return { committed: true };
}

Source: recipes/storage-audit-mail-outbox/composition.ts

Support desk with email-code login

Bench Ticket (synthetic): first-party Identity email-code (not Auth0/Entra/passkeys-required), Sessions, Support Desk create/list/reply, Health, and mail to a catcher. Tests inject memory; environment runbooks inject D1, Azure Tables, or @pegma/storage-dynamodb (requires the storage-core adapter PR to be merged). See environment runbooks.

export function createBenchTicketComposition(
  options: BenchTicketCompositionOptions,
): BenchTicketComposition {
  const store = options.store;
  const clock = options.clock ?? systemClock;
  const { issuer, rpID } = originParts(options.origin);
  const emailCodeProtector = createHmacEmailCodeProtector(
    decodeEmailCodeSecret(options.emailCodeSecretBase64),
  );

  // Passkey limiters exist because Identity requires them. This demo does not
  // require passkeys; email-code is the login path.
  const registrationLimiter = createMemoryLimiter(
    defineRateLimitPolicy({
      name: 'bench-ticket-passkey-registration',
      limit: 10,
      windowMs: 5 * 60_000,
    }),
    { clock },
  );
  const authenticationLimiter = createMemoryLimiter(
    defineRateLimitPolicy({
      name: 'bench-ticket-passkey-authentication',
      limit: 30,
      windowMs: 5 * 60_000,
    }),
    { clock },
  );
  const emailCodeRequestLimiter = createDurableLimiter(
    defineRateLimitPolicy({
      name: 'bench-ticket-email-code-request',
      limit: 10,
      windowMs: 10 * 60_000,
    }),
    store,
    { clock },
  );
  const emailCodeVerificationLimiter = createDurableLimiter(
    defineRateLimitPolicy({
      name: 'bench-ticket-email-code-verification',
      limit: 20,
      windowMs: 10 * 60_000,
    }),
    store,
    { clock },
  );

  const identity = createIdentity({
    store,
    issuer,
    rpName: 'Bench Ticket',
    rpID,
    origins: [options.origin],
    registrationLimiter,
    authenticationLimiter,
    emailCodeProtector,
    emailCodeRequestLimiter,
    emailCodeVerificationLimiter,
    clock,
  });

  const sessions = createSessionStore(store, {
    clock,
    ...(options.logger === undefined ? {} : { logger: options.logger }),
  });

  const support = createSupportDeskApplication({
    store,
    clock,
    ...(options.logger === undefined ? {} : { logger: options.logger }),
    allowedCategories: BENCH_TICKET_CATEGORIES,
  });

  const mailWorker = identity.createMailWorker({
    workerId: options.mailDelivery.workerId ?? 'bench-ticket-identity-mail',
    provider: options.mailDelivery.provider,
    reconciliation: options.mailDelivery.reconciliation,
    renderer: options.mailDelivery.renderer,
    leaseMilliseconds: 30_000,
    acceptedCallbackMilliseconds: 5 * 60_000,
  });

  const health = async (): Promise<HealthHttpResponse> => {
    const result = await runHealthChecks({
      service: BENCH_TICKET.service,
      clock,
      ...(options.logger === undefined ? {} : { logger: options.logger }),
      checks: [
        createProcessCheck('process'),
        createStorePingCheck({
          store,
          collection: healthProbeCollection,
          name: 'storage',
          clock,
        }),
      ],
    });
    return toHealthResponse(result);
  };

  return Object.freeze({
    store,
    origin: options.origin,
    identity,
    sessions,
    support,
    mailWorker,
    emailCodeRequestLimiter,
    emailCodeVerificationLimiter,
    clock,
    health,
    customerAccess: benchTicketCustomerAccess,
  });
}

Source: recipes/bench-ticket/composition.ts

Declare what you keep

A component declares a collection — name, key, codec — and never learns what the database is. The codec is where your types meet flat storage; the same declaration runs over the in-memory store in tests and the Azure Tables adapter in production.

import { defineCollection, createMemoryStore } from "@pegma/storage-core";

interface Session {
  readonly id: string;
  readonly principalId: string;
  readonly expiresAt: string;
}

const sessions = defineCollection<Session>({
  name: "sessions",
  key: (session) => ({ partition: "session", id: session.id }),
  codec: {
    encode: (session) => ({ ...session }),
    decode: (record) => ({
      id: String(record["id"]),
      principalId: String(record["principalId"]),
      expiresAt: String(record["expiresAt"]),
    }),
  },
});

const store = createMemoryStore();
const collection = store.collection(sessions);

Source: storage-core README

Change a record safely

update reads, asks your decider what to write, and writes — re-running the decider against freshly read state whenever someone else got there first. A staleness check inside the decider is re-evaluated on every conflict; a check performed before the call is a check against state that may no longer be true.

const result = await collection.update(key, (current) => {
  if (current === null) return { action: "keep" };
  if (current.version >= incoming.version) return { action: "keep" };
  return { action: "write", value: applyEvent(current, incoming) };
});

Source: storage-core README

Notify without pretending durability

Spine's in-process bus is the lossy tier on purpose — cache invalidation and metrics, never anything that must survive a crash. Durable events belong in a storage-backed outbox, and the choice between tiers is visible in the code rather than left to memory.

import { createEventBus, defineEvent, type PrincipalId } from "@pegma/spine";

interface AccountCreated {
  readonly principalId: PrincipalId;
  readonly email: string;
}

// Declared in a component's contracts package and exported as a constant, so
// publishers and subscribers are checked against the same type.
const AccountCreated = defineEvent<AccountCreated>("account.created");

// Wired once at the host's composition root.
const bus = createEventBus();

bus.subscribe(AccountCreated, (envelope) => {
  welcomeCache.invalidate(envelope.payload.principalId);
});

Source: spine README