Source code for cadrumo.application.flows.checkpoint
"""The per-mode checkpoint port.The substrate defines the port; the domain flow supplies theimplementation, and every implementation routes through the owningdomain's existing encrypted persistence authority — never a bespokestore, never flow-owned crypto. The facts are the checkpoint: the portpersists the canonical answer map only, and resume rebuilds everythingderived (cursor, staleness, validation) from the *current* definition(:mod:`.resume`).Availability is a per-mode declaration on the:class:`~cadrumo.application.flows.definition.FlowDefinition` (``checkpoint``field). ``UNAVAILABLE`` is the declared no-op arm: :func:`save_checkpoint`refuses rather than silently dropping, and frontends read:func:`checkpoint_available` to disable the save-and-exit affordancewith an explicit message — an interrupted run in a no-op mode discardsstaged answers loudly, never silently."""from__future__importannotationsfromcollections.abcimportMappingfromtypingimportProtocol,runtime_checkablefrom...core.flowsimportCheckpointAvailability,FlowModefrom.definitionimportFlowDefinitionfrom.engineimportFlowStatefrom.errorsimportFlowCheckpointError
[docs]@runtime_checkableclassCheckpointStore(Protocol):"""Domain-supplied persistence port for in-progress flow answers. Implementations MUST write through the owning domain's mutation authority (for the profile domain: effective-dated fact writes via the profile lifecycle service) and MUST NOT persist plaintext anywhere. ``load`` returns the persisted canonical answer map or ``None`` when no in-progress run exists; ``discard`` erases through the same authority. """
[docs]defsave(self,_flow_id:str,answers:Mapping[str,str],/)->None:"""Persist the canonical answer map for ``flow_id``."""...
[docs]defload(self,_flow_id:str,/)->Mapping[str,str]|None:"""Return the persisted answer map, or ``None`` when absent."""...
[docs]defdiscard(self,_flow_id:str,/)->None:"""Erase the persisted in-progress run."""...
[docs]defcheckpoint_available(definition:FlowDefinition,mode:FlowMode)->bool:"""Whether the definition declares checkpointing for ``mode``."""returndefinition.checkpoint[mode]isCheckpointAvailability.AVAILABLE
[docs]defsave_checkpoint(definition:FlowDefinition,state:FlowState,store:CheckpointStore,)->None:"""Persist the state's committed answers through the domain store. Refuses in a mode whose declaration is the no-op arm — the frontend should never have offered the affordance; reaching this refusal means a frontend honesty bug, and the refusal (counts only, never answer values) makes it loud. """ifnotcheckpoint_available(definition,state.mode):raiseFlowCheckpointError(translated_message="application.flows.errors.checkpoint_unavailable_mode",context={"flow_id":definition.id,"mode":state.mode.value,"answered_count":len(state.answers),},)store.save(definition.id,dict(state.answers))
[docs]defdiscard_checkpoint(definition:FlowDefinition,store:CheckpointStore)->None:"""Erase the in-progress run through the domain store."""store.discard(definition.id)