Fix 410 Gone on bootstrap fetch with API transport
execute() was calling transition(Active) before spawning quire-ci,
setting the DB state to 'active'. The GET /api/run/bootstrap handler
checks state == 'pending' and returns 410 if not, so quire-ci always
got 410 on its first (and only) bootstrap fetch.
For API transport, the bootstrap endpoint owns the pending→active
transition (it also stamps started_at_ms). Skip the DB write in
execute() for that transport mode; update local state only so the
later transition(Complete/Failed) call passes the state-machine check.
https://claude.ai/code/session_01VwRTUXLHcJ48iQUwB3wfgE
diff --git a/quire-server/src/ci/run.rs b/quire-server/src/ci/run.rs
index d4c1c66..d86e0b3 100644
--- a/quire-server/src/ci/run.rs
+++ b/quire-server/src/ci/run.rs
@@ -307,7 +307,20 @@ impl Run {
sentry_dsn: Option<&str>,
transport: Option<&Transport>,
) -> Result<()> {
- self.transition(RunState::Active, None)?;
+ // For API transport the GET /api/run/bootstrap endpoint owns the
+ // pending → active transition (it sets started_at_ms when quire-ci
+ // fetches the payload). Calling transition() here would set state =
+ // '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 {
+ self.state = RunState::Active;
+ } else {
+ self.transition(RunState::Active, None)?;
+ }
let run_dir = self.path();
let log_path = run_dir.join("quire-ci.log");