cadrumo.application.flows.definition module

Descriptor models for the paged interactive-flow substrate.

The strict frozen pydantic v2 records below compose a closed, declarative description of a paged operator-facing flow: a FlowDefinition is a tuple of FlowSection records; a section holds FlowPage and FlowRepeatingGroup items; each page declares exactly one FlowWidgetKind, its copy references, its validators by registered id, and the optional declarative FlowCondition gate over earlier answers.

Copy slots are CopyRef references, never literal prose: the render-time copy assembler resolves each reference against the bundled locale catalogues, the profile/modelo schema definitions, or the terminology concepts. The definition is the single source of truth read by the flow engine, every frontend, and the domain-key projections; it deliberately carries the one-shot wizard descriptor’s vocabulary forward (page ids, canonical-token answers, choice records, equals/contains gates) so existing catalogues migrate by extension.

class CopyRef(**data)[source]

Bases: BaseModel

One reference into the bundled copy sources, resolved at render time.

ref is a locale key (wizard.setup.profile.tax-id.prompt), a schema field path (identity.tax_id), or a terminology concept id (tema-profile) depending on kind. The reference is resolved by the copy assembler; an unresolvable reference is a loud render failure, never a silent blank.

Parameters:

data (Any)

kind: CopyRefKind
ref: str
class FlowLegalRef(**data)[source]

Bases: BaseModel

One structured legal citation shown on a page’s provenance zone.

ref is the registry legal-ref token (ley-35-2006:art-27); the optional label is a copy reference resolving to display text for the citation. The consuming domain stamps these at definition-build time — the substrate never derives a page’s legal zone, it only resolves and renders what the definition carries.

Parameters:

data (Any)

ref: str
label: CopyRef | None
class FlowCondition(**data)[source]

Bases: BaseModel

Single-clause predicate naming one earlier page’s answer.

Exactly one of equals / contains is set. equals tests the canonical token exactly; contains splits the parent’s comma-joined CHECKBOX answer into a token set and tests membership.

Parameters:

data (Any)

page_id: str
equals: str | None
contains: str | None
class FlowVisibility(**data)[source]

Bases: BaseModel

Disjunction of FlowCondition clauses; visible when any holds.

Parameters:

data (Any)

any_of: tuple[FlowCondition, ...]
class FlowChoice(**data)[source]

Bases: BaseModel

One entry in a SELECT / CHECKBOX / COMPARE_SELECT closed choice set.

For COMPARE_SELECT the choice is a labelled candidate value and provenance names where the candidate came from; the reserved defer arm is engine-provided and never declared as a choice.

Parameters:

data (Any)

value: str
label: CopyRef
description: CopyRef | None
provenance: CopyRef | None
class FlowPage(**data)[source]

Bases: BaseModel

One full-page question in a flow.

domain_key generalises the wizard’s profile_key: the dot-path the answer binds to in the consuming domain’s schema, or None for a UI-only page. answer_validator_ids name registered pure validators run at commit time on top of the widget-level validation; failure_modes are rendered on the page so the operator sees how the input can go wrong before typing.

Parameters:

data (Any)

id: str
widget: FlowWidgetKind
prompt: CopyRef
help: CopyRef | None
format_hint: CopyRef | None
failure_modes: tuple[CopyRef, ...]
legal_zone: tuple[FlowLegalRef, ...]
choices: tuple[FlowChoice, ...]
default: str | None
required: bool
visible_when: FlowCondition | FlowVisibility | None
answer_type: type[str] | type[bool] | type[int] | type[Path]
domain_key: str | None
answer_validator_ids: tuple[str, ...]
class FlowRepeatingGroup(**data)[source]

Bases: BaseModel

A sub-page group instantiated N times (descendientes, actividades, …).

count_from names an earlier INTEGER page whose answer drives the instance count; the review surface may also add and remove instances. Instance answers key the canonical map as <group-id>#<index>.<page-id> and participate individually in validation, staleness, and review.

Parameters:

data (Any)

id: str
title: CopyRef
count_from: str
pages: tuple[FlowPage, ...]
max_instances: int
class FlowSection(**data)[source]

Bases: BaseModel

One grouped sequence of pages inside a flow.

exit_validator_ids name registered cross-field validators run when the operator leaves the section; a failing verdict blocks forward navigation with a typed, rendered result.

Parameters:

data (Any)

id: str
title: CopyRef
items: tuple[FlowItem, ...]
exit_validator_ids: tuple[str, ...]
class FlowDefinition(**data)[source]

Bases: BaseModel

The top-level descriptor for one paged flow surface.

intro is an optional opening-copy slot the line-mode frontend renders before the first page; None is a definition-level decision that the flow opens with no preamble, never a silent humanised key. checkpoint is the per-mode declaration: UNAVAILABLE is the declared no-op arm the frontend must surface honestly. flow_validator_ids name registered flow-scope cross-field validators run at the review surface; submission requires every one to pass alongside the per-page and staleness gates.

Parameters:

data (Any)

id: str
title: CopyRef
description: CopyRef
intro: CopyRef | None
sections: tuple[FlowSection, ...]
answers_model: type[BaseModel]
checkpoint: dict[FlowMode, CheckpointAvailability]
flow_validator_ids: tuple[str, ...]
property fingerprint: str

Stable content identity of the declarative definition.

A convenience identity for callers that want to label or compare definitions (diagnostics, caching). Resume deliberately does NOT consume it: definition change is detected by re-validating every persisted answer against the current definition, so no fingerprint is ever stored. Hashes the declarative content only; the answers_model type is identified by its qualified name so two builds of the same definition fingerprint identically.

iter_flow_conditions(visible_when)[source]

Normalise the three visible_when shapes into a flat clause tuple.

Return type:

tuple[FlowCondition, ...]

Parameters:

visible_when (FlowCondition | FlowVisibility | None)

iter_flow_pages(definition)[source]

Return every page in a definition, flattening repeating groups in order.

Lives with the types it walks. Two wizard modules each carried this loop, which meant two places had to agree that a repeating group contributes its pages rather than itself.

Return type:

tuple[FlowPage, ...]

Parameters:

definition (FlowDefinition)

locale_copy_ref(key)[source]

Return the copy reference for a locale key.

Lives with CopyRef because four modules each built this same two-field construction, which meant four places encoded that a locale key is carried by the LOCALE_KEY kind.

Return type:

CopyRef

Parameters:

key (str)