Resiliency¶
Baseline resiliency is inherited from the Base Template. Entitlements-specific considerations:
Catalog reconciliation¶
ProductCatalogReactionStateMachine reacts to ProductRetiredEvent to close assignments referencing a retired product. Because the saga can replay events, ReactToCatalogProductRetiredAsync must be idempotent - closing already-closed assignments should be a no-op.
Per-tenant invariant¶
UQ_Entitlements_TenantId guarantees a single entitlement aggregate per tenant; CreateDraftAsync throws EntitlementAlreadyExistsForTenantException on a second draft. Edition assignment requires an active entitlement (EditionAssignmentRequiresActiveEntitlementException).
Write serialization¶
EntitlementEditorGrain (keyed by tenant id) serializes concurrent writes per tenant.