Merge origin/main (#592, #593, #594) into the September 16 core audit fixes

config.py conflict: #594 discovers plugins before /config/main matches plugin
keys; this branch routes those sections through the /plugins/config
preparation (F13). Kept both.

#594's secret-separation test posts a plugin section to /config/main, which
this branch now validates through api_v3.schema_manager; the test gets a real
SchemaManager over its temporary plugins directory instead of the helper's
mock. It still fails if the discovery call is reverted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Chuck
2026-09-17 12:46:26 -04:00
co-authored by Claude Opus 5
15 changed files with 794 additions and 52 deletions
+6 -1
View File
@@ -1001,9 +1001,14 @@ def save_main_config():
# flagged degraded at its next load).
plugin_keys_to_remove = []
plugin_secrets_updates = {}
# Discovered first: a plugin key not recognised here skips secret
# separation below and falls through to the generic merge, which wrote
# the plugin's API key into config.json in plain text whenever nothing
# had yet discovered plugins in this process (any save after a restart).
plugin_manifests = _pkg._discovered_plugin_manifests()
for key in data:
# Check if this key is a plugin ID
if api_v3.plugin_manager and key in api_v3.plugin_manager.plugin_manifests:
if api_v3.plugin_manager and key in plugin_manifests:
plugin_id = key
submitted_config = data[key]
if not isinstance(submitted_config, dict):