Set up workspace skeleton

Five crates: runway-core (pure domain), runway-caldav (protocol),
runway-server (axum), runway-web (leptos), runway-cli (smoke tool).

runway-core is feature-gated into model/ical/recurrence so the frontend
can depend on the shared types without pulling icalendar and rrule into
the WASM bundle. The previous iteration shipped reqwest, ical and regex
to the browser for a dead module; the feature split makes that mistake
structurally hard to repeat.

Guardrails are compiler- and CI-enforced rather than aspirational:
workspace lints deny unwrap_used/expect_used, dead_code and unsafe_code,
clippy.toml caps function length and arity, deny.toml pins licences.

Toolchain is pinned per-project so the machine-wide default is untouched.
Cargo.lock is committed this time.

docs/legacy-audit.md carries the marked-up feature decisions and is the
spec for the rewrite.
This commit is contained in:
2026-08-26 12:07:44 -04:00
commit bf63024711
20 changed files with 4272 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
[package]
name = "runway-caldav"
version.workspace = true
edition.workspace = true
license.workspace = true
description = "CalDAV client: discovery, time-ranged queries, ETag-aware CRUD."
[dependencies]
runway-core = { workspace = true, features = ["ical"] }
chrono = { workspace = true }
quick-xml = { workspace = true }
reqwest = { workspace = true }
serde = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }
[dev-dependencies]
tokio = { workspace = true }
[lints]
workspace = true
+1
View File
@@ -0,0 +1 @@
//! CalDAV client: discovery, time-ranged queries and ETag-aware CRUD.
+17
View File
@@ -0,0 +1,17 @@
[package]
name = "runway-cli"
version.workspace = true
edition.workspace = true
license.workspace = true
description = "Smoke tool for exercising a real CalDAV server from the terminal."
[dependencies]
runway-core = { workspace = true, features = ["ical", "recurrence"] }
runway-caldav = { workspace = true }
chrono = { workspace = true }
tokio = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
[lints]
workspace = true
+3
View File
@@ -0,0 +1,3 @@
fn main() {
println!("runway-cli: not yet implemented");
}
+31
View File
@@ -0,0 +1,31 @@
[package]
name = "runway-core"
version.workspace = true
edition.workspace = true
license.workspace = true
description = "Pure calendar domain: RFC 5545 model, iCalendar round-trip, recurrence expansion."
[features]
default = ["model"]
# Types only. Wasm-safe, dependency-light: this is all the frontend needs.
model = []
# iCalendar parsing/serialisation. Server and CLI only.
ical = ["dep:icalendar"]
# RRULE expansion. Server and CLI only.
recurrence = ["dep:rrule", "dep:chrono-tz"]
[dependencies]
chrono = { workspace = true }
serde = { workspace = true }
thiserror = { workspace = true }
uuid = { workspace = true }
chrono-tz = { workspace = true, optional = true }
icalendar = { workspace = true, optional = true }
rrule = { workspace = true, optional = true }
[dev-dependencies]
serde_json = { workspace = true }
pretty_assertions = { workspace = true }
[lints]
workspace = true
+8
View File
@@ -0,0 +1,8 @@
//! Pure calendar domain logic for Runway.
//!
//! This crate holds the RFC 5545 model and, behind feature flags, the iCalendar
//! round-trip and recurrence expansion. It performs no I/O and has no knowledge
//! of HTTP, CalDAV or the database, which keeps it fast to test and — with only
//! the default `model` feature — cheap enough to compile into the WASM bundle.
pub mod model;
+1
View File
@@ -0,0 +1 @@
pub struct Placeholder;
+28
View File
@@ -0,0 +1,28 @@
[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 }
chrono = { workspace = true }
serde = { workspace = true }
serde_json = { 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 }
[lints]
workspace = true
+1
View File
@@ -0,0 +1 @@
//! Runway backend: a CalDAV proxy with sessions, preferences and ICS feeds.
+3
View File
@@ -0,0 +1,3 @@
fn main() {
// Server startup lands in M7, once sessions and the CalDAV proxy exist.
}
+17
View File
@@ -0,0 +1,17 @@
[package]
name = "runway-web"
version.workspace = true
edition.workspace = true
license.workspace = true
description = "Leptos CSR frontend."
[dependencies]
runway-core = { workspace = true }
chrono = { workspace = true }
leptos = { workspace = true, features = ["csr"] }
leptos_router = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
[lints]
workspace = true
+3
View File
@@ -0,0 +1,3 @@
fn main() {
println!("runway-web: not yet implemented");
}