Proving who somebody is and starting a session for them are separate operations. login_with_caldav does the first by asking the CalDAV server whether the credentials work; begin_session does the second and knows nothing about how the question was answered. OIDC arrives as a second way to reach begin_session, not as a second scheme threaded through everything -- which is what v1 had, with a JWT for most of the app and a separate SQLite session_token used only by the preferences API. The token lives in an HttpOnly cookie and nowhere else. v1 kept a JWT and the CalDAV password in localStorage, readable by any script on the origin, and re-sent the password in a header on every request. Here the password never leaves the server: it is encrypted with XChaCha20-Poly1305 and caldav_for is the only path back, handing out a client rather than a credential. Failed decryption is an error, not a subtly wrong password -- the AEAD tag is checked, so a tampered row surfaces here instead of as a mysterious CalDAV rejection later. A wrong password and an unreachable server stay distinct, because telling somebody their password is wrong when the server is down sends them to reset one that was fine. Errors carry a stable code alongside their message, so a client can branch on them. Internal ones say nothing about the inside of the server; the detail goes to the log. Tests go through router(), the same function main calls -- v1's suite rebuilt the route table and tested a copy until it stopped compiling. Skipping is now loud: a skipped test reports "ok", so run.sh sets RUNWAY_REQUIRE_CALDAV=1 and not running becomes a failure.
37 lines
1.0 KiB
TOML
37 lines
1.0 KiB
TOML
[package]
|
|
name = "runway-server"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
license.workspace = true
|
|
description = "Axum backend: CalDAV proxy, sessions, preferences, ICS feeds."
|
|
|
|
[dependencies]
|
|
runway-core = { workspace = true, features = ["ical", "recurrence"] }
|
|
runway-caldav = { workspace = true }
|
|
axum = { workspace = true }
|
|
axum-extra = { workspace = true }
|
|
base64 = { workspace = true }
|
|
chacha20poly1305 = { workspace = true }
|
|
time = "0.3"
|
|
rand = { workspace = true }
|
|
chrono = { workspace = true }
|
|
serde = { workspace = true }
|
|
serde_json = { workspace = true }
|
|
sha2 = { workspace = true }
|
|
sqlx = { workspace = true }
|
|
thiserror = { workspace = true }
|
|
tokio = { workspace = true }
|
|
tower = { workspace = true }
|
|
tower-http = { workspace = true }
|
|
tracing = { workspace = true }
|
|
tracing-subscriber = { workspace = true }
|
|
uuid = { workspace = true }
|
|
|
|
[dev-dependencies]
|
|
reqwest = { workspace = true }
|
|
pretty_assertions = { workspace = true }
|
|
tower = { workspace = true, features = ["util"] }
|
|
|
|
[lints]
|
|
workspace = true
|