mirror of
https://github.com/mcloh/Enterprise-MCP-Service-Bus.git
synced 2026-11-05 22:14:11 +00:00
45 lines
2.0 KiB
Python
45 lines
2.0 KiB
Python
"""Registry lifecycle state machine (EP-02-T04, README.md §23).
|
|
|
|
Nominate -> Review -> Register -> Publish -> Observe
|
|
Observe -> Change -> Publish
|
|
Observe -> Deprecate -> Retire
|
|
|
|
`ACTIVE` collapses README.md's Publish+Observe into one steady state (a
|
|
manifest that is live and being observed simultaneously, from this RI's
|
|
point of view -- there is no separate "being observed" flag to track). The
|
|
one invariant every caller of `transition()` gets for free is the one this
|
|
task's acceptance criterion names directly: nothing reaches `ACTIVE` without
|
|
having passed through `REVIEW` first.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from emcp_bus.registry.models import LifecycleStatus
|
|
|
|
_ALLOWED_TRANSITIONS: dict[LifecycleStatus, frozenset[LifecycleStatus]] = {
|
|
LifecycleStatus.NOMINATE: frozenset({LifecycleStatus.REVIEW}),
|
|
# A rejected review goes back to NOMINATE (revise and resubmit) rather
|
|
# than staying stuck in REVIEW or disappearing from the registry.
|
|
LifecycleStatus.REVIEW: frozenset({LifecycleStatus.REGISTER, LifecycleStatus.NOMINATE}),
|
|
LifecycleStatus.REGISTER: frozenset({LifecycleStatus.ACTIVE}),
|
|
# "Change" (README.md §23) re-publishes an already-active capability;
|
|
# modeled as ACTIVE -> ACTIVE rather than a distinct state.
|
|
LifecycleStatus.ACTIVE: frozenset({LifecycleStatus.ACTIVE, LifecycleStatus.DEPRECATED}),
|
|
LifecycleStatus.DEPRECATED: frozenset({LifecycleStatus.RETIRED}),
|
|
LifecycleStatus.RETIRED: frozenset(),
|
|
}
|
|
|
|
|
|
class InvalidLifecycleTransitionError(Exception):
|
|
pass
|
|
|
|
|
|
def validate_transition(current: LifecycleStatus, target: LifecycleStatus) -> None:
|
|
"""Raises `InvalidLifecycleTransitionError` unless `current -> target` is
|
|
an allowed edge of the state machine above."""
|
|
if target not in _ALLOWED_TRANSITIONS.get(current, frozenset()):
|
|
raise InvalidLifecycleTransitionError(
|
|
f"{current.value} -> {target.value} is not an allowed registry "
|
|
f"lifecycle transition (README.md §23)"
|
|
)
|