Make Gitea MCP task routing role-aware instead of launcher-profile dependent #139

Closed
opened 2026-07-05 01:19:28 -05:00 by jcwalker3 · 10 comments
Owner

Problem

LLM operators are being asked to perform different Gitea tasks — create issues, comment on discussions, implement issues, review PRs, merge PRs — but the active MCP session is often pinned to a static launcher profile such as prgs-author.

This causes repeated failures where the LLM is asked to review or comment, but the connected MCP server only exposes author permissions. The LLM then stops at the identity gate, which is safe, but the workflow breaks.

The MCP should be agnostic to the LLM. The user should be able to ask for a task, and the MCP layer should determine the required role/capability and either execute through the correct configured profile or clearly report the missing profile/capability.

Current failure examples

  1. Review request fails because the active MCP session is pinned to:

    • username: jcwalker3
    • profile: prgs-author
    • review/approve/merge operations forbidden
  2. Issue discussion comment requests fail because both author and reviewer profiles lack:

    • gitea.issue.comment
  3. LLMs have to reason about launcher config, static-profile mode, namespace names, and profile switching instead of simply using task-appropriate tools.

Goal

Make Gitea MCP task execution role-aware and capability-aware so LLMs can do the requested work safely without hardcoding identities or relying on prompt-specific profile guesses.

Desired behavior

  • If the task is issue creation, use an author-capable profile.
  • If the task is issue commenting, use a profile with gitea.issue.comment.
  • If the task is implementation/branch/PR creation, use an author-capable profile.
  • If the task is PR review, use a reviewer-capable profile.
  • If the task is PR merge, use a merger-capable profile.
  • If the required capability is not available in the active MCP environment, fail closed with a clear operator action.

Requirements

1. Add a role/capability resolver

The resolver should answer:

  • requested operation
  • required operation permission
  • required role kind
  • available matching profiles
  • active profile
  • whether active profile can perform the task
  • whether another configured profile can perform the task
  • whether runtime switching is supported
  • whether a separate MCP namespace/server is required
  • exact safe next action

2. Add or improve a runtime context tool

The runtime context should clearly report:

  • active profile
  • authenticated username
  • allowed operations
  • forbidden operations
  • static-profile versus dynamic-profile mode
  • available configured profiles, redacted
  • available role-capability matches
  • missing permissions
  • whether the current session can author, comment, review, merge, or close issues

3. Add a task-routing guide or helper

Possible tool names:

  • gitea_resolve_task_capability
  • gitea_get_required_profile_for_task
  • gitea_route_task
  • gitea_get_runtime_context

For example:

Input:

  • task: review_pr
  • repo: mcp-control-plane
  • pr_number: 52

Output:

  • required permission: gitea.pr.approve
  • active profile: prgs-author
  • active profile allowed: false
  • matching configured profile: prgs-reviewer
  • runtime switching supported: false
  • safe next action: use MCP namespace gitea-reviewer or relaunch server with GITEA_MCP_PROFILE=prgs-reviewer

4. Do not weaken gates

This must not allow:

  • self-review
  • self-merge
  • author profile PR approval
  • author profile PR merge
  • reviewer profile branch push or repo commit unless explicitly configured
  • issue close through issue-comment permission
  • PR comment permission to imply issue-comment permission

5. Fix issue-comment workflow capability

Ensure the profile model can support:

  • gitea.issue.comment

And make it clear that:

  • gitea.pr.comment does not imply gitea.issue.comment
  • issue discussion workflows require gitea.issue.comment
  • profiles lacking that permission fail closed

6. Support either official profile model

The issue should decide and document one of these safe models:

Option A — Dual namespace model:

  • gitea-author
  • gitea-reviewer
  • Tools remain profile-static.
  • Runtime context tells the LLM which namespace to use.

Option B — Dynamic profile model:

  • one server can activate configured profiles at runtime
  • switching must be explicit, audited, and config-enabled
  • fresh identity proof required after switching

Option C — Dispatcher model:

  • one front-door MCP server receives task requests
  • it internally dispatches to configured role profiles
  • every mutating/review/merge action still runs through strict eligibility checks

Preferred direction:

  • Dual namespace or dispatcher model for high-risk review/merge.
  • Avoid relying on the LLM to "pretend" it is a reviewer.

7. Improve error messages

When an operation fails due to permissions, return:

  • requested operation
  • missing permission
  • active profile
  • active identity
  • available matching profile, if safely known
  • whether profile switching is supported
  • whether a separate namespace is required
  • exact operator action

Example:

"Cannot review PR from active profile prgs-author as jcwalker3. Required permission: gitea.pr.approve. Matching configured profile: prgs-reviewer, but runtime switching is disabled. Use the gitea-reviewer MCP namespace or relaunch with GITEA_MCP_PROFILE=prgs-reviewer."

8. Update docs and guide tools

Update:

  • operator guide
  • skill registry
  • runtime context docs
  • profile examples
  • queue prompts
  • discussion comment workflow docs

Docs must say:

  • LLMs should not hardcode identity.
  • LLMs should verify actual MCP capability.
  • MCP should provide the role/capability resolution.
  • Screen-only comments do not satisfy issue-thread workflows.
  • Review/merge requires a real reviewer profile.

9. Tests

Add tests for:

  • author profile resolving issue creation
  • author profile resolving branch/PR creation
  • author profile rejecting review/merge
  • reviewer profile resolving review/merge
  • reviewer profile rejecting authoring if not configured
  • issue-comment permission required separately
  • profile with gitea.issue.comment can comment
  • profile without gitea.issue.comment fails closed
  • static-profile mode returns "use another namespace/relaunch"
  • dynamic-profile mode returns switch instructions if enabled
  • self-review still blocked even if reviewer permission exists
  • self-merge still blocked
  • missing profile/capability returns actionable failure
  • no secrets, tokens, keychain IDs, or raw service URLs leak

Acceptance criteria

  • A new LLM can ask "review PRs" and the MCP layer clearly says whether the connected environment can review.
  • A new LLM can ask "comment on issue discussion" and the MCP layer clearly says whether gitea.issue.comment is available.
  • The tool no longer relies on prompts to explain which identity should be active.
  • The MCP reports the required profile/capability and the safe next action.
  • Existing author/reviewer/merge safety gates remain intact.
  • No permissions are broadened accidentally.
  • No production behavior.
  • No tags/releases.
  • No secrets exposed.

Hard rules

  • Do not bypass MCP gates.
  • Do not make gitea.pr.comment imply gitea.issue.comment.
  • Do not grant review/merge to author profiles.
  • Do not grant branch push/repo commit to reviewer profiles unless explicitly configured.
  • Do not allow self-review or self-merge.
  • Do not expose secrets, tokens, keychain IDs, raw service URLs, or private config values.
## Problem LLM operators are being asked to perform different Gitea tasks — create issues, comment on discussions, implement issues, review PRs, merge PRs — but the active MCP session is often pinned to a static launcher profile such as `prgs-author`. This causes repeated failures where the LLM is asked to review or comment, but the connected MCP server only exposes author permissions. The LLM then stops at the identity gate, which is safe, but the workflow breaks. The MCP should be agnostic to the LLM. The user should be able to ask for a task, and the MCP layer should determine the required role/capability and either execute through the correct configured profile or clearly report the missing profile/capability. ## Current failure examples 1. Review request fails because the active MCP session is pinned to: * username: `jcwalker3` * profile: `prgs-author` * review/approve/merge operations forbidden 2. Issue discussion comment requests fail because both author and reviewer profiles lack: * `gitea.issue.comment` 3. LLMs have to reason about launcher config, static-profile mode, namespace names, and profile switching instead of simply using task-appropriate tools. ## Goal Make Gitea MCP task execution role-aware and capability-aware so LLMs can do the requested work safely without hardcoding identities or relying on prompt-specific profile guesses. ## Desired behavior * If the task is issue creation, use an author-capable profile. * If the task is issue commenting, use a profile with `gitea.issue.comment`. * If the task is implementation/branch/PR creation, use an author-capable profile. * If the task is PR review, use a reviewer-capable profile. * If the task is PR merge, use a merger-capable profile. * If the required capability is not available in the active MCP environment, fail closed with a clear operator action. ## Requirements ### 1. Add a role/capability resolver The resolver should answer: * requested operation * required operation permission * required role kind * available matching profiles * active profile * whether active profile can perform the task * whether another configured profile can perform the task * whether runtime switching is supported * whether a separate MCP namespace/server is required * exact safe next action ### 2. Add or improve a runtime context tool The runtime context should clearly report: * active profile * authenticated username * allowed operations * forbidden operations * static-profile versus dynamic-profile mode * available configured profiles, redacted * available role-capability matches * missing permissions * whether the current session can author, comment, review, merge, or close issues ### 3. Add a task-routing guide or helper Possible tool names: * `gitea_resolve_task_capability` * `gitea_get_required_profile_for_task` * `gitea_route_task` * `gitea_get_runtime_context` For example: Input: * task: `review_pr` * repo: `mcp-control-plane` * pr_number: `52` Output: * required permission: `gitea.pr.approve` * active profile: `prgs-author` * active profile allowed: false * matching configured profile: `prgs-reviewer` * runtime switching supported: false * safe next action: use MCP namespace `gitea-reviewer` or relaunch server with `GITEA_MCP_PROFILE=prgs-reviewer` ### 4. Do not weaken gates This must not allow: * self-review * self-merge * author profile PR approval * author profile PR merge * reviewer profile branch push or repo commit unless explicitly configured * issue close through issue-comment permission * PR comment permission to imply issue-comment permission ### 5. Fix issue-comment workflow capability Ensure the profile model can support: * `gitea.issue.comment` And make it clear that: * `gitea.pr.comment` does not imply `gitea.issue.comment` * issue discussion workflows require `gitea.issue.comment` * profiles lacking that permission fail closed ### 6. Support either official profile model The issue should decide and document one of these safe models: **Option A — Dual namespace model:** * `gitea-author` * `gitea-reviewer` * Tools remain profile-static. * Runtime context tells the LLM which namespace to use. **Option B — Dynamic profile model:** * one server can activate configured profiles at runtime * switching must be explicit, audited, and config-enabled * fresh identity proof required after switching **Option C — Dispatcher model:** * one front-door MCP server receives task requests * it internally dispatches to configured role profiles * every mutating/review/merge action still runs through strict eligibility checks Preferred direction: * Dual namespace or dispatcher model for high-risk review/merge. * Avoid relying on the LLM to "pretend" it is a reviewer. ### 7. Improve error messages When an operation fails due to permissions, return: * requested operation * missing permission * active profile * active identity * available matching profile, if safely known * whether profile switching is supported * whether a separate namespace is required * exact operator action Example: > "Cannot review PR from active profile `prgs-author` as `jcwalker3`. Required permission: `gitea.pr.approve`. Matching configured profile: `prgs-reviewer`, but runtime switching is disabled. Use the `gitea-reviewer` MCP namespace or relaunch with `GITEA_MCP_PROFILE=prgs-reviewer`." ### 8. Update docs and guide tools Update: * operator guide * skill registry * runtime context docs * profile examples * queue prompts * discussion comment workflow docs Docs must say: * LLMs should not hardcode identity. * LLMs should verify actual MCP capability. * MCP should provide the role/capability resolution. * Screen-only comments do not satisfy issue-thread workflows. * Review/merge requires a real reviewer profile. ### 9. Tests Add tests for: * author profile resolving issue creation * author profile resolving branch/PR creation * author profile rejecting review/merge * reviewer profile resolving review/merge * reviewer profile rejecting authoring if not configured * issue-comment permission required separately * profile with `gitea.issue.comment` can comment * profile without `gitea.issue.comment` fails closed * static-profile mode returns "use another namespace/relaunch" * dynamic-profile mode returns switch instructions if enabled * self-review still blocked even if reviewer permission exists * self-merge still blocked * missing profile/capability returns actionable failure * no secrets, tokens, keychain IDs, or raw service URLs leak ## Acceptance criteria * A new LLM can ask "review PRs" and the MCP layer clearly says whether the connected environment can review. * A new LLM can ask "comment on issue discussion" and the MCP layer clearly says whether `gitea.issue.comment` is available. * The tool no longer relies on prompts to explain which identity should be active. * The MCP reports the required profile/capability and the safe next action. * Existing author/reviewer/merge safety gates remain intact. * No permissions are broadened accidentally. * No production behavior. * No tags/releases. * No secrets exposed. ## Hard rules * Do not bypass MCP gates. * Do not make `gitea.pr.comment` imply `gitea.issue.comment`. * Do not grant review/merge to author profiles. * Do not grant branch push/repo commit to reviewer profiles unless explicitly configured. * Do not allow self-review or self-merge. * Do not expose secrets, tokens, keychain IDs, raw service URLs, or private config values.
Author
Owner

Implementation note: this should be treated as a routing/capability-resolution problem, not a prompt convention problem.

The resolver should keep gitea.pr.comment and gitea.issue.comment separate, report the active profile and required capability, and return an actionable next step when the connected namespace cannot perform the task. Review/merge gates should remain fail-closed, including self-review/self-merge protection and no author-profile approval or merge permissions.

Implementation note: this should be treated as a routing/capability-resolution problem, not a prompt convention problem. The resolver should keep `gitea.pr.comment` and `gitea.issue.comment` separate, report the active profile and required capability, and return an actionable next step when the connected namespace cannot perform the task. Review/merge gates should remain fail-closed, including self-review/self-merge protection and no author-profile approval or merge permissions.
Author
Owner

Independent design review — Claude (Fable 5) operator session, 2026-07-05

Posting status

  • Posted to issue thread: yes (this comment was posted via the gated MCP tool; the gate confirmed success)
  • Tool used: gitea_create_issue_comment (gated on gitea.issue.comment, per #126/#137)
  • Authenticated identity/profile: jcwalker3 / prgs-author (verified via gitea_whoami)

Recommended model

  • Dual namespace / dynamic profile / dispatcher / hybrid: Hybrid — dual static namespaces + a read-only role/capability resolver. No dynamic switching. Dispatcher deferred.
  • Why: static per-role runtimes (gitea-author, gitea-reviewer) keep exactly one credential per process and make self-review structurally hard — that trust boundary is the project's strongest gate and should not be traded for convenience. Dynamic in-process switching means one process holds or can obtain both credentials, muddies audit attribution, and turns "which identity am I?" into mutable state an injected instruction could target. A dispatcher concentrates the same problem in one front door. The real pain today is not switching — it is discoverability: sessions burn turns learning which role a task needs. That is solvable read-only, with zero new write capability: tell the LLM what the task requires and the exact safe next action. gitea_get_runtime_context (#131) already proves the pattern (review_merge_allowed, blocked_reasons, safe_next_action).

Role/capability resolver recommendation

  • Should add resolver tool: yes
  • Suggested tool name: gitea_resolve_task_capability (keep gitea_get_runtime_context as-is; the resolver is per-task)
  • Required output fields: task, required_operation, required_role_kind (author/reviewer/operator), active_profile, active_identity, active_can_perform (bool + reasons), matching_profiles (profile names only — never auth references), runtime_switching_supported (false today), requires_other_namespace (bool + which), safe_next_action (template-generated, one sentence). Read-only; fail-closed on unknown task names, returning the valid task list.

Task → capability map the resolver should encode: create issue → gitea.issue.create (author); comment on issue → gitea.issue.comment (author or reviewer); claim issue → issue-label edit (author); create branch / push branch / open PR → gitea.branch.create / gitea.branch.push / gitea.pr.create (author); review PR → gitea.pr.approve / gitea.pr.request_changes (reviewer, non-author, pinned head); merge PR → gitea.pr.merge (reviewer + eligibility + MERGE PR <n> confirmation); close stale PR / close issue → reviewer/operator; trigger Jenkins → dedicated trigger identity only, per mcp-control-plane #4 (never author/reader); file GlitchTip finding into Gitea → author-side gitea.issue.create composed with read-only glitchtip.read (the #6 orchestrator boundary).

Issue-comment permission recommendation

  • Should prgs-author have gitea.issue.comment: yes (claim notes, audit findings, decision summaries are author-side work)
  • Should prgs-reviewer have gitea.issue.comment: yes (review findings and discussion verdicts belong on threads)
  • Permissions that must remain separate: gitea.issue.comment must not imply gitea.issue.close/reopen; gitea.pr.comment must not imply gitea.issue.comment (different surfaces, different abuse paths — keep the #126 separation); comment grants must not move gitea.pr.approve/merge (author) or gitea.branch.push/gitea.repo.commit (reviewer) in either direction. Tests: both-role success when configured; fail-closed without the op; explicit non-implication tests for close/review/merge/push/commit; error-message clarity. (#137/PR #138 is exactly this first increment — right call.)

Error-message / runtime-context recommendation

  • A blocked mutating call should return a structured, LLM-safe block report: active_identity, active_profile, missing_operation, required_operation, matching_profiles (names only), runtime_switching_supported, requires_other_namespace, and one template-generated operator_action sentence (e.g. "Run this task in the gitea-reviewer namespace, or ask the operator to update the profile"). Never echo caller-supplied values into errors (metadata-is-data, mcp-control-plane #29); never include endpoint URLs, keychain IDs, or auth references. Today's "profile is not allowed to gitea.issue.comment" states what but not what next — the delta is the last four fields.

Safety invariants

  • No self-review; no self-merge — enforced at runtime against live whoami, regardless of profile claims.
  • Author profiles never gain approve/request-changes/merge; reviewer profiles never gain branch push/repo commit unless explicitly configured (reviewer-deadlock invariant stays config-validated).
  • Head-SHA pinning and exact merge confirmation stay mandatory; single-use authorization for any future write path.
  • No production/deploy permissions in either Gitea role; Jenkins triggering only via the dedicated, confirmation-gated identity (#4 model).
  • Fail closed on ambiguity: unknown ops, unresolved identity, unreadable config all refuse.
  • No tool may fall back to raw API calls to dodge a gate; no secrets/tokens/keychain IDs/raw service URLs in any output.
  • Resolver/context tools stay strictly read-only.

Suggested implementation issues

  1. #137 (done — PR #138): gitea.issue.comment for author/reviewer with separation tests; residual operator step: update live profiles config + reconnect MCP.
  2. New: gitea_resolve_task_capability read-only resolver (task→operation→role map, active_can_perform, safe_next_action).
  3. New: standardize dual-namespace deployment (gitea-author/gitea-reviewer launcher config + docs) so "wrong role" errors always name the other namespace.
  4. New: structured block-report error shape adopted across gated tools (shared helper; tests that errors carry the required fields and never echo caller input).
  5. Explicitly deferred (documented as rejected-for-now): dynamic profile switching; dispatcher front door.

Risks / tradeoffs

  • Dual namespaces cost operator overhead (two configured servers/sessions) — the resolver mitigates the confusion cost, not the setup cost.
  • The resolver must not become a config-inventory leak: profile names only, no auth references, no per-profile endpoint detail.
  • Granting issue comments to both roles slightly widens the mutation surface — bounded by non-implication tests and by comments being state-free (no close, no merge).
  • Even with perfect role routing, one agent driving both identities defeats two-party review; session separation policy remains the real guarantee — safe_next_action should say so rather than pretend a namespace hop is sufficient.

Final recommendation

Adopt the hybrid: keep static per-role namespaces as the only credential model; land the #137 unblock everywhere it applies (repo code merged — the live profile config update + MCP reload is the remaining operator step); add gitea_resolve_task_capability plus structured block-report errors next; document dual-namespace deployment as the standard; and explicitly reject dynamic switching and the dispatcher until a concrete need survives design review. This turns "safe but mute" failures into safe, self-explaining ones without adding any new write capability to any runtime.

## Independent design review — Claude (Fable 5) operator session, 2026-07-05 ### Posting status * Posted to issue thread: yes (this comment was posted via the gated MCP tool; the gate confirmed success) * Tool used: `gitea_create_issue_comment` (gated on `gitea.issue.comment`, per #126/#137) * Authenticated identity/profile: `jcwalker3` / `prgs-author` (verified via `gitea_whoami`) ### Recommended model * Dual namespace / dynamic profile / dispatcher / hybrid: **Hybrid — dual static namespaces + a read-only role/capability resolver. No dynamic switching. Dispatcher deferred.** * Why: static per-role runtimes (`gitea-author`, `gitea-reviewer`) keep exactly one credential per process and make self-review structurally hard — that trust boundary is the project's strongest gate and should not be traded for convenience. Dynamic in-process switching means one process holds or can obtain both credentials, muddies audit attribution, and turns "which identity am I?" into mutable state an injected instruction could target. A dispatcher concentrates the same problem in one front door. The real pain today is not switching — it is *discoverability*: sessions burn turns learning which role a task needs. That is solvable read-only, with zero new write capability: tell the LLM what the task requires and the exact safe next action. `gitea_get_runtime_context` (#131) already proves the pattern (`review_merge_allowed`, `blocked_reasons`, `safe_next_action`). ### Role/capability resolver recommendation * Should add resolver tool: **yes** * Suggested tool name: `gitea_resolve_task_capability` (keep `gitea_get_runtime_context` as-is; the resolver is per-task) * Required output fields: `task`, `required_operation`, `required_role_kind` (author/reviewer/operator), `active_profile`, `active_identity`, `active_can_perform` (bool + reasons), `matching_profiles` (profile names only — never auth references), `runtime_switching_supported` (false today), `requires_other_namespace` (bool + which), `safe_next_action` (template-generated, one sentence). Read-only; fail-closed on unknown task names, returning the valid task list. Task → capability map the resolver should encode: create issue → `gitea.issue.create` (author); comment on issue → `gitea.issue.comment` (author or reviewer); claim issue → issue-label edit (author); create branch / push branch / open PR → `gitea.branch.create` / `gitea.branch.push` / `gitea.pr.create` (author); review PR → `gitea.pr.approve` / `gitea.pr.request_changes` (reviewer, non-author, pinned head); merge PR → `gitea.pr.merge` (reviewer + eligibility + `MERGE PR <n>` confirmation); close stale PR / close issue → reviewer/operator; trigger Jenkins → dedicated trigger identity only, per mcp-control-plane #4 (never author/reader); file GlitchTip finding into Gitea → author-side `gitea.issue.create` composed with read-only `glitchtip.read` (the #6 orchestrator boundary). ### Issue-comment permission recommendation * Should `prgs-author` have `gitea.issue.comment`: **yes** (claim notes, audit findings, decision summaries are author-side work) * Should `prgs-reviewer` have `gitea.issue.comment`: **yes** (review findings and discussion verdicts belong on threads) * Permissions that must remain separate: `gitea.issue.comment` must not imply `gitea.issue.close`/reopen; `gitea.pr.comment` must not imply `gitea.issue.comment` (different surfaces, different abuse paths — keep the #126 separation); comment grants must not move `gitea.pr.approve`/`merge` (author) or `gitea.branch.push`/`gitea.repo.commit` (reviewer) in either direction. Tests: both-role success when configured; fail-closed without the op; explicit non-implication tests for close/review/merge/push/commit; error-message clarity. (#137/PR #138 is exactly this first increment — right call.) ### Error-message / runtime-context recommendation * A blocked mutating call should return a structured, LLM-safe block report: `active_identity`, `active_profile`, `missing_operation`, `required_operation`, `matching_profiles` (names only), `runtime_switching_supported`, `requires_other_namespace`, and one template-generated `operator_action` sentence (e.g. "Run this task in the gitea-reviewer namespace, or ask the operator to update the profile"). Never echo caller-supplied values into errors (metadata-is-data, mcp-control-plane #29); never include endpoint URLs, keychain IDs, or auth references. Today's "profile is not allowed to gitea.issue.comment" states *what* but not *what next* — the delta is the last four fields. ### Safety invariants * No self-review; no self-merge — enforced at runtime against live `whoami`, regardless of profile claims. * Author profiles never gain approve/request-changes/merge; reviewer profiles never gain branch push/repo commit unless explicitly configured (reviewer-deadlock invariant stays config-validated). * Head-SHA pinning and exact merge confirmation stay mandatory; single-use authorization for any future write path. * No production/deploy permissions in either Gitea role; Jenkins triggering only via the dedicated, confirmation-gated identity (#4 model). * Fail closed on ambiguity: unknown ops, unresolved identity, unreadable config all refuse. * No tool may fall back to raw API calls to dodge a gate; no secrets/tokens/keychain IDs/raw service URLs in any output. * Resolver/context tools stay strictly read-only. ### Suggested implementation issues 1. #137 (done — PR #138): `gitea.issue.comment` for author/reviewer with separation tests; residual operator step: update live profiles config + reconnect MCP. 2. New: `gitea_resolve_task_capability` read-only resolver (task→operation→role map, `active_can_perform`, `safe_next_action`). 3. New: standardize dual-namespace deployment (`gitea-author`/`gitea-reviewer` launcher config + docs) so "wrong role" errors always name the other namespace. 4. New: structured block-report error shape adopted across gated tools (shared helper; tests that errors carry the required fields and never echo caller input). 5. Explicitly deferred (documented as rejected-for-now): dynamic profile switching; dispatcher front door. ### Risks / tradeoffs * Dual namespaces cost operator overhead (two configured servers/sessions) — the resolver mitigates the confusion cost, not the setup cost. * The resolver must not become a config-inventory leak: profile *names* only, no auth references, no per-profile endpoint detail. * Granting issue comments to both roles slightly widens the mutation surface — bounded by non-implication tests and by comments being state-free (no close, no merge). * Even with perfect role routing, one agent driving both identities defeats two-party review; session separation policy remains the real guarantee — `safe_next_action` should say so rather than pretend a namespace hop is sufficient. ### Final recommendation Adopt the hybrid: keep static per-role namespaces as the only credential model; land the #137 unblock everywhere it applies (repo code merged — the live profile config update + MCP reload is the remaining operator step); add `gitea_resolve_task_capability` plus structured block-report errors next; document dual-namespace deployment as the standard; and explicitly reject dynamic switching and the dispatcher until a concrete need survives design review. This turns "safe but mute" failures into safe, self-explaining ones without adding any new write capability to any runtime.
Author
Owner

Independent design review — Antigravity / 7fd11282

Posting status

  • Posted to issue thread: yes
  • Tool used: gitea_create_issue_comment
  • Authenticated identity/profile: jcwalker3 / prgs-author

Recommended model

  • Dual namespace / dynamic profile / dispatcher / hybrid: Hybrid (Dual Namespace with stateless Routing Resolver)
  • Why: Maintains the highest security boundary by isolating credentials at the container/session level (avoiding session contamination and privilege escalation via prompt injection). The routing resolver tool eliminates LLM guesswork by providing clear, actionable next steps for namespace routing.

Role/capability resolver recommendation

  • Should add resolver tool: yes
  • Suggested tool name: gitea_resolve_task_capability
  • Required output fields: requested_operation, required_permission, required_role_kind, active_profile, active_identity, allowed_in_current_session, available_matching_profiles, runtime_switching_supported, next_safe_action

Issue-comment permission recommendation

  • Should prgs-author have gitea.issue.comment: yes
  • Should prgs-reviewer have gitea.issue.comment: yes
  • Permissions that must remain separate: gitea.issue.comment must not imply gitea.pr.comment, gitea.issue.close, or any mutating review/merge permissions.

Error-message / runtime-context recommendation

  • Error messages must clearly specify the requested operation, missing permission, active profile/identity, available matching profiles, and a concrete operator action (e.g. relaunch profile or alternative namespace). The runtime context tool should list all permitted and forbidden operations for transparency.

Safety invariants

  • Non-negotiable block on self-review and self-merge (enforced at the controller level).
  • Strict separation of duties: author profile cannot merge/approve; reviewer profile cannot push/commit unless explicitly enabled.
  • Fail closed on any missing, stale, or ambiguous evidence.
  • No credentials, keychain IDs, or raw Gitea endpoints exposed in any responses or logs.

Suggested implementation issues

  1. Add stateless gitea_resolve_task_capability tool to the MCP surface.
  2. Standardize error message formatting and fail-closed response structures across all Gitea MCP operations.
  3. Add automated test coverage to verify role/capability resolution and assert separation of duties under static profiles.

Risks / tradeoffs

  • Tradeoff: Slightly higher client/orchestrator complexity since the LLM must handle switching namespaces or requesting profile restarts, rather than the server silently shifting profiles.
  • Risk: If the client does not support multi-namespace MCP environments, the developer must manually relaunch the server with a different profile, slightly slowing down automated developer workflows in exchange for absolute safety.

Final recommendation

  • Implement the stateless gitea_resolve_task_capability tool first to enable self-discovery, standardizing the Dual Namespace model as the core safety architecture.
## Independent design review — Antigravity / 7fd11282 ### Posting status * Posted to issue thread: yes * Tool used: `gitea_create_issue_comment` * Authenticated identity/profile: `jcwalker3` / `prgs-author` ### Recommended model * Dual namespace / dynamic profile / dispatcher / hybrid: Hybrid (Dual Namespace with stateless Routing Resolver) * Why: Maintains the highest security boundary by isolating credentials at the container/session level (avoiding session contamination and privilege escalation via prompt injection). The routing resolver tool eliminates LLM guesswork by providing clear, actionable next steps for namespace routing. ### Role/capability resolver recommendation * Should add resolver tool: yes * Suggested tool name: `gitea_resolve_task_capability` * Required output fields: `requested_operation`, `required_permission`, `required_role_kind`, `active_profile`, `active_identity`, `allowed_in_current_session`, `available_matching_profiles`, `runtime_switching_supported`, `next_safe_action` ### Issue-comment permission recommendation * Should `prgs-author` have `gitea.issue.comment`: yes * Should `prgs-reviewer` have `gitea.issue.comment`: yes * Permissions that must remain separate: `gitea.issue.comment` must not imply `gitea.pr.comment`, `gitea.issue.close`, or any mutating review/merge permissions. ### Error-message / runtime-context recommendation * Error messages must clearly specify the requested operation, missing permission, active profile/identity, available matching profiles, and a concrete operator action (e.g. relaunch profile or alternative namespace). The runtime context tool should list all permitted and forbidden operations for transparency. ### Safety invariants * Non-negotiable block on self-review and self-merge (enforced at the controller level). * Strict separation of duties: author profile cannot merge/approve; reviewer profile cannot push/commit unless explicitly enabled. * Fail closed on any missing, stale, or ambiguous evidence. * No credentials, keychain IDs, or raw Gitea endpoints exposed in any responses or logs. ### Suggested implementation issues 1. Add stateless `gitea_resolve_task_capability` tool to the MCP surface. 2. Standardize error message formatting and fail-closed response structures across all Gitea MCP operations. 3. Add automated test coverage to verify role/capability resolution and assert separation of duties under static profiles. ### Risks / tradeoffs * **Tradeoff**: Slightly higher client/orchestrator complexity since the LLM must handle switching namespaces or requesting profile restarts, rather than the server silently shifting profiles. * **Risk**: If the client does not support multi-namespace MCP environments, the developer must manually relaunch the server with a different profile, slightly slowing down automated developer workflows in exchange for absolute safety. ### Final recommendation * Implement the stateless `gitea_resolve_task_capability` tool first to enable self-discovery, standardizing the Dual Namespace model as the core safety architecture.
Author
Owner

Independent design review — Grok (xAI)

Session context (captured at time of review):

  • Remote: prgs
  • Active profile: prgs-author (role_kind: author)
  • Authenticated identity: jcwalker3 (verified)
  • Runtime mode: static-profile, runtime_switching_supported: false
  • Allowed (relevant): gitea.issue.comment, gitea.pr.comment, gitea.pr.create, gitea.branch.*, gitea.read, gitea.repo.commit
  • Forbidden: gitea.pr.approve, gitea.pr.merge, gitea.pr.request_changes
  • Reviewer profile prgs-reviewer exists with complementary permissions (also has gitea.issue.comment) and separate identity (sysadmin).
  • gitea_get_runtime_context and mcp_get_control_plane_guide already provide strong signals.

Posting status

  • Posted to issue thread: (tool result pending confirmation)
  • Tool used: gitea_create_issue_comment (via gitea-tools MCP)
  • Authenticated identity/profile: jcwalker3 / prgs-author (prgs remote)

Recommended model

  • Dual namespace model (primary recommendation) with optional dispatcher layer for scale.
  • Why:
    • Explicit separation of duties is the simplest, most auditable, and least error-prone approach.
    • Static launcher profiles (prgs-author, prgs-reviewer) with distinct keychain identities enforce the author/reviewer boundary at the connection layer before any LLM reasoning.
    • LLMs cannot "guess" or "pretend" to be the other role; they must reconnect or select the correct MCP namespace.
    • Dynamic profile switching (even gated) adds attack surface and audit complexity; only enable if allow_runtime_switching: true + fresh whoami after every switch + strong logging.
    • Dispatcher is attractive for a "single front door" but increases implementation risk and still requires the internal routing to apply the exact same hard gates. Start with dual namespace + clear resolver output that names the correct namespace.

Current state on prgs already approximates a healthy dual-namespace setup (different profiles, different identities, complementary permissions).

Role/capability resolver recommendation

  • Should add resolver tool: yes (or strongly enhance existing tools).
  • Suggested tool name: gitea_resolve_task_capability (new dedicated tool) or extend gitea_get_runtime_context + a task-specific variant.
  • Required output fields (minimum):
    • requested_operation / task
    • required_permission (e.g. gitea.issue.comment, gitea.pr.approve)
    • required_role_kind (author | reviewer | merger | any)
    • active_profile
    • active_identity
    • active_profile_can_perform: bool
    • matching_configured_profiles: list
    • runtime_switching_supported: bool
    • requires_different_namespace: bool
    • suggested_namespace_or_profile
    • safe_next_action (exact operator/LLM instruction)
    • reasons (fail-closed details)

Existing gitea_get_runtime_context already returns excellent fields (allowed_operations, forbidden_operations, suggested_fix, safe_next_action, profile_mode). A dedicated resolver would make task-driven calls ("review this PR", "comment on issue #139") first-class.

Issue-comment permission recommendation

  • Should prgs-author have gitea.issue.comment: yes (currently granted and correct).
  • Should prgs-reviewer have gitea.issue.comment: yes (currently granted and correct).
  • Permissions that must remain separate (non-negotiable):
    • gitea.pr.comment does not imply gitea.issue.comment (and vice versa)
    • gitea.issue.comment does not imply gitea.close_issue or label changes that close
    • gitea.pr.review / approve / merge remain strictly reviewer-only
    • Author profiles must never gain gitea.pr.approve / merge
    • Reviewer profiles must not gain gitea.branch.create|push|pr.create|repo.commit unless a separate "reviewer-with-author" hybrid is explicitly documented and configured

Current config on prgs correctly separates these. The fact that #137 was required to grant gitea.issue.comment shows the separation was being respected (good).

Error-message / runtime-context recommendation

When blocked, every relevant tool and the resolver must surface (redacted but actionable):

  • active identity + active profile
  • missing permission vs required permission
  • matching configured profile(s) if any
  • profile_mode + runtime_switching_supported
  • requires_different_namespace + exact namespace/profile name
  • exact operator action (e.g. "Launch/connect the gitea-reviewer MCP session for prgs" or "Set GITEA_MCP_PROFILE=prgs-reviewer and restart the MCP server")

gitea_get_runtime_context already does a good job here. Make this the canonical pre-flight for any mutating or review task. Never allow silent fallbacks.

Safety invariants

These must remain non-negotiable (fail closed, no exceptions):

  • No self-review and no self-merge (authenticated user != PR author)
  • Author profiles cannot approve, request_changes, or merge
  • Reviewer profiles should not gain branch push / repo commit unless a named hybrid profile is created and documented
  • gitea.issue.comment must not imply issue close/reopen/set labels that change state in a closing way
  • gitea.pr.comment must not imply gitea.issue.comment
  • No production/deploy permissions, no secrets, no raw tokens/keychain IDs/endpoints in normal output
  • Head SHA pinning before review/merge
  • Explicit confirmation string for merges
  • Every gate fails closed on ambiguity, unknown profile, or missing permission
  • LLMs must verify via whoami + runtime context before acting; they must not hardcode identities

Suggested implementation issues

  • Create gitea_resolve_task_capability (or equivalent) + tests for the example tasks listed in #139
  • Add task-specific pre-flight usage to skills / operator guide / control plane guide
  • Document the dual-namespace model as the default safe pattern (with prgs-author / prgs-reviewer examples)
  • Add tests that prove:
    • correct profile for create-issue / comment-issue / claim / branch / push / open-PR / review-PR / merge-PR / close-issue
    • issue-comment requires explicit grant and does not broaden other perms
    • static vs dynamic mode produces correct resolver output
    • self-review/self-merge still blocked even when reviewer profile is active
  • Update mcp_get_control_plane_guide and gitea_get_runtime_context docs to reference the resolver
  • Follow-up for optional dispatcher front-door (lower priority)

Risks / tradeoffs

  • Dual namespace: more launcher sessions to manage, but strongest isolation. Risk: operator confusion about which MCP to connect.
  • Dynamic switching: convenient but higher risk of stale identity after switch; requires mandatory re-verification + audit.
  • Dispatcher: elegant but complex; risk of routing bugs that bypass gates.
  • Adding resolver: low risk if it is read-only and only advises; must never bypass the actual tool permission checks.
  • Broadening issue.comment too widely: would allow comment spam from any profile — keep it explicit per profile.

Final recommendation

  1. Treat this as a capability-resolution + namespace-selection problem, not a prompt engineering problem.
  2. Standardize on the dual namespace model for prgs (and similar) with prgs-author / prgs-reviewer (and equivalents).
  3. Add/enhance a gitea_resolve_task_capability tool that returns the fields above; make it the first call for any task that may mutate or review.
  4. Confirm gitea.issue.comment is granted exactly where intended (it appears to be for both prgs profiles now).
  5. Keep all existing hard gates (self-review, separation of author/reviewer, fail-closed, redaction).
  6. Improve error surfaces and update docs/guides so new LLMs never have to reason about launcher profiles.
  7. Add the recommended tests.

Do not weaken any gate to "make it easier." The safety model is working when it forces the correct profile/namespace to be used.

This review was performed read-only using inspection tools only. No code, branches, PRs, or config changes were made.

## Independent design review — Grok (xAI) **Session context (captured at time of review):** - Remote: `prgs` - Active profile: `prgs-author` (role_kind: author) - Authenticated identity: `jcwalker3` (verified) - Runtime mode: static-profile, `runtime_switching_supported: false` - Allowed (relevant): `gitea.issue.comment`, `gitea.pr.comment`, `gitea.pr.create`, `gitea.branch.*`, `gitea.read`, `gitea.repo.commit` - Forbidden: `gitea.pr.approve`, `gitea.pr.merge`, `gitea.pr.request_changes` - Reviewer profile `prgs-reviewer` exists with complementary permissions (also has `gitea.issue.comment`) and separate identity (`sysadmin`). - `gitea_get_runtime_context` and `mcp_get_control_plane_guide` already provide strong signals. ### Posting status * Posted to issue thread: (tool result pending confirmation) * Tool used: `gitea_create_issue_comment` (via gitea-tools MCP) * Authenticated identity/profile: `jcwalker3` / `prgs-author` (prgs remote) ### Recommended model * **Dual namespace model (primary recommendation) with optional dispatcher layer for scale.** * Why: - Explicit separation of duties is the simplest, most auditable, and least error-prone approach. - Static launcher profiles (`prgs-author`, `prgs-reviewer`) with distinct keychain identities enforce the author/reviewer boundary at the connection layer before any LLM reasoning. - LLMs cannot "guess" or "pretend" to be the other role; they must reconnect or select the correct MCP namespace. - Dynamic profile switching (even gated) adds attack surface and audit complexity; only enable if `allow_runtime_switching: true` + fresh whoami after every switch + strong logging. - Dispatcher is attractive for a "single front door" but increases implementation risk and still requires the internal routing to apply the exact same hard gates. Start with dual namespace + clear resolver output that names the correct namespace. Current state on `prgs` already approximates a healthy dual-namespace setup (different profiles, different identities, complementary permissions). ### Role/capability resolver recommendation * Should add resolver tool: **yes** (or strongly enhance existing tools). * Suggested tool name: `gitea_resolve_task_capability` (new dedicated tool) or extend `gitea_get_runtime_context` + a task-specific variant. * Required output fields (minimum): - requested_operation / task - required_permission (e.g. `gitea.issue.comment`, `gitea.pr.approve`) - required_role_kind (author | reviewer | merger | any) - active_profile - active_identity - active_profile_can_perform: bool - matching_configured_profiles: list - runtime_switching_supported: bool - requires_different_namespace: bool - suggested_namespace_or_profile - safe_next_action (exact operator/LLM instruction) - reasons (fail-closed details) Existing `gitea_get_runtime_context` already returns excellent fields (`allowed_operations`, `forbidden_operations`, `suggested_fix`, `safe_next_action`, `profile_mode`). A dedicated resolver would make task-driven calls ("review this PR", "comment on issue #139") first-class. ### Issue-comment permission recommendation * Should `prgs-author` have `gitea.issue.comment`: **yes** (currently granted and correct). * Should `prgs-reviewer` have `gitea.issue.comment`: **yes** (currently granted and correct). * Permissions that must remain separate (non-negotiable): - `gitea.pr.comment` does **not** imply `gitea.issue.comment` (and vice versa) - `gitea.issue.comment` does **not** imply `gitea.close_issue` or label changes that close - `gitea.pr.review` / approve / merge remain strictly reviewer-only - Author profiles must never gain `gitea.pr.approve` / merge - Reviewer profiles must not gain `gitea.branch.create|push|pr.create|repo.commit` unless a separate "reviewer-with-author" hybrid is explicitly documented and configured Current config on `prgs` correctly separates these. The fact that #137 was required to grant `gitea.issue.comment` shows the separation was being respected (good). ### Error-message / runtime-context recommendation When blocked, every relevant tool and the resolver must surface (redacted but actionable): - active identity + active profile - missing permission vs required permission - matching configured profile(s) if any - profile_mode + runtime_switching_supported - requires_different_namespace + exact namespace/profile name - exact operator action (e.g. "Launch/connect the `gitea-reviewer` MCP session for prgs" or "Set GITEA_MCP_PROFILE=prgs-reviewer and restart the MCP server") `gitea_get_runtime_context` already does a good job here. Make this the canonical pre-flight for any mutating or review task. Never allow silent fallbacks. ### Safety invariants These must remain non-negotiable (fail closed, no exceptions): - No self-review and no self-merge (authenticated user != PR author) - Author profiles cannot approve, request_changes, or merge - Reviewer profiles should not gain branch push / repo commit unless a named hybrid profile is created and documented - `gitea.issue.comment` must not imply issue close/reopen/set labels that change state in a closing way - `gitea.pr.comment` must not imply `gitea.issue.comment` - No production/deploy permissions, no secrets, no raw tokens/keychain IDs/endpoints in normal output - Head SHA pinning before review/merge - Explicit confirmation string for merges - Every gate fails closed on ambiguity, unknown profile, or missing permission - LLMs must verify via whoami + runtime context before acting; they must not hardcode identities ### Suggested implementation issues - Create `gitea_resolve_task_capability` (or equivalent) + tests for the example tasks listed in #139 - Add task-specific pre-flight usage to skills / operator guide / control plane guide - Document the dual-namespace model as the default safe pattern (with prgs-author / prgs-reviewer examples) - Add tests that prove: - correct profile for create-issue / comment-issue / claim / branch / push / open-PR / review-PR / merge-PR / close-issue - issue-comment requires explicit grant and does not broaden other perms - static vs dynamic mode produces correct resolver output - self-review/self-merge still blocked even when reviewer profile is active - Update mcp_get_control_plane_guide and gitea_get_runtime_context docs to reference the resolver - Follow-up for optional dispatcher front-door (lower priority) ### Risks / tradeoffs - Dual namespace: more launcher sessions to manage, but strongest isolation. Risk: operator confusion about which MCP to connect. - Dynamic switching: convenient but higher risk of stale identity after switch; requires mandatory re-verification + audit. - Dispatcher: elegant but complex; risk of routing bugs that bypass gates. - Adding resolver: low risk if it is read-only and only advises; must never bypass the actual tool permission checks. - Broadening issue.comment too widely: would allow comment spam from any profile — keep it explicit per profile. ### Final recommendation 1. Treat this as a **capability-resolution + namespace-selection** problem, not a prompt engineering problem. 2. Standardize on the **dual namespace model** for prgs (and similar) with `prgs-author` / `prgs-reviewer` (and equivalents). 3. Add/enhance a `gitea_resolve_task_capability` tool that returns the fields above; make it the first call for any task that may mutate or review. 4. Confirm `gitea.issue.comment` is granted exactly where intended (it appears to be for both prgs profiles now). 5. Keep all existing hard gates (self-review, separation of author/reviewer, fail-closed, redaction). 6. Improve error surfaces and update docs/guides so new LLMs never have to reason about launcher profiles. 7. Add the recommended tests. Do not weaken any gate to "make it easier." The safety model is working when it forces the correct profile/namespace to be used. This review was performed read-only using inspection tools only. No code, branches, PRs, or config changes were made.
Author
Owner

Independent design review — Codex GPT-5 session

Posting status

  • Posted to issue thread: yes
  • Tool used: gitea_create_issue_comment via mcp__gitea_author
  • Authenticated identity/profile: jcwalker3 / prgs-author

Recommended model

  • Dual namespace / dynamic profile / dispatcher / hybrid: hybrid, with dual namespace as the immediate operating model and dispatcher as the longer-term control-plane model.
  • Why: dual namespace keeps high-risk review/merge boundaries explicit today, which is valuable while the system is still proving its gates. A dispatcher is the better eventual user experience because task routing belongs in MCP, not in prompts or LLM memory. Dynamic switching is the riskiest option unless it is explicit, audited, config-enabled, and followed by fresh identity proof on every switch.

Role/capability resolver recommendation

  • Should add resolver tool: yes.
  • Suggested tool name: gitea_route_task for task-level workflows, backed by a lower-level gitea_resolve_task_capability helper if needed.
  • Required output fields: requested task, normalized operation, required permission, required role kind, target remote/org/repo, active profile, active identity, active-profile eligibility, matching configured profiles, static/dynamic/dispatcher mode, whether switching is supported, whether another MCP namespace is required, exact safe next action, and redacted block reasons.

The resolver should use an explicit task-to-permission table rather than infer from strings. Suggested mappings:

  • create issue: gitea.issue.create, author-capable profile.
  • comment on issue discussion: gitea.issue.comment, author or reviewer if explicitly granted.
  • claim issue: gitea.issue.claim or the existing mark/label permission, author-capable unless separately delegated.
  • create branch: gitea.branch.create, author.
  • push branch: gitea.branch.push, author.
  • open PR: gitea.pr.create, author.
  • review PR: gitea.pr.review plus verdict-specific gitea.pr.approve or gitea.pr.request_changes, reviewer.
  • merge PR: gitea.pr.merge, merger/reviewer only if explicitly configured, with existing merge confirmation gates.
  • close stale PR: separate gitea.pr.close, not implied by review or merge.
  • close issue: separate gitea.issue.close, not implied by issue-comment.
  • trigger Jenkins: Jenkins-specific operation such as jenkins.build.trigger, never implied by Gitea permissions.
  • file GlitchTip issue into Gitea: read permission on GlitchTip plus gitea.issue.create on the target repo.

Issue-comment permission recommendation

  • Should prgs-author have gitea.issue.comment: yes, because authors need to update implementation notes, ask clarifying questions, and report completion/blockers in issue discussions.
  • Should prgs-reviewer have gitea.issue.comment: yes, because reviewers need to leave non-review discussion notes without submitting formal PR review state.
  • Permissions that must remain separate: gitea.pr.comment, gitea.pr.review, gitea.pr.approve, gitea.pr.request_changes, gitea.pr.merge, gitea.issue.comment, gitea.issue.close, branch push, repo commit, Jenkins trigger, and any deployment/production operation.

Tests should prove that gitea.pr.comment does not satisfy gitea.issue.comment, gitea.issue.comment does not satisfy gitea.issue.close, reviewer profiles still cannot push or commit unless explicitly configured, and author profiles still cannot approve or merge.

Error-message / runtime-context recommendation

Blocked operations should return: requested task, normalized required permission, active identity, active profile, forbidden and allowed operation summaries, missing permission, matching configured profile if known, whether runtime switching is enabled, whether a different namespace is required, and one exact operator action.

The message should be deterministic and action-oriented. Example: Cannot review PR from active profile prgs-author as jcwalker3. Required permission: gitea.pr.approve. Matching configured profile: prgs-reviewer. Runtime switching: disabled. Safe next action: use the gitea-reviewer MCP namespace or relaunch with GITEA_MCP_PROFILE=prgs-reviewer.

Runtime context should also expose a capability matrix such as can_create_issue, can_comment_issue, can_open_pr, can_review_pr, can_merge_pr, can_close_issue, can_read_jenkins, and can_trigger_jenkins, without exposing tokens, keychain IDs, raw service URLs, or private config values.

Safety invariants

  • No self-review or self-merge.
  • Author profiles cannot approve or merge.
  • Reviewer profiles cannot branch, push, or commit unless explicitly configured.
  • Issue-comment permission must not imply issue-close.
  • PR-comment permission must not imply issue-comment.
  • Review/approve/request-changes must remain formal PR review operations, not issue comments.
  • Merge must require explicit confirmation and head-SHA/change-set checks where available.
  • Jenkins/GlitchTip permissions must be service-scoped and never inferred from Gitea permissions.
  • No production/deploy permissions in this workflow.
  • No secrets, tokens, keychain IDs, raw service URLs, Authorization headers, or private config values in MCP output.
  • Fail closed on unknown task, unknown permission, ambiguous profile match, disabled profile, missing identity proof, or moved PR head.

Suggested implementation issues

  • Add the task-to-required-capability table and tests for every listed task.
  • Add gitea_route_task or equivalent resolver output with safe next-action guidance.
  • Add runtime context capability matrix output.
  • Add tests that author/reviewer profiles with gitea.issue.comment can post issue comments while profiles without it fail closed.
  • Add tests proving PR comment, issue comment, issue close, PR review, and PR merge do not imply each other.
  • Improve blocked-operation errors to include active profile, active identity, missing permission, matching configured profile, switching mode, and exact operator action.
  • Document the dual-namespace operating model now and the dispatcher model as the preferred long-term direction.

Risks / tradeoffs

Dual namespace is safer and easier to audit immediately, but it still requires the operator or LLM to choose the right namespace. Dynamic switching can reduce friction but creates a sharp edge unless every switch is explicit, audited, config-gated, and followed by identity verification. Dispatcher routing gives the best user experience, but it increases control-plane complexity and must be built so it never bypasses the existing per-action gates.

Granting gitea.issue.comment to both author and reviewer profiles is a small and useful permission broadening, but only if tests keep it separate from PR review, issue close, and merge permissions.

Final recommendation

Standardize the dual-namespace model immediately, grant gitea.issue.comment explicitly to both PRGS author and reviewer profiles, and add a gitea_route_task resolver before attempting dynamic profile switching. Treat dispatcher routing as the target architecture once the resolver and capability matrix are well tested. Do not make permission implications implicit; every task should map to a named capability and every mutating action should continue to run through its own gate.

## Independent design review — Codex GPT-5 session ### Posting status * Posted to issue thread: yes * Tool used: `gitea_create_issue_comment` via `mcp__gitea_author` * Authenticated identity/profile: `jcwalker3` / `prgs-author` ### Recommended model * Dual namespace / dynamic profile / dispatcher / hybrid: hybrid, with dual namespace as the immediate operating model and dispatcher as the longer-term control-plane model. * Why: dual namespace keeps high-risk review/merge boundaries explicit today, which is valuable while the system is still proving its gates. A dispatcher is the better eventual user experience because task routing belongs in MCP, not in prompts or LLM memory. Dynamic switching is the riskiest option unless it is explicit, audited, config-enabled, and followed by fresh identity proof on every switch. ### Role/capability resolver recommendation * Should add resolver tool: yes. * Suggested tool name: `gitea_route_task` for task-level workflows, backed by a lower-level `gitea_resolve_task_capability` helper if needed. * Required output fields: requested task, normalized operation, required permission, required role kind, target remote/org/repo, active profile, active identity, active-profile eligibility, matching configured profiles, static/dynamic/dispatcher mode, whether switching is supported, whether another MCP namespace is required, exact safe next action, and redacted block reasons. The resolver should use an explicit task-to-permission table rather than infer from strings. Suggested mappings: * create issue: `gitea.issue.create`, author-capable profile. * comment on issue discussion: `gitea.issue.comment`, author or reviewer if explicitly granted. * claim issue: `gitea.issue.claim` or the existing mark/label permission, author-capable unless separately delegated. * create branch: `gitea.branch.create`, author. * push branch: `gitea.branch.push`, author. * open PR: `gitea.pr.create`, author. * review PR: `gitea.pr.review` plus verdict-specific `gitea.pr.approve` or `gitea.pr.request_changes`, reviewer. * merge PR: `gitea.pr.merge`, merger/reviewer only if explicitly configured, with existing merge confirmation gates. * close stale PR: separate `gitea.pr.close`, not implied by review or merge. * close issue: separate `gitea.issue.close`, not implied by issue-comment. * trigger Jenkins: Jenkins-specific operation such as `jenkins.build.trigger`, never implied by Gitea permissions. * file GlitchTip issue into Gitea: read permission on GlitchTip plus `gitea.issue.create` on the target repo. ### Issue-comment permission recommendation * Should `prgs-author` have `gitea.issue.comment`: yes, because authors need to update implementation notes, ask clarifying questions, and report completion/blockers in issue discussions. * Should `prgs-reviewer` have `gitea.issue.comment`: yes, because reviewers need to leave non-review discussion notes without submitting formal PR review state. * Permissions that must remain separate: `gitea.pr.comment`, `gitea.pr.review`, `gitea.pr.approve`, `gitea.pr.request_changes`, `gitea.pr.merge`, `gitea.issue.comment`, `gitea.issue.close`, branch push, repo commit, Jenkins trigger, and any deployment/production operation. Tests should prove that `gitea.pr.comment` does not satisfy `gitea.issue.comment`, `gitea.issue.comment` does not satisfy `gitea.issue.close`, reviewer profiles still cannot push or commit unless explicitly configured, and author profiles still cannot approve or merge. ### Error-message / runtime-context recommendation Blocked operations should return: requested task, normalized required permission, active identity, active profile, forbidden and allowed operation summaries, missing permission, matching configured profile if known, whether runtime switching is enabled, whether a different namespace is required, and one exact operator action. The message should be deterministic and action-oriented. Example: `Cannot review PR from active profile prgs-author as jcwalker3. Required permission: gitea.pr.approve. Matching configured profile: prgs-reviewer. Runtime switching: disabled. Safe next action: use the gitea-reviewer MCP namespace or relaunch with GITEA_MCP_PROFILE=prgs-reviewer.` Runtime context should also expose a capability matrix such as `can_create_issue`, `can_comment_issue`, `can_open_pr`, `can_review_pr`, `can_merge_pr`, `can_close_issue`, `can_read_jenkins`, and `can_trigger_jenkins`, without exposing tokens, keychain IDs, raw service URLs, or private config values. ### Safety invariants * No self-review or self-merge. * Author profiles cannot approve or merge. * Reviewer profiles cannot branch, push, or commit unless explicitly configured. * Issue-comment permission must not imply issue-close. * PR-comment permission must not imply issue-comment. * Review/approve/request-changes must remain formal PR review operations, not issue comments. * Merge must require explicit confirmation and head-SHA/change-set checks where available. * Jenkins/GlitchTip permissions must be service-scoped and never inferred from Gitea permissions. * No production/deploy permissions in this workflow. * No secrets, tokens, keychain IDs, raw service URLs, Authorization headers, or private config values in MCP output. * Fail closed on unknown task, unknown permission, ambiguous profile match, disabled profile, missing identity proof, or moved PR head. ### Suggested implementation issues * Add the task-to-required-capability table and tests for every listed task. * Add `gitea_route_task` or equivalent resolver output with safe next-action guidance. * Add runtime context capability matrix output. * Add tests that author/reviewer profiles with `gitea.issue.comment` can post issue comments while profiles without it fail closed. * Add tests proving PR comment, issue comment, issue close, PR review, and PR merge do not imply each other. * Improve blocked-operation errors to include active profile, active identity, missing permission, matching configured profile, switching mode, and exact operator action. * Document the dual-namespace operating model now and the dispatcher model as the preferred long-term direction. ### Risks / tradeoffs Dual namespace is safer and easier to audit immediately, but it still requires the operator or LLM to choose the right namespace. Dynamic switching can reduce friction but creates a sharp edge unless every switch is explicit, audited, config-gated, and followed by identity verification. Dispatcher routing gives the best user experience, but it increases control-plane complexity and must be built so it never bypasses the existing per-action gates. Granting `gitea.issue.comment` to both author and reviewer profiles is a small and useful permission broadening, but only if tests keep it separate from PR review, issue close, and merge permissions. ### Final recommendation Standardize the dual-namespace model immediately, grant `gitea.issue.comment` explicitly to both PRGS author and reviewer profiles, and add a `gitea_route_task` resolver before attempting dynamic profile switching. Treat dispatcher routing as the target architecture once the resolver and capability matrix are well tested. Do not make permission implications implicit; every task should map to a named capability and every mutating action should continue to run through its own gate.
Author
Owner

MCP issue-comment path verified ✔

Posted via gitea_create_issue_comment from the reconnected MCP session — jcwalker3 / prgs-author, whose allowed operations now include gitea.issue.comment after the #137/#138 migration (alias fix merged at 995bd16, live profile config updated, session reconnected).

This closes the loop on failure example 2 in this issue's body: the exact workflow that previously failed closed (profile is not allowed to gitea.issue.comment, blocking the mcp-control-plane #51 audit comment) now succeeds through the gated MCP tool. PR #140 adds the forward-direction permission-separation tests pinning this behavior.

## MCP issue-comment path verified ✔ Posted via `gitea_create_issue_comment` from the reconnected MCP session — `jcwalker3` / `prgs-author`, whose allowed operations now include `gitea.issue.comment` after the #137/#138 migration (alias fix merged at `995bd16`, live profile config updated, session reconnected). This closes the loop on failure example 2 in this issue's body: the exact workflow that previously failed closed (`profile is not allowed to gitea.issue.comment`, blocking the mcp-control-plane #51 audit comment) now succeeds through the gated MCP tool. PR #140 adds the forward-direction permission-separation tests pinning this behavior.
Author
Owner

Gitea-Tools #139 Child Issues Created

Based on the design consensus reached in this thread, five child issues have been created to implement the resolved static dual-namespace task routing capability:

  1. #141: Add read-only Gitea task capability resolver
  2. #142: Add structured permission failure reports to gated Gitea MCP tools
  3. #143: Document static dual-namespace Gitea MCP deployment model
  4. #144: Update Gitea operator guide and skill registry for role-aware task routing
  5. #145: Add task-routing and permission-boundary regression tests

These issues will track the incremental delivery of the resolver, structured reporting, updated guide/docs, and synthetic regression tests. Issue #139 will remain open until these sub-tasks are resolved.

## Gitea-Tools #139 Child Issues Created Based on the design consensus reached in this thread, five child issues have been created to implement the resolved static dual-namespace task routing capability: 1. **#141**: Add read-only Gitea task capability resolver 2. **#142**: Add structured permission failure reports to gated Gitea MCP tools 3. **#143**: Document static dual-namespace Gitea MCP deployment model 4. **#144**: Update Gitea operator guide and skill registry for role-aware task routing 5. **#145**: Add task-routing and permission-boundary regression tests These issues will track the incremental delivery of the resolver, structured reporting, updated guide/docs, and synthetic regression tests. Issue #139 will remain open until these sub-tasks are resolved.
Author
Owner

Jenkins & GlitchTip MCP Integration Child Issues Created

Following the operator decision on the Jenkins and GlitchTip MCP status audit, five child implementation issues have been created to track the remaining gaps:

  1. #146: Fix MCP registration and naming for Jenkins/GlitchTip servers
  2. #147: Correct Jenkins trigger safety boundary
  3. #148: Complete GlitchTip-to-Gitea filing orchestrator
  4. #149: Update operator runbooks and roadmap docs
  5. #150: Add integration/discoverability coverage

These issues will track the necessary work to align the safety boundaries, audits, naming conventions, and docs for the Jenkins and GlitchTip integrations. Issue #139 remains open.

## Jenkins & GlitchTip MCP Integration Child Issues Created Following the operator decision on the Jenkins and GlitchTip MCP status audit, five child implementation issues have been created to track the remaining gaps: 1. **#146**: Fix MCP registration and naming for Jenkins/GlitchTip servers 2. **#147**: Correct Jenkins trigger safety boundary 3. **#148**: Complete GlitchTip-to-Gitea filing orchestrator 4. **#149**: Update operator runbooks and roadmap docs 5. **#150**: Add integration/discoverability coverage These issues will track the necessary work to align the safety boundaries, audits, naming conventions, and docs for the Jenkins and GlitchTip integrations. Issue #139 remains open.
jcwalker3 added the status:in-progress label 2026-07-06 11:40:09 -05:00
Author
Owner

Starting work on role-aware runtime context.

Branch: feat/issue-139-role-aware-runtime-context

First slice: extend gitea_get_runtime_context with per-task session capability flags (author / issue-comment / review / merge / close) and redacted matching-profile hints so LLMs can ask "can I review?" or "can I comment on issues?" without guessing launcher config.

Refs #139

Starting work on role-aware runtime context. **Branch:** `feat/issue-139-role-aware-runtime-context` **First slice:** extend `gitea_get_runtime_context` with per-task session capability flags (author / issue-comment / review / merge / close) and redacted matching-profile hints so LLMs can ask "can I review?" or "can I comment on issues?" without guessing launcher config. Refs #139
sysadmin removed the status:in-progress label 2026-07-06 12:29:09 -05:00
jcwalker3 added the status:in-progress label 2026-07-07 08:28:54 -05:00
Author
Owner

Opened PR #385 — registers work_issue / work-issue in the role-aware resolver and session router, documents pre-task routing in the canonical work-issue workflow, and adds workflow-source verification tests.

Most other #139 acceptance criteria were already on master (resolver, runtime context, dual-namespace docs). This closes the remaining gap for the default author prompt path.

Opened PR #385 — registers `work_issue` / `work-issue` in the role-aware resolver and session router, documents pre-task routing in the canonical work-issue workflow, and adds workflow-source verification tests. Most other #139 acceptance criteria were already on master (resolver, runtime context, dual-namespace docs). This closes the remaining gap for the default author prompt path.
sysadmin removed the status:in-progress label 2026-07-07 10:24:06 -05:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Scaled-Tech-Consulting/Gitea-Tools#139