Files
n_signer/plans/tui_display_connections_on_demand.md

7.3 KiB

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.

================================================================================
                                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.

================================================================================
                                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.crender_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 — 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.cg_main_menu_items (line 825):

    • Add {"^_d^: display connections", 'd'} to the menu array.
  4. 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 §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 §5 Transports:

    • No changes needed — the transport documentation is already separate from the TUI display.

Files Changed

File Change
src/main.c Remove Connections from render_status(), add render_connections(), add d hotkey + menu item + event loop case
README.md Update §3.2 example display to match new layout
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.