@absolutejs/mcp 0.17.6 → 0.17.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,18 @@ This file is generated by `absolute-changelog` from the entries in
6
6
  `changelog/`. Edit an entry, not this file — and add new ones under
7
7
  `changelog/unreleased/`.
8
8
 
9
+ ## 0.17.8 — 2026-09-12
10
+
11
+ ### Fixed
12
+
13
+ - **Correct the VS Code checkout canary after verifying native Windows link consent and document the individual Copilot channel review**
14
+
15
+ ## 0.17.7 — 2026-09-12
16
+
17
+ ### Added
18
+
19
+ - **Ship a synthetic external-checkout host canary with expiring links, explicit approval and purchase-status checks**
20
+
9
21
  ## 0.17.6 — 2026-09-11
10
22
 
11
23
  ### Added
@@ -0,0 +1,198 @@
1
+ /** Synthetic external-checkout fixture. No accounts, card inputs or gateway. */
2
+ import {
3
+ createCheckoutHandoffTool,
4
+ createMcpHandler,
5
+ createPurchaseStatusTool,
6
+ } from "@absolutejs/mcp";
7
+
8
+ export function createCheckoutCanary(origin: string, now = () => Date.now()) {
9
+ const publicUrl = new URL(origin);
10
+ if (publicUrl.protocol !== "https:" || publicUrl.origin !== origin)
11
+ throw Error("Provide an exact HTTPS checkout origin");
12
+ const purchases = new Map<
13
+ string,
14
+ { token: string; expires: number; approved: boolean }
15
+ >();
16
+ const started = now();
17
+ const checkout = createCheckoutHandoffTool({
18
+ origin,
19
+ issue: async (productId) => {
20
+ if (productId !== "synthetic-1000")
21
+ throw Error("Only synthetic-1000 is supported");
22
+ if (purchases.size >= 100)
23
+ throw Error("Restart the canary before creating more fixtures");
24
+ const purchaseId = crypto.randomUUID();
25
+ const token = crypto.randomUUID();
26
+ const expires = now() + 15 * 60_000;
27
+ purchases.set(purchaseId, { token, expires, approved: false });
28
+ return {
29
+ purchaseId,
30
+ url: `${origin}/checkout#${purchaseId}/${token}`,
31
+ expiresAt: new Date(expires).toISOString(),
32
+ };
33
+ },
34
+ });
35
+ const status = createPurchaseStatusTool({
36
+ read: async (purchaseId) => {
37
+ const purchase = purchases.get(purchaseId);
38
+ return purchase
39
+ ? {
40
+ purchaseId,
41
+ status: purchase.approved ? "approved" : "not_started",
42
+ creditsGranted: purchase.approved ? 1000 : 0,
43
+ }
44
+ : null;
45
+ },
46
+ });
47
+ const handler = createMcpHandler({
48
+ issuer: "http://127.0.0.1:4428",
49
+ path: "/mcp",
50
+ serverInfo: { name: "absolute-checkout-canary", version: "1" },
51
+ authorize: async () => ({
52
+ ok: true,
53
+ caller: "synthetic-fixture",
54
+ scopes: [],
55
+ }),
56
+ // This review authorizes only this synthetic developer fixture. Never reuse
57
+ // it for a real merchant or infer a commerce binding from clientInfo.
58
+ commerce: () => ({
59
+ profiles: ["direct-mcp"],
60
+ capabilities: { externalLinks: true },
61
+ reviews: [
62
+ {
63
+ id: "operator-synthetic-checkout-canary",
64
+ profile: "direct-mcp",
65
+ actions: ["external_checkout"],
66
+ categories: ["usage_credits"],
67
+ reviewedAt: new Date(started).toISOString(),
68
+ expiresAt: new Date(started + 60 * 60_000).toISOString(),
69
+ sourceUrls: ["https://code.visualstudio.com/license"],
70
+ },
71
+ ],
72
+ }),
73
+ tools: () => ({
74
+ prepare_test_checkout: {
75
+ ...checkout,
76
+ description: `SYNTHETIC TEST ONLY. Use productId synthetic-1000. ${checkout.description}`,
77
+ },
78
+ get_test_purchase_status: status,
79
+ }),
80
+ });
81
+ const headers = {
82
+ "content-type": "text/html; charset=utf-8",
83
+ "cache-control": "no-store",
84
+ "referrer-policy": "no-referrer",
85
+ "x-content-type-options": "nosniff",
86
+ "content-security-policy":
87
+ "default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline'; connect-src 'self'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'",
88
+ };
89
+ const page = `<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>MCP checkout test</title><style>:root{color-scheme:light dark;font:18px system-ui}body{max-width:40rem;margin:10vh auto;padding:2rem}button{padding:1rem;font:inherit}strong{display:block;margin:1rem 0}</style><h1>MCP checkout test</h1><p>Synthetic developer fixture. No real payment, card information, account or subscription.</p><strong>1,000 simulated credits · $0 charged</strong><p id="status" role="status">Checking test link…</p><button id="approve" disabled>Simulate approval</button><script>
90
+ const capability=location.hash.slice(1);history.replaceState(null,'','/checkout');const status=document.getElementById('status'),button=document.getElementById('approve');
91
+ async function update(action){button.disabled=true;try{const r=await fetch('/state',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({capability,action})});if(!r.ok)throw Error('This test link is invalid or expired.');const value=await r.json();status.textContent=value.approved?'Approved — 1,000 simulated credits. Return to your assistant and check purchase status.':'Ready. Opening this page has not approved anything.';button.hidden=value.approved;button.disabled=value.approved;}catch(e){status.textContent=e.message;}}
92
+ button.addEventListener('click',()=>update('approve'));update('read');</script></html>`;
93
+ return {
94
+ mcp: handler,
95
+ checkout: async (request: Request): Promise<Response> => {
96
+ const url = new URL(request.url);
97
+ if (url.pathname === "/checkout" && request.method === "GET")
98
+ return new Response(page, { headers });
99
+ if (url.pathname !== "/state" || request.method !== "POST")
100
+ return new Response("Not found", { status: 404 });
101
+ if (
102
+ request.headers.get("origin") !== origin ||
103
+ !request.headers.get("content-type")?.startsWith("application/json")
104
+ )
105
+ return new Response("Forbidden", { status: 403 });
106
+ const raw = await request.text();
107
+ if (raw.length > 1024) return new Response("Too large", { status: 413 });
108
+ let input;
109
+ try {
110
+ input = JSON.parse(raw);
111
+ } catch {
112
+ return new Response("Invalid JSON", { status: 400 });
113
+ }
114
+ if (
115
+ !input ||
116
+ typeof input.capability !== "string" ||
117
+ !["read", "approve"].includes(input.action)
118
+ )
119
+ return new Response("Invalid request", { status: 400 });
120
+ const [id, token, extra] = input.capability.split("/");
121
+ const purchase = purchases.get(id);
122
+ if (
123
+ extra !== undefined ||
124
+ !purchase ||
125
+ purchase.token !== token ||
126
+ purchase.expires <= now()
127
+ )
128
+ return new Response("Invalid or expired test link", { status: 404 });
129
+ if (input.action === "approve") purchase.approved = true;
130
+ return Response.json(
131
+ { approved: purchase.approved },
132
+ { headers: { "cache-control": "no-store" } },
133
+ );
134
+ },
135
+ };
136
+ }
137
+
138
+ if (import.meta.main) {
139
+ const fixture = createCheckoutCanary(
140
+ process.env.CANARY_CHECKOUT_ORIGIN ?? "",
141
+ );
142
+ Bun.serve({
143
+ hostname: "127.0.0.1",
144
+ port: 4438,
145
+ fetch: async (request) => {
146
+ const response = await fixture.checkout(request);
147
+ const path = new URL(request.url).pathname;
148
+ console.log(
149
+ JSON.stringify({
150
+ surface: "checkout",
151
+ method: request.method,
152
+ route: path === "/checkout" || path === "/state" ? path : "unknown",
153
+ status: response.status,
154
+ }),
155
+ );
156
+ return response;
157
+ },
158
+ });
159
+ Bun.serve({
160
+ hostname: "127.0.0.1",
161
+ port: 4428,
162
+ fetch: async (request) => {
163
+ let rpc;
164
+ try {
165
+ if (request.method === "POST") rpc = await request.clone().json();
166
+ } catch {
167
+ /* handler validates */
168
+ }
169
+ const response =
170
+ (await fixture.mcp(request)) ??
171
+ new Response("Not found", { status: 404 });
172
+ // Never log checkout capabilities, arguments, transcripts or auth headers.
173
+ console.log(
174
+ JSON.stringify({
175
+ method: rpc?.method ?? request.method,
176
+ status: response.status,
177
+ ...(rpc?.method === "initialize"
178
+ ? {
179
+ client: rpc.params?.clientInfo?.name,
180
+ version: rpc.params?.clientInfo?.version,
181
+ }
182
+ : {}),
183
+ ...(rpc?.method === "tools/call" ? { tool: rpc.params?.name } : {}),
184
+ }),
185
+ );
186
+ return response;
187
+ },
188
+ });
189
+ console.log(
190
+ JSON.stringify({
191
+ ready: true,
192
+ mcp: "http://127.0.0.1:4428/mcp",
193
+ checkoutPort: 4438,
194
+ synthetic: true,
195
+ payments: false,
196
+ }),
197
+ );
198
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "host": "Visual Studio Code",
3
+ "version": "1.135.0",
4
+ "surface": "native Windows Copilot chat, directly configured loopback MCP",
5
+ "fixture": "canary/checkout.ts",
6
+ "date": "2026-09-12",
7
+ "synthetic": true,
8
+ "realPayments": false,
9
+ "results": {
10
+ "discoversBothTools": true,
11
+ "linkCreationApprovalVisible": true,
12
+ "toolResultReviewVisible": true,
13
+ "clickableMarkdownAnchor": true,
14
+ "nativeAnchorLaunch": true,
15
+ "windowsHttpsHandlerOpensReturnedUrl": true,
16
+ "nativeChromeCheckoutPage": true,
17
+ "fragmentRemovedAfterLoad": true,
18
+ "beforeBrowserApproval": {
19
+ "status": "not_started",
20
+ "creditsGranted": 0
21
+ },
22
+ "afterBrowserApproval": {
23
+ "status": "approved",
24
+ "creditsGranted": 1000
25
+ },
26
+ "repeatedRead": {
27
+ "status": "approved",
28
+ "creditsGranted": 1000
29
+ },
30
+ "nativeWindowsExternalSiteConfirmation": true,
31
+ "sameDefaultBrowserApproval": true
32
+ },
33
+ "limits": [
34
+ "Synthetic credits only; no real gateway or OAuth certified.",
35
+ "No editor patch, trusted-domain setting or browser default changed.",
36
+ "Rich payment UI and marketplace distribution are not certified.",
37
+ "No checkout capability, purchase ID, card data or account credentials included."
38
+ ],
39
+ "correction": "Earlier unverified result missed a native Windows #32770 external-site confirmation outside the CDP DOM. Full rerun used the native Open prompt and the same default Chrome page."
40
+ }
package/changelog.json CHANGED
@@ -1,161 +1,181 @@
1
1
  {
2
- "contract": 1,
3
- "name": "@absolutejs/mcp",
4
- "releases": [
5
- {
6
- "version": "0.17.6",
7
- "date": "2026-09-11",
8
- "changes": [
9
- {
10
- "kind": "fixed",
11
- "summary": "Use text and structured report results on affected VS Code builds while their upstream webview startup race remains unresolved"
12
- },
13
- {
14
- "kind": "added",
15
- "summary": "Allow verified patched hosts through the version fallback with optional Apps configuration",
16
- "symbols": [
17
- "clientSupportsMcpApps",
18
- "McpAppsConfig"
19
- ]
20
- }
21
- ]
22
- },
23
- {
24
- "version": "0.17.5",
25
- "date": "2026-09-11",
26
- "changes": [
27
- {
28
- "kind": "added",
29
- "summary": "Distribute a verified VS Code webview startup-race source patch and actual-method regression checker, with explicit upstream delivery requirements"
30
- }
31
- ]
32
- },
33
- {
34
- "version": "0.17.4",
35
- "date": "2026-09-11",
36
- "changes": [
37
- {
38
- "kind": "added",
39
- "summary": "Ship an authenticated two-account staging canary for read isolation, credential rejection and session reconnect with private credentials and aggregate-only results"
40
- }
41
- ]
42
- },
43
- {
44
- "version": "0.17.3",
45
- "date": "2026-09-11",
46
- "changes": [
47
- {
48
- "kind": "fixed",
49
- "summary": "Authorize session deletion, recover explicit client initialization after expiry, and preserve typed HTTP failures without replaying tools"
50
- },
51
- {
52
- "kind": "fixed",
53
- "summary": "Accept the standard protocol-header compatibility fallback used by VS Code Copilot and record native report rendering evidence"
54
- }
55
- ]
56
- },
57
- {
58
- "version": "0.17.2",
59
- "date": "2026-09-11",
60
- "changes": [
61
- {
62
- "kind": "added",
63
- "summary": "Record verified Claude web rendering, refresh, pagination and narrow-viewport host canary evidence"
64
- }
65
- ]
66
- },
67
- {
68
- "version": "0.17.1",
69
- "date": "2026-09-11",
70
- "changes": [
71
- {
72
- "kind": "added",
73
- "summary": "Ship a preflight-validated synthetic host canary and record Claude Code and Codex terminal interoperability evidence"
74
- }
75
- ]
76
- },
77
- {
78
- "version": "0.17.0",
79
- "date": "2026-09-11",
80
- "changes": [
81
- {
82
- "kind": "added",
83
- "summary": "Negotiate MCP Apps with persisted capabilities, guarded offline UI resources and reusable SDK-backed billing views"
84
- },
85
- {
86
- "kind": "added",
87
- "summary": "Preserve remote UI metadata in the client and expose immutable PostgreSQL migration entries"
88
- },
89
- {
90
- "kind": "changed",
91
- "summary": "Extend McpClientOptions, McpRemoteTool, createSessionRegistry, McpSessionStore, McpServerConfig, McpTool and McpToolResult with optional Apps capability and metadata fields; existing text-only callers remain supported",
92
- "symbols": [
93
- "McpClientOptions",
94
- "McpRemoteTool",
95
- "createSessionRegistry",
96
- "McpSessionStore",
97
- "McpServerConfig",
98
- "McpTool",
99
- "McpToolResult"
100
- ]
101
- }
102
- ]
103
- },
104
- {
105
- "version": "0.16.0",
106
- "date": "2026-09-11",
107
- "changes": [
108
- {
109
- "kind": "added",
110
- "summary": "Add account-bound billing status, paginated receipts, bounded usage and reviewed billing-management links"
111
- }
112
- ]
113
- },
114
- {
115
- "version": "0.15.1",
116
- "date": "2026-09-11",
117
- "changes": [
118
- {
119
- "kind": "fixed",
120
- "summary": "Build and test before publishing so checkout exports are present in the distributed artifact"
121
- }
122
- ]
123
- },
124
- {
125
- "version": "0.15.0",
126
- "date": "2026-09-11",
127
- "changes": [
128
- {
129
- "kind": "added",
130
- "summary": "Add commerce-classified account-bound checkout handoff and purchase status tools"
131
- }
132
- ]
133
- },
134
- {
135
- "changes": [
136
- {
137
- "kind": "added",
138
- "summary": "Add explicit credit-budget envelopes for durable prepaid MCP work"
139
- }
140
- ],
141
- "date": "2026-09-11",
142
- "version": "0.14.0"
143
- },
144
- {
145
- "changes": [
146
- {
147
- "kind": "added",
148
- "summary": "Add reviewed host commerce eligibility, execution guards, and reusable credit status tools",
149
- "symbols": [
150
- "McpServerConfig",
151
- "McpTool",
152
- "evaluateCommerce",
153
- "createCreditBalanceTool"
154
- ]
155
- }
156
- ],
157
- "date": "2026-09-11",
158
- "version": "0.13.0"
159
- }
160
- ]
2
+ "contract": 1,
3
+ "name": "@absolutejs/mcp",
4
+ "releases": [
5
+ {
6
+ "changes": [
7
+ {
8
+ "kind": "fixed",
9
+ "summary": "Correct the VS Code checkout canary after verifying native Windows link consent and document the individual Copilot channel review"
10
+ }
11
+ ],
12
+ "date": "2026-09-12",
13
+ "version": "0.17.8"
14
+ },
15
+ {
16
+ "changes": [
17
+ {
18
+ "kind": "added",
19
+ "summary": "Ship a synthetic external-checkout host canary with expiring links, explicit approval and purchase-status checks"
20
+ }
21
+ ],
22
+ "date": "2026-09-12",
23
+ "version": "0.17.7"
24
+ },
25
+ {
26
+ "changes": [
27
+ {
28
+ "kind": "fixed",
29
+ "summary": "Use text and structured report results on affected VS Code builds while their upstream webview startup race remains unresolved"
30
+ },
31
+ {
32
+ "kind": "added",
33
+ "summary": "Allow verified patched hosts through the version fallback with optional Apps configuration",
34
+ "symbols": [
35
+ "clientSupportsMcpApps",
36
+ "McpAppsConfig"
37
+ ]
38
+ }
39
+ ],
40
+ "date": "2026-09-11",
41
+ "version": "0.17.6"
42
+ },
43
+ {
44
+ "changes": [
45
+ {
46
+ "kind": "added",
47
+ "summary": "Distribute a verified VS Code webview startup-race source patch and actual-method regression checker, with explicit upstream delivery requirements"
48
+ }
49
+ ],
50
+ "date": "2026-09-11",
51
+ "version": "0.17.5"
52
+ },
53
+ {
54
+ "changes": [
55
+ {
56
+ "kind": "added",
57
+ "summary": "Ship an authenticated two-account staging canary for read isolation, credential rejection and session reconnect with private credentials and aggregate-only results"
58
+ }
59
+ ],
60
+ "date": "2026-09-11",
61
+ "version": "0.17.4"
62
+ },
63
+ {
64
+ "changes": [
65
+ {
66
+ "kind": "fixed",
67
+ "summary": "Authorize session deletion, recover explicit client initialization after expiry, and preserve typed HTTP failures without replaying tools"
68
+ },
69
+ {
70
+ "kind": "fixed",
71
+ "summary": "Accept the standard protocol-header compatibility fallback used by VS Code Copilot and record native report rendering evidence"
72
+ }
73
+ ],
74
+ "date": "2026-09-11",
75
+ "version": "0.17.3"
76
+ },
77
+ {
78
+ "changes": [
79
+ {
80
+ "kind": "added",
81
+ "summary": "Record verified Claude web rendering, refresh, pagination and narrow-viewport host canary evidence"
82
+ }
83
+ ],
84
+ "date": "2026-09-11",
85
+ "version": "0.17.2"
86
+ },
87
+ {
88
+ "changes": [
89
+ {
90
+ "kind": "added",
91
+ "summary": "Ship a preflight-validated synthetic host canary and record Claude Code and Codex terminal interoperability evidence"
92
+ }
93
+ ],
94
+ "date": "2026-09-11",
95
+ "version": "0.17.1"
96
+ },
97
+ {
98
+ "changes": [
99
+ {
100
+ "kind": "added",
101
+ "summary": "Negotiate MCP Apps with persisted capabilities, guarded offline UI resources and reusable SDK-backed billing views"
102
+ },
103
+ {
104
+ "kind": "added",
105
+ "summary": "Preserve remote UI metadata in the client and expose immutable PostgreSQL migration entries"
106
+ },
107
+ {
108
+ "kind": "changed",
109
+ "summary": "Extend McpClientOptions, McpRemoteTool, createSessionRegistry, McpSessionStore, McpServerConfig, McpTool and McpToolResult with optional Apps capability and metadata fields; existing text-only callers remain supported",
110
+ "symbols": [
111
+ "McpClientOptions",
112
+ "McpRemoteTool",
113
+ "createSessionRegistry",
114
+ "McpSessionStore",
115
+ "McpServerConfig",
116
+ "McpTool",
117
+ "McpToolResult"
118
+ ]
119
+ }
120
+ ],
121
+ "date": "2026-09-11",
122
+ "version": "0.17.0"
123
+ },
124
+ {
125
+ "changes": [
126
+ {
127
+ "kind": "added",
128
+ "summary": "Add account-bound billing status, paginated receipts, bounded usage and reviewed billing-management links"
129
+ }
130
+ ],
131
+ "date": "2026-09-11",
132
+ "version": "0.16.0"
133
+ },
134
+ {
135
+ "changes": [
136
+ {
137
+ "kind": "fixed",
138
+ "summary": "Build and test before publishing so checkout exports are present in the distributed artifact"
139
+ }
140
+ ],
141
+ "date": "2026-09-11",
142
+ "version": "0.15.1"
143
+ },
144
+ {
145
+ "changes": [
146
+ {
147
+ "kind": "added",
148
+ "summary": "Add commerce-classified account-bound checkout handoff and purchase status tools"
149
+ }
150
+ ],
151
+ "date": "2026-09-11",
152
+ "version": "0.15.0"
153
+ },
154
+ {
155
+ "changes": [
156
+ {
157
+ "kind": "added",
158
+ "summary": "Add explicit credit-budget envelopes for durable prepaid MCP work"
159
+ }
160
+ ],
161
+ "date": "2026-09-11",
162
+ "version": "0.14.0"
163
+ },
164
+ {
165
+ "changes": [
166
+ {
167
+ "kind": "added",
168
+ "summary": "Add reviewed host commerce eligibility, execution guards, and reusable credit status tools",
169
+ "symbols": [
170
+ "McpServerConfig",
171
+ "McpTool",
172
+ "evaluateCommerce",
173
+ "createCreditBalanceTool"
174
+ ]
175
+ }
176
+ ],
177
+ "date": "2026-09-11",
178
+ "version": "0.13.0"
179
+ }
180
+ ]
161
181
  }
@@ -264,3 +264,26 @@ The first slice exports `evaluateCommerce` through `@absolutejs/mcp/commerce`, a
264
264
  The bundled rules cover the explicit restrictions established above; the broad host inventory currently maps to reviewed direct/self-hosted or unknown profiles rather than claiming every host has been verified. Missing policy, malformed categories, ambiguous restrictions, expired reviews and unavailable capabilities block the action. Deployment reviews cannot override bundled restrictions.
265
265
 
266
266
  This slice is not a general content filter: prompts, resources, untagged tools and arbitrary returned links require the shared evaluator at their own presentation boundaries. Shared renderers, native capability plumbing, checkout sessions, prepaid accounting changes and live cross-host conformance remain to implement. Existing Agency enforcement remains independent.
267
+
268
+ ## September 12 follow-up: native VS Code developer checkout test
269
+
270
+ The directly configured VS Code/Copilot channel now has a package-owned
271
+ [synthetic checkout canary](host-canaries.md#synthetic-external-checkout-canary).
272
+ This is an application development test within VS Code license §1, with no real
273
+ merchant, card input, funds or credits. It does not change the `direct-mcp`
274
+ production default, approve Marketplace distribution, or establish permission
275
+ for live sales under every Copilot agreement. Check the actual account's terms:
276
+ individual Copilot uses GitHub ToS §J; volume licensing has separate current
277
+ Generative AI Services Terms. The old Copilot product-specific terms are archived.
278
+ The linked canary record preserves the exact native host result independently
279
+ of commercial eligibility. Existing Claude and ChatGPT restrictions still apply.
280
+
281
+ ## September 12 individual Copilot external-checkout review
282
+
283
+ The operator confirmed an individual subscription. The [scoped review](reviews/vscode-individual-external-checkout.md)
284
+ concludes that user-requested, service-owned HTTPS credit checkout is eligible
285
+ for an explicit deployment binding, with a dated interpretation and exact
286
+ conditions. This does not change the global direct-MCP default. The complete
287
+ native handoff now passes after accounting for Windows' external-site dialog;
288
+ no link defect or need for an upstream link fix was established. Rich-view
289
+ startup remains a separate tracked issue.
@@ -103,3 +103,72 @@ MCP 0.17.5 includes `canary/vscode/README.md`, a VS Code source patch and an exe
103
103
  The issue is tracked in [microsoft/vscode#335908](https://github.com/microsoft/vscode/issues/335908). Known affected versions now receive text and structured reports on new sessions, keeping tools usable without invoking the faulty webview path. Other hosts retain their negotiated presentation. See [UPSTREAM_ISSUES.md](../UPSTREAM_ISSUES.md) for scope and removal conditions. This workaround does not certify rich rendering on affected editors.
104
104
 
105
105
  Native Windows VS Code 1.135.0 verification: after removing the in-memory editor patch, reconnecting alone left cached UI metadata and produced resource errors. Running **MCP: Reset Cached Tools**, reloading the window and opening a new chat cleared it. The final run returned all three reports as visible text, with three successful tool calls, no resource reads and no App frames. This is a verified text fallback, not rich rendering evidence.
106
+
107
+ ## Synthetic external-checkout canary
108
+
109
+ `bun run canary:checkout` (installed: `bun node_modules/@absolutejs/mcp/canary/checkout.ts`)
110
+ uses the package's real checkout handoff and purchase-status tools with in-memory
111
+ synthetic purchases. Set `CANARY_CHECKOUT_ORIGIN` to the exact HTTPS origin of a
112
+ temporary reverse proxy to loopback port 4438. Connect the desktop test host only
113
+ to `http://127.0.0.1:4428/mcp`. Expose only port 4438 through the proxy; it serves
114
+ only the fixture page/state routes, never MCP. Stop both processes after testing.
115
+ No account database, payment provider, card input or real credit ledger is used.
116
+ Do not mount either handler in a customer application.
117
+
118
+ This is an operator-authorized development test, not a live commerce approval.
119
+ The fixture's one-hour, server-owned review applies only to synthetic links;
120
+ never copy it into a production commerce binding. VS Code's [license §1](https://code.visualstudio.com/license)
121
+ permits application development/testing. GitHub's [additional product terms](https://docs.github.com/en/site-policy/github-terms/github-terms-for-additional-products-and-features#github-copilot)
122
+ point individual Copilot users to ToS §J and business users to their applicable
123
+ agreement. The older Copilot product terms are archived; current volume purchases
124
+ may instead use the [March 2026 Generative AI Services Terms](https://github.com/customer-terms/github-generative-ai-services-terms).
125
+ Do not treat an old agreement, another product's marketplace rules, or this
126
+ technical test as approval for every Copilot account or live digital sales.
127
+
128
+ 1. Request `prepare_test_checkout` with `productId: "synthetic-1000"` and approve
129
+ the host's tool prompt if shown. Ask for a clickable link and a
130
+ `get_test_purchase_status` read using the returned `purchaseId`.
131
+ 2. Confirm status is `not_started`, with zero granted credits. Click the link
132
+ using the host's ordinary external-link UI. The HTTPS page must clearly say
133
+ synthetic test, show no card fields, and require **Simulate approval**.
134
+ 3. Before clicking that button, read status again: still zero. Click once, then
135
+ return to chat and request status again: approved, 1,000 simulated credits.
136
+ 4. Repeat the read: still 1,000. Never let the agent approve the browser step on
137
+ behalf of a paying customer. This operator test contains no real payment.
138
+
139
+ Links expire after 15 minutes. Capabilities travel in a URL fragment, are removed
140
+ from the address bar on load, and are submitted only to the same checkout origin.
141
+ Refreshing after removal intentionally requires reopening the original link.
142
+ The fixture is bounded to 100 purchases per run. Its aggregate log excludes
143
+ capabilities and tool arguments; keep full host transcripts private. Record the
144
+ actual link UI, approval UI, browser navigation, before/after tool results and
145
+ host version. This does not certify real merchant approval, OAuth continuity,
146
+ 3DS, or rich embedded payment support.
147
+
148
+ ### September 12 VS Code checkout observation
149
+
150
+ Native Windows VS Code 1.135.0/Copilot discovered both tools, displayed link-creation
151
+ and result-review prompts, and rendered the returned HTTPS URL as a Markdown
152
+ anchor. Native Chrome showed the fixture page with its fragment removed. Copilot
153
+ reported `not_started`/0 after the browser opened, then `approved`/1000 after the
154
+ operator's simulated approval, including a second unchanged status read.
155
+
156
+ **Corrected after a complete native rerun:** the previous test missed a Windows
157
+ native `#32770` dialog asking whether Code should open the external website. It
158
+ is outside the CDP page DOM: `getByRole("dialog")` returning zero did not mean no
159
+ prompt existed. Several previous clicks had queued confirmations. Dismissing
160
+ stale test prompts and choosing **Open** for the fresh expected origin produced
161
+ checkout GET and state POST responses. Windows accessibility verified the actual
162
+ default Chrome page, then the operator explicitly invoked its **Simulate approval**
163
+ button. Copilot read zero before that click and approved/1000 twice afterward.
164
+ No manual URL navigation was needed in this final run.
165
+
166
+ Use Windows native dialog inspection when a click appears inert; do not repeatedly
167
+ click, change trusted domains, or patch the editor to bypass the prompt. Preserve
168
+ normal per-link consent. This was a test-automation gap, not an established host
169
+ link defect. See `canary/results/vscode-checkout-2026-09-12.json` for the corrected
170
+ aggregate evidence. The separate rich-view startup issue is unchanged.
171
+
172
+ The [individual Copilot external-checkout review](reviews/vscode-individual-external-checkout.md)
173
+ records the exact eligible deployment scope and activation conditions; the
174
+ synthetic fixture is not a real merchant/OAuth acceptance test.
@@ -0,0 +1,61 @@
1
+ # VS Code individual Copilot: external service-credit checkout
2
+
3
+ Reviewed September 12, 2026; re-review by October 12, 2026. The operator confirmed
4
+ an **individual Copilot subscription**. Channel: native VS Code, manually configured
5
+ remote MCP, service-owned HTTPS checkout. This review covers user-requested
6
+ one-time purchases of non-transferable credits for the connected service.
7
+
8
+ ## Decision and evidence
9
+
10
+ **Eligible for a deployment-specific external-checkout binding under the conditions
11
+ below.** This is our documented interpretation of the reviewed terms, not a
12
+ Microsoft/GitHub certification or an express vendor statement about credit sales.
13
+ The inspected terms do not specifically prohibit this scoped flow. Do not describe
14
+ that absence as permission for every commercial use or every Copilot account.
15
+
16
+ - [GitHub additional product terms, Copilot](https://docs.github.com/en/site-policy/github-terms/github-terms-for-additional-products-and-features#github-copilot)
17
+ directs individual users to the general terms, including AI-feature terms.
18
+ - [GitHub ToS, effective April 27, 2026](https://docs.github.com/en/site-policy/github-terms/github-terms-of-service#j-ai-features-training-and-your-data)
19
+ covers AI inputs/outputs, user responsibility, and individual data-use controls.
20
+ Section B.5 distinguishes third-party relationships; §H restricts API abuse.
21
+ - [GitHub acceptable-use policies](https://docs.github.com/en/site-policy/acceptable-use-policies/github-acceptable-use-policies)
22
+ forbid service resale without permission, unsolicited promotions/spam, privacy
23
+ violations and deceptive conduct. Our scope is a requested purchase of the
24
+ connected merchant's own service, with no GitHub-service resale or unsolicited
25
+ promotion. Do not source sales-lead data from GitHub contrary to these rules.
26
+ - [VS Code license](https://code.visualstudio.com/license) and
27
+ [MCP documentation](https://code.visualstudio.com/docs/agent-customization/mcp-servers)
28
+ describe the editor and direct MCP/trust mechanisms. The license alone was
29
+ sufficient only for the earlier developer test; it is not a commerce certificate.
30
+
31
+ Native VS Code 1.135.0 passed the synthetic handoff through its normal Windows
32
+ external-site confirmation and the default browser. Opening the page granted
33
+ nothing; explicit simulated approval produced one unchanged 1,000-credit result
34
+ across repeated reads. See the [host canary](../host-canaries.md). This tests
35
+ transport and user interaction; the real merchant/account flow needs its own
36
+ staging validation before activation.
37
+
38
+ ## Required deployment scope
39
+
40
+ 1. Bind an operator-reviewed OAuth registration to the authenticated account and
41
+ this exact direct channel. Never grant eligibility from `clientInfo`, model
42
+ name, arbitrary client metadata, or a user-supplied profile. Confirm the
43
+ account's agreement; organization-managed accounts need a separate review.
44
+ 2. Limit this review to `external_checkout` / `usage_credits`. The shared
45
+ `direct-mcp` default remains unverified until the deployment supplies a fresh
46
+ review. Unknown, ambiguous and published restricted profiles stay closed.
47
+ 3. Create an expiring, account-bound link on the merchant's own HTTPS origin.
48
+ Keep card entry and explicit payment confirmation in that browser page.
49
+ Tool approval, native **Open**, page load and a chat claim never charge or
50
+ prove payment. Verify payment and grant credits on the server exactly once.
51
+ 4. Offer the link only in response to a purchase/top-up request. Keep normal
52
+ host trust prompts. Do not automatically opt out of review or mark all
53
+ domains trusted. Never collect payment credentials in MCP arguments or chat.
54
+ 5. Expire the binding at review expiry; re-review changed terms, account type,
55
+ distribution, categories or host behavior. Follow merchant privacy/terms and
56
+ applicable provider requirements. Treat transcripts as potentially retained.
57
+
58
+ Excluded: Marketplace listings, GitHub-hosted storefronts, organization accounts,
59
+ ChatGPT/Claude hosted channels, embedded card forms, saved-card tool charges,
60
+ automatic refill, subscriptions and blanket approval for other MCP clients.
61
+ The VS Code rich-view startup workaround is a separate issue and still applies.
package/package.json CHANGED
@@ -73,7 +73,8 @@
73
73
  "docs/third-party",
74
74
  "canary",
75
75
  "docs/host-canaries.md",
76
- "UPSTREAM_ISSUES.md"
76
+ "UPSTREAM_ISSUES.md",
77
+ "docs/reviews"
77
78
  ],
78
79
  "scripts": {
79
80
  "build": "bun run build:apps && rm -rf dist && bun build src/index.ts src/manifest.ts src/commerce.ts src/apps.ts --outdir dist --root ./src --target=bun --external @absolutejs/agency --external '@absolutejs/agency/*' --external elysia && tsc --emitDeclarationOnly --project tsconfig.json && absolute-manifest emit",
@@ -85,8 +86,9 @@
85
86
  "prepublishOnly": "bun run check:package",
86
87
  "build:apps": "bun scripts/build-apps.ts",
87
88
  "canary": "bun canary/server.ts",
88
- "check:canary": "tsc --noEmit --strict --skipLibCheck --moduleResolution bundler --module esnext --target esnext --types bun canary/server.ts canary/authenticated.ts canary/vscode/check-mount.ts"
89
+ "check:canary": "tsc --noEmit --strict --skipLibCheck --moduleResolution bundler --module esnext --target esnext --types bun canary/server.ts canary/authenticated.ts canary/vscode/check-mount.ts canary/checkout.ts",
90
+ "canary:checkout": "bun canary/checkout.ts"
89
91
  },
90
92
  "types": "./dist/src/index.d.ts",
91
- "version": "0.17.6"
93
+ "version": "0.17.8"
92
94
  }