Add the experience service with sites through analytics/AI hooks, migrations through 0011, and phase docs/manifests marking the track complete. Co-authored-by: Cursor <cursoragent@cursor.com>
51 lines
1.7 KiB
Python
51 lines
1.7 KiB
Python
"""Lifecycle policies for Phase 11.8 aggregates."""
|
|
from app.models.types import (
|
|
BundleDefinitionStatus as D,
|
|
FeatureToggleStatus as F,
|
|
LicenseBindingStatus as L,
|
|
TenantBundleStatus as T,
|
|
)
|
|
from app.validators.bundles import ensure_transition
|
|
|
|
_TRANSITIONS = {
|
|
D: {D.DRAFT: frozenset({D.AVAILABLE, D.RETIRED}), D.AVAILABLE: frozenset({D.RETIRED}), D.RETIRED: frozenset()},
|
|
T: {
|
|
T.PENDING: frozenset({T.ACTIVE, T.REVOKED}),
|
|
T.ACTIVE: frozenset({T.SUSPENDED, T.EXPIRED, T.REVOKED}),
|
|
T.SUSPENDED: frozenset({T.ACTIVE, T.REVOKED}),
|
|
T.EXPIRED: frozenset(),
|
|
T.REVOKED: frozenset(),
|
|
},
|
|
L: {
|
|
L.PENDING: frozenset({L.ACTIVE, L.REVOKED}),
|
|
L.ACTIVE: frozenset({L.EXPIRED, L.REVOKED}),
|
|
L.EXPIRED: frozenset(),
|
|
L.REVOKED: frozenset(),
|
|
},
|
|
F: {
|
|
F.DRAFT: frozenset({F.ACTIVE, F.ARCHIVED}),
|
|
F.ACTIVE: frozenset({F.DRAFT, F.ARCHIVED}),
|
|
F.ARCHIVED: frozenset(),
|
|
},
|
|
}
|
|
|
|
|
|
class BundleDefinitionPolicy:
|
|
def assert_status_change(self, *, current, target):
|
|
ensure_transition(current, target, _TRANSITIONS[D], "bundle_definition")
|
|
|
|
|
|
class TenantBundlePolicy:
|
|
def assert_status_change(self, *, current, target):
|
|
ensure_transition(current, target, _TRANSITIONS[T], "tenant_bundle")
|
|
|
|
|
|
class LicenseBindingPolicy:
|
|
def assert_status_change(self, *, current, target):
|
|
ensure_transition(current, target, _TRANSITIONS[L], "license_binding")
|
|
|
|
|
|
class FeatureTogglePolicy:
|
|
def assert_status_change(self, *, current, target):
|
|
ensure_transition(current, target, _TRANSITIONS[F], "feature_toggle")
|