Files
ai-app/server/Cargo.toml
T
irisandClaude Fable 5 967fc814ab Phase 1 server: TLS + token auth, session registry, EchoDriver, SSE with cursors
The whole pipe behind one Driver trait and a common event model:
spawn/list/delete sessions, message + question answering, append-only
JSONL transcripts whose sequence numbers are the phone's resume cursor
(surviving backend restarts), bearer-token middleware wrapping every
route including the fallback, wg0-only binding that fails closed, and
first-run token enrollment via a terminal QR.

Verified: cargo test (10), clippy clean, and curl end-to-end over pinned
TLS -- auth rejection, spawn, streamed SSE replay/resume, /question
round trip, restart continuing seq numbers, delete removing everything.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017xn8nHw1tw1R6PtiY1eEtw
2026-08-24 20:51:34 -04:00

38 lines
1.2 KiB
TOML

[package]
name = "ai-server"
version = "0.1.0"
edition = "2024"
[[bin]]
name = "ai-server"
path = "src/main.rs"
[dependencies]
axum = { version = "0.8", features = ["json"] }
axum-server = { version = "0.8", features = ["tls-rustls"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros", "net", "sync", "time"] }
tokio-stream = "0.1"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
clap = { version = "4", features = ["derive"] }
anyhow = "1"
thiserror = "2"
# Token auth: hash for storage, constant-time compare for verification,
# CSPRNG-backed generation, base64url for the enrollment string.
sha2 = "0.11"
subtle = "2"
rand = "0.10"
base64 = "0.23"
# Renders the enrollment QR straight to the terminal; no image output needed.
qrcode = { version = "0.14", default-features = false }
# The wg0-bound listener needs the interface's address; the stdlib has no
# getifaddrs. This is the smallest crate that wraps just that.
if-addrs = "0.15"
[dev-dependencies]
tempfile = "3"
# ServiceExt::oneshot, to drive the auth middleware without a socket.
tower = { version = "0.5", features = ["util"] }