Resolved all 11 open questions based on project guidance: Transport: - OQ-01/OQ-07: ACME/Let's Encrypt with domain + IP paths (ADR-008) - OQ-02: Default to n0 relay, --iroh-relay override (ADR-009) - OQ-05: Transport chaining supported natively (ADR-010) Client: - OQ-06: Programmatic-first API, no ~/.ssh/config (ADR-011) Server: - OQ-04: Ed25519 + OpenSSH cert-authority, no password auth (ADR-012) - OQ-08: fail2ban-friendly logging + built-in rate limiting (ADR-013) TUN: - OQ-03/OQ-09: Deferred entirely, recommend tun2proxy (ADR-014) - tun-shim.md marked deprecated NAPI: - OQ-10: Expose both connect() and serve() (ADR-016) - OQ-11: Use napi-rs for FFI bridge (ADR-015) Additional ADRs created during review: - ADR-006: No logging of tunnel destinations (was phantom reference) - ADR-017: Stealth mode protocol multiplexing - ADR-018: Control channel for pubsub over SSH Fixed: ADR-002 status → Superseded, ADR-007 title typo, WRAUTH_SERVER typo, ADR-005 stale wraith-tun refs, undefined ACL feature removed from server.md, --proxy semantic difference documented.
2.3 KiB
2.3 KiB
ADR-011: Programmatic-First API, No File-Based Config
Status
Accepted
Context
The client and server both need configuration (host addresses, keys, transport options, etc.). There are several approaches:
- Read
~/.ssh/config: Parse OpenSSH config for default host/key/port. Reduces CLI verbosity for frequent connections. - Custom config file: Wraith-specific config file (TOML/YAML) with host definitions.
- Programmatic API only: Configuration comes from CLI flags or the library API. No file parsing.
~/.ssh/path conventions are cross-platform trouble (~expansion, Windows paths, etc.). - Hybrid:
--configflag pointing to a wraith-specific config file, but no OpenSSH config parsing.
Decision
Option 3: Programmatic-first API. Configuration is provided via:
- CLI: explicit flags (
--server,--identity,--transport, etc.) - Library API:
wraith_core::client::ConnectOptionsandwraith_core::server::ServeOptionsstructs, constructable programmatically - Environment variables: for a few convenience defaults (e.g.,
WRAITH_SERVER,WRAITH_IDENTITY)
No ~/.ssh/config parsing, no wraith-specific config files. This approach:
- Avoids cross-platform path issues (
~expansion, WindowsUSERPROFILE, etc.) - Makes the library API clean and straightforward for programmatic consumers (NAPI wrapper, pubsub)
- Keeps the CLI simple and explicit — no hidden behavior from config files
- Matches the design principle that the library crate (
wraith-core) is the primary interface
If users want config-file behavior in the future, it can be added as a separate layer that populates the options structs. But the core doesn't need to know about files.
Consequences
- Positive: Clean library API —
ConnectOptionsandServeOptionsare plain Rust structs. - Positive: No cross-platform path issues in the core library.
- Positive: Explicit CLI — no hidden settings from a config file the user forgot about.
- Positive: NAPI wrapper can construct options programmatically without file I/O.
- Negative: Users must type full connection flags each time. Mitigated by shell aliases or environment variables.
- Negative: No config file convenience. Users coming from
ssh configmay find this inconvenient.