Submit an issue View all issues Source
MIR-1465

`app history` hides CI/OIDC deploys — deployment cluster_id filter compares name vs address

Done runtime Bug public
phinze phinze Opened Jul 23, 2026 Updated Jul 24, 2026

miren app history (and app status's "Active Deployment" block) filter deployments by an exact string match on a client-supplied cluster_id, so deploys authenticated by cluster address are invisible to queries that use the cluster name.

Root cause

The cluster_id on a deployment is a free-form, client-supplied string, and it's used as an exact-match partition key on both write and read:

  • Write (servers/deployment/server.go, deploy handler): clusterId := args.ClusterId() — whatever identity the deploying client used. A local miren deploy -C garden sends "garden"; a CI deploy sets MIREN_CLUSTER=<addr>;sha1=<fp> (no cluster name), so it sends the raw address and the deployment is stored with cluster_id: 34.122.229.118:8443.
  • Read (servers/deployment/server.go, listDeploymentsInternal): if dep.ClusterId != clusterId { continue }, where clusterId is the caller's ctx.ClusterName.

So the same physical cluster ends up with deployments filed under two different identity strings, and a name-based query (app history -C garden"garden") can never match the address-stamped CI rows.

Impact

Observability only — no data loss. The deployment entities are written correctly, including full git_info (sha, branch, commit message), confirmed by inspecting the garden entity store directly. It's purely that the query hides them:

  • miren app history -C garden shows a stale deployment (the last manual deploy) as "active" and omits every CI deploy since.
  • app status's "Active Deployment" block is likewise stale.
  • miren app versions is unaffected (it doesn't filter on cluster), so it correctly shows the CI-deployed version as active — which is what makes the discrepancy so confusing.

Repro

  1. Deploy an app to garden via the GitHub Actions OIDC path (mirendev/actions/deploy, MIREN_CLUSTER=<addr>;sha1=<fp>).
  2. miren app history --app <app> -C garden — the CI deploy is absent; the newest row is an older manual deploy.
  3. miren app versions --app <app> -C garden — shows the CI-deployed version as active, created at deploy time.

Confirmed on garden for both codeagent and reviewagent (deploys from PRs mirendev/codeagent#5, mirendev/reviewagent#17 and #16). Example stored deployment entity:

app_version: reviewagent-vCdKbyry6wo7h9JgjePLff
cluster_id: 34.122.229.118:8443    ← address, not "garden"
git_info: { sha: ae4e5ddd…, branch: main, message: "Merge pull request #16 …" }
status: active

Fix direction

The cluster_id is being used as a client-controlled partition key on a store that's already scoped to a single cluster. Options, roughly in order of robustness:

  • Stamp and match deployments against the cluster's canonical identity server-side, rather than trusting the client-supplied string.
  • Or drop the now-redundant cluster filter in listDeploymentsInternal entirely, since a cluster's entity store only holds its own deployments.
  • Normalizing address→name on read would patch the symptom but leaves the same footgun for the next caller that addresses the cluster differently.

Found while wiring up auto-deploy-on-merge for codeagent/reviewagent — this is the first time either app deployed via CI rather than a laptop, which is why it surfaced now.