Add additionalContentExclusionPolicies to SessionConfig (public high-level API)
- Vorherrschende Sprache
- Java
- Sterne
- 10.5k
- Forks
- 1.5k
- Ø Merge
- 1 T. 11 Std.
- Gemergte PRs (30 T.)
- 128
Beschreibung
## Add `additionalContentExclusionPolicies` to `SessionConfig` (public high-level API)
### Summary
The Copilot SDK exposes content exclusion policy support at the low-level RPC layer
(`SessionOpenOptions.additionalContentExclusionPolicies`, `session.rpc.options.update`,
`session.rpc.permissions.configure`) but does not surface it through the public
`SessionConfig` / `SessionConfigBase` interface used by `createSession()` and
`resumeSession()`. This makes it impossible for SDK consumers to set per-session
content exclusion rules through the documented, stable public API.
### Motivation
Content exclusion is a core compliance and data-governance feature. At GitHub
organization level, admins configure it via repository settings. However, SDK
consumers — especially those building multi-tenant agentic applications — need to
inject additional exclusion rules per session, beyond what GitHub org settings provide:
- **Multi-tenant SaaS:** Each tenant has their own data classification rules that
must not be shared with the model context (PII paths, credentials directories,
confidential source trees).
- **Regulated environments (GxP, HIPAA, SOC 2):** Compliance requirements dictate
that certain file patterns are never read by the model, regardless of what
the repository-level GitHub policy says.
- **Agent isolation:** Pipeline orchestrators that spawn per-role sessions need to
scope each session's readable context to only the files that role is authorized
to see, without coupling this to GitHub org settings.
### Current workaround (and why it is insufficient)
The only way to set exclusion rules today is via `session.rpc.permissions.configure()`
after the session is created:
```typescript
const session = await client.createSession({ ... });
// Race condition: session may have already started reading files before this call
await session.rpc.permissions.configure({
additionalContentExclusionPolicies: [{
rules: [{ paths: ["**/secrets/**", "**/.env*"], source: { name: "tenant-policy", type: "host" } }],
last_updated_at: Date.now(),
scope: "all",
}],
});
```
Problems:
1. **Race condition:** The session may read files before the `configure` call returns.
There is no way to guarantee exclusion rules are active before the first turn.
2. **Undocumented surface:** `session.rpc` is a low-level raw RPC accessor marked
`@experimental`. Nothing in the README or SDK docs points consumers here for
content exclusion.
3. **Inconsistent with the rest of the API:** Every other security-relevant session
option (`availableTools`, `excludedTools`, `onPermissionRequest`,
`skipCustomInstructions`, `gitHubToken`, `skipEmbeddingRetrieval`) is set
through `SessionConfigBase`. Content exclusion policies should follow the same
pattern.
4. **Mid-session update (`rpc.options.update`) is the only per-turn path:** There is
no way to supply policies atomically with the session creation RPC.
### Proposed change
Add `additionalContentExclusionPolicies` to `SessionConfigBase`:
```typescript
export interface SessionConfigBase {
// ... existing fields ...
/**
* Additional content-exclusion policies to merge into the session's policy set
* on creation (and on resume). Rules are evaluated alongside natively-discovered
* GitHub organization / repository policies.
*
* Use this to inject application-level or tenant-level path exclusions that
* are not covered by GitHub organization settings — for example, in multi-tenant
* deployments where each session must be scoped to its tenant's permitted file set.
*
* Each policy rule that matches a file path will cause the CLI to deny Copilot
* access to that file, equivalent to a `PermissionDecisionDeniedByContentExclusionPolicy`
* outcome on the permission request for that path.
*
* @example
* ```typescript
* const session = await client.createSession({
* additionalContentExclusionPolicies: [{
* scope: "all",
* last_updated_at: Date.now(),
* rules: [
* {
* paths: ["**/.env*", "**/secrets/**", "**/*.pem"],
* source: { name: "tenant-compliance-policy", type: "host" },
* },
* ],
* }],
* });
* ```
*
* @experimental
*/
additionalContentExclusionPolicies?: ContentExclusionPolicy[];
}
```
The `ContentExclusionPolicy` / `ContentExclusionPolicyRule` types should be exported
as first-class public types (not re-exports of the generated RPC types), with clear
JSDoc:
```typescript
/** Scope for a content exclusion policy. */
export type ContentExclusionPolicyScope = "repo" | "all";
/** A single rule within a content exclusion policy. */
export interface ContentExclusionPolicyRule {
/** Glob patterns for file paths to exclude from Copilot context. */
paths: string[];
/** The rule is active only when at least one of these patterns matches the file content. */
ifAnyMatch?: string[];
/** The rule is active only when none of these patterns matches the file content. */
ifNoneMatch?: string[];
/** Source label identifying who issued this rule. */
source: { name: string; type: string };
}
/** A content exclusion policy applied to a session. */
export interface ContentExclusionPolicy {
/** The rules that make up this policy. */
rules: ContentExclusionPolicyRule[];
/** ISO 8601 timestamp or Unix ms epoch when the policy was last updated. */
last_updated_at: string | number;
/** Whether the policy applies to the current repository only, or all repositories. */
scope: ContentExclusionPolicyScope;
}
```
### Expected behavior
- Policies supplied in `SessionConfig.additionalContentExclusionPolicies` are
applied atomically with the session creation RPC (`SessionOpenOptions`), before
any tool execution can occur.
- On `resumeSession`, the same field re-applies the policies so resumed sessions
respect updated tenant rules.
- Policies compose with GitHub org-level exclusions (same as the current RPC
behavior): a file is excluded if it matches any policy from any source.
### Alternatives considered
- **Rely on `onPermissionRequest` to deny individual file reads:** This works per
permission prompt but does not prevent the model from receiving file content via
attachment or retrieval paths that do not go through the permission system.
- **Use `availableTools` / `excludedTools` to remove read tools:** Too coarse —
this removes read access entirely rather than scoping it to allowed paths.
- **GitHub org content exclusion settings:** Not available in multi-tenant scenarios
where the SDK host is not a GitHub organization admin, or where tenants are
not GitHub entities at all.
### References
- Generated RPC types: `SessionOpenOptions.additionalContentExclusionPolicies`,
`PermissionsConfigureParams.additionalContentExclusionPolicies`,
`OptionsUpdateParams.additionalContentExclusionPolicies`
- Related: `SessionConfigBase.gitHubToken` — per-session GitHub identity for
org-level content exclusion discovery
- Related: `SessionConfigBase.availableTools` / `excludedTools` — tool-level
filtering, not path-level content filtering
Beitragsleitfaden
Bewertung
Dieses Issue wurde noch nicht bewertet.