feat: bound hosted publication windows and add HTTPS acceptance [skip ci]

This commit is contained in:
Forge
2026-09-22 21:15:03 +00:00
parent 89d6996123
commit 384daf329f
7 changed files with 493 additions and 4 deletions
+2 -2
View File
@@ -3,10 +3,10 @@ import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const root=path.dirname(fileURLToPath(import.meta.url));
export async function startLocal({state,testing=false,boundary,port=0,publishing=true,initialize=true}={}) {
export async function startLocal({state,testing=false,boundary,port=0,publishing=true,publishingUntil,initialize=true}={}) {
const mf=new Miniflare({...convertV4MiniflareOptions({host:'127.0.0.1',port,workers:[{name:'registry',modules:true,scriptPath:path.join(root,'.build',testing?'test-worker.js':'worker.js'),compatibilityDate:'2026-09-21',
d1Databases:{DB:'registry'},r2Buckets:{PACKAGES:'packages'},
bindings:{PUBLISHING_ENABLED:String(publishing)},serviceBindings:{
bindings:{PUBLISHING_ENABLED:String(publishing),...(publishingUntil===undefined?{}:{PUBLISHING_UNTIL:publishingUntil})},serviceBindings:{
ASSETS:async req=>{const name=path.basename(new URL(req.url).pathname);if(!['index.html','app.js','style.css'].includes(name))return new Response('Not found',{status:404});return new Response(fs.readFileSync(path.join(root,'../public',name)),{headers:{'Content-Type':name.endsWith('.html')?'text/html':name.endsWith('.js')?'text/javascript':'text/css'}});},
...(boundary?{TEST_BOUNDARY:boundary}:{})}}]}),resourcePersistencePath:state});
await mf.ready;
@@ -0,0 +1,10 @@
import assert from 'node:assert/strict';
import {startLocal} from './local.mjs';
const checks=[];
for(const [label,deadline,enabled] of [['future',new Date(Date.now()+60000).toISOString(),true],['expired',new Date(0).toISOString(),false],['invalid','invalid',false]]){
const s=await startLocal({publishingUntil:deadline});
try{const base='http://127.0.0.1:'+s.port;assert.equal((await(await fetch(base+'/api/health')).json()).publishing,enabled);const r=await fetch(base+'/api/publish',{method:'POST',body:'{}'});assert.equal(r.status,enabled?400:503);checks.push(label+' deadline health and POST agree');}finally{await s.close();}
}
const s=await startLocal({publishingUntil:new Date(Date.now()+4000).toISOString()});
try{const base='http://127.0.0.1:'+s.port;assert.equal((await(await fetch(base+'/api/health')).json()).publishing,true);await new Promise(r=>setTimeout(r,4100));assert.equal((await(await fetch(base+'/api/health')).json()).publishing,false);assert.equal((await fetch(base+'/api/publish',{method:'POST',body:'{}'})).status,503);checks.push('live window expires without deployment or process restart');}finally{await s.close();}
console.log(JSON.stringify({checks,success:true}));
+8 -2
View File
@@ -15,6 +15,12 @@ function decodeBase64(value:string) {
}
function json(status:number,data:unknown) { return Response.json(data,{status,headers:{...headers,'Cache-Control':'no-store'}}); }
class InputError extends Error {}
// Optional operator deadline makes a controlled acceptance window fail closed after interruption.
// Existing local fixtures may omit it; hosted acceptance always supplies an absolute UTC deadline.
function publishingEnabled(env:any) {
return env.PUBLISHING_ENABLED === 'true' &&
(env.PUBLISHING_UNTIL === undefined || Date.now() < Date.parse(env.PUBLISHING_UNTIL));
}
async function readBody(request:Request) {
const limit=MAX_PACKAGE_BYTES*1.5;
if(Number(request.headers.get('content-length'))>limit) throw new InputError('Submission exceeds 12 MiB envelope limit');
@@ -58,7 +64,7 @@ export function createHandler(hook: (phase:string)=>Promise<void> = async()=>{})
// All reads use the primary D1 endpoint. No eventually-consistent cache or replicas.
const schema=await env.DB.prepare("SELECT value FROM registry_meta WHERE key='schema'").first('value');
if(schema!=='1')return json(503,{error:'Registry is not initialized or schema is unsupported; operator must apply migrations'});
if(request.method==='GET'&&url.pathname==='/api/health')return json(200,{ok:true,publishing:env.PUBLISHING_ENABLED==='true',protocol:1,storage:'d1-r2',schema:1});
if(request.method==='GET'&&url.pathname==='/api/health')return json(200,{ok:true,publishing:publishingEnabled(env),protocol:1,storage:'d1-r2',schema:1});
const releases=/^\/api\/extensions\/([a-z0-9-]+)$/.exec(url.pathname);
if(request.method==='GET'&&(url.pathname==='/api/extensions'||releases)) {
const query=releases?env.DB.prepare('SELECT listing FROM releases WHERE id=?').bind(releases[1]):env.DB.prepare('SELECT listing FROM releases');
@@ -78,7 +84,7 @@ export function createHandler(hook: (phase:string)=>Promise<void> = async()=>{})
return new Response(bytes,{headers:{...headers,'Content-Type':'application/vnd.codegraph.extension+json','Content-Length':String(row.size),'Cache-Control':'public, max-age=31536000, immutable','Content-Disposition':`attachment; filename="${download[1]}-${encodeURIComponent(version)}.cgext"`}});
}
if(request.method==='POST'&&url.pathname==='/api/publish') {
if(env.PUBLISHING_ENABLED!=='true')return json(503,{error:'Publishing is disabled; operator must verify storage and usage limits before enabling it'});
if(!publishingEnabled(env))return json(503,{error:'Publishing is disabled; operator must verify storage and usage limits before enabling it'});
const origin=request.headers.get('origin');if(origin&&origin!==url.origin)return json(403,{error:'Publisher origin is not allowed'});
const minute=Math.floor(Date.now()/60000),ip=request.headers.get('CF-Connecting-IP')??'local';
const rateKey=await digest(utf8.encode(ip+':'+minute));
@@ -0,0 +1,216 @@
// PLAYWRIGHT_MODULE=/absolute/path/to/playwright node scripts/validation/marketplace-browser.cjs
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const http = require('node:http');
const assert = require('node:assert/strict');
const { DatabaseSync } = require('node:sqlite');
const { chromium } = require(process.env.PLAYWRIGHT_MODULE || 'playwright');
const { startMarketplaceServer } = process.env.CLOUDFLARE_REGISTRY === '1' ? require('./cloudflare-registry.cjs') : require('../../dist/plugins/marketplace');
const { startExtensionBridge } = require('../../dist/plugins/bridge');
process.env.CODEGRAPH_TELEMETRY = '0';
process.env.CODEGRAPH_PARSE_WORKERS = '2';
const out = path.resolve(process.env.BROWSER_OUTPUT || '.qa/recovery/browser'); fs.mkdirSync(out, { recursive: true });
const checks = [];
const safeError = error => String(error.stack || error).replace(/token=[a-f0-9]+/g, 'token=[redacted]');
function artifact(version, broken = false) {
return Buffer.from(JSON.stringify({ format: 'codegraph-extension-1', package: {
name: '@browser/example', version, main: 'index.cjs', codegraph: { id: 'hosted-browser-20260922', apiVersion: 1, capabilities: ['frameworks'] },
}, files: { 'index.cjs': `module.exports=()=>({frameworks:[{name:'route',languages:['typescript'],detect:()=>true,resolve:()=>null,
extract(file){${broken ? "throw Error('Rejected browser update');" : ''} return {nodes:[{id:'plugin:hosted-browser-20260922:'+file,kind:'route',name:'/browser-${version}',qualifiedName:file+'::browser',filePath:file,language:'typescript',startLine:1,endLine:1,startColumn:0,endColumn:0,updatedAt:0}],references:[]}}}]});` } }));
}
function routes(root) {
const file = path.join(root, '.codegraph/codegraph.db');
if (!fs.existsSync(file)) return [];
const db = new DatabaseSync(file, { readOnly: true });
try { return db.prepare("SELECT name FROM nodes WHERE kind='route' ORDER BY name").all().map(n => n.name); } finally { db.close(); }
}
(async () => {
const temp = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-browser-recovery-'));
const roots = ['one', 'two'].map(n => path.join(temp, n));
roots.forEach(r => { fs.mkdirSync(r); fs.writeFileSync(path.join(r, 'app.ts'), 'export function main() {}'); });
let server, bridge, browser, attacker, debugPage, debugSnapshot, https;
try {
let origin = process.env.HOSTED_REGISTRY;
assert.match(origin || '', /^https:\/\/[a-z0-9.-]+\.workers\.dev$/);
assert.equal((await(await fetch(origin+'/api/extensions/hosted-browser-20260922')).json()).length,0,'Fixture already exists; use a fresh isolated target or rename this owned fixture');
if (process.env.REGISTRY_TEST_HTTPS === '1') { https = await require('./https-marketplace.cjs').httpsMarketplace(server.port, out); origin = https.origin; }
bridge = await startExtensionBridge(roots, origin);
const token = new URLSearchParams(new URL(bridge.connectionUrl).hash.slice(1)).get('token');
const snapshot = async () => (await fetch(bridge.url + '/status', { headers: { Authorization: 'Bearer ' + token } })).json();
debugSnapshot = snapshot;
browser = await chromium.launch({ executablePath: process.env.CHROME_PATH || '/opt/google/chrome/chrome', headless: true, args: ['--no-sandbox'] });
const context = await browser.newContext({ viewport: { width: 1440, height: 1000 } });
context.setDefaultTimeout(30000);
let lastPublication=0;
async function publicationSlot(route){await new Promise(r=>setTimeout(r,Math.max(0,lastPublication+7500-Date.now())));lastPublication=Date.now();await route.continue();}
await context.route('**/api/publish',publicationSlot);
context.setDefaultNavigationTimeout(20000);
const page = await context.newPage();
debugPage = page;
const pageErrors = []; page.on('pageerror', e => pageErrors.push(e.message));
let releaseCatalog, firstCatalog = true;
await page.route('**/api/extensions', async route => {
if (firstCatalog) { firstCatalog = false; await new Promise(resolve => { releaseCatalog = resolve; }); }
await route.continue();
});
await page.goto(bridge.connectionUrl, { waitUntil: 'domcontentloaded' });
if (origin.startsWith('https:')) assert.equal(await page.evaluate(() => isSecureContext), true);
// Reproduce slow native file reads: metadata must never erase typed fields.
await page.evaluate(() => { const original=File.prototype.text; File.prototype.text=async function(){await new Promise(resolve=>setTimeout(resolve,500));return original.call(this);}; });
console.log('Opened marketplace');
await page.getByRole('link', { name: 'Publish an extension' }).click();
async function publish(version, broken = false) {
console.log('Publishing', version);
if (new URL(page.url()).pathname !== '/publish') await page.getByRole('link', { name: 'Publish an extension' }).click();
await page.locator('#artifact').setInputFiles({ name: 'example.cgext', mimeType: 'application/json', buffer: artifact(version, broken) });
await page.locator('#name').fill('Browser example');
await page.locator('#publisher').fill('Recovery publisher');
await page.locator('#description').fill('A second framework used for end-to-end validation.');
await page.locator('#source').fill('https://example.com/recovery-source');
await page.locator('#readme').fill('Validation-only extension. Adds one explicit route to each TypeScript file.');
await page.locator('#package-summary').filter({ hasText: 'v'+version+' ·' }).waitFor();
if (releaseCatalog) {
const response = page.waitForResponse(r=>r.url().endsWith('/api/extensions'));
releaseCatalog(); releaseCatalog = undefined; await response;
await page.waitForTimeout(200);
assert.equal(await page.locator('#artifact').evaluate(input=>input.files[0]?.name),'example.cgext');
checks.push('late catalog response preserves the entered publisher form and package');
}
assert.equal(await page.locator('#description').inputValue(), 'A second framework used for end-to-end validation.');
assert.equal(await page.locator('#source').inputValue(), 'https://example.com/recovery-source');
await page.getByRole('button', { name: 'Publish release' }).click();
console.log('Submitted', version);
await page.waitForURL('**/extensions/hosted-browser-20260922');
await page.getByText(version, { exact: true }).waitFor();
}
await publish('1.0.0'); checks.push('real browser signed publisher upload'); checks.push('slow package metadata preserves typed publisher fields');
const first = (await (await fetch(origin + '/api/extensions')).json()).find(x=>x.id==='hosted-browser-20260922');
assert.equal(first.official, false);
// A separate browser has a separate signing identity and cannot claim this id.
const otherContext = await browser.newContext();
otherContext.setDefaultTimeout(30000);
await otherContext.route('**/api/publish',publicationSlot);
const other = await otherContext.newPage();
await other.goto(origin + '/publish');
await other.locator('#artifact').setInputFiles({ name: 'example.cgext', mimeType: 'application/json', buffer: artifact('9.0.0') });
for (const [id, value] of Object.entries({ name: 'Attempted takeover', publisher: 'Other publisher', description: 'Test', source: 'https://example.com/other', readme: 'Test' })) await other.locator('#' + id).fill(value);
await other.getByRole('button', { name: 'Publish release' }).click();
await other.getByText('This extension id belongs to another publisher', { exact: true }).waitFor();
checks.push('browser publisher ownership rejection');
// Send the real form submission to the real API with a corrupted signature.
await other.route('**/api/publish', async route => {
const body = route.request().postDataJSON(); body.signature = 'invalid';
await route.continue({ postData: JSON.stringify(body) });
});
await other.getByRole('button', { name: 'Publish release' }).click();
await other.locator('#publish-result').filter({ hasText: /signature/i }).waitFor();
await other.unroute('**/api/publish');
checks.push('browser invalid-signature failure state');
const malformed = JSON.parse(artifact('9.0.0')); malformed.format = 'invalid-format';
await other.locator('#artifact').setInputFiles({ name: 'invalid.cgext', mimeType: 'application/json', buffer: Buffer.from(JSON.stringify(malformed)) });
await other.locator('#description').fill('Invalid package validation');
await other.locator('#source').fill('https://example.com/invalid');
await other.getByRole('button', { name: 'Publish release' }).click();
await other.locator('#publish-result').filter({ hasText: /package/i }).waitFor();
assert.equal((await (await fetch(origin + '/api/extensions/hosted-browser-20260922')).json()).length, 1);
await otherContext.close(); checks.push('browser malformed-package rejection without publication');
await page.getByRole('link', { name: 'Marketplace', exact: true }).first().click();
await page.getByRole('link', {name:'Browser example',exact:true}).click();
const popupPromise = page.waitForEvent('popup');
await page.locator('#connect').click();
const popup = await popupPromise;
await popup.getByRole('button', { name: 'Allow connection' }).click();
await page.getByText('CodeGraph connected', { exact: true }).waitFor();
await page.locator('#project').selectOption('1');
let completedJob = 0;
await page.getByRole('button', { name: 'Install extension' }).click();
async function settle(expected) {
await page.waitForFunction(previous => state.snapshot && !state.snapshot.busy && state.snapshot.jobId > previous, completedJob);
const current = await snapshot();
completedJob = current.jobId;
console.log('Companion result', JSON.stringify({ progress: current.progress, error: current.error, jobId: current.jobId }));
assert.ok(!current.error, current.error);
await page.getByText(expected, { exact: true }).first().waitFor({ timeout: 60000 });
}
await settle('Extension activated and graph refreshed');
assert.deepEqual(routes(roots[1]), ['/browser-1.0.0']); assert.deepEqual(routes(roots[0]), []);
checks.push('one-click selected-project install verified in SQLite');
await page.screenshot({ path: path.join(out, 'desktop-installed.png'), fullPage: true });
// Real same-origin message from an iframe: right origin, wrong source window.
const before = (await snapshot()).jobId;
await page.evaluate(() => {
window.__recoveryPopup = state.popup;
const iframe = document.createElement('iframe'); iframe.name = 'wrong-source'; document.body.append(iframe);
});
await page.frame({ name: 'wrong-source' }).evaluate(() => parent.__recoveryPopup.postMessage({ channel: 'codegraph-extensions-v1', type: 'command', id: 'wrong-window', command: { action: 'remove', id: 'hosted-browser-20260922', project: '1' } }, '*'));
await page.waitForTimeout(300); assert.equal((await snapshot()).jobId, before);
await page.locator('iframe[name="wrong-source"]').evaluate(node => node.remove());
checks.push('real postMessage wrong-window command ignored');
await publish('2.0.0', true);
await page.getByRole('button', { name: 'Update to 2.0.0' }).click();
await page.getByText(/Extension activation failed/).first().waitFor({ timeout: 60000 });
completedJob = (await snapshot()).jobId;
assert.deepEqual(routes(roots[1]), ['/browser-1.0.0']);
assert.equal((await snapshot()).projects[1].extensions[0].version, '1.0.0');
checks.push('failed browser update preserves working version and graph');
await publish('3.0.0');
await page.getByRole('button', { name: 'Update to 3.0.0' }).click();
await settle('Extension activated and graph refreshed');
assert.deepEqual(routes(roots[1]), ['/browser-3.0.0']);
checks.push('browser update replaces stale graph contributions');
await page.getByRole('button', { name: 'Disable', exact: true }).click();
await page.getByRole('button', { name: 'Enable', exact: true }).waitFor({ timeout: 60000 });
assert.deepEqual(routes(roots[1]), []);
await page.getByRole('button', { name: 'Enable', exact: true }).click();
await page.getByRole('button', { name: 'Disable', exact: true }).waitFor({ timeout: 60000 });
assert.deepEqual(routes(roots[1]), ['/browser-3.0.0']);
await page.getByRole('button', { name: 'Remove', exact: true }).click();
await page.getByRole('button', { name: 'Install extension' }).waitFor({ timeout: 60000 });
await page.getByText('Extension removed and graph refreshed', { exact: true }).first().waitFor();
assert.deepEqual(routes(roots[1]), []); assert.deepEqual(routes(roots[0]), []);
checks.push('browser disable/enable/remove verified in SQLite');
await page.setViewportSize({ width: 390, height: 844 });
await page.getByText('CodeGraph compatibility', { exact: true }).waitFor();
await page.getByText('3.0.0', { exact: true }).waitFor();
await page.screenshot({ path: path.join(out, 'mobile-detail.png'), fullPage: true });
assert.ok(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth));
checks.push('mobile detail fits viewport');
// Bootstrap a companion from a hostile origin, even with a valid test token:
// its real message origin must still be refused after the local allow click.
attacker = http.createServer((req, res) => { res.setHeader('Content-Type', 'text/html'); res.end('<button id="open">Open</button>'); });
await new Promise(resolve => attacker.listen(0, '127.0.0.1', resolve));
const evil = await context.newPage(); await evil.goto(`http://127.0.0.1:${attacker.address().port}`);
await evil.evaluate(({ url }) => { document.querySelector('#open').onclick = () => { window.target = window.open(url, '_blank'); }; }, { url: bridge.url + '/#token=' + token });
const badPopupPromise = evil.waitForEvent('popup'); await evil.locator('#open').click(); const badPopup = await badPopupPromise;
await badPopup.getByRole('button', { name: 'Allow connection' }).click();
const beforeOrigin = (await snapshot()).jobId;
await evil.evaluate(() => window.target.postMessage({ channel: 'codegraph-extensions-v1', type: 'command', id: 'wrong-origin', command: { action: 'enable', id: 'hosted-browser-20260922', project: '1' } }, '*'));
await evil.waitForTimeout(300); assert.equal((await snapshot()).jobId, beforeOrigin);
checks.push('real postMessage wrong-origin command ignored');
await popup.close();
await page.getByText('Reconnect CodeGraph', { exact: true }).waitFor();
checks.push('closed local companion expires the connection visibly');
await page.setViewportSize({ width: 1440, height: 1000 });
await page.getByRole('link', { name: 'Publish an extension' }).click();
await page.locator('#artifact').setInputFiles({ name: 'example.cgext', mimeType: 'application/json', buffer: artifact('4.0.0') });
for (const [id, value] of Object.entries({ name: 'Browser example', publisher: 'Recovery publisher', description: 'Outage check', source: 'https://example.com/source', readme: 'Outage check' })) await page.locator('#'+id).fill(value);
await page.locator('#package-summary').filter({ hasText: 'v4.0.0' }).waitFor();
await page.route('**/api/publish', route=>route.abort('connectionfailed'));
await page.getByRole('button', { name: 'Publish release' }).click();
await page.locator('#publish-result').filter({ hasText: /marketplace registry/i }).waitFor();
assert.equal(await page.getByRole('button', { name: 'Publish release' }).isEnabled(), true);
assert.deepEqual(routes(roots[1]), []);
checks.push('injected client transport outage shows actionable publisher failure (provider remains running) without changing local graph');
assert.deepEqual(pageErrors, []);
fs.writeFileSync(path.join(out, 'result.json'), JSON.stringify({ origin, browser: browser.version(), platform: process.platform, checks, pageErrors }, null, 2));
console.log(JSON.stringify({ checks, browser: browser.version(), platform: process.platform }));
} catch (error) {
await debugPage?.screenshot({ path: path.join(out, 'failure.png'), fullPage: true }).catch(() => {});
fs.writeFileSync(path.join(out, 'failure.json'), JSON.stringify({ checks, error: safeError(error), snapshot: await debugSnapshot?.() }, null, 2)); throw Error(safeError(error));
} finally {
await browser?.close(); await https?.close(); await bridge?.close(); await server?.close();
if (attacker) await new Promise(resolve => attacker.close(resolve));
fs.rmSync(temp, { recursive: true, force: true });
}
})().catch(error => { console.error(safeError(error)); if(error.cause) console.error(error.cause); process.exitCode = 1; });
@@ -0,0 +1,193 @@
// Build first; PLAYWRIGHT_MODULE=/absolute/path/to/playwright node scripts/validation/extensions-compatibility.cjs
const fs = require('node:fs'), os = require('node:os'), path = require('node:path');
const assert = require('node:assert/strict');
const { spawn } = require('node:child_process');
const { generateKeyPairSync, sign, randomUUID, createHash } = require('node:crypto');
const { chromium } = require(process.env.PLAYWRIGHT_MODULE || 'playwright');
const { createExtensionProject, CodeGraph } = require('../../dist');
const { packExtension } = require('../../dist/plugins/package');
const { startMarketplaceServer } = process.env.CLOUDFLARE_REGISTRY === '1' ? require('./cloudflare-registry.cjs') : require('../../dist/plugins/marketplace');
const { startExtensionBridge } = require('../../dist/plugins/bridge');
const repo = path.resolve(__dirname, '../..'), out = path.resolve(process.env.COMPAT_OUTPUT || path.join(repo, '.qa/recovery/compatibility'));
fs.mkdirSync(out, { recursive: true });
const lab = fs.mkdtempSync(path.join(os.tmpdir(), 'cg-compatible-'));
const author = path.join(lab, 'author'), checks = [], commands = [], releases = [];
const env = { ...process.env, CODEGRAPH_TELEMETRY: '0', CODEGRAPH_PARSE_WORKERS: '2', CODEGRAPH_RESOLVE_WORKERS: '2', CODEGRAPH_PARALLEL_RESOLVE_MIN: '0' };
Object.assign(process.env, env);
const roots = ['first-python-project', 'selected-python-project', 'headless-python-project'].map(n => path.join(lab, n));
for (const root of roots) {
fs.mkdirSync(root); fs.writeFileSync(path.join(root, 'checkout.events.yaml'), 'order.created: send_receipt\n');
fs.writeFileSync(path.join(root, 'handlers.py'), 'def send_receipt():\n return "sent"\n');
}
createExtensionProject(author, 'hosted-compatible-20260922');
const original = fs.readFileSync(path.join(author, 'index.cjs'), 'utf8');
const keys = generateKeyPairSync('ec', { namedCurve: 'prime256v1' });
let server, bridge, browser, page, registry, https;
let lastPublication=0;
async function publicationSlot(){await new Promise(r=>setTimeout(r,Math.max(0,lastPublication+7500-Date.now())));lastPublication=Date.now();}
async function publish(version, engines = '>=1.6.0 <2', id = 'hosted-compatible-20260922', broken = false) {
const pkg = JSON.parse(fs.readFileSync(path.join(author, 'package.json'), 'utf8'));
pkg.version = version; pkg.codegraph.id = id; pkg.codegraph.engines = engines;
fs.writeFileSync(path.join(author, 'package.json'), JSON.stringify(pkg));
fs.writeFileSync(path.join(author, 'index.cjs'), original.replace('Python event dispatch', 'Python event dispatch ' + version).replace('extract(file, source) {', broken ? "extract(file, source) { throw Error('Rejected compatible update');" : 'extract(file, source) {'));
const bytes = packExtension(author);
const payload = JSON.stringify({ name: id, description: 'Compatible generated Python event extension', publisher: 'Compatibility validation',
source: 'https://example.com/extension-source', readme: 'Generated author template; local release selection acceptance.', artifact: bytes.toString('base64'), timestamp: Date.now(), nonce: randomUUID() });
const body = { payload, publicKey: keys.publicKey.export({ format: 'jwk' }), signature: sign('sha256', Buffer.from(payload), { key: keys.privateKey, dsaEncoding: 'ieee-p1363' }).toString('base64') };
await publicationSlot();
const res = await fetch(registry + '/api/publish', { method: 'POST', body: JSON.stringify(body) });
assert.equal(res.status, 201, await res.clone().text());
releases.push({ id, version, engines, integrity: createHash('sha256').update(bytes).digest('hex') });
return { bytes, body };
}
async function graph(root) {
if (!CodeGraph.isInitialized(root)) return [];
const g = await CodeGraph.open(root);
try { return g.getNodesByKind('route').flatMap(n => g.getOutgoingEdges(n.id).filter(e => e.metadata?.synthesizedBy === 'hosted-compatible-20260922').map(e => ({ source: n.name, target: g.getNode(e.target)?.name, label: e.metadata.label }))); }
finally { g.close(); }
}
async function expectGraph(root, version) {
assert.deepEqual(await graph(root), [{ source: 'event:order.created', target: 'send_receipt', label: 'Python event dispatch ' + version }]);
}
async function cli(args, expected = 0) {
const command = [path.join(repo, 'dist/bin/codegraph.js'), 'extensions', ...args];
const start = Date.now();
const result = await new Promise((resolve, reject) => {
const child = spawn(process.execPath, command, { env, cwd: lab, timeout: 120000 });
let stdout = '', stderr = ''; child.stdout.on('data', b => stdout += b); child.stderr.on('data', b => stderr += b);
child.on('error', reject); child.on('close', exit => resolve({ exit, stdout, stderr }));
});
commands.push({ command: [process.execPath, ...command], exit: result.exit, seconds: (Date.now() - start) / 1000 });
fs.writeFileSync(path.join(out, 'commands.json'), JSON.stringify(commands, null, 2));
fs.writeFileSync(path.join(out, `command-${commands.length}.log`), result.stdout + result.stderr);
assert.equal(result.exit, expected, result.stderr); return result;
}
(async () => {
try {
registry = process.env.HOSTED_REGISTRY;
assert.match(registry || '', /^https:\/\/[a-z0-9.-]+\.workers\.dev$/);
assert.equal((await (await fetch(registry+'/api/extensions/hosted-compatible-20260922')).json()).length,0,'Use a fresh isolated target or explicitly rename this owned fixture before another run');
await cli(['test', author]);
await cli(['pack', author, '--out', path.join(lab,'starter.cgext')]);
if (process.env.REGISTRY_TEST_HTTPS === '1') { https = await require('./https-marketplace.cjs').httpsMarketplace(server.port, out); registry = https.origin; }
// Publication order intentionally differs from semantic order; previews and
// a newer incompatible release must never displace the compatible stable one.
const pinned = await publish('1.10.0'); await publish('1.9.0'); await publish('0.5.0');
await publish('20.0.0-beta.1'); await publish('9.0.0', '>=9'); await publish('1.0.0', '>=9', 'hosted-unavailable-20260922');
await publicationSlot();
const duplicate = await fetch(registry + '/api/publish', { method: 'POST', body: JSON.stringify(pinned.body) });
assert.equal(duplicate.status, 400);
const all = await (await fetch(registry + '/api/extensions/hosted-compatible-20260922')).json();
assert.deepEqual(all.map(r => r.version), ['9.0.0', '1.10.0', '1.9.0', '0.5.0', '20.0.0-beta.1']);
assert.equal(all[0].apiVersion, 1); checks.push('signed immutable versions; semantic catalog order independent of publication order');
bridge = await startExtensionBridge(roots.slice(0, 2), registry);
browser = await chromium.launch({ executablePath: process.env.CHROME_PATH || '/opt/google/chrome/chrome', headless: true, args: ['--no-sandbox'] });
page = await browser.newPage({ viewport: { width: 1440, height: 1000 } });
page.setDefaultTimeout(60000);
const errors = []; page.on('pageerror', e => errors.push(e.message));
await page.goto(bridge.connectionUrl);
if (registry.startsWith('https:')) assert.equal(await page.evaluate(() => isSecureContext), true);
const popupWait = page.waitForEvent('popup'); await page.locator('#connect').click(); const popup = await popupWait;
await popup.getByRole('button', { name: 'Allow connection' }).click();
await page.getByText('CodeGraph connected', { exact: true }).waitFor();
await page.locator('#project').selectOption('1');
await page.locator('.compatibility').filter({ hasText: 'Selected 1.10.0' }).waitFor();
await page.getByRole('link', { name: 'hosted-compatible-20260922', exact: true }).click();
await page.locator('.compatibility').filter({ hasText: 'selected-python-project' }).waitFor();
await page.screenshot({ path: path.join(out, 'desktop-selected.png'), fullPage: true });
// Exactly one Install after connection; wait for the real companion job.
await page.getByRole('button', { name: 'Install extension' }).click();
await page.waitForFunction(() => state.snapshot?.jobId === 1 && !state.snapshot.busy);
assert.equal(await page.evaluate(() => state.snapshot.error), undefined);
await expectGraph(roots[1], '1.10.0'); assert.deepEqual(await graph(roots[0]), []);
checks.push('one browser Install selects 1.10.0 over incompatible 9.0.0 and preview; actual Python graph refreshed only in chosen destination');
// Hold actual bridge resolution to inspect the transient destination state.
await page.evaluate(() => {
const originalRpc = rpc;
const gate = new Promise(resolve => window.releaseSelection = resolve);
rpc = (type, value) => type === 'command' && value?.action === 'resolve' ? gate.then(() => originalRpc(type, value)) : originalRpc(type, value);
window.pendingSelection = refreshSelections().finally(() => { rpc = originalRpc; });
});
await page.screenshot({ path: path.join(out, 'metadata-pending.png'), fullPage: true });
assert.equal(await page.locator('[data-installed-version]').innerText(), '1.10.0');
assert.equal(await page.locator('[data-selected-version]').innerText(), 'Checking compatibility…');
assert.equal(await page.locator('a[href^="/api/download/"]').count(), 0);
await page.evaluate(async () => { releaseSelection(); await pendingSelection; });
assert.equal(await page.locator('[data-selected-version]').innerText(), '1.10.0');
assert.equal(await page.locator('[data-installed-version]').innerText(), '1.10.0');
checks.push('pending compatibility refresh never shows incompatible catalog version as selected; installed and selected versions remain distinct');
await page.screenshot({ path: path.join(out, 'desktop-installed.png'), fullPage: true });
const config = fs.readFileSync(path.join(roots[1], 'codegraph.json'), 'utf8');
const noChoice = await page.evaluate(async () => {
try { await rpc('command', { action: 'resolve', id: 'hosted-unavailable-20260922', project: '1' }); return ''; } catch (e) { return e.message; }
});
assert.match(noChoice, /No compatible stable release/);
await page.evaluate(() => rpc('command', { action: 'install', id: 'hosted-unavailable-20260922', project: '1' }));
await page.waitForFunction(() => state.snapshot?.jobId === 2 && !state.snapshot.busy);
assert.match(await page.evaluate(() => state.snapshot.error), /No compatible stable release/);
assert.equal(fs.readFileSync(path.join(roots[1], 'codegraph.json'), 'utf8'), config); await expectGraph(roots[1], '1.10.0');
await page.evaluate(() => navigate('/extensions/hosted-unavailable-20260922'));
await page.locator('.compatibility').filter({ hasText: 'No compatible stable release' }).waitFor();
assert.equal(await page.getByRole('button', { name: 'Install extension' }).isDisabled(), true);
checks.push('no-compatible browser selection/command fails usefully and preserves existing config/graph');
// Independent CLI destination resolves exactly the same release.
await cli(['install', 'hosted-compatible-20260922', '--registry', registry, '--path', roots[2]]); await expectGraph(roots[2], '1.10.0');
const headlessConfig = fs.readFileSync(path.join(roots[2], 'codegraph.json'), 'utf8');
const exactFailure = await cli(['install', 'hosted-compatible-20260922', '--registry', registry, '--version', '9.0.0', '--path', roots[2]], 1);
assert.match(exactFailure.stderr, /No compatible exact release 9.0.0/);
await cli(['update', 'hosted-unavailable-20260922', '--registry', registry, '--path', roots[2]], 1);
const none = await cli(['install', 'hosted-unavailable-20260922', '--registry', registry, '--path', roots[2]], 1);
assert.match(none.stderr, /No compatible stable release/);
assert.equal(fs.readFileSync(path.join(roots[2], 'codegraph.json'), 'utf8'), headlessConfig); await expectGraph(roots[2], '1.10.0');
checks.push('headless automatic selection agrees; exact incompatible pin/no-compatible/missing update fail without mutation');
await cli(['install', 'hosted-compatible-20260922', '--registry', registry, '--version', '20.0.0-beta.1', '--path', roots[2]]);
await expectGraph(roots[2], '20.0.0-beta.1');
const previewConfig = fs.readFileSync(path.join(roots[2], 'codegraph.json'), 'utf8');
const downgrade = await cli(['update', 'hosted-compatible-20260922', '--registry', registry, '--path', roots[2]], 1);
assert.match(downgrade.stderr, /would downgrade/);
assert.equal(fs.readFileSync(path.join(roots[2], 'codegraph.json'), 'utf8'), previewConfig); await expectGraph(roots[2], '20.0.0-beta.1');
await cli(['install', 'hosted-compatible-20260922', '--registry', registry, '--version', '1.9.0', '--path', roots[2]]); await expectGraph(roots[2], '1.9.0');
checks.push('prerelease requires explicit exact pin; automatic update refuses downgrade; explicit lower pin remains exact');
await publish('2.0.0', '>=1.6.0 <2', 'hosted-compatible-20260922', true);
await page.reload(); const reconnect = page.waitForEvent('popup');
// A named existing popup may be reused: reconnect using a fresh window.
await popup.close(); await page.locator('#connect').click(); const second = await reconnect;
await second.getByRole('button', { name: 'Allow connection' }).click();
await page.getByText('CodeGraph connected', { exact: true }).waitFor();
await page.evaluate(() => { state.project = '1'; navigate('/extensions/hosted-compatible-20260922'); return refreshSelections(); });
await page.getByRole('button', { name: 'Update to 2.0.0' }).click();
await page.waitForFunction(() => state.snapshot?.jobId === 3 && !state.snapshot.busy);
assert.match(await page.evaluate(() => state.snapshot.error), /Extension activation failed/);
await expectGraph(roots[1], '1.10.0'); assert.equal(fs.readFileSync(path.join(roots[1], 'codegraph.json'), 'utf8'), config);
checks.push('compatible but broken update retains previous version and graph');
await publish('3.0.0');
await page.evaluate(() => refresh());
await page.getByRole('button', { name: 'Update to 3.0.0' }).click();
await page.waitForFunction(() => state.snapshot?.jobId === 4 && !state.snapshot.busy);
assert.equal(await page.evaluate(() => state.snapshot.error), undefined); await expectGraph(roots[1], '3.0.0');
await cli(['update', 'hosted-compatible-20260922', '--registry', registry, '--path', roots[2]]); await expectGraph(roots[2], '3.0.0');
checks.push('browser and headless update to highest compatible stable; stale graph labels removed');
// Exact URL and file install remain independent of automatic registry selection.
await cli(['install', registry + '/api/download/hosted-compatible-20260922/1.9.0', '--path', roots[2]]); await expectGraph(roots[2], '1.9.0');
const file = path.join(lab, 'pinned.cgext'); fs.writeFileSync(file, pinned.bytes);
await cli(['install', file, '--path', roots[2]]); await expectGraph(roots[2], '1.10.0');
await publish('1.10.0+fixture.1');
await cli(['install', 'hosted-compatible-20260922', '--registry', registry, '--version', '1.10.0+fixture.1', '--path', roots[2]]);
await expectGraph(roots[2], '1.10.0+fixture.1');
checks.push('exact artifact URL/file semantics and build-metadata pin identity preserved');
await page.setViewportSize({ width: 390, height: 844 });
await page.locator('.compatibility').filter({ hasText: 'Selected 3.0.0' }).waitFor();
assert.ok(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth));
await page.screenshot({ path: path.join(out, 'mobile-selected.png'), fullPage: true });
await page.getByRole('button', { name: 'Remove', exact: true }).click();
await page.waitForFunction(() => state.snapshot?.jobId === 5 && !state.snapshot.busy);
await cli(['remove', 'hosted-compatible-20260922', '--path', roots[2]]);
assert.deepEqual(await graph(roots[1]), []); assert.deepEqual(await graph(roots[2]), []);
assert.deepEqual(errors, []); checks.push('removal cleans contributions; desktop/mobile display actual destination compatibility; no page errors');
fs.writeFileSync(path.join(out, 'result.json'), JSON.stringify({ registry, checks, releases, commands, engineVersion: require('../../package.json').version, platform: process.platform, browser: browser.version() }, null, 2));
console.log(JSON.stringify({ checks, commands: commands.length }));
} catch (error) {
await page?.screenshot({ path: path.join(out, 'failure.png'), fullPage: true }).catch(() => {});
fs.writeFileSync(path.join(out, 'failure.json'), JSON.stringify({ checks, error: String(error.stack).replace(/token=[a-f0-9]+/g, 'token=[redacted]') }, null, 2)); throw error;
} finally { await browser?.close(); await https?.close(); await bridge?.close(); await server?.close(); fs.rmSync(lab, { recursive: true, force: true }); }
})().catch(error => { console.error(String(error.stack).replace(/token=[a-f0-9]+/g, 'token=[redacted]')); if(error.cause) console.error(error.cause); process.exitCode = 1; });
@@ -0,0 +1,36 @@
// Actual deployed Worker HTTPS -> browser -> compiled installer -> pinned Drupal corpus.
// Uses a previously reviewed/imported immutable artifact. Never mutates remote storage.
const fs=require('node:fs'),path=require('node:path'),os=require('node:os'),assert=require('node:assert/strict'),cp=require('node:child_process'),crypto=require('node:crypto');
const {DatabaseSync}=require('node:sqlite');
const {chromium}=require(process.env.PLAYWRIGHT_MODULE||'playwright');
const {CodeGraph}=require('../../dist');
const {ExtensionManager}=require('../../dist/plugins/manager');
const {startExtensionBridge}=require('../../dist/plugins/bridge');
Object.assign(process.env,{CODEGRAPH_TELEMETRY:'0',CODEGRAPH_PARSE_WORKERS:'2',CODEGRAPH_RESOLVE_WORKERS:'0'});
const root=path.resolve(__dirname,'../..'),out=path.resolve(process.env.OFFICIAL_BROWSER_OUTPUT||'.qa/hosted/drupal-browser');fs.mkdirSync(out,{recursive:true});
const lab=fs.mkdtempSync(path.join(os.tmpdir(),'cg-official-browser-')),corpus=path.resolve(process.env.PATHAUTO_CORPUS||'../validation/pathauto'),pin='b97aadf47a37cff25f7d6105c3dade6778fccb47';
const project=path.join(lab,'pathauto'),other=path.join(lab,'untouched'),state=path.join(lab,'registry'),artifact=path.join(root,'dist/extensions/drupal.cgext'),bytes=fs.readFileSync(artifact),checks=[],commands=[];
fs.mkdirSync(project);fs.mkdirSync(other);fs.writeFileSync(path.join(other,'example.php'),'<?php function untouched() {}');
cp.execFileSync('tar',['-x','-C',project],{input:cp.execFileSync('git',['-C',corpus,'archive',pin],{maxBuffer:64*1024*1024})});
const extensionVersion=JSON.parse(bytes).package.version;
const hash=b=>crypto.createHash('sha256').update(b).digest('hex');
function snapshot(){const db=new DatabaseSync(path.join(project,'.codegraph/codegraph.db'),{readOnly:true});try{const nodes=db.prepare('SELECT * FROM nodes ORDER BY id').all().map(({updated_at,...n})=>n),edges=db.prepare('SELECT source,target,kind,metadata,line,col,provenance FROM edges ORDER BY source,target,kind,line,col,metadata').all();return {nodes,edges,pluginEdges:edges.filter(e=>JSON.parse(e.metadata||'{}').synthesizedBy==='drupal'),hash:hash(JSON.stringify({nodes,edges})),config:fs.existsSync(path.join(project,'codegraph.json'))?fs.readFileSync(path.join(project,'codegraph.json'),'utf8'):null};}finally{db.close();}}
function verify(data){const definitions=[['/admin/config/search/path/settings','pathauto.routing.yml','buildForm','src/Form/PathautoSettingsForm.php','Drupal route handler'],['/admin/config/search/path/update_bulk','pathauto.routing.yml','buildForm','src/Form/PathautoBulkUpdateForm.php','Drupal route handler'],['getPunctuationCharacters','src/AliasCleaner.php','pathautoPunctuationCharsAlter','tests/modules/pathauto_custom_punctuation_test/src/Hook/PathautoCustomPunctuationTestHooks.php','Drupal hook pathauto_punctuation_chars_alter'],['PathautoGenerator','src/PathautoGenerator.php','AliasCleaner','src/AliasCleaner.php','Drupal service injection']];for(const [from,file,to,target,label]of definitions){const sources=new Set(data.nodes.filter(n=>n.name===from&&n.file_path===file).map(n=>n.id)),targets=new Set(data.nodes.filter(n=>n.name===to&&n.file_path===target).map(n=>n.id));assert.ok(data.pluginEdges.some(e=>sources.has(e.source)&&targets.has(e.target)&&JSON.parse(e.metadata).label===label),'Missing '+label+': '+from);}return definitions;}
function pass(name){checks.push(name);fs.writeFileSync(path.join(out,'progress.json'),JSON.stringify({checks,commands},null,2));console.log('PASS',name);}
async function cli(args){const command=[path.join(root,'marketplace/cloudflare/official-cli.mjs'),...args];const r=await new Promise((resolve,reject)=>{const c=cp.spawn(process.execPath,command,{timeout:60000});let log='';c.stdout.on('data',b=>log+=b);c.stderr.on('data',b=>log+=b);c.on('error',reject);c.on('close',exit=>resolve({exit,log}));});const log='operator-'+(commands.length+1)+'.log';fs.writeFileSync(path.join(out,log),r.log);commands.push({command:[process.execPath,...command],exit:r.exit,log,sha256:hash(r.log)});assert.equal(r.exit,0,r.log);return r.log;}
let server,bridge,browser,page;
(async()=>{try{
const origin=process.env.HOSTED_REGISTRY;assert.ok(/^https:\/\/[-a-z0-9.]+\.workers\.dev$/.test(origin),'Explicit workers.dev origin required');
const catalog=await(await fetch(origin+'/api/extensions')).json(),listing=catalog.find(x=>x.id==='drupal');assert.equal(listing.official,true);assert.equal(listing.publisherId,'codegraph');assert.equal(listing.integrity,hash(bytes));const downloaded=Buffer.from(await(await fetch(origin+'/api/download/drupal/'+extensionVersion)).arrayBuffer());assert.deepEqual(downloaded,bytes);pass('actual hosted catalog and immutable Drupal bytes match reviewed official policy');
const g=await CodeGraph.init(project);try{const r=await g.indexAll();assert.equal(r.filesErrored,0);}finally{g.close();}assert.equal(snapshot().pluginEdges.length,0);
bridge=await startExtensionBridge([other,project],origin);browser=await chromium.launch({executablePath:process.env.CHROME_PATH||'/opt/google/chrome/chrome',headless:true,args:['--no-sandbox']});page=await browser.newPage({viewport:{width:1440,height:1000}});page.setDefaultTimeout(60000);let popups=0;page.on('popup',()=>popups++);const pageErrors=[];page.on('pageerror',e=>pageErrors.push(e.message));
await page.goto(bridge.connectionUrl);assert.equal(await page.evaluate(()=>isSecureContext),true);await page.getByRole('button',{name:'Official',exact:true}).click();await page.locator('.extension-card .official').waitFor();assert.equal(await page.locator('.extension-card').count(),1);assert.match(await page.locator('.extension-card .byline').innerText(),/CodeGraph.*OFFICIAL/s);pass('official catalog filter displays trusted CodeGraph Drupal identity');
const popupReady=page.waitForEvent('popup');await page.locator('#connect').click();const popup=await popupReady;await popup.getByRole('button',{name:'Allow connection'}).click();await page.getByText('CodeGraph connected',{exact:true}).waitFor();await page.locator('#project').selectOption('1');await page.getByRole('link',{name:'Drupal',exact:true}).click();await page.locator('.compatibility').filter({hasText:'Selected '+extensionVersion}).waitFor();assert.equal(await page.locator('.metadata dd.integrity').first().innerText(),'codegraph');await page.getByRole('button',{name:'Install extension'}).click();await page.waitForFunction(()=>state.snapshot?.jobId===1&&!state.snapshot.busy);assert.equal(await page.evaluate(()=>state.snapshot.error),undefined);assert.equal(popups,1);const installed=snapshot(),flows=verify(installed);assert.ok(!CodeGraph.isInitialized(other));pass('one connection and one Install refresh only selected pinned Drupal project; four real route hook and DI edges verified');
fs.writeFileSync(path.join(out,'graph-proof.json'),JSON.stringify({corpus:'pathauto',revision:pin,artifactSHA:hash(bytes),nodes:installed.nodes.length,edges:installed.edges.length,pluginEdges:installed.pluginEdges.length,hash:installed.hash,expected:flows},null,2));await page.screenshot({path:path.join(out,'desktop-installed.png'),fullPage:true});
const manager=new ExtensionManager(project),realFetch=global.fetch;let tampered=false;global.fetch=async(...args)=>{const r=await realFetch(...args);if(String(args[0]).includes('/api/download/drupal/')){tampered=true;return new Response(Buffer.concat([Buffer.from(await r.arrayBuffer()),Buffer.from(' ')]),{status:r.status,headers:r.headers});}return r;};try{await assert.rejects(()=>manager.installFromRegistry({registry:origin,id:'drupal',version:extensionVersion,replaces:['drupal']}),/integrity/);}finally{global.fetch=realFetch;}assert.equal(tampered,true);assert.equal(snapshot().hash,installed.hash);assert.equal(snapshot().config,installed.config);pass('test-owned transport corruption after real HTTPS download is rejected; hosted immutable object untouched');
const incompatible=JSON.parse(bytes);incompatible.package.codegraph.engines='>=9';await assert.rejects(()=>manager.install({bytes:Buffer.from(JSON.stringify(incompatible)),replaces:['drupal']}),/requires/);await assert.rejects(()=>manager.install({bytes:Buffer.from('{}'),replaces:['drupal']}));assert.equal(snapshot().hash,installed.hash);assert.equal(snapshot().config,installed.config);pass('incompatible and malformed installs preserve previously working Drupal graph');
await page.getByRole('button',{name:'Disable',exact:true}).click();await page.getByRole('button',{name:'Enable',exact:true}).waitFor();assert.equal(snapshot().pluginEdges.length,0);pass('browser disable removes actual extension contributions');
await page.getByRole('button',{name:'Enable',exact:true}).click();await page.getByRole('button',{name:'Disable',exact:true}).waitFor();verify(snapshot());await page.setViewportSize({width:390,height:844});await page.screenshot({path:path.join(out,'mobile-official.png'),fullPage:true});pass('browser enable restores expected graph and mobile official details');
await page.getByRole('button',{name:'Remove',exact:true}).click();await page.getByText('Extension removed and graph refreshed',{exact:true}).first().waitFor();assert.equal(snapshot().pluginEdges.length,0);assert.equal(new ExtensionManager(project).list().length,0);assert.ok(!CodeGraph.isInitialized(other));assert.deepEqual(pageErrors,[]);pass('browser removal clears extension config and SQLite contributions; no page errors');
fs.writeFileSync(path.join(out,'result.json'),JSON.stringify({revision:cp.execFileSync('git',['rev-parse','HEAD'],{encoding:'utf8'}).trim(),dirty:!!cp.execFileSync('git',['status','--porcelain'],{encoding:'utf8'}).trim(),platform:process.platform,origin,browser:browser.version(),corpus:{name:'pathauto',revision:pin},checks,commands,success:true},null,2));
}catch(error){if(page)await page.screenshot({path:path.join(out,'failure.png'),fullPage:true}).catch(()=>{});fs.writeFileSync(path.join(out,'failure.json'),JSON.stringify({checks,commands,error:String(error.stack)},null,2));throw error;}finally{await browser?.close();await bridge?.close();await server?.close();fs.rmSync(lab,{recursive:true,force:true});}})().catch(e=>{console.error(e);process.exitCode=1;});
@@ -0,0 +1,28 @@
// Controlled writes only to a dedicated preview with a bounded publication window.
const fs=require('node:fs'),path=require('node:path'),assert=require('node:assert/strict');
const {generateKeyPairSync,sign,randomUUID,createHash}=require('node:crypto');
const origin=process.env.HOSTED_REGISTRY,out=path.resolve(process.env.HOSTED_PACKAGE_OUTPUT||'.qa/hosted/packages');
assert.match(origin||'',/^https:\/\/[a-z0-9.-]+\.workers\.dev$/);fs.mkdirSync(out,{recursive:true});
const suffix=Date.now().toString(36),keys=generateKeyPairSync('ec',{namedCurve:'prime256v1'}),checks=[],requests=[];
const hash=b=>createHash('sha256').update(b).digest('hex');
function artifact(id,version='1.0.0',size){const p={format:'codegraph-extension-1',package:{name:'@preview/'+id,version,main:'index.cjs',codegraph:{id,apiVersion:1,capabilities:['frameworks']}},files:{'index.cjs':'module.exports=()=>({frameworks:[]});'}};if(size){p.files['padding.txt']='';p.files['padding.txt']='x'.repeat(size-Buffer.byteLength(JSON.stringify(p)));}return Buffer.from(JSON.stringify(p));}
function signed(bytes,key=keys,extra={}){const payload=JSON.stringify({name:'Hosted acceptance fixture',description:'Disposable preview contract check',publisher:'Preview validation',source:'https://github.com/colbymchenry/codegraph',readme:'Test fixture. Not a recommended extension.',artifact:bytes.toString('base64'),timestamp:Date.now(),nonce:randomUUID(),...extra});return{payload,publicKey:key.publicKey.export({format:'jwk'}),signature:sign('sha256',Buffer.from(payload),{key:key.privateKey,dsaEncoding:'ieee-p1363'}).toString('base64')};}
let last=0;
async function post(body,expected,headers={}){await new Promise(r=>setTimeout(r,Math.max(0,last+7500-Date.now())));last=Date.now();const start=new Date().toISOString(),t=performance.now(),r=await fetch(origin+'/api/publish',{method:'POST',headers,body:JSON.stringify(body)}),data=await r.json();requests.push({start,path:'/api/publish',status:r.status,wallMs:performance.now()-t,expected,result:data});fs.writeFileSync(path.join(out,'progress.json'),JSON.stringify({origin,checks,requests},null,2));assert.equal(r.status,expected,JSON.stringify(data));return data;}
const passed=x=>{checks.push(x);console.log('PASS',x);};
(async()=>{
assert.equal((await(await fetch(origin+'/api/health')).json()).publishing,true);
const id='hosted-max-'+suffix,large=artifact(id,'1.0.0',8*1024*1024);assert.equal(large.length,8*1024*1024);const published=await post(signed(large),201);assert.equal(published.integrity,hash(large));
for(let i=0;i<3;i++){const start=new Date().toISOString(),t=performance.now(),r=await fetch(origin+'/api/download/'+id+'/1.0.0?sample='+i),bytes=Buffer.from(await r.arrayBuffer());assert.equal(r.status,200);assert.equal(bytes.length,large.length);assert.equal(hash(bytes),hash(large));requests.push({start,path:'/api/download/'+id+'/1.0.0?sample='+i,status:r.status,wallMs:performance.now()-t,bytes:bytes.length,sha256:hash(bytes),cacheControl:r.headers.get('cache-control')});}passed('full 8 MiB signed upload and three byte-identical provider downloads');
await post(signed(Buffer.concat([large,Buffer.from(' ')])),400);passed('8 MiB plus one byte rejected by trusted package validator');
await post(signed(artifact('spoof-'+suffix),keys,{official:true,publisherId:'codegraph'}),400);passed('signed community official/publisher spoof rejected');
await post({...signed(artifact('signature-'+suffix)),signature:'AAAA'},400);await post(signed(Buffer.from('{}')),400);passed('invalid signature and malformed package rejected');
await post(signed(artifact(id,'2.0.0'),generateKeyPairSync('ec',{namedCurve:'prime256v1'})),400);await post(signed(artifact(id,'1.0.0')),400);passed('ownership and immutable version reject without replacing bytes');
await post(signed(artifact('origin-'+suffix)),403,{Origin:'https://attacker.example'});passed('foreign browser origin rejected by provider');
// Simultaneous first claims through independent requests, without spoofing Cloudflare IP headers.
await new Promise(r=>setTimeout(r,6500));
const race='race-'+suffix,one=signed(artifact(race)),two=signed(artifact(race),generateKeyPairSync('ec',{namedCurve:'prime256v1'}));
const rr=await Promise.all([one,two].map(async body=>{const start=new Date().toISOString(),r=await fetch(origin+'/api/publish',{method:'POST',body:JSON.stringify(body)}),data=await r.json();requests.push({start,path:'/api/publish',status:r.status,result:data});return r.status;}));assert.deepEqual(rr.sort(),[201,400]);passed('actual concurrent provider ownership/version claim has exactly one winner');
const release=await(await fetch(origin+'/api/extensions/'+id)).json();assert.equal(release.length,1);assert.equal(release[0].integrity,hash(large));assert.equal(hash(Buffer.from(await(await fetch(origin+'/api/download/'+id+'/1.0.0')).arrayBuffer())),hash(large));passed('all rejected requests retain original catalog and bytes');
fs.writeFileSync(path.join(out,'result.json'),JSON.stringify({origin,checks,requests,large:{id,bytes:large.length,sha256:hash(large)},success:true},null,2));
})().catch(e=>{fs.writeFileSync(path.join(out,'failure.json'),JSON.stringify({origin,checks,requests,error:String(e.stack)},null,2));console.error(e);process.exitCode=1;});