feat(desktop): add mutation review guardrails

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Senior Frontend Engineer
2026-03-31 08:47:14 +00:00
parent bf6f8bc0bf
commit 35040ef0c9
7 changed files with 1084 additions and 125 deletions

View File

@@ -47,6 +47,7 @@ Use a four-zone workspace:
- New connection form entry point
- Active DB switcher
- Safety posture and backend boundary summary
- Local smoke fixture assist for repeatable QA runs
### Browser pane
@@ -84,29 +85,45 @@ Use a four-zone workspace:
- `apps/desktop` now runs on React and Tailwind-based styling.
- The shell now consumes the existing Tauri bridge for `backend_bootstrap`, `test_redis_connection`, `browse_redis_keys`, `read_redis_value`, `write_redis_value`, and `execute_redis_command`.
- The inspector now consumes `update_redis_key_ttl` for live TTL set and persist actions in desktop runtime.
- The repository now also contains a visible string-only `Add key` dialog wired to `create_redis_value`, but that capability remains a separately tracked next-phase surface rather than part of this baseline milestone's required acceptance.
- shadcn-style UI primitives are used locally for buttons, inputs, textareas, badges, and dialogs.
- Browser-only dev mode uses explicit demo fallback so the visible shell can still be reviewed without a Tauri runtime.
- Tauri desktop mode now allows live connection tests, live key browsing, live value inspection, string save for supported keys, live TTL updates, and live command execution while keeping browser dev mode on explicit demo fallback.
- Non-string live values now render in structured read-only panels for `hash`, `list`, `set`, `zset`, and `stream`, so operators can scan typed payloads without reading raw JSON dumps.
- The visible shell now validates draft-connection name, host, port, and DB input before creation, and prevents duplicate profile names inside the local shell state.
- The DB switcher now exposes a predictable default operator range from `db0` through `db15` and keeps an out-of-range active DB visible instead of depending on a four-item hardcoded list.
- Zero-result key searches now place the inspector into an explicit empty state instead of leaving a stale key visible.
- Frontend error handling now routes stable backend error codes through a shared operator-facing notice layer so live failures render with consistent copy and banner tone across connection, browse, inspect, write, TTL, and command flows.
- The inspector now also renders a dedicated readability layer with explicit inspect status, value-surface semantics, next-step guidance, and key facts so string, structured, missing, and demo-fallback states are easier to interpret.
- Current-phase writable actions now require a scoped review step before string save, TTL set, or TTL removal proceeds, and no-op submissions are blocked before they reach the live bridge or demo fallback.
- The utility rail now exposes a bounded local smoke assist surface with fixture targeting, `smoke:*` focus, safe command presets, and the seeded key list from the local smoke runbook.
- Browser-only demo mode now keeps session-local mock string-save and TTL changes visible in the browser, inspector, and mock command responses so shell review does not claim success while leaving stale UI state behind.
## QA Acceptance For This Milestone
- The shell renders four distinct zones: rail, browser, inspector, command tray.
- The header keeps app version, runtime mode, and build mode visible for smoke validation.
- The utility rail exposes a copyable QA snapshot with runtime, connection, selection, and latest command context.
- The utility rail exposes the seeded local smoke fixture path and safe smoke shortcuts without requiring manual re-entry from the runbook.
- The active connection and active DB stay visible without opening a modal.
- The DB switcher exposes `db0` through `db15` by default and still keeps the current DB visible when the active scope falls outside that range.
- Search filters the browser list and shows a no-results state.
- Search now exposes explicit mode feedback so operators can see whether the current input is being treated as a contains search or a raw Redis pattern.
- Search now exposes a bounded clear action in the browser header so operators can return to normal browse state without manually deleting the entire input.
- When search returns zero keys, the inspector switches to an empty state instead of showing the last selected key.
- Empty browser and inspector states now distinguish between an empty DB and a filtered no-match result instead of using one generic no-results sentence.
- The connection action distinguishes desktop live testing from browser demo fallback.
- Invalid draft connections cannot be created from the visible shell.
- Live backend failures are shown through a consistent banner treatment instead of per-surface ad hoc copy.
- Non-string keys are explicitly read-only.
- Non-string keys render as structured typed panels instead of raw JSON text blobs.
- The inspector keeps current status, value semantics, action guidance, and key facts visible without requiring operators to infer meaning from badges or raw payload shape alone.
- String keys show a save affordance near the value surface.
- TTL controls stay beside the inspector metadata and expose both set and remove flows.
- String save and TTL mutations now require a second review step that repeats scoped current-vs-next state before continuing.
- Failed save and TTL attempts keep the current draft value or TTL input in place so operators can adjust and retry without rebuilding context.
- Browser demo mode keeps mock string-save and TTL changes visible for the current session while still labeling the runtime as non-live.
- Current baseline sign-off does not require the visible `Add key` surface to pass or fail; keep any Add Key evidence separate unless PM explicitly promotes it into the active milestone.
- Delete requires a second confirmation step that includes key name and DB context.
- The command tray visibly blocks dangerous administrative commands.
- Command history marks whether each result came from the live desktop bridge or the demo shell.
@@ -123,7 +140,7 @@ pnpm run desktop:dev
Notes:
- `pnpm run desktop:dev` is the browser shell path. It supports layout review and demo fallback only.
- `pnpm run desktop:dev` is the browser shell path. It supports layout review and session-local demo fallback only; mock save and TTL actions update visible UI state, but no Tauri or Redis mutation occurs.
- `pnpm run desktop:tauri:dev` is the desktop integration path. Use it when QA or backend needs to validate the existing command bridge against a live Redis target.
- `pnpm --filter @redis-gui/desktop test` should stay green before handing frontend foundation changes to QA or other feature teams.
- Use `pnpm run desktop:build` for a production bundle check before handing the shell to QA or integration work.

View File

@@ -1,38 +1,50 @@
# Redis GUI V1 Acceptance Matrix
Date: 2026-03-27
Date: 2026-03-31
Owner: QA Engineer
## Evidence Collected On 2026-03-27
## Evidence Collected On 2026-03-31
- A fresh `cargo test -p redis-core` rerun passes in this session with 16 tests green.
- `pnpm install --lockfile-only` passes at repository root after adding `pnpm-workspace.yaml`.
- `cargo test -p redis-core` passes in this session with 20 tests green.
- `pnpm --filter @redis-gui/desktop test` passes in this session with 11 files and 44 tests green.
- `pnpm run desktop:build` passes and emits `apps/desktop/dist/`.
- `pnpm run desktop:tauri:build` now completes Linux `.deb` and `.rpm` artifact generation under `target/release/bundle/`, then fails later in the AppImage stage with `io: Connection reset by peer (os error 104)`.
- `pnpm run desktop:dev` starts Vite on `http://127.0.0.1:1420/`, and the served HTML points to the desktop shell entrypoint.
- `pnpm run desktop:tauri:build` now completes Linux `.deb` and `.rpm` artifact generation under `target/release/bundle/`.
- `pnpm run desktop:tauri:build:all` still fails later in the AppImage stage because `linuxdeploy` aborts in the current environment.
- `dpkg-deb -I target/release/bundle/deb/Redis GUI Foundation_0.1.0_amd64.deb` confirms Debian package metadata and runtime dependencies on `libwebkit2gtk-4.1-0` and `libgtk-3-0`.
- Direct launch of `target/release/desktop-shell` in this heartbeat fails before window creation with `Failed to initialize GTK`, because the current session has no `DISPLAY`, `WAYLAND_DISPLAY`, or `xvfb-run`.
- `./scripts/redis-fixture/start.sh`, `seed.sh`, and `stop.sh` pass in this session, and the seeded fixture exposes 7 `smoke:*` keys with expected string, TTL, hash, list, set, zset, and stream evidence.
- `./scripts/redis-fixture/seed.sh` also fails correctly when the fixture container is absent, with an explicit instruction to run `start.sh` first.
- The repository still contains no `Dockerfile`, `docker-compose.yml`, `compose.yaml`, or equivalent compose asset; Docker-backed verification currently depends on the documented fixture scripts plus a reachable local Docker daemon.
- The repository now contains a Rust workspace, a React workspace UI baseline, Tauri commands for connection testing and command execution, and shared frontend scope documentation.
- Browser dev mode still uses demo data for shell review, while Tauri desktop mode can now exercise live connection-test, key browse, value read/write, and command-execution bridges.
- The checked-out desktop shell now also exposes a visible string-only `Add key` flow through `create_redis_value`, but PM phase notes still treat that capability as next-phase inventory rather than a required current-baseline acceptance item.
- Browser dev mode now also keeps mock string-save and TTL changes visible for the current session, reducing shell-review drift between action banners and visible UI state without changing the live acceptance boundary.
- The desktop DB switcher now exposes a default `db0` through `db15` range and keeps an active out-of-range DB visible in the selector.
- A repeatable local Redis fixture and smoke runbook now exist in `scripts/redis-fixture/` and `docs/qa/local-desktop-smoke.md`.
- `docs/frontend-workspace-baseline.md` and `docs/redis-gui-v1-product-requirements.md` now both exist in-repo.
## Matrix
| Scope | Happy Path Acceptance | Failure Path Acceptance | Required Evidence | Current Status |
| --- | --- | --- | --- | --- |
| Linux app smoke | App installs or launches from a documented command, opens main window, connects to test Redis, exits cleanly | Missing Redis, bad host, bad password, unsupported DB or network loss surface actionable error and app stays stable | Launch steps, versioned artifact or dev command, screenshots, QA run log | Partially blocked: documented fixture and smoke path now exist, but a full Linux launch-and-connect evidence set is still pending |
| Linux app smoke | App installs or launches from a documented command, opens main window, connects to test Redis, exits cleanly | Missing Redis, bad host, bad password, unsupported DB or network loss surface actionable error and app stays stable | Launch steps, versioned artifact or dev command, screenshots, QA run log | Partially blocked: documented fixture, package artifacts, and smoke path now exist, but this heartbeat had no GUI-capable display session, so real Tauri window launch-and-connect evidence is still pending |
| macOS app smoke | Same as Linux, using signed or documented macOS artifact | Same failure paths, plus first-run permission or gatekeeper guidance if relevant | Build artifact name, install steps, screenshots, QA run log | Blocked: no validated macOS build or artifact evidence |
| Windows app smoke | Same as Linux, using installer or portable package | Same failure paths, plus Windows-specific install and uninstall validation | Build artifact name, install steps, screenshots, QA run log | Blocked: no validated Windows build or artifact evidence |
| Desktop workspace shell | Rail, browser, inspector, and command tray render together with active connection, build identity, runtime mode, and a copyable QA snapshot visible; command history labels live vs demo results | Empty search state clears the inspector selection, read-only non-string value state, destructive confirmation, and browser-mode demo fallback stay stable and explicit | `npm run desktop:dev` or `npm run desktop:build`, `docs/frontend-workspace-baseline.md`, screenshots or copied QA snapshot text | Pass for shell-level evidence; not a substitute for Redis feature acceptance |
| Connection management | Create a validated draft profile, keep DB context visible, and run the existing live connection-test bridge from Tauri desktop mode | Invalid host, bad port, bad password, duplicate name, timeout, and unreachable server are handled with consistent operator-facing messaging | Tauri run log, screenshots, repeatable steps, Redis target | Partially blocked: the shell now validates draft name/host/port/DB locally, maps backend error codes into shared notices, and calls the real connection-test command, but profile persistence and full evidence capture are not complete |
| Desktop workspace shell | Rail, browser, inspector, and command tray render together with active connection, build identity, runtime mode, a copyable QA snapshot, local smoke assist, visible inspector summary/key facts surfaces, and scoped mutation review for current-phase write actions | Empty search state clears the inspector selection, search mode feedback and clear action stay visible and predictable, read-only non-string value state, inspector status/action guidance stays aligned to live vs demo vs missing cases, destructive confirmation, no-op write attempts are blocked before execution, and browser-mode demo fallback stays explicit while mock save and TTL actions update session-local UI state | `npm run desktop:dev` or `npm run desktop:build`, `docs/frontend-workspace-baseline.md`, screenshots or copied QA snapshot text | Pass for shell-level evidence; not a substitute for Redis feature acceptance |
| Connection management | Create a validated draft profile, keep DB context visible, switch among a predictable default DB range, and run the existing live connection-test bridge from Tauri desktop mode | Invalid host, bad port, bad password, duplicate name, timeout, and unreachable server are handled with consistent operator-facing messaging | Tauri run log, screenshots, repeatable steps, Redis target | Partially blocked: the shell now validates draft name/host/port/DB locally, exposes `db0` through `db15` while preserving active out-of-range DB context, maps backend error codes into shared notices, and calls the real connection-test command, but profile persistence and full evidence capture are not complete |
| Key browsing | Browse DBs and keys, paginate or virtualize large lists, view metadata | Empty DB, deleted key during browse, permission error, and connection drop do not crash UI, and live failures reuse the shared error banner treatment | Seed dataset, result screenshots, observed limits | Partially blocked: desktop UI now calls the live browse bridge with `SCAN` pagination and metadata, but fixture-backed Tauri screenshots and measured limits are still pending |
| Search | Search by key name or pattern and return matching set within documented limits | No matches, invalid pattern, and very large result sets are handled predictably | Seed dataset, search queries, measured behavior | Partially blocked: desktop UI now maps search to live browse requests, but fixture-backed evidence and measured limits are still pending |
| Value editing | Open supported value types, edit, save, and refresh persisted value | Concurrent modification, invalid payload, and permission error preserve user context and surface failure through the shared operator notice layer | Before/after values, screenshots, repeatable steps | Partially blocked: string read/save/refresh is wired through the live desktop bridge, and non-string types now render in structured read-only inspector panels, but fixture-backed evidence and broader editing scope remain pending |
| TTL operations | View TTL, set TTL, remove TTL, and verify expiration behavior | Invalid TTL, already expired key, and permission error handled safely with consistent banner feedback | Seed dataset, timestamps, verification steps | Partially blocked: desktop UI now exposes live TTL set and remove controls through the existing contract, but seeded-fixture validation evidence is still missing |
| Search | Search by key name or pattern and return matching set within documented limits; visible shell makes it clear whether the current input is treated as a contains search or a raw Redis pattern | No matches, invalid pattern, empty DB state, and very large result sets are handled predictably, and operators can clear search back to browse state without ambiguity | Seed dataset, search queries, measured behavior | Partially blocked: desktop UI now maps search to live browse requests and exposes clearer search-state feedback, but fixture-backed evidence and measured limits are still pending |
| Value editing | Open supported value types, review pending string replacement, confirm save, and refresh persisted value; inspector keeps current state and write semantics explicit while editing | Concurrent modification, invalid payload, missing-key transitions, and permission error preserve user context, while no-op edits are blocked before execution and live failures reuse the shared operator notice layer | Before/after values, screenshots, repeatable steps | Partially blocked: string read/save/refresh is wired through the live desktop bridge, non-string types now render in structured read-only inspector panels, inspector guidance is clearer across live and fallback states, scoped review now clarifies current-vs-next value before save, and browser demo mode keeps session-local save state coherent, but fixture-backed live evidence and broader editing scope remain pending |
| TTL operations | View TTL, review pending TTL change or removal, confirm the mutation, and verify the resulting expiration behavior | Invalid TTL, already persistent/no-op TTL requests, already expired key, and permission error are handled safely with explicit guardrails and consistent banner feedback | Seed dataset, timestamps, verification steps | Partially blocked: desktop UI now exposes live TTL set and remove controls through the existing contract, blocks no-op TTL submissions, and keeps browser demo TTL state coherent, but seeded-fixture live validation evidence is still missing |
| Command console | Execute safe Redis commands in Tauri desktop mode and show result or error output with explicit live/demo labeling | Invalid command, long-running command, and blocked dangerous command are handled predictably, and backend failures reuse the shared operator notice mapping | Command transcript, screenshots, allow or deny rules | Partially blocked: the desktop UI now calls the real command execution bridge, but it is not yet validated against a shared live Redis fixture and dangerous mutations still stay blocked at shell level |
| Dangerous operation confirmation | Delete, flush, overwrite, or destructive commands require explicit confirmation | Cancel path does not mutate data; confirm path mutates only intended scope | Confirmation UX screenshots, before/after data | Blocked: feature not implemented |
| Installer and packaging | Package metadata, icon, version, and uninstall behavior are correct on each target OS | Corrupt install, upgrade, downgrade, and missing dependency behavior are documented or handled | Artifact checklist, install logs, uninstall evidence | Partially blocked: Linux `.deb` and `.rpm` artifacts now exist, but AppImage failed and install or uninstall evidence is still absent |
| Installer and packaging | Package metadata, icon, version, and uninstall behavior are correct on each target OS | Corrupt install, upgrade, downgrade, and missing dependency behavior are documented or handled | Artifact checklist, install logs, uninstall evidence | Partially blocked: Linux `.deb` metadata and contents are inspectable and the standard `.deb`/`.rpm` build path is stable, but AppImage remains blocked and install or uninstall evidence is still absent |
## Current Acceptance Judgment
- No Redis-backed Redis GUI V1 feature acceptance item can be marked passed on 2026-03-27.
- Current repository state now supports shell-level frontend acceptance and partial backend feature review: the React workspace shell builds, live desktop bridges exist for connection test, browse, value read/write, and command execution, draft-validation and empty-state behavior are explicit, and shared UI scope documentation is present in-repo.
- Rust source-level test evidence is now current for `redis-core`, Linux package artifacts exist for `.deb` and `.rpm`, but live Redis screenshots and installation evidence are still required.
- QA can now reuse the documented fixture and smoke path, but feature acceptance and release sign-off remain blocked on end-to-end desktop evidence.
- No Redis-backed Redis GUI V1 feature acceptance item can be marked passed on 2026-03-31.
- Current repository state now supports shell-level frontend acceptance and partial backend feature review: the React workspace shell builds, live desktop bridges exist for connection test, browse, string create, value read/write, and command execution, draft-validation and empty-state behavior are explicit, and shared UI scope documentation is present in-repo.
- The visible `Add key` surface should be tracked as implemented next-phase inventory only; its presence in the repository must not be treated as automatic current-baseline pass criteria or release scope expansion.
- Rust source-level test evidence is current for `redis-core`, the desktop test baseline is current, the browser demo entrypoint is reproducible, Linux package artifacts exist for `.deb` and `.rpm`, Debian metadata is inspectable, and the fixture path is reproducible on both success and one key failure path, but live Redis screenshots or logs and installation evidence are still required.
- QA can now independently execute the documented Linux baseline path, and the phase-level evidence loop is summarized in `docs/qa/current-phase-evidence-loop.md`, but feature acceptance and release sign-off remain blocked on a GUI-capable desktop session for end-to-end evidence, AppImage packaging, cross-platform evidence, and installer install or uninstall checks.