4.5 KiB
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.candsrc/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
- Single foreground process replaces daemon + TUI + client multi-binary model
- No config files — all state entered at runtime, lives in RAM only
- Abstract namespace sockets replace filesystem sockets
- Control socket eliminated — TUI is in-process
- Policy simplified to same-uid default + interactive approval
- Crash = total wipe is a security feature, not a limitation
- Same core modules target both Linux desktop and ESP32 MCU
2026-05-02 — Earlier decisions (retained)
role_pathmust be pre-registered (no ad-hoc derivation)nostr_indexnaming (notrole_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)