Inline ApiSession into quire-core/ci/run; delete ci/session module
The session module held a single struct. ApiSession now lives next to
RunMeta in quire-core/src/ci/run.rs, which is the natural home for
run-scoped data shared between the orchestrator and quire-ci.

https://claude.ai/code/session_01Ngf4zbFf87zJFUR5ee2Y8b
change
commit 7c8b14ef35bd7bae0cdea217c07b5a7d40f31931
author Claude <noreply@anthropic.com>
date
parent 54b0281d
diff --git a/quire-ci/src/main.rs b/quire-ci/src/main.rs
index ac0eb11..88c19be 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::session::ApiSession;
+use quire_core::ci::run::ApiSession;
 use quire_core::fennel::FennelError;
 use quire_core::secret::{Error as SecretError, Result as SecretResult, SecretRegistry};
 use quire_core::telemetry::{self, FmtMode, MietteLayer};
diff --git a/quire-core/src/ci/mod.rs b/quire-core/src/ci/mod.rs
index b3e3103..6f417fc 100644
--- a/quire-core/src/ci/mod.rs
+++ b/quire-core/src/ci/mod.rs
@@ -12,4 +12,3 @@ pub mod pipeline;
 pub mod registration;
 pub mod run;
 pub mod runtime;
-pub mod session;
diff --git a/quire-core/src/ci/run.rs b/quire-core/src/ci/run.rs
index b6ba4db..8b2e181 100644
--- a/quire-core/src/ci/run.rs
+++ b/quire-core/src/ci/run.rs
@@ -2,10 +2,11 @@
 //!
 //! The full `Run` lifecycle (state machine, db rows, log files) lives
 //! in `quire-server::ci::run`. This module carries only the immutable
-//! metadata that the runtime needs at execute time so it can run in
-//! either a server or an in-container `quire-ci` context.
+//! metadata and session credentials the runtime needs at execute time.
 
 use jiff::Timestamp;
+use rand::distr::Alphanumeric;
+use rand::Rng as _;
 
 /// Immutable metadata for a CI run. Passed to `Runs::create` at
 /// enqueue time; the fields are written to the `runs` row once.
@@ -18,3 +19,30 @@ pub struct RunMeta {
     /// When the push occurred.
     pub pushed_at: Timestamp,
 }
+
+/// Credentials and endpoint for a single orchestrator-dispatched run.
+/// Holds everything quire-ci needs to call back to the server:
+/// where it is, and the bearer token it issued.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct ApiSession {
+    /// Base URL of quire-server (e.g. `http://127.0.0.1:3000`).
+    pub server_url: String,
+    /// Bearer token minted at run creation time. Matches
+    /// `runs.run_token` server-side.
+    pub run_token: String,
+}
+
+impl ApiSession {
+    /// Mint a fresh session for a new run. Generates a CSPRNG bearer
+    /// token and derives the loopback server URL from `port`.
+    pub fn new(port: u16) -> Self {
+        Self {
+            server_url: format!("http://127.0.0.1:{port}"),
+            run_token: rand::rng()
+                .sample_iter(&Alphanumeric)
+                .take(32)
+                .map(char::from)
+                .collect(),
+        }
+    }
+}
diff --git a/quire-core/src/ci/session.rs b/quire-core/src/ci/session.rs
deleted file mode 100644
index 770dbde..0000000
--- a/quire-core/src/ci/session.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-//! API session credentials for CI ↔ server communication.
-//!
-//! The orchestrator constructs an `ApiSession` per run (minting the
-//! auth token); quire-ci reconstructs it from the `QUIRE__*` environment
-//! variables.
-
-use rand::distr::Alphanumeric;
-use rand::Rng as _;
-
-/// Credentials and endpoint coordinates for a single CI run's API
-/// channel. Holds everything quire-ci needs to call back to the
-/// server about *this* run: which run, where the server is, and
-/// the bearer token it issued.
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct ApiSession {
-    /// Base URL of quire-server (e.g. `http://127.0.0.1:3000`).
-    pub server_url: String,
-    /// Bearer token minted at run creation time. Matches
-    /// `runs.run_token` server-side. Also serves as the run
-    /// identifier — the server looks up the run by this token.
-    pub run_token: String,
-}
-
-impl ApiSession {
-    /// Mint a fresh session for a new orchestrator-dispatched run.
-    /// Generates a CSPRNG bearer token and derives the loopback URL from `port`.
-    pub fn new(port: u16) -> Self {
-        Self {
-            server_url: format!("http://127.0.0.1:{port}"),
-            run_token: rand::rng()
-                .sample_iter(&Alphanumeric)
-                .take(32)
-                .map(char::from)
-                .collect(),
-        }
-    }
-}
diff --git a/quire-server/src/ci/mod.rs b/quire-server/src/ci/mod.rs
index 7b547d3..0062c60 100644
--- a/quire-server/src/ci/mod.rs
+++ b/quire-server/src/ci/mod.rs
@@ -9,7 +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::session::ApiSession;
+pub use quire_core::ci::run::ApiSession;
 pub use quire_core::ci::{pipeline, registration, runtime};
 pub use run::{Executor, Run, RunState, Runs, materialize_workspace, reconcile_orphans};
 
diff --git a/quire-server/src/ci/run.rs b/quire-server/src/ci/run.rs
index 82265cb..ace2225 100644
--- a/quire-server/src/ci/run.rs
+++ b/quire-server/src/ci/run.rs
@@ -9,7 +9,7 @@ use std::collections::HashMap;
 use std::path::{Path, PathBuf};
 
 use jiff::Timestamp;
-use quire_core::ci::session::ApiSession;
+use quire_core::ci::run::ApiSession;
 use super::error::{Error, Result};
 
 pub use quire_core::ci::run::RunMeta;