Skip to content

feat(platform): give AuthState::LoginFailed a typed kind - #401

Open
filvecchiato wants to merge 7 commits into
mainfrom
feat/typed-login-failure
Open

feat(platform): give AuthState::LoginFailed a typed kind#401
filvecchiato wants to merge 7 commits into
mainfrom
feat/typed-login-failure

Conversation

@filvecchiato

Copy link
Copy Markdown
Collaborator

Closes #390.

  • LoginFailed { kind, reason } with LoginFailureKind::{NoFreeAllowanceSlots, Other}. Hosts branch on kind and use reason as display copy.
  • The wallet reports refusals as prose over EncryptedResponse::Failed(String), so the core recovers the discriminant once in runtime/login_failure.rs instead of leaving every host to regex it.
  • That text comes from this workspace's own SlotError Display impls, and the tests classify straight from them — rewording one now fails CI here rather than silently turning a host's fast-fail into a retry loop.

Typing the inter-host wire itself is a follow-up: it needs a coordinated wallet rollout, and kind means hosts won't need a second API change when it lands.

@filvecchiato
filvecchiato requested a review from a team August 14, 2026 13:41

@Imod7 Imod7 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rust/crates/truapi-host-cli/src/main.rs line 1170 already does this classification:

err.to_string().contains("no free StatementStore slot")

With the new classify_login_failure, the same fact lives in two crates under two different rules, and the CLI copy is the weaker one: case-sensitive, and no long-term-storage marker. It is load-bearing, prepare_pairing_response uses it to rotate an exhausted auto-managed account. Could you move the markers plus one predicate into rust/crates/truapi-server/src/runtime/statement_allowance/slot.rs, next to the SlotError Display strings they mirror, and call it from both places. I tried it: pub fn reports_exhausted_period(text: &str) -> bool there, classify_login_failure as a wrapper, and the CLI calling truapi_server::statement_allowance::slot::reports_exhausted_period(&err.to_string()). It compiles and the new tests stay green.

Comment thread rust/crates/truapi-server/src/runtime/login_failure.rs Outdated
Comment thread rust/crates/truapi-server/src/runtime/auth_state.rs
Comment thread rust/crates/truapi-platform/src/lib.rs
@filvecchiato
filvecchiato requested a review from Imod7 August 17, 2026 16:31
let reason = reason.to_ascii_lowercase();
// Every phrasing seen for an exhausted allowance period names both, and no
// other failure this workspace can render names both.
if reason.contains("no free") && reason.contains("slot") {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moderate. This rule matches "no free" and "slot" anywhere in the reason, so it is a guess, but LoginFailureKind::NoFreeAllowanceSlots is documented as "Deterministic until the period rolls over: retrying wastes the user's remaining budget". I ran three transient strings through the classifier and all came back NoFreeAllowanceSlots: "no free slot in the connection pool, try again", "no free memory for slot allocation", "no free worker slot available, retrying shortly". That doc is host-facing, it is copied verbatim into truapi_platform.swift:1562-1564, so it is what an iOS host author reads when deciding whether to offer a retry. I would not narrow this rule, that reintroduces the bug this commit fixed. Could you soften the doc on the variant instead: say the kind is recovered heuristically from wallet prose and is a strong hint rather than a proof, and phrase the guidance as "do not make retry the primary action".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AuthState::LoginFailed carries only free text, so hosts must regex-match prose to classify a failure

3 participants