cadrumo.application.live.snapshot_base module¶
Shared lifecycle base classes and helpers for live snapshot services.
This module factors the duplicated state-machine, supersession, and content-
addressed-id derivation logic shared across the bucket-scoped live snapshot
services (Borrador100, Censo, Expedientes, and Notifications). Each concrete
service writes and reads snapshot payloads through a SnapshotRepository
scoped to the active profile bucket.
This module declares the PORT and the lifecycle bases only. The encrypted
secure-object backend that satisfies the port lives in the persistence adapter,
as adapters.persistence.profile.snapshots.SecureSnapshotRepository, so the
storage coupling is an adapter-internal edge rather than an application-layer
reach outward.
Design notes:
SnapshotLifecycleStatecarries the three operator-visible states all stateful snapshot services share. Every stateful service binds payloadstatedirectly to this enum.SnapshotRepositoryis a Protocol — not an abstract class — so concrete per-service repositories (which need to bind a specific TPayload model and a domain-specific object-key prefix) do not need to inherit from it. The service base accepts any object that structurally satisfies the protocol.SnapshotServiceis a generic abstract base whosecapturetemplate method coordinates the dedup-by-content-id, auto-supersession, and late-arrival demotion flow. Subclasses implement_payload_axis_keyand_build_active_payloadto express their domain axis and construction contract; everything else (state transitions, repository orchestration) is shared.StatelessSnapshotServiceis the append-only base for services (Expedientes, Notifications) with no state machine. It acceptsbucket_idper call and constructs a fresh repository for the call from an injectedrepository_factory— the natural shape for services whose public verbs are themselves multi-bucket. Supersession and discard helpers are deliberately absent.
- exception SnapshotNotFoundError(message=None, *, context=None, translated_message=None)[source]¶
Bases:
CadrumoErrorShared base for per-service snapshot-lookup-miss errors.
Inherits from both
cadrumo.core.errors.hierarchy.CadrumoErrorandKeyErrorso the class is enrolled in theERROR_REGISTRYvia theCadrumoError.__init_subclass__hook while preserving the mapping-style lookup-miss type.CadrumoErroris listed first so MRO routes__init__throughCadrumoError.__init__(which accepts the structuredcontext=/translated_message=kwargs) rather thanKeyError’s C-level constructor.Per-service subclasses (BorradorSnapshotNotFoundError, ExpedientesSnapshotNotFoundError, NotificationsSnapshotNotFoundError, and future siblings) inherit from this base alongside
cadrumo.core.errors.hierarchy.CadrumoErrorso callers can either catch the domain-specific class name or the shared parent.- Parameters:
- Return type:
None
- code¶
- class SnapshotLifecycleState(*values)[source]¶
Bases:
StrEnumLifecycle states shared across stateful live snapshot services.
ACTIVE— current valid capture; readers consume this.SUPERSEDED— replaced by a newer ACTIVE capture on the same axis; retained for audit. Carriessuperseded_by_snapshot_id.DISCARDED— explicitly retired by an operator; carries actor + reason audit metadata.
- ACTIVE¶
- SUPERSEDED¶
- DISCARDED¶
- SnapshotLifecycleStateValue¶
The same lifecycle where a CLI row or payload must accept the plain token.
alias of
Literal[ACTIVE,SUPERSEDED,DISCARDED]
- class SnapshotStateFilter(*values)[source]¶
Bases:
StrEnumOperator-facing filter over
SnapshotLifecycleState, plusALL.ALLis deliberately NOT a member ofSnapshotLifecycleState. No persisted snapshot is ever in an “all” state, so adding it there would give every exhaustive match over the lifecycle a branch that cannot occur and would let a stored record claim a state that means “no filter”. The filter is its own closed axis that maps onto the lifecycle, mirroringReviewState.Every lifecycle state has a member here, so a filter exists for each; the correspondence is enforced by a gate rather than left to the next author.
- ACTIVE¶
- SUPERSEDED¶
- DISCARDED¶
- ALL¶
- class SnapshotRepository(*args, **kwargs)[source]¶
-
Structural contract for bucket-scoped snapshot persistence backends.
Implementations may be SecureObjectRepository-backed (Borrador100, Censo) or file-system-backed (stateless services).
- load(snapshot_id)[source]¶
Execute this public contract operation.
- Return type:
TPayload
- Parameters:
snapshot_id (str)
- enforce_snapshot_state_invariants(*, state, has_supersession_pointer, discarded_at, discarded_by, discard_reason='')[source]¶
Enforce the three-state lifecycle invariants for any snapshot payload.
ACTIVE: no supersession pointer, no discard audit metadata. SUPERSEDED: requires supersession pointer, no discard audit metadata. DISCARDED: forbids supersession pointer, requires actor + timestamp.
Domain-specific Pydantic model validators wrap this helper so the same rules apply across Borrador100, Censo, and future stateful services.
- class SnapshotService(*, bucket_id, repository)[source]¶
-
Abstract lifecycle service base for stateful bucket-scoped snapshots.
Subclasses bind
TPayloadto their concrete Pydantic snapshot model and implement two hooks:_payload_axis_key— returns a tuple identifying the domain axis on which prior ACTIVE snapshots are superseded (e.g.(modelo, year, period)for Borrador100,(profile_id,)for Censo)._build_active_payload— constructs an ACTIVE snapshot from keyword-only capture arguments and a derived snapshot id.
The
capturetemplate orchestrates dedup, auto-supersession of prior ACTIVE snapshots, and late-arrival demotion when a freshly-captured snapshot arrives older than the current ACTIVE on the same axis.- Parameters:
bucket_id (str)
repository (SnapshotRepository[TPayload])
- class StatelessSnapshotService(*, repository_factory)[source]¶
-
Append-only base for stateless snapshot services with per-call buckets.
Subclasses inject a
repository_factorythat returns a freshSnapshotRepositoryfor a given bucket id; each public verb acceptsbucket_idand materialises the repository on demand. The per-bucket repository is responsible for storage layout and bucket isolation; the base provides the shared dedup, list, and resolve logic.Subclasses implement two hooks:
_derive_snapshot_idand_build_payload._build_payloadreceives the resolvedbucket_idso payload models can record it on the persisted record.- Parameters:
repository_factory (Callable[[str], SnapshotRepository[TPayload]])