Files
DodoSSH/README.md
T
jaap-jan ce43f397a6 Add ADRs 0001-0006 and README (M0)
Records the decisions the milestone plan already made, with their costs stated rather
than only their benefits:

- 0001 e2ee-trust-model: key hierarchy, the AAD-to-row binding that stops the server
  moving ciphertext between rows, and the four-layer public-key trust story. States
  plainly that revocation is not retroactive, that Connect cannot be a security
  boundary, and that the IdP becomes a key-distribution trust root.
- 0002 minimal-apis: feature modules with explicit registration; capability negotiation
  instead of Asp.Versioning, since client and server upgrade independently when
  self-hosted.
- 0003 sync-protocol: single write path, revision cursors, and the bigserial
  pre-commit sequence gap that silently corrupts sync — plus the per-vault advisory
  lock that fixes it and the test that must prove it.
- 0004 relay-authorization: relay forwards bytes rather than terminating SSH, so
  zero-knowledge survives; server-resolved target IPs in the ticket to defeat DNS
  rebinding; why host addresses must be plaintext when relay is enabled.
- 0005 no-application-layer: why the usual Application/mediator layer earns nothing
  here, with the trigger that would make us revisit it.
- 0006 observability-stack: OTel plus built-in ILogger; liveness excludes dependencies
  so a database blip cannot restart the container and kill live SSH sessions.

Also adds a README covering layout, build, enforced conventions and milestones.
2026-07-28 12:28:44 +02:00

97 lines
3.7 KiB
Markdown

# DodoSSH
A self-hosted, team-oriented SSH client with an end-to-end encrypted vault.
Manage hosts, credentials and keys in a desktop app; sync them across your devices and share
them with teammates through a server you run yourself. **The server stores ciphertext and never
holds a key** — the operator cannot read the credentials it stores.
> Status: early development. See [the milestone plan](#milestones) for what exists today.
## Why
Teams either scatter SSH credentials across individual `~/.ssh` directories with no sharing
story, or pay per-seat for a hosted product that holds their infrastructure credentials.
DodoSSH keeps the convenience of a synced, shareable vault while remaining self-hostable and
zero-knowledge.
## Architecture
| Component | Choice |
| --- | --- |
| Backend | ASP.NET Core on .NET 10, PostgreSQL + EF Core |
| Client | Avalonia (C#) for Windows/Linux/macOS; terminal pane is a WebView running xterm.js |
| Auth | OIDC, provider-agnostic (Entra ID, Keycloak, Auth0, Authentik) |
| Vault | End-to-end encrypted; X25519 + Ed25519 + XChaCha20-Poly1305, Argon2id unlock |
| Connections | Client-direct SSH by default, with an optional raw-TCP server relay |
Two consequences worth knowing before you read further:
- **Revocation is not retroactive.** A removed member keeps what they already downloaded. The
real remediation is rotating the SSH credential, so offboarding is built around a rotation
checklist rather than a button that implies more than it delivers.
- **No session recording in relay mode.** The relay forwards SSH ciphertext, so it cannot see
commands. That is the cost of the relay not being able to read your traffic.
The reasoning behind each major decision is recorded in [`docs/adr/`](docs/adr/), starting with
[the E2EE trust model](docs/adr/0001-e2ee-trust-model.md).
## Repository layout
```
src/
DodoSSH.Contracts DTOs shared with the client — the real API contract
DodoSSH.Crypto DSH1 envelope, AAD derivation, key wrapping
DodoSSH.Domain entities and invariants, no EF
DodoSSH.Infrastructure DbContext, configurations, migrations
DodoSSH.Api the host
tests/ one test project per source project
docs/adr/ architecture decision records
```
## Building
Requires the .NET SDK pinned in [`global.json`](global.json) (10.0.x).
```bash
dotnet build DodoSSH.slnx
```
```bash
dotnet test DodoSSH.slnx
```
Run the API locally:
```bash
dotnet run --project src/DodoSSH.Api
```
It listens on `http://localhost:5233`, serving `/healthz/live`, `/healthz/ready` and — in
Development — `/openapi/v1.json`.
### Conventions the build enforces
- Warnings are errors. `dotnet format --verify-no-changes` gates CI.
- Package versions are centralised in `Directory.Packages.props`; `packages.lock.json` is
committed and CI restores in locked mode.
- [`BannedSymbols.txt`](BannedSymbols.txt) bans `DateTime.UtcNow` (use `TimeProvider`),
`Guid.NewGuid` (use `CreateVersion7`), sync-over-async, MD5/SHA1 and PBKDF2.
- Public members of `DodoSSH.Contracts` must be declared in `PublicAPI.Unshipped.txt`, so a
contract change is a build error rather than a client-side surprise.
## Milestones
- **M0 — foundation.** Repo structure, build conventions, CI, ADRs. *Done.*
- **M1 — vertical slice.** OIDC login → enroll → create a host → open a shell. Gated on
freezing `DodoSSH.Contracts` and the crypto AAD, plus two client spikes (Linux WebView,
SSH.NET window-change).
- **M2 — full personal vault**, robust sync, relay.
- **M3 — teams**, sharing, ACLs.
- **M4 — hardening and ops**, packaging, self-hosting guide.
- **M5 — multi-provider OIDC**, key rotation, per-item content keys.
## Licence
Not yet chosen.