Files
computer-playbook/tests/unit/python/plugins
kevinveenbirkenbachandClaude Opus 5 8e3fe04d72 fix(mcp): read a provider's bearer where provisioning writes it
Discovery resolved applications[role].credentials, the address from
before f713ba8350 moved every credential under secrets.credentials. The
run's own inventory shows which one is real: twelve applications carry
secrets.credentials, none carries the top-level key. So every provider
declaring credential.source: credentials - fifteen of the twenty - handed
back an empty mapping, and reconciliation aborted on a secret that had
been provisioned all along:

  mcp_servers: 1 authorized MCP server(s) cannot be rendered.
  web-app-prometheus: credential_missing: web-app-prometheus declares
  owner 'mcp-web-app-prometheus' but no secret resolved

The five providers on token_store read through users and were never
affected, which is why only some clients broke.

Provider and client were reading the same secret at two addresses:
web-app-prometheus/vars/main.yml:32 renders its bearer from
secrets.credentials.mcp_bearer. Without the strict assert this would have
surfaced as a 401 at runtime rather than a failed deploy.

The lookup was correct when 6881ac5132 wrote it - the rename landed on a
branch it was not an ancestor of, and arrived here through the main
merges of 08-15. Its own message notes that no regex over lookup('config')
could see an access path like this one; a .get("credentials") split across
two lines in a Python plugin is equally invisible to it.

The address now comes from credential_key's constants, which is where the
module already claims a credential is addressed by exactly one string.

resolve_credential was always handed a fabricated mapping directly, so the
function was covered and its caller's address was not. The new tests close
that seam, one of them end to end over the shape provisioning produces.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-29 20:57:07 +02:00
..