# License & Entitlement Contracts

> **Contracts only.** Integrates services by reference — no cross-service ownership.  
> ADR: [ADR-023](../architecture/adr/ADR-023.md) · [ADR-021](../architecture/adr/ADR-021.md)  
> Contract version: `license-entitlement.v1`

---

## 1. Layering (aligned with Payment L1/L2/L3)

| Layer | Name | Owner | Example |
| --- | --- | --- | --- |
| L1 | Service / module / feature entitlement | Core Platform | `payment.module.enabled` |
| L2 | Service capability pack | Owning service | `payment.byo_psp.basic` |
| L3 | Feature toggle / capability flag | Owning service | `refunds_enabled` |

Commercial License grants **L1** (and may *request* L2 activation via events). Services remain authoritative for L2/L3.

---

## 2. Contracts

### 2.1 ServiceEntitlement

| Field | Type | Meaning |
| --- | --- | --- |
| `tenant_id` | uuid | |
| `service_identifier` | string | Manifest id |
| `enabled` | bool | L1 gate |
| `license_id` | uuid? | Source license |
| `visible_to_tenant` | bool | Tenant Visibility |
| `source` | enum | `subscription` \| `trial` \| `admin_grant` \| `legacy` |

### 2.2 ModuleEntitlement

| Field | Type | Meaning |
| --- | --- | --- |
| `tenant_id` | uuid | |
| `module_key` | string | |
| `service_identifier` | string | |
| `enabled` | bool | |
| `license_id` | uuid? | |

### 2.3 FeatureEntitlement

| Field | Type | Meaning |
| --- | --- | --- |
| `tenant_id` | uuid | |
| `feature_key` | string | |
| `enabled` | bool | |
| `license_id` | uuid? | |

### 2.4 Quota

| Field | Type | Meaning |
| --- | --- | --- |
| `quota_key` | string | e.g. `sms.monthly`, `seats` |
| `tenant_id` | uuid | |
| `limit` | int \| `unlimited` | |
| `period` | enum | `monthly` \| `yearly` \| `lifetime` \| `rolling_30d` |
| `license_id` | uuid? | |

### 2.5 UsageLimit

| Field | Type | Meaning |
| --- | --- | --- |
| `limit_key` | string | |
| `tenant_id` | uuid | |
| `max_value` | int | |
| `enforcement` | enum | `hard` \| `soft` \| `observe` |

### 2.6 CapabilityFlag

| Field | Type | Meaning |
| --- | --- | --- |
| `capability_key` | string | Discovery / UI gate |
| `tenant_id` | uuid | |
| `value` | bool \| string \| number | |
| `owner_service` | string | Who evaluates |

### 2.7 TenantVisibility

| Field | Type | Meaning |
| --- | --- | --- |
| `tenant_id` | uuid | |
| `resource_kind` | enum | `service` \| `module` \| `bundle` \| `admin_nav` \| `capability` |
| `resource_key` | string | |
| `visible` | bool | Hide inactive commercial surfaces |
| `reason` | string? | |

---

## 3. Integration matrix (contracts only)

| Service | How commercial foundation integrates |
| --- | --- |
| **Identity** | AuthN/session; role checks use permissions exposed when L1+visibility allow; Identity does not own licenses |
| **Payment** | L1 `payment.module.enabled` from Core; L2/L3 remain Payment; activation may emit `payment.activation.requested` |
| **Accounting** | Opaque `accounting.contract.requested`; Accounting owns books |
| **Experience** | Workspace/dashboard shells after entitlement; Experience does not own subscription |
| **CRM** | Optional L1 `crm.module.enabled`; CRM owns CRM data |
| **Communication** | Quotas (e.g. SMS) via Quota contracts; Communication owns send engines |
| **Delivery / Hospitality / Healthcare / Sports / Loyalty** | Same pattern: L1 from Core license; service owns domain |

Events that invalidate caches: reuse / extend Core `feature_access.changed` semantics (existing platform pattern).

---

## 4. Invariants

1. No service writes another service’s L2/L3 rows.
2. Hidden / disabled entitlements MUST not expose admin nav, APIs, or capabilities (same isolation rule as ADR-021).
3. Quotas are commercial limits; usage metering engines remain future/service-owned.
