v0.0.54 - TUI: show full derivation path in Roles table, move connection instructions to on-demand 'd' hotkey display with spaced transport blocks

This commit is contained in:
Laan Tungir
2026-07-20 09:49:20 -04:00
parent 0b0ec5eb1a
commit a0a5987ffa
3 changed files with 449 additions and 70 deletions

View File

@@ -0,0 +1,151 @@
# Plan: Move Connection Instructions to On-Demand Display
## Problem
The Connections section in the running TUI is verbose and confusing. It mixes server addresses with client command examples, and when multiple transports are active (Unix + TCP + HTTP) it takes up a large chunk of the status screen, pushing the Roles and Activity sections down. The connection instructions are only needed once when a user wants to know how to reach the signer — they don't need to be permanently visible.
## Solution
Remove the Connections section from the default `render_status()` display. Add a new hotkey **`d`** (display connection instructions) that prints the connection info on demand, then returns to the normal status view on the next refresh/keystroke.
## Design
### Default status display (after change)
The Connections section is removed. The display shows: Roles, Activity, status line, hotkey menu. A one-line hint at the top reminds the user that `d` shows connection instructions.
```text
================================================================================
n_signer v0.0.53
================================================================================
> Main Menu
Press d for connection instructions
Roles
Role Purpose Curve Selector
-------------------- ------------ ------------ ------------
main nostr secp256k1 nostr_index
ops nostr secp256k1 nostr_index
backup bitcoin secp256k1 role_path
Activity (latest first)
16:03:11 allow caller=uid:1000 method=get_public_key role=main
16:02:44 prompt caller=uid:1000 method=sign_event role=ops
16:02:46 allow caller=uid:1000 method=sign_event role=ops
15:59:10 deny caller=uid:1001 method=sign_event error=unauthorized
session=unlocked (12 words) signer=nsigner_hairy_dog derived=3 auto-approve=OFF
l lock/reunlock
r refresh
a toggle auto-approve
d display connections
q/x quit
```
### On-demand connection display (press `d`)
When the user presses `d`, the screen clears and shows **only** the connection instructions, with clear spacing between transports. Each transport block shows the **connection string** (the address/endpoint to reach), a blank line, then an **Example:** with the client command indented beneath. No "Server:" / "Client:" labels — just the address and an example. A footer tells the user how to return.
```text
================================================================================
n_signer v0.0.53
================================================================================
> Connection Instructions
Unix socket
@nsigner_hairy_dog
Example:
nsigner --socket-name nsigner_hairy_dog client '<json>'
Qrexec (bridge-source-trusted):
qrexec-client-vm <target_qube> qubes.NsignerRpc
FIPS
http://npub10vt4scusw6lq27qw83nfwp5sqer492h0tnwa8ugqjvp6l4xuz2qsdycrwd.fips:11111
Example:
curl -X POST http://npub10vt4scusw6lq27qw83nfwp5sqer492h0tnwa8ugqjvp6l4xuz2qsdycrwd.fips:11111/ \
-H 'Content-Type: application/json' \
-d '<json>'
HTTP
http://127.0.0.1:11112
Example:
curl -X POST http://127.0.0.1:11112/ \
-H 'Content-Type: application/json' \
-d '<json>'
OTP pad: 333e9902db839d9d... (offset 288 / 1048576 bytes)
session=unlocked (12 words) signer=nsigner_hairy_dog derived=3 auto-approve=OFF
Press any key to return
```
### Key differences from current display
1. **Spacing between transports** — each transport gets its own titled block with blank lines separating it from the next, instead of a flat list of `Server:` / `Client:` lines.
2. **Connection string + example, no labels** — each block shows the bare connection string (e.g. `http://127.0.0.1:11112`), then an `Example:` with the client command indented beneath. No confusing "Server:" / "Client:" labels.
3. **On-demand only** — the default running display no longer shows connections at all, just a one-line hint. The user presses `d` when they need the instructions, reads them, then presses any key to return.
4. **OTP pad status** — shown at the bottom of the connection display (it's connection-related: which pad is bound and how much has been consumed).
## Implementation Steps
1. **[`src/main.c`](src/main.c) — `render_status()`** (line 1451):
- Remove the Connections section (lines 1464-1471).
- Add a one-line hint after the top frame: `tui_print("Press d for connection instructions");`
- Add a blank line after the hint.
2. **[`src/main.c`](src/main.c) — new function `render_connections()`**:
- Clears the screen and renders the top frame.
- Iterates `g_connection_info` but formats it with the spaced layout shown above. Since `g_connection_info` already stores formatted strings like `"Server: unix @nsigner_hairy_dog"` and `" Client: nsigner --socket-name ... client '<json>'"`, either:
- **Option A**: Reformat the stored strings into blocks by detecting `Server:` lines as transport boundaries and printing blank lines + indentation.
- **Option B**: Store connection info in a structured form (transport type, server address, client command(s)) and render the block layout from the structured data.
- Option B is cleaner but requires changing `connection_info_add()` and all its call sites. Option A is a smaller change. **Recommend Option A** for now — parse the existing flat list into blocks.
- **FIPS section**: The connection string is the npub-based FIPS URL (`http://<npub>.fips:<port>`), which FIPS resolves to the signer's TCP endpoint. The example uses `curl` since FIPS makes the endpoint HTTP-reachable for clients with FIPS installed. The raw TCP bind address (`tcp:[::]:11111`) is not shown — it's an implementation detail; the npub URL is what clients use.
- Print OTP pad status if bound.
- Print the status line at the bottom.
- Print "Press any key to return" footer.
3. **[`src/main.c`](src/main.c) — `g_main_menu_items`** (line 825):
- Add `{"^_d^: display connections", 'd'}` to the menu array.
4. **[`src/main.c`](src/main.c) — event loop** (line ~3068, the stdin keystroke handler):
- Add a case for `'d'`:
- Call `render_connections()`.
- Read one keystroke from stdin (blocking `read()`).
- Call `render_status()` to return to the normal display.
5. **[`README.md`](README.md) §3.2**:
- Update the example TUI layout to match the new default display (no Connections section, `d` in hotkeys).
- Add a note that pressing `d` shows the connection instructions.
6. **[`api.md`](api.md) §5 Transports**:
- No changes needed — the transport documentation is already separate from the TUI display.
## Files Changed
| File | Change |
|------|--------|
| [`src/main.c`](src/main.c) | Remove Connections from `render_status()`, add `render_connections()`, add `d` hotkey + menu item + event loop case |
| [`README.md`](README.md) | Update §3.2 example display to match new layout |
| [`api.md`](api.md) | No changes |
## Verification
- `make dev` builds clean.
- Start nsigner with all transports selected. Default display shows no Connections section, just the "Press d for connection instructions" hint.
- Press `d` — connection instructions appear with clear spacing between transports.
- Press any key — returns to normal status display.
- All other hotkeys (`l`, `r`, `a`, `q`) still work.