Phase log 1: Phases 1–3 (pre-2026-06-05)
Salvaged from the Session History of
CLAUDE.original.md, a rolling log that held every session before Phase 12 in one file. That file was split up and deleted on 2026-08-25; its pitfalls and decisions live inCLAUDE.md. This entry is its text verbatim - written as a log, not to the handoff template, so it has no Goal/Next Steps sections.
Goal: Build core Tauri desktop app: encrypted local vault, TypeScript/Vite frontend, inline handler elimination, Projects groundwork.
Phase 1 - What Was Built
VaultStoreabstraction (LocalVaultStore↔TauriVaultStore) - zero UI changes to swap implementations- Schema-driven form tooltips via
schema.json - Simple Icons CDN with letter-avatar fallback
- CSS themes via
data-themeon<html>(6 themes) repeat(auto-fill, minmax(...))set in JS - CSSrepeat(var(...))is invalidcloseIconPickeronClosecallback pattern- Tauri CSP as single string - array form rejected by Tauri 2 schema
- Removed
devUrlfromtauri.conf.json- Tauri 2 needs HTTP URI or absent
Phase 2 - What Was Built
mod commands {}- all#[tauri::command]fns in submodule to avoid E0255 proc-macro collisionexecCommandclipboard fallback for WebKitGTK silently-failingnavigator.clipboarddata-actiondelegation - replaced allonclick="..."ininnerHTML-webkit-appearance: noneon<select>for WebKit CSS coloursNO_STRIP=1env var - workaround for linuxdeploy strip on Fedora 43productNamewithout spaces - prevents unquoted path in linuxdeployAPPIMAGE_EXTRACT_AND_RUN=1must be in~/.bashrc, not just PowerShellGDK_BACKEND=x11inrun()viastd::env::set_var- Argon2id Phase 1 migration:
unlock_vaultimports legacyvault.json→ SQLCipher → deletes plaintext
Phase 3 - What Was Built
- Source moved
public/→src/for Vite;vault.js→vault.ts,icons.js→icons.ts, newtypes.ts "type": "module"inpackage.json- fixes Vite CJS deprecation warningdist/is now TaurifrontendDist- Card grid, icon picker, export/copy dropdowns, load banner all converted to
data-actiondelegation - Global
<img>error listener (capture phase) replaces allonerrorfallbacks iconPickerrefactored to mutable object (ESM import reassignment breaks at runtime)- WebKitGTK
<input type="file">ghost: removed static inputs from HTML;openFilePicker()creates input dynamically, appends, clicks, removes onchange/cancel/window.focuswithdoneflag <select multiple size>ghost: replaced with custom div-based picker (project-pick-item)position:fixedghost:top:-9999px; left:-9999px; display:noneCSS default; JScssTextsets coords on open- Header/unlock overlay collision: hide
#headerwhen overlay opens -backdrop-filtercreates separate compositing layer - Sidebar styling unified - both Projects and Categories emit
button.sidebar-item + span.sidebar-label + span.sidebar-count - Rename/delete for projects and categories; category tree toggle deselect on re-click
- Categories ↔ Projects section swap (Categories section =
vault.user_categories; Projects section =vault.projects) - Sort dropdown: native
<select>→<button>+showDropdown()callback map - VSCode activity bar (48px icon-only
#activity-bar);switchPanel()always called ininit() - Tools panel with 10 panes wired via
initTools() version_historyper VaultEntry - auto-populated in Rust onapi_keychange, capped 50vault_audittable - append-only, written on add/update/deletecert_key_data?: string | null- PEM private key for certificate entriesenv_var_subtype- display hint for env_var entriesgenerate_certificate+generate_ssh_keypairRust commands inmod commands {}- WireGuard + Docker project types with chunk system, chunk edit modal, project creation modal
- SI_REGISTRY expanded from ~120 to ~300 entries
Phase 3 Issues (all resolved)
| # | Issue | Fix |
|---|---|---|
| 1 | <input type="file"> ghost widget (WebKitGTK) | Dynamic DOM insert/remove |
| 2 | <select multiple size> ghost listbox (WebKitGTK) | Custom div picker |
| 3 | .dropdown/.custom-select-list top-left ghost | top:-9999px; left:-9999px CSS default |
| 4 | Header collides with unlock overlay | Hide #header when overlay opens |
| 5 | Categories/Projects section label swap | HTML text fixes (IDs unchanged) |
| 6 | new-category-form dropped by HTML linter | Re-added; always verify IDs after formatting |
| 7 | Category tree no deselect on re-click | Toggle: ids[0] === id ? ['Universal'] : [id] |
| 8 | Projects/Categories styling mismatch | Unified button.sidebar-item pattern |
| 9 | Sidebar startup overlap (tools panel ghost) | Always call switchPanel(activePanel) in init() |
| 10 | Sort dropdown native/white | Custom showDropdown() callback map |
| 11 | initTools() not idempotent | _toolsInited guard |