fix(controller): production client_instance_id launch path and instance-aware mutation gate
Remediate review 655 blockers on PR #979 (issue #978): B1 — Production launcher (mcp_application_launcher) mints one trusted client_instance_id per application launch and propagates it to all five namespace workers via GITEA_MCP_CLIENT_INSTANCE. launcher_entry and multi_namespace_launcher_entries use that path. Workers never invent a trusted ID; missing/malformed/user-supplied values fail closed. B2 — _check_mcp_runtimes_diagnostics is instance-aware: two legitimate instances sharing a profile are allowed when each has a distinct trusted client_instance_id; duplicate workers for the same (instance, profile) still fail closed. Worker identity/generation exported for peer scans. Tests cover shared ID across five namespaces, distinct launches, multi- instance same profile, same-instance duplicates, untrusted attribution, and the production launcher path. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
@@ -175,8 +175,21 @@ class TestLauncherSnippets(unittest.TestCase):
|
||||
def test_only_safe_keys_no_secrets(self):
|
||||
entry = gitea_config.launcher_entry("prgs", "/cfg/profiles.json")["gitea-tools"]
|
||||
self.assertEqual(set(entry), {"command", "args", "env"})
|
||||
self.assertEqual(set(entry["env"]), {"GITEA_MCP_CONFIG", "GITEA_MCP_PROFILE", "GITEA_CLIENT_MANAGED"})
|
||||
# #978 B1: production launcher also injects trusted client identity.
|
||||
required = {
|
||||
"GITEA_MCP_CONFIG",
|
||||
"GITEA_MCP_PROFILE",
|
||||
"GITEA_CLIENT_MANAGED",
|
||||
"GITEA_MCP_CLIENT",
|
||||
"GITEA_MCP_CLIENT_INSTANCE",
|
||||
"GITEA_MCP_INSTANCE_PROVENANCE",
|
||||
}
|
||||
self.assertTrue(required.issubset(set(entry["env"])), entry["env"])
|
||||
self.assertEqual(entry["env"]["GITEA_MCP_PROFILE"], "prgs")
|
||||
self.assertTrue(
|
||||
entry["env"]["GITEA_MCP_CLIENT_INSTANCE"].startswith("inst-"),
|
||||
entry["env"]["GITEA_MCP_CLIENT_INSTANCE"],
|
||||
)
|
||||
blob = json.dumps(entry).lower()
|
||||
for word in ("token", "password", "secret"):
|
||||
self.assertNotIn(word, blob)
|
||||
|
||||
Reference in New Issue
Block a user