Files
n_signer/plans/nsigner.md
Laan Tungir 268b33b6d3 first
2026-05-02 12:31:26 -04:00

4.5 KiB

nsigner Implementation Plan

This document is the implementation roadmap for n_signer.

Authoritative behavior documentation: README.md.

1. Architecture pivot: program not daemon

This plan adopts a single foreground program model instead of a daemon model to reduce operational complexity and eliminate persistent runtime artifacts.

  • Single foreground process, not a background daemon
  • No config files — all state entered at runtime via TUI
  • No control socket — TUI is built into the program
  • No separate binaries — one binary with subcommands
  • Abstract namespace sockets — no filesystem artifacts

2. Module inventory (what exists, what stays, what goes)

Module Fate
src/secure_mem.{h,c} KEEP unchanged
src/mnemonic.{h,c} KEEP unchanged
src/role_table.{h,c} KEEP data structures, REMOVE file-loading code
src/selector.{h,c} KEEP unchanged
src/enforcement.{h,c} KEEP unchanged
src/dispatcher.{h,c} KEEP unchanged
src/cjson/ KEEP unchanged
src/policy.{h,c} REFACTOR: remove file loading, add interactive approval, hardcode same-uid default
src/daemon.{h,c} REPLACE with src/server.{h,c}: abstract namespace socket, poll-based, integrated with TUI
src/control.{h,c} DELETE (control socket no longer needed)
src/tui.c DELETE as separate binary (functionality moves into src/main.c)
src/client.c DELETE as separate binary (becomes subcommand in src/main.c)
src/main.c REWRITE: startup TUI + server loop + status display + client subcommand
config/ DELETE entirely
tests/test_daemon_integration.c DELETE or rewrite
tests/test_full_flow.c REWRITE for new architecture
tests/test_policy.c UPDATE for new policy API

3. Implementation phases (new)

Phase A — Cleanup and removal

  • Delete config/, src/control.{h,c}, src/tui.c, src/client.c
  • Remove file-loading functions from src/role_table.c and src/policy.c
  • Remove old daemon integration tests

Phase B — Server module (replaces daemon)

  • Add src/server.{h,c}: abstract namespace socket, poll-based accept loop
  • Keep peer-cred extraction behavior on abstract socket
  • Add integration point for TUI approval callbacks

Phase C — Unified main with built-in TUI

  • Startup phase: mnemonic prompt (echo off), word count confirm, optional role enrollment
  • Transition to running phase: status display, activity log, hotkey handling
  • Approval prompt overlay when policy requires it
  • Client subcommand: nsigner client '<json>' connects to abstract socket, sends request, prints response
  • Signal handling: SIGINT/SIGTERM → zeroize and exit

Phase D — Policy simplification

  • Default policy: same-uid as process = allow all verbs on all roles, no prompt
  • Unknown caller: display approval prompt in TUI, user decides per-request or per-session
  • No file-based policy at all

Phase E — Integration test

  • Single test that launches the program (with mnemonic piped via stdin for automation), sends requests via client subcommand, verifies responses

4. Decisions log

2026-05-02 — Program not daemon pivot

  1. Single foreground process replaces daemon + TUI + client multi-binary model
  2. No config files — all state entered at runtime, lives in RAM only
  3. Abstract namespace sockets replace filesystem sockets
  4. Control socket eliminated — TUI is in-process
  5. Policy simplified to same-uid default + interactive approval
  6. Crash = total wipe is a security feature, not a limitation
  7. Same core modules target both Linux desktop and ESP32 MCU

2026-05-02 — Earlier decisions (retained)

  • role_path must be pre-registered (no ad-hoc derivation)
  • nostr_index naming (not role_index)
  • Multi-curve support from start (secp256k1, ed25519, x25519)
  • README.md is authoritative behavior spec

5. Open questions

  • Automated test strategy for interactive TUI (stdin pipe? expect-style? separate test mode flag?)
  • ESP32 transport shim interface definition
  • NIP-46 relay transport integration timeline
  • Role enrollment UX: how many questions at startup vs. "just use main = index 0"?
  • Lock-without-exit: needed? Or is quit-and-relaunch sufficient?

6. Immediate next work

  • Execute Phase A (cleanup)
  • Execute Phase B (server module)
  • Execute Phase C (unified main)
  • Execute Phase D (policy simplification)
  • Execute Phase E (integration test)