Commit Graph

12 Commits

Author SHA1 Message Date
DuProcess 8b1af51bc6 Persist sessions across server restarts via per-session holders
Make dosh terminal sessions survive a dosh-server restart
(crash/upgrade/systemctl restart): a reattaching client lands on the
SAME shell with screen state intact, instead of a fresh one.

Design: when persist_sessions is on (new config, default true) each
terminal session's shell runs in a small detached per-session holder
process (the dosh-server binary re-exec'd as `dosh-server hold`). The
holder double-forks + setsid into its own session, opens the PTY, spawns
the shell as ITS child, and serves the PTY master fd over a per-session
Unix socket via SCM_RIGHTS. The server adopts that fd to build a PtyHandle
that DETACHES (does not kill the shell) on drop, so a server exit leaves
holder + shell alive. On startup the server scans the runtime dir under
sessions_dir/run, reconnects to each live holder, receives the master fd
again, restores the persisted vt100 screen, and rebuilds the Session.

Screen/scrollback (server-memory only) is mirrored to disk atomically:
byte-throttled on the output hot path plus a 2s periodic flush, and
restored on re-adoption so reattach repaints. Truly-abandoned persistent
sessions are still reaped per the existing grace logic by asking the
holder to shut down. Anything in the persistent path failing degrades
gracefully to the original in-process shell.

PtyHandle gains an Owned (kill-on-drop, unchanged default) vs Adopted
(detach-on-drop) backing; resize on an adopted master uses TIOCSWINSZ.

No wire-format change, so protocol::VERSION stays 3. New deps: libc
(direct). New config: persist_sessions (default true); existing
integration tests pin it false to keep exercising the non-persistent
path unchanged.

Adds tests/integration_smoke.rs::session_survives_server_restart_same_
shell_and_screen: attaches, sets `cd /tmp; export MARK=...`, paints a
screen marker, KILLs the server, restarts it on the same config, reattaches
and asserts same shell pid + MARK + PWD + restored screen. Plus persist.rs
unit tests (name round-trip, screen save/load, dead-holder scan cleanup,
SCM_RIGHTS fd round-trip). cargo fmt --check and cargo test green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 14:19:09 -04:00
DuProcess 9a52d65beb Add opt-in, security-gated SSH-agent forwarding
Item 3: SSH-agent forwarding, double-gated (client -A/forward_agent AND server
allow_agent_forwarding) and off by default on both ends.

Wire: new ForwardingKind::Agent (appended, existing bincode discriminants
unchanged). Bumped protocol VERSION 2 -> 3 so a pre-agent peer answers with a
clear version-mismatch reject instead of a deserialize error.

Client: -A / --forward-agent flag; requires local SSH_AUTH_SOCK. Requests an
Agent forwarding during native auth (agent forwarding requires native auth) and,
on a server-initiated StreamOpen carrying the reserved @dosh-agent sentinel,
splices the stream into the local agent unix socket (separate agent_writers map,
TCP forwarding paths untouched). Rejects agent StreamOpens unless it opted in, so
a server cannot reach the agent without consent.

Server: when the client opted in and allow_agent_forwarding is set, binds a
per-session proxy unix socket (dir 0700, socket 0600) before the shell spawns,
exports its path as the session's SSH_AUTH_SOCK, and tunnels each connection back
to the client over the agent sentinel stream. Applies only to freshly spawned
shells (documented). Socket cleaned up on auth/forward failure and when the
accept loop ends. SECURITY rationale documented in comments.

Tests: 2 end-to-end integration tests (full chain identities round-trip via a
PTY-hosted client + looping fake agent; and "no -A => no proxy socket"). Docs
updated (README forwarding + disconnect-status note, spec §12.1). fmt + full test
suite green (122 tests).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 11:10:44 -04:00
DuProcess c47ae98c68 Merge track C: benchmark path matrix + safe local harness + BENCHMARKS.md 2026-06-14 10:34:30 -04:00
DuProcess c48f2280a0 Add benchmark path matrix and safe local harness
Extend dosh-bench to benchmark the full attach path matrix and emit both raw
per-iteration samples and summary statistics (count/min/median/p95/mean/max):

- --cold-native:   native cold auth terminal-ready (dosh_cold_native_ms)
- --cached-ticket: cached attach-ticket fast path (dosh_cached_attach_ms)
- --resume:        UDP resume path (dosh_resume_ms; roaming-only, see docs)
- --local-auth:    self-contained local bootstrap, no SSH (dosh_local_attach_ms)
- default:         legacy SSH-bootstrap cold attach (dosh_attach_ms)

Existing ssh-bootstrap/local-auth/mosh modes and all assert gates are preserved;
legacy flags (--local-auth/--warm-cache/--no-cache) keep their prior behavior so
the CI docker scripts run unchanged. Add --json (machine-readable raw samples)
and --label. Add a table/JSON renderer and percentile-based summary stats.

Add scripts/bench-local.sh: a safe, self-contained harness that builds release,
spins up a throwaway dosh-server bound to 127.0.0.1 on a random free UDP port in
a temp HOME (never port 50000, never a systemd unit), runs the matrix, prints
results, sanity-checks native auth actually trusted the host, and cleans up.

Point `make bench-local` at the new harness and add `make bench-local-json`;
keep bench-docker-* targets intact.

Add docs/BENCHMARKS.md: how to run each benchmark, metric meanings, methodology
and caveats (resume is the roaming path, not cold reconnect; cite cached attach
as the core claim per PUBLIC_READINESS.md), plus a real loopback sample table
with machine/OS/sample-count and raw samples.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 10:33:37 -04:00
DuProcess 828206f757 Publish threat model and refresh native v1 docs
Add docs/THREAT_MODEL.md deriving a publishable threat model from
NATIVE_V1_SPEC.md sections 4-6: assets, in/out-of-scope attackers,
security properties vs SSH (including where Dosh aims to exceed it),
cryptographic building blocks as implemented, and an honest
accepted-residual-risks / known-gaps section.

Refresh docs/PUBLIC_READINESS.md: feature matrix now reflects native
auth, host-key trust, authorized_keys policy, doctor, and -L/-R/-D
forwarding; add a per-item "Native v1 verification checklist status"
table mapping spec section 16 to done/in-progress/pending from code.

Update README.md status with a native v1 section and honest claim
posture pointing to THREAT_MODEL.md. Annotate NATIVE_V1_SPEC.md with a
v1 status block summarizing milestone progress. Point SPEC.md security
model and header at native auth and the threat model.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 10:27:40 -04:00
DuProcess 6c14d669b8 Gate non-loopback remote binds
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-14 09:10:09 -04:00
DuProcess f66de64b3f Support host-config login users
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 22:32:45 -04:00
DuProcess 1b1278f39e Add explicit environment propagation
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 22:30:15 -04:00
DuProcess f6ab4473bd Define native Dosh workflow parity requirements
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 11:25:52 -04:00
DuProcess 9bece26bc8 Spec native Dosh auth and forwarding v1
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-13 10:54:19 -04:00
DuProcess 93374162ff Measure cached Dosh attach fast path
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-12 22:45:13 -04:00
DuProcess 3a38a9da80 Add public comparison benchmarks and SSH import
ci / test (push) Has been cancelled
ci / remote-bench (push) Has been cancelled
2026-06-12 14:27:58 -04:00