fix(inventory): exempt credentials at their renamed root

compare_application_keys skips generated credentials because no default exists
for a secret, but it recognised them by the pre-rename prefix. Once the
generator started writing them again, every credential arrived as
secrets.credentials.<key> and the exemption stopped matching, so validation
rejected three keys per credential -- the leaf and both intermediate nodes,
which recursive_keys emits separately -- and aborted the deploy before the
playbook ran. The condition now admits the bare secrets node and the
secrets.credentials subtree, leaving a sibling such as secrets.other flagged.

The check in the inventory manager stays on the bare prefix on purpose: it
walks meta/secrets.yml, whose own root key is credentials.

test_credentials_keys_are_skipped fed the validator the old shape, so it kept
passing while real inventories were being rejected.

Evidence: run 31655559799, job 94311023723,
"Missing default for web-app-dashboard: secrets.credentials.sso_proxy_cookie_secret".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kevinveenbirkenbachandClaude Opus 5 committed 2026-08-13 03:13:26 +02:00
1 parent 32d9755763
commit d86913225b
2 files changed
+4 -2

No files matched your search

@@ -2,6 +2,8 @@
from __future__ import annotations
from utils.manager.credential_key import OVERRIDE_SECTION, SECRETS_KEY
from .keys import recursive_keys
@@ -22,7 +24,7 @@ def compare_application_keys(applications, application_defaults, source, variant
for variant in variants.get(app_id, []):
legal_keys |= recursive_keys(variant)
for key in recursive_keys(conf):
if key.startswith("credentials"):
if key == SECRETS_KEY or key.startswith(OVERRIDE_SECTION):
continue
if key not in legal_keys:
errs.append(f"{source}: Missing default for {app_id}: {key}")
@@ -32,7 +32,7 @@ class TestCompareApplicationKeys(unittest.TestCase):
def test_credentials_keys_are_skipped(self):
apps = {
"app1": {
"credentials": {"api_key": "secret"},
"secrets": {"credentials": {"api_key": "secret"}},
"services": {"port": 8080},
}
}