Repository navigation
🤖 fix: hold a deleted CoderControlPlane while AI Gateway keys and providers still use it - #362
Conversation
…ders still use it Change-Id: I164b54a6e97adda127ff939ebe618143a6ccfee3 Signed-off-by: Thomas Kosiewski <tk@coder.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
Security findingsAdvisory findings (3)
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
@codex security review |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b457bee9eb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…round deletes, and give dependents a grace period Change-Id: I3364c141387c6cd90d64e6a0ba2e785549b46ecf Signed-off-by: Thomas Kosiewski <tk@coder.com>
|
@codex review |
|
@codex security review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1874d474e2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Dogfood on head 1874d47I ran both checks in a licensed Kind cluster (Kubernetes v1.32.0, Coder v2.37.2, AI Bridge on). The operator image is built from this head:
Check 2 is the expected limit of this PR: a hold cannot help when Kubernetes deletes Coder's Deployment and token first. The docs say so. The cleanup records planned for #353 cover this case. Recording of check 1: normal-delete.mp4Recording of check 2: foreground-delete.mp4Check 1 transcriptCheck 2 transcriptThe scripts never print the key or the provider API key. I scanned both transcripts for Generated with |
There was a problem hiding this comment.
🛡️ Codex Security Review
Here are some automated security review suggestions for this pull request.
Reviewed commit: 1874d474e2
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
… period, and drop stale release records Change-Id: Ic848eea8fb199e9f2f082dc1c48502a10c574861 Signed-off-by: Thomas Kosiewski <tk@coder.com>
|
@codex review |
|
@codex security review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ad8cc53b4b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
🛡️ Codex Security Review
Here are some automated security review suggestions for this pull request.
Reviewed commit: ad8cc53b4b
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
Dogfood on head ad8cc53 (round 2 fixes)Same licensed Kind cluster as the comment above. The operator image is built from this head:
The recordings of check 1 and then check 2 follow at the end of this comment. Check 1 transcriptCheck 2 transcriptThe scripts never print the key or the provider API key. Recordings: r3-normal-delete.mp4r3-live-dependents.mp4Generated with |
…endents Change-Id: I7dfa9189c34f89eec3b91fb09fb442d7e7ed6534 Signed-off-by: Thomas Kosiewski <tk@coder.com>
|
@codex review |
|
@codex security review |
|
Codex Review: Didn't find any major issues. Bravo. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Dogfood on head f667afb (workspace RBAC fix)Same licensed Kind cluster. The operator image is built from this head: Check: delete the CoderControlPlane, the CoderAIGatewayKey and the CoderAIProvider in one go, and count the workspace RoleBindings of the control plane (label Result: pass. The RoleBinding count went from 1 to 0 within 1 s of the deletion, while the control plane still held (297 s, the key's settle window). Coder still deleted the key and the provider ( TranscriptRecording: r4-rbac-hold.mp4Generated with |
There was a problem hiding this comment.
🛡️ Codex Security Review
Here are some automated security review suggestions for this pull request.
Reviewed commit: f667afb00e
ℹ️ About Codex security reviews in GitHub
This is an experimental Codex feature. Security reviews are triggered when:
- You comment "@codex security review"
- A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review
Once complete, Codex will leave suggestions, or a comment if no findings are found.
…nd cap the grace period Change-Id: I51e0c91bb48d94962e4807298ecdf1cad6ffc68d Signed-off-by: Thomas Kosiewski <tk@coder.com>
|
@codex review |
|
@codex security review |
🛡️ Codex Security ReviewSecurity review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 49e6fdc0dc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".





Part 1 of #353. When you delete a
CoderControlPlanewhileCoderAIGatewayKeyorCoderAIProviderobjects still use it, the control plane now waits for them for up to 10 minutes. Coder keeps running in that time, so they can delete their keys and providers in Coder. Before this change, Kubernetes garbage-collected the Coder Deployment at once, and the objects released their finalizers withControlPlaneGone, leaving the keys and providers valid in Coder.Design note (#353)
What a hold can and cannot fix. A namespace deletion removes every object in the namespace in parallel: the Coder Deployment, ReplicaSets, Pods, the Service and the operator token Secret. A finalizer on the control plane keeps only the control plane object, not Coder, so no hold can keep Coder reachable during a namespace deletion. The dogfood on #346 saw both outcomes: the control plane gone first, or Coder already refusing connections. So the fix has three parts:
deployment_idfrom/api/v2/buildinfo) later sweeps what a namespace deletion left behind. The record type (a small cluster-scoped CRD, or a ConfigMap) is a maintainer decision. I will ask it separately.If Coder's database is deleted with the namespace, nothing leaks. The leak matters only when the database survives, for example when it is external or shared.
What changes
finalizeWorkspaceRBACkeepscoder.com/workspace-rbac-cleanupwhile aCoderAIGatewayKeyorCoderAIProviderin the namespace that references the control plane is being deleted and still has its cleanup finalizer. A dependent that is not being deleted holds it only for 30 s after the control plane deletion (controlPlaneLiveDependentWait), which covers one command that deletes both.deletionTimestamp(controlPlaneDependentHold).Waiting for the objects that use this control plane to delete their resources in Coderlists the dependents.controlPlaneHolds.502keeps the finalizer and retries, instead of releasing at once. A key waits for its settle window as usual.coder_k8s_cleanup_released_without_delete_total{kind}counts every release without a delete in Coder, next to the existing log line. It counts after the finalizer patch succeeds, and a retry that then deletes in Coder does not count. The repo uses no Kubernetes Events, so this PR adds none.internal/controller/controlplane_hold.go.go.modlistsgithub.com/prometheus/client_golangas a direct requirement, because the metric uses it. It was already vendored.Tests
TestControlPlaneWaitsForDependents:TestCoderAIGatewayKeyDeleteUnderControlPlaneHold:DeletingKeys, requeue 5 minutes) instead of the bounded pass.OperatorAccessNotReadywith a 60 s retry, and keeps the keys.TestCoderAIProviderDeleteUnderControlPlaneHold: a502on DELETE keeps the finalizer (CoderUnavailable, 60 s). The next reconcile deletes the provider and releases.TestReleasedWithoutDeleteMetric: aControlPlaneGonerelease increments the counter.Mutations that the tests catch:
controlPlaneRef;finalizeWorkspaceRBAC;Size: about 150 production lines (with docs) and 180 test lines.
Local gates on the head:
make verify-vendor,make build,make lint,make test,make test-integration,go tool govulncheck ./...,go test -race ./internal/controller/...,make codegen,make build-installerandmake docs-referencewith no drift,make docs-check, and actionlint.Refs #353
Generated with
xum• Model:anthropic:claude-opus-5-5• Thinking:high• Cost:$151.58