first
This commit is contained in:
104
plans/nsigner.md
Normal file
104
plans/nsigner.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# nsigner Implementation Plan
|
||||
|
||||
This document is the implementation roadmap for `n_signer`.
|
||||
|
||||
Authoritative behavior documentation: [README.md](../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](../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)
|
||||
87
plans/nsigner_browser_extension.md
Normal file
87
plans/nsigner_browser_extension.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# nsigner Browser Extension — NIP-07 frontend over nsigner
|
||||
|
||||
> **Project:** subtree of `n_signer` at `browser-extension/` (may spin out later).
|
||||
>
|
||||
> **Status:** Planning. This document describes a WebExtension that exposes [NIP-07](https://github.com/nostr-protocol/nips/blob/master/07.md) `window.nostr` and forwards calls to a running `nsigner` instance.
|
||||
>
|
||||
> **Authoritative signer behavior:** [`../README.md`](../README.md)
|
||||
|
||||
## 1. What this is
|
||||
|
||||
A Chrome/Firefox/Brave WebExtension (Manifest V3) that:
|
||||
|
||||
1. injects a standard NIP-07-compatible `window.nostr` surface
|
||||
2. forwards each call to `nsigner` over native-messaging, TLS, or relay fallback transport
|
||||
3. applies per-origin permission policy and per-origin role pinning
|
||||
|
||||
The extension is not a wallet and holds no private keys.
|
||||
|
||||
## 2. Important compatibility note with multi-purpose roles
|
||||
|
||||
`nsigner` role entries now carry explicit purpose/curve metadata (see [`../README.md`](../README.md)).
|
||||
For browser NIP-07 operations, the extension must request only roles whose purpose resolves to `nostr`.
|
||||
If a role is configured for another purpose (e.g. bitcoin/ssh/age), extension UI must hide or reject it for NIP-07 signing/encryption calls instead of forwarding an invalid request.
|
||||
|
||||
## 3. Architecture (unchanged high level)
|
||||
|
||||
- page -> content script -> service worker
|
||||
- service worker -> chosen transport -> `nsigner`
|
||||
- policy and user prompts in extension UI
|
||||
|
||||
## 4. NIP-07 surface mapping
|
||||
|
||||
Standard NIP-07 calls map to `nsigner` request verbs:
|
||||
|
||||
- `getPublicKey`
|
||||
- `signEvent`
|
||||
- `nip04.encrypt` / `nip04.decrypt`
|
||||
- `nip44.encrypt` / `nip44.decrypt`
|
||||
|
||||
The extension attaches role selector options when needed, but role choices must remain purpose-compatible with Nostr operations.
|
||||
|
||||
## 5. Transport options
|
||||
|
||||
1. Native messaging bridge (primary)
|
||||
2. TLS to local/nearby `nsigner`
|
||||
3. Relay-based fallback
|
||||
|
||||
## 6. Permission model
|
||||
|
||||
Per-origin policy remains the control point:
|
||||
|
||||
- allow/deny by verb/kind/origin
|
||||
- origin-level role pinning
|
||||
- explicit prompts for sensitive operations
|
||||
|
||||
## 7. Security constraints
|
||||
|
||||
- no private key/mnemonic persistence in extension storage
|
||||
- no plaintext decrypt cache
|
||||
- strong defaults for decrypt operations
|
||||
- role purpose compatibility checks before forwarding signer requests
|
||||
|
||||
## 8. Implementation phases (extension-specific)
|
||||
|
||||
1. native helper
|
||||
2. MVP extension with native path
|
||||
3. role-aware UI
|
||||
4. TLS transport
|
||||
5. management/audit UX
|
||||
6. relay fallback transport
|
||||
7. browser polish and release
|
||||
|
||||
## 9. Repo location
|
||||
|
||||
Planned extension subtree remains:
|
||||
|
||||
- `browser-extension/extension/`
|
||||
- `browser-extension/native-bridge/`
|
||||
- `browser-extension/install/`
|
||||
- `browser-extension/tests/`
|
||||
|
||||
## 10. Open questions
|
||||
|
||||
- extension coexistence with other NIP-07 providers
|
||||
- multi-profile signer selection UX
|
||||
- mobile constraints without native messaging
|
||||
- hardware-token pending-confirmation UX in popup
|
||||
135
plans/seed_phrase_uses.md
Normal file
135
plans/seed_phrase_uses.md
Normal file
@@ -0,0 +1,135 @@
|
||||
# Seed Phrase Use Catalog for n_signer
|
||||
|
||||
This document catalogs potential uses of a single memorized BIP-39 seed phrase when mediated through `n_signer` role/purpose/curve controls.
|
||||
|
||||
It is intentionally expansive: some entries are immediate, others are future-facing.
|
||||
|
||||
## 1. Core idea
|
||||
|
||||
A single mnemonic can deterministically derive many key families. `n_signer` treats those as distinct role entries with explicit metadata:
|
||||
|
||||
- purpose
|
||||
- curve
|
||||
- derivation selector/path
|
||||
- policy scope
|
||||
|
||||
This prevents "same seed means same trust domain" mistakes by separating identities at the policy layer.
|
||||
|
||||
## 2. Immediate and near-term domains
|
||||
|
||||
### 2.1 Nostr identities (`purpose="nostr"`)
|
||||
|
||||
- Curve: `secp256k1`
|
||||
- Typical shorthand: `nostr_index` -> `m/44'/1237'/<index>'/0/0`
|
||||
- Uses:
|
||||
- main pub identity
|
||||
- throwaway anti-correlation identity
|
||||
- per-app/per-origin identities
|
||||
- delegated service identities for local systems
|
||||
|
||||
### 2.2 Bitcoin keys (`purpose="bitcoin"`)
|
||||
|
||||
- Curve: `secp256k1`
|
||||
- Typical path families (examples):
|
||||
- BIP44 legacy account trees
|
||||
- BIP49 wrapped-segwit
|
||||
- BIP84 native segwit
|
||||
- BIP86 taproot keypath flows
|
||||
- Uses:
|
||||
- deterministic receive/change branches
|
||||
- per-context account segregation
|
||||
- deterministic recovery for wallet setups
|
||||
|
||||
### 2.3 Lightning-related identity material
|
||||
|
||||
- Curve: usually `secp256k1`
|
||||
- Uses vary by node software and key hierarchy model.
|
||||
- Practical use with `n_signer` should be constrained to explicit purpose-bound role entries, not shared with general signing identities.
|
||||
|
||||
### 2.4 Mesh/service identities (`purpose="fips"` and similar)
|
||||
|
||||
- Curve: primarily `secp256k1` in current planning
|
||||
- Uses:
|
||||
- deterministic node identity roots
|
||||
- stable key-derived addressing inputs
|
||||
- service bootstrapping in reproducible deployments
|
||||
|
||||
## 3. Additional potential domains
|
||||
|
||||
### 3.1 SSH identity material (`purpose="ssh"`)
|
||||
|
||||
- Candidate curves: `ed25519` (primary), potentially others
|
||||
- Uses:
|
||||
- deterministic host/user key regeneration
|
||||
- environment-specific SSH key derivation without storing private keys on disk
|
||||
|
||||
### 3.2 age-style encryption identities (`purpose="age"`)
|
||||
|
||||
- Candidate curves: `x25519` / age-native identity mapping
|
||||
- Uses:
|
||||
- deterministic file encryption identity recovery
|
||||
- reproducible offline decryption setups
|
||||
|
||||
### 3.3 WireGuard-like transport identities
|
||||
|
||||
- Candidate curves: curve25519 family
|
||||
- Uses:
|
||||
- deterministic tunnel identity generation
|
||||
- ephemeral/per-peer derivation schemes (policy-gated)
|
||||
|
||||
### 3.4 PGP/OpenPGP-like profiles (future)
|
||||
|
||||
- Possible but operationally complex due to multipurpose key lifecycles and tooling expectations.
|
||||
- Better treated as explicit, isolated purpose entries if ever added.
|
||||
|
||||
### 3.5 Deterministic password or secret derivation (future)
|
||||
|
||||
- Could derive app/site secrets from role-scoped KDF outputs.
|
||||
- Must never blur boundaries with signing keys; separate purpose namespace and strict export policy required.
|
||||
|
||||
### 3.6 API/service auth tokens (future)
|
||||
|
||||
- Per-service deterministic auth keys (HMAC or asymmetric challenge keys depending on service model).
|
||||
- Strongly policy-scoped to avoid accidental cross-service linkage.
|
||||
|
||||
## 4. Curve and derivation notes
|
||||
|
||||
`n_signer` currently models curve metadata from day one:
|
||||
|
||||
- `secp256k1`
|
||||
- `ed25519`
|
||||
- `x25519`
|
||||
|
||||
Not every purpose should be valid on every curve. Enforcement should be explicit in policy/runtime validation.
|
||||
|
||||
## 5. Operational caveats
|
||||
|
||||
1. **One seed phrase is one root compromise domain**
|
||||
- If the mnemonic is exposed, every derivable domain is exposed.
|
||||
|
||||
2. **Purpose isolation is mandatory**
|
||||
- Reusing one role across unrelated domains collapses privacy and security boundaries.
|
||||
|
||||
3. **Pre-registration requirement matters**
|
||||
- Arbitrary ad-hoc `role_path` requests are too permissive; only pre-registered paths should be derivable by clients.
|
||||
|
||||
4. **Policy must constrain verbs + purposes + roles**
|
||||
- A caller authorized for Nostr signing should not implicitly gain rights for Bitcoin or SSH derivations.
|
||||
|
||||
5. **Auditability and naming discipline are crucial**
|
||||
- Human-readable role names should clearly encode domain intent to avoid operator mistakes.
|
||||
|
||||
## 6. Practical guidance
|
||||
|
||||
Recommended baseline for early deployments:
|
||||
|
||||
- keep `purpose="nostr"` roles as primary production scope
|
||||
- add non-Nostr purposes only when a concrete consumer exists
|
||||
- require explicit approval to register new purpose+path combinations
|
||||
- test recovery procedures per purpose before relying on them operationally
|
||||
|
||||
## 7. Relationship to main docs
|
||||
|
||||
- Product behavior contract: [`README.md`](../README.md)
|
||||
- Implementation sequencing: [`plans/nsigner.md`](nsigner.md)
|
||||
- Browser integration planning: [`plans/nsigner_browser_extension.md`](nsigner_browser_extension.md)
|
||||
Reference in New Issue
Block a user