Verify TrustOps VS Code / Copilot Enforcement — Implementation Report
Release identity
- Requested baseline:
2e9ccc5(1.0.747), migration head - Repository version found at implementation time:
1.0.748. - Release version after the required single patch bump:
1.0.749. - Enforcement migration:
0040_intelligence_enforcement. - The final local implementation commit is recorded by the release gate
0039_data_export_schema_widen.
(git log -1); nothing is tagged, pushed, or deployed by this work.
Delivered
- Organization-owned policy identities and immutable policy versions with
- Consistent bulk evidence materialization, semantic evidence cutoffs,
- Pure
vscode_managed_settingscompiler, target-specific URL projection, - Private object-store publication with generating/published/failed/superseded
intelligence:enforcementauthenticated API under- Flagged anonymous MCP Registry v0.1 projection with strict field whitelisting,
- TrustOps product-page explanation and the architecture/operator contract.
resolved inventories and deterministic policy/inventory fingerprints.
evaluator-versioned idempotent snapshots, lifecycle states, four distinct decisions, structured reason codes, and source references.
strict Pydantic native contract validation, deterministic bytes, 2 MiB configurable guardrail, empty-allowlist warning, and native/manifest separation.
states, exact native and manifest SHA-256 values, rule mappings, signed downloads, impact diffs, usage attribution, and material-change webhooks.
/v1/intelligence/enforcement with organization+ID lookup constraints.
ALLOW-only filtering, pagination/search, version routes, conditional caching, and CORS/OPTIONS behavior.
Persistence and schemas
Migration 0040_intelligence_enforcement creates six tables:
intelligence_enforcement_policiesintelligence_enforcement_policy_versionsintelligence_enforcement_decision_snapshotsintelligence_enforcement_decisionsintelligence_enforcement_artifactsintelligence_enforcement_artifact_rules
Uniqueness covers policy name per organization, version number per policy, snapshot input identity, decision server per snapshot, artifact compiler identity, and artifact server mappings. Organization lookup indexes exist on tenant roots and artifact/snapshot lookup paths.
External inputs, native settings, compiler inputs/outputs, and registry output use strict Pydantic models. Native files contain only Microsoft settings; manifest metadata is serialized and hashed separately.
Tests and performance gates
verify/tests/test_intelligence_enforcement.py covers URL identity, query/path/ trailing-slash preservation, default ports, exact strict and deny-only bytes, shuffled-input determinism, malformed/wildcard/local rule rejection, conflict precedence, empty allowlist warning, size status, four-way decisions, strict registry projection, evaluator-version snapshot identity, publication idempotency, separate hashes, and non-publishing oversized previews.
Snapshot evaluation uses a fixed number of bulk database reads for servers and trust snapshots and no HTTP requests. Inventory size is capped at 1,000; no query occurs inside the per-fact evaluation loop. The automated benchmark passes at 10, 100, and 1,000 servers with at most 12 SQL statements per snapshot build, preventing a query-per-server regression.
Release gates completed on 2026-08-27:
- Focused enforcement suite: 20 passed.
- Full Verify suite: 987 passed.
- Repository
make test-suites: 350 passed; line coverage 75.75%, branch - Migration
0039 -> 0040 -> 0039: upgrade and downgrade passed in an isolated - Installed-build VS Code smoke: passed the compiler/matcher diagnostics and a
coverage 60.85% (both quality gates passed).
SQLite database. PostgreSQL remains the production target for the REPEATABLE READ evidence transaction.
live strict-policy file-channel Developer: Policy Diagnostics run as described below.
VS Code diagnostics
Target smoke version: VS Code 1.135.0. The smoke gate must preserve and restore existing managed-settings and macOS policy state even on failure. It must record Policy Diagnostics results for strict and deny-only modes and the observed /mcp vs /mcp/, :443 vs default, and query-string matcher behavior. No permanent workstation policy is installed.
The non-destructive installed-build smoke ran against VS Code 1.135.0 (08d4889f9ec4a1685d257b9b95de036c8e1ce1e5, arm64). Its shipped matcher implementation confirms deny-before-allow policy handling and exact anchored URL matching with case-insensitive comparison. Observed matcher behavior:
/mcpand/mcp/are distinct.https://host/mcpandhttps://host:443/mcpare distinct at the matcher- Query-bearing matchers preserve and require the query.
- Path comparison is case-insensitive in VS Code 1.135.0 even though Verify
function boundary.
preserves source path case while compiling.
scripts/smoke_vscode_enforcement.py records these diagnostics directly from the installed app bundle and exercises allowed, denied, and unlisted remote identities. A live Developer: Policy Diagnostics UI run was subsequently completed with a temporary strict-mode managed-settings.json containing reserved .invalid allow and deny endpoints. VS Code reported all three target policies with source Managed Settings: File: ChatAllowedMcpServers, ChatDeniedMcpServers, and ChatAllowManagedMcpServersOnly; their effective values matched the native artifact and managed-only was true. The pre-test baseline had all three policies unset. After the test, the file and temporary directory were removed, VS Code was restarted, and the three diagnostic entries were confirmed absent again. No permanent workstation policy remains.
Follow-up live behavioral checks were completed on 2026-08-29 with three loopback Streamable HTTP MCP identities on ports 18765 (allowed), 18766 (denied), and 18767 (unlisted). In strict mode, VS Code connected only to the allowed fixture, completed MCP initialization, and issued ListTools; the healthy denied and unlisted listeners received no request. In deny-only mode, a loopback packet capture showed connection attempts to allowed port 18765 and unlisted port 18767, with no packet to denied port 18766. The allowed/unlisted attempts received TCP resets because those fixture processes had exited before that capture, but the presence/absence of SYN traffic verifies the policy gate: unlisted followed normal behavior and the explicit deny was blocked before network access.
The deny-only Policy Diagnostics run separately confirmed that only ChatDeniedMcpServers was applied; neither an allowlist nor ChatAllowManagedMcpServersOnly was present. After both behavioral checks, all fixture processes were stopped and the system managed-settings file was removed. A final filesystem/listener check confirmed no policy file and no fixture ports remained.
Registry and CORS
The registry projection never merges or returns raw_registry_payload. Responses contain only strict projected v0.1 fields. Success, 404, validation error, conditional 304, and OPTIONS responses receive the required wildcard CORS headers. The feature remains disabled by default and bound to one explicit organization/policy pair.
Limitations and deferred work
- Live VS Code matcher behavior is an external product contract and remains a
- The registry projection is experimental and public-record-only; no private
- Artifact signing/PKI, automatic deployment, device management, local-command
- Governance records and native objects are retained indefinitely in V1.
per-supported-version release smoke gate.
gallery auth or management UI is included.
support, wildcard generation, and object lifecycle deletion are deferred.