# @wrnexus/metering

Framework-native entitlement catalogs, credit packs, and usage metering for WrNexus applications.

The package keeps policy separate from persistence: applications provide a `MeterStore`, while the metering facade validates unit amounts and reports insufficient balances separately from storage faults. All amounts are positive safe integers except explicit adjustments, which may be positive or negative but never zero.

## Usage

```ts
import { defineEntitlements, defineMeter, definePacks } from "@wrnexus/metering";

const entitlements = defineEntitlements({
  plans: () => [
    { code: "free", name: "Free", features: [], allowance: 10 },
    { code: "pro", name: "Pro", features: ["exports"], allowance: 1_000 },
  ],
  subscriptionFor: async (subjectId) => subscriptions.planFor(subjectId),
  fallback: "free",
});

const packs = definePacks([
  { code: "starter", units: 100 },
  { code: "plus", units: 500 },
]);

const meter = defineMeter({ store });

if (await entitlements.enabled("user-1", "exports")) {
  const result = await meter.reserve("user-1", 1, "export report");
  if (!result.ok) console.error(result.reason);
}
```

## API

- `defineEntitlements(options)` resolves a subject's plan, features, and allowance from a server-owned catalog, with an explicit fallback plan.
- `definePacks(entries)` creates an immutable, prototype-safe lookup of purchasable unit packs. Clients select a pack code rather than supplying an amount.
- `defineMeter(options)` exposes `balance`, `reserve`, `grant`, `purchase`, `refund`, and `adjust` operations over an application-provided store.

Meter operations return `{ ok: true }` on success or `{ ok: false, reason, fault? }` on refusal. A result with `fault: true` identifies an underlying storage error; use `onFault` for operational reporting without exposing exception-based control flow to callers.
