MCP 2b-5: enable writes behind the full gate (completes #17)#33
Merged
Conversation
Final slice of #17's [2b] items — write tools become available, bounded by every previously shipped layer plus this slice's additions: - enable_writes flag (default false). Startup validation HARD-REQUIRES [[mcp.agents]] + [mcp.github_app] + [mcp.audit] — writes are never available in network-trust mode, never run on pooled PATs, never unaudited. Default upstream flips to the full write surface when set. - Scoped installation tokens (community review): when an agent's repos are all exact entries under one owner, its token is minted with the repositories parameter — GitHub enforces the repo boundary itself. Wildcards/mixed owners fall back to installation-wide (proxy checks remain). Per-envelope token cache in AppTokenProvider. - Per-agent in-flight write cap (max_inflight_writes, default 4, 0 = unlimited) via RAII guard; at-cap writes get 429 before any side effect. - Safe-retry: ghpool never retries forwarded calls (documented; ambiguous outcomes are audited as undeterminable and surfaced to the caller). - Docs: README write section incl. required App permission set; revocation semantics (restart clears in-memory pins; upstream DELETE is a no-op — ghpool is the session authority). 84 tests (7 new: write-gate validation matrix, upstream default flip, scope_envelope rules, scoped-mint envelope caching, write allowed e2e with audit trail + X-MCP-Tools, denials still enforced with writes on, in-flight guard + 429 at cap).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Final slice of #17: write tools become available for authenticated agents, behind every layer the previous slices built. This closes the remaining
[2b]gate items and completes the Phase 2 gate — after this merges, v0.4.0 can ship per the release plan.The gate, end to end
A write call must pass, in order:
X-Ghpool-Keyagent authentication (MCP Phase 2a: X-Ghpool-Key agent authn + default-deny tool allowlist #26)enable_writesflagmax_inflight_writes, default 4; at-cap → 429 before any side effect)isError) audited (MCP 2b-4: durable fail-closed audit for write-classified calls #32)New in this slice
enable_writes(default false) with startup validation:truerequires[[mcp.agents]]+[mcp.github_app]+[mcp.audit]— the "never in network-trust mode, never on PATs, never unaudited" rules are enforced in code at boot, not documented hopes. Default upstream flips from/mcp/readonlyto the full surface when set (explicitupstreamalways wins).reposare all exact entries under a single owner gets tokens minted with the API'srepositoriesparameter — GitHub itself enforces the repo boundary, demoting ghpool's argument parsing to defense-in-depth. Wildcards/mixed owners fall back to installation-wide. Per-envelope token cache (one credential per policy envelope, per the homogeneous-pool rule).tool_error: null) and surfaced — retry decisions belong to the caller. This was already true; it is now documented as a guarantee and closes the[2b]safe-retry item.[2b]item), revocation semantics (in-memory pins + restart = revocation; upstream DELETE is a no-op so ghpool is the session authority — closes the design-note item).Tested
84 tests (7 new): validation matrix (each missing section rejected, full set accepted), upstream default flip,
scope_enveloperules (exact/single-owner → names; wildcard/mixed/empty → installation-wide), scoped-mint per-envelope caching against the mock GitHub API, write allowed end-to-end (200 +X-MCP-Toolsinjected + request/result audit records with agent attribution), denials still enforced with writes on (wrong repo / off-allowlist → 403, audit untouched), in-flight guard unit + 429-at-cap integration. Clippy-D warningsclean.Deliberately not in this PR
permissionsscoping at mint (repo scoping ships now; permission scoping is a compatible follow-up).After this
All 14 #17 gate items complete → v0.4.0 release (per the recorded plan).