feat: add read-only gitea_get_profile discovery tool (#13)

Add a read-only MCP tool that reports the active runtime execution
profile so an LLM can inspect what the current process is configured to
do before deciding whether to attempt an action later.

- gitea_get_profile: returns profile_name, allowed/forbidden operation
  categories, audit_label, token_source_name (a NAME, never a value),
  base_url, remote, resolved server, and — optionally — the verified
  authenticated username. Identity resolution fails soft and marks
  identity_status (verified/unknown/unavailable/not_resolved); the
  profile config is always returned. Never mutates Gitea.
- gitea_auth.get_profile(): extended with forbidden_operations,
  audit_label, token_source_name from env (non-secret metadata).
- .env.example / README: document the new optional metadata vars and
  the discovery tool.
- tests: metadata parsing, verified/unavailable/unknown identity paths,
  skip-identity, and secret-redaction.

Read-only. No token exposure. No multi-token switching. No PR
eligibility, review, or merge workflow. No Jenkins/Ops/GlitchTip/
Release/deploy behavior.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-01 13:41:14 -04:00
parent 769bec05e7
commit 38c96d5815
5 changed files with 195 additions and 8 deletions
+19 -4
View File
@@ -181,24 +181,39 @@ def get_profile():
environment variables. This function reads only the non-secret profile
metadata:
- ``GITEA_PROFILE_NAME`` — a human label for the running profile.
- ``GITEA_ALLOWED_OPERATIONS`` — optional comma-separated operation
- ``GITEA_PROFILE_NAME`` — a human label for the running profile.
- ``GITEA_ALLOWED_OPERATIONS`` — optional comma-separated operation
categories (descriptive only; not enforced here).
- ``GITEA_BASE_URL`` — optional informational base URL.
- ``GITEA_FORBIDDEN_OPERATIONS`` — optional comma-separated operation
categories this profile must not perform (descriptive only).
- ``GITEA_AUDIT_LABEL`` — optional short label for audit records.
- ``GITEA_TOKEN_SOURCE`` — optional *name* of the secret source
(e.g. an env var name). This is a name only, never a token value.
- ``GITEA_BASE_URL`` — optional informational base URL.
It never reads, returns, or logs ``GITEA_TOKEN`` or any credential. The
token continues to be resolved separately by ``get_auth_header`` and is
never part of this metadata. Callers may surface the result safely.
Returns:
dict with 'profile_name', 'allowed_operations' (list), and 'base_url'.
dict with 'profile_name', 'allowed_operations' (list),
'forbidden_operations' (list), 'audit_label', 'token_source_name',
and 'base_url'.
"""
name = (os.environ.get("GITEA_PROFILE_NAME") or "gitea-default").strip()
raw_ops = os.environ.get("GITEA_ALLOWED_OPERATIONS") or ""
ops = [o.strip() for o in raw_ops.split(",") if o.strip()]
raw_forbidden = os.environ.get("GITEA_FORBIDDEN_OPERATIONS") or ""
forbidden = [o.strip() for o in raw_forbidden.split(",") if o.strip()]
audit_label = (os.environ.get("GITEA_AUDIT_LABEL") or "").strip() or None
# A *name* of the token source (e.g. "GITEA_TOKEN"), never the token value.
token_source = (os.environ.get("GITEA_TOKEN_SOURCE") or "").strip() or None
base_url = os.environ.get("GITEA_BASE_URL") or None
return {
"profile_name": name,
"allowed_operations": ops,
"forbidden_operations": forbidden,
"audit_label": audit_label,
"token_source_name": token_source,
"base_url": base_url,
}