Run the layer acceptance under a default-deny network policy with per-layer assertion manifests and strict switch contracts

Every scenario runs through scripts/qa-strict-harness.mjs: each page, frame and worker gets an ordered block list before it runs (paid hosts and routes first, then only the preview, declared fixtures, keyless probes and cached free tile hosts), switches with real input on the picker, and records its assertions per layer and engine. The runner reads the catalog from the live page, fails any layer without an assertion on either engine, can build and serve a keyless checkout itself, and adds rapid, hidden-tab, context-loss, failure-injection, cold-chunk and soak scenarios. The main chunk gets a 1% size budget.
This commit is contained in:
German Khokhlov committed 2026-11-03 20:15:50 +04:00
1 parent 3144169057
commit 1773494116
36 files changed
+6003 -1774

No files matched your search

+102
View File
@@ -13,3 +13,105 @@ export async function blockPaidQaMaps(page, { allowPaidMaps = false } = {}) {
});
return session;
}
/**
* Free public tile hosts the strict acceptance lets a page ask for. The page
* never reaches them: the strict harness answers them from a disk cache
* (scripts/qa/tileCache.mjs), and Node fetches a missing tile once, politely.
* OpenStreetMap raster tiles, the keyless re:earth terrain, the EOX
* Sentinel-2 cloudless mosaic and Esri World Imagery (the keyless Cesium
* base imagery and the Navara startup imagery).
*/
export const STRICT_TILE_HOSTS = Object.freeze([
'tile.openstreetmap.org',
'terrain.reearth.land',
'tiles.maps.eox.at',
'services.arcgisonline.com',
]);
/**
* Requests every keyless page makes on its own, answered by the strict
* harness exactly as the keyless preview would (or with an empty stylesheet
* for Google Fonts), so they reach neither the preview's paid routes nor
* Google. Any other request under a paid route or host stays blocked.
* Keys are URLPattern strings relative to the preview origin or absolute.
*/
export const KEYLESS_PROBES = Object.freeze([
{
pattern: '/api/openai/hud-summary/status',
method: 'GET',
status: 200,
contentType: 'application/json',
body: '{"configured":false}',
},
{ pattern: '/api/google/tiles-token', method: 'GET', status: 204 },
{ pattern: '/api/realtime/debug-log', method: 'POST', status: 204 },
{
pattern: 'https://fonts.googleapis.com/css2*',
method: 'GET',
status: 200,
contentType: 'text/css',
body: '/* Google Fonts withheld by the strict QA policy */',
},
]);
/** A probe's absolute URLPattern string. */
export const probePattern = (origin, probe) =>
probe.pattern.startsWith('/')
? new URL(origin).origin + probe.pattern
: probe.pattern;
/** Paid or keyed services: blocked first, whatever else a scenario allows. */
export const PAID_HOST_PATTERNS = Object.freeze([
'*://*.googleapis.com/*',
'*://googleapis.com/*',
'*://*.google.com/*',
'*://google.com/*',
'*://maps.google.*/*',
'*://*.gstatic.com/*',
'*://*.cesium.com/*',
'*://cesium.com/*',
]);
/** Preview routes that spend a key (OpenAI, Realtime, Google proxies). */
export const PAID_PREVIEW_PATHS = Object.freeze([
'/api/openai/*',
'/api/realtime/*',
'/api/google/*',
]);
/**
* The ordered Network.setBlockedURLs patterns of the strict policy (first
* match wins): the keyless probes the harness answers are let through to
* it, paid hosts and paid preview routes are blocked, then the
* preview origin, the scenario's fixture URLs and the free tile hosts are
* allowed, then everything else is blocked.
*
* @param {string} origin The preview origin, e.g. http://127.0.0.1:4208
* @param {{fixtures?: string[], tileHosts?: readonly string[]}} [options]
* `fixtures` are URLPattern strings for requests the scenario answers.
*/
export function strictBlockPatterns(
origin,
{ fixtures = [], tileHosts = STRICT_TILE_HOSTS } = {},
) {
const preview = new URL(origin).origin;
return [
...KEYLESS_PROBES.map((probe) => ({
urlPattern: probePattern(origin, probe),
block: false,
})),
...PAID_HOST_PATTERNS.map((urlPattern) => ({ urlPattern, block: true })),
...PAID_PREVIEW_PATHS.map((path) => ({
urlPattern: preview + path,
block: true,
})),
{ urlPattern: preview + '/*', block: false },
...fixtures.map((urlPattern) => ({ urlPattern, block: false })),
...tileHosts.map((host) => ({
urlPattern: `https://${host}/*`,
block: false,
})),
{ urlPattern: '*://*:*/*', block: true },
];
}