# Support, Entitlements, Billing, and Customer Operations

This page covers the customer-operations governance area of Oshun V1: how a
customer's plan and feature access (**entitlements**) are defined, how money
turns into entitlement (**billing**, settled crypto-first), how usage is metered
and capped, how lapses and refunds are handled (**dunning** and **self-serve**),
and how human help reaches the customer (**support cases**, SLAs, copilots). It
serves paying customers, institutional contract owners, support agents, and the
platform operators who run the billing and support machinery. In the V1
layering, the entitlement/billing/support core is real, shipped, deterministic
domain code in `libs/oshun/billing-support` (package `@oshun/billing-support`,
§23), composed by the product surfaces; the canonical crypto settlement that
_funds_ those entitlements lives in the Aje domain (`libs/aje/`) and is
documented on
[Crypto Payments — Non-Custodial Entitlement Settlement](./crypto-payments.md).
The backlog for this area is **§23**; the feature hub is
[../features.md](../features.md); the companion architecture page is
[Support, Billing, and Crypto](../architecture/support-billing-and-crypto.md).

> **Where the billing logic actually lives — and why the docs were hard to
> navigate.** Both [../features.md](../features.md) (the crypto-settlement path,
> via `libs/aje/` and `libs/oshun/payments-bridge/`) and the architecture page
> (the fiat adapter, via `libs/shared/inbound-integrations/src/payment.ts`)
> describe _payment_ paths that genuinely exist in code. But neither names the
> library that holds the **entitlement, dunning, metered, self-serve, tax, and
> support-case state machines** a reader is actually looking for. That is
> `libs/oshun/billing-support`. This page treats that library as the source of
> truth and wires the payment paths into it explicitly, so the entitlement code
> is findable from the prose for the first time.

## What This Area Is, Concretely

`@oshun/billing-support` is a pure-function domain library — deterministic state
machines and policy tables, no I/O. Its barrel (`src/index.ts`) re-exports
exactly eight modules, and a ninth single-file bridge:

| Module               | Path                                 | Responsibility                                                                                      |
| -------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------- |
| `entitlements`       | `src/entitlements/entitlements.ts`   | Entitlement classes, feature map, subscription state machine, proration, feature-gate, intro offers |
| `paywalls`           | `src/paywalls/paywalls.ts`           | Web/mobile paywall decision and recommended-upgrade computation                                     |
| `dunning`            | `src/dunning/dunning.ts`             | Payment-failure handling, dunning-stage progression, grace windows, trial-conversion scheduling     |
| `self-serve`         | `src/self-serve/self-serve.ts`       | Refund eligibility, pause/resume quotas, promo/gift-code redemption                                 |
| `tax-billing`        | `src/tax-billing/tax-billing.ts`     | VAT/GST/sales-tax application, EU reverse charge, locale-correct receipts                           |
| `metered`            | `src/metered/metered.ts`             | Per-dimension usage accrual, included/soft-cap/hard-cap, usage meter cards                          |
| `support-cases`      | `src/support-cases/support-cases.ts` | Case intake/routing, SLAs, support copilot, CSAT                                                    |
| `billing-aje-bridge` | `src/billing-aje-bridge.ts`          | Maps billing classes → canonical product tier; advances subscription from a settled Aje payment     |

The honest boundary: these are pure cores. The _enforcement_ — charging a real
chain, persisting an immutable invoice, sending a dunning email — is the
runtime's job and the payment adapters'. The library decides; the surrounding
services act.

## Settlement Is Crypto-First and Non-Custodial

V1 settlement is **crypto-first and non-custodial**. The canonical payment
surface is documented in full on
[Crypto Payments — Non-Custodial Entitlement Settlement](./crypto-payments.md),
covering Bitcoin (on-chain + Lightning), Monero, and EVM stablecoins (USDC and
DAI on Base, Arbitrum, and Optimism). The chain implementations live under
`libs/aje/chains/`. Note a documentation correction here:
[../features.md](../features.md) and the architecture notes describe "five new
chain modules" (`monero`, `litecoin`, `ton`, `ergo`, `tron`) — and all five do
exist with real, non-test source — but the actual `libs/aje/chains/` set is
**eight** directories: those five **plus** `cardano`, `solana`, and
`abstraction`. The "five new" count is stale relative to the present chain set.

> **Release: V1.1.** Fiat acceptance is **built but not part of V1.0.** V1.0
> charges through the Aje crypto rail only; the fiat rails ship with the native
> apps in V1.1. The BFF refuses `/v1/payments/fiat/*` with
> `payment_rail_deferred_to_v1_1` — except `/v1/payments/fiat/stripe/webhook`,
> which stays open so settlement callbacks for charges made before the cut still
> land. Everything described below is real and stays in the tree.

Fiat acceptance is implemented as of 2026-07-04: **Stripe Billing**, plus
**Apple Pay** and **Google Pay** (both as Stripe-tokenized payment methods and
as fully-implemented merchant-decrypted wallet tokens), live in
`libs/oshun/fiat-payments/` with BFF routes under `/v1/payments/fiat/*` — see
[Fiat Payments — Stripe Billing, Apple Pay, and Google Pay](../architecture/fiat-payments-and-wallets.md).
The older `libs/shared/inbound-integrations/src/payment.ts` adapter remains the
generic multi-tenant connector framework (now with capture-bounded refunds).
Crypto and fiat terminate in the _same_ place twice over: a **settlement** that
`billing-aje-bridge` translates into a subscription-state transition, and
identical-schema **entitlement-bus events** distinguished only by the `rail`
field. The fiat routes are fail-closed without deployment credentials
(`STRIPE_SECRET_KEY`, webhook secret, Apple merchant identity certificate) —
they refuse rather than pretend.

### The Aje Bridge — One Source of Truth for "Are You Entitled?"

The single most important fact the prose docs omit entirely is the
`billing-aje-bridge`, which closes a long-standing duplication. Two parallel
entitlement vocabularies had drifted apart: the six **billing classes** in
`@oshun/billing-support`, and the three canonical **product tiers**
(`OshunEntitlementTier` from `@oshun/auth-client`) that actually gate the
product. The bridge collapses the former onto the latter via `TIER_BY_CLASS`:

| Billing class (`EntitlementClass`) | Canonical product tier (`OshunEntitlementTier`) |
| ---------------------------------- | ----------------------------------------------- |
| `free`                             | `free`                                          |
| `starter`                          | `pro`                                           |
| `plus`                             | `pro`                                           |
| `pro`                              | `premium`                                       |
| `scholar`                          | `premium`                                       |
| `institutional`                    | `premium`                                       |

`toOshunEntitlementTier(class)` does that mapping;
`entitlementTierForSubscription(sub, nowUnixSeconds)` is **time-aware** (since
the 2026-07-04 audit remediation) and delegates its window decision to
`featureGate`, so the coarse tier and the fine-grained feature gate can never
drift: an `active`/`restored` subscription entitles only while the current
period covers `now`; `trial` requires an unexpired `trialEndsAt`; `grace`
requires an unexpired `graceEndsAt`; `past-due` keeps access **within the
current period** (dunning retries don't instantly cut a paying customer off);
`canceled` keeps access inside its paid-through window (`canceledEffectiveAt`);
everything else — including any state whose window has lapsed — returns `free`.
`subscriptionPermitsFeature(sub, featureKey, now)` is the feature-level
authority (a `scholar` subscription passes premium-tier checks but is still
denied `voice.cloning`).

The other half is `applyPaymentSettlementToSubscription`, which takes a settled
Aje payment — normalized from the confirmation ladder into an
`AjePaymentSettlement` with `status: 'confirmed' | 'failed' | 'refunded'` and an
opaque `reference` (the Aje receipt/tx id, for audit) — and advances the
subscription. It never invents a transition: it computes a target state and then
delegates to `transitionSubscription`, so only legal moves apply, and a
settlement with no transition for the current state is a no-op
(`changed: false`). The mapping:

- **`confirmed`** → `trial`/`past-due`/`grace`/`paused`/`restored` become
  `active`; `canceled`/`lapsed` become `restored`; an already-`active`
  subscription is a no-op.
- **`failed`** → an `active` subscription drops to `past-due`; other states have
  no failed-payment transition.
- **`refunded`** → `active`/`paused`/`trial`/`restored` move to `canceled`;
  `grace`/`past-due` move to `lapsed` (a refund during dunning or grace ends the
  entitling state immediately — previously a silent no-op that let a refunded
  customer keep access until the window expired).

## Entitlement Classes, Features, and the Subscription State Machine

`ENTITLEMENT_CLASSES` is the six-class ladder: `free`, `starter`, `plus`, `pro`,
`scholar`, `institutional`. Each class owns a set of `FEATURE_KEYS` resolved by
`featuresFor(class)`. The full key set is twelve entries, including the
premium-gated `voice.cloning`, `voice.premium-narration`, `avatar.cloning`,
`avatar.premium`, `generated.video`, `generated.high-rate`, and the
institution-only `institutional.gradebook`:

| Class           | Notable feature keys it unlocks (cumulative)                                                                  |
| --------------- | ------------------------------------------------------------------------------------------------------------- |
| `free`          | `assistant.basic`                                                                                             |
| `starter`       | `+ study.basic`                                                                                               |
| `scholar`       | `assistant.deep`, `study.adaptive`, `persona.premium`, `voice.premium-narration` (narration, **not** cloning) |
| `plus`          | `assistant.deep`, `study.adaptive`, `persona.premium`                                                         |
| `pro`           | everything plus `voice.cloning`, `avatar.cloning`, `generated.video`, `generated.high-rate`                   |
| `institutional` | the `plus` set plus `voice.premium-narration` and `institutional.gradebook`                                   |

The deliberate asymmetry — `scholar` and `institutional` grant
`voice.premium-narration` but **not** `voice.cloning` or `avatar.cloning` — is a
governance choice: classroom and institutional contexts get premium narration
without handing students cloning tools.

A `Subscription` carries `entitlementClass`, a `state` from
`SUBSCRIPTION_STATES` (`trial`, `active`, `past-due`, `grace`, `paused`,
`canceled`, `lapsed`, `restored`), the current period bounds, and the timestamps
that make trial/cancellation/grace/intro-offer behavior decidable
(`trialEndsAtUnixSeconds`, `canceledEffectiveAtUnixSeconds`,
`graceEndsAtUnixSeconds`, `introOfferAppliedThroughUnixSeconds`). State moves
are guarded by an explicit `VALID_TRANSITIONS` table inside
`transitionSubscription`; illegal moves return an `illegal-transition` error
rather than silently applying.

### Feature Gating Is Time- and State-Aware

`featureGate({ subscription, featureKey, nowUnixSeconds })` is the single point
a surface asks "may this customer use this feature _right now_?" It returns
either `{ granted: true, via: 'entitlement' | 'trial' | 'grace' }` or
`{ granted: false, reason: 'not-in-plan' | 'subscription-lapsed' | 'paused' }`.
The logic is genuinely time-aware, not a flat boolean:

- A `lapsed` subscription is denied; a `paused` one is denied with `paused`.
- A `canceled` subscription still grants until `canceledEffectiveAtUnixSeconds`
  **and** only while the current period covers `now` — cancellation is honored
  as paid-through-period, then de-entitles.
- A `trial` grants via `trial` only while `now <= trialEndsAtUnixSeconds` and
  the period covers `now`.
- A `grace` subscription grants via `grace` only until `graceEndsAtUnixSeconds`.
- Otherwise the feature must be in the class's feature set _and_ the current
  period must cover `now`.

### Proration and Intro Offers

`computeUpgradeProration` charges (or refunds) the price delta scaled by the
fraction of the billing period remaining:
`charge = round(fractionRemaining * (toPrice - fromPrice))`. A positive charge
means `effectiveNow: true` (an upgrade applies immediately); a negative one (a
downgrade refund) defers. `applyIntroOffer` is one-time-per-user — it rejects
with `already-used` if `introOfferAppliedThroughUnixSeconds` is already set,
`class-not-eligible` if the subscription's class isn't in
`offer.applicableClasses`, and `invalid-offer` for a malformed
discount/duration; on success it stamps the offer through
`now + durationDays * 86400`.

## Paywalls and Upgrade Surfaces

`decidePaywall` powers the web and mobile
(`'web' | 'mobile-ios' | 'mobile-android'`) paywalls and entitlement-aware
gating. Given the customer's current class and the requested feature, it returns
a `PaywallDecision`:

- If the current class already includes the feature →
  `{ showPaywall: false, upsellAngle: 'feature-included' }`.
- If no class includes the feature → `{ upsellAngle: 'graceful-degradation' }`
  (nothing to upsell to).
- Otherwise it computes the _minimum_ class that includes the feature
  (`minimumClassFor`, walking a `CLASS_RANK` order
  `free < starter < scholar < plus < pro < institutional`), and if that target
  outranks the current class returns
  `{ showPaywall: true, recommendedClass, priceAnchor, upsellAngle: 'feature-locked' }`,
  with the price anchor pulled per-class from the supplied
  `PaywallPriceCatalog`.

For the crypto path the surface renders a per-invoice address or BOLT11 string
plus a QR code and never redirects to a custodial processor — that rendering and
the rate-locking detail live on [Crypto Payments](./crypto-payments.md).

## Metered Billing — Usage, Caps, and Meter Cards

`METERED_DIMENSIONS` is five dimensions, two of which the prose docs miss
entirely (`gpu-minutes`, and the unit name `agentic-cost-units`):

```
['agentic-cost-units', 'voice-seconds', 'avatar-seconds',
 'storage-bytes-hours', 'gpu-minutes']
```

`accrueUsage` is the metered core. It first **rejects** mismatched input
(dimension or subscription mismatch, non-positive quantity, an out-of-period
timestamp, or a soft-cap above the hard-cap). It then applies the included
allowance: only usage _past_ `includedQuantityPerPeriod` is billable, computed
as the marginal slice `max(0, next - included) - max(0, used - included)` and
priced at `perUnitCentsAfterIncluded`. Caps gate the result:

- crossing `softCapQuantityPerPeriod` raises `alert: 'soft-cap-warn'`;
- being at/over `hardCapQuantityPerPeriod` rejects with `hard-cap-reached`
  (`accepted: false`), pinning `newUsedQuantity` to the hard cap so usage never
  silently exceeds it.

`buildUsageMeterCard` produces the per-user UI meter — `used`,
`includedQuantity`, caps, `fractionOfHardCap` (clamped to 1), and a `status` of
`'ok' | 'soft-cap' | 'hard-cap'` — which drives the usage-meter and budget-cap
surfaces. Metered top-ups settle through the same invoice contract as everything
else.

## Dunning, Grace, and Trial Conversion

`DUNNING_STAGES` is the five-stage ladder
`first-warning → second-warning → final-warning → grace → lapse`.
`recordPaymentFailure` enters or advances the dunning state and schedules the
next retry at `now + retryBackoffSeconds`; `recordPaymentSuccess` clears it.
`advanceDunningStage` walks the ladder against a `DunningPolicy` whose
`DEFAULT_DUNNING_POLICY` is concrete: 3 retries per stage, a 1-day (`86400 s`)
retry backoff, 3 days between first→second and second→final warnings, and a
7-day grace window. The ladder progresses on _elapsed time and retry count_ —
`final-warning` advances to `grace` only after `retryCount >= retriesPerStage`,
and `grace` advances to `lapse` only once `now >= graceEndsAtUnixSeconds`. On
`lapse`, `degradedEntitlementOnLapse()` returns `'free'`: graceful feature
degradation, not a hard cutoff. `trialPromptSchedule` fires three conversion
prompts — `pre-expiry` (3 days before), `at-expiry`, and `post-expiry` (1 day
after).

## Self-Serve Refunds, Pause/Resume, and Codes

`SELF_SERVE_ACTIONS` enumerates `refund-request`, `credit-issued`,
`plan-change`, `pause`, `resume`, `redeem-gift-code`, `redeem-promo-code`.

`evaluateRefundEligibility` is a real risk gate, not a rubber stamp. It
auto-approves only reason codes in a fixed table — `first-7d-cancel` (≤
\$50.00), `duplicate-charge` (≤ \$1,000.00), `service-outage` (≤ \$50.00) — and
routes everything else to `manual-review` with a specific reason:
`reason-not-auto-approvable`, `amount-exceeds-auto-cap`, or
`refund-velocity-throttle` once a customer has had 3+ refunds in the month.
Crypto refunds additionally require the customer to supply a destination address
(Monero has no on-chain return path; Bitcoin and EVM default to the original
sender, with explicit override) — see [Crypto Payments](./crypto-payments.md).

`startPause`/`endPause` enforce a `maxPauseDaysPerYear` quota
(`pause-quota-exceeded` when `daysPausedInLast365 >= maxPauseDaysPerYear`).
`redeemPromoCode` validates a `PromoCode` against expiry, `maxUses`/`usesSoFar`,
and `applicableClasses`, returning a `{ percent, cents }` discount or a typed
rejection (`expired`, `max-uses-reached`, `class-not-eligible`, `unknown-code`,
`invalid-code`).

## Tax-, Region-, and Currency-Aware Billing

`applyTax` computes VAT/GST/sales-tax/HST/PST against a per-jurisdiction
`TaxRate`. Its non-trivial case is **EU cross-border B2B reverse charge**: when
a VAT-rated, business customer with a VAT number transacts cross-border between
two EU jurisdictions (matched against the explicit 27-member `EU_JURISDICTIONS`
set), tax is shifted to the customer (`taxCents: 0`,
`reverseChargeApplied: true`). `formatCurrency` and `buildReceiptSummary`
produce locale-correct receipts via `Intl.NumberFormat` (with a graceful
`CUR 0.00` fallback), and the receipt explicitly annotates a reverse-charge
line. Crypto invoices additionally show fiat-equivalent at invoice time plus the
locked rate and slippage tolerance — detailed on
[Crypto Payments](./crypto-payments.md).

## Support Cases — Intake, Routing, SLAs, Copilots

The concrete support-case state machine lives in
`src/support-cases/support-cases.ts` (the architecture page describes SLAs as
"monitored by `libs/shared/queue/src/sla-monitor.ts` patterns" and points the
`SupportCase` contract at the backlog, but never names this implementation —
that is where the real logic is).

`CASE_ROUTING_QUEUES` is the seven-queue set
`['general', 'billing', 'technical', 'safety', 'privacy', 'institutional', 'crisis']`,
and `CASE_STATES` runs
`received → triaged → in-progress → awaiting-customer → resolved → reopened → escalated`.
`routeCase` applies a priority order: a crisis signal routes to `crisis` first,
then institutional to `institutional`, then any safety/privacy tag wins (so a
safety concern is never buried under a billing tag), then the first tag's mapped
queue, else `general`.

SLAs are per-queue, with the safety and crisis queues mirroring Trust & Safety's
urgency:

| Queue                   | First-response budget | Resolution budget |
| ----------------------- | --------------------- | ----------------- |
| `crisis`                | 5 min                 | 1 h               |
| `safety`                | 30 min                | 24 h              |
| `privacy`               | 4 h                   | 14 d              |
| `institutional`         | 4 h                   | 5 d               |
| `billing`               | 12 h                  | 3 d               |
| `general` / `technical` | 24 h                  | 7 d               |

`evaluateCaseSla` reports `firstResponseBreached` / `resolutionBreached` and the
seconds remaining against each budget. `answerWithCitations` is the support
**copilot**: it is grounded-by-construction — the caller supplies retrieved
passages, and the copilot **abstains and escalates to a human** when there are
no valid passages or the mean relevance of its top-3 passages is below 0.4,
rather than guessing. `captureCsat` accepts a 1–5 score only on a `resolved`
case, and `aggregateCsat` rolls up the mean. A `SupportCase` also records a
`memoryPrivacyMode` (`'no-access' | 'session-only' | 'with-consent'`) so an
agent never reads memory without the corresponding privacy posture.

## How This Fits the Broader Governance Area

Support, entitlements, and billing are one of four interlocking governance
cores. The others — **Trust & Safety** (policy taxonomy, severity SLAs, the
appeal/decision taxonomy, and the cross-surface crisis-frame cascade) and
**Privacy** (consent, DSAR, retention/deletion, residency, and regulatory
compliance) — are documented on the sibling pages
[Review, Compliance, and Trust & Safety](./review-trust-safety.md) and
[Privacy, Consent, Data Portability, and User Controls](./privacy-consent-portability.md).
They connect directly to billing in several places, and three connections are
worth making concrete because they cross the area boundary:

- **The crisis queue.** `routeCase` sends a crisis-signalled support case to the
  `crisis` queue with the harshest SLA (5 min first response). On the Trust &
  Safety side this is backed by a real cross-surface cascade: the event
  `LILITH_CRISIS_FRAME_ACTIVATED_EVENT = 'lilith.crisis_frame.activated'` is
  published (via a port — the domain stays free of `@oshun/event-bus` by design)
  and fanned out to
  `CRISIS_FRAME_SURFACES = ['psyche', 'lilith-video', 'tara', 'iris', 'assistant']`
  by per-surface projectors, with `crisis-frame-worker.ts` binding the real
  Redis `@oshun/event-bus`. A crisis frame always sets `haltSynthesis` and
  `suspendMemoryWrites` — non-overridable. See
  [Review, Compliance, and Trust & Safety](./review-trust-safety.md).
- **Severity SLA budgets.** Trust & Safety's `SLA_BY_SEVERITY` is a real
  `SlaBudget` table keyed by `['P0','P1','P2','P3']` — P0: 5-min triage / 15-min
  action, `minReviewerTier: 'crisis-trained'`, `requiresParallelIncident` and
  `requiresPostIncidentReview`; P1: 30-min / 2-h, `'senior'`; P2: 8-h / 48-h,
  `'standard'`; P3: weekly aggregate only. A `billing-action-reversal` is an
  **appealable** decision kind, which is why billing reversals issued as safety
  decisions still flow back through the appeal machinery.
- **Privacy retention of billing data.** Privacy's `RETENTION_DAYS` table pins
  `billing` and `audit` data to `365 * 7` (seven years), `raw-chat` to 30 days,
  `summarized-profile` to `'durable'`, and `generated-artifact` to
  `'per-artifact-policy'`, with `SOFT_DELETE_DEFAULT_SECONDS = 30 * 86400` and a
  `validateSoftDeleteWindow` bound (24 h min, 90 d max). That is why a full
  account erasure does not wipe seven-year billing/audit records — they are
  retained under regulatory policy. See
  [Privacy, Consent, Data Portability, and User Controls](./privacy-consent-portability.md).

> **A note on `libs/maat`.** Some grounding lists cite `libs/maat` as governance
> code. It is **not** Oshun V1 governance: `@maat/*` is a separate Ghana B2B
> intelligence product (`COMPLIANCE_LIBRARY = '@maat/compliance'`, with a
> Ghana-data-protection compliance engine, regulatory-filing automation, and ESG
> reporting). The Oshun review/T&S/privacy/billing implementation is
> `libs/oshun/trust-safety`, `libs/oshun/privacy`, and
> `libs/oshun/billing-support` — not `libs/maat`.

## Honest Status

The entitlement, paywall, dunning, self-serve, tax, metered, support-case, and
Aje-bridge logic in `@oshun/billing-support` is real, deterministic, typed, and
tested (`billing-support.test.ts`, `billing-aje-bridge.test.ts`). Nothing in
this core fabricates a result. The boundaries are honest and live elsewhere by
design: actually charging a chain and confirming settlement is the Aje domain's
job (`libs/aje/`, [Crypto Payments](./crypto-payments.md)); fiat acceptance is
**V1.x optional** through `libs/shared/inbound-integrations/src/payment.ts`;
persisting immutable invoices/audit and sending dunning communications is the
runtime's. The library decides who is entitled, what to bill, when to dun, and
how to route a case — it does not pretend to have performed the I/O it hands
off.

## Related

- [Crypto Payments — Non-Custodial Entitlement Settlement](./crypto-payments.md)
  — the canonical settlement surface that funds these entitlements; chains under
  `libs/aje/chains/`.
- [Review, Compliance, and Trust & Safety](./review-trust-safety.md) — policy
  taxonomy, severity SLAs, decision/appeal taxonomy, and the crisis-frame
  cascade that the `crisis` support queue feeds.
- [Privacy, Consent, Data Portability, and User Controls](./privacy-consent-portability.md)
  — retention/deletion of billing and audit data, consent, DSAR, and residency.
- [Tenant, Institution, and Operator Toolkit](./tenant-toolkit.md) — tenant
  seats and institutional contracts that the `institutional` class and
  tenant-scoped invoicing serve.
- [Generation Audience Tiers and Surface Boundaries](./generation-tiers-and-surfaces.md)
  — the generated/voice/avatar features that `pro` and `institutional` gate.
- [Admin Products — Web and Mobile](./admin-products.md) — the operator surfaces
  that run billing, dunning, and support queues.
- [Architecture, Platform Foundations, and Security](./platform-foundations-and-security.md)
  — platform isolation and audit context.
- Companion architecture:
  [Support, Billing, and Crypto](../architecture/support-billing-and-crypto.md).
- [Subsystem Glossary](./glossary.md) and
  [Product Surfaces](./product-surfaces.md).
- Hub: [../features.md](../features.md). Backlog: §23.
