Skip to content

CoderAIProvider sync and disable: trust only Coder's own 404 (can lose ownership; gate before next release) #327

Closed

Description

@ThomasK33

Summary

The CoderAIProvider sync and disable paths treat any 404 as "the provider is gone" (internal/controller/coderaiprovider_sync.go, the GET by ID; coderaiprovider_disable.go, the GET before the disable PATCH). An HTML 404 from a proxy, or Coder's Route not found. for a wrong base URL, counts too.

Impact

  • In sync, before the spec is fully applied, such a 404 clears status.providerID, and the controller goes back to the create path. That can lead to a second create attempt, which the existing name and marker checks then handle.
  • When the provider is already applied, the same 404 stalls the object with DeletedExternally, which is a wrong reason.
  • Neither case deletes the wrong provider.

Fix

Use the isCoderResourceNotFound check that #325 added for the delete path in sync and disable as well. A non-Coder 404 then waits with CoderUnavailable. Add a test for an HTML 404 and for Route not found. on each path.

Found by the final assessment of #325. Refs #154


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: medium

Activity

  1. ThomasK33 commented on Oct 14, 2026

    @ThomasK33
    MemberAuthor

    One more effect, from the Codex review of #315 (r4267285174, rated P1 there): in disableWithoutConsent a non-Coder 404 on the GET stalls the object with the credential reason and the message "Provider does not exist in Coder.", and the operator sends no enabled: false PATCH. The same broken route would also stop that PATCH, so no disable that could succeed is skipped, but the message tells an admin the kill switch is complete when the provider can still be enabled and using the key. The fix in this issue (use isCoderResourceNotFound and wait with "Coder can still send the key ...") covers it.


    Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high

  2. ThomasK33 commented on Oct 14, 2026

    @ThomasK33
    MemberAuthor

    Correction from the final assessment of #315 (the activation PR). The impact section above understates the risk.

    Real impact in sync: a provider is applied, then the spec is edited and is not yet applied. A 404 that Coder did not send then makes providerGone clear ProviderID and Credential (coderaiprovider_sync.go). The create path then reads by name, and the display name is no longer the nonce. So it stalls with NameConflict and clears the marker. The object loses ownership for good. After that:

    • a credential failure no longer disables the provider (disable runs only when ProviderID is set), so Coder can keep sending the key to an origin the Secret owner revoked;
    • a delete releases the finalizer without deleting the provider in Coder.

    Disable path: a non-Coder 404 on the GET skips the disable and reports that the provider does not exist (r4267285174 on #315).

    Gate: this must land before the next release tag. The fix must cover both GET and re-read uses in sync and the GET in disable, with tests for an HTML 404 and for Route not found. on each. The how-to's kill-switch text is only fully true once this lands.


    Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: medium

  3. changed the title [-]CoderAIProvider sync and disable: trust only Coder's own 404, as the delete path does[/-] [+]CoderAIProvider sync and disable: trust only Coder's own 404 (can lose ownership; gate before next release)[/+] on Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions