# Pathrule Pattern: Pricing and Plan Modeling (1.0.0)
# ::pathrule:package:pricing-plan-modeling

### [RULE] Never mutate a price already used by a subscription  (path: /src/billing/catalog)
<!-- scope: folder | priority: high | strict -->

Commercial changes create a new immutable price version with an explicit migration policy. Editing amount, currency, interval, included quantity, or tax behavior in place silently changes the meaning of historical and active subscriptions. Enforce this boundary in /src/billing/catalog so invalid work stops before it reaches another subsystem or creates an externally visible side effect.

- Give products and entitlements stable internal keys while treating display names as editable presentation.
- Create a new price identifier for any monetary or billing-term change and record its effective window.
- Keep legacy prices resolvable for invoices, credits, reporting, and subscriptions that have not migrated.
- Require a migration decision for existing customers: grandfather, opt in, scheduled move, or contract-specific handling.

Verification: Create an active subscription, publish a replacement price, and confirm the original invoice path and entitlement snapshot do not change until the chosen migration runs.

---

### [MEMORY] Entitlements are not plan names  (path: /src/entitlements)

A plan is a commercial package, while an entitlement is a stable product capability with limits and conditions. Resolve a subscription or contract into entitlement keys at one boundary and let product code ask for capabilities such as projects.create or exports.monthly_limit.

Keep marketing labels, provider price IDs, and billing intervals out of authorization checks. Represent quantitative limits and feature access separately so an add-on can alter one without cloning a plan. Version entitlement mappings and preserve the resolved snapshot used for each access period. Keep the decision explicit at /src/entitlements; moving it into an incidental caller makes behavior depend on which route happened to execute first.

See /src/billing/catalog for commercial versions and the subscription billing pattern for access state. That related boundary consumes this decision and carries the evidence that proves it still holds.

---

### [MEMORY] Products, prices, and terms have separate identities  (path: /src/billing/catalog)

The thing sold, the amount and cadence charged, and the contractual conditions change on different timelines and serve different consumers. Model a product as the durable offer, a price as an immutable charge definition, and terms as eligibility, commitment, trial, renewal, or negotiated conditions.

Allow several prices to reference one product without implying identical entitlement mappings. Keep provider IDs as adapters around internal catalog IDs so a provider migration does not rewrite product logic. Snapshot the accepted commercial terms when an order or subscription begins. Keep the decision explicit at /src/billing/catalog; moving it into an incidental caller makes behavior depend on which route happened to execute first.

See /migrations for catalog transitions and /src/entitlements for capability resolution. That related boundary consumes this decision and carries the evidence that proves it still holds.
