cadrumo.application.wizard.commands module

Typer command factory for wizard flows.

build_wizard_command(flow) returns a Typer-compatible callable whose signature is composed at construction time from the flow’s questions plus three fixed mode flags (--profile, --quiet, --accept-defaults). The closure runs the flow and persists the typed answers.

Flag derivation per question kind:

  • TEXT / SECRET / PATH → --<question-id> str option (Path for PATH);

  • INTEGER → --<question-id> int option;

  • CONFIRM → --<question-id>/--no-<question-id> boolean pair;

  • SELECT → --<question-id> option with click.Choice([c.value for c in choices]);

  • CHECKBOX → repeated --<question-id> option that accumulates a list[str].

An interactive walk projects the one-shot wizard catalogue into a substrate FlowDefinition (via flow_definition_from_wizard_flow()) and drives it through an injected frontend runner: the full-screen Textual frontend where the host supports it, degrading to the line-mode frontend otherwise, and refusing instructively on a non-interactive host. The application default renders the line frontend (a same-layer application.flows primitive); the CLI entrypoint injects the capability-selecting runner that reaches the full-screen inbound adapter. The committed answers are then replayed through the same scripted projection the --quiet / --accept-defaults paths use, so the persisted typed model is produced identically regardless of frontend.

setup_flow_definition(flow, *, attach_descendants=True, operation)[source]

Bridge and decorate the wizard flow into the shared substrate definition.

The single projected FlowDefinition every frontend drives: the substrate bridge, format hints, setup legal validators, the flow-scope taxpayer-construction validator, and – for CREATE – the descendant repeating group, applied in one place so no caller can diverge on the definition it runs.

The taxpayer-construction validator is attached before the descendant group so it enrols the top-level pages only: repeating-group answers serialise through the descendant fact path, not the taxpayer projection.

attach_descendants gates the descendant group. It is spliced for CREATE (where the facts-as-checkpoint store seeds and re-seeds the group) and withheld for MODIFY. Modify-mode seeding cannot instantiate the repeating group: the modify frontend seeds render-time page defaults over a fresh start_flow() state, and instance pages are generated dynamically from the group’s count rather than being static items the default-seed mechanism can reach. Rendering the group unseeded would show an operator’s existing descendants as an empty group whose commit – via the namespace-replacing clearing guard – would then silently erase them. So MODIFY withholds the group and the command surfaces the descendant door instead of a silently-lossy surface.

Return type:

FlowDefinition

Parameters:
scripted_profile_facts(flow, kwargs, *, operation)[source]

Project a scripted create’s field flags into initial profile facts.

Creation is the credential door’s authority, not this flow’s: a profile exists only once a passphrase has wrapped its DEK. That leaves the field flags of a scripted config profile create with nowhere to land, because the flow’s own create arm is retired and its patch arm is bound to edit and to an already-authenticated session. This is the seam between the two. The projection is deliberately PURE – it writes nothing and opens no session, so the caller hands the result to the registration door and the facts are published inside the create transaction that already holds the record session, rather than through a second unlock afterwards.

A refused value refuses HERE, before the caller registers anything, so a foral CCAA token costs the operator no profile to correct afterwards.

The foral check is not redundant with the question validators. Dropping it does still refuse – the widget validator behind the CCAA question raises too – but it refuses as a generic wizard-validation failure instead of the domain refusal that names the Concierto Económico and the foral tax office the operator actually has to file with. The flow’s own command body calls it for the same reason. It runs first so the good message wins.

No filing-baseline check applies. A profile created this way is born INCOMPLETE on purpose, so demanding the full filing baseline would refuse the very state the create door exists to produce.

Parameters:
  • flow (WizardFlow) – The setup flow whose questions name the accepted flags.

  • kwargs (Mapping[str, object]) – The verb’s parsed keyword arguments, keyed by parameter name.

  • operation (PinnedAuthorityOperation) – Caller-owned pinned authority operation used for all operation-scoped catalogue checks.

Return type:

tuple[UserProfileFact, ...]

Returns:

The supplied flags as facts, empty when the caller named none.

DEFAULT_PROFILE_NEXT_COMMAND

a profile carrying no fiscal-residency classification that redirects it elsewhere. Public because a consumer projecting this same guidance onto another surface (the profile manager) needs to tell “the ordinary default applies” from “this profile earned a specific next step” without re-deriving the comparison.

Type:

The routing projection’s default suggestion

profile_next_step_modelo(profile_values, *, operation)[source]

The modelo id the routing projection singles out, or None for the default.

The one canonical classification a taxpayer’s declared facts route through — currently a single rule (IRNR non-residents route to Modelo 210, TRLIRNR RDLeg 5/2004 Art. 2) — None for every profile the projection does not single out. This is the PRIMARY authority; next_step_command_for_profile_values() derives its CLI command text from it rather than repeating the classification, so a consumer whose channel cannot carry command prose (the shared Notice structurally forbids an embedded executable aeat ... invocation outside its typed action projection) can still word its own sentence around the routed modelo.

Parameters:
  • profile_values (dict[str, str]) – Dotted-path fact values as the wizard’s canonical question-id keys, or the equivalent record_to_path_values() projection of a UserProfileRecord — the two share the same taxpayer_type.fiscal_residency key.

  • operation (PinnedAuthorityOperation) – Caller-owned pinned authority operation used to classify the fiscal-residency token.

Return type:

str | None

next_step_command_for_profile_values(profile_values, *, operation)[source]

Resolve the CLI command a profile’s declared facts point at next.

Derived from profile_next_step_modelo(), the canonical classification, falling back to DEFAULT_PROFILE_NEXT_COMMAND when it singles out no modelo. Consumed by the scripted wizard’s own success line, which renders the command as text.

Return type:

str

Parameters:
build_wizard_command(flow, *, mode, operation, invocation_notices=<class 'tuple'>)[source]

Return a Typer-compatible callable that runs flow.

The returned closure carries one parameter per question in the flow (typed and annotated for Typer to derive a CLI flag) plus the three mode flags.

mode binds the closure to a single wizard verb. "create" refuses a name that already has a manifest; "edit" refuses a name that has none. Both refusals fire before the wizard prompts, so an operator is never walked through 40-odd questions only to have the persistence step reject the work.

There is no interactive walk: an operator at a capable terminal is diverted to the profile manager before this command runs, so what is left here is the programmatic contract — flags in, JSON envelope out. An invocation that supplies neither --quiet/--accept-defaults nor the values it needs is refused with the flag form named.

Return type:

Callable[..., None]

Parameters: