116 lines
3.7 KiB
Markdown
116 lines
3.7 KiB
Markdown
# Subscription Contracts
|
||
|
||
> **Platform contracts only.** No backend subscription engine.
|
||
> ADR: [ADR-023](../architecture/adr/ADR-023.md)
|
||
> Related: [pricing-catalog.md](pricing-catalog.md), [license-entitlement-contracts.md](license-entitlement-contracts.md), [payment-contracts.md](payment-contracts.md)
|
||
> Contract version: `subscription.v1`
|
||
|
||
---
|
||
|
||
## 1. Ownership
|
||
|
||
| Concern | Owner |
|
||
| --- | --- |
|
||
| Subscription commercial lifecycle | Core Platform |
|
||
| Pricing binding | Pricing Catalog refs |
|
||
| License issuance | Core (license contracts) |
|
||
| Payment collection / PSP capture | Payment (when activated) |
|
||
| Accounting AR / contract | Accounting (opaque refs) |
|
||
|
||
Payment’s reserved `payment.future.subscriptions` is a **billing shell**, not ownership of platform Subscription aggregates.
|
||
|
||
---
|
||
|
||
## 2. Contracts
|
||
|
||
### 2.1 SubscriptionPlan
|
||
|
||
| Field | Type | Meaning |
|
||
| --- | --- | --- |
|
||
| `plan_code` | string | Stable code |
|
||
| `display_name` | string | |
|
||
| `bundle_code` | string | Business bundle definition |
|
||
| `bundle_version_code` | string | Pinned commercial version |
|
||
| `default_pricing_item_code` | string | Primary Pricing Catalog ref |
|
||
| `status` | enum | `draft` \| `active` \| `retired` |
|
||
|
||
### 2.2 Subscription
|
||
|
||
| Field | Type | Meaning |
|
||
| --- | --- | --- |
|
||
| `subscription_id` | uuid | Logical id |
|
||
| `tenant_id` | uuid | |
|
||
| `plan_code` | string | |
|
||
| `status` | SubscriptionStatus | |
|
||
| `period` | SubscriptionPeriod | Current period |
|
||
| `renewal_policy` | RenewalPolicy | |
|
||
| `cancellation_policy` | CancellationPolicy | |
|
||
| `grace_period` | GracePeriod | |
|
||
| `pricing_item_code` | string | Bound list price |
|
||
| `started_at` / `ended_at` | datetime? | |
|
||
| `ext` | object | Additive |
|
||
|
||
### 2.3 SubscriptionItem
|
||
|
||
| Field | Type | Meaning |
|
||
| --- | --- | --- |
|
||
| `subscription_id` | uuid | |
|
||
| `item_code` | string | Line identity |
|
||
| `kind` | enum | `bundle` \| `addon` \| `usage` |
|
||
| `pricing_item_code` | string | |
|
||
| `quantity` | int | Default 1 |
|
||
| `service_identifier` | string? | When item maps to a service |
|
||
|
||
### 2.4 SubscriptionLicense
|
||
|
||
| Field | Type | Meaning |
|
||
| --- | --- | --- |
|
||
| `license_id` | uuid | |
|
||
| `subscription_id` | uuid | |
|
||
| `tenant_id` | uuid | |
|
||
| `bundle_code` | string | |
|
||
| `status` | enum | `requested` \| `active` \| `suspended` \| `revoked` \| `expired` |
|
||
| `entitlement_grant_refs[]` | string[] | Opaque refs to entitlement grants |
|
||
| `valid_from` / `valid_to` | datetime? | |
|
||
|
||
### 2.5 SubscriptionStatus
|
||
|
||
`requested` | `trialing` | `active` | `past_due` | `grace` | `cancelled` | `expired` | `suspended`
|
||
|
||
### 2.6 SubscriptionPeriod
|
||
|
||
| Field | Meaning |
|
||
| --- | --- |
|
||
| `period_start` | Inclusive |
|
||
| `period_end` | Exclusive or inclusive per future policy doc |
|
||
| `billing_anchor` | Day/time anchor |
|
||
|
||
### 2.7 RenewalPolicy
|
||
|
||
| Field | Meaning |
|
||
| --- | --- |
|
||
| `mode` | `auto` \| `manual` \| `none` |
|
||
| `notice_days` | Pre-renewal notice |
|
||
|
||
### 2.8 CancellationPolicy
|
||
|
||
| Field | Meaning |
|
||
| --- | --- |
|
||
| `mode` | `end_of_period` \| `immediate` \| `admin_only` |
|
||
| `refund_policy_ref` | Opaque; Payment refunds are separate (14.6+ **not** in this wave) |
|
||
|
||
### 2.9 GracePeriod
|
||
|
||
| Field | Meaning |
|
||
| --- | --- |
|
||
| `days` | Length after past_due before suspend |
|
||
| `entitlements_during_grace` | `full` \| `read_only` \| `none` |
|
||
|
||
---
|
||
|
||
## 3. Invariants
|
||
|
||
1. Creating a Subscription MUST NOT by itself mutate Payment or Accounting databases — only emit activation/request events (see activation flow).
|
||
2. License is derived from an accepted Subscription; entitlements are derived from License.
|
||
3. Amounts come from Pricing Catalog (or enterprise quote process), not from bundle JSON.
|