Require session info when quire-ci is invoked remotely
quire-ci now distinguishes two invocation modes:

- Local (standalone): no --run-id/--server-url, filesystem executor,
  placeholder meta. Used by developers running quire-ci directly.
- Remote (orchestrated): --run-id and --server-url co-required (both or
  neither), QUIRE_CI_TOKEN required via env. Filesystem executor by
  default; --transport api selects the HTTP path. Session info is stored
  in TransportArgs::Filesystem(Some(_)) for forward-compatible adoption
  of upcoming API routes.

On the server side, Transport::Filesystem now always carries an ApiSession
(minting a UUID and bearer token alongside Api). execute_via_quire_ci
passes --run-id, --server-url, and QUIRE_CI_TOKEN to quire-ci for both
transport variants, plus the filesystem-specific flags for the filesystem
path. The auth_token is always persisted in runs.auth_token so the DB is
ready when API-side token validation arrives.

https://claude.ai/code/session_015rhr3z3HFRqBTMqtqEdpSf
change
commit 8280a074d008565785dbb4a1a99c131e1b4faa55
author Claude <noreply@anthropic.com>
date
parent lxsywuvo
diff --git a/quire-ci/src/main.rs b/quire-ci/src/main.rs
index 694701a..4dc433a 100644
--- a/quire-ci/src/main.rs
+++ b/quire-ci/src/main.rs
@@ -95,8 +95,12 @@ enum Commands {
 }
 
 /// CLI flags for the CI ↔ server transport. Grouped so the related
-/// args travel together and `Transport == Api` can pull its required
-/// peers in via `required_if_eq`.
+/// args travel together.
+///
+/// `--run-id` and `--server-url` are co-required: either both are
+/// provided (remote/orchestrated invocation) or neither is (local
+/// standalone invocation). `--transport api` additionally requires
+/// both.
 #[derive(clap::Args, Debug)]
 struct TransportFlags {
     /// Transport for CI ↔ server communication.
@@ -104,24 +108,39 @@ struct TransportFlags {
     transport: Transport,
 
     /// Run ID assigned by the orchestrator.
-    /// Required when `--transport api`.
-    #[arg(long, required_if_eq("transport", "api"))]
+    /// Must be paired with `--server-url`; required when `--transport api`.
+    #[arg(long, requires = "server_url", required_if_eq("transport", "api"))]
     run_id: Option<String>,
 
     /// Base URL of quire-server (e.g. `http://127.0.0.1:3000`).
-    /// Required when `--transport api`.
-    #[arg(long, required_if_eq("transport", "api"))]
+    /// Must be paired with `--run-id`; required when `--transport api`.
+    #[arg(long, requires = "run_id", required_if_eq("transport", "api"))]
     server_url: Option<String>,
 }
 
 impl TransportFlags {
     /// Promote into the resolved [`TransportArgs`], folding in the
-    /// `QUIRE_CI_TOKEN` env var. clap's `required_if_eq` guarantees
-    /// `--run-id` and `--server-url` are present for `Transport::Api`;
-    /// the token must arrive via env and is non-optional on the wire.
+    /// `QUIRE_CI_TOKEN` env var.
+    ///
+    /// - No session flags → local standalone mode (`Filesystem(None)`).
+    /// - `--run-id`/`--server-url` present → remote mode; token required
+    ///   via env var. Filesystem executor unless `--transport api`.
     fn resolve(self, auth_token: Option<String>) -> miette::Result<TransportArgs> {
         match self.transport {
-            Transport::Filesystem => Ok(TransportArgs::Filesystem),
+            Transport::Filesystem => match (self.run_id, self.server_url) {
+                (None, None) => Ok(TransportArgs::Filesystem(None)),
+                (Some(run_id), Some(server_url)) => {
+                    let auth_token = auth_token.ok_or_else(|| {
+                        miette::miette!("--run-id/--server-url require the QUIRE_CI_TOKEN env var")
+                    })?;
+                    Ok(TransportArgs::Filesystem(Some(ApiSession {
+                        run_id,
+                        server_url,
+                        auth_token,
+                    })))
+                }
+                _ => unreachable!("clap enforces --run-id and --server-url together"),
+            },
             Transport::Api => {
                 let auth_token = auth_token.ok_or_else(|| {
                     miette::miette!("--transport api requires the QUIRE_CI_TOKEN env var")
@@ -221,13 +240,16 @@ pub enum Transport {
     Api,
 }
 
-/// Resolved transport produced by [`TransportFlags::resolve`]. The
-/// `Api` variant carries the shared [`ApiSession`] — same shape the
-/// server constructed when it created the run.
+/// Resolved transport produced by [`TransportFlags::resolve`].
+///
+/// - `Filesystem(None)`: local/standalone invocation; no server session.
+/// - `Filesystem(Some(_))`: remote invocation with filesystem executor;
+///   session info held for upcoming API route use.
+/// - `Api(_)`: remote invocation with HTTP API executor.
 #[derive(Debug)]
-#[allow(dead_code)] // session read by the upcoming API client
+#[allow(dead_code)] // session fields read by upcoming API client
 enum TransportArgs {
-    Filesystem,
+    Filesystem(Option<ApiSession>),
     Api(ApiSession),
 }
 
diff --git a/quire-server/src/bin/quire/commands/ci.rs b/quire-server/src/bin/quire/commands/ci.rs
index 9aee15b..1ba27a3 100644
--- a/quire-server/src/bin/quire/commands/ci.rs
+++ b/quire-server/src/bin/quire/commands/ci.rs
@@ -2,7 +2,7 @@ use std::path::PathBuf;
 
 use miette::{IntoDiagnostic, Result};
 use quire::Quire;
-use quire::ci::{Ci, CommitRef, RunMeta, Runs, Transport};
+use quire::ci::{Ci, CommitRef, RunMeta, Runs, Transport, TransportMode};
 
 /// Validate a repo's ci.fnl without executing any jobs.
 ///
@@ -74,9 +74,11 @@ pub async fn run(quire: &Quire, maybe_sha: Option<&str>) -> Result<()> {
         pushed_at: jiff::Timestamp::now(),
     };
 
-    // Local `quire ci run` always uses filesystem transport; it never
-    // talks to the server, so no server_url is needed.
-    let transport = Transport::Filesystem;
+    // Local `quire ci run` uses filesystem transport. Session info is
+    // minted so quire-ci receives the standard remote-mode flags; the
+    // server_url is a loopback placeholder (never contacted in filesystem
+    // mode).
+    let transport = Transport::for_new_run(TransportMode::Filesystem, 0);
     let run = runs.create(&meta, &transport)?;
     let run_id = run.id().to_string();
     println!(
diff --git a/quire-server/src/ci/mod.rs b/quire-server/src/ci/mod.rs
index d07c747..76d827b 100644
--- a/quire-server/src/ci/mod.rs
+++ b/quire-server/src/ci/mod.rs
@@ -520,7 +520,13 @@ exit 0
         let secrets = HashMap::new();
         let ctx = run_ctx(&repo, &db_path, &secrets);
         let trigger_result = with_path(&fake_path, || {
-            run_ref_inner(&ctx, pushed_at, &push_ref, &Transport::Filesystem, None)
+            run_ref_inner(
+                &ctx,
+                pushed_at,
+                &push_ref,
+                &Transport::for_new_run(TransportMode::Filesystem, 3000),
+                None,
+            )
         });
 
         trigger_result.expect("trigger_ref should succeed with fake quire-ci");
@@ -569,7 +575,13 @@ exit 0
         let secrets = HashMap::new();
         let ctx = run_ctx(&repo, &db_path, &secrets);
         let trigger_result = with_path(&fake_path, || {
-            run_ref_inner(&ctx, pushed_at, &push_ref, &Transport::Filesystem, None)
+            run_ref_inner(
+                &ctx,
+                pushed_at,
+                &push_ref,
+                &Transport::for_new_run(TransportMode::Filesystem, 3000),
+                None,
+            )
         });
 
         let err = trigger_result.expect_err("should fail when quire-ci exits nonzero");
@@ -607,8 +619,14 @@ exit 0
         let db_path = quire.db_path();
         let secrets = HashMap::new();
         let ctx = run_ctx(&repo, &db_path, &secrets);
-        run_ref_inner(&ctx, pushed_at, &push_ref, &Transport::Filesystem, None)
-            .expect("should succeed without ci.fnl");
+        run_ref_inner(
+            &ctx,
+            pushed_at,
+            &push_ref,
+            &Transport::for_new_run(TransportMode::Filesystem, 3000),
+            None,
+        )
+        .expect("should succeed without ci.fnl");
     }
 
     fn push_event(repo: &str, sha: &str) -> PushEvent {
diff --git a/quire-server/src/ci/run.rs b/quire-server/src/ci/run.rs
index 1eacfe7..381959b 100644
--- a/quire-server/src/ci/run.rs
+++ b/quire-server/src/ci/run.rs
@@ -42,27 +42,28 @@ pub enum TransportMode {
 /// Runtime transport for a single CI run. Built once per run from
 /// the config-shape [`TransportMode`] + the server's listen port,
 /// then passed to `Runs::create` and `Run::execute_via_quire_ci`.
-/// The `Api` variant carries the shared [`ApiSession`] — quire-ci
-/// receives a structurally identical value via its CLI flags.
-#[derive(Clone, Debug, Default)]
+/// Both variants carry an [`ApiSession`] so quire-ci always receives
+/// session info — enabling forward-compatible adoption of API routes.
+#[derive(Clone, Debug)]
 pub enum Transport {
-    #[default]
-    Filesystem,
+    Filesystem(ApiSession),
     Api(ApiSession),
 }
 
 impl Transport {
-    /// Build a runtime transport for a new run. For `Api`, mints a
-    /// fresh run ID and CSPRNG bearer token, derives the loopback
-    /// server URL from `port`, and bundles them into an [`ApiSession`].
+    /// Build a runtime transport for a new run. Always mints a fresh
+    /// run ID and CSPRNG bearer token, deriving the loopback server
+    /// URL from `port`. The variant controls whether quire-ci uses
+    /// the filesystem or HTTP API executor.
     pub fn for_new_run(mode: TransportMode, port: u16) -> Self {
+        let session = ApiSession {
+            run_id: uuid::Uuid::now_v7().to_string(),
+            server_url: format!("http://127.0.0.1:{port}"),
+            auth_token: mint_auth_token(),
+        };
         match mode {
-            TransportMode::Filesystem => Transport::Filesystem,
-            TransportMode::Api => Transport::Api(ApiSession {
-                run_id: uuid::Uuid::now_v7().to_string(),
-                server_url: format!("http://127.0.0.1:{port}"),
-                auth_token: mint_auth_token(),
-            }),
+            TransportMode::Filesystem => Transport::Filesystem(session),
+            TransportMode::Api => Transport::Api(session),
         }
     }
 }
@@ -136,15 +137,15 @@ impl Runs {
     /// Inserts a row into `runs` and creates the run directory for
     /// workspace materialization and log storage.
     ///
-    /// `transport` is built by the caller via [`Transport::for_new_run`];
-    /// for `Api`, the run's id comes from the `ApiSession` (so quire-ci
-    /// and the DB agree on which run a bearer token belongs to) and
-    /// the token is persisted in `runs.auth_token`. For `Filesystem`,
-    /// a fresh UUID is minted here.
+    /// `transport` is built by the caller via [`Transport::for_new_run`].
+    /// The run's id and bearer token come from the transport's [`ApiSession`]
+    /// in both variants — both are persisted so quire-ci and the DB always
+    /// agree on which run a token belongs to.
     pub fn create(&self, meta: &RunMeta, transport: &Transport) -> Result<Run> {
         let (id, auth_token_str) = match transport {
-            Transport::Filesystem => (uuid::Uuid::now_v7().to_string(), None),
-            Transport::Api(api) => (api.run_id.clone(), Some(api.auth_token.as_str())),
+            Transport::Filesystem(api) | Transport::Api(api) => {
+                (api.run_id.clone(), Some(api.auth_token.as_str()))
+            }
         };
         let workspace_path = self.base_dir.join(&id).join("workspace");
 
@@ -355,7 +356,12 @@ impl Run {
         cmd.arg("run").arg("--workspace").arg(workspace);
 
         match transport {
-            Transport::Filesystem => {
+            Transport::Filesystem(api) => {
+                cmd.arg("--run-id")
+                    .arg(&api.run_id)
+                    .arg("--server-url")
+                    .arg(&api.server_url);
+                cmd.env("QUIRE_CI_TOKEN", &api.auth_token);
                 cmd.arg("--out-dir")
                     .arg(&run_dir)
                     .arg("--events")
@@ -365,9 +371,11 @@ impl Run {
             }
             Transport::Api(api) => {
                 cmd.arg("--run-id")
-                    .arg(&self.id)
+                    .arg(&api.run_id)
                     .arg("--server-url")
-                    .arg(&api.server_url);
+                    .arg(&api.server_url)
+                    .arg("--transport")
+                    .arg("api");
                 cmd.env("QUIRE_CI_TOKEN", &api.auth_token);
             }
         }
@@ -754,6 +762,10 @@ mod tests {
         Runs::new(quire.db_path(), "test.git".to_string(), base_dir)
     }
 
+    fn test_transport() -> Transport {
+        Transport::for_new_run(TransportMode::Filesystem, 3000)
+    }
+
     fn test_meta() -> RunMeta {
         RunMeta {
             sha: "abc123".to_string(),
@@ -910,31 +922,38 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
         let parsed = uuid::Uuid::parse_str(run.id()).expect("should be valid UUID");
         assert_eq!(parsed.get_version(), Some(uuid::Version::SortRand));
     }
 
     #[test]
-    fn create_with_filesystem_leaves_auth_token_null() {
+    fn create_with_filesystem_persists_auth_token() {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
-        let run = runs
-            .create(&test_meta(), &Transport::Filesystem)
-            .expect("create");
+        let transport = Transport::for_new_run(TransportMode::Filesystem, 3000);
+        let run = runs.create(&test_meta(), &transport).expect("create");
+
+        let Transport::Filesystem(api) = &transport else {
+            panic!("expected Filesystem transport");
+        };
+
+        // Run id and ApiSession.run_id are the same value.
+        assert_eq!(run.id(), api.run_id);
 
         let conn = crate::db::open(&quire.db_path()).expect("db");
-        let token: Option<String> = conn
+        let stored: Option<String> = conn
             .query_row(
                 "SELECT auth_token FROM runs WHERE id = ?1",
                 rusqlite::params![run.id()],
                 |row| row.get(0),
             )
             .expect("row");
-        assert!(
-            token.is_none(),
-            "filesystem transport should not mint a token"
+        assert_eq!(
+            stored.as_deref(),
+            Some(api.auth_token.as_str()),
+            "filesystem transport should persist its minted auth token"
         );
     }
 
@@ -966,22 +985,32 @@ mod tests {
 
     #[test]
     fn for_new_run_mints_alphanumeric_token() {
-        let transport = Transport::for_new_run(TransportMode::Api, 4000);
-        let Transport::Api(api) = transport else {
-            panic!("expected Api transport");
-        };
-        assert_eq!(api.server_url, "http://127.0.0.1:4000");
-        assert_eq!(api.auth_token.len(), 32);
-        assert!(
-            api.auth_token.chars().all(|c| c.is_ascii_alphanumeric()),
-            "token should be alphanumeric, got {:?}",
-            api.auth_token
-        );
-        assert!(
-            uuid::Uuid::parse_str(&api.run_id).is_ok(),
-            "run_id should be a UUID, got {:?}",
-            api.run_id
-        );
+        for (transport, expected_url) in [
+            (
+                Transport::for_new_run(TransportMode::Filesystem, 3000),
+                "http://127.0.0.1:3000",
+            ),
+            (
+                Transport::for_new_run(TransportMode::Api, 4000),
+                "http://127.0.0.1:4000",
+            ),
+        ] {
+            let api = match &transport {
+                Transport::Filesystem(api) | Transport::Api(api) => api,
+            };
+            assert_eq!(api.server_url, expected_url);
+            assert_eq!(api.auth_token.len(), 32);
+            assert!(
+                api.auth_token.chars().all(|c| c.is_ascii_alphanumeric()),
+                "token should be alphanumeric, got {:?}",
+                api.auth_token
+            );
+            assert!(
+                uuid::Uuid::parse_str(&api.run_id).is_ok(),
+                "run_id should be a UUID, got {:?}",
+                api.run_id
+            );
+        }
     }
 
     #[test]
@@ -996,7 +1025,7 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
 
         assert_eq!(run.state(), RunState::Pending);
@@ -1021,7 +1050,7 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let mut run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
         let id = run.id().to_string();
 
@@ -1044,7 +1073,7 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let mut run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
 
         run.transition(RunState::Active, None).expect("to active");
@@ -1059,7 +1088,7 @@ mod tests {
         let runs = test_runs(&quire);
 
         let mut completed = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
         completed
             .transition(RunState::Active, None)
@@ -1070,7 +1099,7 @@ mod tests {
         assert!(completed.read_finished_at().expect("read").is_some());
 
         let mut failed = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
         failed
             .transition(RunState::Active, None)
@@ -1086,7 +1115,7 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let mut run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
         let id = run.id().to_string();
 
@@ -1110,7 +1139,7 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let mut run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
         let id = run.id().to_string();
 
@@ -1135,13 +1164,13 @@ mod tests {
 
         // Pending -> Failed is not allowed (must go via Active).
         let mut run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
         assert!(run.transition(RunState::Failed, None).is_err());
 
         // Terminal -> anything is not allowed.
         let mut completed = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
         completed
             .transition(RunState::Active, None)
@@ -1158,7 +1187,7 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let mut run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
 
         run.transition(RunState::Active, None).expect("to active");
@@ -1178,7 +1207,7 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let mut run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
 
         run.transition(RunState::Active, None).expect("to active");
@@ -1193,7 +1222,7 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
         let id = run.id().to_string();
 
@@ -1208,7 +1237,7 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let mut run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
         run.transition(RunState::Active, None).expect("to active");
         let id = run.id().to_string();
@@ -1224,7 +1253,7 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let mut run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
         run.transition(RunState::Active, None).expect("to active");
         run.transition(RunState::Complete, None)
@@ -1250,7 +1279,7 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
         let run_id = run.id().to_string();
 
@@ -1364,7 +1393,7 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
 
         let missing = run.path().join("events.jsonl");
@@ -1391,7 +1420,7 @@ mod tests {
 
         // Create first run.
         let run1 = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create run1");
         let run1_id = run1.id().to_string();
         assert_eq!(run1.state(), RunState::Pending);
@@ -1402,9 +1431,7 @@ mod tests {
             r#ref: "refs/heads/main".to_string(),
             pushed_at: "2026-04-28T13:00:00Z".parse().unwrap(),
         };
-        let run2 = runs
-            .create(&meta2, &Transport::Filesystem)
-            .expect("create run2");
+        let run2 = runs.create(&meta2, &test_transport()).expect("create run2");
         assert_eq!(run2.state(), RunState::Pending);
 
         // First run should now be superseded.
@@ -1423,7 +1450,7 @@ mod tests {
 
         // Create and activate first run.
         let mut run1 = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create run1");
         let run1_id = run1.id().to_string();
         run1.transition(RunState::Active, None).expect("to active");
@@ -1434,9 +1461,7 @@ mod tests {
             r#ref: "refs/heads/main".to_string(),
             pushed_at: "2026-04-28T13:00:00Z".parse().unwrap(),
         };
-        let run2 = runs
-            .create(&meta2, &Transport::Filesystem)
-            .expect("create run2");
+        let run2 = runs.create(&meta2, &test_transport()).expect("create run2");
         assert_eq!(run2.state(), RunState::Pending);
 
         // First run should be superseded.
@@ -1455,7 +1480,7 @@ mod tests {
 
         // Create run for main.
         let run1 = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create run1");
         let run1_id = run1.id().to_string();
 
@@ -1465,9 +1490,7 @@ mod tests {
             r#ref: "refs/heads/feature".to_string(),
             pushed_at: "2026-04-28T13:00:00Z".parse().unwrap(),
         };
-        let _run2 = runs
-            .create(&meta2, &Transport::Filesystem)
-            .expect("create run2");
+        let _run2 = runs.create(&meta2, &test_transport()).expect("create run2");
 
         // First run should still be pending.
         let reopened = Run::open(quire.db_path(), run1_id, runs.base_dir.clone()).expect("reopen");
@@ -1481,7 +1504,7 @@ mod tests {
 
         // Create and complete first run.
         let mut run1 = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create run1");
         let run1_id = run1.id().to_string();
         run1.transition(RunState::Active, None).expect("to active");
@@ -1494,9 +1517,7 @@ mod tests {
             r#ref: "refs/heads/main".to_string(),
             pushed_at: "2026-04-28T13:00:00Z".parse().unwrap(),
         };
-        let _run2 = runs
-            .create(&meta2, &Transport::Filesystem)
-            .expect("create run2");
+        let _run2 = runs.create(&meta2, &test_transport()).expect("create run2");
 
         // First run should still be complete.
         let reopened = Run::open(quire.db_path(), run1_id, runs.base_dir.clone()).expect("reopen");
@@ -1508,7 +1529,7 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let mut run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
         run.transition(RunState::Superseded, None)
             .expect("to superseded");
@@ -1520,7 +1541,7 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let mut run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
         run.transition(RunState::Active, None).expect("to active");
         run.transition(RunState::Superseded, None)
@@ -1533,7 +1554,7 @@ mod tests {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
         let mut run = runs
-            .create(&test_meta(), &Transport::Filesystem)
+            .create(&test_meta(), &test_transport())
             .expect("create");
         run.transition(RunState::Active, None).expect("to active");