cadrumo.application.flows.validators module¶
Validator contracts and registries for the flow substrate.
Three validator scopes exist, mirroring the three-tier validation the
substrate renders: per-answer validators run at commit time on one
page’s raw token; section-exit validators run when the operator leaves a
section; flow-scope validators run at the review surface. All three are
pure functions returning ValidationVerdict records carrying
i18n message keys (never prose) and redacted context — raw operator
answers never enter diagnostics.
Domain flows register their validators by id at import time and name
those ids on the FlowDefinition; the registries reject
duplicate ids so a validator has exactly one owner. Widget-level shape
validation (blank/choice/integer/date/decimal/path canonicalisation) is
built in and runs before any registered per-answer validator.
- class ValidationVerdict(**data)[source]¶
Bases:
BaseModelOne typed validation outcome, renderable on the page or review surface.
message_keyis a translation key;contextcarries only redacted, non-sensitive interpolation values (counts, choice sets, field labels — never the raw answer).- Parameters:
data (Any)
- ok: bool¶
- message_key: str | None¶
- context: dict[str, object]¶
- register_answer_validator(validator_id, validator)[source]¶
Register a per-answer validator under a unique id.
- register_cross_field_validator(validator_id, validator)[source]¶
Register a section-exit or flow-scope validator under a unique id.
- resolve_answer_validator(validator_id)[source]¶
Return the registered per-answer validator or refuse loudly.
- Return type:
TypeAliasType- Parameters:
validator_id (str)
- resolve_cross_field_validator(validator_id)[source]¶
Return the registered cross-field validator or refuse loudly.
- Return type:
TypeAliasType- Parameters:
validator_id (str)
- validate_widget_shape(page, raw)[source]¶
Validate and canonicalise
rawagainst the page’s widget shape.Returns
(canonical_token, verdict). The canonical token is meaningful only when the verdict passes. Blank-answer policy is keyed on the static descriptor exactly as the one-shot wizard’s validators were: a blank fails only for an unconditionally required page (requiredand novisible_when); a gated or optional page accepts blank as the undeclared state.A
DATEpage carries its canonical answer as the ISO-8601 string (YYYY-MM-DD) and aDECIMALpage as thestr(Decimal)form: both keepanswer_type = stron the page rather than widening theFlowPageanswer-type union todate/Decimal. The shape validation here is the sole guarantee the stored token parses, so the consuming domain re-parses the canonical string with the same core parser it validated against.- Return type:
- Parameters: