feat: canonical shared runtime-profiles config with typed auth refs (#19) #30
Reference in New Issue
Block a user
Delete Branch "feat/json-runtime-profiles"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Completes issue #19. Refs roadmap #10.
Problem
LLM MCP configs were drifting — each client's
mcp_config.jsonduplicatingGITEA_USER_*/GITEA_PASS_*/GITEA_SITE_*blocks and sometimes raw tokens. That duplicates runtime profiles, exposes secrets, and makes identity/merge safety hard to reason about.Solution
One canonical profiles file; each LLM launcher is a thin pointer.
Canonical file:
Thin launcher (Claude/Gemini/Codex) — two env vars, no secrets:
Implemented format
version(must be1) +profilesmap.base_url,username,default_owner,execution_profile, and a typedauthreference:{ "type": "keychain", "id": "..." }→ macOS keychain (security find-generic-password, on-demand).{ "type": "env", "name": "..." }→ named env var.token/passwordkeys are rejected (never accepted or echoed).GITEA_MCP_CONFIG(path) +GITEA_MCP_PROFILE(name).Precedence
Explicit process env vars (
GITEA_PROFILE_NAME,GITEA_BASE_URL,GITEA_TOKEN, …) override the JSON profile; the JSON profile fills only what env leaves unset.GITEA_MCP_CONFIGunset ⇒ legacy env-only mode (unchanged).Safety
ConfigErrorthat never prints file contents, tokens, or passwords.Tests / checks
tests/test_config.py— 31 cases: legacy env-only, selection, multiple profiles, missing/unset profile, invalid JSON (no leak), unsupported version, env-override precedence, keychain + env auth parsing & resolution, missing-secret errors, inline token/password redaction, no-network parse.get_profile/get_auth_header/mcp tests unchanged → backwards compat). JUnit XML (harness swallows pytest stdout on multi-file runs).py_compileclean; example JSON validated; real configs gitignored (gitea-mcp*.json).Files changed
gitea_config.py(canonical loader/selector/auth-resolver),gitea_auth.py(get_profileoverlay +get_auth_headerfallback),tests/test_config.py,gitea-mcp.example.json,README.md,.env.example.⚠️ Authored by me — do not self-merge. Needs review by another author.
Let one MCP server select among named Gitea runtime profiles from a JSON file instead of editing code or juggling many .env files: GITEA_MCP_CONFIG=/path/to/gitea-mcp.json GITEA_MCP_PROFILE=dev - New gitea_config.py: load/validate the JSON, select the named profile, and resolve its token by env-var reference. Profiles supply base_url, profile_name, token_env, owner/repo, allowed/forbidden operations, and audit label. - gitea_auth.get_profile() now overlays env over the selected JSON profile: explicit env vars win, the JSON profile fills only what env leaves unset. - gitea_auth.get_auth_header() gains a JSON token_env fallback after explicit env tokens (env still wins). Security / safety: - Tokens are referenced by env-var NAME (token_env); an inline "token" is rejected and never echoed. The value is never stored in or returned as profile metadata. - Fail-safe errors: missing file / invalid JSON / unknown or unset selected profile raise a clear ConfigError that never prints file contents or tokens (JSONDecodeError context is suppressed so the raw file text can't surface). - No network calls during config parsing. - Real config files are gitignored (gitea-mcp*.json), example kept. Backwards compatible: with GITEA_MCP_CONFIG unset, behaviour is exactly the prior env-only behaviour (all existing get_profile/get_auth_header tests pass unchanged). Docs: README JSON-profiles section + env table rows, .env.example placeholders, gitea-mcp.example.json. Tests: tests/test_config.py (22 cases) — env-only, selection, multiple profiles, env-override precedence, missing file, invalid JSON, missing/unset profile, inline-token rejection + redaction, and no-network-during-parse. Refs #10. Note: issue #19 (env-based profiles) was already implemented and closed; this JSON-file capability is adjacent new scope tracked under the roadmap rather than reopening #19. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Superseded by the canonical runtime-profiles work under #19 (branch
feat/issue-19-canonical-runtime-profiles). That schema is a refinement of this one: addsversion, richer profile fields (username,default_owner,execution_profile), and typed auth references ({type: keychain|env, ...}). Closing this PR in favor of #19.feat: JSON multi-profile runtime config for Gitea MCP (roadmap #10)to feat: canonical shared runtime-profiles config with typed auth refs (#19)Correction to my earlier comment: this PR is not being closed. Per direction (reuse #30, no competing PR), it was reopened and reworked in place to the canonical shared runtime-profiles schema (version + typed keychain/env auth refs). It now completes #19. Title/body updated.
Reopened. This PR was found closed without merging —
masteris still at the #29 merge and does not contain this branch's commits (3aaba73,b88ca0c). Branchfeat/json-runtime-profilesre-pushed and PR reopened so an eligible (non-author) reviewer can merge it. Merge this before #32 (which stacks on it).Pull request closed