Repository navigation
canonical(secrets): close the final two #15276 tail sites in the vault-resolution sweep - #15355
Merged
Merged
Conversation
…t-resolution sweep claude_code_backend.py's anthropic_api_key and notification_service.py's smtp_password were the last two of the 29 sites #15276 named, left behind by #15291 because both files sit at their frozen KNOWN_LARGE ceiling and a new resolve_provider_key import had no obvious line-neutral home. Each gets one now: the import folds into a slot vacated by merging two adjacent same-shape assignments in the same function, so neither file's line count moves and neither ceiling (scripts/python_file_size_known_large.py, repo_tests/python_file_size_ratchet_baseline.py) needs to change. AUTOBOT_SMTP_PASSWORD joins SERVICE_CREDENTIAL_KEY_NAMES (and _CREDENTIAL_CONSUMERS) in provider_key_vault.py so it actually hydrates from the System vault like its four siblings; anthropic_api_key already had a resolved-key entry from the LLM provider registry. Both now-fixed ALLOWLIST entries are removed and TRACKED_GAP_CEILING drops from 2 to 0 -- the ratchet in credential_vault_resolution_ratchet_test.py turns both ways, so leaving it at 2 would itself fail the build.
Contributor
✅ SSOT Configuration Compliance: Passing🎉 No new hardcoded values of either class — Known backlog in |
Owner
Author
|
Full local run of `repo_tests/` completed (15m36s, ran in background after the PR body was written): 1843 passed, 7 failed, 10 skipped, 2 xfailed. All 7 failures are pre-existing local-environment artifacts, unrelated to this change (none touch `provider_key_vault.py`, `claude_code_backend.py`, or `notification_service.py`), confirmed by re-running each in isolation:
This supersedes the "not run locally" note in the PR body's Verification section — the full suite was run and the only failures are these three known-unrelated clusters. |
5 tasks
This was referenced Aug 31, 2026
Open
3 tasks
This was referenced Aug 31, 2026
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.
Thinking Path
#15276 listed 29 direct (non-vault) credential read sites as the tail of the
#15267/#15268 sweep. A ground-truth check against the tree found that a prior
PR (#15291, merged as
c13c92882onDev_new_gui) had already migrated 27 ofthe 29 and left the remaining two as
TRACKED_GAPentries inrepo_tests/credential_vault_resolution_allowlist.py, ratcheted atTRACKED_GAP_CEILING = 2— both blocked on the same obstacle: their file is aKNOWN_LARGE-grandfathered file already at its frozen line-count ceiling(
scripts/python_file_size_known_large.py/repo_tests/python_file_size_ratchet_baseline.py,both a CHECKED PAIR that fail if the recorded count and the real count
diverge), and a bare
from services.provider_key_vault import resolve_provider_keyplus its call site adds lines that ceiling may not grow to absorb (#14236's
"the exemption freezes" rule).
The two remaining sites:
services/execution/claude_code_backend.py:317—anthropic_api_keyservices/notification_service.py:450—smtp_passwordEach needed a genuinely line-neutral edit rather than a raised ceiling. For
claude_code_backend.py, restructuring_resolve_api_key's early-return intoa single
if not self._api_key:block freed exactly the line the localimport needs.
black(a repo pre-commit hook, confirmed already clean on bothfiles pre-edit) then inserts its mandatory blank line after any function-local
import, which would have pushed the file 1 line over ceiling — offset by
merging
self._mcp_host = mcp_host/self._mcp_port = mcp_portin__init__into one tuple assignment.notification_service.pygot the sametreatment: the local import took the slot the blank line after the docstring
used to occupy, and merging
smtp_host/smtp_portinto one assignmentabsorbed
black's inserted blank after the import. Both files verifiedblack --checkclean and at their exact recorded ceiling (661 / 634 lines)after the edit.
AUTOBOT_SMTP_PASSWORDalso needed to joinSERVICE_CREDENTIAL_KEY_NAMES(and_CREDENTIAL_CONSUMERS) inprovider_key_vault.py—anthropic_api_keyalready had a resolved-key entry via
LLM_PROVIDER_KEY_NAMES, but nothingpreviously hydrated the SMTP password from the vault, since #15291 explicitly
removed it from that set rather than claim false coverage.
No new guard was needed for regression protection: #15269/#15278/#15280's
existing guard (
repo_tests/credential_vault_resolution_guard_test.py) alreadyscans every git-tracked production
.pyfile (not a fixed site list) for anydirect read of a credential-shaped
ssot_configfield not routed throughresolve_provider_key, already carries a vacuity floor(
test_the_ssot_config_field_scan_finds_known_credential_fieldsassertslen(fields) >= 20), andtest_allowlist_entries_still_correspond_to_a_real_matchwould fail if either newly-migrated site's stale
ALLOWLISTentry were left inplace. Removing both entries and dropping
TRACKED_GAP_CEILINGfrom 2 to 0 incredential_vault_resolution_ratchet_test.pyis therefore the completeregression-guard extension: a reintroduced bare read at either site is
automatically unlisted and fails the guard.
What Changed
autobot-backend/services/provider_key_vault.py—AUTOBOT_SMTP_PASSWORDadded to
SERVICE_CREDENTIAL_KEY_NAMESand_CREDENTIAL_CONSUMERS; moduledocstring updated to describe the line-neutral technique used at both
remaining sites instead of the "deliberately not here" note.
autobot-backend/services/execution/claude_code_backend.py—_resolve_api_keynow resolvesANTHROPIC_API_KEYthroughresolve_provider_key(env wins, then vault) instead of readingconfig.anthropic_api_keydirectly. Line-count-neutral (661 lines, matchesKNOWN_LARGE/ratchet-baseline ceiling exactly).autobot-backend/services/notification_service.py—_send_emailnowresolves
AUTOBOT_SMTP_PASSWORDthroughresolve_provider_keyinstead ofreading
config.smtp_passworddirectly. Line-count-neutral (634 lines,matches ceiling exactly).
repo_tests/credential_vault_resolution_allowlist.py— bothTRACKED_GAP #15276entries removed (now real, vault-routed reads, not gaps).repo_tests/credential_vault_resolution_ratchet_test.py—TRACKED_GAP_CEILINGlowered from 2 to 0 to match.Ground truth vs. the issue body (all sites verified against the tree, not
assumed): every one of the other 27 named sites (
llm_shared/adapters/*,llm_shared/providers/*,services/provider_health/providers.py,agent_loop/slack_hook.py,security/threat_intelligence.py,initialization/lifespan.py,integrations/capability_registry.py,knowledge/base.py) was already migrated toresolve_provider_keyby #15291— confirmed with a fresh
git grepand a direct run of the guard's ownproduction_credential_reads()scanner (see Verification), not by sampling.No premise in the issue body was found false; the "third-party/service
credential" classification and the exact
resolve_provider_key(env_var, config_value)call shape from #15267/#15268 were followed as instructed, withno parallel resolution path, no new helper duplicating the seam, and no
config-direct fallback introduced.
Verification
python3 -m pytest repo_tests/credential_vault_resolution_guard_test.py repo_tests/credential_vault_resolution_ratchet_test.py repo_tests/credential_vault_prose_strip_test.py repo_tests/python_file_size_ratchet_test.py -q— 63 passed.production_credential_reads()(the guard's own scanner) runagainst the full tree returns 0 unlisted direct reads and 0 stale
allowlist entries (allowlist size 24, all
AUTH_BOOTSTRAP/NOT_A_READ,zero
TRACKED_GAP).python3 -m pytest autobot-backend/tests/services/notification_service_test.py autobot-backend/chat_workflow/delegation_test.py autobot-backend/integrations/capability_registry_test.py autobot-backend/agent_loop/search/registry_test.py autobot-backend/voice_processing/realtime/openai_provider_test.py -q— 126passed (all consumers of the touched modules).
python3 -m flake8andpython3 -m black --check— clean on all threeedited source files.
function_length_checker.py(thepre-commit-function-lengthhook'sengine) — no violations on either edited file.
wc -lon both editedKNOWN_LARGEfiles matches their recorded ceilingexactly (661 / 634) — the CHECKED PAIR (
scripts/python_file_size_known_large.py/
repo_tests/python_file_size_ratchet_baseline.py) needed no change.git pushran the local pre-push hook, which selectedrepo_tests/credential_vault_resolution_ratchet_test.pyas the relevanttest and reported
pytest: all relevant tests pass.repo_tests/andautobot-backend/tests/suites(very large; a full run was started in the background but did not finish
producing output within the working session — CI is the source of truth for
the full suite). Local interpreter is Python 3.10.12 against a
requirements.txtdeclaring floors as high as 3.12-targeted packages (90 of206 declared versions unmet) — every test invocation above carries pytest's
own "environment is BELOW the declared dependency floors" notice, so a local
pass does not stand in for a CI pass, only for "this specific surface is not
broken."
touched:
resolve_provider_keyis a pureenv_var or cache.get(...)lookup with no logging; neither edited call site adds a
logger.*orraisereferencing the resolved value.Model Used
Claude Sonnet 5
Closes #15276