cadrumo.entrypoints.tui.secret.registration module¶
Registration: full-screen credential entry that creates and unlocks one profile.
This is the literal first surface of the application. Everything else — the manager, the overview, filing — is behind it, because everything else needs an unlocked encrypted bucket and this is where that bucket is created.
The screen is deliberately a single page rather than a paged flow. The three fields are one decision (“who am I on this machine, and what protects it”), and a password field needs its confirmation and its strength feedback visible at the same time as itself; splitting them across pages would make the operator hold state in their head for no gain. The paged substrate remains the right shape for the many-question profile detail that follows, and is used there.
The copy carries what an offline CLI tool owes the operator at this moment: what is being created, why a password is being asked for at all when nothing is going over a network, and what happens if it is lost.
Recovery is an explicit, skippable follow-up. Once the profile exists the screen asks whether to set up a recovery code, says plainly what it buys (a way to reset a forgotten passphrase) and what declining means, and defaults to declining. Choosing it shows the code once and asks for it back before anything is installed; cancelling at any point leaves the freshly created profile exactly as it was, with its passphrase as its only door.
See also
register_profile_with_credentials()The application door this screen drives; it creates the profile, provisions the key material, and leaves the session unlocked.
enroll_profile_recovery()The optional second door, driven from the offer that follows creation.
assess_profile_password()The canonical assessment behind validation and the live strength line.
LoginScreenThe other credential surface; the two share their attempt lifecycle and panel layout through
CredentialScreen.
- class RegistrationRefusal(message_key, context=())[source]¶
Bases:
objectSecret-free localized refusal retained as data until rendering.
- exception RecoveryHandoverDeclinedError(message=None, *, context=None, translated_message=None)[source]¶
Bases:
CadrumoErrorThe operator did not confirm the code; raised inside the handover to abort enrolment.
The application treats any exception from the handover as “nothing was installed”, which is exactly the outcome a decline wants. The enrolment door in this module catches it and reports a decline, not a refusal.
- Parameters:
- Return type:
None
- code¶
- class RegistrationAttempt(outcome=None, expected_refusal=None)[source]¶
Bases:
objectThe outcome of asking the application to create a profile.
A refusal arrives as text the screen displays, not as an exception it has to recognise. That keeps refusal classification with the layer that owns the rules, and leaves the screen doing what a screen does: show the operator what happened.
- Parameters:
outcome (ProfileRegistrationOutcome | None)
expected_refusal (RegistrationRefusal | None)
-
outcome:
ProfileRegistrationOutcome|None¶
-
expected_refusal:
RegistrationRefusal|None¶
- class RecoveryEnrollmentAttempt(enrolled=False, declined=False, expected_refusal=None)[source]¶
Bases:
objectThe outcome of asking the application to enrol recovery after creation.
enrolledis true only when the wrapper was installed after the operator confirmed the code.declinedrecords a deliberate cancel, which is not a refusal and shows nothing. Anything else is an expected refusal carried as localized data.- Parameters:
enrolled (bool)
declined (bool)
expected_refusal (RegistrationRefusal | None)
-
expected_refusal:
RegistrationRefusal|None¶
- class RegistrationScreen(*, assess, register, enroll_recovery=None, suggested_name=None)[source]¶
Bases:
CredentialScreen[ProfileRegistrationOutcome]Full-screen credential entry that creates and unlocks one profile.
- Parameters:
assess (Callable[[str], ProfilePasswordAssessment])
register (Callable[[str, str, str], RegistrationAttempt])
enroll_recovery (Callable[[str, str, Callable[[ProfileRecoveryEnrollment], str]], RecoveryEnrollmentAttempt] | None)
suggested_name (str | None)
- SCOPED_CSS: ClassVar[bool]¶
Should default css be limited to the widget type?
- DEFAULT_CSS: ClassVar[str]¶
Default TCSS.
- ATTEMPT_NAME: ClassVar[str]¶
- on_select_changed(event)[source]¶
Re-word the whole page in the language the operator just picked.
The choice has to reach the screen and not only the profile it will create: this is the first surface of the application, so an operator who cannot read the language it opened in has nothing else to go to. Applying it here is also what makes the chooser legible as a chooser — the page answering in the chosen language is the confirmation that the setting took.
- selected_output_language()[source]¶
Return the closed language selection for the profile being created.
- Return type:
- resolve_attempt_refusal(attempt)[source]¶
Render structured registration refusals under this screen’s locale.
- Return type:
- Parameters:
attempt (CredentialAttempt[ProfileRegistrationOutcome])
- action_create()[source]¶
Validate the form locally, then create the profile.
Local checks cover only what the screen can see — a blank name, a mismatched confirmation, an invalid password. Everything else (a duplicate label, a storage refusal) is the application door’s decision, surfaced here as its translated message rather than re-derived, so the screen never becomes a second authority on what a valid registration is.
- Return type:
- progress_message()[source]¶
Operator-facing description of the subclass’s in-flight attempt.
- Return type:
- refuse(message)[source]¶
Show refusal and return the keyboard to the form.
A refusal the application door raises – a duplicate label, a storage refusal – arrives while the fields are disabled, so re-enabling them leaves nothing focused and the operator cannot type without reaching for the mouse. The local checks focus the field they name immediately after calling this, so the name field is only the landing place for a refusal that named none.
- leave(outcome)[source]¶
Offer recovery once the profile exists; leave immediately otherwise.
The base lifecycle calls this with the successful outcome. Instead of closing straight away, the screen holds the outcome and puts the one optional question to the operator. Declining, cancelling, and finishing enrolment all end here again through
_finish_registration(), which is the only path that closes.- Return type:
- Parameters:
outcome (ProfileRegistrationOutcome | None)
- on_worker_state_changed(event)[source]¶
Settle the enrolment worker here; everything else is the base attempt.
- Return type:
- Parameters:
event (StateChanged)
- on_unmount()[source]¶
Release every pending handoff and wipe the passphrase when the application stops.
- Return type:
- can_focus: bool¶
Widget may receive focus.
- can_focus_children: bool¶
Widget’s children may receive focus.
- class RecoveryOfferScreen(*, locale, on_accept, on_skip)[source]¶
-
Ask once whether to set up recovery, with the trade-off stated plainly.
- Parameters:
locale (str)
on_accept (Callable[[], None])
on_skip (Callable[[], None])
- BINDINGS: ClassVar¶
A list of key bindings.
- DEFAULT_CSS: ClassVar[str]¶
Default TCSS.
- compose()[source]¶
Called by Textual to create child widgets.
This method is called when a widget is mounted or by setting recompose=True when calling [refresh()][textual.widget.Widget.refresh].
Note that you don’t typically need to explicitly call this method.
Example
def compose(self) -> ComposeResult: yield Header() yield Label("Press the button below:") yield Button() yield Footer()
- action_skip_recovery()[source]¶
Escape declines the offer, which is what leaving it already means.
- Return type:
- action_toggle_appearance()[source]¶
Switch appearance here as on every other credential surface.
- Return type:
- can_focus: bool¶
Widget may receive focus.
- can_focus_children: bool¶
Widget’s children may receive focus.
- class RecoveryCodeScreen(*, enrollment, locale, on_confirm, on_cancel)[source]¶
-
Show the recovery code once and return masked exact re-entry proof.
- Parameters:
enrollment (ProfileRecoveryEnrollment)
locale (str)
on_confirm (Callable[[str], None])
on_cancel (Callable[[], None])
- BINDINGS: ClassVar¶
A list of key bindings.
- DEFAULT_CSS: ClassVar[str]¶
Default TCSS.
- compose()[source]¶
Called by Textual to create child widgets.
This method is called when a widget is mounted or by setting recompose=True when calling [refresh()][textual.widget.Widget.refresh].
Note that you don’t typically need to explicitly call this method.
Example
def compose(self) -> ComposeResult: yield Header() yield Label("Press the button below:") yield Button() yield Footer()
- action_cancel_code()[source]¶
Escape declines enrolment, so nothing is installed for this code.
- Return type:
- action_toggle_appearance()[source]¶
Switch appearance here as on every other credential surface.
- Return type:
- can_focus: bool¶
Widget may receive focus.
- can_focus_children: bool¶
Widget’s children may receive focus.
- build_profile_registration_attempt(label, candidate_passphrase, output_language)[source]¶
Adapt the public registration door into this screen’s result contract.
This is the production
registerdoor. It classifies nothing itself: the application owns which refusals are expected, and this only carries the localized message key and its context forward as data. No passphrase is retained beyond the call.- Return type:
- Parameters:
- build_profile_recovery_enrollment_attempt(profile_id, current_passphrase, recovery_handover)[source]¶
Adapt the public enrolment door into this screen’s result contract.
A declined handover is not a refusal: the operator chose to keep the profile passphrase-only, and the application installed nothing.
- Return type:
- Parameters:
profile_id (str)
current_passphrase (str)
recovery_handover (Callable[[ProfileRecoveryEnrollment], str])