Files
vscode/scripts/mock-policy-server/README.md
Josh Spicer 593c7f2366 policy: dev mock server for copilot_internal policy endpoints (#321871)
* policy: add dev mock server for copilot_internal policy endpoints

Adds scripts/mock-policy-server, a standalone dev tool (npm run
mock-policy-server) that mocks the Copilot policy endpoints
DefaultAccountService calls: entitlements (/copilot_internal/user), token
(/copilot_internal/v2/token), MCP registry (/copilot/mcp_registry) and
managed settings (/copilot_internal/managed_settings).

A small web GUI lets devs pick presets or edit each JSON response, and
Wire/Unwire buttons point product.overrides.json at the local server
(preserving the rest of defaultChatAgent, since bootstrap-meta merges
overrides shallowly). The managed-settings JSON schema is loaded from
--schema/MANAGED_SETTINGS_SCHEMA, defaulting to
./copilot-agent-runtime/schema/managed-settings-schema.json relative to
the app cwd; web URLs and file URIs are accepted, and the GUI warns about
keys not declared in the schema.

The three browser/shared .js files are added to
.eslint-allowed-javascript-files since the GUI loads them directly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* policy: address mock-policy-server review feedback

- Scope permissive CORS to the mocked GET endpoints only; keep /api/*
  same-origin so a website can't drive /api/wire and rewrite
  product.overrides.json (CSRF).
- Coerce an empty editor body to {} instead of "" so mocked responses
  stay JSON objects.
- Build the endpoint meta line with textContent/DOM nodes instead of
  innerHTML.
- Drop the misused tablist/tab ARIA roles; the nav now has an aria-label
  and the active item uses aria-current.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* policy: document mock policy server in add-policy skill

Add local-testing.md to the add-policy skill with basic steps for using
the mock policy server (scripts/mock-policy-server) to exercise the
account/managed-settings flow locally, and link it from SKILL.md and
github-managed-settings.md.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* policy: polish mock server GUI — schema validation, wiring backup, localStorage persistence

* policy: auto-save, rename wiring to product.overrides.json, copy path button

* mock-policy-server: convert server.js to TypeScript; add raw response diagnostics

- Convert server.js → server.ts (runs via --experimental-strip-types)
- Add endpoints.d.ts type declarations for the UMD endpoints module
- Add managedSettingsRawResponse to IDefaultAccountProvider/IDefaultAccountService
- Show raw response in Developer: Sync Account Policy output
- Remove server.js from eslint allowed-javascript-files

* mock-policy-server: convert all JS to TypeScript

- endpoints.js → endpoints.ts with proper interfaces (replaces .d.ts)
- public/app.js → public/app.ts with full type annotations
- Server uses module.stripTypeScriptTypes() to serve .ts as plain JS
  to the browser — no build step needed
- Remove all mock-policy-server entries from .eslint-allowed-javascript-files

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-18 21:55:01 +00:00

3.9 KiB

Mock Copilot policy endpoints

A standalone dev tool that mocks the Copilot policy endpoints that DefaultAccountService (src/vs/workbench/services/accounts/browser/defaultAccount.ts) calls, so you can exercise the entitlement / token / MCP-registry / managed-settings (policy) pipeline locally without the real GitHub backend.

It is not part of the shipped product — it is a local Node server + web GUI.

What it mocks

Endpoint Path product.json key Response
Entitlements /copilot_internal/user entitlementUrl IEntitlementsData (chat_enabled, copilot_plan, cloud_session_storage_enabled, …)
Token /copilot_internal/v2/token tokenEntitlementUrl { token: "agent_mode=1;editor_preview_features=1;mcp=1;…:sig" }
MCP registry /copilot/mcp_registry mcpRegistryDataUrl { mcp_registries: [{ url, registry_access }] }
Managed settings /copilot_internal/managed_settings managedSettingsUrl IManagedSettingsResponse (enterprise settings.json)

The flow is gated: the token and managed settings are only fetched when entitlements report chat_enabled: true, and the MCP registry only when the token enables mcp.

Usage

npm run mock-policy-server          # starts on http://127.0.0.1:3000
npm run mock-policy-server -- --port 4000
npm run mock-policy-server -- --schema ./copilot-agent-runtime/schema/managed-settings-schema.json
  1. Open the printed GUI URL.
  2. Pick an endpoint tab, choose a preset or edit the JSON, and Save.
  3. Click Wire all endpoints to point product.overrides.json at this server.
  4. Reload Code OSS (running from sources, so VSCODE_DEV is set).
  5. Sign in with your GitHub/Copilot account.
  6. Run Developer: Sync Account Policy (forces a refresh).
  7. Run Developer: Policy Diagnostics to inspect the applied values.

Click Unwire to restore the original URLs.

Managed-settings schema

The GUI loads the managed-settings JSON schema and, on the Managed Settings tab, warns about top-level keys that are not declared in it (mirroring how projectManagedSettings drops undeclared keys). The schema source is resolved in this order:

  1. --schema <url | file-uri | path> CLI flag
  2. MANAGED_SETTINGS_SCHEMA environment variable
  3. Default: ./copilot-agent-runtime/schema/managed-settings-schema.json, resolved against the app's current working directory (normally the vscode repo root, where the schema repo sits side-by-side).

http(s):// URLs and file:// URIs are both accepted; relative paths are resolved from the cwd. The schema is re-read on every Refresh, so you can edit it without restarting the server. A missing schema is non-fatal — the GUI just shows the resolved path and skips schema validation.

How wiring works

src/bootstrap-meta.ts merges product.overrides.json over product.json with a shallow, top-level Object.assign, only when VSCODE_DEV is set, and the file is git-ignored. To override nested keys the tool writes back the entire defaultChatAgent object (seeded from product.json) with only the four endpoint URLs flipped, preserving every other key. Unwiring restores those URLs to their product.json values and removes the file if nothing else remains.

Caveats

  • Works for the default (github.com) provider path, which reads these URLs directly from config. The enterprise provider derives some URLs from the enterprise host instead.
  • You must be signed in; the fetch only fires for an authenticated account.
  • Overrides require a reload and only apply when running from sources.
  • The server ignores the Authorization header — any token is accepted.

Files

  • server.js — zero-dependency Node http server (endpoints + control API + schema loader + static).
  • endpoints.js — shared endpoint definitions and presets (used by server and GUI).
  • public/ — the web GUI (index.html, app.js, style.css).