mcp door: extend service-session bearer to per-topic + per-loop spawns
ci / gates (push) Successful in 5s
ci / rust (push) Failing after 9s
ci / frontend (push) Successful in 27s
ci / e2e (push) Skipped
ci / publish (push) Skipped

Per-team runtimes had their MCP bearer swap wired in the prior slice,
but per-topic (research_container::spawn) and per-loop (spawn_loop)
containers still baked the stale template bearer and 401'd every
tools/list. Same fix, extended: mint a workspace-owner service session
via runtime_provision::mint_workspace_service_token and inject via
prewrite_daemon_config_with_risk.

Move mint_workspace_service_token from topology_worker into
runtime_provision so all three spawn call sites share the helper.

Callers updated: routes/research.rs (start_topic), routes/research_setup.rs
(prepare_topic_runtime), routes/loops.rs (ensure_loop_container).

Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
Omar Sobh
2026-07-18 16:14:38 -07:00
co-authored by Claude Opus 4.7
parent 6504ed6062
commit 657b666219
6 changed files with 82 additions and 24 deletions
+18 -1
View File
@@ -245,7 +245,24 @@ async fn ensure_loop_container(pool: &PgPool, workspace_id: Uuid, loop_id: Uuid)
}
};
let state_root = loop_state_root().join(loop_id.to_string()).join("state");
let spawned = match crate::research_container::spawn_loop(&docker, loop_id, &state_root).await {
let mcp_bearer = crate::runtime_provision::mint_workspace_service_token(
pool,
cm_domain::WorkspaceId::from(workspace_id),
)
.await
.map_err(|e| {
eprintln!("loops::ensure_loop_container({loop_id}): mint MCP bearer failed: {e}");
e
})
.ok();
let spawned = match crate::research_container::spawn_loop(
&docker,
loop_id,
&state_root,
mcp_bearer.as_deref(),
)
.await
{
Ok(s) => s,
Err(e) => {
eprintln!("loops::ensure_loop_container({loop_id}): spawn failed: {e}");
+19 -1
View File
@@ -772,7 +772,25 @@ pub async fn start_topic(
if let Some(repo_path) = repo_path_for_container {
match crate::research_container::connect() {
Ok(docker) => {
match crate::research_container::spawn(&docker, id, &repo_path, &state_root).await {
let mcp_bearer = crate::runtime_provision::mint_workspace_service_token(
&state.pool,
user.workspace_id,
)
.await
.map_err(|e| {
eprintln!("start_topic: mint MCP bearer failed: {e}");
e
})
.ok();
match crate::research_container::spawn(
&docker,
id,
&repo_path,
&state_root,
mcp_bearer.as_deref(),
)
.await
{
Ok(spawned) => {
if let Err(e) = cm_db::repo::research_topics::set_zeroclaw_container(
&state.pool,
+19 -1
View File
@@ -93,7 +93,25 @@ pub async fn prepare_topic_runtime(pool: &PgPool, workspace_id: Uuid, topic_id:
return;
}
};
match crate::research_container::spawn(&docker, topic_id, &repo_path, &state_root).await {
let mcp_bearer = crate::runtime_provision::mint_workspace_service_token(
pool,
cm_domain::WorkspaceId::from(workspace_id),
)
.await
.map_err(|e| {
eprintln!("prepare_topic_runtime({topic_id}): mint MCP bearer failed: {e}");
e
})
.ok();
match crate::research_container::spawn(
&docker,
topic_id,
&repo_path,
&state_root,
mcp_bearer.as_deref(),
)
.await
{
Ok(spawned) => {
if let Err(e) = cm_db::repo::research_topics::set_zeroclaw_container(
pool,