You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Part of #15 (see Revision 2 of the RFC — this issue's scope was significantly expanded by the community review). Depends on Phase 1 (#16, shipped in #20) and the Phase 0 compatibility spike (#22 — key findings incorporated below).
Phase 0 spike results that shape this design (details in #22 findings):
App installation tokens work against the hosted endpoint — the credential backend below is verified viable.
X-MCP-Tools (undocumented, verified) is an exact per-tool allowlist — use it, not X-MCP-Toolsets categories.
X-MCP-Toolsets fails open on invalid names (typo → full tool surface) — never rely on it for enforcement.
Policy headers are honored per-request — ghpool must inject on every request and strip all client X-MCP-* (a client header would widen access mid-session).
Upstream DELETE is a no-op (session remains usable) — ghpool's session cache is the sole session/revocation authority.
Tool surface varies with App permissions (41 vs 44 tools App vs PAT) — the required App permission set must be documented and pinned.
Goal
Introduce agent identity and default-deny per-agent policy, unlocking write access through the MCP proxy. This phase is the security gate: no write tool is exposed until every item below ships.
Delivery plan: two slices (decision 2026-07-12)
Phase 2 as a monolith is ~10x Phase 1's complexity. It ships in two independently valuable slices:
Slice 2a — agent authn + policy, still read-only. Per-agent X-Ghpool-Key, default-deny tool allowlist enforced at the proxy + injected X-MCP-Tools upstream, tools/list pruning, per-agent audit attribution, TLS guidance. Upstream stays /readonly and the PAT pool stays. Immediate value: least privilege and per-agent attribution on reads; no fail-closed audit backend needed yet.
Slice 2b — writes. GitHub App credential backend (mint/refresh installation tokens), repo allowlists + resource resolution (deny-if-unresolvable), session-to-agent binding + revocation, durable fail-closed audit, write classification, safe-retry rules. Only after 2b is complete does any write tool go live. v0.4.0 releases when 2b closes.
2b-5 credential model: per-envelope scoped installation tokens — mint with the API's repositories+permissions parameters so the token is already narrowed to the agent's allowlist; GitHub becomes the authoritative resource boundary, ghpool's argument parser is defense-in-depth. One credential per policy envelope.
Writes require the App backend, enforced in code — write path stays 403 without [mcp.github_app]; PATs never serve writes.
2b-4 audit records tool-level outcomes — isError arrives inside HTTP 200/SSE, so write-call responses are buffered (bounded) and parsed before forwarding; HTTP status alone is not a success signal.
2b-5 adds a simple per-agent in-flight cap (full quotas remain Phase 3).
Revocation semantics documented: config change = restart = all session pins cleared (in-memory), until hot-reload exists.
Checklist items below are tagged [2a]/[2b].
Gate checklist (from RFC Revision 2 — ALL required before writes)
[2a] Agent authentication — X-Ghpool-Key per-agent API keys (baseline; SigV4 shim is Phase 3):
256-bit entropy, constant-time comparison, excluded from logs/traces
two simultaneously valid keys per agent for zero-downtime rotation
[2b] GitHub App credential backend (shipped: MCP 2b-3: GitHub App credential backend #31 — live-verified mint via e2e App-mode section) — installation tokens (1h TTL, auto-refresh, private key in AWS Secrets Manager) replace the PAT pool on the MCP path (compliance: avoids PAT rate-limit aggregation)
Audit backend choice for fail-closed writes (local WAL + ship vs. direct to CloudWatch/S3)
Identity binding: verify key per request (stateless) vs. bind at session init alongside the pin (RFC leans session binding — required by the session-to-agent gate anyway)
Part of #15 (see Revision 2 of the RFC — this issue's scope was significantly expanded by the community review). Depends on Phase 1 (#16, shipped in #20) and the Phase 0 compatibility spike (#22 — key findings incorporated below).
Goal
Introduce agent identity and default-deny per-agent policy, unlocking write access through the MCP proxy. This phase is the security gate: no write tool is exposed until every item below ships.
Delivery plan: two slices (decision 2026-07-12)
Phase 2 as a monolith is ~10x Phase 1's complexity. It ships in two independently valuable slices:
Slice 2a — agent authn + policy, still read-only. Per-agent
X-Ghpool-Key, default-deny tool allowlist enforced at the proxy + injectedX-MCP-Toolsupstream,tools/listpruning, per-agent audit attribution, TLS guidance. Upstream stays/readonlyand the PAT pool stays. Immediate value: least privilege and per-agent attribution on reads; no fail-closed audit backend needed yet.Slice 2b — writes. GitHub App credential backend (mint/refresh installation tokens), repo allowlists + resource resolution (deny-if-unresolvable), session-to-agent binding + revocation, durable fail-closed audit, write classification, safe-retry rules. Only after 2b is complete does any write tool go live. v0.4.0 releases when 2b closes.
Checklist items below are tagged [2a]/[2b].
Gate checklist (from RFC Revision 2 — ALL required before writes)
X-Ghpool-Keyper-agent API keys (baseline; SigV4 shim is Phase 3):env:/aws:secretsmanager:/k8s:)X-MCP-*headers and rebuild from policy (client cannot widen its own permissions)tools/listresponse filtering — inject per-agentX-MCP-Tools: <exact allowlist>upstream (native filtering, verified in MCP proxy Phase 0: compliance & compatibility spike (hosted endpoint contract, App tokens) #22) AND enforce the same allowlist ontools/callat the proxy (authoritative; upstream header is defense-in-depth). Do NOT useX-MCP-Toolsetsfor enforcement — it fails open on invalid names (MCP proxy Phase 0: compliance & compatibility spike (hosted endpoint contract, App tokens) #22 finding F)Policy config sketch
Also fold in from Phase 1's accepted limitations
allowed_owners-equivalent enforcement on the MCP path (superseded by the per-agentreposallowlist above){ "url": "https://ghpool:8080/mcp", "headers": { "X-Ghpool-Key": "${GHPOOL_KEY}" } }Open questions