chore: move issue tracking to Gitea
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
# Issue tracker: Local Markdown
|
||||
|
||||
Issues and specs for this repo live as Markdown files in `.scratch/`.
|
||||
|
||||
## Conventions
|
||||
|
||||
- One feature per directory: `.scratch/<feature-slug>/`
|
||||
- The spec is `.scratch/<feature-slug>/spec.md`
|
||||
- Implementation issues are one file per ticket at
|
||||
`.scratch/<feature-slug>/issues/<NN>-<slug>.md`
|
||||
- Tickets are numbered from `01`
|
||||
- Comments and conversation history are appended under `## Comments`
|
||||
|
||||
## When a skill says "publish to the issue tracker"
|
||||
|
||||
Create a new file under `.scratch/<feature-slug>/`, creating the directory if needed.
|
||||
|
||||
## When a skill says "fetch the relevant ticket"
|
||||
|
||||
Read the referenced file. The user will normally provide its path or issue number.
|
||||
|
||||
## Wayfinding operations
|
||||
|
||||
- Map: `.scratch/<effort>/map.md`
|
||||
- Child ticket: `.scratch/<effort>/issues/NN-<slug>.md`
|
||||
- `Type:` records `research`, `prototype`, `grilling`, or `task`
|
||||
- `Status:` records `claimed` or `resolved`
|
||||
- `Blocked by: NN, NN` declares blocking relationships
|
||||
- Claim a ticket by setting `Status: claimed`
|
||||
- Resolve it by adding `## Answer`, setting `Status: resolved`, and updating the map
|
||||
@@ -0,0 +1,27 @@
|
||||
# Protocol Probe
|
||||
|
||||
## Decisions
|
||||
|
||||
1. **Probe semantics**. The Protocol Probe is a user-initiated handshake check against the Single proxy URL endpoint. It reports which proxy protocols the endpoint speaks (HTTP, SOCKS5, or both). It never forwards traffic through the proxy and never contacts anything beyond the endpoint itself.
|
||||
|
||||
2. **Trigger**. Ctrl+D starts a probe only when:
|
||||
- the Profile form is in Single mode, and
|
||||
- the active field is the Single proxy URL field.
|
||||
It does not run on the Name or Bypass fields, and it does not run when saving with Ctrl+S.
|
||||
|
||||
3. **Bare host:port default**. A typed endpoint without a scheme is treated as `http://` for parsing and dialing, matching the curl convention used elsewhere in the app.
|
||||
|
||||
4. **Mapping table**. After detection, the Profile is updated as follows:
|
||||
- HTTP only: the Single proxy URL becomes `http://<host:port>`.
|
||||
- HTTP and SOCKS5: the form switches to advanced mode; HTTP and HTTPS become `http://<host:port>`, while ALL/SOCKS becomes `socks5://<host:port>`. This preserves both detected capabilities and creates a Profile representable by GNOME as well as HTTP-only Targets.
|
||||
- SOCKS5 only: the Single proxy URL becomes `socks5h://<host:port>`.
|
||||
- Unrecognized protocol: status message only; the field is left untouched.
|
||||
- Dial failure: status message only; the field is left untouched.
|
||||
|
||||
5. **Userinfo preservation**. The exact bytes of any typed `user:pass@` userinfo are preserved, including special characters such as `@` and spaces. Only the scheme is replaced.
|
||||
|
||||
6. **Stale-result safety**. A probe started on the form is tagged with a generation ID. If the user leaves the form (Esc or a successful Ctrl+S) before the probe completes, the result is ignored and cannot mutate the abandoned form or the profiles page status.
|
||||
|
||||
7. **Failure UX**. A failed or unrecognized probe shows a status message and leaves the typed field unchanged so the user can correct the input and still save the Profile.
|
||||
|
||||
8. **Documentation**. README and CONTEXT already describe the Protocol Probe, its privacy boundary, and the `socks5h` GNOME caveat.
|
||||
@@ -0,0 +1,180 @@
|
||||
# proxyctl v1 specification
|
||||
|
||||
## Problem Statement
|
||||
|
||||
Linux users frequently need one proxy configuration to apply across several independent configuration surfaces. Changing Shell environment variables is insufficient for daemons, container defaults, desktop applications, and commands whose environment changes across privilege boundaries. Each surface has different configuration formats, state semantics, permissions, and restart requirements.
|
||||
|
||||
Users currently have to remember which files and commands control each surface, repeat the same proxy details, distinguish Docker daemon behavior from container/build behavior, preserve pre-existing settings, and diagnose partial failures manually. This is error-prone and makes switching between locations or networks unnecessarily risky.
|
||||
|
||||
## Solution
|
||||
|
||||
Build `proxyctl`, a keyboard-driven Linux TUI that coordinates one Active Profile across independently switchable Targets. The default screen shows only Available Targets, their detected state, the Active Profile, a concise explanation of the selected Target, and immediate operation feedback. Proxy Profile management lives on a separate page.
|
||||
|
||||
The first release supports Bash/Zsh Shell environments, APT, systemd-managed Docker daemon proxying, Docker container/build defaults, and GNOME desktop proxy settings. Every Target owns its detection, application, restoration, compatibility checks, and explanation behind one common Interface.
|
||||
|
||||
`proxyctl` preserves user-owned configuration wherever possible. It prefers a tool-owned overlay; when a Target has only a single mutable configuration surface, it records enough original state to restore it safely. It never silently discards unsupported Proxy Profile fields or Bypass rules.
|
||||
|
||||
## User Stories
|
||||
|
||||
1. As a Linux user, I want to open `proxyctl` without arguments, so that I immediately see the proxy controls relevant to my machine.
|
||||
2. As a Linux user, I want the main screen to show the Active Profile, so that I know which proxy settings an enable action will apply.
|
||||
3. As a Linux user, I want only Available Targets on the main screen, so that absent software does not clutter routine use.
|
||||
4. As a curious user, I want the help page to list every Target supported by `proxyctl`, so that I can discover integrations not available on my current system.
|
||||
5. As a troubleshooting user, I want unavailable Target explanations to state what was not detected, so that I understand why an integration is hidden.
|
||||
6. As a keyboard-focused user, I want to navigate with arrow keys or `j`/`k`, so that the TUI feels natural in a terminal.
|
||||
7. As a keyboard-focused user, I want to toggle the selected Target with Space, so that routine switching is fast.
|
||||
8. As a keyboard-focused user, I want `p` to open Proxy Profile management, so that configuration editing is separate from routine switching.
|
||||
9. As a keyboard-focused user, I want `?` to open help, so that explanations are always discoverable.
|
||||
10. As a keyboard-focused user, I want `r` to refresh detection, so that newly installed or removed software is reflected without restarting.
|
||||
11. As a keyboard-focused user, I want `q` or Escape to leave the current page or exit, so that navigation is predictable.
|
||||
12. As a user in a mouse-capable terminal, I want the keyboard Interface to remain complete without mouse support, so that behavior is consistent across terminals.
|
||||
13. As a Linux user, I want the selected Target's summary visible on the main screen, so that I understand what its switch affects.
|
||||
14. As a Linux user, I want each Target explanation to state what it does not affect, so that names such as Docker daemon are not misleading.
|
||||
15. As a Linux user, I want each Target explanation to describe expected permissions and side effects, so that I can anticipate failures or restarts.
|
||||
16. As a Linux user, I want detailed help for each Target, so that I can inspect configuration scope and detection evidence when needed.
|
||||
17. As a user with several networks, I want to create named Proxy Profiles, so that I can reuse proxy settings without retyping them.
|
||||
18. As a user with several Proxy Profiles, I want exactly one of them selected as the Active Profile, so that all Enabled Targets have one unambiguous source.
|
||||
19. As a first-time user, I want the Target screen to remain usable when no Proxy Profiles exist, so that I am not forced through an onboarding wizard.
|
||||
20. As a first-time user, I want an attempt to enable a Target without an Active Profile to explain the problem and point me to Profile management, so that the failed action is understandable.
|
||||
21. As a user with no Active Profile, I want to remain able to disable previously managed Targets, so that stale system configuration can always be removed.
|
||||
22. As a user editing a Proxy Profile, I want a default Single proxy mode, so that common local-proxy setups require only one URL and a Bypass list.
|
||||
23. As an advanced user, I want separate HTTP, HTTPS, and ALL/SOCKS values, so that I can model proxies with protocol-specific endpoints.
|
||||
24. As a user switching from Single proxy to advanced mode, I want my existing value preserved and expanded, so that changing modes does not discard input.
|
||||
25. As a user entering a proxy endpoint, I want malformed URLs and unsupported schemes rejected before application, so that bad configuration never reaches a Target.
|
||||
26. As a user with an HTTP proxy, I want `http` and `https` proxy URL schemes supported, so that standard enterprise proxies can be represented.
|
||||
27. As a user with a SOCKS proxy, I want `socks5` and `socks5h` kept distinct, so that DNS resolution behavior remains explicit.
|
||||
28. As a user with internal resources, I want Bypass entries for exact hostnames, domain suffixes, IPv4, IPv6, and CIDR ranges, so that internal traffic can avoid the proxy.
|
||||
29. As a user editing Bypass rules, I want entries normalized and deduplicated, so that the Proxy Profile stays understandable.
|
||||
30. As a security-conscious user, I want a Target to reject an incompatible Bypass rule rather than silently drop it, so that traffic is not unexpectedly sent through a proxy.
|
||||
31. As a user with an authenticated proxy, I want credentials representable in proxy URLs, so that authenticated endpoints work.
|
||||
32. As a user with an authenticated proxy, I want passwords obscured in the TUI and removed from logs and errors, so that credentials are not casually exposed.
|
||||
33. As a user who values portable configuration, I want Proxy Profiles stored in a human-readable format under the standard user configuration area, so that I can inspect and back them up.
|
||||
34. As a user storing credentials, I want the Profile configuration restricted to my user account, so that other local users cannot read it.
|
||||
35. As a Linux user, I want Shell proxy variables to include conventional upper- and lower-case forms, so that common command-line tools inherit them reliably.
|
||||
36. As a Bash or Zsh user, I want a one-time Shell integration installer, so that later TUI changes can update my current parent Shell after the TUI exits.
|
||||
37. As a Bash or Zsh user, I want to uninstall the Shell integration cleanly, so that `proxyctl` leaves no stale startup hook.
|
||||
38. As a user of an unsupported Shell, I want the Shell Target hidden and the help page to explain the supported shells, so that the limitation is explicit.
|
||||
39. As an APT user, I want persistent APT proxy control, so that package operations remain consistent even when an interactive Shell environment is not propagated.
|
||||
40. As an APT user with existing configuration, I want `proxyctl` to preserve that configuration beneath its own overlay, so that disabling the Target restores my prior setup.
|
||||
41. As a Docker user, I want Docker daemon proxying separate from Docker container/build defaults, so that I can control registry access independently from injected container variables.
|
||||
42. As a Docker user, I want the Docker daemon Target to explain that it affects daemon network operations, so that I do not mistake it for container networking.
|
||||
43. As a Docker user, I want a warning before Docker daemon configuration triggers a restart, so that I can avoid disrupting running work unexpectedly.
|
||||
44. As a Docker user, I want cancellation of the restart warning to make no changes, so that declining is safe.
|
||||
45. As a Docker user, I want daemon configuration and restart failures reflected immediately, so that the TUI never implies a change succeeded when it did not.
|
||||
46. As a Docker user, I want container/build defaults to affect only future containers and builds, so that the behavior matches Docker's documented model.
|
||||
47. As a GNOME user, I want a desktop proxy Target, so that applications using GNOME system network settings receive the Active Profile.
|
||||
48. As a non-GNOME user, I want the GNOME Target hidden, so that unsupported desktop settings are not offered.
|
||||
49. As a user toggling a Target, I want an applying state followed immediately by success or a red error, so that every Space press has visible feedback.
|
||||
50. As a user whose enable operation fails before writing anything, I want the previous Target state preserved, so that a failed operation does not move the switch.
|
||||
51. As a user whose operation partially changes a Target, I want `proxyctl` to re-inspect the real configuration, so that the displayed state reflects what is actually present.
|
||||
52. As a user switching the Active Profile, I want every Enabled Target updated to the new Profile, so that enabled configuration remains coordinated.
|
||||
53. As a user switching the Active Profile, I want each Target row to update as its operation completes, so that progress and failures are visible immediately.
|
||||
54. As a user facing a partial Active Profile switch, I want successful Targets to remain updated and failed Targets to become Drifted when appropriate, so that the tool does not hide partial success.
|
||||
55. As a user, I want an Enabled Target to mean its actual managed configuration matches the Active Profile, so that the status has a precise meaning.
|
||||
56. As a user, I want a Drifted Target to identify a managed configuration that no longer matches the Active Profile, so that I know it needs repair or removal.
|
||||
57. As a user with pre-existing proxy settings, I want a recognized non-`proxyctl` configuration shown as External, so that the tool does not claim ownership of it.
|
||||
58. As a user disabling a Target that previously had External configuration, I want that configuration restored and the state to return to External, so that my prior setup is preserved.
|
||||
59. As a user with an unrecognized configuration source, I accept that absence of positive detection is displayed as Disabled, so that the first release avoids an Unknown state.
|
||||
60. As a user inspecting an External state, I want the details to identify the evidence that was detected, so that I can locate the original configuration.
|
||||
61. As a safety-conscious user, I want `proxyctl` to prefer dedicated tool-owned configuration fragments, so that it avoids rewriting unrelated user files.
|
||||
62. As a safety-conscious user, I want original values recorded when an isolated fragment is impossible, so that disabling can restore the previous state.
|
||||
63. As a safety-conscious user, I want configuration writes to be atomic, so that a crash does not leave a partially written file.
|
||||
64. As a user, I want only one `proxyctl` operation to mutate state at a time, so that concurrent sessions cannot corrupt recovery metadata.
|
||||
65. As an unprivileged user, I want writable Targets to work normally and permission failures to be reported plainly, so that the TUI does not surprise me with a password prompt.
|
||||
66. As an unprivileged user, I want `proxyctl` never to initiate privilege escalation, so that authority changes remain under my control.
|
||||
67. As a user who explicitly starts `proxyctl` through `sudo`, I want the invoking user to remain the Profile and user-configuration owner, so that I do not see an unrelated root configuration.
|
||||
68. As a user who explicitly starts `proxyctl` through `sudo`, I want system Targets to use the available root authority while user Targets still operate on the invoking user's configuration, so that mixed-scope behavior is predictable.
|
||||
69. As a root login user, I want root to be treated as the configuration owner when there is no invoking user, so that direct root sessions remain coherent.
|
||||
70. As a troubleshooting user, I want `proxyctl doctor` to report configuration, permission, command, and Target detection problems, so that I can diagnose failures without guessing.
|
||||
71. As a user removing `proxyctl`, I want `proxyctl reset` to disable all managed Targets after confirmation and restore prior configuration, so that uninstalling does not strand proxy settings.
|
||||
72. As a Shell user, I want explicit Shell install and uninstall maintenance commands, so that startup-file changes are reversible.
|
||||
73. As a user, I want a version command, so that I can report the exact build when seeking help.
|
||||
74. As a user, I want local diagnostic logs with bounded growth, so that failures can be investigated without consuming unlimited disk space.
|
||||
75. As a privacy-conscious user, I want no telemetry or automatic update checks, so that `proxyctl` never contacts the network on its own.
|
||||
76. As a user, I want `proxyctl` not to test proxy connectivity automatically, so that toggling configuration has no hidden network side effects.
|
||||
77. As a Linux amd64 user, I want a single-file release binary, so that installation is straightforward.
|
||||
78. As a Linux arm64 user, I want an equivalent release binary, so that devices such as ARM development boards are supported.
|
||||
79. As a release consumer, I want checksums for release artifacts, so that I can verify downloads.
|
||||
80. As a developer, I want `go install` support, so that I can build and install directly from source.
|
||||
|
||||
## Implementation Decisions
|
||||
|
||||
- The product and executable are named `proxyctl`.
|
||||
- The implementation uses Go and Bubble Tea.
|
||||
- The default invocation opens the TUI. Maintenance commands cover Shell integration installation/removal, diagnostics, full managed-state reset, and version reporting. Scriptable Profile switching and Target toggling are not part of the first CLI Interface.
|
||||
- The TUI is keyboard-only in the first release. Its default page is the Target switch panel; Proxy Profile management and help are separate pages.
|
||||
- The Target panel shows only Available Targets. The help page lists all built-in Targets and explains failed detection.
|
||||
- The supported first-release Target Adapters are Bash/Zsh Shell environment, APT, systemd-managed Docker daemon, Docker container/build defaults, and GNOME desktop proxy.
|
||||
- The core TUI and Shell behavior target general Linux. APT support is limited to Debian-family systems, Docker daemon support to systemd-managed installations, Docker container/build support to the standard Docker client configuration model, and GNOME support to systems exposing the expected settings schema.
|
||||
- Target integrations are compiled in. There is no plugin Interface, arbitrary-command Target, or user-authored executable hook.
|
||||
- One Application Module coordinates Proxy Profiles, Active Profile transitions, Target operations, persistence, and user-facing results. Both TUI and maintenance commands consume its Interface.
|
||||
- A single Target seam hides platform-specific behavior. Target Adapters expose description, inspection, and desired-state operations; callers do not know configuration paths or system commands.
|
||||
- Target dependencies such as filesystem access and command execution are accepted at internal seams rather than created globally, permitting hermetic tests.
|
||||
- A Proxy Profile has a simple Single proxy editing mode and an advanced HTTP/HTTPS/ALL-SOCKS mode. Single mode expands into protocol values without losing the original value when advanced editing is opened.
|
||||
- Accepted URL schemes are HTTP, HTTPS, SOCKS5, and SOCKS5H. Scheme semantics are preserved, and each Target validates compatibility rather than converting unsupported schemes.
|
||||
- Bypass rules support exact hostnames, domain suffixes, IPv4, IPv6, and CIDR. They are normalized and deduplicated. A Target must reject an incompatible rule instead of dropping it.
|
||||
- Proxy URLs may contain credentials. The human-readable Profile configuration is stored under the XDG user configuration location with owner-only permissions. Secrets are obscured in the TUI and redacted from diagnostics and logs.
|
||||
- User-authored configuration, generated Shell integration, runtime recovery metadata, generated Shell environment, and logs are separated according to XDG configuration and state conventions.
|
||||
- Configuration and state writes use temporary output followed by atomic replacement. Cross-process mutation is serialized with a lock.
|
||||
- `proxyctl` prefers tool-owned overlays or fragments. When a Target cannot provide an isolated overlay, recovery state records the original value and the last applied fingerprint.
|
||||
- Target inspection distinguishes Enabled, Disabled, External, and Drifted. External is shown only when an Adapter positively recognizes a non-`proxyctl` proxy setting. If no recognized external setting is found, the state is Disabled; there is no Unknown state in the first release.
|
||||
- An operation changes the displayed switch only after success. Failures are rendered immediately on the affected row with full redacted detail in the explanation area.
|
||||
- After any partial write or command failure, the Adapter re-inspects the Target and returns the state implied by actual configuration.
|
||||
- Changing the Active Profile attempts to update every Enabled Target and reports progress per Target. Cross-Target rollback is not attempted. Failed Targets may become Drifted while successful Targets remain Enabled on the new Profile.
|
||||
- No Active Profile is permitted when no Proxy Profiles exist. Attempts to enable a Target in that state fail with a direct route to Profile management. Disabling remains available.
|
||||
- Deleting the final Proxy Profile requires confirmation. Existing managed Target configuration is retained and becomes Drifted rather than being modified implicitly.
|
||||
- Shell behavior uses a one-time Bash/Zsh integration because a child TUI process cannot mutate its parent Shell environment. The wrapper reloads generated exports/unsets after the TUI exits. Unsupported shells do not expose the Shell Target.
|
||||
- Shell output includes conventional upper- and lower-case proxy environment names and explicit unsets when disabled.
|
||||
- Docker daemon and Docker container/build defaults remain separate Targets because their documented effects and configuration surfaces differ.
|
||||
- Docker daemon changes require an explicit warning before any mutation. Confirmation applies the configuration, reloads the manager as required, and restarts Docker immediately. Cancellation performs no mutation; there is no Pending Restart state.
|
||||
- APT remains a dedicated Target for persistence and privilege-boundary reliability even though APT supports proxy environment variables.
|
||||
- `proxyctl` never invokes `sudo`, `pkexec`, or another privilege escalation mechanism. Permission failures are normal operation results.
|
||||
- When already running under `sudo`, `proxyctl` uses the invoking user's identity and XDG locations for Profiles and user Targets while allowing system Targets to use current authority. With no invoking user, the effective root user is the owner.
|
||||
- Local logs contain redacted operation diagnostics, have bounded growth, and never contain unredacted proxy credentials.
|
||||
- The program has no telemetry, automatic update requests, or automatic proxy connectivity checks.
|
||||
- Release output consists of checksum-verifiable single binaries for Linux amd64 and arm64, plus source installation through Go tooling. Distribution-specific packages are deferred.
|
||||
|
||||
## Testing Decisions
|
||||
|
||||
- Good tests assert externally observable behavior through the highest practical seam: returned application state, rendered user-facing outcomes, managed configuration effects, restoration behavior, and invoked system operations. They do not assert private helper calls, internal data layout, or incidental implementation order.
|
||||
- The primary test seam is the Application Module Interface used by both the TUI and maintenance commands. Tests submit the same intents a user can trigger and assert resulting snapshots and operation results.
|
||||
- Application tests cover Proxy Profile CRUD, Active Profile selection and deletion, Single/Advanced validation, absence of an Active Profile, per-Target immediate feedback, partial Profile switching, reset, diagnostics, and credential redaction.
|
||||
- The shared Target Interface is the second seam. Every real Target Adapter is run through common contract tests for availability detection, Disabled, Enabled, External, Drifted, enable, disable, restoration, idempotency, incompatible Proxy Profile rejection, permission failure, partial failure, and redaction.
|
||||
- Adapter tests use isolated XDG directories, temporary filesystem roots, and a fake command runner. They must never modify the developer machine's Shell startup files, APT configuration, Docker daemon, Docker client configuration, GNOME settings, or systemd state.
|
||||
- Target-specific tests cover Bash and Zsh integration behavior, APT overlay precedence and restoration, Docker daemon restart confirmation and command failures, Docker container/build semantics, and GNOME settings snapshot/restoration.
|
||||
- `sudo` identity behavior is tested using injected process identity and environment data rather than requiring tests to run as root.
|
||||
- TUI tests remain thin: key-to-intent mapping, page navigation, visible Active Profile, status/error rendering, and selected-Target explanation. Business behavior is not duplicated at the rendering layer.
|
||||
- Process-level smoke tests cover default startup, Shell integration maintenance commands, doctor, reset confirmation, and version output.
|
||||
- Filesystem tests verify owner-only secret-bearing configuration, atomic replacement, lock behavior, original-state preservation, and cleanup.
|
||||
- Failure tests verify that no operation reports success before effects complete, cancellation mutates nothing, unsupported Bypass rules are never silently omitted, and logs/errors redact credentials.
|
||||
- There is no existing codebase test prior art. The first tracer implementation must establish reusable application and Target contract harnesses for later Adapters.
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- Starting, stopping, configuring, or supervising proxy programs such as Clash, sing-box, or Xray.
|
||||
- Proxy subscriptions, node management, latency testing, automatic node selection, and routing-rule management.
|
||||
- Transparent proxying, TUN devices, iptables, nftables, or other traffic interception.
|
||||
- Automatic proxy connectivity checks.
|
||||
- Arbitrary systemd service proxy configuration.
|
||||
- Git, DNF, npm, pip, or other tools that already consume conventional Shell proxy variables in the intended first-release scenarios.
|
||||
- Firefox-specific policy or profile modification.
|
||||
- Chromium-specific launch-flag management.
|
||||
- KDE or other desktop proxy integrations beyond GNOME.
|
||||
- Snap/Ubuntu Core proxy configuration.
|
||||
- Fish and other Shells beyond Bash and Zsh.
|
||||
- Mouse interaction.
|
||||
- Plugins, custom Targets, and arbitrary user-defined commands.
|
||||
- A complete headless CLI for Profile and Target operations.
|
||||
- Internal privilege escalation or graphical authorization agents.
|
||||
- Cross-Target atomic transactions and rollback.
|
||||
- Distribution-specific deb, rpm, AUR, Snap, Flatpak, or similar packages.
|
||||
- Windows, macOS, and non-Linux Unix platforms.
|
||||
|
||||
## Further Notes
|
||||
|
||||
- Domain terminology is defined in the repository glossary and must be used consistently in code, tests, issues, and user-facing explanations.
|
||||
- The supporting research corrects an important premise: APT, DNF, and Git do support conventional proxy environment variables. Dedicated integrations are justified by persistence, process, privilege, or desktop boundaries rather than a blanket lack of environment-variable support.
|
||||
- Docker daemon and Docker container/build defaults are deliberately separate because Docker documents them as independent configuration surfaces with different effects.
|
||||
- GNOME desktop proxy support is preferred over browser-specific modification because Chromium consumes system network settings and Firefox can use a system proxy mode.
|
||||
- External detection is explicitly best-effort. The first release favors a simpler four-state Interface and documents detection evidence rather than claiming exhaustive discovery of every possible configuration source.
|
||||
- No ADR is currently required: the decisions are contained within this product specification and do not yet meet the threshold of a surprising, costly-to-reverse architectural trade-off proven against an existing implementation.
|
||||
@@ -0,0 +1,212 @@
|
||||
# Efficient professional TUI redesign
|
||||
|
||||
## Problem Statement
|
||||
|
||||
`proxyctl` is functionally capable, but its current terminal interface is an unbounded plain-text document rather than an efficient operational dashboard. Routine use requires navigating away from the Target panel to switch the Active Profile, long descriptions and errors compete with the Target list, and operations temporarily block useful browsing. The interface does not respond to terminal size, scroll long content, provide mature field editing, or present consistent focus, status, confirmation, and error behavior.
|
||||
|
||||
The visual hierarchy is too weak for users to assess configuration health at a glance. Target states are plain bracketed words, Profile markers are unexplained, errors are styled inconsistently, and busy or deferred-exit states are not always visible. The static Help page and long lists can extend beyond the terminal with no viewport. Profile fields support only appending and backspacing, making correction of long URLs and Bypass rules unnecessarily slow.
|
||||
|
||||
Some actions are also described too generically. In particular, treating every Target action as a toggle hides the meaningful difference between enabling a Disabled Target, applying an Active Profile to an External Target, and performing Drift Resolution on a Drifted Target.
|
||||
|
||||
## Solution
|
||||
|
||||
Redesign the TUI as a keyboard-only, responsive, professional dashboard optimized for frequent operation. The default wide layout presents a stable Target list beside concise details for the selected Target, with the Active Profile and global Target health summarized in the header. Narrow terminals automatically use a single-column layout without changing the underlying workflows.
|
||||
|
||||
Use restrained semantic color, standard Unicode symbols, explicit state text, stable focus treatment, contextual actions, scrollable content, structured status feedback, and safe modal dialogs. Color reinforces meaning but is never the sole signal. The interface adapts to light and dark terminals and respects `NO_COLOR`.
|
||||
|
||||
Make Active Profile switching a first-class main-screen action through a searchable picker, while keeping Profile creation, editing, and deletion in a dedicated management experience. Replace the append-only form with mature text inputs, field-level validation, a parsed Bypass preview, and an explicit Protocol Probe action.
|
||||
|
||||
Keep system mutations serial and safe while allowing the user to browse the dashboard during an operation. Preserve the existing no-cross-Target-rollback rule, surface partial outcomes directly on Target rows, and focus the first failed Target. Introduce explicit Drift Resolution choices for reapplying the Active Profile or restoring original configuration when ownership evidence permits.
|
||||
|
||||
Rebuild the presentation layer around Bubble Tea, Bubbles, and Lip Gloss, with separate layout, theme, page, modal, and reusable component responsibilities. Permit focused changes to the Application Interface where required for progressive detection, structured progress, structured errors, and Drift Resolution, while preserving stable Target configuration semantics.
|
||||
|
||||
## User Stories
|
||||
|
||||
1. As a frequent proxyctl user, I want the default screen optimized for rapid scanning, so that I can understand system proxy state immediately.
|
||||
2. As a frequent proxyctl user, I want the Active Profile visible in the header, so that I know which Proxy Profile is being applied.
|
||||
3. As a frequent proxyctl user, I want a global count of Enabled, Disabled, External, and Drifted Targets, so that I can identify abnormal state without inspecting every row.
|
||||
4. As a frequent proxyctl user, I want Target ordering to remain stable, so that state changes do not move actions beneath my cursor.
|
||||
5. As a frequent proxyctl user, I want failed Targets focused after a partial operation, so that I can investigate without searching.
|
||||
6. As a keyboard user, I want every workflow to remain fully operable without a mouse, so that proxyctl works consistently over SSH and in minimal terminals.
|
||||
7. As a keyboard user, I want familiar arrow and terminal navigation conventions, so that the interface is quick to learn.
|
||||
8. As a keyboard user, I want Tab to move focus between interactive regions, so that focus changes are explicit.
|
||||
9. As a keyboard user, I want the focused region visibly highlighted, so that I always know where input will apply.
|
||||
10. As a keyboard user, I want contextual shortcuts in a fixed footer, so that the most relevant actions remain discoverable.
|
||||
11. As a keyboard user, I want complete shortcuts available through Help, so that the footer can remain concise.
|
||||
12. As a user who prefers redesigned shortcuts, I want the new interaction model optimized without preserving every legacy key, so that obsolete constraints do not weaken the redesign.
|
||||
13. As a user in a wide terminal, I want a Target list and Target details visible side by side, so that selection and explanation do not compete for vertical space.
|
||||
14. As a user in a narrow terminal, I want the interface to become a usable single-column layout, so that split panes and SSH sessions remain supported.
|
||||
15. As a user in a terminal smaller than the supported minimum, I want a concise size warning rather than corrupted layout, so that recovery is obvious.
|
||||
16. As a user who resizes a terminal, I want the layout to update immediately while preserving selection and focus, so that resizing does not reset my work.
|
||||
17. As a user with long Target details, I want a scrollable details viewport, so that every explanation remains reachable.
|
||||
18. As a user with many Proxy Profiles, I want scrollable lists, so that selection never moves beyond visible content.
|
||||
19. As a user opening Help in a short terminal, I want scrollable Help content, so that no instructions are inaccessible.
|
||||
20. As a user, I want restrained professional styling, so that the interface is polished without becoming visually noisy.
|
||||
21. As a user, I want standard Unicode or ASCII symbols, so that the interface does not depend on Nerd Font installation.
|
||||
22. As a user, I want Target states represented by symbols, color, and words together, so that meaning survives monochrome terminals and screenshots.
|
||||
23. As a user in a light terminal, I want readable contrast, so that styling designed for dark backgrounds does not disappear.
|
||||
24. As a user in a dark terminal, I want readable contrast, so that the dashboard remains comfortable for long sessions.
|
||||
25. As a user who sets `NO_COLOR`, I want all meaning retained without color, so that accessibility and terminal preferences are respected.
|
||||
26. As a user, I want a small recognizable proxyctl title, so that the interface has identity without wasting screen space on a large logo.
|
||||
27. As a user, I want only Available Targets shown during routine operation, so that absent integrations do not create clutter.
|
||||
28. As a troubleshooting user, I want to toggle visibility of unavailable Targets, so that detection evidence is available without leaving the dashboard.
|
||||
29. As a user selecting a Target, I want its state and evidence shown before long documentation, so that the most actionable information appears first.
|
||||
30. As a user selecting a Target, I want to see what it affects, so that I understand the configuration surface.
|
||||
31. As a user selecting a Target, I want permission and restart risks highlighted, so that operational consequences are not buried in prose.
|
||||
32. As a user, I want Disabled Targets to offer an Enable action, so that the operation is unambiguous.
|
||||
33. As a user, I want Enabled Targets to offer a Disable action, so that the operation is unambiguous.
|
||||
34. As a user, I want External Targets to offer Apply Profile, so that I understand proxyctl will begin managing that configuration while preserving restorable state.
|
||||
35. As a user, I want Drifted Targets to offer Drift Resolution, so that the interface does not guess my intended recovery.
|
||||
36. As a user resolving drift, I want to reapply the Active Profile, so that managed configuration can return to Enabled.
|
||||
37. As a user resolving drift, I want to restore original configuration when ownership evidence permits, so that I can stop proxyctl management safely.
|
||||
38. As a user resolving drift without sufficient ownership evidence, I want restoration to fail truthfully and safely, so that external changes are not overwritten.
|
||||
39. As a user performing a routine reversible Target action, I do not want a confirmation dialog, so that frequent operation remains fast.
|
||||
40. As a user deleting a Proxy Profile, I want a confirmation dialog, so that destructive actions are deliberate.
|
||||
41. As a user whose action will restart Docker, I want a high-impact confirmation dialog, so that running work is not disrupted unexpectedly.
|
||||
42. As a user in a confirmation dialog, I want cancellation to be the safe default, so that accidental confirmation is unlikely.
|
||||
43. As a user, I want to switch the Active Profile directly from the dashboard, so that routine switching does not require entering management screens.
|
||||
44. As a user switching Profiles, I want a searchable picker, so that selection remains fast with many Profiles.
|
||||
45. As a user opening the Profile picker, I want the Active Profile pinned first and other Profiles sorted by name, so that ordering is stable and predictable.
|
||||
46. As a user, I want Profile switching and Profile management to remain distinct, so that routine activation is not mixed with destructive editing actions.
|
||||
47. As a user, I want to create, edit, and delete Proxy Profiles in a dedicated management page, so that those workflows have enough space and context.
|
||||
48. As a user editing a Proxy Profile, I want a real text cursor and insertion editing, so that I can correct text without deleting from the end.
|
||||
49. As a user editing a Proxy Profile, I want Home, End, Delete, Backspace, and paste behavior, so that terminal text editing is efficient.
|
||||
50. As a user editing a long URL, I want horizontal scrolling with visible focus, so that the field remains usable in narrow layouts.
|
||||
51. As a user entering invalid data, I want validation beside the relevant field, so that I know exactly what to fix.
|
||||
52. As a user correcting a field, I want stale field errors to clear or update, so that the form reflects current input.
|
||||
53. As a user switching between Single and Advanced Profile modes, I want existing values preserved according to current Profile semantics, so that mode changes do not discard work.
|
||||
54. As a user entering Bypass rules, I want to paste a comma-separated list, so that common configuration remains fast.
|
||||
55. As a user entering Bypass rules, I want a live normalized preview, so that deduplication and canonical forms are visible before saving.
|
||||
56. As a user entering an invalid Bypass rule, I want the specific rule identified, so that one bad entry does not produce an opaque form error.
|
||||
57. As a user entering proxy credentials, I want passwords obscured while editing and reviewing Profiles, so that shoulder surfing and screenshots do not expose secrets.
|
||||
58. As a security-conscious user, I want all TUI status, evidence, and error text defensively redacted before rendering, so that a lower layer cannot accidentally expose credentials.
|
||||
59. As a user with an uncertain endpoint, I want an explicit Protocol Probe action beside the applicable URL field, so that discovery is visible rather than hidden behind an unexplained shortcut.
|
||||
60. As a user who knows the Protocol Probe shortcut, I want the shortcut retained as an efficient path, so that frequent use remains quick.
|
||||
61. As a privacy-conscious user, I want Protocol Probe to run only when explicitly requested, so that saving and opening forms never create hidden network traffic.
|
||||
62. As a user probing an endpoint, I want progress attached to the URL field, so that the operation is connected to its source.
|
||||
63. As a user probing an endpoint, I want detected HTTP and SOCKS5 capabilities displayed, so that the resulting Profile values are understandable.
|
||||
64. As a user probing a dual-protocol endpoint, I want a compatible Advanced Profile populated, so that HTTP-only and GNOME Targets can share the Active Profile.
|
||||
65. As a user whose probe input changes while a probe is running, I want stale results ignored, so that old endpoint results never overwrite new input.
|
||||
66. As a user launching proxyctl, I want the dashboard to appear immediately with per-Target Checking states, so that slow detection does not look like a hung process.
|
||||
67. As a user refreshing Targets, I want each Target row to update as detection completes, so that progress is visible incrementally.
|
||||
68. As a user applying a Target change, I want an in-row spinner and a bottom status message, so that both local and global progress are visible.
|
||||
69. As a user waiting for a system mutation, I want to navigate Targets and read Help, so that the entire interface is not unnecessarily frozen.
|
||||
70. As a user waiting for a system mutation, I want conflicting modifications disabled, so that configuration operations remain serialized.
|
||||
71. As a user attempting a disabled action, I want an explanation of why it is unavailable, so that the interface does not silently ignore input.
|
||||
72. As a user switching the Active Profile, I want each affected Target to update independently, so that partial progress is truthful.
|
||||
73. As a user whose Active Profile switch partially fails, I want successful Target updates retained and failed Targets clearly marked, so that the existing no-global-rollback rule is visible.
|
||||
74. As a user whose Active Profile switch partially fails, I want the error summary preserved until acknowledged, so that the failure is not replaced by a transient success message.
|
||||
75. As a user completing a successful operation, I want the success notice replaceable by the next operation, so that routine feedback does not require dismissal.
|
||||
76. As a user receiving an error, I want concise text in the status area and an option to expand current details, so that diagnostics are available without permanently consuming space.
|
||||
77. As a user, I do not want an in-TUI activity history, so that the interface remains focused on current state.
|
||||
78. As a troubleshooting user, I want historical operation details to remain in the existing redacted log, so that removing an activity page does not remove diagnostics.
|
||||
79. As a user pressing Escape, I want the current modal closed or the current page left, so that back navigation is consistent.
|
||||
80. As a user pressing `q` on a child page, I want to return to the previous page, so that accidental application exit is less likely.
|
||||
81. As a user pressing `q` on the dashboard, I want to exit, so that the primary quit path remains efficient.
|
||||
82. As a user pressing Ctrl+C on any page, I want to exit, so that terminal interrupt behavior is consistent.
|
||||
83. As a user requesting exit during a mutation, I want a visible message that proxyctl will exit safely after completion, so that my input is not silently ignored.
|
||||
84. As a safety-conscious user, I do not want a system mutation terminated at an arbitrary intermediate step, so that exit does not strand configuration unnecessarily.
|
||||
85. As a user leaving proxyctl, I want the prior terminal screen restored, so that the dashboard does not leave redraw artifacts in shell history.
|
||||
86. As a user, I do not want the dashboard to claim that a proxy is online merely because Targets are Enabled, so that configuration state is not confused with connectivity.
|
||||
87. As a user, I want Protocol Probe results confined to Profile editing, so that handshake capability is not presented as global health or latency.
|
||||
88. As a maintainer, I want layout, theme, pages, dialogs, and components separated, so that future TUI work does not enlarge one monolithic state machine.
|
||||
89. As a maintainer, I want mature terminal components for text input, lists, viewports, and spinners, so that common interaction behavior is not reimplemented incompletely.
|
||||
90. As a maintainer, I want the Application Interface to expose structured progress and Drift Resolution intents, so that the TUI does not infer domain outcomes from display strings.
|
||||
91. As a maintainer, I want Target Adapter configuration semantics preserved, so that a visual redesign does not destabilize working proxy configuration.
|
||||
92. As a maintainer, I want each migration phase to leave a runnable TUI, so that the redesign can be verified incrementally.
|
||||
93. As a maintainer, I want fixed-size rendering tests, so that responsive layouts do not regress silently.
|
||||
94. As a maintainer, I want behavioral tests to drive the same Model used in production, so that test confidence covers real navigation and rendering composition.
|
||||
95. As a maintainer, I want long content, resize, focus, modal, and no-color cases tested, so that edge terminals receive deliberate behavior.
|
||||
|
||||
## Implementation Decisions
|
||||
|
||||
- The redesign optimizes first for rapid daily operation and second for polished visual quality. New-user explanation is available contextually but does not dominate the dashboard.
|
||||
- The primary wide-screen layout is a two-pane dashboard with a stable Target list on the left and concise selected-Target details on the right.
|
||||
- Layout is responsive. Terminals at least 100 columns by 28 rows receive the complete two-pane layout. Terminals from 60 through 99 columns use a single-column layout. Terminals smaller than 60 columns or 16 rows receive a compact size warning rather than a broken full interface.
|
||||
- Bubble Tea remains the application runtime. Bubbles supplies mature list, text-input, viewport, and spinner behavior. Lip Gloss supplies semantic styling and responsive composition.
|
||||
- The TUI is decomposed into explicit responsibilities for application state coordination, responsive layout, semantic theme, pages, dialogs, status presentation, and reusable components. The redesign must not continue concentrating all behavior and rendering in one file.
|
||||
- The program uses the terminal alternate screen and restores the previous terminal display on exit.
|
||||
- The interface remains strictly keyboard-only. Mouse handling is out of scope.
|
||||
- Existing shortcuts are not a compatibility contract. The redesign may replace them, while still preferring familiar terminal conventions and displaying contextual help.
|
||||
- Standard Unicode symbols are used for visual status. The interface does not depend on Nerd Font glyphs. ASCII-safe degradation is permitted where terminal capabilities require it.
|
||||
- Target state uses a symbol, semantic color, and explicit word. Color is reinforcement rather than the sole carrier of meaning.
|
||||
- The theme adapts to light and dark terminal backgrounds and respects `NO_COLOR`. Styling is restrained, professional, and low-saturation outside meaningful states and warnings.
|
||||
- The header contains a compact proxyctl identity, the Active Profile, and global Target state counts. It does not contain a large logo, version clutter, latency, or a global connected indicator.
|
||||
- The dashboard shows Available Targets by default. A contextual action toggles unavailable Targets into the same stable list with detection evidence and disabled mutation actions.
|
||||
- Target ordering is fixed by product composition rather than dynamically grouped by state.
|
||||
- Target details prioritize current state, evidence, affected scope, permissions, restart risk, and current contextual action. Longer explanation remains scrollable below those facts.
|
||||
- Tab moves focus between dashboard regions. The focused pane or component has a clear non-color-only focus treatment. Arrow keys act within the focused component.
|
||||
- The footer presents only the most important actions for the current focus and state. Complete contextual keyboard help appears in a scrollable Help dialog.
|
||||
- Active Profile switching is available from the dashboard through a searchable modal picker. The Active Profile is pinned first and remaining Profiles sort by name.
|
||||
- Proxy Profile creation, editing, and deletion remain in a dedicated management page, separate from routine activation.
|
||||
- Profile forms use mature text inputs with insertion, deletion, cursor movement, paste, focus styling, and horizontal scrolling.
|
||||
- Validation is structured by field. A changed field updates or clears stale validation feedback instead of leaving unrelated global errors in place.
|
||||
- Bypass editing accepts efficient delimited text and simultaneously renders normalized, deduplicated entries with item-specific validation.
|
||||
- Protocol Probe is an explicit field action with a keyboard shortcut. It remains user-initiated, never runs on save or form entry, and never becomes a general connectivity or latency test.
|
||||
- Protocol Probe progress and results belong to the field that initiated the probe. Results are invalidated when relevant input or mode changes.
|
||||
- Dual HTTP and SOCKS5 detection creates an Advanced Profile with HTTP transport values for HTTP and HTTPS and a GNOME-compatible SOCKS5 value for ALL/SOCKS, preserving the behavior already established in the current implementation.
|
||||
- Disabled, Enabled, External, and Drifted Targets do not share an ambiguous Toggle label. Their primary actions are Enable, Disable, Apply Profile, and Resolve respectively.
|
||||
- Drift Resolution is explicit. It offers reapplication of the Active Profile and restoration of original configuration when ownership evidence permits. Failed ownership checks remain truthful failures and never overwrite externally changed state.
|
||||
- Confirmation dialogs are limited to destructive Profile deletion and disruptive Docker restart paths, including Active Profile switches that require that restart. Cancellation is the default focus.
|
||||
- Target detection at startup and refresh is progressive. The dashboard appears immediately, each Target begins in a Checking state, and rows update independently.
|
||||
- Mutations remain serialized. During a mutation, browsing, selection, details, and Help remain usable, while conflicting mutations and management actions are disabled with an explanation.
|
||||
- Per-Target and Active Profile operations expose structured progress rather than requiring the TUI to parse notice strings.
|
||||
- Active Profile transitions retain successful Target updates when another Target fails. There is no cross-Target rollback. The first failed Target is selected, row states remain truthful, and the current error summary remains visible.
|
||||
- A successful status may be replaced by subsequent activity. An error remains until acknowledged or superseded by an explicit successful resolution of that error.
|
||||
- Current error details may be expanded, but the TUI does not add an activity-history page. Existing bounded, redacted operation logging remains the historical diagnostic surface.
|
||||
- All text crossing into the TUI is defensively redacted immediately before rendering, in addition to lower-layer redaction.
|
||||
- Escape closes a dialog or returns one level. `q` returns from child pages and exits from the dashboard. Ctrl+C requests exit from every page.
|
||||
- Exit during a system operation is deferred until the operation reaches a safe completion. The UI explicitly displays the pending-exit state and rejects new work.
|
||||
- Selection, focus, viewport position, and active dialogs survive terminal resize whenever their referenced item still exists.
|
||||
- The Application Interface may change to represent progressive detection, structured progress, structured current errors, action availability, and Drift Resolution. These changes must remain independent of Bubble Tea presentation types.
|
||||
- Stable Target Adapter configuration and restoration semantics are not redesigned as part of this effort.
|
||||
- Migration proceeds in runnable stages: responsive/theme foundation; dashboard; Profile picker and management; forms/dialogs/Help; status, accessibility, and consistency completion. A long-lived legacy/new TUI switch is not introduced.
|
||||
|
||||
## Testing Decisions
|
||||
|
||||
- Tests assert externally observable behavior through the highest practical seam rather than component implementation, Lip Gloss calls, or private state layout.
|
||||
- The primary seam is the complete TUI Model with an injected fake Application Module. Tests send terminal resize messages, keyboard messages, asynchronous progress messages, and completion results, then assert rendered semantics, focus, visible actions, emitted intents, and navigation outcomes.
|
||||
- Fixed-size render snapshots are produced through the complete Model at representative sizes: a wide 120×36 dashboard, an 80×24 single-column layout, and a 59×15 below-minimum layout.
|
||||
- Render coverage includes light, dark, and `NO_COLOR` modes. Assertions must not rely only on raw ANSI sequences; semantic text and layout remain testable without color.
|
||||
- The secondary seam is the Application Interface. It tests progressive detection, structured progress, serialized mutation, Drift Resolution choices, safe restore refusal, and partial Active Profile transition behavior.
|
||||
- Existing Application Module tests for progressive Profile activation, partial failure without rollback, confirmation, and Target state coordination are prior art and should be extended rather than duplicated at lower seams.
|
||||
- Existing TUI tests that submit keys and inspect rendered output are prior art for the primary seam. They should migrate to the new layout contract rather than preserving obsolete literal views.
|
||||
- Target Adapter tests remain responsible for actual configuration translation, ownership, restoration, permissions, and command sequencing. The redesign does not duplicate those tests in the TUI.
|
||||
- Bubbles and Lip Gloss internals are not unit tested. Small component tests are added only when a pure input boundary cannot be exercised deterministically through the complete Model.
|
||||
- Responsive tests cover resizing in both directions while retaining valid selection, focus, viewport, in-flight state, and dialogs.
|
||||
- List and viewport tests cover enough Targets, Profiles, Help text, and detail text to exceed terminal height.
|
||||
- Content tests cover long Target names, long evidence, long redacted errors, long URLs, long Profile names, and many Bypass entries.
|
||||
- Form tests cover insertion, cursor movement, deletion, paste, horizontal scrolling, field navigation, Single/Advanced transitions, inline validation, Bypass normalization preview, save, and cancel.
|
||||
- Protocol Probe tests cover explicit invocation, in-field progress, HTTP-only, SOCKS5-only, dual-protocol population, failure, unrecognized protocol, credential-safe status, and stale-result invalidation after edits or mode changes.
|
||||
- Status tests cover replaceable success, persistent errors, expanded current details, disabled-action explanations, deferred exit, and removal of stale status after a successful resolution.
|
||||
- Action tests cover contextual Enable, Disable, Apply Profile, and both Drift Resolution branches rather than a generic toggle.
|
||||
- Confirmation tests cover safe default focus, cancellation without mutation, Profile deletion, Docker restart, and confirmation required during Active Profile switching.
|
||||
- Accessibility tests verify that state, focus, progress, warnings, and errors remain understandable with color disabled.
|
||||
- Credential tests inject secrets through Profile fields, malformed URLs, evidence, notices, errors, runner output, and confirmation text, then assert that no rendered frame contains the secret.
|
||||
- Startup tests assert immediate dashboard rendering followed by independent Target detection updates rather than waiting for one aggregate completion.
|
||||
- Busy-state tests assert that browsing remains available, conflicting mutations are disabled, and exit is visibly deferred until safe completion.
|
||||
- Full repository tests remain hermetic and must not mutate real Shell, APT, Docker, GNOME, or systemd state.
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- Mouse input, clickable controls, hover states, or wheel-specific interaction.
|
||||
- Nerd Font or terminal-font installation requirements.
|
||||
- User-selectable theme packs or a theme configuration screen.
|
||||
- Large ASCII logos or decorative animation unrelated to progress.
|
||||
- An in-TUI activity or historical log viewer.
|
||||
- Automatic proxy connectivity tests, latency checks, health monitoring, or background network requests.
|
||||
- Treating Enabled Target state as proof that the proxy endpoint or Internet is reachable.
|
||||
- Changes to Profile persistence format unless independently required by a later specification.
|
||||
- Reworking stable Target-specific proxy translation, file ownership, restoration, permission, or service-control behavior.
|
||||
- Cross-Target rollback after partial Active Profile transition failure.
|
||||
- Parallel system mutations.
|
||||
- Long-term coexistence of legacy and redesigned TUI implementations.
|
||||
- Changes to doctor, reset, Shell integration, release packaging, or non-interactive CLI behavior except where shared Application Interface evolution requires compatibility adaptation.
|
||||
- A graphical desktop interface or web interface.
|
||||
|
||||
## Further Notes
|
||||
|
||||
- The project glossary defines Drift Resolution as the explicit choice between reapplying the Active Profile and restoring original configuration when ownership evidence permits. UI copy and Application intents should use this language consistently.
|
||||
- The throwaway interactive prototype selected **Variant A — Operations Console**: a compact responsive Target list and details layout. Wide terminals use side-by-side panes; narrow terminals stack the same regions vertically. This won over the metric-heavy status board and the single-Target workbench because it preserves complete Target scanability while keeping evidence and actions visible.
|
||||
- The full three-variant prototype is preserved as the primary design source on branch `prototype/tui-operations-console` at commit `364f28d`. Its prototype code must not be promoted directly into production.
|
||||
- The redesign should retain the product's privacy boundary: Protocol Probe is the only user-initiated network handshake, and display of its result must not imply general connectivity.
|
||||
Reference in New Issue
Block a user