fix(mcp): invalidate review session state on cross-profile activation (Closes #690)
A mid-run profile switch (reviewer -> author -> reviewer) left workflow-load proof, reviewer lease binding, the review decision lock, live namespace health, and preflight identity/capability stamps intact, so a formal verdict could be recorded under contaminated session state. - gitea_activate_profile now invalidates all review-critical session state on a cross-profile switch, in memory and in durable state keyed by either profile identity, and reports the invalidation + re-preflight requirement. - Full reviewer preflight (whoami, load_review_workflow, resolve_task_capability(review_pr), head re-pin, lease re-acquire) is required before any formal verdict after a switch; switching back cannot resurrect the stale run. - Namespace provenance: optional launcher-declared GITEA_MCP_NAMESPACE is reported by whoami/runtime context/capability resolution, and a declared namespace that disagrees with a task's required namespace fails closed. - Docs: supported pattern is separate session/namespace per role, not in-process profile hopping mid-review.
This commit is contained in:
@@ -589,6 +589,47 @@ When dynamic profile switching is enabled and a profile is activated via `gitea_
|
||||
2. Call `gitea_whoami` with the target remote to prove and verify the fresh Gitea authenticated identity.
|
||||
This guarantees the active profile operations align with the actual Gitea authenticated user credential.
|
||||
|
||||
### 4. Review-State Invalidation on Profile Switch (#690)
|
||||
|
||||
A cross-profile activation (e.g. reviewer → author → reviewer) is a session
|
||||
boundary for formal review state. On any switch where the activated profile
|
||||
differs from the previous one, `gitea_activate_profile` invalidates, in
|
||||
memory **and** in durable session state (for both the old and new profile
|
||||
identities):
|
||||
|
||||
- preflight identity/capability stamps (`gitea_whoami` / `gitea_resolve_task_capability` proof),
|
||||
- review workflow-load proof (`gitea_load_review_workflow`),
|
||||
- the review decision lock (including `final_review_decision_ready` markers),
|
||||
- the reviewer PR session lease binding,
|
||||
- live namespace-health assessments.
|
||||
|
||||
Before any formal verdict (`gitea_mark_final_review_decision` /
|
||||
`gitea_submit_pr_review`) the full reviewer preflight must be re-established
|
||||
under the new profile: `gitea_whoami`, `gitea_load_review_workflow`,
|
||||
`gitea_resolve_task_capability(review_pr)`, live head re-pin, and lease
|
||||
re-acquire/adopt. Switching back to the earlier profile does **not**
|
||||
resurrect the prior run — durable state keyed by either profile identity is
|
||||
cleared at switch time.
|
||||
|
||||
The supported pattern remains **separate session/namespace per role**
|
||||
(dual-namespace, §2): file author-side follow-ups from an author session,
|
||||
not by hopping profiles inside a formal review run. Runtime profile
|
||||
switching is the operator-approved exception and always carries the
|
||||
re-preflight cost above.
|
||||
|
||||
### 5. Namespace Provenance (#690)
|
||||
|
||||
The server cannot derive its own client-managed MCP namespace name, so a
|
||||
launcher may declare it via the `GITEA_MCP_NAMESPACE` environment variable
|
||||
(e.g. `gitea-reviewer`). `gitea_whoami`, `gitea_get_runtime_context`, and
|
||||
`gitea_resolve_task_capability` report `namespace_provenance` — the
|
||||
configured client namespace, the active execution profile, and, for tasks
|
||||
with a required namespace (`review_pr` → `gitea-reviewer`, `merge_pr` →
|
||||
`gitea-merger`), a mismatch verdict. A declared namespace that disagrees
|
||||
with the requested task's required namespace **fails closed**. An
|
||||
undeclared namespace is reported as `unknown` and is never treated as
|
||||
proof either way.
|
||||
|
||||
## Gitea MCP Runtime Isolation and Worktree Safety
|
||||
|
||||
To ensure high availability and prevent broken feature worktrees from disabling essential security/identity controls, the Gitea MCP server implements runtime isolation:
|
||||
|
||||
@@ -86,3 +86,24 @@ When a namespace returns EOF, follow
|
||||
|
||||
When blocked, repair the IDE namespace and re-record a healthy
|
||||
`client_namespace` assessment before retrying the mutation.
|
||||
|
||||
## Namespace provenance (#690)
|
||||
|
||||
A server process cannot derive the name of the client-managed namespace it is
|
||||
registered under, so the launcher may declare it with the
|
||||
`GITEA_MCP_NAMESPACE` environment variable (e.g. `GITEA_MCP_NAMESPACE=gitea-reviewer`).
|
||||
|
||||
- `gitea_whoami`, `gitea_get_runtime_context`, and
|
||||
`gitea_resolve_task_capability` report `namespace_provenance`: the declared
|
||||
client namespace, the active execution profile, and — for tasks with a
|
||||
required namespace (`review_pr`/`submit_review` → `gitea-reviewer`,
|
||||
`merge_pr` → `gitea-merger`) — a `mismatch` verdict.
|
||||
- A declared namespace that disagrees with the requested task's required
|
||||
namespace **fails closed** (`allowed_in_current_session=false` with a STOP
|
||||
guidance entry).
|
||||
- An undeclared namespace is reported as `namespace_source="unknown"` and is
|
||||
never treated as proof either way.
|
||||
- A profile switch via `gitea_activate_profile` clears all recorded live
|
||||
namespace-health assessments; re-probe through the client before further
|
||||
review/merge mutations.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user