cadrumo.application.wizard.descendant_door module

The paged descendant door onto the setup flow’s repeating group.

A dedicated, descendant-only FlowDefinition that hosts the exact count page and FlowRepeatingGroup the full setup flow uses (build_descendant_group() and the entry-event cross-field validator id) — the pages and validators are adopted, not re-authored, so the door and the setup flow can never diverge on the descendant surface.

The door exists because modify-mode seeding cannot instantiate the repeating group inside the main setup flow: instance pages are generated dynamically from the count answer, so the render-time default-seed mechanism cannot reach them and the group is withheld from a bridged modify definition. This door closes that gap by seeding through resume_flow(), whose walk commits the count answer first (revealing the instance pages) and then seeds each instance answer — the one seeding channel that re-instantiates the group from persisted facts.

Lifecycle of one door invocation:

The door declares checkpointing UNAVAILABLE in both modes: the commit is owned here, not by a frontend save-and-exit, so no checkpoint store is wired.

DESCENDANT_DOOR_FLOW_ID

The door’s flow and familia section ids.

class DescendantDoorAnswers(**data)[source]

Bases: BaseModel

The door’s declared answers_model: the group carries every answer.

The descendant surface is entirely a repeating group whose instance answers key the canonical map as descendientes#<index>.<page-id> — none is a top-level model field — so the door’s typed answer model is empty. The commit path reads the engine’s committed page-keyed answer map directly (through descendant_facts_from_answers()), never a projection through this model; it exists only to satisfy the FlowDefinition contract.

Parameters:

data (Any)

build_descendant_door_definition(*, operation)[source]

Return the descendant-only door FlowDefinition.

Adopts the operation-scoped count page and build_descendant_group() verbatim into a single familia section, and names the entry-event cross-field validator on the definition so a bad entry date — or one the declared relación cannot carry — blocks submit — the same validators the setup flow runs. The count page’s visible_when gate on the entity-type page is stripped: the door has no entity-type page (an operator who opened the descendant surface is declaring descendants), and a gate naming a page absent from the definition would fail the definition’s earlier-page-reference validator at construction.

Return type:

FlowDefinition

Parameters:

operation (PinnedAuthorityOperation)

build_descendant_door(record, *, operation)[source]

Return the door definition and a MODIFY-mode state seeded from record.

Re-projects the record’s renta_family.descendiente.{n}.* facts into the page-keyed answer map through descendant_answers_from_record(), then resumes a fresh FlowState over the door definition: resume_flow() commits the seeded count answer first (revealing the instance pages) and then seeds each instance answer against the current definition, so the operator opens on their existing descendants. A childless record seeds an empty map and opens on the count page’s zero default.

Parameters:
Return type:

tuple[FlowDefinition, FlowState]

load_active_descendant_record(*, operation)[source]

Load the authoritative record that one descendant-door run will edit.

Return type:

UserProfileRecord

Parameters:

operation (PinnedAuthorityOperation)

persist_descendant_door_answers(answers, *, baseline, operation)[source]

Commit the door’s submitted answers as the full descendant fact set.

Projects the committed page-keyed answers into the canonical renta_family.descendiente.{n}.* facts and aggregates through descendant_facts_from_answers(), and clears every on-record descendant path the fresh projection no longer covers (a shrunk count, a removed optional field) through descendant_clearing_facts(), in one authenticated compare-and-swap command. The clearing reads the authoritative current record before constructing the replacement, so a count-shrink never strands a descendant index above the answered count.

Core types: UserProfileRecord.

Return type:

UserProfileRecord

Parameters:
run_descendant_door(*, operation, input=None, output=None)[source]

Drive and persist one descendant door invocation through the real line frontend.

The door resolves and loads the authenticated active profile itself before prompting, binding the submitted write to that exact revision and digest. Headless callers bind prompt-toolkit devices, which exercises the same production frontend and the same atomic profile writer without replacing either boundary with a test callback.

Return type:

tuple[FlowState, ReviewProjection, UserProfileRecord]

Parameters: