fix: remaining HIGH audit findings - dead 2FA cleanup + <html lang> (LC-353, LC-354) #368

Merged
longjacksonle merged 2 commits from fix/lc-353-354-audit-high-cleanup into main 2026-06-19 05:19:26 +02:00

The two remaining HIGH findings from the UI audit. just test and just test-saas both green.

LC-353 - remove dead 2FA UI cruft

The 2FA UI has been unreachable since the LC-22 pure-RP Bunyip cutover retired local auth. The templates posted to /login/2fa, /login/recovery, /register/2fa, /settings/2fa/setup (none registered), and the view structs + AppState::two_factor_available were used by zero handlers.

Deleted: templates/two_factor/ (5 files), views/two_factor.rs (+ its mod line), locales/{en,es}/two-factor.ftl (35 keys each), and the dead two_factor_available helper. The i18n_catalog coverage gate stays green: en/es are removed in lockstep and no live template referenced the keys. CLAUDE.md already documents auth as SSO-only, so no doc change.

LC-354 - <html lang> follows the request locale

base.html hardcoded <html lang="en"> despite a shipped, reachable es locale, so Spanish users got es content under lang="en" (WCAG 3.1.1 failure on every page). Added i18n::current_lang_code (reads the CURRENT_LOCALE task-local, falls back outside a request) + a lang Askama filter, and render <html lang="{{ ""|lang }}">. Unit test covers the scoped-locale and fallback paths.

Closes LC-353, LC-354.

The two remaining HIGH findings from the UI audit. `just test` and `just test-saas` both green. ## LC-353 - remove dead 2FA UI cruft The 2FA UI has been unreachable since the LC-22 pure-RP Bunyip cutover retired local auth. The templates posted to `/login/2fa`, `/login/recovery`, `/register/2fa`, `/settings/2fa/setup` (none registered), and the view structs + `AppState::two_factor_available` were used by zero handlers. Deleted: `templates/two_factor/` (5 files), `views/two_factor.rs` (+ its mod line), `locales/{en,es}/two-factor.ftl` (35 keys each), and the dead `two_factor_available` helper. The `i18n_catalog` coverage gate stays green: en/es are removed in lockstep and no live template referenced the keys. CLAUDE.md already documents auth as SSO-only, so no doc change. ## LC-354 - <html lang> follows the request locale `base.html` hardcoded `<html lang="en">` despite a shipped, reachable `es` locale, so Spanish users got es content under `lang="en"` (WCAG 3.1.1 failure on every page). Added `i18n::current_lang_code` (reads the `CURRENT_LOCALE` task-local, falls back outside a request) + a `lang` Askama filter, and render `<html lang="{{ ""|lang }}">`. Unit test covers the scoped-locale and fallback paths. Closes LC-353, LC-354.
The 2FA UI has been unreachable since the pure-RP Bunyip cutover retired local auth: templates/two_factor/* posted to /login/2fa, /login/recovery, /register/2fa, /settings/2fa/setup, none of which are registered, and views/two_factor.rs's structs plus AppState::two_factor_available were instantiated/called by zero handlers.

Delete templates/two_factor/ (5 files), views/two_factor.rs (+ its mod line), the now-unreferenced server/locales/{en,es}/two-factor.ftl catalogs (35 keys each; the i18n_catalog coverage gate stays green since en/es are removed in lockstep and no live template references them), and the dead two_factor_available helper. CLAUDE.md already describes auth as SSO-only post-LC-22, so no doc change is needed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(i18n): drive <html lang> from the resolved request locale (LC-354)
All checks were successful
check-secrets / Nosey parker (pull_request) Successful in 3s
check-secrets / TruffleHog (push) Successful in 4s
check-secrets / Kingfisher (push) Successful in 5s
check-secrets / TruffleHog (pull_request) Successful in 9s
check-secrets / Nosey parker (push) Successful in 9s
check-secrets / Kingfisher (pull_request) Successful in 11s
Create release / Create release from merged PR (pull_request) Has been skipped
Check / clippy + fmt + tests (pull_request) Successful in 5m17s
8786932a51
base.html hardcoded `<html lang="en">` even though a Spanish locale ships and is reachable via POST /settings/language, so es users got es content under lang="en" - a WCAG 3.1.1 failure on every page (screen readers mispronounce, translation tools mis-detect). Add i18n::current_lang_code (reads the CURRENT_LOCALE task-local, falls back to the default outside a request) and a `lang` Askama filter, and render `<html lang="{{ ""|lang }}">`. Unit test covers the scoped-locale and fallback paths.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
longjacksonle deleted branch fix/lc-353-354-audit-high-cleanup 2026-06-19 05:19:26 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!368
No description provided.