Commit Graph
4 Commits
Author SHA1 Message Date
joshspicerandCopilot App 8fb912f511 Mock policy server: upstream passthrough, per-endpoint mocking, request log (#330711)
* Mock policy server: upstream passthrough, per-endpoint mocking, request log

The mock policy server only worked via product.overrides.json, which limits it
to Code OSS running from sources, requires a reload after every change, and
cannot exercise a stable/Insiders build or the CLI. Support a system HTTP proxy
as a second wiring path, keeping product.overrides.json as the default.

- Proxy anything not explicitly mocked to the real API (--upstream, default
  https://api.github.com) and stream it back, so a blanket proxy rule is safe:
  only endpoints deliberately switched on are faked. Rewrites Host, strips
  hop-by-hop headers and accept-encoding, forwards Authorization untouched, and
  reports upstream failures as 502.
- Add a per-endpoint mock/passthrough toggle. Only managed settings is mocked by
  default; applying a preset implicitly switches mocking on.
- Add managed-settings disk cache clearing. A cache entry under an hour old
  makes the runtime skip the network entirely, so an override is never even
  requested. Paths verified against managed_settings_cache.rs and
  path_helpers.rs, including the COPILOT_CACHE_HOME override.
- Add a rolling request log (GET/DELETE /api/log) surfaced in the GUI, so it is
  obvious whether the client actually reached the server.
- Add realistic managed-settings presets, each validated against the schema, and
  branch-point presets for the other endpoints.
- Only warn about unknown schema keys on 2xx, and re-validate on status change:
  a 404/466/500 body is an error payload, not a policy document.
- Route GUI assets from an explicit allowlist instead of probing public/ for
  anything that looks like a file, which would otherwise shadow proxied paths.

UX:
- Make save semantics consistent: everything auto-saves, with a pill showing
  whether the editor matches what is being served.
- Surface mocked vs proxied via tab dots, a checkbox, and reactive help text.
- Add a light palette; the dark-only one declared color-scheme: light dark, so
  UA form controls rendered light on a dark page.
- Make the schema disclosure a real button with aria-expanded, add focus-visible
  styles, and expose tab state to screen readers.
- Build the validation table from DOM nodes rather than innerHTML.
- Surface save and wire failures instead of failing silently, and fall back to
  the shared endpoint definitions when the control API is unreachable.
- Answer the GUI's own favicon request so it stops appearing in the log as a
  proxied 404.

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

* Polish mock policy server workflows

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

* Route runtime policy diagnostics through proxy

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

* Minimize runtime proxy integration

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

* Move runtime proxy fix to separate PR

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

* Address mock policy server review feedback

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

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-08-13 23:29:50 +00:00
b5e1c2c740 test: add managed settings compatibility mock responses (#330320)
* chat: negotiate managed settings client compatibility

Report the VS Code managed-settings client version, securely transport the User-Agent, parse compatibility responses, and preserve fail-closed state across refreshes.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: simplify managed settings client identity

Use the existing browser-safe Editor-Version convention from productService and remove the dedicated User-Agent IPC transport.

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

* chat: report bundled Copilot runtime version

Send the runtime version from product metadata alongside the VS Code editor identity and include both values in policy diagnostics.

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

* test: align peer chat sandbox expectation

Use the shared sandbox config builder introduced on main so the peer-chat assertion follows the current sandbox semantics.

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

* chat: use standard AI feature gate for compatibility

Route managed-settings compatibility failures through the existing entitlement hidden state instead of bespoke chat and Agents-window blocking.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: apply compatibility to policy gate context

Drive both the standard policy-gate context and entitlement hidden state when managed-settings compatibility is rejected, and cover their combined transitions.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: show minimum compatible client version

Include the server-provided minimum client version in the managed-settings update notification, with a fallback for malformed responses.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chat: show compatibility warning as modal

Use the built-in VS Code modal dialog for managed-settings compatibility lockout while preserving update, learn-more, close, and keyboard-dismiss actions.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test: add managed settings compatibility mock responses

Add 404 and client_update_required presets plus configurable response status support to the local policy server.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test: fix managed settings mock controls

Reset schema-generated examples to a successful response and document that selected presets must be applied.

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

* test: allow managed settings client identity header

Permit Editor-Version in mock endpoint CORS preflights so local testing matches the simplified client contract.

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

* test: allow Copilot runtime identity header

Permit Copilot-Runtime-Version in mock endpoint CORS preflights alongside Editor-Version.

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

* test: expose mock response status

Show and edit each mock endpoint's HTTP response status in the GUI, validate the supported range, and autosave it with the response body.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Dmitriy Vasyura <dmitriv@microsoft.com>
2026-08-13 07:28:41 -07:00
Josh SpicerandCopilot a4ce08f735 Refactor Copilot managed-settings for maintainability (#322439)
* Refactor Copilot managed-settings for maintainability

Centralize structured (object/array) managed-setting handling behind a
single descriptor table so adding a key touches one place, consolidate the
duplicated equality helpers onto `equals`, and add shared
`hasManagedSettingsDefinitions` and `managedSettingValue` helpers. Strictly
behavior-preserving.

Incorporates a 3-model maintainability review:

- `adaptManagedSettings` builds the scalar remainder via `{ ...response }`
  plus delete (CopyDataProperties) instead of for..in + assignment, so a
  server-sent own `__proto__` key cannot trigger the inherited setter. This
  matches the original `...rest` semantics; adds a regression test.
- `managedSettingValue` is memoized per key so its policy-definition
  reference identity is real rather than incidental to the call site.
- Corrected JSDoc and skill docs that overstated `responseField` as
  compiler-checked; it is a hand-maintained union backstopped by tests.

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

* Clarify why structured managed-settings keys must declare type: 'string'

The bag-carrying `type` is load-bearing, not cosmetic: `projectManagedSettings`
gates each value with `typeof value === type` and drops mismatches, and the
native MDM watcher reads the registry/plist value as that type. Spell out that
omitting it (or declaring the object/array type) makes a structured key fail
projection and silently never apply.

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

* Address PR review: allocation-free empty check, __proto__ test, doc accuracy

- hasManagedSettingsDefinitions: reuse the allocation-free isEmptyObject
  helper instead of Object.keys(...).length (the bot's only valid nit).
- Add a primitive `__proto__` regression test proving a server-sent
  `{"__proto__": true}` scalar is dropped, never pollutes the result
  (disproves the reviewer's prototype-pollution concern).
- Fix github-managed-settings.md: omitting `type` or declaring
  `'object'`/`'array'` is a compile error (the field is required and
  constrained to `'string' | 'number' | 'boolean'`), not a runtime drop;
  only `'number'`/`'boolean'` compile-but-drop-at-runtime.

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

* Surface managed-settings source in Policy Diagnostics

Centralize the server-over-MDM precedence into a shared selectManagedSettings
helper (plus a ManagedSettingsSource union) and reuse it in both
AccountPolicyService and the Policy Diagnostics report, so the report can never
drift from the source that policy evaluation actually applies.

Rewrite the diagnostics "Managed Settings" section to:
- show the Active source (GitHub Server API / Native MDM / None)
- break down each channel (server fetch status + raw response, native MDM bag)
- label the raw response as the last *successful* fetch, so a later failed
  fetch (e.g. a 404) no longer looks like it contradicts an empty effective bag
- compute the true effective bag via the shared projectManagedSettings

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

* Fix mock policy server "Generate example" not persisting

The "Generate example" button filled the editor and the localStorage draft but
never called debouncedSave(), so the generated body was never POSTed to
/api/state and the endpoint kept serving the empty preset. Add the missing
debouncedSave() to match applyPreset() and the editor input handler.

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

* Strip prose from Policy Diagnostics and collect managed-settings parse errors

The Developer: Policy Diagnostics "Managed Settings" section now renders
data only (tables and JSON blocks, no explanatory paragraphs).

It also collects non-fatal parsing/normalization warnings from every stage
of the managed-settings pipeline, jsonc-style (accumulate, never throw), and
surfaces them in a new "Parse Errors" section:
- adapt: re-runs adaptManagedSettings on the raw server response
- project: re-runs projectManagedSettings against the declared policy keys
- parse: re-parses JSON-payload string values with the jsonc parser

This explains why a key is silently dropped. For example a server
extraKnownMarketplaces entry with source "github" but no "repo" now shows
the "requires \"repo\"" warning instead of just vanishing from the bag.

Adds a focused test for that github-without-repo normalization case.

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

* Tighten Policy Diagnostics managed-settings rendering (review follow-up)

Code-quality pass on the managed-settings diagnostics section:

- Extract a jsonBlock() helper for the repeated fenced-JSON rendering
  (4 call sites collapsed).
- Parse only the known JSON-payload keys (enabledPlugins,
  strictKnownMarketplaces, extraKnownMarketplaces) instead of a
  leading-brace heuristic. This mirrors what PolicyConfiguration actually
  parses, avoids mis-sniffing scalar values, and catches malformed payloads
  that don't start with a brace.
- Unify the raw-response guard on isObject() so the printed raw response and
  the adapt-stage warning harvest use one predicate.
- Drop the defensive object copy in projectManagedSettings(); it is read-only,
  so normalize undefined with `?? {}` instead of spreading.

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

* Fix native MDM availability in Policy Diagnostics; tidy table headers

The diagnostics report showed "Native MDM | Available | no (desktop only)"
even on desktop. ICopilotManagedSettingsService was registered only in the
electron-main process and hand-plumbed into AccountPolicyService, but never
placed in the renderer service collection, so the report's
accessor.get(ICopilotManagedSettingsService) always threw and mislabeled the
channel as unavailable.

Register the CopilotManagedSettingsChannelClient (the renderer's handle to the
main-process service) in the service collection in both desktop.main.ts and
sessions.main.ts. The diagnostics now resolves it on desktop and Agents windows
and reports real native MDM availability and values; web still has no native
channel and correctly reports unavailable.

Also tidy the report builder: extract a PROPERTY_VALUE_TABLE_HEADER constant for
the five repeated two-column table headers, and drop the now-misleading
"(desktop only)" annotation on the availability row.

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-22 17:42:10 -07:00
Josh SpicerandCopilot 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