Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
341 changes: 0 additions & 341 deletions .github/skills/add-policy/SKILL.md

This file was deleted.

63 changes: 63 additions & 0 deletions .github/skills/policy-and-managed-settings/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
name: policy-and-managed-settings
description: Use whenever adding, modifying, or reviewing any Copilot, agent, LLM, AI, tool, permission, sandbox, MCP, model, telemetry, feature-gate, setting, configuration, or enterprise control—especially anything an organization or administrator may need to manage. Start here to decide whether it belongs in runtime managed settings, a typed SDK contract, VS Code configuration policy, extension policy, or a split implementation. Run on every new Copilot/agent/LLM control and ANY change that adds a `policy:` field.
---

# Adding an Enterprise Policy

Choose the policy destination by **where the governed behavior is implemented**, not by
which team requested it. Most controls for Copilot agent behavior belong in the
SDK/runtime rather than VS Code.

```mermaid
flowchart TD
A[Enterprise control] --> P{Existing permission policy<br/>introduced before VS Code 1.133.0?}
P -->|Yes| L[Pre-1.133 compatibility migration]
P -->|No| B{Where is the governed behavior implemented?}

B -->|Copilot runtime, tools, MCP,<br/>sandbox, or agent loop| R[SDK/runtime managed setting]
B -->|VS Code editor or workbench| V[VS Code configuration policy]
B -->|Extension-provided setting| E[Extension policy]
B -->|Independent runtime and editor behavior| M[Split runtime/editor control]
```

Follow the matching guide:

- [SDK/runtime managed setting](./sdk-runtime-policy.md)
- [VS Code configuration policy](./vscode-policy.md)
- [Extension-provided setting](./extension-policy.md)
- [Split runtime/editor control](./mixed-policy.md)
- [Pre-1.133 permission-policy migration](./legacy-permission-policy.md)

General rules:

- Runtime enforcement is authoritative for behavior executed inside the runtime.
- Do not duplicate a runtime parser, matcher, or security decision in VS Code.
- A VS Code policy is appropriate only for editor/workbench-owned behavior.
- New Copilot enterprise controls should target the shared managed-settings/SDK model.
- Run `npm run export-policy-data` for every VS Code or extension policy change. Never
edit `build/lib/policies/policyData.jsonc` manually.

## Deprecated and Historical Channels

Some policy channels remain supported for existing controls but are closed to new
properties:

- **GitHub token/account policy data** (`IPolicyData` fields consumed by
`AccountPolicyService`) is deprecated for new controls. Do not add new entitlement or
policy properties from the GitHub token. Existing fields remain for compatibility.
- New Copilot enterprise controls use managed settings and runtime/SDK enforcement.
- Pre-1.133 permission-policy translation is a bounded migration, not a reusable channel.

When another channel is deprecated, record the boundary here and keep implementation
details in the relevant destination guide.

Supporting references:

- [GitHub Copilot managed settings](./github-managed-settings.md)
- [Local policy testing](./local-testing.md)

Keep these guides contract-focused. Document contributor decisions and behavioral
invariants; point to source rather than copying implementation that will drift.

Trust executable source and tests over planning documents.
46 changes: 46 additions & 0 deletions .github/skills/policy-and-managed-settings/extension-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Extension-Provided Setting Policy

Use this path when the setting is contributed by an extension rather than VS Code core.
Extensions cannot declare core `policy:` metadata in their `package.json`.

The source of truth is `extensionConfigurationPolicy` in `vscode-distro`
`mixin/{quality}/product.json`. At runtime, VS Code attaches that metadata to matching
extension configuration properties.

```json
"publisher.extension.settingName": {
"name": "PolicyName",
"category": "InteractiveSession",
"minimumVersion": "1.133",
"description": "Human-readable description."
}
```

## Procedure

1. Add the setting to `extensionConfigurationPolicy` in every `vscode-distro`
product-quality `product.json` (`stable`, `insider`, and `exploration`).
2. Include:
- unique PascalCase `name`;
- valid `PolicyCategory`;
- first shipping `minimumVersion`;
- human-readable `description`.
Comment on lines +19 to +27
3. Update VS Code's pinned distro commit.
4. Update
`src/vs/workbench/contrib/policyExport/test/node/extensionPolicyFixture.json`.
5. Run `npm run export-policy-data`.
6. Verify and include `build/lib/policies/policyData.jsonc`.

The fixture must match the pinned distro policy data or the policy-export integration
test fails.

The canonical export launches both Workbench and the Agents window with isolated
profiles and merges their policy catalogs. Do not invoke a single entrypoint directly.

Downstream consumers:

| Consumer | Output |
|---|---|
| `build/lib/policies/policyGenerator.ts` | Windows ADMX/ADML, macOS mobileconfig, Linux policy JSON |
| `vscode-website` policy build | Enterprise policy reference |
| `vscode-docs` | Generated enterprise policy documentation |
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,14 @@ Client-side merging still happens *within* a channel's value (e.g. `enabledPlugi
When the developer has `copilot-agent-runtime` checked out side-by-side, reference
`copilot-agent-runtime/schema/managed-settings-schema.json` as the authoritative
shape. It is aligned with the `managed_settings` API output and is the schema for all
delivery channels (MDM plist/registry, file-based, server-managed). Its top-level
properties today are `permissions`, `enabledPlugins`, `extraKnownMarketplaces`, and
`strictKnownMarketplaces` (nested objects/arrays). Note the schema is **nested**, whereas
the VS Code bag is **flattened** to dot-paths — e.g. the schema's nested
delivery channels (MDM plist/registry, file-based, server-managed). The runtime schema
also contains keys that VS Code never projects because their behavior is runtime-owned.
The table below contains selected VS Code-projected examples with non-obvious composition
or encoding. It is not an inventory; derive the current key set from policy declarations
and the runtime schema.

The schema is **nested**, whereas the VS Code bag is **flattened** to dot-paths — e.g.
the schema's nested
`permissions.disableBypassPermissionsMode` becomes the flat bag key of the same name
(the `COPILOT_DISABLE_BYPASS_PERMISSIONS_MODE_KEY` constant):

Expand Down Expand Up @@ -148,8 +152,9 @@ Key rules for the `value` callback:
fields were **removed**; everything is the canonical bag now).
- Return the **locking value** when the managed setting demands it, `undefined` otherwise
(so the user's setting falls through).
- It's fine to combine with `chat_preview_features_enabled === false` (see SKILL.md's
"GitHub Preview Features" section).
- Existing policies may also contain the historical
`chat_preview_features_enabled === false` token-entitlement check. Preserve it when
maintaining those policies, but do not add it to a new control.

For the **common pass-through case** — lock to the managed value, otherwise fall through to
the user's setting — use the `managedSettingValue(KEY)` helper instead of hand-writing the
Expand All @@ -161,8 +166,8 @@ import { managedSettingValue } from '../../../../platform/policy/common/copilotM
value: managedSettingValue(COPILOT_ENABLED_PLUGINS_KEY),
```

Policies that combine the managed value with other conditions (like `ChatToolsAutoApprove`
above, which also checks `chat_preview_features_enabled`) keep a custom callback. The helper
Existing policies that combine the managed value with historical conditions (like
`ChatToolsAutoApprove` above) keep a custom callback. The helper
returns a callback memoized per key (the same function reference for a given key on every call),
preserving the policy-definition reference identity that lets `isSamePolicyDefinition` avoid
needless re-registration.
Expand Down Expand Up @@ -294,7 +299,11 @@ API, which returns the same payload as `session.managed_settings_resolved` witho
active session. This runtime snapshot is not treated as another VS Code delivery channel because
the runtime owns its schema and authority resolution independently.

## Adding a brand-new managed-settings key (checklist)
## Projecting a managed-settings key into VS Code (checklist)

Follow this checklist only after the root [SKILL.md](./SKILL.md) routes the control to a
VS Code or split runtime/editor policy. Runtime-only managed settings need no VS Code
constant, configuration policy, or policy-data export.

1. **Pick the canonical dot-path** and add it as a constant in
`copilotManagedSettings.ts`. It must match the server `managed_settings` API field /
Expand All @@ -315,9 +324,10 @@ the runtime owns its schema and authority resolution independently.
`managed-settings-schema.json` must agree on the key name and value type. The
declaration-driven projection (`projectManagedSettings`) silently drops anything that
doesn't match the declared type, so a type drift = a silently ignored setting.
5. **Export & test** as in SKILL.md Step 3–4 (`npm run typecheck-client`,
`npm run export-policy-data`). Verify the policy appears in `policyData.jsonc`. A transport-only
control has no policy catalog entry, so it does not require a policy-data export.
5. **Export & test** as described in [vscode-policy.md](./vscode-policy.md)
(`npm run typecheck-client` when needed, then `npm run export-policy-data`). Verify
the policy appears in `policyData.jsonc`. A transport-only control has no policy
catalog entry, so it does not require a policy-data export.

### Transport-only control: `forceRemoteSettingsRefresh`

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Pre-1.133 Permission-Policy Migration

This is a temporary compatibility path for existing permission policies introduced
before VS Code 1.133.0. The migration remains in progress.

Do not use this path for new controls.

## Rules

- Translate only exact enterprise `policyValue`; never user/workspace values.
- Map only to an equivalent runtime capability.
- Preserve restrictive semantics; do not synthesize permissive authorization.
- The compatibility bridge may emit managed rules, but the runtime remains the grammar
and enforcement authority.
- Validate emitted rules across the real SDK/runtime boundary.
- Retain existing enforcement until the SDK/runtime replacement is effective.
- Cover local create/resume, omission/removal, default and peer sessions, and diagnostics.

Known facts to reverify while working here:

- Kind-only `Shell` is the all-shell form; `Shell(*)` is invalid managed-rule syntax.
- Agent Host custom terminal tools arrive as `custom-tool`, not `shell`.
- AHP `permissions.deny` exists but is not enforced by the current host permission manager.
- Managed Tool and MCP tool-call coverage is evolving.
- Hook permission requests are outside the currently managed request families.
- Account-scoped managed-settings diagnostics omit the session-local injected layer.

Do not expand this bridge into a general translation framework. New enterprise controls
belong in the shared managed-settings/SDK model.
28 changes: 28 additions & 0 deletions .github/skills/policy-and-managed-settings/mixed-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Split Runtime/Editor Control

Use this path only when one enterprise control governs two independent behaviors:

1. agent behavior executed inside the runtime; and
2. editor/workbench behavior implemented by VS Code.

## Separation

- Add the authoritative managed setting and enforcement in the runtime.
- Add a VS Code policy only for the editor-owned behavior.
- Keep both projections semantically aligned.
- Do not duplicate runtime matching or enforcement in VS Code.
- Do not use editor UI suppression as a substitute for runtime enforcement.

If the runtime lacks an exact capability, add it first and retain existing editor
behavior until the authoritative replacement exists.

## Integration Checks

- Permission authorization remains separate from sandbox containment.
- Create, resume, removal, peer, subagent, and cloud behavior are explicit.
- Runtime-effective diagnostics include all enforced layers, or the gap is documented.

Follow both:

- [SDK/runtime managed setting](./sdk-runtime-policy.md)
- [VS Code configuration policy](./vscode-policy.md)
71 changes: 71 additions & 0 deletions .github/skills/policy-and-managed-settings/sdk-runtime-policy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# SDK/Runtime Managed Setting

Use this path when policy governs behavior implemented inside the Copilot runtime:

- tools, shell, files, URLs, MCP, plugins, or subagents;
- permissions, approvals, or sandboxing;
- runtime-owned model, telemetry, or remote-agent behavior.

## Contract

The runtime owns:

- managed-settings schema and rule grammar;
- restrictive composition across enterprise sources;
- enforcement immediately before side effects;
- managed-ask one-time semantics;
- effective-policy and enforcement events;
- public SDK types when an integrator must supply or observe the control.

Prefer runtime discovery of managed settings. Add a host-supplied SDK contract only when
the host genuinely owns the value.

Do not add a VS Code `policy:` merely to mirror runtime policy.
Do not add a GitHub-token/account-policy field as a substitute for managed settings.

## Permissions

- Managed `deny` / `ask` / `allow` are runtime policy.
- AHP `{ allow, deny }` contains tool-name client preferences; it is not the managed DSL.
- New VS Code/AHP code transports managed rules opaquely and does not parse or match them.
- `managedApprovalRequired` bypasses all automatic and persistent approval paths.
- Managed approval is human-only and one-time-only.
- Permission authorization never widens sandbox access.
- Validate rule grammar through the real SDK/runtime boundary.

## Host-Injection Lifecycle (In Progress)

The runtime host-injection capability is still being adopted by the public SDK and VS
Code. When an integrator uses it, host-injected managed settings are startup
configuration:

- supply them on local create and resume;
- re-supply them because they are not persisted;
- omission clears the previous injected layer;
- refresh default and peer sessions before the next turn when policy changes;
- reject unsupported cloud use instead of ignoring it.

Policy removal must survive real JSON/AHP serialization.

Client-injected settings are strict: malformed or unsupported rules reject create/resume.
Server/device discovery instead uses its defined cache and fail-open/fail-closed
degradation behavior.

The runtime composes managed sandbox floors. While sandbox configuration remains
host-driven, verify that Agent Host applies the effective floor to session
`sandboxConfig`; policy state and containment must not diverge.

Do not log raw enterprise rules or values.

## Tests

- Runtime: schema, parsing, matching, composition, revalidation, and pre-side-effect deny.
- SDK: create/resume serialization, events, handler safety, and cloud rejection.
- Agent Host E2E: generated grammar, managed asks, removal/resume, and diagnostics.

Start with:

- `github/copilot-agent-runtime/schema/managed-settings-schema.json`
- `github/copilot-agent-runtime/src/runtime/src/permissions/managed.rs`
- `github/copilot-agent-runtime/src/runtime/src/permissions/orchestrator.rs`
- `github/copilot-sdk/nodejs/src/types.ts`
Loading
Loading