Repository navigation
🤖 fix: provider and MCP creates adopt only by a secret nonce from the cleanup record - #429
Merged
Merged
Conversation
…426) Change-Id: I09458d1f910f09b9016af22eef8325af09f82e5d Signed-off-by: Thomas Kosiewski <tk@coder.com>
…cord (#426) The temporary display name of a create was coder-k8s:<object UID>, which anyone who can read the object sees. A create now sends coder-k8s: and a random secret that only the cleanup record holds, and the create path adopts only a resource with the recorded nonce. A record of an older version keeps its UID nonce until the next create. Change-Id: I24cef38b9d832dd866e3289057c18ebd53bb629b Signed-off-by: Thomas Kosiewski <tk@coder.com>
…te (#422) Change-Id: I4deab98eed66e407e8d36895642cbdfa5b38c2eb Signed-off-by: Thomas Kosiewski <tk@coder.com>
#422) Change-Id: I17a9040ca9554da0c0d17151eb083563f5d2df58 Signed-off-by: Thomas Kosiewski <tk@coder.com>
Change-Id: I8d0394a03baa8bb1bd1764ce252a2c42713f8a64 Signed-off-by: Thomas Kosiewski <tk@coder.com>
#426) Change-Id: I6cfb631af524abd36a9b552558341491f53b328e Signed-off-by: Thomas Kosiewski <tk@coder.com>
…leases (#422) Change-Id: I4a95915b3b9b432eaa756e284975405a14cbc111 Signed-off-by: Thomas Kosiewski <tk@coder.com>
…able to release (#422) Change-Id: Id24ae05ac3be7f5ec092d17d3097e49c409598ae Signed-off-by: Thomas Kosiewski <tk@coder.com>
Change-Id: I44fd62a03699678a24c555ccb5b79d6608363ee3 Signed-off-by: Thomas Kosiewski <tk@coder.com>
…ords (#426) Change-Id: I1e511651edd2d12e5e0cc67e50a7a2d43b285028 Signed-off-by: Thomas Kosiewski <tk@coder.com>
Change-Id: I735cf368639faf217a6219f073aef7e884d8900f Signed-off-by: Thomas Kosiewski <tk@coder.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ 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. |
Member
Author
|
@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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The operator no longer adopts a Coder AI provider or MCP server config because its display name is
coder-k8s:<object UID>. Anyone who can read the Kubernetes object sees that UID. A create now sendscoder-k8s:and a random secret (crypto/rand.Text), and only the cleanup record holds it. After a lost create answer, the operator adopts only a resource whose display name is the recorded nonce. Once it knows the Coder ID, that nonce adopts no other resource.A
CoderAIProviderfrom before cleanup records now gets its record before its delete, as aCoderMCPServeralready did. That backfill gets half of the bounded delete attempt, so a hanging Coder call still leaves time for the delete and the release.Fixes #426
Fixes #422
Background
#423 kept create-path adoption by the temporary display name, because it is the only recovery for a lost create answer (#253). #426 tracks the gap: a Coder user who creates a resource with that display name can get it adopted, overwritten and later deleted by ID.
#422 status after this PR. Items 1, 4 and 5 were fixed in #423. Item 2 is a documented limit, and this PR adds the docs sentence. Item 3 is fixed for providers and documented for both kinds (see Risks). Item 6 is the recorded decision that the control plane hold never ends early.
Implementation
cleanup_record.go:nextCreateNoncekeeps the recorded random nonce while the record has no Coder ID, so a late commit is still recognized. After the ID is known, Coder has shown the nonce, so the next create gets a new one.keptCreateNoncegives an object without a record (from before records) the oldcoder-k8s:<UID>nonce, because that is what its create sent.adoptionNoncereturns the nonce that may prove a found resource. It returns nothing when the record holds another Coder ID. It also returns nothing for an old UID nonce unless the object still has its create marker.CoderAIProviderReconciler.deleteStepbackfills a missing record. The MCP delete no longer re-reads the record after its backfill: that read used a context that a hanging Coder call had used up, which turned the bounded pass into a reconcile error loop.Validation
Each test commit comes before its fix. On main (
03eca051) with the new tests, these fail:TestCoderAIProviderUIDDisplayNameNotAdoptedandTestCoderMCPServerUIDDisplayNameNotAdopted: a person's resource withcoder-k8s:<UID>was adopted.Test*LostCreateAnswerRecoversByNonce,TestCoderAIProviderNonceReuseandTestCoderMCPServerNewNonceAfterKnownID: the nonce was the UID. The recovery itself passes on both.Test*ShownNonceNotAdopted: a person replaced a known resource with one that carried its nonce.Test*OldNonceAdoptedUntilNextCreateandTest*OldNonceNotAdoptedWithoutPendingCreate: the migration rules.TestCoderAIProviderRecordBackfillOnDelete, andTestCoderMCPServerRecordBackfillOnDeleteHangs(fails on main: reconcile error from an expired context).TestCoderAIProviderRecordBackfillOnDeleteHangspasses on main. It guards the new provider backfill.Local gates on
f18b14f6:make verify-vendor,make build,make lint,make test,make test-integration,nix develop -c make docs-check, andmarkdownlint-cli2andcspellon the two changed docs. Two independent pre-PR reviewers (claude-opus-5-5, gpt-6.1-sol) checked the branch. Their findings on known-ID replay, open-ended old UID nonces and the bounded backfill are fixed here.Risks
coder.comresources. Aview,editoradminbinding in that namespace, or a ClusterRoleBinding of them, exposes it. The docs say so. A Secret store would need new RBAC, so it is not in this PR.NameConflictorSlugConflict. Nothing is adopted or deleted wrongly. The sweep reports it withManualCleanupNeeded.ControlPlaneGone, and the docs say to delete the resource by hand.Generated with
mux• Model:anthropic:claude-opus-5-5• Thinking:xhigh