Detectord: fix stale setup when installing release over demo - #68
Conversation
|
ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing |
There was a problem hiding this comment.
2 issues found across 3 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="crates/detectord/crates/mcp_detector_daemon/src/runner.rs">
<violation number="1" location="crates/detectord/crates/mcp_detector_daemon/src/runner.rs:134">
P1: When a running worker is re-enrolled into a different org, this block updates `enrollment` but leaves `seen` bound to the original org. Reopen `SeenStore` with `fresh.org_id` before assigning `enrollment`; otherwise release fingerprints are keyed as demo data, and a restart loses them.</violation>
</file>
<file name="crates/detectord/crates/mcp_detector_daemon/src/ops.rs">
<violation number="1" location="crates/detectord/crates/mcp_detector_daemon/src/ops.rs:396">
P2: When the enrollment file cannot be written, `apply_policy` discards `save_for`'s error, so this refresh returns `Ok(Status)` after `status()` reloads the old policy. Make policy application fallible and propagate the persistence error here, as the previous direct save did.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| if fresh.api_base_url != enrollment.api_base_url || fresh.api_key != enrollment.api_key | ||
| { | ||
| tracing::info!(url = %fresh.api_base_url, "backend credentials changed; rebuilding client"); | ||
| client = BackendClient::new(fresh.api_base_url.clone(), fresh.api_key.clone()); | ||
| // Don't sit on the wrong tenant's cached policy for up to | ||
| // REFRESH_INTERVAL; re-fetch on this pass. | ||
| force_refresh = true; | ||
| } |
There was a problem hiding this comment.
P1: When a running worker is re-enrolled into a different org, this block updates enrollment but leaves seen bound to the original org. Reopen SeenStore with fresh.org_id before assigning enrollment; otherwise release fingerprints are keyed as demo data, and a restart loses them.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At crates/detectord/crates/mcp_detector_daemon/src/runner.rs, line 134:
<comment>When a running worker is re-enrolled into a different org, this block updates `enrollment` but leaves `seen` bound to the original org. Reopen `SeenStore` with `fresh.org_id` before assigning `enrollment`; otherwise release fingerprints are keyed as demo data, and a restart loses them.</comment>
<file context>
@@ -123,6 +125,20 @@ pub async fn worker(user: String, enforce: bool, events: Option<EventTx>) -> any
+ // the worker keeps polling the OLD backend for the whole life of
+ // the process: policy and fingerprints come back for the wrong
+ // tenant, and `refresh` persists that answer over the correct one.
+ if fresh.api_base_url != enrollment.api_base_url || fresh.api_key != enrollment.api_key
+ {
+ tracing::info!(url = %fresh.api_base_url, "backend credentials changed; rebuilding client");
</file context>
| if fresh.api_base_url != enrollment.api_base_url || fresh.api_key != enrollment.api_key | |
| { | |
| tracing::info!(url = %fresh.api_base_url, "backend credentials changed; rebuilding client"); | |
| client = BackendClient::new(fresh.api_base_url.clone(), fresh.api_key.clone()); | |
| // Don't sit on the wrong tenant's cached policy for up to | |
| // REFRESH_INTERVAL; re-fetch on this pass. | |
| force_refresh = true; | |
| } | |
| if fresh.api_base_url != enrollment.api_base_url || fresh.api_key != enrollment.api_key | |
| { | |
| tracing::info!(url = %fresh.api_base_url, "backend credentials changed; rebuilding client"); | |
| client = BackendClient::new(fresh.api_base_url.clone(), fresh.api_key.clone()); | |
| // Don't sit on the wrong tenant's cached policy for up to | |
| // REFRESH_INTERVAL; re-fetch on this pass. | |
| force_refresh = true; | |
| } | |
| if fresh.org_id != enrollment.org_id { | |
| seen = SeenStore::open(paths::seen_store_path(&user), fresh.org_id.clone())?; | |
| } |
| match client.fetch_policy().await { | ||
| // Same tenant check the reconcile loop applies; `apply_policy` | ||
| // persists on its own. | ||
| Ok(p) => crate::runner::apply_policy(&p, &mut e, user), |
There was a problem hiding this comment.
P2: When the enrollment file cannot be written, apply_policy discards save_for's error, so this refresh returns Ok(Status) after status() reloads the old policy. Make policy application fallible and propagate the persistence error here, as the previous direct save did.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At crates/detectord/crates/mcp_detector_daemon/src/ops.rs, line 396:
<comment>When the enrollment file cannot be written, `apply_policy` discards `save_for`'s error, so this refresh returns `Ok(Status)` after `status()` reloads the old policy. Make policy application fallible and propagate the persistence error here, as the previous direct save did.</comment>
<file context>
@@ -382,12 +382,21 @@ pub fn status(user: &str) -> anyhow::Result<Status> {
+ match client.fetch_policy().await {
+ // Same tenant check the reconcile loop applies; `apply_policy`
+ // persists on its own.
+ Ok(p) => crate::runner::apply_policy(&p, &mut e, user),
+ Err(err) => {
+ tracing::warn!(error = %err, "policy refresh failed; keeping last-known-good")
</file context>
Summary by cubic
Fixes stale backend state when switching from demo to release by rebuilding the backend client on credential changes and refusing to cache a policy from the wrong tenant. Previously the daemon kept polling the old backend and persisted that tenant’s policy; now it verifies
org_id, warns, and keeps the last-known-good policy on mismatch.mcp_backend::Policyincludes optionalorg_idparsed from domain-config; empty/absent is treated as None for backward compatibility.mcp_detector_daemonrebuilds theBackendClientwhenapi_base_urlorapi_keychanges and forces an immediate refresh.apply_policychecks the tenant (org_id) before persisting; on mismatch it warns and keeps the cache. Older backends withoutorg_idremain accepted.refresh_policylogs fetch failures and routes successful updates throughapply_policy, preserving the cached policy on error.Written for commit a76a9af. Summary will update on new commits.