124 lines
11 KiB
Markdown
124 lines
11 KiB
Markdown
# Desktop parity, platform, and security audit
|
|
|
|
The Iced application is a presentation adapter over `crates/storage`. The
|
|
tables below are the milestone 01/02 coverage record. `action.rs` is the single
|
|
desktop action and enablement registry used by menus, shortcuts, direct
|
|
controls, context controls, Help, and the command palette. A desktop unit test
|
|
requires every registered action ID to remain present in this document.
|
|
|
|
## Coverage matrix
|
|
|
|
| Area and compatible operation | Registered desktop action and menu | Direct control, dialog, or view | Command palette |
|
|
| --- | --- | --- | --- |
|
|
| Configuration and lock: open configured store | `open-folder` (File) | Compact toolbar control and native folder picker; storage validates and persists configuration | Yes |
|
|
| Configuration and lock: edit shared settings | `settings` (IronStorage) | Compact shared utility shell with grouped vault, default-key, timeout, command-link, and configuration-detail panels | Yes |
|
|
| Configuration and lock: refresh typed tree | `refresh` (View) | Sidebar Refresh control | Yes |
|
|
| Configuration and lock: lock/unlock | `lock` (Tools) | Toolbar Lock control; opening protected content starts storage authentication | Lock only; unlock is the protected action being resumed |
|
|
| Base pass: `init` root or nested recipient policy | `initialize-store`, `new-folder` (File) | Recipient/default-key form and explicit replacement confirmation | Yes |
|
|
| Base pass: default/list/`ls`/`list` | `refresh` (View) | Expandable storage-provided tree with object icons and descendant entry counts | Yes for refresh; browsing is direct navigation |
|
|
| Base pass: `show` and reload | `open-entry`, `reload-entry` (Entry) | Tree activation, typed identity header, structured viewer, Reload control | Yes |
|
|
| Base pass: `insert`/`add` | `new-entry` (File) | New Entry form creates a lossless draft, then the structured editor saves it | Yes |
|
|
| Base pass: `edit` and save | `edit-entry`, `save` (Entry/File) | Compact Edit and Save controls; shared Save/Discard/Cancel guard | Yes |
|
|
| Base pass: `generate` and replace | `generate-password` (Entry) | Field Generate control and explicit replacement confirmation | Yes |
|
|
| Base pass: authenticated values and clipboard | `copy-field`, `copy-edited-field` (Entry) | Every field is visible while unlocked; compact Copy controls retain the configured cleanup countdown | Yes |
|
|
| Base pass: `find` | `find` (Edit) | Name-search form and typed result activation | Yes |
|
|
| Base pass: `grep` | `search-contents` (Edit) | Authenticated decrypted-search form and typed result activation | Yes |
|
|
| Base pass: `mv`/`rename`, `cp`/`copy`, `rm`/`remove` | `move-entry`, `copy-entry`, `delete-entry` (Entry) | Sidebar context controls and validated mutation forms; delete is confirmed | Yes |
|
|
| KeePass migration: additive KDBX import and quick add | `import-kdbx` (Tools) | Native file/key picker, protected password input, explicit confirmation, and storage-owned tree refresh | Yes |
|
|
| Pass OTP: code/show and timed copy | `generate-otp`, `copy-otp` (Entry) | Unlocked entry header shows the large code and storage-period countdown bar; the OTP field retains metadata/actions and HOTP confirmation | Yes |
|
|
| Pass OTP: insert/add/append and validate | `import-otp` (Entry) | URI/QR import form; storage validates, replaces, and commits | Yes |
|
|
| Pass OTP: URI terminal/clipboard/QR | `show-otp-uri`, `copy-otp-uri`, `show-otp-qr` (Entry) | Explicit secret view, timed copy, and storage-provided QR matrix | Yes |
|
|
| Pass OTP: remove | `remove-otp` (Entry) | Explicit permanent-removal confirmation | Yes |
|
|
| Embedded Git: status, history, remote divergence | `git-status` (Tools) | Git dashboard renders the storage snapshot and recent history | Yes |
|
|
| Embedded Git: fetch/pull | `git-pull` (Tools) | Pull progress/cancel control; fetch is the receive phase of the typed pull | Yes |
|
|
| Embedded Git: push | `git-push` (Tools) | Push progress/cancel control | Yes |
|
|
| Embedded Git: sync and conflicts | `git-sync` (Tools) | Sync progress plus per-path local/remote conflict choices | Yes |
|
|
| Desktop command discovery and pane navigation | `command-palette`, `toggle-pane-focus` (View) | Toolbar search, Tab focus transfer, arrows/Home/End/Enter navigation | The palette opens itself by shortcut/control and is intentionally not a result |
|
|
| Desktop text editing | `undo`, `redo`, `cut`, `paste` (Edit) | Platform text controls own these standard operations; the shared registry explains why app-level dispatch is disabled | Listed with its current availability |
|
|
| Window/application lifecycle | `about`, `close-window`, `quit`, `minimize` (IronStorage/File/Window) | Standard native roles on macOS and equivalent in-window actions elsewhere | Yes except native-only minimize behavior where the OS owns the role |
|
|
| Help and current shortcuts | `help` (Help) | Labelled, scrollable Help view generated from the action registry | Yes |
|
|
|
|
The CLI/TUI expose a few terminal-shaped selectors rather than separate domain
|
|
capabilities. Generic `show --qrcode`, OTP version output, arbitrary embedded
|
|
Git plumbing, and shell completion are therefore not duplicate desktop
|
|
actions. The desktop viewer already renders an ordinary field, OTP version
|
|
compatibility belongs to storage/CLI metadata, Git initialization and commits
|
|
occur within typed storage mutations, remote configuration is shared Settings,
|
|
and desktop command discovery is the palette. Git history and conflict
|
|
resolution are controls inside `git-status` rather than separate commands.
|
|
These are deliberate presentation differences, not storage-feature gaps.
|
|
|
|
## Interaction and accessibility evidence
|
|
|
|
- Keyboard-only operation uses Tab between panes, arrows/Home/End/Enter within
|
|
trees, fields, menus, and palette results, Escape to dismiss, and registered
|
|
accelerators. The same controls are mouse/touch activatable; sidebar context
|
|
actions also accept a secondary click.
|
|
- Both panes are independently scrollable, the divider is resizable, action
|
|
rows wrap, long names and storage-grouped multiline values are retained, and
|
|
the supported narrow window floor is 480 by 360 logical pixels. Iced/winit applies native
|
|
display scaling before layout.
|
|
- Compact main and utility toolbar controls use one 16-by-16 vector icon system
|
|
with descriptive delayed tooltips and registered shortcuts. Every utility
|
|
panel shares the entry palette, flat controls, responsive 760-pixel content
|
|
cap, and compact header/footer chrome; field labels remain visible as a
|
|
non-colour cue.
|
|
- The app implements no animation or motion-driven state transition. The one-
|
|
second subscription updates lease, OTP, Git, and clipboard presentation state
|
|
without moving focus or renewing authentication, so reduced-motion mode has
|
|
no additional transition to disable.
|
|
- Iced 0.14 does not expose a stable application API for supplying a native
|
|
screen-reader accessibility tree. Controls therefore have complete visible
|
|
labels and deterministic keyboard focus, but native screen-reader role/name
|
|
integration is an explicit framework limitation rather than a silent stub.
|
|
|
|
## Platform menu and workflow smoke contract
|
|
|
|
`conventional_shortcuts_resolve_on_every_supported_platform` executes the
|
|
Command-versus-Control mapping for macOS, Linux, and Windows on every test host.
|
|
The macOS-only native adapter test verifies its native accelerators. Linux and
|
|
Windows use the same action registry through the in-window menu, so its labels,
|
|
enablement, palette dispatch, and workflow state tests are platform-neutral.
|
|
|
|
Native equivalent runners use stable Rust and run from the repository root:
|
|
|
|
```sh
|
|
cargo test --package ironstorage-desktop --all-targets
|
|
cargo check --package ironstorage-desktop --all-targets
|
|
cargo run --package ironstorage-desktop
|
|
```
|
|
|
|
For the final smoke step on each native host:
|
|
|
|
| Platform | Menu/accelerator smoke | Primary workflow smoke |
|
|
| --- | --- | --- |
|
|
| macOS | System App/File/Edit/View/Entry/Tools/Window/Help menus; Command-O/S/F/K/L, Tab, F1 | Open a test vault, unlock/view/edit/save, search, Git refresh, OTP code/copy, lock, close |
|
|
| Linux | In-window menus; Ctrl-O/S/F/K/L, Tab, F1 | Same sequence under X11 or Wayland with the desktop portal available |
|
|
| Windows | In-window menus; Ctrl-O/S/F/K/L, Tab, F1 | Same sequence with the native folder picker and Windows secure store available |
|
|
|
|
The automated state tests use temporary real encrypted stores and cover the
|
|
same primary workflows without retaining a GUI password or starting a helper.
|
|
Native picker, clipboard, secure-store, and actual screen-reader integration
|
|
remain native-host smoke checks because CI cannot emulate those OS services.
|
|
|
|
## Security and architecture audit
|
|
|
|
| Risk | Enforced behavior and executable evidence |
|
|
| --- | --- |
|
|
| Plaintext lifetime and persistence | Entry/OTP values use storage `SecretBytes` or zeroizing edit buffers. Lock, expiry, vault switch, and stale completion paths drop the editor and sensitive presentation state. The source audit rejects desktop filesystem writes. |
|
|
| Authenticated values, errors, and diagnostics | Storage supplies sensitivity and redacted typed errors. Viewer/editor tests require every field to remain visible until lock or lease expiry; malformed and non-UTF-8 fields remain lossless. Desktop messages are not `Debug`, and the source audit rejects print/debug/log-style output. |
|
|
| Clipboard | `NativeClipboardManager` owns timeout and replacement-safe cleanup. Desktop state shows a live remaining-seconds value, cancels cleanup on lock, and ignores stale completions. |
|
|
| Authentication expiry | Storage authentication leases own the clock and policy. Passive ticks, rendering, pointer movement, and window events do not renew activity; deterministic tests cover expiry during protected state. |
|
|
| Dirty documents and conflicts | Every entry/vault/window/Git worktree replacement routes through one Save/Discard/Cancel decision. Failed saves and conflicts keep the complete draft. |
|
|
| Background and window lifecycle | Generation counters reject stale asynchronous results. Lock cancels Git/clipboard work and clears OTP, QR, URI, entry, and editor state. Close and quit use the same dirty guard. |
|
|
| Repository and domain ownership | The executable source audit rejects repository/Git construction, process launch, OTP/QR parsing, filesystem writes, unsafe blocks, and insecure HTTP literals in production desktop modules. HTTPS and SSH endpoint parsing, host trust, authentication, and protocol behavior remain in `crates/storage`; desktop only presents typed state and native confirmation or masked-passphrase prompts. The folder picker may read only a user-selected QR image; all password-store I/O remains in `crates/storage`. |
|
|
|
|
Run the complete repository gate after the desktop-specific checks:
|
|
|
|
```sh
|
|
cargo fmt --all -- --check
|
|
RUSTFLAGS="-D warnings" cargo check --workspace --all-targets
|
|
cargo clippy --workspace --all-targets -- -D warnings
|
|
cargo test --workspace
|
|
```
|