Files
runway/Cargo.toml
T
connor f8e4a497fa Add the CalDAV client and a CLI to drive it
Discovery is the three PROPFINDs RFC 4791 describes rather than a walk
through likely URLs. Queries use time-range, which v1 never did -- it
fetched whole calendars and filtered in the browser on every view change.
Every write states a precondition, so a stale ETag produces a Conflict a
caller can act on instead of silently destroying somebody's edit.

XML goes through quick-xml with namespace resolution. v1 matched prefixes
with six regexes tried in sequence and recompiled inside the loop; there
is a fixture here that is the same document under different prefixes, and
it parses identically.

Protocol parsing is split from transport so it can be tested against
responses recorded from a real Baikal -- including the second propstat
carrying 404s, which is what makes "this calendar has no colour" different
from "this calendar has an empty colour".

Live tests run against a real server, never a mock. tests/baikal/run.sh
starts a container, walks Baikal's install wizard, and runs them; each
test builds and destroys its own collection, so pointing it at a real
server touches nothing that was already there. They cover discovery,
round-trip, stale-ETag conflict, duplicate create, delete, time-range
filtering, a series returned whole with its override, and writing every
synthetic golden fixture to the server and reading it back.

libdav was evaluated first, as planned. Not adopted: its HttpClient trait
is defined over hyper::body::Incoming, so using it means replacing reqwest
everywhere, plus a DNS resolver for service discovery we do not do and a
second XML parser. Its precondition design is where Precondition's shape
comes from. Reasons are recorded in the crate docs.
2026-08-26 15:32:08 -04:00

72 lines
1.7 KiB
TOML

[workspace]
resolver = "3"
members = [
"crates/runway-core",
"crates/runway-caldav",
"crates/runway-server",
"crates/runway-web",
"crates/runway-cli",
]
[workspace.package]
version = "0.1.0"
edition = "2024"
license = "MIT"
repository = "https://github.com/connorjohnstone/runway"
[workspace.lints.rust]
dead_code = "deny"
unused_must_use = "deny"
unsafe_code = "forbid"
[workspace.lints.clippy]
# v1 had 65 of these. Tests opt out locally.
unwrap_used = "deny"
expect_used = "deny"
[workspace.dependencies]
# Internal
runway-core = { path = "crates/runway-core" }
runway-caldav = { path = "crates/runway-caldav" }
# Core data
chrono = { version = "0.4", default-features = false, features = ["serde", "clock", "std"] }
chrono-tz = { version = "0.10", features = ["serde"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
uuid = { version = "1", features = ["v4", "serde"] }
# Calendar domain
icalendar = "0.17"
rrule = "0.14"
# Errors + logging
thiserror = "2"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
# Backend
axum = "0.8"
tokio = { version = "1", features = ["rt-multi-thread", "macros", "net", "signal"] }
tower = "0.5"
tower-http = { version = "0.6", features = ["cors", "trace"] }
sqlx = { version = "0.9", features = ["runtime-tokio", "sqlite", "chrono", "uuid", "migrate"] }
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
quick-xml = "0.42"
# Frontend
leptos = "0.8"
leptos_router = "0.8"
# CLI
clap = { version = "4", features = ["derive", "env"] }
# Dev
pretty_assertions = "1"
[profile.release]
opt-level = "z"
lto = true
codegen-units = 1
strip = true