Remove TransportMode and filesystem bootstrap fallback
`TransportMode` (Filesystem/Api) is gone — server-dispatched runs always
use API transport. quire-ci no longer accepts `--bootstrap` or
`QUIRE__TRANSPORT`; it detects local runs (no `QUIRE__SERVER_URL`) and
falls back to a bootstrap file only in that path. `write_bootstrap` and
the 0600 file handoff are removed from the `Some(transport)` arm;
`store_bootstrap_data` + `GET /api/run/bootstrap` is now the only path
for orchestrator-dispatched runs. `CiConfig.transport` is dropped from
the global config and docs.

https://claude.ai/code/session_01Ngf4zbFf87zJFUR5ee2Y8b
change
commit be501cf3d1d02934152b149e3206862712622a55
author Claude <noreply@anthropic.com>
date
parent e830aca3
diff --git a/docs/config.md b/docs/config.md
index 25e7a3d..fd21568 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -14,7 +14,6 @@ Operator-created. Re-read on every call (no caching today).
 | `:port`              | integer        | no       | TCP port the HTTP server binds to (on `0.0.0.0`). Default: `3000`. |
 | `:sentry :dsn`       | `SecretString` | no       | Sentry DSN for error reporting from both `quire` and `quire-ci`. Omit to disable. |
 | `:secrets`           | table          | no       | Named secrets exposed to `ci.fnl` jobs as `(secret :name)`. |
-| `:ci :transport`     | string         | no       | How `quire-ci` receives secrets. `"filesystem"` (default) bakes revealed values into the bootstrap file; `"api"` serves them on demand via the HTTP API instead. See [Secret transport modes](#secret-transport-modes) below. |
 
 Minimal (no Sentry, no secrets):
 
@@ -84,31 +83,6 @@ Limits worth knowing:
   their *recorded* output redacted at record time.
 - Tracing output is not yet redacted (tracked separately).
 
-## Secret transport modes
-
-The `:ci :transport` key controls how `quire-ci` obtains secret values at
-run time. The two modes are:
-
-**`"filesystem"` (default):** Secrets are revealed into the bootstrap JSON
-file (mode `0600`) before `quire-ci` is spawned. The subprocess reads and
-immediately unlinks the file.
-
-**`"api"`:** `quire-ci` ignores the secrets map in the bootstrap file and
-fetches each value on demand from `GET /api/run/secrets/{name}`
-using the per-run bearer token when a run-fn calls `(secret :name)`. The
-bootstrap file is still written and used for run metadata; only the secret
-values travel over the loopback HTTP channel instead of disk.
-
-To opt in:
-
-```fennel
-{:ci {:transport :api}}
-```
-
-The filesystem path remains the default. Use `:api` to validate the HTTP
-path before a future change stops writing secrets to the bootstrap file
-entirely.
-
 ## See also
 
 - [`fennel.md`](fennel.md) — how Fennel files are loaded into Rust structs.
diff --git a/quire-ci/src/main.rs b/quire-ci/src/main.rs
index 082a5bc..7a42e0e 100644
--- a/quire-ci/src/main.rs
+++ b/quire-ci/src/main.rs
@@ -14,7 +14,7 @@ use quire_core::ci::event::{Event, EventKind, JobOutcome, RunOutcome};
 use quire_core::ci::pipeline::{self, Pipeline, RunFn};
 use quire_core::ci::run::RunMeta;
 use quire_core::ci::runtime::{Runtime, RuntimeError, RuntimeEvent, RuntimeHandle};
-use quire_core::ci::transport::{ApiSession, Transport, TransportMode};
+use quire_core::ci::transport::ApiSession;
 use quire_core::fennel::FennelError;
 use quire_core::secret::{Error as SecretError, Result as SecretResult, SecretRegistry};
 use quire_core::telemetry::{self, FmtMode, MietteLayer};
@@ -49,8 +49,7 @@ struct Cli {
 
     /// Transport credentials and telemetry settings for
     /// orchestrator-dispatched runs, sourced from `QUIRE__*` env vars:
-    /// `QUIRE__SERVER_URL`, `QUIRE__RUN_TOKEN`, `QUIRE__TRANSPORT`,
-    /// `QUIRE__SENTRY_DSN`.
+    /// `QUIRE__SERVER_URL`, `QUIRE__RUN_TOKEN`, `QUIRE__SENTRY_DSN`.
     #[facet(args::config, args::env_prefix = "QUIRE")]
     quire: QuireConfig,
 
@@ -75,10 +74,6 @@ struct QuireConfig {
     #[facet(sensitive, default)]
     run_token: String,
 
-    /// Transport mode (`QUIRE__TRANSPORT`).
-    #[facet(default)]
-    transport: TransportMode,
-
     /// Sentry DSN for error reporting (`QUIRE__SENTRY_DSN`).
     #[facet(default)]
     sentry_dsn: Option<String>,
@@ -112,8 +107,8 @@ enum Commands {
         out_dir: Option<PathBuf>,
 
         /// Path to a JSON bootstrap file produced by the orchestrator.
-        /// Required for `filesystem` transport; omitted for `api`
-        /// transport, which fetches bootstrap via the server API instead.
+        /// Required for local runs (no `QUIRE__SERVER_URL`); omitted for
+        /// server-dispatched runs, which fetch bootstrap via the API.
         #[facet(args::named, default)]
         bootstrap: Option<PathBuf>,
     },
@@ -317,20 +312,15 @@ fn main() -> Result<()> {
                 server_url: cli.quire.server_url,
                 run_token: cli.quire.run_token,
             };
-            let transport = Transport {
-                session: session.clone(),
-                mode: cli.quire.transport,
-            };
-            let client = RunClient::new(session);
-
-            let (git_dir, meta, sentry_trace_id) = match transport.mode {
-                TransportMode::Api => client.fetch_bootstrap()?,
-                TransportMode::Filesystem => {
-                    let Some(path) = bootstrap else {
-                        bail!("--bootstrap is required for filesystem transport");
-                    };
-                    load_bootstrap(&path)?
-                }
+            let client = RunClient::new(session.clone());
+
+            let (git_dir, meta, sentry_trace_id) = if session.server_url.is_empty() {
+                let Some(path) = bootstrap else {
+                    bail!("--bootstrap is required for local runs (no QUIRE__SERVER_URL set)");
+                };
+                load_bootstrap(&path)?
+            } else {
+                client.fetch_bootstrap()?
             };
 
             // Drop order: `_sentry` flushes first (still inside the
@@ -351,7 +341,7 @@ fn main() -> Result<()> {
 
             let registry = SecretRegistry::new(move |name| client.fetch_secret(name));
 
-            run_pipeline(workspace, sink, log_dir, git_dir, meta, registry, transport)
+            run_pipeline(workspace, sink, log_dir, git_dir, meta, registry)
         }
     }
 }
@@ -445,7 +435,6 @@ fn run_pipeline(
     git_dir: PathBuf,
     meta: RunMeta,
     registry: SecretRegistry,
-    _transport: Transport,
 ) -> Result<()> {
     let pipeline = match compile_at(&workspace) {
         Ok(p) => p,
diff --git a/quire-core/src/ci/bootstrap.rs b/quire-core/src/ci/bootstrap.rs
index 6e43157..8d23325 100644
--- a/quire-core/src/ci/bootstrap.rs
+++ b/quire-core/src/ci/bootstrap.rs
@@ -1,15 +1,11 @@
 //! Wire format for handing off a run from the orchestrator to
 //! `quire-ci`.
 //!
-//! The orchestrator writes a [`Bootstrap`] as JSON to a file inside
-//! the run directory and passes the path via `--bootstrap`. `quire-ci`
-//! deserializes it on startup to recover push metadata. Standalone
-//! `quire-ci run` invocations skip the file entirely and fall back to
-//! placeholder values.
-//!
-//! The file is a one-shot handoff: `quire-ci` unlinks it as soon as
-//! it has read the bytes into memory, and the orchestrator
-//! best-effort unlinks after the subprocess exits as a safety net.
+//! For server-dispatched runs the orchestrator stores a [`Bootstrap`]
+//! in the database; `quire-ci` fetches it via `GET /api/run/bootstrap`
+//! using the per-run bearer token. For local dev runs without a server
+//! the orchestrator writes the JSON to a file and passes the path via
+//! `--bootstrap`.
 
 use std::path::PathBuf;
 
diff --git a/quire-core/src/ci/transport.rs b/quire-core/src/ci/transport.rs
index 231183f..d5bbdf2 100644
--- a/quire-core/src/ci/transport.rs
+++ b/quire-core/src/ci/transport.rs
@@ -1,9 +1,8 @@
 //! Shared transport types for CI ↔ server communication.
 //!
 //! The on-the-wire pairing both sides agree on. The orchestrator
-//! constructs a `Transport` per run (minting the auth token and
-//! using the run's UUID); quire-ci reconstructs it from the
-//! `QUIRE__*` environment variables.
+//! constructs a `Transport` per run (minting the auth token);
+//! quire-ci reconstructs it from the `QUIRE__*` environment variables.
 
 /// Credentials and endpoint coordinates for a single CI run's API
 /// channel. Holds everything quire-ci needs to call back to the
@@ -19,33 +18,9 @@ pub struct ApiSession {
     pub run_token: String,
 }
 
-/// Transport mode for CI ↔ server communication.
-#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, facet::Facet, serde::Deserialize)]
-#[facet(rename_all = "kebab-case")]
-#[serde(rename_all = "kebab-case")]
-#[repr(u8)]
-pub enum TransportMode {
-    #[default]
-    Filesystem,
-    Api,
-}
-
-impl std::str::FromStr for TransportMode {
-    type Err = String;
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        match s {
-            "filesystem" => Ok(Self::Filesystem),
-            "api" => Ok(Self::Api),
-            other => Err(format!("unknown transport mode: {other}")),
-        }
-    }
-}
-
 /// Runtime transport for a single CI run.
 /// Use `None` for local runs where no server is involved.
 #[derive(Clone, Debug)]
 pub struct Transport {
     pub session: ApiSession,
-    pub mode: TransportMode,
 }
diff --git a/quire-server/src/ci/mod.rs b/quire-server/src/ci/mod.rs
index ac8a6a5..153df02 100644
--- a/quire-server/src/ci/mod.rs
+++ b/quire-server/src/ci/mod.rs
@@ -9,8 +9,7 @@ pub use quire_core::ci::pipeline::{
     DefinitionError, Diagnostic, Job, Pipeline, PipelineError, StructureError,
 };
 pub use quire_core::ci::run::RunMeta;
-pub use quire_core::ci::transport::ApiSession;
-pub use quire_core::ci::transport::{Transport, TransportMode};
+pub use quire_core::ci::transport::{ApiSession, Transport};
 pub use quire_core::ci::{pipeline, registration, runtime};
 pub use run::{
     Executor, Run, RunState, Runs, materialize_workspace, new_transport, reconcile_orphans,
@@ -103,7 +102,6 @@ impl Ci {
 struct TriggerContext<'a> {
     run: RunContext<'a>,
     event_repo: &'a str,
-    transport_mode: TransportMode,
     port: u16,
     sentry_dsn: Option<String>,
 }
@@ -157,7 +155,6 @@ pub fn trigger(quire: &crate::Quire, event: &PushEvent) {
             executor: config.ci.executor,
         },
         event_repo: &event.repo,
-        transport_mode: config.ci.transport,
         port: config.port,
         sentry_dsn,
     };
@@ -184,7 +181,7 @@ fn run_ref(
     trace_id: sentry::protocol::TraceId,
     span_id: sentry::protocol::SpanId,
 ) {
-    let transport = new_transport(ctx.transport_mode, ctx.port);
+    let transport = new_transport(ctx.port);
     let sentry_trace_id = ctx.sentry_dsn.as_ref().map(|_| trace_id.to_string());
     sentry::with_scope(
         |scope| {
@@ -506,14 +503,7 @@ exit 0
         let db_path = quire.db_path();
         let ctx = run_ctx(&repo, &db_path);
         let trigger_result = with_path(&fake_path, || {
-            run_ref_inner(
-                &ctx,
-                pushed_at,
-                &push_ref,
-                &new_transport(TransportMode::Filesystem, 3000),
-                None,
-                None,
-            )
+            run_ref_inner(&ctx, pushed_at, &push_ref, &new_transport(3000), None, None)
         });
 
         trigger_result.expect("trigger_ref should succeed with fake quire-ci");
@@ -561,14 +551,7 @@ exit 0
         let db_path = quire.db_path();
         let ctx = run_ctx(&repo, &db_path);
         let trigger_result = with_path(&fake_path, || {
-            run_ref_inner(
-                &ctx,
-                pushed_at,
-                &push_ref,
-                &new_transport(TransportMode::Filesystem, 3000),
-                None,
-                None,
-            )
+            run_ref_inner(&ctx, pushed_at, &push_ref, &new_transport(3000), None, None)
         });
 
         let err = trigger_result.expect_err("should fail when quire-ci exits nonzero");
@@ -605,15 +588,8 @@ exit 0
 
         let db_path = quire.db_path();
         let ctx = run_ctx(&repo, &db_path);
-        run_ref_inner(
-            &ctx,
-            pushed_at,
-            &push_ref,
-            &new_transport(TransportMode::Filesystem, 3000),
-            None,
-            None,
-        )
-        .expect("should succeed without ci.fnl");
+        run_ref_inner(&ctx, pushed_at, &push_ref, &new_transport(3000), None, 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 04df1d9..f80b58f 100644
--- a/quire-server/src/ci/run.rs
+++ b/quire-server/src/ci/run.rs
@@ -15,7 +15,7 @@ use rand::{Rng, distr::Alphanumeric};
 use super::error::{Error, Result};
 
 pub use quire_core::ci::run::RunMeta;
-pub use quire_core::ci::transport::{Transport, TransportMode};
+pub use quire_core::ci::transport::Transport;
 
 /// How a run dispatches its pipeline.
 ///
@@ -31,15 +31,13 @@ pub enum Executor {
 }
 
 /// Mint a fresh transport for a new orchestrator-dispatched run. Generates
-/// a UUIDv7 run ID and CSPRNG bearer token, deriving the loopback server
-/// URL from `port`.
-pub fn new_transport(mode: TransportMode, port: u16) -> Transport {
+/// a CSPRNG bearer token, deriving the loopback server URL from `port`.
+pub fn new_transport(port: u16) -> Transport {
     Transport {
         session: ApiSession {
             server_url: format!("http://127.0.0.1:{port}"),
             run_token: mint_run_token(),
         },
-        mode,
     }
 }
 
@@ -293,10 +291,6 @@ impl Run {
     /// * `jobs/<job>/sh-<n>.log` — per-sh CRI logs, written by quire-ci
     ///   via `--out-dir`.
     ///
-    /// When `transport` is `Api`, passes `--run-id`, `--server-url`,
-    /// and `QUIRE_CI_TOKEN` to the subprocess instead of the
-    /// filesystem-based flags.
-    ///
     /// Run finishes `Complete` on exit 0, `Failed` otherwise. The DB
     /// rows are written even on failure so the web UI can render
     /// partial progress.
@@ -315,10 +309,7 @@ impl Run {
         // 'active' in the DB before quire-ci connects, causing the endpoint
         // to return 410 Gone. Update local state only so the later
         // transition(Complete/Failed) call passes the state-machine check.
-        let uses_api_transport = transport
-            .map(|t| t.mode == TransportMode::Api)
-            .unwrap_or(false);
-        if uses_api_transport {
+        if transport.is_some() {
             self.state = RunState::Active;
         } else {
             self.transition(RunState::Active, None)?;
@@ -355,15 +346,9 @@ impl Run {
                 cmd.arg("--bootstrap").arg(&bootstrap_path);
             }
             Some(t) => {
+                self.store_bootstrap_data(git_dir, sentry_trace_id)?;
                 cmd.env("QUIRE__SERVER_URL", &t.session.server_url);
                 cmd.env("QUIRE__RUN_TOKEN", &t.session.run_token);
-                if t.mode == TransportMode::Api {
-                    self.store_bootstrap_data(git_dir, sentry_trace_id)?;
-                    cmd.env("QUIRE__TRANSPORT", "api");
-                } else {
-                    write_bootstrap(&bootstrap_path, git_dir, meta, sentry_trace_id)?;
-                    cmd.arg("--bootstrap").arg(&bootstrap_path);
-                }
             }
         }
         if let Some(dsn) = sentry_dsn {
@@ -380,11 +365,11 @@ impl Run {
                 source,
             })?;
 
-        // quire-ci unlinks the bootstrap file after `load_bootstrap`;
-        // this is a best-effort safety net for paths where it didn't
-        // get that far (spawn failed mid-exec, arg parsing rejected
-        // input, panic before read). `NotFound` is the expected case.
-        if let Err(e) = fs_err::remove_file(&bootstrap_path)
+        // For local runs (None transport), quire-ci unlinks the bootstrap
+        // file after reading it. This is a best-effort safety net for
+        // paths where it didn't get that far. `NotFound` is expected.
+        if transport.is_none()
+            && let Err(e) = fs_err::remove_file(&bootstrap_path)
             && e.kind() != std::io::ErrorKind::NotFound
         {
             tracing::warn!(
@@ -759,7 +744,7 @@ mod tests {
     }
 
     fn test_transport() -> Transport {
-        new_transport(TransportMode::Filesystem, 3000)
+        new_transport(3000)
     }
 
     fn test_meta() -> RunMeta {
@@ -918,35 +903,10 @@ mod tests {
     }
 
     #[test]
-    fn create_with_filesystem_persists_run_token() {
-        let (_dir, quire) = tmp_quire();
-        let runs = test_runs(&quire);
-        let transport = new_transport(TransportMode::Filesystem, 3000);
-        let run = runs.create(&test_meta(), Some(&transport)).expect("create");
-
-        // Run ID is minted by the server, not taken from the transport.
-        assert!(uuid::Uuid::parse_str(run.id()).is_ok());
-
-        let conn = crate::db::open(&quire.db_path()).expect("db");
-        let stored: Option<String> = conn
-            .query_row(
-                "SELECT run_token FROM runs WHERE id = ?1",
-                rusqlite::params![run.id()],
-                |row| row.get(0),
-            )
-            .expect("row");
-        assert_eq!(
-            stored.as_deref(),
-            Some(transport.session.run_token.as_str()),
-            "filesystem transport should persist its minted run token"
-        );
-    }
-
-    #[test]
-    fn create_with_api_persists_minted_run_token() {
+    fn create_persists_minted_run_token() {
         let (_dir, quire) = tmp_quire();
         let runs = test_runs(&quire);
-        let transport = new_transport(TransportMode::Api, 3000);
+        let transport = new_transport(3000);
         let run = runs.create(&test_meta(), Some(&transport)).expect("create");
 
         // Run ID is minted by the server, not taken from the transport.
@@ -967,32 +927,19 @@ mod tests {
     }
 
     #[test]
-    fn for_new_run_mints_alphanumeric_token() {
-        for (transport, expected_url) in [
-            (
-                new_transport(TransportMode::Filesystem, 3000),
-                "http://127.0.0.1:3000",
-            ),
-            (
-                new_transport(TransportMode::Api, 4000),
-                "http://127.0.0.1:4000",
-            ),
-        ] {
-            assert_eq!(transport.session.server_url, expected_url);
-            assert_eq!(transport.session.run_token.len(), 32);
-            assert!(
-                transport
-                    .session
-                    .run_token
-                    .chars()
-                    .all(|c| c.is_ascii_alphanumeric()),
-                "token should be alphanumeric, got {:?}",
-                transport.session.run_token
-            );
-            // Transport no longer carries a run_id — the server mints
-            // the run ID at creation time and the token alone identifies
-            // the run.
-        }
+    fn new_transport_mints_alphanumeric_token() {
+        let transport = new_transport(3000);
+        assert_eq!(transport.session.server_url, "http://127.0.0.1:3000");
+        assert_eq!(transport.session.run_token.len(), 32);
+        assert!(
+            transport
+                .session
+                .run_token
+                .chars()
+                .all(|c| c.is_ascii_alphanumeric()),
+            "token should be alphanumeric, got {:?}",
+            transport.session.run_token
+        );
     }
 
     #[test]
diff --git a/quire-server/src/quire/mod.rs b/quire-server/src/quire/mod.rs
index 1d88b54..525b8ad 100644
--- a/quire-server/src/quire/mod.rs
+++ b/quire-server/src/quire/mod.rs
@@ -6,7 +6,7 @@ use miette::{Context, IntoDiagnostic, Result, ensure};
 
 pub mod web;
 
-use crate::ci::{Ci, Executor, Runs, TransportMode};
+use crate::ci::{Ci, Executor, Runs};
 use crate::{Error, Result as AppResult};
 use quire_core::fennel::Fennel;
 use quire_core::secret::SecretString;
@@ -43,13 +43,6 @@ pub struct CiConfig {
     /// out to the `quire-ci` binary via `Executor::Process`.
     #[serde(default)]
     pub executor: Executor,
-    /// Transport for CI ↔ server communication.
-    ///
-    /// `"filesystem"` (default) writes dispatch/events/logs to disk;
-    /// `"api"` uses the HTTP API with bearer-token auth (requires
-    /// the top-level `server-url`).
-    #[serde(default)]
-    pub transport: TransportMode,
 }
 
 #[derive(serde::Deserialize, Debug)]
@@ -412,29 +405,17 @@ mod tests {
     }
 
     #[test]
-    fn global_config_ci_defaults_to_filesystem() {
+    fn global_config_ci_defaults() {
         let dir = tempfile::tempdir().expect("tempdir");
         let config_path = dir.path().join("config.fnl");
         fs_err::write(&config_path, "{}").expect("write");
 
         let q = Quire::new(dir.path().to_path_buf());
         let config = q.global_config().expect("global_config should load");
-        assert_eq!(config.ci.transport, TransportMode::Filesystem);
         assert_eq!(config.ci.executor, Executor::Process);
         assert_eq!(config.port, 3000);
     }
 
-    #[test]
-    fn global_config_parses_api_transport() {
-        let dir = tempfile::tempdir().expect("tempdir");
-        let config_path = dir.path().join("config.fnl");
-        fs_err::write(&config_path, r#"{:ci {:transport :api}}"#).expect("write");
-
-        let q = Quire::new(dir.path().to_path_buf());
-        let config = q.global_config().expect("global_config should load");
-        assert_eq!(config.ci.transport, TransportMode::Api);
-    }
-
     #[test]
     fn global_config_parses_custom_port() {
         let dir = tempfile::tempdir().expect("tempdir");
diff --git a/quire-server/src/quire/web/api.rs b/quire-server/src/quire/web/api.rs
index 1d5f69e..ffee856 100644
--- a/quire-server/src/quire/web/api.rs
+++ b/quire-server/src/quire/web/api.rs
@@ -232,7 +232,7 @@ mod tests {
     use tower::ServiceExt;
 
     use crate::Quire;
-    use crate::ci::{RunMeta, Runs, TransportMode, new_transport};
+    use crate::ci::{RunMeta, Runs, new_transport};
 
     struct TestEnv {
         _dir: tempfile::TempDir,
@@ -301,7 +301,7 @@ mod tests {
     #[tokio::test]
     async fn bootstrap_returns_401_without_auth() {
         let env = TestEnv::new();
-        let transport = new_transport(TransportMode::Api, 3000);
+        let transport = new_transport(3000);
         create_run_with_bootstrap(&env, &transport, "/repos/test.git", None).await;
 
         let resp = get(env.app(), "/run/bootstrap", None).await;
@@ -319,7 +319,7 @@ mod tests {
     #[tokio::test]
     async fn bootstrap_returns_payload_on_first_fetch() {
         let env = TestEnv::new();
-        let transport = new_transport(TransportMode::Api, 3000);
+        let transport = new_transport(3000);
         create_run_with_bootstrap(&env, &transport, "/repos/test.git", None).await;
 
         let resp = get(
@@ -339,7 +339,7 @@ mod tests {
     #[tokio::test]
     async fn bootstrap_returns_410_on_second_fetch() {
         let env = TestEnv::new();
-        let transport = new_transport(TransportMode::Api, 3000);
+        let transport = new_transport(3000);
         create_run_with_bootstrap(&env, &transport, "/repos/test.git", None).await;
         let token = &transport.session.run_token;
 
@@ -353,7 +353,7 @@ mod tests {
     #[tokio::test]
     async fn secret_returns_401_without_auth() {
         let env = TestEnv::new();
-        let transport = new_transport(TransportMode::Api, 3000);
+        let transport = new_transport(3000);
         env.runs()
             .create(&TestEnv::meta(), Some(&transport))
             .expect("create");
@@ -370,7 +370,7 @@ mod tests {
             r#"{:secrets {:my_token "hunter2"}}"#,
         )
         .expect("write config");
-        let transport = new_transport(TransportMode::Api, 3000);
+        let transport = new_transport(3000);
         env.runs()
             .create(&TestEnv::meta(), Some(&transport))
             .expect("create");