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

Merged
jcwalker3 merged 1 commits from feature/13-gitea-profile-discovery into master 2026-07-01 12:50:05 -05:00
Owner

Closes #13
Roadmap parent: #10

Summary

Adds a read-only MCP tool gitea_get_profile that reports the active runtime execution profile, so an LLM can inspect what the current process is configured to do before deciding whether an action should be attempted later.

Returned safe metadata:

  • profile_name
  • allowed_operations, forbidden_operations
  • audit_label
  • token_source_name — a name only (e.g. GITEA_TOKEN), never a value
  • base_url, remote, resolved server
  • authenticated_username (optional, read-only lookup)
  • identity_statusverified / unknown / unavailable / not_resolved

Behavior:

  • Read-only — no mutation; never approves/merges/comments/creates.
  • Fails soft on identity — if the username can't be resolved, it's null and identity_status marks it, but the profile config is still returned (inspectable). Unknown remote is marked unknown with a remote_error, not raised.
  • No secrets — never returns token value, Authorization header, password, raw env, or credential paths.

Supporting change: gitea_auth.get_profile() extended to read three new non-secret env fields — GITEA_FORBIDDEN_OPERATIONS, GITEA_AUDIT_LABEL, GITEA_TOKEN_SOURCE (name only). gitea_whoami output is unchanged.

Files changed (5, +195/-8)

File Change
mcp_server.py new gitea_get_profile tool (+70)
gitea_auth.py get_profile() gains forbidden_operations, audit_label, token_source_name
.env.example document the 3 new optional metadata vars
README.md tool-table row + env-table rows
tests/test_mcp_server.py TestProfileDiscovery (7 tests) + adjusted one #19 assertion (see note)

Validation

  • git diff --check → clean.
  • python3 -m py_compile mcp_server.py tests/test_mcp_server.py gitea_auth.py → OK.
  • pytest tests/test_mcp_server.py41 passed.
  • Secret scan on additions → no real tokens (placeholders / test synthetic super-secret-token, asserted absent from output).
  • Manual: no auth headers in output, no raw env dump, no credential paths, no unrelated files.

Explicit statements

  • No real secrets added.env.example/tests use placeholders; real .env* stays gitignored.
  • No multi-token switching inside one runtime.
  • No PR eligibility / review / merge workflow added — those are #14/#15/#16.
  • No Jenkins/Ops/GlitchTip/Release/deploy behavior added.

Note on the adjusted #19 test

get_profile() now legitimately returns a token_source_name field (a non-secret name). The old #19 test asserted the substring "token" never appears in the dict repr — too broad now that a non-secret field name contains it. Updated to assert the token value never appears and that token_source_name is None when unset. Intent (token value never leaks) is preserved and strengthened.

Scoped to #13 only. Does not touch #14–#18. Do not merge — awaiting independent review.

Closes #13 Roadmap parent: #10 ## Summary Adds a **read-only** MCP tool `gitea_get_profile` that reports the active runtime execution profile, so an LLM can inspect what the current process is configured to do *before* deciding whether an action should be attempted later. Returned safe metadata: * `profile_name` * `allowed_operations`, `forbidden_operations` * `audit_label` * `token_source_name` — a **name** only (e.g. `GITEA_TOKEN`), never a value * `base_url`, `remote`, resolved `server` * `authenticated_username` (optional, read-only lookup) * `identity_status` — `verified` / `unknown` / `unavailable` / `not_resolved` Behavior: * **Read-only** — no mutation; never approves/merges/comments/creates. * **Fails soft** on identity — if the username can't be resolved, it's `null` and `identity_status` marks it, but the profile config is still returned (inspectable). Unknown remote is marked `unknown` with a `remote_error`, not raised. * **No secrets** — never returns token value, Authorization header, password, raw env, or credential paths. Supporting change: `gitea_auth.get_profile()` extended to read three new **non-secret** env fields — `GITEA_FORBIDDEN_OPERATIONS`, `GITEA_AUDIT_LABEL`, `GITEA_TOKEN_SOURCE` (name only). `gitea_whoami` output is unchanged. ## Files changed (5, +195/-8) | File | Change | |------|--------| | `mcp_server.py` | new `gitea_get_profile` tool (+70) | | `gitea_auth.py` | `get_profile()` gains `forbidden_operations`, `audit_label`, `token_source_name` | | `.env.example` | document the 3 new optional metadata vars | | `README.md` | tool-table row + env-table rows | | `tests/test_mcp_server.py` | `TestProfileDiscovery` (7 tests) + adjusted one #19 assertion (see note) | ## Validation * `git diff --check` → clean. * `python3 -m py_compile mcp_server.py tests/test_mcp_server.py gitea_auth.py` → OK. * `pytest tests/test_mcp_server.py` → **41 passed**. * Secret scan on additions → no real tokens (placeholders / test synthetic `super-secret-token`, asserted **absent** from output). * Manual: no auth headers in output, no raw env dump, no credential paths, no unrelated files. ## Explicit statements * **No real secrets added** — `.env.example`/tests use placeholders; real `.env*` stays gitignored. * **No multi-token switching** inside one runtime. * **No PR eligibility / review / merge workflow** added — those are #14/#15/#16. * **No Jenkins/Ops/GlitchTip/Release/deploy behavior** added. ## Note on the adjusted #19 test `get_profile()` now legitimately returns a `token_source_name` **field** (a non-secret name). The old #19 test asserted the substring `"token"` never appears in the dict repr — too broad now that a non-secret field name contains it. Updated to assert the token **value** never appears and that `token_source_name` is `None` when unset. Intent (token value never leaks) is preserved and strengthened. Scoped to #13 only. Does not touch #14–#18. **Do not merge** — awaiting independent review.
jcwalker3 added 1 commit 2026-07-01 12:41:42 -05:00
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>
Author
Owner

Independent review for issue #13 is held due reviewer eligibility.

Validation performed:

  • PR #23 is open and targets master.
  • Authenticated Gitea account is jcwalker3, which matches the PR author, so I cannot approve this PR from this account.
  • Head reviewed: 38c96d5.
  • Changed files verified exactly: .env.example, README.md, gitea_auth.py, mcp_server.py, tests/test_mcp_server.py.
  • git fetch --all --prune completed.
  • git diff --check prgs/master...38c96d5 passed.
  • git diff --name-only prgs/master...38c96d5 returned only the expected files.
  • python3 -m py_compile mcp_server.py tests/test_mcp_server.py gitea_auth.py passed.
  • pytest tests/test_mcp_server.py passed: 41 passed.
  • git check-ignore .env.personal || true confirmed .env.personal is ignored.
  • git check-ignore .env.example || true returned no output, as expected for the tracked example file.

Manual review notes:

  • gitea_get_profile is read-only and only attempts a GET to /api/v1/user for optional identity resolution; it does not create/update/delete/comment/approve/merge/label/push/deploy/rollback/restart/migrate anything.
  • Returned profile metadata is limited to descriptive fields: profile name, allowed/forbidden operation categories, audit label, token source name, base/server URL, remote, authenticated username when verified, and identity status.
  • No token value, authorization header, password, raw environment dump, credential file path, or secret material is returned.
  • Identity lookup exceptions are swallowed into identity_status: "unavailable"; README/tool docs describe profile metadata as descriptive/inspectable and do not present unavailable identity as eligible for mutation.
  • token_source_name is operator-declared metadata only; no automatic secret path discovery or token value exposure found.
  • The adjusted #19 test preserves the original token-value non-leakage check while allowing the non-secret field name token_source_name.
  • .env.example uses placeholders/example-invalid values only.
  • No unrelated #14-#18 implementation, PR eligibility checks, review/approve/merge workflow, operation enforcement, multi-token switching, Jenkins/Ops/GlitchTip/Release/deploy/rollback/migration/restart/production behavior found.

Blocker: reviewer is ineligible from the current authenticated Gitea account (jcwalker3). A different reviewer account is required to approve.

Independent review for issue #13 is held due reviewer eligibility. Validation performed: - PR #23 is open and targets `master`. - Authenticated Gitea account is `jcwalker3`, which matches the PR author, so I cannot approve this PR from this account. - Head reviewed: `38c96d5`. - Changed files verified exactly: `.env.example`, `README.md`, `gitea_auth.py`, `mcp_server.py`, `tests/test_mcp_server.py`. - `git fetch --all --prune` completed. - `git diff --check prgs/master...38c96d5` passed. - `git diff --name-only prgs/master...38c96d5` returned only the expected files. - `python3 -m py_compile mcp_server.py tests/test_mcp_server.py gitea_auth.py` passed. - `pytest tests/test_mcp_server.py` passed: 41 passed. - `git check-ignore .env.personal || true` confirmed `.env.personal` is ignored. - `git check-ignore .env.example || true` returned no output, as expected for the tracked example file. Manual review notes: - `gitea_get_profile` is read-only and only attempts a GET to `/api/v1/user` for optional identity resolution; it does not create/update/delete/comment/approve/merge/label/push/deploy/rollback/restart/migrate anything. - Returned profile metadata is limited to descriptive fields: profile name, allowed/forbidden operation categories, audit label, token source name, base/server URL, remote, authenticated username when verified, and identity status. - No token value, authorization header, password, raw environment dump, credential file path, or secret material is returned. - Identity lookup exceptions are swallowed into `identity_status: "unavailable"`; README/tool docs describe profile metadata as descriptive/inspectable and do not present unavailable identity as eligible for mutation. - `token_source_name` is operator-declared metadata only; no automatic secret path discovery or token value exposure found. - The adjusted #19 test preserves the original token-value non-leakage check while allowing the non-secret field name `token_source_name`. - `.env.example` uses placeholders/example-invalid values only. - No unrelated #14-#18 implementation, PR eligibility checks, review/approve/merge workflow, operation enforcement, multi-token switching, Jenkins/Ops/GlitchTip/Release/deploy/rollback/migration/restart/production behavior found. Blocker: reviewer is ineligible from the current authenticated Gitea account (`jcwalker3`). A different reviewer account is required to approve.
jcwalker3 reviewed 2026-07-01 12:50:05 -05:00
jcwalker3 left a comment
Author
Owner

All checks passed. Verified head 38c96d5, correct file scope, and 41 passing tests. Merging.

All checks passed. Verified head 38c96d5, correct file scope, and 41 passing tests. Merging.
jcwalker3 merged commit 92acb36406 into master 2026-07-01 12:50:05 -05:00
Sign in to join this conversation.