···33use std::{path::PathBuf, sync::Arc};
4455mod app;
66-#[allow(dead_code)]
76mod db;
8798#[derive(Parser)]
···4241 );
43424443 let addr = format!("{}:{}", config.bind_address, config.port);
4444+4545+ // **Intentional deviation from design:** The design doc's startup sequence shows
4646+ // `open_pool(&config.database_url)` directly. However, `config.database_url` defaults
4747+ // to a plain filesystem path (e.g. `/var/pds/relay.db`) when not explicitly set, which
4848+ // is not a valid sqlx URL. We format it here rather than changing Config or open_pool,
4949+ // keeping both functions general-purpose.
5050+ //
5151+ // Plain absolute paths like "/var/pds/relay.db" become "sqlite:///var/pds/relay.db".
5252+ // Already-formatted "sqlite://..." URLs pass through unchanged.
5353+ let db_url = if config.database_url.starts_with("sqlite:") {
5454+ config.database_url.clone()
5555+ } else if config.database_url.starts_with('/') {
5656+ format!("sqlite://{}", config.database_url)
5757+ } else {
5858+ format!("sqlite:{}", config.database_url)
5959+ };
6060+6161+ let pool = db::open_pool(&db_url)
6262+ .await
6363+ .with_context(|| format!("failed to open database at {}", config.database_url))?;
6464+6565+ db::run_migrations(&pool)
6666+ .await
6767+ .with_context(|| "failed to run database migrations")?;
6868+4569 let state = app::AppState {
4670 config: Arc::new(config),
7171+ db: pool,
4772 };
48734974 let listener = tokio::net::TcpListener::bind(&addr)