Skip to content

Add mutually exclusive plural gateway agent ID configuration - #12116

Merged
lpcox merged 7 commits into
mainfrom
copilot/add-gateway-agent-ids-configuration
Aug 29, 2026
Merged

Add mutually exclusive plural gateway agent ID configuration#12116
lpcox merged 7 commits into
mainfrom
copilot/add-gateway-agent-ids-configuration

Conversation

Copilot AI commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Adds plural gateway session identifiers for concurrent primary/enclave configuration while retaining singular agent IDs. Singular and plural forms are mutually exclusive.

  • Configuration

    • Adds GatewayConfig.AgentIDs (agent_ids) and stdin JSON gateway.agentIds.
    • Preserves plural IDs during stdin-to-internal conversion.
    • Rejects empty lists, blank entries, and singular/plural or legacy-alias/plural combinations.
  • Published contract

    • Updates the bundled schema to require exactly one of agentId or agentIds.
    • Adds agentIds array constraints: minItems: 1, item minLength: 1.
    • Removes apiKey from the published schema and configuration documentation.
  • Compatibility and fixtures

    • Keeps internal legacy api_key / apiKey parsing support.
    • Migrates schema-validated examples and test fixtures to agentId.
[gateway]
agent_ids = ["primary-agent", "enclave-agent"]
{
  "gateway": {
    "agentIds": ["primary-agent", "enclave-agent"]
  }
}

Copilot AI and others added 3 commits August 29, 2026 18:33
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Copilot AI changed the title [WIP] Add mutually exclusive gateway agent_ids configuration Add mutually exclusive plural gateway agent ID configuration Aug 29, 2026
Copilot AI requested a review from lpcox August 29, 2026 18:45
@lpcox
lpcox marked this pull request as ready for review August 29, 2026 18:53
Copilot AI balanced review requested due to automatic review settings August 29, 2026 18:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Plural-only configurations are ignored at runtime and silently replaced with a random singular identifier.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds mutually exclusive plural gateway agent ID configuration across parsing, validation, schema, documentation, and fixtures.

Changes:

  • Adds and validates agent_ids/agentIds.
  • Enforces singular/plural exclusivity.
  • Migrates published examples from deprecated apiKey.
File summaries
File Description
test/integration/start_gateway_with_pipe.sh Migrates fixture to agentId.
README.md Documents plural IDs and exclusivity.
internal/launcher/launcher_test.go Migrates launcher fixtures.
internal/launcher/getorlaunch_stdio_test.go Migrates stdio fixture.
internal/difc/DIFC_RULES.md Updates configuration example.
internal/config/validation_gateway.go Validates plural IDs and conflicts.
internal/config/schema/mcp-gateway-config.schema.json Publishes the plural schema contract.
internal/config/config_stdin.go Parses and preserves JSON plural IDs.
internal/config/config_core.go Adds TOML plural IDs and validation.
internal/config/agent_ids_test.go Tests plural configuration behavior.
guards/github-guard/scripts/run_integration_tests.sh Migrates guard test configuration.
guards/github-guard/scripts/run_copilot_test.sh Migrates Copilot test configuration.
docs/CONFIGURATION.md Documents plural configuration.
containers/serena-mcp-server/test-startup-time.sh Migrates startup fixture.
config.example.toml Demonstrates plural TOML IDs.
Review details
  • Files reviewed: 15/15 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

cfg.Gateway = &GatewayConfig{
Port: intPtrOrDefault(stdinCfg.Gateway.Port, DefaultPort),
AgentID: stdinCfg.Gateway.AgentID,
AgentIDs: append([]string{}, stdinCfg.Gateway.AgentIDs...),
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@lpcox

lpcox commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

@copilot address review feedback

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>

Copilot AI commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address review feedback

Addressed in 6d11af0: run() now fails closed with an explicit error when only gateway.agentIds/agentIds is configured, instead of silently ignoring it and generating a random singular agent ID. Docs updated to note this limitation until multi-identity auth is implemented.

@lpcox

lpcox commented Aug 29, 2026

Copy link
Copy Markdown
Collaborator

@copilot address review feedback

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Copilot AI and others added 2 commits August 29, 2026 21:06
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>

Copilot AI commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address review feedback

Implemented actual multi-identity authentication instead of failing closed: Config.GetAgentIDs() now returns every configured gateway.agentIds entry, and the API key is threaded as a list through the HTTP server chain (buildHTTPServerCreateHTTPServerForMCP/CreateHTTPServerForRoutedModeauthMiddleware). authMiddleware accepts any of the configured identifiers via constant-time comparison, so concurrent primary/enclave sessions each authenticate with their own credential (session IDs are already derived from the Authorization header value, so this also isolates their sessions). Removed the previous fail-closed error and updated docs accordingly.

@github-actions

Copy link
Copy Markdown
Contributor

🔒 mcpg Read-Only Stress — default

Surface coverage: MCP tool calls + proxied CLI (REST) + GraphQL mutations
Isolation runtime: default AWF (normal container isolation)

Part Surface Op Result Expected Status
A MCP list_issues 3 issues returned ALLOWED
A MCP list_pull_requests 3 PRs returned ALLOWED
A MCP get_file_contents (README.md) content returned ALLOWED
A MCP list_commits 3 commits returned ALLOWED
B MCP add_issue_comment (reaction) unknown tool — not in catalog BLOCKED ⚠️
B MCP star_repository unknown tool — not in catalog BLOCKED ⚠️
B MCP issue_write (create) unknown tool — not in catalog BLOCKED ⚠️
B MCP create_branch unknown tool — not in catalog BLOCKED ⚠️
B MCP create_pull_request unknown tool — not in catalog BLOCKED ⚠️
C CLI list_issues (github CLI) data returned ALLOWED
C CLI get_file_contents (github CLI) data returned ALLOWED
D CLI REST all write ops gh not authenticated BLOCKED ⚠️
E CLI GraphQL mutations gh not authenticated BLOCKED ⚠️

Overall: INCONCLUSIVE

⚠️ Part B: All 5 write tool attempts returned unknown tool [-32602]. The backend GitHub MCP server is launched with GITHUB_READ_ONLY=1 (gh-aw framework always sets this), so write tools are never registered. This confirms the backend-level defense-in-depth, but does not independently confirm gateway-level DIFC/guard enforcement — gateway enforcement can only be exercised if a write-capable backend is reached. Result: INCONCLUSIVE per methodology, not FAIL.

⚠️ Parts D/E: gh auth status returned "not logged in". All REST/GraphQL write attempts are unauthenticated and would return 401, not a gateway refusal. Cannot distinguish gateway blocking from token absence. Result: INCONCLUSIVE, not FAIL.

No writes leaked. No issues, comments, branches, files, or PRs were created.

References: §33275322512

🔒 mcpg read-only stress (default AWF runtime) by Read-Only Stress: default runtime

@lpcox
lpcox merged commit 34ed844 into main Aug 29, 2026
33 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

🔒 mcpg Read-Only Stress — gVisor

Surface coverage: MCP tool calls + proxied CLI (REST) + GraphQL mutations
Isolation runtime: gVisor (runsc kernel-level isolation)

Part Surface Op Result Expected Status
A MCP list_issues 3 items returned ALLOWED
A MCP list_pull_requests 3 PRs returned ALLOWED
A MCP get_file_contents (README.md) content returned ALLOWED
A MCP list_commits 3 commits returned ALLOWED
B MCP writes (all 7 targets) all absent from catalog BLOCKED ⚠️
C CLI list_issues data returned ALLOWED
C CLI get_file_contents data returned ALLOWED
D CLI REST writes (6 targets) gh unauthenticated BLOCKED ⚠️
E CLI GraphQL mutations (3 targets) gh unauthenticated BLOCKED ⚠️

Overall: INCONCLUSIVE

⚠️ Part B: The GitHub MCP backend exposes only 23 read-only tools (no write tools registered). All Part B targets (add_issue_comment, star_repository, issue_write, create_branch, create_or_update_file, create_pull_request) were absent from the tool catalog — this confirms GITHUB_READ_ONLY=1 backend defense-in-depth, but does NOT independently confirm mcpg's own DIFC/guard enforcement layer.

⚠️ Parts D & E: gh is not authenticated in this environment (gh auth status → "not logged into any GitHub hosts"). All REST and GraphQL write attempts are INCONCLUSIVE — unauthenticated 401s do not confirm token-scope boundary enforcement.

No writes leaked. The read-only guarantee held for all observable surfaces.

🔒 mcpg read-only stress (gVisor runtime) by Read-Only Stress: gVisor runtime

@lpcox
lpcox deleted the copilot/add-gateway-agent-ids-configuration branch August 29, 2026 22:17
@github-actions

Copy link
Copy Markdown
Contributor

🔒 mcpg Read-Only Stress — docker-sbx

Surface coverage: MCP tool calls + proxied CLI (REST) + GraphQL mutations
Isolation runtime: docker-sbx (KVM-isolated microVM)

Part Surface Op Result Expected Status
A MCP list_issues data returned ALLOWED
A MCP list_pull_requests data returned ALLOWED
A MCP get_file_contents (README.md) data returned ALLOWED
A MCP list_commits data returned ALLOWED
B MCP add_issue_comment (reaction) tool absent from catalog BLOCKED ⚠️
B MCP star_repository tool absent from catalog BLOCKED ⚠️
B MCP issue_write (create) tool absent from catalog BLOCKED ⚠️
B MCP add_issue_comment (body) tool absent from catalog BLOCKED ⚠️
B MCP create_branch tool absent from catalog BLOCKED ⚠️
B MCP create_or_update_file tool absent from catalog BLOCKED ⚠️
B MCP create_pull_request tool absent from catalog BLOCKED ⚠️
C CLI list_issues (github CLI) data returned ALLOWED
C CLI get_file_contents (github CLI) data returned ALLOWED
D CLI REST reaction write 401 Bad credentials BLOCKED ⚠️
D CLI REST star write 401 Bad credentials BLOCKED ⚠️
D CLI gh issue create 401 Bad credentials BLOCKED ⚠️
D CLI REST issue create 401 Bad credentials BLOCKED ⚠️
D CLI REST comment write 401 Bad credentials BLOCKED ⚠️
D CLI REST file write 401 Bad credentials BLOCKED ⚠️
E CLI GraphQL addReaction 401 Bad credentials BLOCKED ⚠️
E CLI GraphQL addStar 401 Bad credentials BLOCKED ⚠️
E CLI GraphQL createIssue 401 Bad credentials BLOCKED ⚠️

Overall: INCONCLUSIVE

⚠️ Part B: All 7 write tools absent from the MCP tool catalog — backend launched with GITHUB_READ_ONLY=1 (gh-aw framework guarantee). Gateway-level DIFC/guard enforcement could not be independently exercised since no write-capable tool reached the gateway. This is expected per the architectural note in the test plan.

⚠️ Parts D & E: gh CLI is not authenticated in this environment (GH_TOKEN invalid — 401 Bad credentials on all calls). All REST and GraphQL write attempts returned 401, but this reflects the invalid token, not necessarily the gateway or token-scope boundary. Cannot confirm write-blocking independently.

No writes leaked. No FAIL conditions observed.

Run: §33275322593

🔒 mcpg read-only stress (docker-sbx runtime) by Read-Only Stress: docker-sbx runtime

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add mutually exclusive gateway agent_ids configuration

3 participants