feat: add granular per-session flags for multitenancy hardening#1474
Conversation
Add 7 new optional fields to SessionConfigBase across all 6 SDK languages (Node.js, Go, Python, .NET, Rust, Java): - skipEmbeddingRetrieval: prevent cross-session info leakage via embedding cache - organizationCustomInstructions: inject org-level instructions into system prompt - enableOnDemandInstructionDiscovery: control instruction file discovery after file views - enableFileHooks: control loading of file-based hooks from .github/hooks/ - enableHostGitOperations: control git operations on host filesystem - enableSessionStore: control cross-session store for search/retrieval - enableSkills: control skill loading (builtin + discovered) All fields are optional and pass through to the runtime without SDK-side default coercion. Empty mode applies restrictive defaults for multitenancy. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds a set of optional, per-session “granular multitenancy” flags across all SDKs to let hosts selectively disable host-level features (embedding retrieval, instruction discovery, file hooks, git ops, session store, skills) and to optionally inject organization-scoped instructions, with restrictive safe-defaults applied in “empty” mode.
Changes:
- Introduces 7 new session config fields and wires them through
session.create/session.resumepayloads across Node.js, Go, Python, .NET, Rust, and Java. - Applies “empty” mode restrictive defaults for the new flags (skip embeddings on; enable* off) while preserving caller overrides.
- Adds/extends tests (notably Node/Go/.NET/Java) to validate defaulting and wire propagation.
Show a summary per file
| File | Description |
|---|---|
| rust/src/wire.rs | Extends Rust create/resume wire structs with the new optional fields (camelCase on the wire). |
| rust/src/types.rs | Adds new config fields, defaults, builders, and wires them into into_wire for create/resume. |
| rust/src/session.rs | Applies “empty” mode restrictive defaults for the new flags during create/resume. |
| python/test_tool_set.py | Updates test imports for new empty-mode default helpers (currently introduces unused imports). |
| python/copilot/client.py | Adds new kwargs, empty-mode defaulting, and JSON payload fields for create/resume. |
| python/copilot/_mode.py | Factors out a generic empty-mode default helper and adds new defaulting functions. |
| nodejs/test/toolSet.test.ts | Adds tests covering empty-mode defaults, overrides, pass-through, and resume behavior. |
| nodejs/src/types.ts | Adds new SessionConfigBase fields and JSDoc describing the flags. |
| nodejs/src/client.ts | Applies empty-mode defaults and forwards new fields on create/resume requests. |
| java/src/test/java/com/github/copilot/SessionRequestBuilderTest.java | Adds tests verifying propagation of new fields into create/resume requests. |
| java/src/test/java/com/github/copilot/OptionalApiAndJacksonTest.java | Adds tests validating Optional/null behavior for the new config fields. |
| java/src/test/java/com/github/copilot/ConfigCloneTest.java | Adds tests ensuring clone preserves the new fields. |
| java/src/main/java/com/github/copilot/SessionRequestBuilder.java | Wires new config fields into create/resume request builders. |
| java/src/main/java/com/github/copilot/rpc/SessionConfig.java | Adds new config fields + fluent accessors/clearers, and clone support. |
| java/src/main/java/com/github/copilot/rpc/ResumeSessionConfig.java | Adds new resume config fields + fluent accessors/clearers, and clone support. |
| java/src/main/java/com/github/copilot/rpc/CreateSessionRequest.java | Adds new wire fields with Jackson annotations + accessors. |
| java/src/main/java/com/github/copilot/rpc/ResumeSessionRequest.java | Adds new wire fields with Jackson annotations + accessors. |
| go/types.go | Adds new config fields and wire request fields for create/resume. |
| go/toolset_test.go | Adds tests for empty-mode defaults, override precedence, and non-empty mode behavior. |
| go/mode_empty.go | Applies empty-mode defaults for the new flags on create and resume configs. |
| go/client.go | Forwards new config fields into the create/resume wire requests. |
| dotnet/test/E2E/ClientOptionsE2ETests.cs | Adds E2E assertions for create/resume wire propagation and empty-mode defaults. |
| dotnet/src/Types.cs | Adds new per-session config properties and copy-constructor propagation. |
| dotnet/src/Client.cs | Applies empty-mode defaults and forwards new fields into create/resume request records. |
Copilot's findings
- Files reviewed: 24/24 changed files
- Comments generated: 7
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Generated by SDK Consistency Review Agent for issue #1474 · ● 5.1M
SteveSandersonMS
left a comment
There was a problem hiding this comment.
Great! Thanks for getting all these in.
Some of the CCR comments look valid - approving now to keep things unblocked.
- Go: change OrganizationCustomInstructions to *string for cross-SDK consistency - Go: clarify *bool field docs (nil = runtime default, non-nil = forwarded) - Rust: redact organization_custom_instructions in Debug impls - Node.js: clarify JSDoc defaults apply only in empty mode - Python: replace unused imports with parametrized tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Merge origin/main into feature branch. Conflicts resolved in: - dotnet/src/Types.cs: added EnableMcpApps alongside our 7 new fields - go/types.go: merged wire structs with new fields from both sides (ReasoningSummary, PluginDirectories, LargeOutput, RequestMcpApps from main) - rust/src/types.rs: merged enable_mcp_apps field and builder methods alongside our 7 granular multitenancy fields - java SessionRequestBuilderTest: kept both our new tests and main's new tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
Adds embeddingCacheStorage field ("persistent" | "in-memory") to session
create and resume across all 6 SDKs. In empty mode, defaults to "in-memory"
for multitenant isolation. Companion to runtime PR #8388.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nular-multitenancy-flags # Conflicts: # dotnet/src/Client.cs # go/mode_empty.go # go/toolset_test.go # go/types.go # java/src/main/java/com/github/copilot/CopilotClient.java # java/src/test/java/com/github/copilot/SessionRequestBuilderTest.java # nodejs/src/client.ts # python/copilot/_mode.py # python/copilot/client.py
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Generated by SDK Consistency Review Agent for issue #1474 · ● 5.4M
… improve tests - Run formatters across all SDKs (prettier, gofmt, ruff, cargo fmt, spotless, dotnet format) - Convert EmbeddingCacheStorage from string to EmbeddingCacheStorageMode enum in .NET - Rename test methods to avoid temporal wording - Expand EnableFileHooks doc comment in Go ResumeSessionConfig - Add embeddingCacheStorage test coverage in Go, Java Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
Simplify doc comments across all SDKs to focus on user-facing behavior rather than SDK-to-runtime interaction details. Removes boilerplate like 'When nil, the runtime default is used. When non-nil, the value is passed through to the runtime.' in favor of concise, behavior-focused docs that match the existing style of other properties. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rename to use 'granularMultitenancyFields' instead of 'newSessionFields' for consistency with .NET and Node.js test naming. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Generated by SDK Consistency Review Agent for issue #1474 · ● 7.2M
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Cross-SDK Consistency Review identified that Java was only applying embeddingCacheStorage and mcpOAuthTokenStorage in empty mode, but missing the 6 boolean flags (skipEmbeddingRetrieval, enableOnDemandInstructionDiscovery, enableFileHooks, enableHostGitOperations, enableSessionStore, enableSkills). Also adds embeddingCacheStorage assertion to Node.js empty-mode test for coverage parity with Go and .NET. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Generated by SDK Consistency Review Agent for issue #1474 · ● 7.5M
Add the missing embedding_cache_storage field to: - SessionConfig custom Debug impl - ResumeSessionConfig custom Debug impl - SessionConfig fluent builder (with_embedding_cache_storage) - ResumeSessionConfig fluent builder (with_embedding_cache_storage) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add BaseDirectory and AvailableTools to .NET empty-mode default tests so they don't throw at client construction time - Fix enableConfigDiscovery Javadoc in ResumeSessionConfig: use Optional.empty() instead of null in @return, remove null from @param (setter takes primitive boolean) - Fix stale 'runtime default' wording in SessionConfig.java getter Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
✅ Cross-SDK Consistency ReviewThis PR maintains excellent consistency across all 6 SDK implementations. Here's a summary of the cross-language review: Fields added uniformly across all SDKs
Naming conventions followed correctly
Empty-mode defaults consistent across all SDKsAll SDKs apply the same restrictive defaults in empty mode:
Wire serialization consistentAll SDKs serialize field names as camelCase JSON keys, matching the expected protocol format ( No cross-SDK consistency issues found. 🎉
|
Summary
Add 8 new optional fields to
SessionConfigBaseacross all 6 SDK languages (Node.js, Go, Python, .NET, Rust, Java) for granular per-session control of host-level features in multitenant deployments.Fixes https://github.com/github/copilot-agent-runtime/issues/7156
New fields
skipEmbeddingRetrievalboolean?organizationCustomInstructionsstring?enableOnDemandInstructionDiscoveryboolean?enableFileHooksboolean?.github/hooks/enableHostGitOperationsboolean?enableSessionStoreboolean?enableSkillsboolean?embeddingCacheStoragestring?"persistent"or"in-memory")Design decisions
undefined/nil/null/Nonemeans "use runtime default"skipEmbeddingRetrieval: true, allenable*: false,embeddingCacheStorage: "in-memory") for secure multitenant deploymentsorganizationCustomInstructionshas no empty-mode default (it's host-supplied content, not a toggle)Changes per language
types.ts(interface),client.ts(wire + empty defaults),toolSet.test.ts(5 new tests)types.go(structs),client.go(wire),mode_empty.go(defaults),toolset_test.go(3 new tests)client.py(params + wire),_mode.py(defaults),test_tool_set.py(tests)Types.cs(properties),Client.cs(wire + defaults),ClientOptionsE2ETests.cs(tests)types.rs(structs + builders),wire.rs(wire structs),session.rs(mapping)SessionConfig.java,CreateSessionRequest.java,ResumeSessionRequest.java,ResumeSessionConfig.java,SessionRequestBuilder.java(wiring),CopilotClient.java(empty-mode defaults)Testing