+++ title = "Implement auth code session storage — utility module and AuthModal pre-fill integration" priority = 7 status = "todo" ticket_type = "task" dependencies = [] +++ Resolved from TRIAGE ticket 0bc655. The auth code (4-word passphrase) that authorises edit and delete operations must be available to the UI without forcing the user to re-enter it on every interaction within a browsing session. Chosen strategy: **session storage per quote ID**. The code is stored in the browser's `sessionStorage` under the key `auth_code_{id}` when first entered. It is automatically cleared when the tab closes. No explicit clear-on-delete is required (session storage is short-lived by design), but it is good practice and should be included. Options considered: - localStorage: ruled out — indefinite persistence is unnecessary; the app tells users to store the code externally anyway, and localStorage has a wider XSS exposure window. - Component state only: ruled out — code is lost on any page navigation or reload, making the edit/delete flow unusable in practice. **Part 1 — Storage utility (`src/bin/ui/storage.rs`)** Create a module with three public functions that wrap the browser's `sessionStorage` API: ```rust use web_sys::window; /// Retrieve the stored auth code for a given quote ID, if any. pub fn get_auth_code(quote_id: &str) -> Option { let storage = window()?.session_storage().ok()??; storage.get_item(&format!("auth_code_{quote_id}")).ok()? } /// Persist the auth code for a quote ID in sessionStorage. pub fn set_auth_code(quote_id: &str, code: &str) { if let Some(Ok(storage)) = window().map(|w| w.session_storage()) { if let Some(storage) = storage { let _ = storage.set_item(&format!("auth_code_{quote_id}"), code); } } } /// Remove the auth code for a quote ID from sessionStorage (call after DELETE). pub fn clear_auth_code(quote_id: &str) { if let Some(Ok(storage)) = window().map(|w| w.session_storage()) { if let Some(storage) = storage { let _ = storage.remove_item(&format!("auth_code_{quote_id}")); } } } ``` Expose this module from the UI binary root: add `mod storage;` to `src/bin/ui/main.rs`. **Part 2 — AuthModal pre-fill** Update the `AuthModal` component (ticket f850c6) to accept an `initial_value: Option` prop. Pre-populate the `` value from this prop when the modal opens. The parent component is responsible for reading from storage and passing the value in. ```rust #[derive(Properties, PartialEq)] pub struct AuthModalProps { pub on_submit: Callback, pub on_cancel: Callback<()>, pub initial_value: Option, // pre-fill if auth code is already stored } ``` **Part 3 — SingleQuotePage integration** In the SingleQuotePage (or whichever component renders edit/delete for a quote), integrate storage around the `AuthModal`: - Before opening the modal: read `storage::get_auth_code("e.id)` and pass it as `initial_value` to `AuthModal`. - After a successful **edit** (POST /api/quotes/:id returns 200): call `storage::set_auth_code("e.id, &submitted_code)`. - After a successful **delete** (DELETE /api/quotes/:id returns 204): call `storage::clear_auth_code("e.id)`. - If the API returns 403 (wrong code): do NOT store the code; clear any existing stored value with `storage::clear_auth_code("e.id)` so a stale code is not re-offered. - The storage utility must compile only for `wasm32-unknown-unknown` — `web_sys::window()` is not available on the host target. Gate the module under `#[cfg(target_arch = "wasm32")]` or ensure it is only imported by the `ui` binary, which is always compiled for wasm32. - `web_sys` must be available with the `Window`, `Storage` features — confirm these are included in the `web_sys` dependency in `Cargo.toml` (ticket 93515e covers UI Cargo.toml setup). - Do NOT use `gloo-storage` — it wraps localStorage by default and the API difference matters. Use `web_sys` directly as shown above. - The key pattern is `auth_code_{quote_id}` (underscore separator, not slash or dot). - Session storage is tab-scoped: no cross-tab contamination is possible — no additional scoping by domain or user is needed. ```sh trunk build ``` `feat(quotesdb): implement auth code session storage utility and AuthModal pre-fill` quotesdb/ui