Skip to content

🤖 CoderMCPServer: disable the config in Coder when credential consent is withdrawn #311

Closed

Description

@ThomasK33

Problem

Once the dormant CoderMCPServer controller applies a config (#307), Coder holds the config enabled with the credentials from the referenced Secrets. Later, a Secret owner can withdraw consent: delete the Secret, remove the coder.com/credential=true label, or remove the config's origin from coder.com/credential-destinations. readMCPServerCredentials then stalls before any Coder call (fail static). The config stays enabled in Coder, and Coder keeps sending the stored credential to the MCP server for every member who can read it.

The kind is not registered, so no install is affected today.

Expected

The same rule as CoderAIProvider (#276, #290):

  1. For an object with status.configID, a credential Secret that is deleted, loses the opt-in label, or stops listing an origin that Coder sends the credential to makes the controller verify the recorded config and the destination that Coder currently holds.
  2. It then disables the config in Coder with one PATCH that holds enabled: false and no credential and no destination field.
  3. A spec edit is needed to enable it again (the kill-switch rule).
  4. envtest coverage for each of the three cases after a successful apply.

Gate

The #155 plan lists this as gate G8, implemented in M6. It must land before the activation PR M9.

Found by the Codex normal and security reviews of #307.

Refs #155


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

Activity

  1. ThomasK33 commented on Oct 14, 2026

    @ThomasK33
    MemberAuthor

    #330 implements this issue (the disable, the consent check against what Coder holds, and the tests for each case). It says "Refs #311", not "Fixes", because one part of the spec-edit rule (item 3 above) is still open:

    Remaining before M9 (gate G8): with a newer generation that is not applied yet, the disable PATCH can commit while its answer is lost, or the status write after it can fail. status.appliedGeneration then stays on the old generation. If the Secret gets consent back before the next disable reconcile records the disable, the sync applies the pending generation and enables the config without a spec edit after the disable. The re-enable happens only after the credential read passes again, so no credential goes to an origin without consent. What breaks is the rule that a spec edit is needed to enable the config again.

    A one-line marker in the !found.Enabled branch is not enough: that branch also sees a pending edit from enabled: false to enabled: true. The fix needs a design choice (for example, persist the marker before the disable PATCH) and a test.

    Found by the Codex review of #330 (thread 4267416953). Deferred after two fix rounds on an advisor's recommendation. This issue stays open until it is fixed, so the G8 check before M9 catches it.


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

  2. added a commit that references this issue on Oct 14, 2026
    3aedefb
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