TanstackTemplate
Reference Contracts

Usage Event Ledger Extraction Protocol

Candidate: usage-event-ledger

Target owner: cloudflare-saas-core

Target package: cloudflare-saas-core/packages/usage-ledger

Purpose

This protocol freezes the shared contract for append-only usage accounting before usage ledger code moves out of this vertical template. The goal is to make usage events, replay windows, aggregate reports, and privacy scanning reusable across AI and SaaS templates without turning product-specific event names, plan packaging, or quota policy into core behavior.

Shared Contract

The shared package should own pure schemas and validators for:

  • usage event envelope shape
  • idempotency key semantics
  • plan-at-submission snapshots
  • replay and backfill windows
  • aggregate usage summaries
  • public-safe usage report privacy scanning

Core may define required fields such as event id, event type, subject label, plan key, quantity, occurred-at time, and idempotency key. Core should not own a product's event namespace, billing meaning, plan catalog, quota calculation, or workspace identity mapping.

Core Inputs

Core can receive structured inputs such as:

  • product event records after the product maps them into the shared envelope
  • replay bounds and dry-run flags
  • aggregate counts by public-safe plan label and event kind
  • redacted actor/workspace references
  • operator-owned backfill references
  • evidence that raw ids, storage keys, and provider metadata were excluded

Every input must be safe for an ops summary or release packet. Secret values, raw account identifiers, provider execution identifiers, storage keys, and image bytes must stay out of the shared artifact.

Product Adapters

The product template keeps adapters for:

  • mapping product event names into the shared event envelope
  • mapping vertical plan names and capabilities into public-safe labels
  • reading product-specific D1 source rows for backfill
  • deciding whether live quota uses job counts, ledger replay, or paid metering
  • rendering product-specific quota copy in the UI

Adapters emit public-safe events and aggregate summaries into the shared contract. Core validates and formats; it does not decide what a conversion, message, render, or seat means commercially.

Privacy Rules

The shared validators must reject artifacts containing:

  • API tokens, bearer tokens, webhook secrets, or provider credentials
  • raw actor, user, account, workspace, customer, or owner ids
  • R2 object keys, provider input keys, generated output keys, or private URLs
  • raw provider execution ids, Gateway metadata, or image bytes
  • raw billing provider customer or subscription ids

Artifacts may include stable public labels, redacted references, event counts, plan labels, UTC timestamps, current commit SHAs, and reviewer-owned reference labels.

Acceptance Fixture

The product-free fixture lives at usage-event-ledger.core-fixture.json. Before extraction, the fixture must keep these constraints true:

  • it references usage-event-ledger
  • it names cloudflare-saas-core/packages/usage-ledger as the target
  • it includes event, replay, ops summary, and privacy-boundary stages
  • it keeps product adapters separate from core validators
  • it contains no vertical product name, raw storage key, token marker, or actor identifier

Extraction Sequence

  1. Keep current product-local usage events as the source of truth.
  2. Add a second product or platform fixture that maps different event names into the same envelope.
  3. Move only envelope validation, idempotency checks, aggregate report formatting, and privacy scanning into core.
  4. Keep quota policy, plan catalog, event names, backfill source queries, and UI copy in each product template.
  5. Run the product template's usage, ops, and backfill tests before claiming the extraction complete.

Non-Goals

  • No billing-grade invoice calculation.
  • No payment provider SDK integration.
  • No global quota policy.
  • No shared plan catalog.
  • No migration of product event tables without a separate data plan.

On this page