Files
waggle-os/packages/server/tests/tauri-config.test.ts
Oleg Maslov b20b138fe4 moving
2026-09-02 10:14:22 +02:00

7383 lines
332 KiB
TypeScript

/**
* 9D-1/9D-2/9D-7: Tauri configuration tests.
*
* Validates tauri.conf.json, Cargo.toml, lib.rs, and build scripts
* are properly configured for production desktop builds.
*/
import { beforeEach, describe, it, expect } from 'vitest';
import fs from 'node:fs';
import { createHash } from 'node:crypto';
import http from 'node:http';
import os from 'node:os';
import path from 'node:path';
import { execFile, spawnSync } from 'node:child_process';
import { pathToFileURL } from 'node:url';
import Database from 'better-sqlite3';
import { parse as parseYaml } from 'yaml';
const ROOT = path.resolve(import.meta.dirname, '..', '..', '..');
const TAURI_DIR = path.join(ROOT, 'app', 'src-tauri');
const WINDOWS_1252_EXTRA_CODEPOINTS = new Set([
0x20ac, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030,
0x0160, 0x2039, 0x0152, 0x017d, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022,
0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x017e, 0x0178,
]);
const STAGED_DEPENDENCY_ALLOWLIST = new Set(['onnxruntime-web']);
const FIRST_PARTY_RUNTIME_ENTRIES = new Set([
'dist',
'LICENSE',
'LICENSE.md',
'LICENSE.txt',
'NOTICE',
'NOTICE.md',
'NOTICE.txt',
'package.json',
]);
const SOURCE_ARTIFACT_PATTERN = /(?:\.map|\.(?:[cm]?ts|tsx)|\.tsbuildinfo)$/i;
beforeEach(async () => {
// Let Vitest acknowledge the previous task update before the next test enters
// a synchronous Windows child-process probe that can occupy the worker thread.
await new Promise<void>((resolve) => setImmediate(resolve));
});
function powershellProbeExecutable() {
const configuredPwsh = process.env.WAGGLE_PWSH7_PATH;
const powerShellMajor = (executable: string) => {
const result = spawnSync(
executable,
['-NoLogo', '-NoProfile', '-Command', '$PSVersionTable.PSVersion.Major'],
{ encoding: 'utf-8', timeout: 10_000, windowsHide: true },
);
const major = Number.parseInt(result.stdout?.trim() ?? '', 10);
return result.status === 0 && Number.isInteger(major) ? major : undefined;
};
const requirePowerShell7 = (executable: string) => {
if ((powerShellMajor(executable) ?? 0) < 7) {
throw new Error('PowerShell 7 required Windows release-workflow probes');
}
return executable;
};
if (configuredPwsh) {
if (!fs.existsSync(configuredPwsh)) {
throw new Error('Configured PowerShell 7 probe executable is missing');
}
return requirePowerShell7(configuredPwsh);
}
const pwshCandidates = [
path.join(
process.env.ProgramFiles ?? 'C:\\Program Files',
'PowerShell',
'7',
'pwsh.exe',
),
process.env.LOCALAPPDATA
? path.join(process.env.LOCALAPPDATA, 'Microsoft', 'WindowsApps', 'pwsh.exe')
: undefined,
];
for (const pwsh of pwshCandidates) {
// Windows Store app execution aliases report false through fs.existsSync,
// so probe the executable rather than treating metadata access as authority.
if (pwsh && (powerShellMajor(pwsh) ?? 0) >= 7) return pwsh;
}
if (process.env.WAGGLE_REQUIRE_PWSH7 === '1') {
throw new Error('PowerShell 7 is required for Windows release-workflow probes');
}
return path.join(
process.env.SystemRoot ?? 'C:\\Windows',
'System32',
'WindowsPowerShell',
'v1.0',
'powershell.exe',
);
}
function isWindows1252PathSafe(value: string) {
for (const char of value) {
const code = char.codePointAt(0) ?? 0;
if (code <= 0x7f || (code >= 0xa0 && code <= 0xff)) continue;
if (WINDOWS_1252_EXTRA_CODEPOINTS.has(code)) continue;
return false;
}
return true;
}
function listFiles(dir: string) {
const files: string[] = [];
const stack = [dir];
while (stack.length > 0) {
const current = stack.pop()!;
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
const full = path.join(current, entry.name);
if (entry.isDirectory()) stack.push(full);
else if (entry.isFile()) files.push(full);
}
}
return files;
}
function listPackageDirs(nodeModulesDir: string) {
if (!fs.existsSync(nodeModulesDir)) return [];
const packageDirs: string[] = [];
const stack = [nodeModulesDir];
while (stack.length > 0) {
const current = stack.pop()!;
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
if (!entry.isDirectory()) continue;
const full = path.join(current, entry.name);
if (fs.existsSync(path.join(full, 'package.json'))) {
packageDirs.push(full);
}
stack.push(full);
}
}
return packageDirs;
}
function resolveWithinStagedResources(fromPackageDir: string, dep: string, resourcesDir: string) {
let current = fromPackageDir;
for (;;) {
const candidate = path.join(current, 'node_modules', ...dep.split('/'), 'package.json');
if (fs.existsSync(candidate)) return true;
if (path.resolve(current) === path.resolve(resourcesDir)) return false;
const parent = path.dirname(current);
if (parent === current) return false;
current = parent;
}
}
function localWorkspacePackageNames() {
const names = new Set<string>();
for (const workspaceRoot of ['packages', 'apps'].map((entry) => path.join(ROOT, entry))) {
if (!fs.existsSync(workspaceRoot)) continue;
for (const entry of fs.readdirSync(workspaceRoot, { withFileTypes: true })) {
if (!entry.isDirectory()) continue;
try {
const manifest = JSON.parse(
fs.readFileSync(path.join(workspaceRoot, entry.name, 'package.json'), 'utf-8'),
) as { name?: unknown };
if (typeof manifest.name === 'string') names.add(manifest.name);
} catch {
// Non-package workspace directories are irrelevant to staged runtime checks.
}
}
}
return names;
}
describe('Tauri Production Configuration', () => {
it('pins Tauri-rewritten manifests and generated schemas to LF across platforms', () => {
const trackedPaths = [
'app/src-tauri/Cargo.toml',
'app/src-tauri/gen/schemas/windows-schema.json',
'app/src-tauri/gen/schemas/desktop-schema.json',
];
const result = spawnSync('git', ['check-attr', '-z', 'text', 'eol', '--', ...trackedPaths], {
cwd: ROOT,
encoding: 'utf-8',
windowsHide: true,
});
expect(result.error).toBeUndefined();
expect(result.status).toBe(0);
const fields = result.stdout.split('\0').filter(Boolean);
const effectiveAttributes = new Map<string, string>();
for (let index = 0; index < fields.length; index += 3) {
effectiveAttributes.set(`${fields[index]}:${fields[index + 1]}`, fields[index + 2]);
}
for (const trackedPath of trackedPaths) {
expect(effectiveAttributes.get(`${trackedPath}:text`)).toBe('set');
expect(effectiveAttributes.get(`${trackedPath}:eol`)).toBe('lf');
}
});
it('tauri.conf.json exists and has valid version', () => {
const conf = JSON.parse(fs.readFileSync(path.join(TAURI_DIR, 'tauri.conf.json'), 'utf-8'));
expect(conf.productName).toBe('Waggle');
expect(conf.version).toMatch(/^\d+\.\d+\.\d+$/);
// Canonical bundle identifier — Egzakta-branded for code signing
// + App Store / Mac notarization. Set in tauri.conf.json. Don't
// change without coordinating with the signing cert subject.
expect(conf.identifier).toBe('com.egzakta.waggle');
});
it('tauri.conf.json has bundle targets configured', () => {
const conf = JSON.parse(fs.readFileSync(path.join(TAURI_DIR, 'tauri.conf.json'), 'utf-8'));
// targets: "all" builds for the current platform (NSIS on Windows, DMG on macOS, etc.)
expect(conf.bundle.targets).toBe('all');
expect(conf.bundle.active).toBe(true);
});
it('tauri.conf.json bundles resources directory', () => {
const conf = JSON.parse(fs.readFileSync(path.join(TAURI_DIR, 'tauri.conf.json'), 'utf-8'));
expect(conf.bundle.resources).toContain('resources/*');
});
it('tauri.conf.json has correct window settings', () => {
const conf = JSON.parse(fs.readFileSync(path.join(TAURI_DIR, 'tauri.conf.json'), 'utf-8'));
const win = conf.app.windows[0];
expect(win.title).toBe('Waggle');
expect(win.create).toBe(false);
expect(win.width).toBe(1200);
expect(win.height).toBe(800);
expect(win.minWidth).toBe(800);
expect(win.minHeight).toBe(600);
expect(win.resizable).toBe(true);
const lib = fs.readFileSync(path.join(TAURI_DIR, 'src', 'lib.rs'), 'utf-8');
expect(lib).toContain('WAGGLE_CERTIFIER_WEBVIEW_DEBUG_PORT');
expect(lib).toContain('additional_browser_args');
});
it('tauri.conf.json has the auto-updater intentionally disabled for v1', () => {
// The updater plugin config was removed because release.yml published
// latest.json with EMPTY signatures — with a pubkey present, every client
// update would fail signature verification (a broken update channel). It
// stays disabled until updater signing is provisioned (TAURI_SIGNING_PRIVATE_KEY
// + createUpdaterArtifacts + a real-signature manifest generator).
const conf = JSON.parse(fs.readFileSync(path.join(TAURI_DIR, 'tauri.conf.json'), 'utf-8'));
expect(conf.plugins?.updater).toBeUndefined();
});
it('creates exactly one tray icon from Rust so the context menu is always attached', () => {
const conf = JSON.parse(fs.readFileSync(path.join(TAURI_DIR, 'tauri.conf.json'), 'utf-8'));
expect(conf.app.trayIcon).toBeUndefined();
const tray = fs.readFileSync(path.join(TAURI_DIR, 'src', 'tray.rs'), 'utf-8');
expect(tray).toContain('TrayIconBuilder::new()');
expect(tray).toContain('.menu(&menu)');
const certifier = fs.readFileSync(
path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'),
'utf-8',
);
expect(certifier).toContain('status --porcelain=v1 --untracked-files=all');
});
it('tray menu exposes only implemented desktop actions', () => {
const tray = fs.readFileSync(path.join(TAURI_DIR, 'src', 'tray.rs'), 'utf-8');
expect(tray).toContain('"Open Waggle"');
expect(tray).toContain('"Settings"');
expect(tray).toContain('"Quit Waggle"');
expect(tray).toContain('app.exit(0)');
expect(tray).toContain('.show_menu_on_left_click(false)');
expect(tray).toContain('button: MouseButton::Left');
expect(tray).toContain('button_state: MouseButtonState::Up');
expect(tray).toContain('"waggle://navigate"');
expect(tray).toContain('"/settings"');
expect(tray).not.toContain('"Pause Agents"');
expect(tray).not.toContain('"About Waggle"');
expect(tray).not.toContain('"waggle://pause-agents"');
expect(tray).not.toContain('"waggle://quit"');
expect(tray).not.toContain('"/about"');
});
it('packaged Windows sidecar stays hidden and writes bounded diagnostics', () => {
const service = fs.readFileSync(path.join(TAURI_DIR, 'src', 'service.rs'), 'utf-8');
const certifier = fs.readFileSync(
path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'),
'utf-8',
);
expect(service).toContain('const CREATE_NO_WINDOW: u32 = 0x08000000');
expect(service).toContain('command.creation_flags(CREATE_NO_WINDOW)');
expect(service).toContain('service.log');
expect(service).toContain('MAX_SERVICE_LOG_BYTES');
expect(service).toContain('rotate_service_log');
expect(certifier).toContain('function Assert-NoVisibleConsoleDescendant');
const consoleCheck = certifier.slice(
certifier.indexOf('function Assert-NoVisibleConsoleDescendant'),
certifier.indexOf('function Wait-ForInstalledRuntimeStop'),
);
expect(consoleCheck).not.toHaveLength(0);
expect(consoleCheck).toContain('MainWindowHandle');
expect(consoleCheck).toContain('[IntPtr]::Zero');
expect(consoleCheck).toContain('[WaggleInstallerWindowProbe]::IsWindowVisible');
expect(consoleCheck).toMatch(
/catch \{[\s\S]*Get-Process -Id \$consoleProcessId[\s\S]*throw/,
);
expect(certifier).toContain("$receipt.checks['firstBootHiddenService']");
expect(certifier).toContain("$receipt.checks['repairHiddenService']");
});
it('preserves detached user sessions while IPC-supervising owned service runtimes', () => {
const service = fs.readFileSync(path.join(TAURI_DIR, 'src', 'service.rs'), 'utf-8');
const lifecycle = fs.readFileSync(
path.join(ROOT, 'packages', 'server', 'src', 'local', 'lifecycle.ts'),
'utf-8',
);
expect(service).toContain('JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK');
expect(lifecycle).toContain('spawnSidecarOwnedProcess');
expect(lifecycle).not.toMatch(/litellmProcess\s*=\s*spawn\(/);
});
it('web app mounts the Tauri desktop navigation bridge', () => {
const app = fs.readFileSync(path.join(ROOT, 'apps', 'web', 'src', 'App.tsx'), 'utf-8');
expect(app).toContain('listenDesktopNavigation');
expect(app).toContain('listenDesktopShellEvents');
expect(app).toContain('<TauriDesktopEventBridge />');
});
it('tauri.conf.json has CSP that allows localhost connections', () => {
const conf = JSON.parse(fs.readFileSync(path.join(TAURI_DIR, 'tauri.conf.json'), 'utf-8'));
const csp = conf.app.security.csp;
expect(csp).toContain('http://localhost:*');
expect(csp).toContain('ws://localhost:*');
});
it('desktop startup remains visible when the app bundle cannot mount', () => {
const main = fs.readFileSync(
path.join(ROOT, 'apps', 'web', 'src', 'main.tsx'),
'utf-8',
);
const css = fs.readFileSync(
path.join(ROOT, 'apps', 'web', 'src', 'index.css'),
'utf-8',
);
const appEntry = fs.readFileSync(
path.join(ROOT, 'apps', 'web', 'src', 'app-entry.tsx'),
'utf-8',
);
expect(main).toContain("document.getElementById('root')");
expect(main).toContain('Starting Waggle');
expect(main).toContain("startup.dataset.waggleStartup = 'loading'");
expect(main).toContain("import('./app-entry')");
expect(main).toContain('.catch((error) =>');
expect(main).toContain('Waggle could not start');
expect(appEntry).toContain("dataset.waggleUiReady = 'ready'");
expect(css).not.toMatch(/@import\s+(?:url\()?['"]?https?:\/\//i);
});
it('desktop CSP permits only the local Tauri IPC bridge', () => {
const conf = JSON.parse(fs.readFileSync(path.join(TAURI_DIR, 'tauri.conf.json'), 'utf-8'));
const csp = conf.app.security.csp;
expect(csp).toContain('ipc:');
expect(csp).toContain('http://ipc.localhost');
expect(csp).not.toContain('https://fonts.googleapis.com');
});
it('installer certification fails closed on a blank desktop WebView', () => {
const helperPath = path.join(ROOT, 'scripts', 'read-tauri-bootstrap-token.mjs');
const result = spawnSync(process.execPath, [helperPath, '--self-test'], {
cwd: ROOT,
encoding: 'utf-8',
timeout: 30_000,
windowsHide: true,
});
expect(result.status, result.stderr || result.stdout).toBe(0);
expect(JSON.parse(result.stdout)).toEqual({ pass: true, cases: 9 });
const certifier = fs.readFileSync(
path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'),
'utf-8',
);
expect(certifier).toContain("$tokenPayload.PSObject.Properties['uiReady']");
expect(certifier).toContain('Installed Waggle WebView did not render its application shell.');
expect(certifier).toContain("$receipt.checks['firstBootUi']");
expect(certifier).toContain("$receipt.checks['repairUi']");
});
it('keeps candidate-only desktop gates compatible with the protected previous release', () => {
const helper = fs.readFileSync(
path.join(ROOT, 'scripts', 'read-tauri-bootstrap-token.mjs'),
'utf-8',
);
const certifier = fs.readFileSync(
path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'),
'utf-8',
);
const previousReleaseBlock = certifier.slice(
certifier.indexOf('$previousProcess = Start-InstalledApp'),
certifier.indexOf('$previousTier = Invoke-JsonRequest'),
);
expect(helper).toContain("argument === '--allow-legacy-ui'");
expect(certifier).toContain('[switch]$AllowLegacyUi');
expect(previousReleaseBlock).toContain('-AllowLegacyUi');
expect(previousReleaseBlock).not.toContain('Assert-NoVisibleConsoleDescendant');
expect(previousReleaseBlock).not.toContain("$receipt.checks['previousHiddenService']");
});
it('Cargo.toml has updater plugin dependency', () => {
const cargo = fs.readFileSync(path.join(TAURI_DIR, 'Cargo.toml'), 'utf-8');
expect(cargo).toContain('tauri-plugin-updater');
expect(cargo).toContain('tauri-plugin-notification');
expect(cargo).toContain('tauri-plugin-single-instance');
});
it('capabilities do not expose updater commands while updater config is disabled', () => {
const caps = JSON.parse(
fs.readFileSync(path.join(TAURI_DIR, 'capabilities', 'default.json'), 'utf-8'),
);
expect(caps.permissions).not.toContain('updater:default');
});
it('does not configure unit-only Tauri plugins as objects', () => {
// Regression: the packaged debug exe panicked during startup when
// `plugins.dialog` was `{ open, save }`; tauri-plugin-dialog expects no
// config payload when initialized with `tauri_plugin_dialog::init()`.
const conf = JSON.parse(fs.readFileSync(path.join(TAURI_DIR, 'tauri.conf.json'), 'utf-8'));
expect(conf.plugins?.dialog).toBeUndefined();
});
it('lib.rs does not initialize updater while config is disabled', () => {
// Regression: registering tauri-plugin-updater without plugins.updater
// config deserializes as null and panics before the desktop UI starts.
const lib = fs.readFileSync(path.join(TAURI_DIR, 'src', 'lib.rs'), 'utf-8');
expect(lib).not.toContain('tauri_plugin_updater::Builder::new().build()');
expect(lib).not.toContain('.updater()');
});
it('NSIS installer template never deletes profile data', () => {
const nsis = fs.readFileSync(path.join(TAURI_DIR, 'nsis', 'installer.nsi'), 'utf-8');
const conf = JSON.parse(fs.readFileSync(path.join(TAURI_DIR, 'tauri.conf.json'), 'utf-8'));
expect(nsis).toContain('NSIS_HOOK_PREINSTALL');
// Data erasure is an authenticated, confirmation-phrase-gated in-app flow.
// The package uninstaller must never recursively delete the real profile.
expect(nsis).not.toContain('NSIS_HOOK_POSTUNINSTALL');
expect(nsis).toContain('NSIS_HOOK_PREUNINSTALL');
expect(nsis).toMatch(/StrCpy\s+\$DeleteAppDataCheckboxState\s+0/);
expect(nsis).not.toMatch(
/\b(?:RMDir|Delete)\b[^\r\n]*(?:\$PROFILE[\\/]+\.waggle|\.waggle)/i,
);
expect(conf.bundle.windows.nsis.installerHooks).toBe('nsis/installer.nsi');
expect(conf.bundle.windows.nsis.installMode).toBe('currentUser');
// Tauri owns shortcuts and normal/silent launch behavior. Duplicating those
// in POSTINSTALL caused double launches and made repair certificates racy.
expect(nsis).not.toContain('NSIS_HOOK_POSTINSTALL');
expect(nsis).not.toContain('CreateShortcut');
expect(nsis).not.toMatch(/\bExec\s+['"]/);
});
it('pilot-signed Windows build consumes the generated Tauri override', () => {
const manifest = JSON.parse(
fs.readFileSync(path.join(ROOT, 'app', 'package.json'), 'utf-8'),
);
const signedBuild = manifest.scripts?.['tauri:build:win:pilot-signed'];
const windowsBuild = manifest.scripts?.['tauri:build:win'];
const override = JSON.parse(
fs.readFileSync(
path.join(TAURI_DIR, 'tauri.build-override.conf.json'),
'utf-8',
),
);
expect(signedBuild).toContain('npm run tauri:sign:pilot:win:apply');
expect(signedBuild).toContain(
'npm run tauri:build:win -- --config src-tauri/tauri.build-override.conf.json',
);
expect(override.build.beforeBuildCommand).toBe('');
const stageIndex = windowsBuild.indexOf('stage-sidecar-deps.mjs');
const preflightIndex = windowsBuild.indexOf('check-sidecar-resources.mjs');
const tauriIndex = windowsBuild.indexOf('npx tauri build');
expect(stageIndex).toBeGreaterThanOrEqual(0);
expect(preflightIndex).toBeGreaterThan(stageIndex);
expect(tauriIndex).toBeGreaterThan(preflightIndex);
});
it('icon.ico exists', () => {
expect(fs.existsSync(path.join(TAURI_DIR, 'icons', 'icon.ico'))).toBe(true);
});
it('build-sidecar script exists', () => {
const script = path.join(ROOT, 'scripts', 'build-sidecar.mjs');
expect(fs.existsSync(script)).toBe(true);
const content = fs.readFileSync(script, 'utf-8');
expect(content).toContain('esbuild');
expect(content).toContain('service.ts');
expect(content).toContain('resources/service.js');
expect(content).toContain('sourcemap: false');
expect(content).toContain('fs.rmSync(sourceMapFile, { force: true })');
expect(content).toContain("path.join(root, 'packages', 'marketplace', 'marketplace.db')");
expect(content).not.toContain("'marketplace', 'seed', 'marketplace.db'");
expect(content).toContain('Required marketplace database is missing');
expect(content).toContain(
"'@waggle/agent/external-process-env': path.join(root, 'packages', 'agent', 'src', 'external-process-env.ts')",
);
const serverIndex = fs.readFileSync(
path.join(ROOT, 'packages', 'server', 'src', 'local', 'index.ts'),
'utf-8',
);
expect(serverIndex).toContain("path.resolve(__dirname, 'marketplace.db')");
});
it('build-sidecar exact alias resolves the agent env helper before its root alias', async () => {
const esbuild = await import('esbuild');
const result = await esbuild.build({
stdin: {
contents: "import { buildExternalProcessEnv } from '@waggle/agent/external-process-env'; export const env = buildExternalProcessEnv({ PATH: 'fixture' });",
loader: 'ts',
resolveDir: ROOT,
sourcefile: 'sidecar-agent-subpath-probe.ts',
},
absWorkingDir: ROOT,
bundle: true,
platform: 'node',
target: 'node20',
format: 'esm',
write: false,
logLevel: 'silent',
alias: {
'@waggle/agent/external-process-env': path.join(
ROOT, 'packages', 'agent', 'src', 'external-process-env.ts',
),
'@waggle/agent': path.join(ROOT, 'packages', 'agent', 'src', 'index.ts'),
},
});
expect(result.errors).toEqual([]);
expect(result.outputFiles[0]?.text).toContain('buildExternalProcessEnv');
});
it('build-sidecar provenance follows transitive tsconfig inheritance', () => {
const fixtureRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-sidecar-tsconfig-'));
const writeRelative = (relative: string, content: string | Buffer) => {
const target = path.join(fixtureRoot, ...relative.split('/'));
fs.mkdirSync(path.dirname(target), { recursive: true });
fs.writeFileSync(target, content);
return target;
};
const runResult = (command: string, args: string[]) => spawnSync(command, args, {
cwd: fixtureRoot,
env: {
...process.env,
TEMP: fixtureRoot,
TMP: fixtureRoot,
TMPDIR: fixtureRoot,
},
encoding: 'utf8',
timeout: 60_000,
windowsHide: true,
});
const run = (command: string, args: string[]) => {
const result = runResult(command, args);
expect(result.status, result.stderr || result.stdout).toBe(0);
return result;
};
try {
fs.mkdirSync(path.join(fixtureRoot, 'scripts'), { recursive: true });
fs.copyFileSync(
path.join(ROOT, 'scripts', 'build-sidecar.mjs'),
path.join(fixtureRoot, 'scripts', 'build-sidecar.mjs'),
);
const trackedFiles = new Map<string, string>([
['package-lock.json', '{"lockfileVersion":3}\n'],
['package.json', '{"name":"sidecar-tsconfig-fixture","private":true}\n'],
['packages/marketplace/marketplace.db', 'fixture database'],
['packages/server/package.json', '{"name":"@waggle/server"}\n'],
['packages/server/src/local/service.ts', 'export const fixture = true;\n'],
['packages/server/tsconfig.json', '{"extends":"../../tsconfig.base"}\n'],
['tsconfig.base.json', '{"extends":["./tsconfig.shared"]}\n'],
['tsconfig.shared.json', '{"compilerOptions":{"target":"ES2022"}}\n'],
]);
for (const [relative, content] of trackedFiles) writeRelative(relative, content);
writeRelative(
'node_modules/esbuild/package.json',
JSON.stringify({ name: 'esbuild', version: '0.0.0', type: 'module', exports: './index.js' }),
);
writeRelative(
'node_modules/esbuild/index.js',
[
"import fs from 'node:fs';",
"import path from 'node:path';",
'export async function build(options) {',
' fs.mkdirSync(path.dirname(options.outfile), { recursive: true });',
" fs.writeFileSync(options.outfile, 'fixture bundle\\n');",
' return {',
' errors: [],',
' warnings: [],',
" metafile: { inputs: { 'packages/server/src/local/service.ts': { bytes: 29, imports: [] } } },",
' };',
'}',
'',
].join('\n'),
);
writeRelative(
'node_modules/typescript/package.json',
JSON.stringify({ name: 'typescript', version: '0.0.0', type: 'module', exports: './index.js' }),
);
writeRelative(
'node_modules/typescript/index.js',
[
'export default {',
' parseConfigFileTextToJson(_file, text) {',
' try { return { config: JSON.parse(text) }; }',
' catch (error) { return { error }; }',
' },',
'};',
'',
].join('\n'),
);
run('git', ['init']);
run('git', ['config', 'user.email', 'sidecar-tsconfig@waggle.invalid']);
run('git', ['config', 'user.name', 'Waggle Fixture']);
run('git', ['add', '--', 'scripts/build-sidecar.mjs', ...trackedFiles.keys()]);
run('git', ['commit', '-m', 'fixture']);
run(process.execPath, ['scripts/build-sidecar.mjs']);
const service = fs.readFileSync(
path.join(fixtureRoot, 'app', 'src-tauri', 'resources', 'service.js'),
);
const lineEnd = service.indexOf(0x0a);
const prefix = '// Waggle-Sidecar-Provenance: ';
const firstLine = service.subarray(0, lineEnd).toString('utf8');
expect(firstLine.startsWith(prefix)).toBe(true);
const manifest = JSON.parse(
Buffer.from(firstLine.slice(prefix.length), 'base64').toString('utf8'),
) as { sourceInputs: Array<{ path: string }> };
const sourcePaths = manifest.sourceInputs.map((input) => input.path);
expect(sourcePaths).toEqual(
expect.arrayContaining([
'packages/server/tsconfig.json',
'tsconfig.base.json',
'tsconfig.shared.json',
]),
);
const marketplacePath = path.join(
fixtureRoot,
'packages',
'marketplace',
'marketplace.db',
);
const marketplaceResourcePath = path.join(
fixtureRoot,
'app',
'src-tauri',
'resources',
'marketplace.db',
);
const committedMarketplace = Buffer.from(
trackedFiles.get('packages/marketplace/marketplace.db')!,
);
expect(fs.readFileSync(marketplaceResourcePath)).toEqual(committedMarketplace);
fs.writeFileSync(marketplacePath, 'dirty worktree database');
const dirtyMarketplaceResult = runResult(
process.execPath,
['scripts/build-sidecar.mjs'],
);
expect(
dirtyMarketplaceResult.status,
dirtyMarketplaceResult.stderr || dirtyMarketplaceResult.stdout,
).toBe(1);
expect(dirtyMarketplaceResult.stderr).toContain(
'canonical marketplace database does not match exact source revision',
);
expect(fs.readFileSync(marketplaceResourcePath)).toEqual(committedMarketplace);
expect(
fs.readdirSync(path.dirname(marketplaceResourcePath))
.filter((name) => name.startsWith('marketplace.db.stage-')),
).toEqual([]);
} finally {
fs.rmSync(fixtureRoot, { recursive: true, force: true });
}
});
it('D12: the bundled sidecar is generated at build time, never tracked', () => {
// beforeBuildCommand regenerates the bundle on EVERY build path — including
// a raw `npx tauri build` that bypasses the npm scripts and CI steps. A
// tracked copy goes stale silently; a binary shipping an old server is a
// release-stopping defect class (UX-Refactor P4 / D12 ruling).
const conf = JSON.parse(fs.readFileSync(path.join(TAURI_DIR, 'tauri.conf.json'), 'utf-8'));
expect(conf.build.beforeBuildCommand).toContain('build-sidecar.mjs');
const gitignore = fs.readFileSync(path.join(ROOT, '.gitignore'), 'utf-8');
expect(gitignore).toContain('app/src-tauri/resources/service.js');
expect(gitignore).not.toContain('app/src-tauri/resources/service.js.map');
});
it('bundle-node pins the supported desktop Node release used by CI', () => {
const script = fs.readFileSync(path.join(ROOT, 'scripts', 'bundle-node.mjs'), 'utf-8');
expect(script).toContain("const DESKTOP_NODE_VERSION = '22.23.2'");
expect(script).toContain('const NODE_VERSION = DESKTOP_NODE_VERSION');
expect(script).toContain("const SAFE_NPM_IP_ADDRESS_VERSION = '10.4.0'");
expect(script).toContain('Hardened bundled npm with ip-address');
expect(script).not.toContain('process.versions.node;');
for (const workflowPath of [
'.github/workflows/release.yml',
'.github/workflows/tauri-build-pr.yml',
]) {
const workflow = fs.readFileSync(path.join(ROOT, workflowPath), 'utf-8');
expect(workflow.match(/node-version: 22\.23\.2/g), workflowPath).toHaveLength(2);
expect(workflow, workflowPath).not.toMatch(/node-version: 20(?:\s|$)/);
const runtimeSteps = [...workflow.matchAll(/run: node scripts\/bundle-node\.mjs/g)];
const sidecarSteps = [...workflow.matchAll(/run: node scripts\/build-sidecar\.mjs/g)];
const nativeSteps = [...workflow.matchAll(/run: node scripts\/bundle-native-deps\.mjs/g)];
expect(runtimeSteps, workflowPath).toHaveLength(2);
expect(sidecarSteps, workflowPath).toHaveLength(2);
expect(nativeSteps, workflowPath).toHaveLength(2);
for (let index = 0; index < runtimeSteps.length; index++) {
expect(runtimeSteps[index].index, `${workflowPath} job ${index + 1}`).toBeLessThan(
sidecarSteps[index].index,
);
expect(runtimeSteps[index].index, `${workflowPath} job ${index + 1}`).toBeLessThan(
nativeSteps[index].index,
);
}
}
});
it('desktop builds verify the selected Node ABI before staging native resources', () => {
const manifest = JSON.parse(
fs.readFileSync(path.join(ROOT, 'app', 'package.json'), 'utf-8'),
) as { scripts?: Record<string, string> };
for (const scriptName of [
'tauri:build',
'tauri:build:local',
'tauri:build:win',
'tauri:build:mac:arm64',
'tauri:build:mac:x64',
]) {
const command = manifest.scripts?.[scriptName] ?? '';
expect(command.indexOf('bundle-node.mjs'), scriptName).toBeGreaterThanOrEqual(0);
expect(command.indexOf('bundle-node.mjs'), scriptName).toBeLessThan(
command.indexOf('build-sidecar.mjs'),
);
expect(command.indexOf('bundle-node.mjs'), scriptName).toBeLessThan(
command.indexOf('bundle-native-deps.mjs'),
);
}
const script = fs.readFileSync(path.join(ROOT, 'scripts', 'bundle-node.mjs'), 'utf-8');
const probeIndex = script.indexOf('assertNativeRuntimeCompatible();');
const mutationIndex = script.indexOf('fs.copyFileSync(nodeSource, destBinary)');
const stagedRuntimeMutationIndex = script.indexOf(
'fs.rmSync(stagedRuntimeDir, { recursive: true, force: true })',
);
expect(probeIndex).toBeGreaterThanOrEqual(0);
expect(mutationIndex).toBeGreaterThan(probeIndex);
expect(stagedRuntimeMutationIndex).toBeGreaterThan(probeIndex);
expect(script).toContain("const database = new Database(':memory:')");
expect(script).toContain('SELECT 1 AS ok');
expect(script).toContain('native ABI compatibility probe failed');
});
it('pins patched transitive dependency versions used by desktop builds', () => {
const manifest = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf-8')) as {
engines?: { node?: string };
overrides?: Record<string, string | Record<string, string>>;
dependencies?: Record<string, string>;
};
const lockfile = JSON.parse(
fs.readFileSync(path.join(ROOT, 'package-lock.json'), 'utf-8'),
) as {
packages: Record<string, { version?: string }>;
};
const expectedOverrides = {
'@fastify/static': '>=10.1.2 <11',
'brace-expansion@1': '1.1.18',
'brace-expansion@2': '2.1.4',
'brace-expansion@5': '5.0.9',
'fast-uri': '3.1.5',
'ip-address': '10.4.0',
'find-my-way': '9.7.0',
'js-yaml': '4.3.1',
'better-sqlite3': '12.6.2',
'@huggingface/transformers': { sharp: '0.35.3' },
next: '16.3.0',
};
expect(manifest.engines?.node).toBe('^20.19.0 || >=22.12.0');
expect(manifest.overrides).toMatchObject(expectedOverrides);
expect(manifest.dependencies).toMatchObject({
'@huggingface/transformers': '3.8.1',
sharp: '0.35.3',
});
const fastifyStaticRanges = ['launcher', 'server'].map((workspace) => {
const workspaceManifest = JSON.parse(fs.readFileSync(
path.join(ROOT, 'packages', workspace, 'package.json'),
'utf-8',
)) as { dependencies?: Record<string, string> };
return workspaceManifest.dependencies?.['@fastify/static'];
});
expect(new Set(fastifyStaticRanges)).toEqual(new Set(['^10.1.2']));
const betterSqliteRanges = [
'core',
'hive-mind-core',
'launcher',
'marketplace',
'server',
].map((workspace) => {
const workspaceManifest = JSON.parse(fs.readFileSync(
path.join(ROOT, 'packages', workspace, 'package.json'),
'utf-8',
)) as { dependencies?: Record<string, string> };
return workspaceManifest.dependencies?.['better-sqlite3'];
});
expect(new Set(betterSqliteRanges)).toEqual(new Set(['^12.6.2']));
const versionsFor = (packageName: string) => {
const matching = Object.entries(lockfile.packages)
.filter(([packagePath]) => packagePath.endsWith(`node_modules/${packageName}`));
expect(matching.length).toBeGreaterThan(0);
for (const [, metadata] of matching) {
expect(metadata.version).toEqual(expect.any(String));
}
return new Set(matching.map(([, metadata]) => metadata.version!));
};
expect(versionsFor('@fastify/static')).toEqual(new Set(['10.1.2']));
expect(versionsFor('brace-expansion')).toEqual(new Set(['1.1.18', '2.1.4', '5.0.9']));
expect(versionsFor('fast-uri')).toEqual(new Set(['3.1.5']));
expect(versionsFor('ip-address')).toEqual(new Set(['10.4.0']));
expect(versionsFor('find-my-way')).toEqual(new Set(['9.7.0']));
expect(versionsFor('js-yaml')).toEqual(new Set(['4.3.1']));
expect(versionsFor('sharp')).toEqual(new Set(['0.35.3']));
expect(versionsFor('better-sqlite3')).toEqual(new Set(['12.6.2']));
const sharpBindings = Object.entries(lockfile.packages)
.filter(([packagePath]) => (
/node_modules\/@img\/sharp-(?!libvips-)[^/]+$/.test(packagePath)
));
expect(sharpBindings.length).toBeGreaterThan(0);
expect(new Set(sharpBindings.map(([, metadata]) => metadata.version))).toEqual(
new Set(['0.35.3']),
);
});
it('rejects unsafe staged dependency versions without native runtime setup', () => {
const fixture = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-dependency-floor-'));
const checker = path.join(ROOT, 'scripts', 'check-sidecar-resources.mjs');
const writeManifest = (relative: string, name?: string, version?: string) => {
const packageDir = path.join(fixture, ...relative.split('/'));
fs.mkdirSync(packageDir, { recursive: true });
fs.writeFileSync(
path.join(packageDir, 'package.json'),
JSON.stringify({ name, version }),
'utf-8',
);
return packageDir;
};
const run = () => spawnSync(
process.execPath,
[checker, '--dependency-versions-only', fixture],
{ encoding: 'utf-8', windowsHide: true },
);
const bundledBrace = [
'waggle-node-runtime',
'node_modules',
'npm',
'node_modules',
'brace-expansion',
].join('/');
try {
writeManifest('brace-expansion', 'brace-expansion', '5.0.9');
writeManifest('fast-uri', 'fast-uri', '3.1.5');
writeManifest('ip-address', 'ip-address', '10.4.0');
writeManifest('better-sqlite3', 'better-sqlite3', '12.9.0');
writeManifest('sharp', 'sharp', '0.35.3');
writeManifest(bundledBrace, 'brace-expansion', '2.1.4');
expect(run().status).toBe(0);
writeManifest('better-sqlite3', 'better-sqlite3', '12.6.2');
expect(run().status).toBe(0);
writeManifest('better-sqlite3', 'better-sqlite3', '12.9.0');
writeManifest('better-sqlite3', 'better-sqlite3', '11.10.0');
const legacyBetterSqlite = run();
expect(legacyBetterSqlite.status).toBe(1);
expect(legacyBetterSqlite.stderr).toContain('better-sqlite3@11.10.0');
writeManifest('better-sqlite3', 'better-sqlite3', '12.6.1');
expect(run().status).toBe(1);
writeManifest('better-sqlite3', 'better-sqlite3', '13.0.0');
expect(run().status).toBe(1);
writeManifest('better-sqlite3', 'not-better-sqlite3', '12.9.0');
const spoofedBetterSqlite = run();
expect(spoofedBetterSqlite.status).toBe(1);
expect(spoofedBetterSqlite.stderr).toContain('must identify as better-sqlite3');
writeManifest('better-sqlite3', 'better-sqlite3');
const missingBetterSqliteVersion = run();
expect(missingBetterSqliteVersion.status).toBe(1);
expect(missingBetterSqliteVersion.stderr).toContain('required version: >=12.6.2 <13');
for (const invalidVersion of [
'12.07.0',
'12.9007199254740992.0',
'12.6.2-beta.1',
'12.6.2+build.1',
]) {
writeManifest('better-sqlite3', 'better-sqlite3', invalidVersion);
const invalidBetterSqlite = run();
expect(
invalidBetterSqlite.status,
`${invalidVersion}: ${invalidBetterSqlite.stderr}`,
).toBe(1);
}
fs.rmSync(path.join(fixture, 'better-sqlite3'), { recursive: true, force: true });
writeManifest('Better-SQLite3', 'not-better-sqlite3', '12.9.0');
const uppercaseDirectBetterSqlite = run();
expect(uppercaseDirectBetterSqlite.status).toBe(1);
expect(uppercaseDirectBetterSqlite.stderr).toContain('must identify as better-sqlite3');
fs.rmSync(path.join(fixture, 'Better-SQLite3'), { recursive: true, force: true });
writeManifest(
'vendor/node_modules/Better-SQLite3',
'not-better-sqlite3',
'12.9.0',
);
const uppercaseNestedBetterSqlite = run();
expect(uppercaseNestedBetterSqlite.status).toBe(1);
expect(uppercaseNestedBetterSqlite.stderr).toContain('must identify as better-sqlite3');
fs.rmSync(path.join(fixture, 'vendor'), { recursive: true, force: true });
writeManifest('better-sqlite3', 'better-sqlite3', '12.9.0');
writeManifest(bundledBrace, 'brace-expansion', '2.1.2');
const vulnerableNpm = run();
expect(vulnerableNpm.status).toBe(1);
expect(vulnerableNpm.stderr).toContain('must be exactly 2.1.4');
writeManifest(bundledBrace, 'brace-expansion', '2.1.4');
writeManifest('brace-expansion', 'brace-expansion', '5.0.7');
const vulnerableStagedBrace = run();
expect(vulnerableStagedBrace.status).toBe(1);
expect(vulnerableStagedBrace.stderr).toContain('brace-expansion@5.0.7');
writeManifest('brace-expansion', 'brace-expansion', '5.0.9');
writeManifest('fast-uri', 'fast-uri', '3.1.4');
const vulnerableFastUri = run();
expect(vulnerableFastUri.status).toBe(1);
expect(vulnerableFastUri.stderr).toContain('fast-uri@3.1.4');
writeManifest('fast-uri', 'fast-uri', '3.1.5');
writeManifest('ip-address', 'ip-address', '10.2.0');
const vulnerableIpAddress = run();
expect(vulnerableIpAddress.status).toBe(1);
expect(vulnerableIpAddress.stderr).toContain('ip-address@10.2.0');
writeManifest('ip-address', 'ip-address', '10.4.0');
writeManifest('sharp', 'sharp', '0.34.5');
const vulnerableSharp = run();
expect(vulnerableSharp.status).toBe(1);
expect(vulnerableSharp.stderr).toContain('sharp@0.34.5');
writeManifest('sharp', 'sharp', '0.35.3');
writeManifest('vendor/node_modules/js-yaml', 'js-yaml', '4.3.0');
const stagedDevDependency = run();
expect(stagedDevDependency.status).toBe(1);
expect(stagedDevDependency.stderr).toContain('development-only js-yaml');
fs.rmSync(path.join(fixture, 'vendor'), { recursive: true, force: true });
fs.rmSync(
path.join(fixture, ...bundledBrace.split('/')),
{ recursive: true, force: true },
);
const missingBundledBrace = run();
expect(missingBundledBrace.status).toBe(1);
expect(missingBundledBrace.stderr).toContain('found missing');
} finally {
fs.rmSync(fixture, { recursive: true, force: true });
}
});
it('sidecar resource preflight uses bundled runtime probes instead of checker-host ABI', () => {
const script = fs.readFileSync(
path.join(ROOT, 'scripts', 'check-sidecar-resources.mjs'),
'utf-8',
);
expect(script).not.toContain('const currentAbi = process.versions.modules');
expect(script).not.toContain('does not match current Node ABI');
expect(script).toContain('execFileSync(nodePath');
expect(script).toContain('const database = new Database');
expect(script).toContain('SELECT 1 AS ok');
expect(script).toContain('SELECT vec_version() AS version');
expect(script).toContain('const onnx = require(process.argv[4])');
expect(script).toContain('const { RawImage } = require(process.argv[1])');
expect(script).toContain('image.toSharp().resize(1, 1).png().toBuffer()');
expect(script).toContain('Buffer.from([137,80,78,71,13,10,26,10])');
expect(script).toContain('sharp.versions?.emscripten');
expect(script).toContain('if (process.argv[3]) require(process.argv[3])');
expect(script).toContain('process.arch !== process.argv[2]');
});
it.runIf(process.platform === 'win32')(
'Sharp 0.35.3 works through the Transformers RawImage consumer',
() => {
const probe = [
'const { RawImage } = require("@huggingface/transformers");',
'const sharp = require("sharp");',
'if (sharp.versions?.emscripten) throw new Error("Sharp fell back to WASM");',
'const image = new RawImage(',
'Uint8Array.from([255,0,0,255,0,255,0,255,0,0,255,255,255,255,255,255]),',
'2,2,4);',
'void (async () => {',
'const buffer = await image.toSharp().resize(1,1).png().toBuffer();',
'const signature = Buffer.from([137,80,78,71,13,10,26,10]);',
'if (!buffer.subarray(0,8).equals(signature)) throw new Error("invalid PNG");',
'process.stdout.write(JSON.stringify({ bytes: buffer.length }));',
'})().catch((error) => { console.error(error); process.exit(1); });',
].join('');
const result = spawnSync(process.execPath, ['-e', probe], {
cwd: ROOT,
encoding: 'utf-8',
timeout: 30_000,
windowsHide: true,
});
expect(result.status, result.stderr).toBe(0);
expect(JSON.parse(result.stdout)).toMatchObject({
bytes: expect.any(Number),
});
},
);
it('native bundling is fatal on missing payloads and validates target Mach-O architecture', () => {
const script = fs.readFileSync(
path.join(ROOT, 'scripts', 'bundle-native-deps.mjs'),
'utf-8',
);
expect(script).toContain("execFileSync('/usr/bin/lipo'");
expect(script).toContain('required native dependency');
expect(script).toContain('sqlite-vec-${vecOs}-${arch}');
expect(script).not.toContain("arch === 'arm64' ? 'aarch64'");
});
it.runIf(process.platform === 'win32')(
'sidecar resource preflight rejects missing Windows runtimes and sidecar source artifacts',
async () => {
const fixtureRoot = fs.mkdtempSync(
path.join(os.tmpdir(), 'waggle-sidecar-preflight-'),
);
const fixtureScripts = path.join(fixtureRoot, 'scripts');
const fixtureResources = path.join(fixtureRoot, 'app', 'src-tauri', 'resources');
const fixtureChecker = path.join(fixtureScripts, 'check-sidecar-resources.mjs');
const requiredNativeFiles = [
'better_sqlite3.node',
'vec0.dll',
'onnxruntime/onnxruntime_binding.node',
];
const stagedRuntimeFiles = [
'@waggle/hive-mind-core/dist/index.js',
'@waggle/hive-mind-cli/dist/index.js',
'@waggle/hive-mind-hooks-claude-code/dist/bin/claude-code-hooks-cli.js',
'@waggle/hive-mind-hooks-claude-desktop/dist/bin/claude-desktop-hooks.js',
'@waggle/hive-mind-hooks-codex/dist/bin/codex-hooks.js',
'@waggle/hive-mind-hooks-codex-desktop/dist/bin/codex-desktop-hooks.js',
'@waggle/hive-mind-hooks-cursor/dist/bin/cursor-hooks.js',
'@waggle/hive-mind-hooks-hermes/dist/bin/hermes-hooks.js',
'@waggle/hive-mind-hooks-openclaw/dist/bin/openclaw-hooks.js',
'@waggle/hive-mind-hooks-openclaw/dist/handler.bundle.cjs',
'waggle-memory-mcp/dist/index.js',
'waggle-test-runtime/dist/index.js',
];
const writeFixtureFile = (base: string, relative: string, content = '') => {
const target = path.join(base, ...relative.split('/'));
fs.mkdirSync(path.dirname(target), { recursive: true });
fs.writeFileSync(target, content, 'utf-8');
return target;
};
const runFixtureGit = (args: string[]) => {
const result = spawnSync('git', args, {
cwd: fixtureRoot,
encoding: 'utf-8',
timeout: 30_000,
windowsHide: true,
});
expect(result.status, result.stderr || result.stdout).toBe(0);
return result.stdout.trim();
};
try {
fs.mkdirSync(fixtureScripts, { recursive: true });
fs.mkdirSync(fixtureResources, { recursive: true });
fs.copyFileSync(
path.join(ROOT, 'scripts', 'check-sidecar-resources.mjs'),
fixtureChecker,
);
const fixtureNode = path.join(fixtureResources, 'node.exe');
// A hardlink shares the running Vitest executable's Windows image lock,
// so fixture cleanup cannot delete it until the parent test process exits.
fs.copyFileSync(process.execPath, fixtureNode);
let fixtureSourceRevision = 'a'.repeat(40);
const fixtureSourceContents = new Map<string, string>([
['package-lock.json', '{"lockfileVersion":3}\n'],
['package.json', '{"name":"waggle-sidecar-fixture"}\n'],
['packages/server/package.json', '{"name":"@waggle/server"}\n'],
['packages/server/src/local/service.ts', 'export const fixture = true;\n'],
['packages/server/tsconfig.json', '{"extends":"../../tsconfig.base.json"}\n'],
['scripts/build-sidecar.mjs', 'export {};\n'],
['tsconfig.base.json', '{"compilerOptions":{"target":"ES2022"}}\n'],
]);
for (const [relative, content] of fixtureSourceContents) {
writeFixtureFile(fixtureRoot, relative, content);
}
const fixtureSourceInputs = [...fixtureSourceContents.entries()]
.map(([relative, content]) => ({
path: relative,
sha256: createHash('sha256').update(content).digest('hex'),
}))
.sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0);
const fixtureServicePayload = Buffer.from('console.log("sidecar");\n', 'utf8');
const fixtureServiceProvenance = {
schemaVersion: 1,
sourceRevision: fixtureSourceRevision,
entryPoint: 'packages/server/src/local/service.ts',
sourceInputs: fixtureSourceInputs,
bundlePayload: {
sizeBytes: fixtureServicePayload.byteLength,
sha256: createHash('sha256').update(fixtureServicePayload).digest('hex'),
},
};
let certifiedFixtureService = Buffer.concat([
Buffer.from(
`// Waggle-Sidecar-Provenance: ${Buffer.from(JSON.stringify(fixtureServiceProvenance)).toString('base64')}\n`,
'utf8',
),
fixtureServicePayload,
]);
const fixtureServicePath = path.join(fixtureResources, 'service.js');
fs.writeFileSync(fixtureServicePath, certifiedFixtureService);
const fixtureMarketplaceSource = path.join(
fixtureRoot,
'packages',
'marketplace',
'marketplace.db',
);
fs.mkdirSync(path.dirname(fixtureMarketplaceSource), { recursive: true });
const fixtureMarketplace = new Database(fixtureMarketplaceSource);
fixtureMarketplace.pragma('journal_mode = WAL');
fixtureMarketplace.exec(`
CREATE TABLE sources (id INTEGER PRIMARY KEY, name TEXT NOT NULL);
CREATE TABLE packages (id INTEGER PRIMARY KEY, source_id INTEGER, name TEXT NOT NULL);
INSERT INTO sources (id, name) VALUES (1, 'mcp_registry');
INSERT INTO packages (id, source_id, name) VALUES (1, 1, 'memory');
`);
fixtureMarketplace.pragma('wal_checkpoint(TRUNCATE)');
fixtureMarketplace.close();
const fixtureMarketplaceResource = path.join(fixtureResources, 'marketplace.db');
fs.copyFileSync(fixtureMarketplaceSource, fixtureMarketplaceResource);
runFixtureGit(['init']);
runFixtureGit(['config', 'user.email', 'sidecar-preflight@waggle.invalid']);
runFixtureGit(['config', 'user.name', 'Waggle Fixture']);
runFixtureGit([
'add',
'--',
'scripts/check-sidecar-resources.mjs',
...fixtureSourceContents.keys(),
'packages/marketplace/marketplace.db',
]);
runFixtureGit(['commit', '-m', 'fixture']);
fixtureSourceRevision = runFixtureGit(['rev-parse', 'HEAD']).toLowerCase();
fixtureServiceProvenance.sourceRevision = fixtureSourceRevision;
certifiedFixtureService = Buffer.concat([
Buffer.from(
`// Waggle-Sidecar-Provenance: ${Buffer.from(JSON.stringify(fixtureServiceProvenance)).toString('base64')}\n`,
'utf8',
),
fixtureServicePayload,
]);
fs.writeFileSync(fixtureServicePath, certifiedFixtureService);
const fixtureNpmVersion = '0.0.0-fixture';
const fixtureNpmRuntimeRoot = 'node_modules/waggle-node-runtime';
const fixtureNpmCli = `process.stdout.write(${JSON.stringify(fixtureNpmVersion)} + '\\n');\n`;
const fixtureNpmWrapper = (cli: 'npm' | 'npx') => [
'@ECHO OFF',
'SETLOCAL',
'SET "NODE_EXE=%~dp0\\..\\..\\..\\node.exe"',
`SET "NPM_CLI_JS=%~dp0\\..\\node_modules\\npm\\bin\\${cli}-cli.js"`,
'"%NODE_EXE%" "%NPM_CLI_JS%" %*',
'EXIT /B %ERRORLEVEL%',
'',
].join('\r\n');
writeFixtureFile(
fixtureResources,
`${fixtureNpmRuntimeRoot}/package.json`,
JSON.stringify({
name: 'waggle-node-runtime',
private: true,
version: process.versions.node,
}),
);
writeFixtureFile(fixtureResources, `${fixtureNpmRuntimeRoot}/NODE-LICENSE`, 'Node license');
writeFixtureFile(
fixtureResources,
`${fixtureNpmRuntimeRoot}/node_modules/npm/package.json`,
JSON.stringify({ name: 'npm', version: fixtureNpmVersion }),
);
writeFixtureFile(
fixtureResources,
`${fixtureNpmRuntimeRoot}/node_modules/npm/node_modules/brace-expansion/package.json`,
JSON.stringify({ name: 'brace-expansion', version: '2.1.4' }),
);
writeFixtureFile(
fixtureResources,
`${fixtureNpmRuntimeRoot}/node_modules/npm/LICENSE`,
'npm license',
);
writeFixtureFile(
fixtureResources,
`${fixtureNpmRuntimeRoot}/node_modules/npm/bin/npm-cli.js`,
fixtureNpmCli,
);
writeFixtureFile(
fixtureResources,
`${fixtureNpmRuntimeRoot}/node_modules/npm/bin/npx-cli.js`,
fixtureNpmCli,
);
writeFixtureFile(
fixtureResources,
`${fixtureNpmRuntimeRoot}/bin/npm.cmd`,
fixtureNpmWrapper('npm'),
);
writeFixtureFile(
fixtureResources,
`${fixtureNpmRuntimeRoot}/bin/npx.cmd`,
fixtureNpmWrapper('npx'),
);
const installedBetterSqlite = path.join(ROOT, 'node_modules', 'better-sqlite3');
const fixtureBetterSqlite = path.join(fixtureResources, 'node_modules', 'better-sqlite3');
fs.mkdirSync(path.dirname(fixtureBetterSqlite), { recursive: true });
fs.cpSync(installedBetterSqlite, fixtureBetterSqlite, { recursive: true });
for (const packageName of ['bindings', 'file-uri-to-path']) {
fs.cpSync(
path.join(ROOT, 'node_modules', packageName),
path.join(fixtureResources, 'node_modules', packageName),
{ recursive: true },
);
}
const installedBinding = path.join(installedBetterSqlite, 'build', 'Release', 'better_sqlite3.node');
const installedVec = path.join(ROOT, 'node_modules', 'sqlite-vec-windows-x64', 'vec0.dll');
const installedOnnx = path.join(ROOT, 'node_modules', 'onnxruntime-node');
const fixtureOnnx = path.join(fixtureResources, 'node_modules', 'onnxruntime-node');
fs.mkdirSync(fixtureOnnx, { recursive: true });
fs.copyFileSync(path.join(installedOnnx, 'package.json'), path.join(fixtureOnnx, 'package.json'));
fs.cpSync(path.join(installedOnnx, 'dist'), path.join(fixtureOnnx, 'dist'), { recursive: true });
const installedOnnxBin = path.join(installedOnnx, 'bin', 'napi-v3', 'win32', 'x64');
const fixtureOnnxBin = path.join(fixtureOnnx, 'bin', 'napi-v3', 'win32', 'x64');
fs.cpSync(installedOnnxBin, fixtureOnnxBin, { recursive: true });
fs.cpSync(
path.join(ROOT, 'node_modules', 'onnxruntime-common'),
path.join(fixtureResources, 'node_modules', 'onnxruntime-common'),
{ recursive: true },
);
const installedOnnxBinding = path.join(installedOnnxBin, 'onnxruntime_binding.node');
const fixtureTransformers = path.join(
fixtureResources,
'node_modules',
'@huggingface',
'transformers',
);
writeFixtureFile(
path.join(fixtureResources, 'node_modules'),
'sharp/package.json',
JSON.stringify({ name: 'sharp', version: '0.35.3', main: 'index.cjs' }),
);
writeFixtureFile(
path.join(fixtureResources, 'node_modules'),
'sharp/index.cjs',
'module.exports = { versions: { sharp: "0.35.3", vips: "8.18.3" } };',
);
writeFixtureFile(
path.join(fixtureResources, 'node_modules'),
'@img/sharp-win32-x64/package.json',
JSON.stringify({ name: '@img/sharp-win32-x64', version: '0.35.3' }),
);
fs.cpSync(
path.join(ROOT, 'node_modules', '@img', 'sharp-win32-x64', 'lib'),
path.join(
fixtureResources,
'node_modules',
'@img',
'sharp-win32-x64',
'lib',
),
{ recursive: true },
);
const stagedSharpBinding = path.join(
fixtureResources,
'node_modules',
'@img',
'sharp-win32-x64',
'lib',
'sharp-win32-x64-0.35.3.node',
);
writeFixtureFile(
path.join(fixtureResources, 'node_modules'),
'@huggingface/transformers/package.json',
JSON.stringify({ name: '@huggingface/transformers', version: '3.8.1' }),
);
writeFixtureFile(
path.join(fixtureResources, 'node_modules'),
'@huggingface/transformers/dist/transformers.node.cjs',
[
'class RawImage {',
'toSharp() {',
'return {',
'resize() { return this; },',
'png() { return this; },',
'async toBuffer() {',
'return Buffer.from([137,80,78,71,13,10,26,10,0]);',
'},',
'};',
'}',
'}',
'module.exports = { RawImage };',
].join(''),
);
for (const entry of requiredNativeFiles) {
const target = writeFixtureFile(path.join(fixtureResources, 'native'), entry);
if (entry === 'better_sqlite3.node') fs.copyFileSync(installedBinding, target);
if (entry === 'vec0.dll') fs.copyFileSync(installedVec, target);
if (entry === 'onnxruntime/onnxruntime_binding.node') fs.copyFileSync(installedOnnxBinding, target);
}
for (const entry of stagedRuntimeFiles) {
writeFixtureFile(
path.join(fixtureResources, 'node_modules'),
entry,
entry.endsWith('package.json') ? '{}' : '',
);
}
const stagedPackageNames = new Set(stagedRuntimeFiles.map((entry) => {
const parts = entry.split('/');
return entry.startsWith('@') ? `${parts[0]}/${parts[1]}` : parts[0];
}));
for (const name of stagedPackageNames) {
writeFixtureFile(
path.join(fixtureResources, 'node_modules'),
`${name}/package.json`,
JSON.stringify({ name }),
);
}
writeFixtureFile(
fixtureRoot,
'packages/test-runtime/package.json',
JSON.stringify({ name: 'waggle-test-runtime' }),
);
writeFixtureFile(
path.join(fixtureResources, 'node_modules'),
'waggle-test-runtime/package.json',
JSON.stringify({ name: 'waggle-test-runtime', main: 'dist/index.js' }),
);
const coreManifestPath = path.join(
fixtureResources,
'node_modules',
'@waggle',
'hive-mind-core',
'package.json',
);
const coreDistEntry = path.join(
fixtureResources,
'node_modules',
'@waggle',
'hive-mind-core',
'dist',
'index.js',
);
const writeCoreManifest = (main: string, exports?: Record<string, unknown>) => {
fs.writeFileSync(
coreManifestPath,
JSON.stringify({
name: '@waggle/hive-mind-core',
main,
...(exports === undefined ? {} : { exports }),
}),
'utf-8',
);
};
writeCoreManifest('dist/index.js');
const runChecker = async (
{
runtimeProbe = 'none',
expectedSourceRevision = fixtureSourceRevision,
}: {
runtimeProbe?: 'none' | 'all' | 'marketplace' | 'native' | 'image';
expectedSourceRevision?: string;
} = {},
) => {
const hiddenFiles: Array<{ hidden: string; target: string }> = [];
const hideFixtureFile = (target: string) => {
const hidden = `${target}.fixture-disabled`;
fs.renameSync(target, hidden);
hiddenFiles.push({ hidden, target });
};
try {
// Structural rejection cases should not repeat unrelated native, npm,
// marketplace, and image probes. Probe-specific cases keep the bundled
// runtime but hide inputs for every other expensive probe.
if (runtimeProbe === 'none') {
hideFixtureFile(fixtureNode);
} else if (runtimeProbe !== 'all') {
hideFixtureFile(path.join(
fixtureResources,
...`${fixtureNpmRuntimeRoot}/package.json`.split('/'),
));
if (runtimeProbe !== 'marketplace') hideFixtureFile(fixtureMarketplaceResource);
if (runtimeProbe !== 'native') {
hideFixtureFile(path.join(fixtureOnnx, 'package.json'));
}
if (runtimeProbe !== 'image') hideFixtureFile(stagedSharpBinding);
}
const result = await new Promise<{
status: number | null;
stdout: string;
stderr: string;
error?: Error;
}>((resolve) => {
execFile(
process.execPath,
[fixtureChecker, '--expected-source-revision', expectedSourceRevision],
{
encoding: 'utf-8',
timeout: 60_000,
windowsHide: true,
},
(error, stdout, stderr) => {
if (!error) {
resolve({ status: 0, stdout, stderr });
return;
}
if (
typeof error.code === 'number'
&& !error.killed
&& (error.signal === null || error.signal === undefined)
) {
resolve({ status: error.code, stdout, stderr });
return;
}
resolve({ status: null, stdout, stderr, error });
},
);
});
if (result.error) throw result.error;
return result;
} finally {
for (const file of hiddenFiles.reverse()) {
fs.renameSync(file.hidden, file.target);
}
}
};
const fixtureMarketplaceBeforeProbe = fs.readFileSync(fixtureMarketplaceResource);
const baselineResult = await runChecker({ runtimeProbe: 'all' });
expect(
baselineResult.status,
baselineResult.stderr || baselineResult.stdout,
).toBe(0);
expect(fs.readFileSync(fixtureMarketplaceResource)).toEqual(fixtureMarketplaceBeforeProbe);
fs.appendFileSync(fixtureMarketplaceSource, 'dirty worktree database');
fs.copyFileSync(fixtureMarketplaceSource, fixtureMarketplaceResource);
const dirtyMarketplaceResult = await runChecker();
expect(dirtyMarketplaceResult.status).toBe(1);
expect(dirtyMarketplaceResult.stderr).toContain(
'canonical marketplace database does not match exact source revision',
);
fs.writeFileSync(fixtureMarketplaceSource, fixtureMarketplaceBeforeProbe);
fs.writeFileSync(fixtureMarketplaceResource, fixtureMarketplaceBeforeProbe);
fs.appendFileSync(fixtureServicePath, '// stale payload\n');
const staleServiceResult = await runChecker();
expect(staleServiceResult.status).toBe(1);
expect(staleServiceResult.stderr).toContain(
'resources/service.js payload does not match embedded provenance',
);
fs.writeFileSync(fixtureServicePath, certifiedFixtureService);
const fixtureEntryPoint = path.join(
fixtureRoot,
'packages',
'server',
'src',
'local',
'service.ts',
);
fs.appendFileSync(fixtureEntryPoint, '// stale source\n');
const staleSourceResult = await runChecker();
expect(staleSourceResult.status).toBe(1);
expect(staleSourceResult.stderr).toContain(
'resources/service.js source input hash does not match current source',
);
fs.writeFileSync(
fixtureEntryPoint,
fixtureSourceContents.get('packages/server/src/local/service.ts')!,
'utf8',
);
const fixtureTsconfig = path.join(fixtureRoot, 'packages', 'server', 'tsconfig.json');
fs.appendFileSync(fixtureTsconfig, '// stale transform config\n');
const staleConfigResult = await runChecker();
expect(staleConfigResult.status).toBe(1);
expect(staleConfigResult.stderr).toContain(
'resources/service.js source input hash does not match current source',
);
fs.writeFileSync(
fixtureTsconfig,
fixtureSourceContents.get('packages/server/tsconfig.json')!,
'utf8',
);
const staleRevisionResult = await runChecker({
expectedSourceRevision: 'b'.repeat(40),
});
expect(staleRevisionResult.status).toBe(1);
expect(staleRevisionResult.stderr).toContain(
'resources/service.js source revision does not match expected revision',
);
const nestedResourceDb = path.join(
fixtureResources,
'node_modules',
'fixture-package',
'state',
'cache.DB',
);
fs.mkdirSync(path.dirname(nestedResourceDb), { recursive: true });
const staleSidecars: Array<{
path: string;
label: string;
diagnostic: string;
suffix: string;
}> = [];
for (const target of [
{
path: fixtureMarketplaceResource,
label: 'resources/marketplace.db',
diagnostic: 'must not be packaged',
},
{
path: fixtureMarketplaceSource,
label: 'packages/marketplace/marketplace.db',
diagnostic: 'must not be present while staging',
},
{
path: nestedResourceDb,
label: 'resources/node_modules/fixture-package/state/cache.DB',
diagnostic: 'must not be packaged',
},
]) {
for (const suffix of ['-wal', '-shm', '-journal']) {
expect(fs.existsSync(`${target.path}${suffix}`)).toBe(false);
fs.writeFileSync(`${target.path}${suffix}`, 'stale SQLite sidecar');
staleSidecars.push({ ...target, suffix });
}
}
const staleSidecarResult = await runChecker();
expect(staleSidecarResult.status).toBe(1);
for (const target of staleSidecars) {
expect(staleSidecarResult.stderr).toContain(
`${target.label}${target.suffix} ${target.diagnostic}`,
);
fs.rmSync(`${target.path}${target.suffix}`);
}
const fixtureMarketplaceContent = fs.readFileSync(fixtureMarketplaceResource);
fs.rmSync(fixtureMarketplaceResource);
const missingMarketplaceResult = await runChecker();
expect(missingMarketplaceResult.status).toBe(1);
expect(missingMarketplaceResult.stderr).toContain('resources/marketplace.db');
fs.writeFileSync(fixtureMarketplaceResource, fixtureMarketplaceContent);
fs.appendFileSync(fixtureMarketplaceResource, 'tampered');
const mismatchedMarketplaceResult = await runChecker();
expect(mismatchedMarketplaceResult.status).toBe(1);
expect(mismatchedMarketplaceResult.stderr).toContain(
'resources/marketplace.db does not match the canonical marketplace database',
);
fs.writeFileSync(fixtureMarketplaceResource, fixtureMarketplaceContent);
const fixtureMarketplaceSourceContent = fs.readFileSync(fixtureMarketplaceSource);
fs.writeFileSync(fixtureMarketplaceSource, 'not a SQLite database');
fs.writeFileSync(fixtureMarketplaceResource, 'not a SQLite database');
const invalidMarketplaceResult = await runChecker({ runtimeProbe: 'marketplace' });
expect(invalidMarketplaceResult.status).toBe(1);
expect(invalidMarketplaceResult.stderr).toContain(
'resources/marketplace.db failed its SQLite integrity/schema probe',
);
fs.writeFileSync(fixtureMarketplaceSource, fixtureMarketplaceSourceContent);
fs.writeFileSync(fixtureMarketplaceResource, fixtureMarketplaceContent);
const fixtureNpmRuntimeManifest = path.join(
fixtureResources,
...`${fixtureNpmRuntimeRoot}/package.json`.split('/'),
);
const fixtureNpmRuntimeManifestContent = fs.readFileSync(fixtureNpmRuntimeManifest);
fs.rmSync(fixtureNpmRuntimeManifest);
const missingNpmRuntimeResult = await runChecker();
expect(missingNpmRuntimeResult.status).toBe(1);
expect(missingNpmRuntimeResult.stderr).toContain(
'resources/node_modules/waggle-node-runtime/package.json',
);
fs.writeFileSync(fixtureNpmRuntimeManifest, fixtureNpmRuntimeManifestContent);
const stagedBinding = path.join(
fixtureBetterSqlite,
'build',
'Release',
'better_sqlite3.node',
);
const stagedOnnxBinding = path.join(fixtureOnnxBin, 'onnxruntime_binding.node');
const fixtureVec = path.join(fixtureResources, 'native', 'vec0.dll');
for (const target of [stagedBinding, stagedOnnxBinding, fixtureVec]) {
const original = fs.readFileSync(target);
fs.writeFileSync(target, 'not a native payload');
const invalidRuntimeResult = await runChecker({ runtimeProbe: 'native' });
expect(invalidRuntimeResult.status).toBe(1);
expect(invalidRuntimeResult.stderr).toContain('resources native runtime probe failed');
fs.writeFileSync(target, original);
}
const stagedSharpBindingContent = fs.readFileSync(stagedSharpBinding);
fs.writeFileSync(stagedSharpBinding, 'not a native payload');
const invalidImageRuntimeResult = await runChecker({ runtimeProbe: 'image' });
expect(invalidImageRuntimeResult.status).toBe(1);
expect(invalidImageRuntimeResult.stderr).toContain('resources image runtime probe failed');
fs.writeFileSync(stagedSharpBinding, stagedSharpBindingContent);
const imageDependencyTargets = [
{
manifest: path.join(fixtureResources, 'node_modules', 'sharp', 'package.json'),
diagnostic: 'resources/node_modules/sharp',
},
{
manifest: path.join(fixtureTransformers, 'package.json'),
diagnostic: 'resources/node_modules/@huggingface/transformers',
},
].map((target) => ({
...target,
content: fs.readFileSync(target.manifest),
}));
for (const target of imageDependencyTargets) {
fs.rmSync(target.manifest);
}
const missingImageDependencyResult = await runChecker();
expect(missingImageDependencyResult.status).toBe(1);
for (const target of imageDependencyTargets) {
expect(missingImageDependencyResult.stderr).toContain(target.diagnostic);
fs.writeFileSync(target.manifest, target.content);
}
const missingNativeTargets = requiredNativeFiles.map((entry) => {
const target = path.join(
fixtureResources,
'native',
...entry.split('/'),
);
return { entry, target, original: fs.readFileSync(target) };
});
for (const target of missingNativeTargets) {
fs.rmSync(target.target);
}
const missingNativeResult = await runChecker();
expect(missingNativeResult.status).toBe(1);
for (const target of missingNativeTargets) {
expect(missingNativeResult.stderr).toContain(`resources/native/${target.entry}`);
fs.writeFileSync(target.target, target.original);
}
const serviceMapPath = writeFixtureFile(
fixtureResources,
'service.js.map',
JSON.stringify({ sourcesContent: ['private TypeScript source'] }),
);
writeFixtureFile(
path.join(fixtureResources, 'node_modules'),
'@waggle/hive-mind-core/src/evolution-runs.ts',
'export const proprietary = true;\n',
);
const hiveSourceDir = path.join(
fixtureResources,
'node_modules',
'@waggle',
'hive-mind-core',
'src',
);
writeFixtureFile(
path.join(fixtureResources, 'node_modules'),
'waggle-test-runtime/src/private.ts',
'export const privateSource = true;\n',
);
const unscopedSourceDir = path.join(
fixtureResources,
'node_modules',
'waggle-test-runtime',
'src',
);
writeFixtureFile(
path.join(fixtureResources, 'node_modules'),
'vendor/node_modules/@waggle/shared/package.json',
JSON.stringify({ name: '@waggle/shared' }),
);
writeFixtureFile(
path.join(fixtureResources, 'node_modules'),
'vendor/node_modules/@waggle/shared/src/private.ts',
'export const privateSource = true;\n',
);
const nestedVendorDir = path.join(
fixtureResources,
'node_modules',
'vendor',
);
const firstPartyReadme = writeFixtureFile(
path.join(fixtureResources, 'node_modules'),
'@waggle/hive-mind-core/README.md',
'internal package documentation\n',
);
const disallowedPayloadResult = await runChecker();
expect(disallowedPayloadResult.status).toBe(1);
for (const diagnostic of [
'resources/service.js.map must not be packaged',
'resources/node_modules/@waggle/hive-mind-core/src/evolution-runs.ts must not be packaged',
'resources/node_modules/waggle-test-runtime/src/private.ts must not be packaged',
'resources/node_modules/vendor/node_modules/@waggle/shared/src/private.ts must not be packaged',
'resources/node_modules/@waggle/hive-mind-core/README.md is not a runtime package entry',
]) {
expect(disallowedPayloadResult.stderr).toContain(diagnostic);
}
fs.rmSync(serviceMapPath);
fs.rmSync(hiveSourceDir, { recursive: true });
fs.rmSync(unscopedSourceDir, { recursive: true });
fs.rmSync(nestedVendorDir, { recursive: true });
fs.rmSync(firstPartyReadme);
writeFixtureFile(
path.join(fixtureResources, 'node_modules'),
'@waggle/missing-manifest/dist/index.js',
'export {};\n',
);
const missingManifestDir = path.join(
fixtureResources,
'node_modules',
'@waggle',
'missing-manifest',
);
writeFixtureFile(
path.join(fixtureResources, 'node_modules'),
'@waggle/malformed-manifest/package.json',
'{',
);
const malformedManifestDir = path.join(
fixtureResources,
'node_modules',
'@waggle',
'malformed-manifest',
);
const invalidManifestResult = await runChecker();
expect(invalidManifestResult.status).toBe(1);
expect(invalidManifestResult.stderr).toContain(
'resources/node_modules/@waggle/missing-manifest/package.json is missing or invalid',
);
expect(invalidManifestResult.stderr).toContain(
'resources/node_modules/@waggle/malformed-manifest/package.json is missing or invalid',
);
fs.rmSync(missingManifestDir, { recursive: true });
fs.rmSync(malformedManifestDir, { recursive: true });
writeCoreManifest('dist/../package.json');
const traversalTargetResult = await runChecker();
expect(traversalTargetResult.status).toBe(1);
expect(traversalTargetResult.stderr).toContain(
'has an invalid or missing runtime target: dist/../package.json',
);
const runtimeDirectory = path.join(
fixtureResources,
'node_modules',
'@waggle',
'hive-mind-core',
'dist',
'runtime-directory',
);
fs.mkdirSync(runtimeDirectory, { recursive: true });
writeCoreManifest('dist/runtime-directory');
const directoryTargetResult = await runChecker();
expect(directoryTargetResult.status).toBe(1);
expect(directoryTargetResult.stderr).toContain(
'has an invalid or missing runtime target: dist/runtime-directory',
);
fs.rmSync(runtimeDirectory, { recursive: true });
const coreDistDir = path.dirname(coreDistEntry);
const outsideDistDir = path.join(fixtureRoot, 'outside-runtime-dist');
writeFixtureFile(outsideDistDir, 'index.js', 'export {};\n');
fs.rmSync(coreDistDir, { recursive: true });
fs.symlinkSync(outsideDistDir, coreDistDir, 'junction');
writeCoreManifest('dist/index.js');
const junctionTargetResult = await runChecker();
expect(junctionTargetResult.status).toBe(1);
expect(junctionTargetResult.stderr).toContain(
'has an invalid or missing runtime target: dist/index.js',
);
fs.rmSync(coreDistDir, { recursive: true });
fs.mkdirSync(coreDistDir, { recursive: true });
fs.writeFileSync(coreDistEntry, 'export {};\n', 'utf-8');
writeCoreManifest('dist/index.js', {
'.': {
types: './dist/index.d.ts',
import: './dist/index.js',
},
});
expect((await runChecker({ runtimeProbe: 'all' })).status).toBe(0);
fs.writeFileSync(
coreDistEntry,
'export {};\n//# sourceMappingURL=index.js.map\n',
'utf-8',
);
fs.writeFileSync(
path.join(fixtureResources, 'service.js'),
'console.log("sidecar");\n//# sourceMappingURL=data:application/json;base64,e30=\n',
'utf-8',
);
const inlineMapResult = await runChecker();
expect(inlineMapResult.status).toBe(1);
expect(inlineMapResult.stderr).toContain(
'resources/node_modules/@waggle/hive-mind-core/dist/index.js contains a sourceMappingURL directive',
);
expect(inlineMapResult.stderr).toContain(
'resources/service.js contains a sourceMappingURL directive',
);
} finally {
fs.rmSync(fixtureRoot, { recursive: true, force: true });
}
},
180_000,
);
it('staged sidecar resources have Windows MSI codepage-safe relative paths', () => {
// WiX 3 links the en-US MSI with codepage 1252. Dependency test fixtures
// with paths such as "snowman" Unicode names must be pruned before MSI
// bundling or light.exe fails after the Rust build has already succeeded.
const resources = path.join(TAURI_DIR, 'resources');
const unsafe = listFiles(resources)
.map((file) => path.relative(resources, file))
.filter((file) => !isWindows1252PathSafe(file));
expect(unsafe).toEqual([]);
});
it('staged sidecar node_modules is self-contained after MSI extraction', () => {
// Running from app/src-tauri/resources can accidentally resolve missing
// packages from the repo root node_modules. The installed MSI layout cannot.
const resources = path.join(TAURI_DIR, 'resources');
const nodeModules = path.join(resources, 'node_modules');
const missing: string[] = [];
for (const packageDir of listPackageDirs(nodeModules)) {
const manifest = JSON.parse(
fs.readFileSync(path.join(packageDir, 'package.json'), 'utf-8'),
) as { name?: string; dependencies?: Record<string, string> };
for (const dep of Object.keys(manifest.dependencies ?? {})) {
if (STAGED_DEPENDENCY_ALLOWLIST.has(dep)) continue;
if (!resolveWithinStagedResources(packageDir, dep, resources)) {
missing.push(`${path.relative(nodeModules, packageDir)} -> ${dep}`);
}
}
}
expect(missing).toEqual([]);
});
it('stages the patched archive parser required by dynamic sidecar imports', () => {
const stageScript = fs.readFileSync(
path.join(ROOT, 'scripts', 'stage-sidecar-deps.mjs'),
'utf-8',
);
expect(stageScript).toContain("const DYNAMIC_RUNTIME_ROOTS = new Set(['adm-zip']);");
expect(stageScript).toContain('adm-zip runtime root must be version 0.6.0 or newer');
const stagedManifest = path.join(
TAURI_DIR,
'resources',
'node_modules',
'adm-zip',
'package.json',
);
if (!fs.existsSync(path.join(TAURI_DIR, 'resources', 'node_modules'))) return;
expect(fs.existsSync(stagedManifest)).toBe(true);
const { version } = JSON.parse(fs.readFileSync(stagedManifest, 'utf-8')) as {
version: string;
};
const [major, minor] = version.split('.').map(Number);
expect(major > 0 || minor >= 6).toBe(true);
});
it.runIf(fs.existsSync(path.join(TAURI_DIR, 'resources', 'node_modules')))(
'stages only runtime payloads for first-party packages',
() => {
const resources = path.join(TAURI_DIR, 'resources');
const nodeModules = path.join(resources, 'node_modules');
const firstPartyRoot = path.join(resources, 'node_modules', '@waggle');
const firstPartyPackageDirs = new Set<string>();
const workspacePackageNames = localWorkspacePackageNames();
const unexpected: string[] = [];
if (fs.existsSync(firstPartyRoot)) {
for (const packageEntry of fs.readdirSync(firstPartyRoot, { withFileTypes: true })) {
if (packageEntry.isDirectory()) {
firstPartyPackageDirs.add(path.join(firstPartyRoot, packageEntry.name));
}
}
}
for (const name of workspacePackageNames) {
const directPackageDir = path.join(nodeModules, ...name.split('/'));
if (fs.existsSync(directPackageDir)) firstPartyPackageDirs.add(directPackageDir);
}
for (const packageDir of listPackageDirs(nodeModules)) {
try {
const manifest = JSON.parse(
fs.readFileSync(path.join(packageDir, 'package.json'), 'utf-8'),
) as { name?: unknown };
if (
typeof manifest.name === 'string'
&& (manifest.name.startsWith('@waggle/') || workspacePackageNames.has(manifest.name))
) {
firstPartyPackageDirs.add(packageDir);
}
} catch {
// The executable checker reports malformed first-party manifests.
}
}
for (const packageDir of firstPartyPackageDirs) {
for (const entry of fs.readdirSync(packageDir, { withFileTypes: true })) {
if (!FIRST_PARTY_RUNTIME_ENTRIES.has(entry.name)) {
unexpected.push(path.relative(resources, path.join(packageDir, entry.name)));
}
}
for (const file of listFiles(packageDir)) {
if (SOURCE_ARTIFACT_PATTERN.test(file)) {
unexpected.push(path.relative(resources, file));
}
if (
/\.(?:[cm]?js)$/i.test(file)
&& /(?:\/\/|\/\*)[#@]\s*sourceMappingURL\s*=/.test(fs.readFileSync(file, 'utf-8'))
) {
unexpected.push(`${path.relative(resources, file)} -> sourceMappingURL`);
}
}
}
expect(unexpected).toEqual([]);
},
);
});
describe('CI/CD Configuration', () => {
it('bounds the broad root Vitest lane to two workers', () => {
const workflow = parseYaml(
fs.readFileSync(path.join(ROOT, '.github', 'workflows', 'ci.yml'), 'utf-8'),
) as {
jobs?: Record<string, { steps?: Array<{ name?: string; run?: string }> }>;
};
const steps = workflow.jobs?.test?.steps ?? [];
const matches = steps.filter(
(step) => step.name === 'Unit tests — packages + cross-cutting (root vitest)',
);
expect(matches).toHaveLength(1);
const run = matches[0]?.run ?? '';
const workerValues = [
...run.matchAll(/--maxWorkers(?:=|\s+)([^\s\\]+)/g),
].map((match) => match[1]);
expect(workerValues).toEqual(['2']);
expect(run).not.toContain('--no-file-parallelism');
expect(run).not.toMatch(/--fileParallelism(?:=|\s+)false\b/);
});
it('keeps Intel macOS PR verification app-only while retaining DMG release coverage', () => {
type MacJob = {
strategy?: {
matrix?: {
include?: Array<{
target?: string;
arch?: string;
runner?: string;
bundles?: string;
artifact_path?: string;
}>;
};
};
steps?: Array<{
name?: string;
run?: string;
with?: { path?: string; 'if-no-files-found'?: string };
}>;
};
const prWorkflow = parseYaml(
fs.readFileSync(path.join(ROOT, '.github', 'workflows', 'tauri-build-pr.yml'), 'utf-8'),
) as { jobs?: { 'verify-macos'?: MacJob } };
const prJob = prWorkflow.jobs?.['verify-macos'];
const matrix = prJob?.strategy?.matrix?.include ?? [];
expect(matrix).toEqual([
{
target: 'aarch64-apple-darwin',
arch: 'arm64',
runner: 'macos-15',
bundles: 'dmg',
artifact_path: 'app/src-tauri/target/aarch64-apple-darwin/release/bundle/dmg/*.dmg',
},
{
target: 'x86_64-apple-darwin',
arch: 'x64',
runner: 'macos-15-intel',
bundles: 'app',
artifact_path: 'app/src-tauri/target/x86_64-apple-darwin/release/bundle/macos/*.app',
},
]);
const prBuild = prJob?.steps?.find(
(step) => step.name === 'Build Tauri (macOS ${{ matrix.target }})',
);
expect(prBuild?.run).toBe(
'cd app && node node_modules/@tauri-apps/cli/tauri.js build --target ${{ matrix.target }} --bundles ${{ matrix.bundles }}',
);
const prUpload = prJob?.steps?.find((step) => step.name === 'Upload macOS artifacts');
expect(prUpload?.with?.path).toBe('${{ matrix.artifact_path }}');
expect(prUpload?.with?.['if-no-files-found']).toBe('error');
const releaseWorkflow = parseYaml(
fs.readFileSync(path.join(ROOT, '.github', 'workflows', 'release.yml'), 'utf-8'),
) as { jobs?: { 'build-macos'?: MacJob } };
const releaseJob = releaseWorkflow.jobs?.['build-macos'];
const releaseMatrix = releaseJob?.strategy?.matrix?.include ?? [];
expect(releaseMatrix).toEqual([
{
target: 'aarch64-apple-darwin',
arch: 'arm64',
runner: 'macos-15',
},
{
target: 'x86_64-apple-darwin',
arch: 'x64',
runner: 'macos-15-intel',
},
]);
const releaseBuild = releaseJob?.steps?.find(
(step) => step.name === 'Build Tauri (macOS)',
);
expect(releaseBuild?.run).toBe(
'cd app && node node_modules/@tauri-apps/cli/tauri.js build --target ${{ matrix.target }}',
);
const releaseDmgUpload = releaseJob?.steps?.find(
(step) => step.name === 'Upload macOS DMG verification artifact',
);
expect(releaseDmgUpload?.with?.path).toBe(
'app/src-tauri/target/${{ matrix.target }}/release/bundle/dmg/*.dmg',
);
expect(releaseDmgUpload?.with?.['if-no-files-found']).toBe('error');
const releaseAppUpload = releaseJob?.steps?.find(
(step) => step.name === 'Upload macOS app verification artifact',
);
expect(releaseAppUpload?.with?.path).toBe(
'app/src-tauri/target/${{ matrix.target }}/release/bundle/macos/*.app',
);
expect(releaseAppUpload?.with?.['if-no-files-found']).toBe('error');
});
it('clean-checkout CI resolves vendored PPTX and uses the locked dependency graph', () => {
const rootPackage = JSON.parse(
fs.readFileSync(path.join(ROOT, 'package.json'), 'utf-8'),
) as { dependencies?: Record<string, string> };
const agentPackage = JSON.parse(
fs.readFileSync(path.join(ROOT, 'packages', 'agent', 'package.json'), 'utf-8'),
) as {
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
bundledDependencies?: string[];
scripts?: Record<string, string>;
};
const packageLock = JSON.parse(
fs.readFileSync(path.join(ROOT, 'package-lock.json'), 'utf-8'),
) as {
packages?: Record<
string,
{
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
resolved?: string;
link?: boolean;
version?: string;
dev?: boolean;
}
>;
};
const vendorPackage = JSON.parse(
fs.readFileSync(path.join(ROOT, 'vendor', 'pptxgenjs', 'package.json'), 'utf-8'),
) as { name?: string; version?: string };
const workflow = parseYaml(fs.readFileSync(
path.join(ROOT, '.github', 'workflows', 'hive-mind-cli-cross-platform.yml'),
'utf-8',
)) as {
on?: { pull_request?: { paths?: string[] } };
jobs?: Record<string, { steps?: Array<{ name?: string; run?: string }> }>;
};
const vaultTests = fs.readFileSync(
path.join(ROOT, 'packages', 'core', 'tests', 'vault.test.ts'),
'utf-8',
);
expect(rootPackage.dependencies?.pptxgenjs).toBeUndefined();
expect(packageLock.packages?.['']?.dependencies?.pptxgenjs).toBeUndefined();
expect(packageLock.packages?.['node_modules/pptxgenjs']).toBeUndefined();
expect(agentPackage.dependencies?.pptxgenjs).toBeUndefined();
expect(agentPackage.dependencies?.jszip).toBe('^3.10.1');
expect(agentPackage.devDependencies?.pptxgenjs).toBe('file:../../vendor/pptxgenjs');
expect(agentPackage.bundledDependencies).toBeUndefined();
expect(agentPackage.scripts).toMatchObject({
build: 'tsc --build --force && node ../../scripts/stage-agent-pptx-runtime.mjs',
prepack: 'tsc --build --force && node ../../scripts/stage-agent-pptx-runtime.mjs',
});
expect(packageLock.packages?.['packages/agent']).toMatchObject({
dependencies: { jszip: '^3.10.1' },
devDependencies: { pptxgenjs: 'file:../../vendor/pptxgenjs' },
});
expect(packageLock.packages?.['packages/agent']?.dependencies?.pptxgenjs).toBeUndefined();
expect(packageLock.packages?.['packages/agent']?.devDependencies?.pptxgenjs).toBe(
'file:../../vendor/pptxgenjs',
);
expect(packageLock.packages?.['packages/agent/node_modules/pptxgenjs']).toMatchObject({
resolved: 'vendor/pptxgenjs',
link: true,
});
expect(packageLock.packages?.['vendor/pptxgenjs']).toMatchObject({
version: vendorPackage.version,
dev: true,
});
expect(vendorPackage).toMatchObject({ name: 'pptxgenjs', version: '4.0.1-waggle.0' });
const installStep = workflow.jobs?.['install-and-smoke']?.steps?.find(
(step) => step.name === 'Install workspace deps',
);
expect(installStep?.run).toBe('npm ci');
expect(workflow.on?.pull_request?.paths).toEqual(
expect.arrayContaining([
'vendor/pptxgenjs/**',
'package.json',
'package-lock.json',
'.github/workflows/hive-mind-cli-cross-platform.yml',
]),
);
expect(vaultTests).toMatch(
/removes a pre-existing explicit Everyone allow ACE[\s\S]*?node_modules\/vite-node\/vite-node\.mjs[\s\S]*?'--config'[\s\S]*?probePath[\s\S]*?\r?\n\s*210_000,\r?\n\s*\);/,
);
expect(vaultTests).not.toContain("'--script'");
});
it('release workflow exists for Windows + macOS builds', () => {
const workflow = path.join(ROOT, '.github', 'workflows', 'release.yml');
expect(fs.existsSync(workflow)).toBe(true);
const content = fs.readFileSync(workflow, 'utf-8');
expect(content).toContain('build-windows');
expect(content).toContain('build-macos');
expect(content).not.toMatch(/uses:\s+tauri-apps\/tauri-action/);
expect(content).toContain('Upload macOS DMG verification artifact');
expect(content).toContain('Upload macOS app verification artifact');
expect(content).toContain('aarch64-apple-darwin');
expect(content).toContain('x86_64-apple-darwin');
expect(content).toContain('runner: macos-15');
expect(content).toContain('runner: macos-15-intel');
expect(content).toContain('runs-on: ${{ matrix.runner }}');
expect(content).toContain('TARGET_ARCH: ${{ matrix.arch }}');
});
it.runIf(process.platform === 'win32')(
'PowerShell 7 workflow override rejects Windows PowerShell 5.1',
() => {
const previousPath = process.env.WAGGLE_PWSH7_PATH;
const previousRequirement = process.env.WAGGLE_REQUIRE_PWSH7;
try {
process.env.WAGGLE_REQUIRE_PWSH7 = '1';
process.env.WAGGLE_PWSH7_PATH = path.join(
process.env.SystemRoot ?? 'C:\\Windows',
'System32',
'WindowsPowerShell',
'v1.0',
'powershell.exe',
);
expect(() => powershellProbeExecutable()).toThrow(
'PowerShell 7 required Windows release-workflow probes',
);
} finally {
if (previousPath === undefined) delete process.env.WAGGLE_PWSH7_PATH;
else process.env.WAGGLE_PWSH7_PATH = previousPath;
if (previousRequirement === undefined) delete process.env.WAGGLE_REQUIRE_PWSH7;
else process.env.WAGGLE_REQUIRE_PWSH7 = previousRequirement;
}
},
);
it.runIf(process.platform === 'win32')(
'release mode resolver permits only the exact v0.2.0 bootstrap identity',
() => {
const workflow = fs
.readFileSync(path.join(ROOT, '.github', 'workflows', 'release.yml'), 'utf-8')
.replace(/\r\n/g, '\n');
const resolverStart = workflow.indexOf(
' function Resolve-WindowsReleaseMode {',
);
const resolverEnd = workflow.indexOf(
'\n $releaseMode = Resolve-WindowsReleaseMode',
resolverStart,
);
expect(resolverStart).toBeGreaterThanOrEqual(0);
expect(resolverEnd).toBeGreaterThan(resolverStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-release-mode-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const helperSource = workflow
.slice(resolverStart, resolverEnd)
.replace(/^ {10}/gm, '');
const fixtureSource = String.raw`
function Expect-Mode {
param([scriptblock]$Action, [string]$ExpectedMode)
$actualMode = & $Action
if ($actualMode -ne $ExpectedMode) {
throw "Expected mode $ExpectedMode, got $actualMode"
}
}
function Expect-Rejection {
param([scriptblock]$Action, [string]$Label)
$rejected = $false
try {
& $Action | Out-Null
} catch {
$rejected = $true
}
if (-not $rejected) {
throw "Expected release-mode rejection: $Label"
}
}
$candidateSha = 'a' * 40
$baseSha256 = 'B' * 64
$baseCommit = 'c' * 40
Expect-Mode {
Resolve-WindowsReleaseMode -CandidateVersion '0.2.0' -CandidateTag 'v0.2.0' -CandidateSha $candidateSha -BootstrapIdentity "v0.2.0@$candidateSha" -BaseTag '' -BaseAssetName '' -BaseSha256 '' -BaseCommit ''
} 'bootstrap'
Expect-Mode {
Resolve-WindowsReleaseMode -CandidateVersion '0.2.1' -CandidateTag 'v0.2.1' -CandidateSha $candidateSha -BootstrapIdentity '' -BaseTag 'v0.2.0' -BaseAssetName 'Waggle_0.2.0_x64-setup.exe' -BaseSha256 $baseSha256 -BaseCommit $baseCommit
} 'upgrade'
Expect-Mode {
Resolve-WindowsReleaseMode -CandidateVersion '0.2.2' -CandidateTag 'v0.2.2' -CandidateSha $candidateSha -BootstrapIdentity '' -BaseTag 'v0.2.1' -BaseAssetName 'Waggle_0.2.1_x64-setup.exe' -BaseSha256 $baseSha256 -BaseCommit $baseCommit
} 'upgrade'
Expect-Rejection {
Resolve-WindowsReleaseMode -CandidateVersion '0.2.0' -CandidateTag 'v0.2.0' -CandidateSha $candidateSha -BootstrapIdentity "v0.2.0@$baseCommit" -BaseTag '' -BaseAssetName '' -BaseSha256 '' -BaseCommit ''
} 'wrong bootstrap commit'
Expect-Rejection {
Resolve-WindowsReleaseMode -CandidateVersion '0.2.0' -CandidateTag 'v0.2.0' -CandidateSha $candidateSha -BootstrapIdentity "v0.2.0@$candidateSha" -BaseTag 'v0.1.9' -BaseAssetName '' -BaseSha256 '' -BaseCommit ''
} 'bootstrap with partial baseline'
Expect-Rejection {
Resolve-WindowsReleaseMode -CandidateVersion '0.2.1' -CandidateTag 'v0.2.1' -CandidateSha $candidateSha -BootstrapIdentity '' -BaseTag '' -BaseAssetName '' -BaseSha256 '' -BaseCommit ''
} 'later release without baseline'
Expect-Rejection {
Resolve-WindowsReleaseMode -CandidateVersion '0.2.1' -CandidateTag 'v0.2.1' -CandidateSha $candidateSha -BootstrapIdentity "v0.2.1@$candidateSha" -BaseTag 'v0.2.0' -BaseAssetName 'Waggle_0.2.0_x64-setup.exe' -BaseSha256 $baseSha256 -BaseCommit $baseCommit
} 'bootstrap authorization on later release'
Expect-Rejection {
Resolve-WindowsReleaseMode -CandidateVersion '0.2.1' -CandidateTag 'v0.2.1' -CandidateSha $candidateSha -BootstrapIdentity '' -BaseTag ' ' -BaseAssetName 'Waggle_0.2.0_x64-setup.exe' -BaseSha256 $baseSha256 -BaseCommit $baseCommit
} 'whitespace baseline'
Expect-Rejection {
Resolve-WindowsReleaseMode -CandidateVersion '0.2.1' -CandidateTag 'v0.2.2' -CandidateSha $candidateSha -BootstrapIdentity '' -BaseTag 'v0.2.0' -BaseAssetName 'Waggle_0.2.0_x64-setup.exe' -BaseSha256 $baseSha256 -BaseCommit $baseCommit
} 'candidate tag mismatch'
Expect-Rejection {
Resolve-WindowsReleaseMode -CandidateVersion '0.2' -CandidateTag 'v0.2' -CandidateSha $candidateSha -BootstrapIdentity '' -BaseTag 'v0.2.0' -BaseAssetName 'Waggle_0.2.0_x64-setup.exe' -BaseSha256 $baseSha256 -BaseCommit $baseCommit
} 'malformed candidate version'
Expect-Rejection {
Resolve-WindowsReleaseMode -CandidateVersion '0.2.1' -CandidateTag 'v0.2.1' -CandidateSha ('A' * 40) -BootstrapIdentity '' -BaseTag 'v0.2.0' -BaseAssetName 'Waggle_0.2.0_x64-setup.exe' -BaseSha256 $baseSha256 -BaseCommit $baseCommit
} 'uppercase candidate commit'
Expect-Rejection {
Resolve-WindowsReleaseMode -CandidateVersion '0.2.1' -CandidateTag 'v0.2.1' -CandidateSha ('a' * 39) -BootstrapIdentity '' -BaseTag 'v0.2.0' -BaseAssetName 'Waggle_0.2.0_x64-setup.exe' -BaseSha256 $baseSha256 -BaseCommit $baseCommit
} 'short candidate commit'
Expect-Rejection {
Resolve-WindowsReleaseMode -CandidateVersion '0.2.1' -CandidateTag 'v0.2.1' -CandidateSha $candidateSha -BootstrapIdentity '' -BaseTag 'v0.2.0' -BaseAssetName 'Waggle_0.2.0_x64-setup.exe' -BaseSha256 $baseSha256 -BaseCommit ''
} 'upgrade with only three baseline inputs'
Expect-Rejection {
Resolve-WindowsReleaseMode -CandidateVersion '0.1.9' -CandidateTag 'v0.1.9' -CandidateSha $candidateSha -BootstrapIdentity '' -BaseTag 'v0.1.8' -BaseAssetName 'Waggle_0.1.8_x64-setup.exe' -BaseSha256 $baseSha256 -BaseCommit $baseCommit
} 'release older than bootstrap'
Expect-Rejection {
Resolve-WindowsReleaseMode -CandidateVersion '0.2.1' -CandidateTag 'v0.2.1' -CandidateSha $candidateSha -BootstrapIdentity '' -BaseTag 'v0.1.9' -BaseAssetName 'Waggle_0.1.9_x64-setup.exe' -BaseSha256 $baseSha256 -BaseCommit $baseCommit
} 'first upgrade without v0.2.0 baseline'
`;
try {
fs.writeFileSync(probePath, `${helperSource}\n${fixtureSource}`, 'utf-8');
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
if (result.status !== 0) {
throw new Error(
`Release-mode probe failed: ${result.stderr || result.stdout}`,
);
}
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
);
it('release workflow isolates unsigned build, protected signing, and publication authority', () => {
const workflow = fs.readFileSync(
path.join(ROOT, '.github', 'workflows', 'release.yml'),
'utf-8',
).replace(/\r\n/g, '\n');
const publisherPath = path.join(ROOT, 'scripts', 'publish-windows-release.ps1');
expect(fs.existsSync(publisherPath)).toBe(true);
const publisher = fs.readFileSync(publisherPath, 'utf-8');
const parsedWorkflow = parseYaml(workflow) as {
jobs?: Record<
string,
{
environment?: unknown;
if?: unknown;
steps?: Array<{
name?: string;
uses?: string;
with?: Record<string, unknown>;
if?: unknown;
'continue-on-error'?: unknown;
}>;
}
>;
};
const job = (name: string, nextName: string) => {
const marker = ` ${name}:`;
const nextMarker = `\n ${nextName}:`;
const start = workflow.indexOf(marker);
const end = workflow.indexOf(nextMarker, start);
expect(start).toBeGreaterThanOrEqual(0);
expect(workflow.lastIndexOf(marker)).toBe(start);
expect(end).toBeGreaterThan(start);
return workflow.slice(start, end);
};
const step = (jobSource: string, name: string) => {
const marker = ` - name: ${name}`;
const start = jobSource.indexOf(marker);
expect(start).toBeGreaterThanOrEqual(0);
expect(jobSource.lastIndexOf(marker)).toBe(start);
const end = jobSource.indexOf('\n - name:', start + 1);
return jobSource.slice(start, end >= 0 ? end : undefined);
};
const buildJob = job('build-windows-prebuilt', 'prepare-windows-signing');
const preparationJob = job('prepare-windows-signing', 'sign-windows');
const signingJob = job('sign-windows', 'certify-windows');
const certificationJob = job('certify-windows', 'attest-windows');
const attestationJob = job('attest-windows', 'publish-windows');
const publicationJob = job('publish-windows', 'build-macos');
const parsedSigningJob = parsedWorkflow.jobs?.['sign-windows'];
const parsedAttestationJob = parsedWorkflow.jobs?.['attest-windows'];
const parsedPublicationJob = parsedWorkflow.jobs?.['publish-windows'];
expect(parsedSigningJob).toBeDefined();
expect(parsedSigningJob).not.toHaveProperty('environment');
expect(parsedPublicationJob?.if).toBe(
"vars.WINDOWS_PUBLIC_RELEASE_AUTHORIZED == 'true' && github.event.repository.private == false && startsWith(github.ref, 'refs/tags/v')",
);
expect(workflow).toContain('WINDOWS_SIGNING_TRANSPORT_MAX_ITEMS: 60000');
expect([
...workflow.matchAll(
/\$maxItems = \[int\]\$env:WINDOWS_SIGNING_TRANSPORT_MAX_ITEMS/g,
),
]).toHaveLength(2);
expect([...workflow.matchAll(/\$items\.Count -gt \$maxItems/g)]).toHaveLength(2);
expect(workflow).not.toMatch(/\bgit\s+(?:fetch|ls-remote)\b/);
expect(workflow).toContain(
'$baseCommit = (git rev-parse --verify "refs/tags/$baseTag^{}").Trim().ToLowerInvariant()',
);
expect(buildJob).toContain('permissions:\n contents: read');
expect(buildJob).not.toMatch(/^ {4}environment:/m);
expect(buildJob).not.toContain('id-token: write');
expect(buildJob).not.toContain('attestations: write');
expect(buildJob).not.toContain('contents: write');
expect(buildJob).not.toContain('azure/login@');
expect(buildJob).not.toContain('GH_TOKEN:');
expect(preparationJob).toContain('needs: build-windows-prebuilt');
expect(preparationJob).toContain('permissions:\n contents: read');
expect(preparationJob).not.toContain('id-token: write');
expect(preparationJob).not.toContain('azure/login@');
expect(signingJob).toContain(
'needs: [build-windows-prebuilt, prepare-windows-signing]',
);
expect(signingJob).not.toMatch(/^ {4}environment:/m);
expect(signingJob).toContain('permissions:\n contents: read');
expect(signingJob).not.toContain('attestations: write');
expect(signingJob).toContain('id-token: write');
expect(signingJob).not.toContain('contents: write');
expect([...certificationJob.matchAll(/GH_TOKEN: \$\{\{ secrets\.GITHUB_TOKEN \}\}/g)])
.toHaveLength(1);
expect(certificationJob).toContain('needs: sign-windows');
expect(certificationJob).not.toMatch(/^ {4}environment:/m);
expect(certificationJob).not.toContain('id-token: write');
expect(certificationJob).not.toContain('azure/login@');
expect(attestationJob).toContain('needs: certify-windows');
expect(parsedAttestationJob?.if).toBe('github.event.repository.private == false');
expect(parsedAttestationJob?.environment).toBe('production');
expect(attestationJob).toContain('runs-on: ubuntu-latest');
expect(attestationJob).toContain('attestations: write');
expect(attestationJob).toContain('id-token: write');
expect(attestationJob).not.toContain('azure/login@');
expect(publicationJob).toContain('needs: [certify-windows, attest-windows]');
expect(publicationJob).toContain('permissions:\n contents: write');
expect(publicationJob).not.toMatch(/^ {4}environment:/m);
expect(publicationJob).not.toContain('id-token: write');
expect(publicationJob).not.toContain('attestations: write');
expect(publicationJob).not.toContain('azure/login@');
expect(publicationJob).not.toContain('sign-windows-artifact.ps1');
expect(publicationJob).not.toContain('certify-windows-installer.ps1');
for (const forbidden of [
'WINDOWS_CODESIGN_PFX_BASE64',
'WINDOWS_CODESIGN_PFX_PASSWORD',
'Import-PfxCertificate',
'Cert:\\',
'WAGGLE_IMPORTED_CERT_THUMBPRINTS',
'WINDOWS_CODESIGN_APPROVED_THUMBPRINT',
'client-secret:',
'creds:',
]) {
expect(workflow).not.toContain(forbidden);
}
expect(signingJob).toContain(
'azure/login@f5d393ae46f8fde4be8b75f32e3fc50e654ad0ca',
);
expect(signingJob).toContain('client-id: ${{ vars.AZURE_CLIENT_ID }}');
expect(signingJob).toContain('tenant-id: ${{ vars.AZURE_TENANT_ID }}');
expect(signingJob).toContain('subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}');
expect(signingJob).toContain('audience: api://AzureADTokenExchange');
expect(workflow).not.toContain('[checked]');
const boundaryStep = step(signingJob, 'Validate exact hosted OIDC release boundary');
expect(boundaryStep).toContain("$env:GITHUB_EVENT_NAME -cne 'push'");
expect(boundaryStep).toContain("$env:GITHUB_REPOSITORY -cne 'marolinik/waggle-os'");
expect(boundaryStep).toContain("$env:GITHUB_REF_TYPE -cne 'tag'");
expect(boundaryStep).toContain('$env:GITHUB_REF -cne "refs/tags/v$version"');
expect(boundaryStep).toContain('$env:GITHUB_REF_NAME -cne "v$version"');
expect(boundaryStep).toContain(
'$env:GITHUB_WORKFLOW_REF -cne "marolinik/waggle-os/.github/workflows/release.yml@$env:GITHUB_REF"',
);
expect(boundaryStep).toContain('$env:GITHUB_WORKFLOW_SHA -cne $env:GITHUB_SHA');
const refreshStep = step(signingJob, 'Refresh exact signing repository refs');
expect(refreshStep).toContain(
'actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5',
);
expect(refreshStep).toContain('ref: ${{ github.ref }}');
expect(refreshStep).toContain('fetch-depth: 0');
expect(refreshStep).toContain('persist-credentials: false');
expect(refreshStep).toContain('clean: false');
const parsedSigningSteps = parsedSigningJob?.steps ?? [];
const parsedRefreshIndex = parsedSigningSteps.findIndex(
({ name }) => name === 'Refresh exact signing repository refs',
);
const parsedRevalidationIndex = parsedSigningSteps.findIndex(
({ name }) => name === 'Revalidate exact signing revision against fresh origin main',
);
const parsedAzureIndex = parsedSigningSteps.findIndex(
({ name }) => name === 'Authenticate Azure Artifact Signing with OIDC',
);
expect(parsedRefreshIndex).toBeGreaterThanOrEqual(0);
expect(parsedRevalidationIndex).toBe(parsedRefreshIndex + 1);
expect(parsedAzureIndex).toBe(parsedRevalidationIndex + 1);
expect(parsedSigningSteps[parsedRefreshIndex]).toMatchObject({
uses: 'actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5',
with: {
repository: 'marolinik/waggle-os',
ref: '${{ github.ref }}',
'fetch-depth': 0,
'persist-credentials': false,
clean: false,
},
});
expect(parsedSigningSteps[parsedAzureIndex]?.uses).toBe(
'azure/login@f5d393ae46f8fde4be8b75f32e3fc50e654ad0ca',
);
for (const index of [parsedRefreshIndex, parsedRevalidationIndex, parsedAzureIndex]) {
expect(parsedSigningSteps[index]).not.toHaveProperty('if');
expect(parsedSigningSteps[index]).not.toHaveProperty('continue-on-error');
}
const revalidationStep = step(
signingJob,
'Revalidate exact signing revision against fresh origin main',
);
expect(revalidationStep).toContain(
'git merge-base --is-ancestor $env:GITHUB_SHA refs/remotes/origin/main',
);
expect(revalidationStep).toContain('$checkedOutRevision -cne $env:GITHUB_SHA');
expect(revalidationStep).toContain('$env:GITHUB_WORKFLOW_SHA -cne $env:GITHUB_SHA');
expect(signingJob.indexOf('Refresh exact signing repository refs'))
.toBeLessThan(signingJob.indexOf('Revalidate exact signing revision against fresh origin main'));
expect(signingJob.indexOf('Revalidate exact signing revision against fresh origin main'))
.toBeLessThan(signingJob.indexOf('Authenticate Azure Artifact Signing with OIDC'));
expect(publicationJob).toContain(
"vars.WINDOWS_PUBLIC_RELEASE_AUTHORIZED == 'true'",
);
expect(publicationJob).toContain('github.event.repository.private == false');
const capacityIndex = preparationJob.indexOf(
'Validate capacity before duplicate handoff extraction',
);
const setupNodeIndex = preparationJob.indexOf(
'Setup Node.js for protected packaging',
);
const rootDependenciesIndex = certificationJob.indexOf(
'Install locked certification dependencies',
);
const certificationSetupNodeIndex = certificationJob.indexOf(
'Setup Node.js for source-bound certification',
);
const appDependenciesIndex = preparationJob.indexOf(
'Install locked Tauri packaging CLI',
);
const certificationIndex = certificationJob.indexOf(
'Certify Windows Solo installer lifecycle',
);
expect(capacityIndex).toBeGreaterThanOrEqual(0);
expect(setupNodeIndex).toBeGreaterThan(capacityIndex);
expect(appDependenciesIndex).toBeGreaterThan(setupNodeIndex);
expect(certificationSetupNodeIndex).toBeGreaterThanOrEqual(0);
expect(rootDependenciesIndex).toBeGreaterThan(certificationSetupNodeIndex);
expect(rootDependenciesIndex).toBeGreaterThanOrEqual(0);
expect(certificationIndex).toBeGreaterThan(rootDependenciesIndex);
const resolverStep = step(preparationJob, 'Resolve Windows release mode');
expect(resolverStep).toContain('id: release-mode');
expect(resolverStep).toContain(
'-CandidateVersion $candidateVersion `',
);
expect(resolverStep).toContain('-CandidateTag $env:GITHUB_REF_NAME `');
expect(resolverStep).toContain('-CandidateSha $env:GITHUB_SHA `');
expect(resolverStep).toContain(
'"mode=$releaseMode" | Out-File -FilePath $env:GITHUB_OUTPUT',
);
const baselineStep = step(certificationJob, 'Download signed Windows upgrade baseline');
expect(baselineStep).toContain(
"if: steps.verify-signed.outputs.release_mode == 'upgrade'",
);
expect(baselineStep).toContain('GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}');
const certificateStep = step(certificationJob, 'Certify Windows Solo installer lifecycle');
expect(certificateStep).toContain(
'WAGGLE_RELEASE_MODE: ${{ steps.verify-signed.outputs.release_mode }}',
);
expect(certificateStep).toContain(
"if ($env:WAGGLE_RELEASE_MODE -eq 'upgrade') {",
);
expect(certificateStep).toContain(
'Bootstrap certification unexpectedly produced an upgrade receipt',
);
const bootstrapAttestation = step(attestationJob, 'Attest bootstrap Windows artifacts');
expect(bootstrapAttestation).toContain(
"if: needs.certify-windows.outputs.release_mode == 'bootstrap'",
);
expect(bootstrapAttestation).toContain('windows-installer-certificate.json');
expect(bootstrapAttestation).not.toContain(
'windows-installer-upgrade-certificate.json',
);
const upgradeAttestation = step(attestationJob, 'Attest upgrade Windows artifacts');
expect(upgradeAttestation).toContain(
"if: needs.certify-windows.outputs.release_mode == 'upgrade'",
);
expect(upgradeAttestation).toContain('windows-installer-certificate.json');
expect(upgradeAttestation).toContain(
'windows-installer-upgrade-certificate.json',
);
const publishStep = step(publicationJob, 'Publish certified Windows release');
expect(publishStep).toContain(
"if: success() && startsWith(github.ref, 'refs/tags/v')",
);
expect(publishStep).toContain('GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}');
expect(publishStep).toContain(
'WINDOWS_CODESIGN_APPROVED_SUBJECT: ${{ needs.certify-windows.outputs.signer_subject }}',
);
expect(publishStep).toContain(
'WAGGLE_RELEASE_MODE: ${{ needs.certify-windows.outputs.release_mode }}',
);
expect(publishStep).toContain(
'WAGGLE_CERTIFIED_CANDIDATE_SHA256: ${{ needs.certify-windows.outputs.candidate_sha256 }}',
);
expect(publishStep).toContain(
'./scripts/publish-windows-release.ps1 -Mode $env:WAGGLE_RELEASE_MODE',
);
expect(publishStep).not.toContain('gh release ');
expect(publisher).toContain(
"[ValidateSet('bootstrap', 'upgrade')]",
);
expect(publisher).toContain(
'$expectedBootstrapIdentity = "v0.2.0@$env:GITHUB_SHA"',
);
expect(publisher).toContain(
'Bootstrap publication is not bound to the exact authorized v0.2.0 release',
);
expect(publisher).toContain(
'Upgrade publication requires an empty bootstrap authorization and all baseline inputs',
);
expect(publisher).toContain(
'Bootstrap publication found an unexpected upgrade certificate',
);
expect(publisher).toContain('$releaseAssets = @($installer, $cleanReceipt)');
expect(publisher).toContain(
'$releaseAssets = @($installer, $cleanReceipt, $upgradeReceipt)',
);
expect(publisher).toContain('Assert-PassingWindowsCertificateReceipt');
expect(publisher).toContain('Assert-ExpectedAuthenticodeSignature');
expect(publisher).toContain('Assert-RemoteTagCommit');
expect(publisher).toContain('Refusing to use a pre-existing release');
expect([
...publisher.matchAll(
/^\s*\$createdReleaseId\s*=/gm,
),
]).toHaveLength(0);
expect([...publisher.matchAll(/^function Set-ReadOnlyCreatedReleaseId \{/gm)])
.toHaveLength(1);
expect([
...publisher.matchAll(
/^Set-ReadOnlyCreatedReleaseId \(\[string\]\$releaseData\.id\)\s*$/gm,
),
]).toHaveLength(1);
expect(publisher).not.toMatch(/Set-Variable[^\r\n]*-Force/);
expect(publisher).toContain(
'Published release assets do not exactly match the certified artifact set',
);
expect(publisher).toContain('[System.StringComparer]::Ordinal');
expect(publisher).not.toContain('Compare-Object');
expect([...publisher.matchAll(/^function Assert-ExactReleaseAssets \{/gm)])
.toHaveLength(1);
expect([...publisher.matchAll(/^function Assert-ReleaseIdentity \{/gm)])
.toHaveLength(1);
expect([...publisher.matchAll(/^function New-ReleaseAssetManifest \{/gm)])
.toHaveLength(1);
expect([...publisher.matchAll(/^function Assert-RemoteReleaseAssetContents \{/gm)])
.toHaveLength(1);
expect([
...publisher.matchAll(
/^function Assert-ReleaseAssetFileMatchesManifest \{/gm,
),
]).toHaveLength(1);
expect([
...publisher.matchAll(
/^function Assert-LocalReleaseAssetsUnchanged \{/gm,
),
]).toHaveLength(1);
expect([...publisher.matchAll(/^\s*gh release create \$tag\b/gm)])
.toHaveLength(1);
expect([...publisher.matchAll(/^\s*gh release upload \$tag\b/gm)])
.toHaveLength(1);
expect([
...publisher.matchAll(
/^\s*gh release edit \$tag --draft=false --prerelease=false\s*$/gm,
),
]).toHaveLength(1);
expect([
...publisher.matchAll(
/^\s*Assert-ExactReleaseAssets \$uploadedRelease \$releaseAssets\s*$/gm,
),
]).toHaveLength(1);
expect([
...publisher.matchAll(
/^\s*Assert-ExactReleaseAssets \$publishedRelease \$releaseAssets\s*$/gm,
),
]).toHaveLength(1);
expect([
...publisher.matchAll(
/^\s*Assert-RemoteReleaseAssetContents \$tag \$uploadedRelease \$releaseAssetManifest 'uploaded'\s*$/gm,
),
]).toHaveLength(1);
expect([
...publisher.matchAll(
/^\s*Assert-RemoteReleaseAssetContents \$tag \$publishedRelease \$releaseAssetManifest 'published'\s*$/gm,
),
]).toHaveLength(1);
const uploadIndex = publisher.indexOf('gh release upload $tag @releaseAssetPaths');
const uploadedHashIndex = publisher.indexOf(
"Assert-RemoteReleaseAssetContents $tag $uploadedRelease $releaseAssetManifest 'uploaded'",
);
const publishIndex = publisher.indexOf(
'gh release edit $tag --draft=false --prerelease=false',
);
const publishedHashIndex = publisher.indexOf(
"Assert-RemoteReleaseAssetContents $tag $publishedRelease $releaseAssetManifest 'published'",
);
expect(uploadIndex).toBeGreaterThanOrEqual(0);
expect(uploadedHashIndex).toBeGreaterThan(uploadIndex);
expect(publishIndex).toBeGreaterThan(uploadedHashIndex);
expect(publishedHashIndex).toBeGreaterThan(publishIndex);
const tagBindingIndices = [
...publisher.matchAll(
/^Assert-PublicationTagBindings \$Mode \$tag \$sourceRevision\s*$/gm,
),
].map((match) => match.index);
expect(tagBindingIndices).toHaveLength(3);
expect(tagBindingIndices[0]).toBeLessThan(
publisher.indexOf('gh release create $tag'),
);
expect(tagBindingIndices[1]).toBeGreaterThan(
publisher.indexOf('gh release create $tag'),
);
expect(tagBindingIndices[1]).toBeLessThan(uploadIndex);
expect(tagBindingIndices[2]).toBeGreaterThan(uploadIndex);
expect(tagBindingIndices[2]).toBeLessThan(publishIndex);
const remoteHelperStart = publisher.indexOf(
'function Assert-RemoteReleaseAssetContents {',
);
const remoteHelperEnd = publisher.indexOf(
'\nfunction Assert-ManagedModelAndMemoryEvidence {',
remoteHelperStart,
);
const remoteHelper = publisher.slice(remoteHelperStart, remoteHelperEnd);
expect([
...remoteHelper.matchAll(
/^\s*Assert-ReleaseAssetFileMatchesManifest `\s*$/gm,
),
]).toHaveLength(1);
const remoteDownloadIndex = remoteHelper.indexOf(
'gh release download $Tag --dir $downloadRoot',
);
const remoteCountIndex = remoteHelper.indexOf(
'if ($downloadedFiles.Count -ne $Manifest.Count)',
);
const remoteHashIndex = remoteHelper.indexOf(
'Assert-ReleaseAssetFileMatchesManifest `',
);
expect(remoteDownloadIndex).toBeGreaterThanOrEqual(0);
expect(remoteCountIndex).toBeGreaterThan(remoteDownloadIndex);
expect(remoteHashIndex).toBeGreaterThan(remoteCountIndex);
expect([
...publisher.matchAll(
/^Assert-ReleaseIdentity `\s*$/gm,
),
]).toHaveLength(3);
});
it('keeps Azure signing, candidate execution, GitHub attestation, and publication in separate jobs', () => {
const workflow = fs
.readFileSync(path.join(ROOT, '.github', 'workflows', 'release.yml'), 'utf-8')
.replace(/\r\n/g, '\n');
const job = (name: string, nextName: string) => {
const start = workflow.indexOf(` ${name}:`);
const end = workflow.indexOf(`\n ${nextName}:`, start);
expect(start, name).toBeGreaterThanOrEqual(0);
expect(end, nextName).toBeGreaterThan(start);
return workflow.slice(start, end);
};
const signingJob = job('sign-windows', 'certify-windows');
const preparationJob = job('prepare-windows-signing', 'sign-windows');
const certificationJob = job('certify-windows', 'attest-windows');
const attestationJob = job('attest-windows', 'publish-windows');
const publicationJob = job('publish-windows', 'build-macos');
expect(preparationJob).toContain('needs: build-windows-prebuilt');
expect(signingJob).toContain(
'needs: [build-windows-prebuilt, prepare-windows-signing]',
);
expect(signingJob).not.toMatch(/^ {4}environment:/m);
expect(signingJob).toContain('id-token: write');
expect(signingJob).toContain('azure/login@');
expect(signingJob).toContain('Package and sign from immutable prepared inputs');
expect(signingJob).not.toContain('certify-windows-installer.ps1');
expect(signingJob).not.toContain('attest-build-provenance@');
expect(signingJob).not.toContain('GH_TOKEN:');
expect(certificationJob).toContain('needs: sign-windows');
expect(certificationJob).toContain('runs-on: windows-latest');
expect(certificationJob).toContain('permissions:\n contents: read');
expect(certificationJob).not.toMatch(/^ {4}environment:/m);
expect(certificationJob).not.toContain('id-token: write');
expect(certificationJob).not.toContain('attestations: write');
expect(certificationJob).not.toContain('azure/login@');
expect(certificationJob).toContain('Validate exact signed handoff before candidate execution');
expect(certificationJob).toContain('Certify Windows Solo installer lifecycle');
expect(certificationJob.indexOf('Validate exact signed handoff before candidate execution'))
.toBeLessThan(certificationJob.indexOf('Certify Windows Solo installer lifecycle'));
expect(attestationJob).toContain('needs: certify-windows');
expect(attestationJob).toContain('if: github.event.repository.private == false');
expect(attestationJob).toContain('runs-on: ubuntu-latest');
expect(attestationJob).toContain('attestations: write');
expect(attestationJob).toContain('id-token: write');
expect(attestationJob).toContain('environment: production');
expect(attestationJob).not.toContain('azure/login@');
expect(attestationJob).not.toContain('certify-windows-installer.ps1');
expect(attestationJob).not.toContain('Start-Process');
expect(attestationJob).not.toContain('& $installer');
expect(publicationJob).toContain('needs: [certify-windows, attest-windows]');
expect(publicationJob).not.toContain('id-token: write');
expect(publicationJob).not.toContain('azure/login@');
expect(workflow).toContain('artifact-ids: ${{ needs.build-windows-prebuilt.outputs.artifact_id }}');
expect(workflow).toContain('artifact-ids: ${{ needs.prepare-windows-signing.outputs.artifact_id }}');
expect(workflow).toContain('artifact-ids: ${{ needs.sign-windows.outputs.artifact_id }}');
expect(workflow).toContain('artifact-ids: ${{ needs.certify-windows.outputs.artifact_id }}');
expect(workflow).not.toMatch(/^\s+[a-z_]*path:\s*\$\{\{\s*steps\.[^\n]+outputs\.[^\n]+\}\}/m);
});
it('confines OIDC to a minimal receipt-bound Windows signing job', () => {
const workflow = parseYaml(
fs.readFileSync(path.join(ROOT, '.github', 'workflows', 'release.yml'), 'utf-8'),
) as {
jobs?: Record<
string,
{
needs?: unknown;
permissions?: Record<string, string>;
if?: unknown;
environment?: unknown;
outputs?: Record<string, string>;
steps?: Array<{
name?: string;
uses?: string;
id?: string;
env?: Record<string, string>;
with?: Record<string, unknown>;
run?: string;
if?: unknown;
'continue-on-error'?: unknown;
}>;
}
>;
};
const jobs = workflow.jobs ?? {};
const preparationJob = jobs['prepare-windows-signing'];
const signingJob = jobs['sign-windows'];
expect(preparationJob).toBeDefined();
expect(preparationJob?.needs).toBe('build-windows-prebuilt');
expect(preparationJob?.permissions).toEqual({ contents: 'read' });
expect(preparationJob).not.toHaveProperty('environment');
expect(JSON.stringify(preparationJob)).not.toContain('id-token');
expect(JSON.stringify(preparationJob)).not.toContain('azure/login@');
expect(JSON.stringify(preparationJob)).not.toContain('contents":"write');
expect(preparationJob?.outputs).toMatchObject({
preparation_receipt_sha256: '${{ steps.stage-prepared.outputs.receipt_sha256 }}',
preparation_size_bytes: '${{ steps.stage-prepared.outputs.size_bytes }}',
artifact_id: '${{ steps.upload-prepared.outputs.artifact-id }}',
artifact_digest: '${{ steps.upload-prepared.outputs.artifact-digest }}',
});
expect(signingJob?.needs).toEqual([
'build-windows-prebuilt',
'prepare-windows-signing',
]);
expect(signingJob?.permissions).toEqual({ contents: 'read', 'id-token': 'write' });
expect(signingJob).not.toHaveProperty('environment');
const signingSteps = signingJob?.steps ?? [];
expect(signingSteps.map(({ name, uses }) => name ?? uses)).toEqual([
'actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5',
'Validate exact hosted OIDC release boundary',
'Validate initial signing revision on fresh origin main',
'Download immutable prepared Windows signing handoff',
'Verify and restore immutable prepared Windows signing handoff',
'Refresh exact signing repository refs',
'Revalidate exact signing revision against fresh origin main',
'Authenticate Azure Artifact Signing with OIDC',
'Package and sign from immutable prepared inputs',
'Stage exact signed handoff',
'Upload immutable signed Windows handoff',
]);
expect(JSON.stringify(signingJob)).not.toMatch(
/actions\/setup-node@|npm ci|Invoke-WebRequest|Invoke-RestMethod|Provision pinned|Resolve Windows release mode|Validate protected signer subject|Validate capacity before/,
);
for (const step of signingSteps) {
expect(step).not.toHaveProperty('if');
expect(step).not.toHaveProperty('continue-on-error');
}
const signingRunBodies = signingSteps.map(({ run }) => run ?? '').join('\n');
expect(signingRunBodies).not.toMatch(
/\b(?:curl(?:\.exe)?|wget(?:\.exe)?|Start-BitsTransfer|winget|choco|scoop|npm|npx|pnpm|yarn|pip|nuget)\b|\bgh\s+(?:api|release)\b|Invoke-(?:WebRequest|RestMethod)/i,
);
expect([...signingRunBodies.matchAll(/\bgit fetch\b/g)]).toHaveLength(0);
const preparedDownload = signingSteps.find(
({ name }) => name === 'Download immutable prepared Windows signing handoff',
);
expect(preparedDownload).toMatchObject({
uses: 'actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093',
with: {
'artifact-ids': '${{ needs.prepare-windows-signing.outputs.artifact_id }}',
path: '${{ runner.temp }}\\waggle-windows-signing-prepared',
'merge-multiple': true,
},
});
const preparedVerification = signingSteps.find(
({ name }) => name === 'Verify and restore immutable prepared Windows signing handoff',
);
expect(preparedVerification?.env).toMatchObject({
EXPECTED_PREPARATION_RECEIPT_SHA256:
'${{ needs.prepare-windows-signing.outputs.preparation_receipt_sha256 }}',
EXPECTED_PREPARATION_ARTIFACT_ID:
'${{ needs.prepare-windows-signing.outputs.artifact_id }}',
EXPECTED_PREPARATION_ARTIFACT_DIGEST:
'${{ needs.prepare-windows-signing.outputs.artifact_digest }}',
});
expect(preparedVerification?.run).toContain('Get-FileHash');
expect(preparedVerification?.run).toContain('$env:EXPECTED_PREPARATION_RECEIPT_SHA256');
expect(preparedVerification?.run).toContain('$env:EXPECTED_PREPARATION_ARTIFACT_ID');
expect(preparedVerification?.run).toContain('$env:EXPECTED_PREPARATION_ARTIFACT_DIGEST');
const preparationSteps = preparationJob?.steps ?? [];
const preparedStage = preparationSteps.find(
({ name }) => name === 'Stage fully inventoried Windows signing preparation',
);
const assertPreparedHandoffContract = (stageSource: string, verifySource: string) => {
for (const required of [
'Assert-WagglePreparedTree $payloadRoot',
'Windows signing preparation contains a non-allowlisted payload path',
'[IO.FileAttributes]::ReparsePoint',
'Get-Item -LiteralPath $item.FullName -Stream *',
]) {
if (!stageSource.includes(required)) throw new Error(`missing preparation guard: ${required}`);
}
for (const required of [
'Assert-WaggleTransportTree $preparedRoot',
'$actualSizeBytes -ne [long]$env:EXPECTED_PREPARATION_SIZE_BYTES',
'Get-FileHash -LiteralPath $receiptPath -Algorithm SHA256',
"Assert-WaggleExactValue $receipt.build.artifactId",
"Assert-WaggleExactValue $receipt.build.artifactDigest",
"Assert-WaggleExactValue $receipt.release.mode",
"Assert-WaggleExactValue $receipt.signerSubject",
"Assert-WaggleExactValue $receipt.azure.clientId",
'$actualPayloadInventory | ConvertTo-Json -Depth 32 -Compress',
'Get-TrustedPath',
'$destination.StartsWith($canonicalPrefix',
]) {
if (!verifySource.includes(required)) throw new Error(`missing verification guard: ${required}`);
}
};
const stageSource = preparedStage?.run ?? '';
const verificationSource = preparedVerification?.run ?? '';
expect(() => assertPreparedHandoffContract(stageSource, verificationSource)).not.toThrow();
for (const marker of [
'Assert-WagglePreparedTree $payloadRoot',
'Windows signing preparation contains a non-allowlisted payload path',
'[IO.FileAttributes]::ReparsePoint',
'Get-Item -LiteralPath $item.FullName -Stream *',
]) {
expect(() => assertPreparedHandoffContract(stageSource.split(marker).join(''), verificationSource))
.toThrow();
}
for (const marker of [
'Assert-WaggleTransportTree $preparedRoot',
'$actualSizeBytes -ne [long]$env:EXPECTED_PREPARATION_SIZE_BYTES',
'Get-FileHash -LiteralPath $receiptPath -Algorithm SHA256',
'Assert-WaggleExactValue $receipt.build.artifactId',
'Assert-WaggleExactValue $receipt.build.artifactDigest',
'Assert-WaggleExactValue $receipt.release.mode',
'Assert-WaggleExactValue $receipt.signerSubject',
'Assert-WaggleExactValue $receipt.azure.clientId',
'$actualPayloadInventory | ConvertTo-Json -Depth 32 -Compress',
'Get-TrustedPath',
'$destination.StartsWith($canonicalPrefix',
]) {
expect(() => assertPreparedHandoffContract(stageSource, verificationSource.split(marker).join('')))
.toThrow();
}
expect(signingJob?.outputs).toMatchObject({
release_mode: '${{ needs.prepare-windows-signing.outputs.release_mode }}',
bootstrap_identity: '${{ needs.prepare-windows-signing.outputs.bootstrap_identity }}',
signer_subject: '${{ needs.prepare-windows-signing.outputs.signer_subject }}',
candidate_sha256: '${{ steps.stage-signed.outputs.candidate_sha256 }}',
handoff_receipt_sha256: '${{ steps.stage-signed.outputs.receipt_sha256 }}',
artifact_id: '${{ steps.upload-signed.outputs.artifact-id }}',
artifact_digest: '${{ steps.upload-signed.outputs.artifact-digest }}',
});
expect(jobs['certify-windows']?.needs).toBe('sign-windows');
expect(jobs['attest-windows']?.needs).toBe('certify-windows');
expect(jobs['attest-windows']?.if).toBe('github.event.repository.private == false');
expect(jobs['attest-windows']?.environment).toBe('production');
expect(jobs['publish-windows']?.needs).toEqual(['certify-windows', 'attest-windows']);
});
it('flattens every immutable artifact-ID download into its exact configured root', () => {
const workflow = parseYaml(
fs.readFileSync(path.join(ROOT, '.github', 'workflows', 'release.yml'), 'utf-8'),
) as {
jobs?: Record<
string,
{
steps?: Array<{
name?: string;
uses?: string;
with?: Record<string, unknown>;
}>;
}
>;
};
const idDownloads = Object.entries(workflow.jobs ?? {}).flatMap(([jobName, job]) =>
(job.steps ?? [])
.filter(
(step) =>
step.uses?.startsWith('actions/download-artifact@') &&
typeof step.with?.['artifact-ids'] === 'string',
)
.map((step) => ({
jobName,
name: step.name,
artifactIds: step.with?.['artifact-ids'],
path: step.with?.path,
mergeMultiple: step.with?.['merge-multiple'],
})),
);
expect(idDownloads).toEqual([
{
jobName: 'prepare-windows-signing',
name: 'Download immutable prebuilt handoff for unsigned verification',
artifactIds: '${{ needs.build-windows-prebuilt.outputs.artifact_id }}',
path: '${{ runner.temp }}\\waggle-prebuilt-unsigned',
mergeMultiple: true,
},
{
jobName: 'prepare-windows-signing',
name: 'Download immutable prebuilt handoff for signed packaging',
artifactIds: '${{ needs.build-windows-prebuilt.outputs.artifact_id }}',
path: '${{ runner.temp }}\\waggle-prebuilt-signing',
mergeMultiple: true,
},
{
jobName: 'sign-windows',
name: 'Download immutable prepared Windows signing handoff',
artifactIds: '${{ needs.prepare-windows-signing.outputs.artifact_id }}',
path: '${{ runner.temp }}\\waggle-windows-signing-prepared',
mergeMultiple: true,
},
{
jobName: 'certify-windows',
name: 'Download immutable signed Windows handoff',
artifactIds: '${{ needs.sign-windows.outputs.artifact_id }}',
path: '${{ runner.temp }}\\waggle-windows-signed',
mergeMultiple: true,
},
{
jobName: 'attest-windows',
name: 'Download certified Windows release by immutable artifact ID',
artifactIds: '${{ needs.certify-windows.outputs.artifact_id }}',
path: '${{ runner.temp }}/waggle-windows-sealed',
mergeMultiple: true,
},
{
jobName: 'publish-windows',
name: 'Download sealed Windows release outputs',
artifactIds: '${{ needs.certify-windows.outputs.artifact_id }}',
path: '${{ runner.temp }}\\waggle-windows-sealed',
mergeMultiple: true,
},
]);
});
it.runIf(process.platform === 'win32')(
'normalizes lowercase upload-artifact digests before exact signed-handoff comparison',
() => {
const workflow = fs
.readFileSync(path.join(ROOT, '.github', 'workflows', 'release.yml'), 'utf-8')
.replace(/\r\n/g, '\n');
const stepMarker = ' - name: Validate exact signed handoff before candidate execution\n';
const stepStart = workflow.indexOf(stepMarker);
const stepEnd = workflow.indexOf('\n - name:', stepStart + stepMarker.length);
const stepSource = workflow.slice(stepStart, stepEnd);
const runMarker = ' run: |\n';
const runStart = stepSource.indexOf(runMarker);
expect(stepStart).toBeGreaterThanOrEqual(0);
expect(stepEnd).toBeGreaterThan(stepStart);
expect(runStart).toBeGreaterThanOrEqual(0);
const stepScript = stepSource
.slice(runStart + runMarker.length)
.split('\n')
.map((line) => line.replace(/^ {10}/, ''))
.join('\n');
const bindingStart = stepScript.indexOf('$receipt = Get-Content');
const bindingEnd = stepScript.indexOf('. ./app/scripts/sign-windows-artifact.ps1');
expect(bindingStart).toBeGreaterThanOrEqual(0);
expect(bindingEnd).toBeGreaterThan(bindingStart);
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-signed-binding-'));
try {
const receiptPath = path.join(root, 'signing-handoff-receipt.json');
const sourceRevision = '1'.repeat(40);
const candidateSha256 = 'A'.repeat(64);
const buildReceiptSha256 = 'B'.repeat(64);
const lowercaseBuildArtifactDigest = 'c1'.repeat(32);
fs.writeFileSync(
receiptPath,
JSON.stringify({
schemaVersion: 1,
sourceRevision,
candidateTag: 'v0.2.0',
candidateVersion: '0.2.0',
releaseMode: 'bootstrap',
bootstrapIdentity: 'v0.2.0',
upgradeBaseTag: '',
upgradeBaseAssetName: '',
upgradeBaseSha256: '',
upgradeBaseCommit: '',
signerSubject: 'CN=Waggle Test',
candidateSha256,
buildReceiptSha256,
buildArtifactId: '123',
buildArtifactDigest: lowercaseBuildArtifactDigest.toUpperCase(),
timestampPolicy: 'fresh-certification-monotonic-v1',
}),
'utf-8',
);
const scriptPath = path.join(root, 'validate-binding.ps1');
fs.writeFileSync(
scriptPath,
`$receiptPath = $env:WAGGLE_FIXTURE_RECEIPT\n${stepScript.slice(bindingStart, bindingEnd)}`,
'utf-8',
);
const result = spawnSync(
powershellProbeExecutable(),
['-NoLogo', '-NoProfile', '-NonInteractive', '-File', scriptPath],
{
cwd: ROOT,
encoding: 'utf-8',
windowsHide: true,
env: {
...process.env,
WAGGLE_FIXTURE_RECEIPT: receiptPath,
GITHUB_SHA: sourceRevision,
GITHUB_REF_NAME: 'v0.2.0',
EXPECTED_CANDIDATE_VERSION: '0.2.0',
EXPECTED_RELEASE_MODE: 'bootstrap',
EXPECTED_BOOTSTRAP_IDENTITY: 'v0.2.0',
EXPECTED_UPGRADE_BASE_TAG: '',
EXPECTED_UPGRADE_BASE_ASSET_NAME: '',
EXPECTED_UPGRADE_BASE_SHA256: '',
EXPECTED_UPGRADE_BASE_COMMIT: '',
EXPECTED_SIGNER_SUBJECT: 'CN=Waggle Test',
EXPECTED_CANDIDATE_SHA256: candidateSha256,
EXPECTED_BUILD_RECEIPT_SHA256: buildReceiptSha256,
EXPECTED_BUILD_ARTIFACT_ID: '123',
EXPECTED_BUILD_ARTIFACT_DIGEST: lowercaseBuildArtifactDigest,
},
},
);
expect(result.status, `${result.stdout}\n${result.stderr}`).toBe(0);
} finally {
fs.rmSync(root, { recursive: true, force: true });
}
},
30_000,
);
it.runIf(process.platform === 'win32')(
'executes exact publication staging for bootstrap and upgrade and rejects tampering',
() => {
const workflow = fs
.readFileSync(path.join(ROOT, '.github', 'workflows', 'release.yml'), 'utf-8')
.replace(/\r\n/g, '\n');
const stepMarker = ' - name: Stage exact publication inputs\n';
const stepStart = workflow.indexOf(stepMarker);
const stepEnd = workflow.indexOf('\n - name:', stepStart + stepMarker.length);
const stepSource = workflow.slice(stepStart, stepEnd);
const runMarker = ' run: |\n';
const runStart = stepSource.indexOf(runMarker);
expect(stepStart).toBeGreaterThanOrEqual(0);
expect(stepEnd).toBeGreaterThan(stepStart);
expect(runStart).toBeGreaterThanOrEqual(0);
const stageScript = stepSource
.slice(runStart + runMarker.length)
.split('\n')
.map((line) => line.replace(/^ {10}/, ''))
.join('\n');
const sha256 = (value: string) => createHash('sha256').update(value).digest('hex').toUpperCase();
const runFixture = (
mode: 'bootstrap' | 'upgrade',
mutation?: 'tampered-source' | 'unexpected-file',
) => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), `waggle-publish-stage-${mode}-`));
const runnerTemp = path.join(root, 'runner');
const sealedRoot = path.join(runnerTemp, 'waggle-windows-sealed');
const releaseRoot = path.join(sealedRoot, 'release');
const sourceNsisRoot = path.join(sealedRoot, 'source', 'release-nsis');
const sourceResourcesRoot = path.join(sealedRoot, 'source', 'resources');
const provenanceRoot = path.join(sealedRoot, 'provenance');
const repositoryRoot = path.join(root, 'repo');
const outputPath = path.join(root, 'github-output.txt');
const envPath = path.join(root, 'github-env.txt');
const candidateVersion = mode === 'bootstrap' ? '0.2.0' : '0.3.0';
const candidateSha = '1'.repeat(40);
const installerName = `Waggle_${candidateVersion}_x64-setup.exe`;
const installer = 'signed-installer';
const nsis = 'signed-nsis';
const service = 'signed-service';
fs.mkdirSync(releaseRoot, { recursive: true });
fs.mkdirSync(sourceNsisRoot, { recursive: true });
fs.mkdirSync(sourceResourcesRoot, { recursive: true });
fs.mkdirSync(provenanceRoot, { recursive: true });
fs.mkdirSync(path.join(repositoryRoot, 'app', 'src-tauri', 'resources'), { recursive: true });
fs.writeFileSync(path.join(releaseRoot, installerName), installer);
fs.writeFileSync(path.join(sourceNsisRoot, 'installer.nsi'), nsis);
fs.writeFileSync(path.join(sourceResourcesRoot, 'service.js'), service);
fs.writeFileSync(path.join(provenanceRoot, 'provenance-receipt.json'), '{}');
fs.writeFileSync(
path.join(releaseRoot, 'windows-installer-certificate.json'),
JSON.stringify({
evidence: {
generatedInstallerScriptSha256: sha256(nsis),
sidecarBundleSha256: sha256(service),
},
}),
);
let baseName = '';
let baseSha256 = '';
if (mode === 'upgrade') {
fs.writeFileSync(path.join(releaseRoot, 'windows-installer-upgrade-certificate.json'), '{}');
const baselineRoot = path.join(sealedRoot, 'baseline');
fs.mkdirSync(baselineRoot, { recursive: true });
baseName = 'Waggle_0.2.0_x64-setup.exe';
const baseline = 'baseline-installer';
baseSha256 = sha256(baseline);
fs.writeFileSync(path.join(baselineRoot, baseName), baseline);
}
if (mutation === 'tampered-source') {
fs.appendFileSync(path.join(sourceResourcesRoot, 'service.js'), '-tampered');
}
const inventoryEntries = listFiles(sealedRoot)
.map((file) => ({
path: path.relative(sealedRoot, file).split(path.sep).join('\\'),
size: fs.statSync(file).size,
sha256: createHash('sha256').update(fs.readFileSync(file)).digest('hex').toUpperCase(),
}))
.sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0));
const bootstrapIdentity = mode === 'bootstrap' ? `v0.2.0@${candidateSha}` : '';
const baseTag = mode === 'upgrade' ? 'v0.2.0' : '';
const baseCommit = mode === 'upgrade' ? '2'.repeat(40) : '';
const signerSubject = 'CN=EGZAKTA DOO BEOGRAD, O=EGZAKTA DOO BEOGRAD, L=Amsterdam, C=NL';
const sealedReceipt = {
schemaVersion: 1,
sourceRevision: candidateSha,
candidateTag: `v${candidateVersion}`,
candidateVersion,
releaseMode: mode,
bootstrapIdentity,
upgradeBaseTag: baseTag,
upgradeBaseAssetName: baseName,
upgradeBaseSha256: baseSha256,
upgradeBaseCommit: baseCommit,
signerSubject,
candidateSha256: sha256(installer),
signedHandoffReceiptSha256: 'A'.repeat(64),
signedHandoffArtifactId: '123',
signedHandoffArtifactDigest: 'B'.repeat(64),
inventory: {
entries: inventoryEntries,
sha256: sha256(JSON.stringify(inventoryEntries)),
},
};
const sealedReceiptPath = path.join(sealedRoot, 'sealed-release-receipt.json');
fs.writeFileSync(sealedReceiptPath, JSON.stringify(sealedReceipt));
if (mutation === 'unexpected-file') {
fs.writeFileSync(path.join(sealedRoot, 'unexpected.txt'), 'unexpected');
}
const scriptPath = path.join(root, 'stage.ps1');
fs.writeFileSync(scriptPath, stageScript);
const result = spawnSync(
powershellProbeExecutable(),
['-NoLogo', '-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-File', scriptPath],
{
cwd: repositoryRoot,
encoding: 'utf-8',
timeout: 30_000,
windowsHide: true,
env: {
...process.env,
RUNNER_TEMP: runnerTemp,
GITHUB_OUTPUT: outputPath,
GITHUB_ENV: envPath,
GITHUB_SHA: candidateSha,
GITHUB_REF_NAME: `v${candidateVersion}`,
WAGGLE_RELEASE_MODE: mode,
EXPECTED_CANDIDATE_SHA256: sha256(installer),
EXPECTED_CANDIDATE_VERSION: candidateVersion,
EXPECTED_BOOTSTRAP_IDENTITY: bootstrapIdentity,
EXPECTED_BASE_TAG: baseTag,
EXPECTED_BASE_ASSET_NAME: baseName,
EXPECTED_BASE_SHA256: baseSha256,
EXPECTED_BASE_COMMIT: baseCommit,
EXPECTED_SIGNER_SUBJECT: signerSubject,
EXPECTED_SEALED_RECEIPT_SHA256: createHash('sha256')
.update(fs.readFileSync(sealedReceiptPath))
.digest('hex')
.toUpperCase(),
EXPECTED_SEALED_ARTIFACT_ID: '456',
EXPECTED_SEALED_ARTIFACT_DIGEST: 'C'.repeat(64),
},
},
);
return { root, result, outputPath, envPath };
};
for (const mode of ['bootstrap', 'upgrade'] as const) {
const positive = runFixture(mode);
try {
expect(positive.result.status, positive.result.stderr || positive.result.stdout).toBe(0);
const statePath = fs.existsSync(positive.envPath) ? positive.envPath : positive.outputPath;
const state = fs.readFileSync(statePath, 'utf-8');
expect(state).toContain('WAGGLE_UPGRADE_BASE_INSTALLER_PATH=');
if (mode === 'upgrade') expect(state).toContain('Waggle_0.2.0_x64-setup.exe');
} finally {
fs.rmSync(positive.root, { recursive: true, force: true });
}
const tampered = runFixture(mode, 'tampered-source');
try {
expect(tampered.result.status).not.toBe(0);
expect(tampered.result.stderr).toContain(
'Sealed publication source inputs differ from their certified hashes.',
);
} finally {
fs.rmSync(tampered.root, { recursive: true, force: true });
}
const unexpected = runFixture(mode, 'unexpected-file');
try {
expect(unexpected.result.status).not.toBe(0);
expect(unexpected.result.stderr).toContain(
'Sealed publication artifact topology is not exact.',
);
} finally {
fs.rmSync(unexpected.root, { recursive: true, force: true });
}
}
},
180_000,
);
it('release workflow binds one immutable prebuilt handoff and restores its exact NSIS closure', () => {
const workflow = fs
.readFileSync(path.join(ROOT, '.github', 'workflows', 'release.yml'), 'utf-8')
.replace(/\r\n/g, '\n');
const buildStart = workflow.indexOf(' build-windows-prebuilt:');
const preparationStart = workflow.indexOf('\n prepare-windows-signing:', buildStart);
const signingStart = workflow.indexOf('\n sign-windows:', preparationStart);
const certificationStart = workflow.indexOf('\n certify-windows:', signingStart);
expect(buildStart).toBeGreaterThanOrEqual(0);
expect(preparationStart).toBeGreaterThan(buildStart);
expect(signingStart).toBeGreaterThan(preparationStart);
expect(certificationStart).toBeGreaterThan(signingStart);
const buildJob = workflow.slice(buildStart, preparationStart);
const preparationJob = workflow.slice(preparationStart, signingStart);
const signingJob = workflow.slice(signingStart, certificationStart);
const buildIndex = buildJob.indexOf('Build full unsigned Tauri NSIS package');
const handoffIndex = buildJob.indexOf('Issue immutable Windows signing handoff');
const uploadIndex = buildJob.indexOf('Upload immutable Windows signing handoff');
expect(buildIndex).toBeGreaterThanOrEqual(0);
expect(handoffIndex).toBeGreaterThan(buildIndex);
expect(uploadIndex).toBeGreaterThan(handoffIndex);
expect(buildJob).toContain('./app/scripts/new-windows-signing-handoff.ps1');
expect(buildJob).toContain(
'build_receipt_sha256: ${{ steps.handoff.outputs.receipt_sha256 }}',
);
expect(buildJob).toContain('name: waggle-windows-prebuilt-${{ github.sha }}');
expect(buildJob).toContain('include-hidden-files: true');
expect([
...preparationJob.matchAll(/artifact-ids: \$\{\{ needs\.build-windows-prebuilt\.outputs\.artifact_id \}\}/g),
]).toHaveLength(2);
expect(preparationJob).toContain('waggle-prebuilt-unsigned');
expect(preparationJob).toContain('waggle-prebuilt-signing');
expect(preparationJob).toContain(
'EXPECTED_BUILD_RECEIPT_SHA256: ${{ needs.build-windows-prebuilt.outputs.build_receipt_sha256 }}',
);
expect(preparationJob).toContain('foreach ($path in @($unsignedReceipt, $signingReceipt))');
expect(preparationJob).toContain('build-receipt.package.json');
expect(preparationJob).toContain(
"@($receipt.nsisInventory.entries).Count -ne 442",
);
expect(preparationJob).toContain(
"1FC822D1A183552A80ADEA01B0BF456F462B90518256EF1FE9EDFA22D76CD85A",
);
expect(preparationJob).toContain("Join-Path $env:LOCALAPPDATA 'tauri\\NSIS'");
expect(preparationJob).toContain(
'Fresh protected signer runner unexpectedly already contains a Tauri NSIS closure.',
);
expect(preparationJob).toContain('[IO.Directory]::Move($temporaryNsisRoot, $installedNsisRoot)');
expect(preparationJob).toContain(
'($receipt.nsisInventory | ConvertTo-Json -Depth 8 -Compress)',
);
expect(preparationJob).toContain('Assert-WaggleCanonicalInventoryEntries $resourceEntries');
expect(preparationJob).toContain(
'Materialized canonical repository resources differ from the hosted build receipt.',
);
for (const argument of [
"-UnsignedInputRoot '${{ steps.verify-prepared.outputs.unsigned_root }}'",
"-SigningInputRoot '${{ steps.verify-prepared.outputs.signing_root }}'",
"-BuildReceiptPath '${{ steps.verify-prepared.outputs.build_receipt_path }}'",
'-BuildReceiptSha256 $env:EXPECTED_BUILD_RECEIPT_SHA256',
]) {
expect(signingJob).toContain(argument);
}
expect(signingJob).not.toContain('node node_modules/@tauri-apps/cli/tauri.js build');
expect(signingJob).not.toContain('node scripts/build-sidecar.mjs');
expect(signingJob).not.toContain('node scripts/bundle-node.mjs');
});
it('protected signer uses only pinned explicit portable package tools', () => {
const workflow = fs.readFileSync(
path.join(ROOT, '.github', 'workflows', 'release.yml'),
'utf-8',
);
const wrapper = fs.readFileSync(
path.join(ROOT, 'app', 'scripts', 'sign-windows-artifact.ps1'),
'utf-8',
);
const signingStart = workflow.indexOf(' sign-windows:');
const preparationStart = workflow.indexOf(' prepare-windows-signing:');
const certificationStart = workflow.indexOf('\n certify-windows:', signingStart);
const signingJob = workflow.slice(signingStart, certificationStart);
const preparationJob = workflow.slice(preparationStart, signingStart);
for (const expected of [
'https://nodejs.org/dist/v22.22.2/node-v22.22.2-win-x64.zip',
'7C93E9D92BF68C07182B471AA187E35EE6CD08EF0F24AB060DFFF605FCC1C57C',
'https://github.com/git-for-windows/git/releases/download/v2.51.0.windows.1/MinGit-2.51.0-64-bit.zip',
'C2C955A21FA99889D83F485F24FA5D9A38FFFC2D509D4022385510E11C26B250',
'https://www.7-zip.org/a/7z2501-x64.exe',
'78AFA2A1C773CAF3CF7EDF62F857D2A8A5DA55FB0FFF5DA416074C0D28B2B55F',
'AE1A50511BE58E987483FDBC12125407443926D2D394669ADE2352776E920DD3',
'34A408843194BE320D8A87A3C12CD5C7D2E08D03B24567A41DB32E21D12569D2',
'4CD7D776C686427226A151789D2D61F0B2ED2C392148CC4E69C0238362FAFECF',
'5BD20FB38499D95C39594F41D4781B6181B3304B7F1F4D06B0182F514E7EAA74',
'CN=OpenJS Foundation, O=OpenJS Foundation, L=San Francisco, S=California, C=US',
'CN=Johannes Schindelin, O=Johannes Schindelin, S=Nordrhein-Westfalen, C=DE',
'linked file or alternate data stream',
'@($toolchainInventory.entries).Count -ne 2495',
'D64F897D4E1A7F07FE9BA62D6AF062EF9F0E41C595CDAF2F3C4F73991BBEA0F5',
'portable-toolchain-receipt.json',
'inventory = $toolchainInventory',
'receipt_path=$receiptPath',
'receipt_sha256=$receiptSha256',
]) {
expect(preparationJob).toContain(expected);
}
for (const argument of [
"-PortableToolchainRoot '${{ steps.verify-prepared.outputs.portable_root }}'",
"-PortableToolchainReceiptPath '${{ steps.verify-prepared.outputs.portable_receipt_path }}'",
"-PortableToolchainReceiptSha256 '${{ steps.verify-prepared.outputs.portable_receipt_sha256 }}'",
"-PortableNodePath '${{ steps.verify-prepared.outputs.portable_node }}'",
"-PortableGitPath '${{ steps.verify-prepared.outputs.portable_git }}'",
"-PortableSevenZipPath '${{ steps.verify-prepared.outputs.portable_sevenzip }}'",
]) {
expect(signingJob).toContain(argument);
}
expect(signingJob).toContain(
"& 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'",
);
for (const parameter of [
'PortableToolchainRoot',
'PortableNodePath',
'PortableGitPath',
'PortableSevenZipPath',
]) {
expect(wrapper).toContain(`[string]$${parameter}`);
}
expect(wrapper).toContain('function Get-WagglePortableToolchain');
expect(wrapper).toContain(
"$DotNetPublisher = 'CN=.NET, O=Microsoft Corporation, L=Redmond, S=Washington, C=US'",
);
});
it('sealed Windows publication reconstructs certified NSIS and sidecar source evidence', () => {
const workflow = fs
.readFileSync(path.join(ROOT, '.github', 'workflows', 'release.yml'), 'utf-8')
.replace(/\r\n/g, '\n');
const certificationStart = workflow.indexOf(' certify-windows:');
const attestationStart = workflow.indexOf('\n attest-windows:', certificationStart);
const publicationStart = workflow.indexOf('\n publish-windows:', attestationStart);
const macStart = workflow.indexOf('\n build-macos:', publicationStart);
const certificationJob = workflow.slice(certificationStart, attestationStart);
const attestationJob = workflow.slice(attestationStart, publicationStart);
const publicationJob = workflow.slice(publicationStart, macStart);
const certifyIndex = certificationJob.indexOf('Certify Windows Solo installer lifecycle');
const sealIndex = certificationJob.indexOf('Stage sealed Windows release outputs');
const uploadIndex = certificationJob.indexOf('Upload sealed Windows release outputs');
const attestIndex = attestationJob.indexOf('Attest bootstrap Windows artifacts');
expect(certifyIndex).toBeGreaterThanOrEqual(0);
expect(sealIndex).toBeGreaterThan(certifyIndex);
expect(uploadIndex).toBeGreaterThan(sealIndex);
expect(attestIndex).toBeGreaterThanOrEqual(0);
expect(certificationJob).toContain("Join-Path $sealedRoot 'source\\release-nsis'");
expect(certificationJob).toContain("Get-Item -LiteralPath 'app/src-tauri/resources/service.js'");
expect(certificationJob).toContain('evidence.generatedInstallerScriptSha256');
expect(certificationJob).toContain('evidence.sidecarBundleSha256');
expect(attestationJob).toContain('waggle-windows-sealed/source/release-nsis/installer.nsi');
expect(attestationJob).toContain('waggle-windows-sealed/source/resources/service.js');
expect(certificationJob).toContain("Join-Path $sealedRoot 'provenance'");
const stageIndex = publicationJob.indexOf('Stage exact publication inputs');
const publishIndex = publicationJob.indexOf('Publish certified Windows release');
expect(stageIndex).toBeGreaterThanOrEqual(0);
expect(publishIndex).toBeGreaterThan(stageIndex);
expect(publicationJob).toContain(
"'app/src-tauri/target/x86_64-pc-windows-msvc/release'",
);
expect(publicationJob).toContain("Join-Path $targetReleaseRoot 'bundle\\nsis'");
expect(publicationJob).toContain("Join-Path $targetReleaseRoot 'nsis'");
expect(publicationJob).toContain("'app/src-tauri/resources/service.js'");
expect(publicationJob).toContain(
'Publication bundle contains an unexpected asset; provenance must remain separate.',
);
expect(publicationJob).not.toContain('npm ci');
expect(publicationJob).not.toContain('cargo ');
expect(publicationJob).not.toContain('@tauri-apps/cli/tauri.js');
const publisher = fs.readFileSync(
path.join(ROOT, 'scripts', 'publish-windows-release.ps1'),
'utf-8',
);
expect(publisher).toContain(
'Assert-ReceiptSourceHashes $receiptDataSet $installer $sourceRevision',
);
expect(publisher).toContain("Join-Path $releaseDirectory 'nsis'");
expect(publisher).toContain("$currentSidecarPath = 'app/src-tauri/resources/service.js'");
});
it.runIf(process.platform === 'win32')(
'release publisher rejects differently-cased asset names',
() => {
const publisher = fs
.readFileSync(path.join(ROOT, 'scripts', 'publish-windows-release.ps1'), 'utf-8')
.replace(/\r\n/g, '\n');
const helperStart = publisher.indexOf('function Assert-ExactReleaseAssets {');
const helperEnd = publisher.indexOf('\nfunction ', helperStart + 1);
expect(helperStart).toBeGreaterThanOrEqual(0);
expect(helperEnd).toBeGreaterThan(helperStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-release-assets-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const fixtureSource = String.raw`
function Expect-Rejection {
param([scriptblock]$Action, [string]$Label)
$rejected = $false
try { & $Action } catch { $rejected = $true }
if (-not $rejected) { throw "$Label was accepted" }
}
$expectedPath = Join-Path $PSScriptRoot 'Waggle_0.2.0_x64-setup.exe'
$receiptPath = Join-Path $PSScriptRoot 'windows-installer-certificate.json'
[System.IO.File]::WriteAllText($expectedPath, 'fixture')
[System.IO.File]::WriteAllText($receiptPath, 'receipt')
$expectedAssets = @(
Get-Item -LiteralPath $expectedPath
Get-Item -LiteralPath $receiptPath
)
$exactRelease = [pscustomobject]@{
assets = @(
[pscustomobject]@{ name = 'Waggle_0.2.0_x64-setup.exe' }
[pscustomobject]@{ name = 'windows-installer-certificate.json' }
)
}
$wrongCaseRelease = [pscustomobject]@{
assets = @(
[pscustomobject]@{ name = 'waggle_0.2.0_x64-setup.exe' }
[pscustomobject]@{ name = 'windows-installer-certificate.json' }
)
}
$missingRelease = [pscustomobject]@{
assets = @([pscustomobject]@{ name = 'Waggle_0.2.0_x64-setup.exe' })
}
$extraRelease = [pscustomobject]@{
assets = @(
[pscustomobject]@{ name = 'Waggle_0.2.0_x64-setup.exe' }
[pscustomobject]@{ name = 'windows-installer-certificate.json' }
[pscustomobject]@{ name = 'unexpected.txt' }
)
}
$duplicateRelease = [pscustomobject]@{
assets = @(
[pscustomobject]@{ name = 'Waggle_0.2.0_x64-setup.exe' }
[pscustomobject]@{ name = 'Waggle_0.2.0_x64-setup.exe' }
)
}
Assert-ExactReleaseAssets $exactRelease $expectedAssets
Expect-Rejection {
Assert-ExactReleaseAssets $wrongCaseRelease $expectedAssets
} 'differently-cased asset'
Expect-Rejection {
Assert-ExactReleaseAssets $missingRelease $expectedAssets
} 'missing asset'
Expect-Rejection {
Assert-ExactReleaseAssets $extraRelease $expectedAssets
} 'extra asset'
Expect-Rejection {
Assert-ExactReleaseAssets $duplicateRelease $expectedAssets
} 'duplicate asset'
`;
try {
fs.writeFileSync(
probePath,
`${publisher.slice(helperStart, helperEnd)}\n${fixtureSource}`,
'utf-8',
);
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
if (result.status !== 0) {
throw new Error(`Release asset probe failed: ${result.stderr || result.stdout}`);
}
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
);
it.runIf(process.platform === 'win32')(
'release signer identity accepts exact subjects or legacy thumbprints, never both',
() => {
const publisher = fs
.readFileSync(path.join(ROOT, 'scripts', 'publish-windows-release.ps1'), 'utf-8')
.replace(/\r\n/g, '\n');
const helperStart = publisher.indexOf('function Get-ProtectedSignerIdentity {');
const helperEnd = publisher.indexOf(
'\nfunction Assert-PassingWindowsCertificateReceipt {',
helperStart,
);
expect(helperStart).toBeGreaterThanOrEqual(0);
expect(helperEnd).toBeGreaterThan(helperStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-signer-identity-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const fixtureSource = String.raw`
function Expect-Rejection {
param([scriptblock]$Action, [string]$Label)
$rejected = $false
try { & $Action } catch { $rejected = $true }
if (-not $rejected) { throw "$Label was accepted" }
}
$subject = 'CN=Managed Identity, O=Fixture Corp, C=NL'
$thumbprint = '0123456789abcdef0123456789abcdef01234567'
$artifactPath = Join-Path $PSScriptRoot 'fixture.exe'
[System.IO.File]::WriteAllText($artifactPath, 'fixture')
$artifact = Get-Item -LiteralPath $artifactPath
$script:fakeSignature = [pscustomobject]@{
Status = 'Valid'
SignatureType = 'Authenticode'
SignerCertificate = [pscustomobject]@{
Subject = $subject
Thumbprint = $thumbprint
}
TimeStamperCertificate = [pscustomobject]@{ Subject = 'CN=Timestamp Fixture' }
}
function Get-AuthenticodeSignature { return $script:fakeSignature }
Remove-Item Env:WINDOWS_CODESIGN_APPROVED_SUBJECT -ErrorAction SilentlyContinue
Remove-Item Env:WINDOWS_CODESIGN_APPROVED_THUMBPRINT -ErrorAction SilentlyContinue
Expect-Rejection { Get-ProtectedSignerIdentity } 'missing identity'
$env:WINDOWS_CODESIGN_APPROVED_SUBJECT = $subject
$env:WINDOWS_CODESIGN_APPROVED_THUMBPRINT = $thumbprint
Expect-Rejection { Get-ProtectedSignerIdentity } 'ambiguous identity'
Remove-Item Env:WINDOWS_CODESIGN_APPROVED_THUMBPRINT
$subjectBinding = Get-ProtectedSignerIdentity
if ($subjectBinding.mode -cne 'subject' -or $subjectBinding.subject -cne $subject) {
throw 'Exact subject binding was not preserved'
}
$actualSubjectIdentity = Assert-ExpectedAuthenticodeSignature $artifact $subjectBinding
Remove-Item Env:WINDOWS_CODESIGN_APPROVED_SUBJECT
$env:WINDOWS_CODESIGN_APPROVED_THUMBPRINT = '01 23 45 67 89 ab cd ef 01 23 45 67 89 ab cd ef 01 23 45 67'
$thumbprintBinding = Get-ProtectedSignerIdentity
if ($thumbprintBinding.mode -cne 'thumbprint' -or
$thumbprintBinding.thumbprint -cne $thumbprint.ToUpperInvariant()) {
throw 'Legacy thumbprint binding was not normalized'
}
$actualThumbprintIdentity = Assert-ExpectedAuthenticodeSignature $artifact $thumbprintBinding
$receiptArtifact = [pscustomobject]@{
signerSubject = $subject
signerThumbprint = $thumbprint
}
Assert-ReceiptSignerIdentity $receiptArtifact $actualSubjectIdentity 'valid receipt'
$receiptArtifact.signerSubject = $subject.ToLowerInvariant()
Expect-Rejection {
Assert-ReceiptSignerIdentity $receiptArtifact $actualSubjectIdentity 'wrong-case subject'
} 'wrong-case subject receipt'
$receiptArtifact.signerSubject = $subject
$receiptArtifact.signerThumbprint = 'ffffffffffffffffffffffffffffffffffffffff'
Expect-Rejection {
Assert-ReceiptSignerIdentity $receiptArtifact $actualThumbprintIdentity 'wrong thumbprint'
} 'wrong thumbprint receipt'
$script:fakeSignature.SignatureType = 'Catalog'
Expect-Rejection {
Assert-ExpectedAuthenticodeSignature $artifact $subjectBinding
} 'non-embedded signature'
`;
try {
fs.writeFileSync(
probePath,
`${publisher.slice(helperStart, helperEnd)}\n${fixtureSource}`,
'utf-8',
);
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
if (result.status !== 0) {
throw new Error(`Signer identity probe failed: ${result.stderr || result.stdout}`);
}
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
);
it.runIf(process.platform === 'win32')(
'release identity receipts remain rotation-safe without weakening legacy pinning',
() => {
const publisher = fs
.readFileSync(path.join(ROOT, 'scripts', 'publish-windows-release.ps1'), 'utf-8')
.replace(/\r\n/g, '\n');
const helperStart = publisher.indexOf('function Get-ProtectedSignerIdentity {');
const helperEnd = publisher.indexOf(
'\nfunction Assert-PassingWindowsCertificateReceipt {',
helperStart,
);
expect(helperStart).toBeGreaterThanOrEqual(0);
expect(helperEnd).toBeGreaterThan(helperStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-signer-rotation-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const fixtureSource = String.raw`
function Expect-Rejection {
param([scriptblock]$Action, [string]$Label)
$rejected = $false
try { & $Action } catch { $rejected = $true }
if (-not $rejected) { throw "$Label was accepted" }
}
$subject = 'CN=Managed Identity, O=Fixture Corp, C=NL'
$previousThumbprint = '1111111111111111111111111111111111111111'
$candidateThumbprint = '2222222222222222222222222222222222222222'
$previousPath = Join-Path $PSScriptRoot 'previous.exe'
$candidatePath = Join-Path $PSScriptRoot 'candidate.exe'
[System.IO.File]::WriteAllText($previousPath, 'previous')
[System.IO.File]::WriteAllText($candidatePath, 'candidate')
$previousArtifact = Get-Item -LiteralPath $previousPath
$candidateArtifact = Get-Item -LiteralPath $candidatePath
$script:signatureByName = @{
'previous.exe' = [pscustomobject]@{
Status = 'Valid'
SignatureType = 'Authenticode'
SignerCertificate = [pscustomobject]@{
Subject = $subject
Thumbprint = $previousThumbprint
}
TimeStamperCertificate = [pscustomobject]@{ Subject = 'CN=Timestamp Fixture' }
}
'candidate.exe' = [pscustomobject]@{
Status = 'Valid'
SignatureType = 'Authenticode'
SignerCertificate = [pscustomobject]@{
Subject = $subject
Thumbprint = $candidateThumbprint
}
TimeStamperCertificate = [pscustomobject]@{ Subject = 'CN=Timestamp Fixture' }
}
}
function Get-AuthenticodeSignature {
param([string]$FilePath)
return $script:signatureByName[(Split-Path -Leaf $FilePath)]
}
$env:WINDOWS_CODESIGN_APPROVED_SUBJECT = $subject
Remove-Item Env:WINDOWS_CODESIGN_APPROVED_THUMBPRINT -ErrorAction SilentlyContinue
$subjectBinding = Get-ProtectedSignerIdentity
$previousIdentity = Assert-ExpectedAuthenticodeSignature $previousArtifact $subjectBinding
$candidateIdentity = Assert-ExpectedAuthenticodeSignature $candidateArtifact $subjectBinding
if ($previousIdentity.thumbprint -ceq $candidateIdentity.thumbprint) {
throw 'Rotation fixture did not produce distinct certificate thumbprints'
}
$previousReceiptIdentity = [pscustomobject]@{
signerSubject = $subject
signerThumbprint = $previousThumbprint
}
$candidateReceiptIdentity = [pscustomobject]@{
signerSubject = $subject
signerThumbprint = $candidateThumbprint
}
$lifecycleReceipt = [pscustomobject]@{
previousInstaller = $previousReceiptIdentity
previousInstalledApp = $previousReceiptIdentity
installer = $candidateReceiptIdentity
installedApp = $candidateReceiptIdentity
}
Assert-LifecycleReceiptSignerIdentities $lifecycleReceipt $previousIdentity $candidateIdentity
$swappedLifecycleReceipt = [pscustomobject]@{
previousInstaller = $candidateReceiptIdentity
previousInstalledApp = $candidateReceiptIdentity
installer = $previousReceiptIdentity
installedApp = $previousReceiptIdentity
}
Expect-Rejection {
Assert-LifecycleReceiptSignerIdentities $swappedLifecycleReceipt $previousIdentity $candidateIdentity
} 'swapped lifecycle receipt mappings'
Remove-Item Env:WINDOWS_CODESIGN_APPROVED_SUBJECT
$env:WINDOWS_CODESIGN_APPROVED_THUMBPRINT = $previousThumbprint
$legacyBinding = Get-ProtectedSignerIdentity
$null = Assert-ExpectedAuthenticodeSignature $previousArtifact $legacyBinding
Expect-Rejection {
Assert-ExpectedAuthenticodeSignature $candidateArtifact $legacyBinding
} 'legacy fixed-thumbprint rotation'
`;
try {
fs.writeFileSync(
probePath,
`${publisher.slice(helperStart, helperEnd)}\n${fixtureSource}`,
'utf-8',
);
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
if (result.status !== 0) {
throw new Error(`Signer rotation probe failed: ${result.stderr || result.stdout}`);
}
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
);
it.runIf(process.platform === 'win32')(
'installer certifier applies the chosen signer identity to Authenticode evidence',
() => {
const certifier = fs
.readFileSync(path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'), 'utf-8')
.replace(/\r\n/g, '\n');
const helperStart = certifier.indexOf('function Assert-True {');
const helperEnd = certifier.indexOf(
'\nfunction ConvertTo-StrictSemanticVersion {',
helperStart,
);
const environmentHelperStart = certifier.indexOf(
'function Remove-CertificationControlEnvironment {',
);
const environmentHelperEnd = certifier.indexOf(
'\nfunction Invoke-RawProcess {',
environmentHelperStart,
);
expect(helperStart).toBeGreaterThanOrEqual(0);
expect(helperEnd).toBeGreaterThan(helperStart);
expect(environmentHelperStart).toBeGreaterThanOrEqual(0);
expect(environmentHelperEnd).toBeGreaterThan(environmentHelperStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-certifier-signer-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const fixtureSource = String.raw`
function Expect-Rejection {
param([scriptblock]$Action, [string]$Label)
$rejected = $false
try { & $Action } catch { $rejected = $true }
if (-not $rejected) { throw "$Label was accepted" }
}
$subject = 'CN=Managed Identity, O=Fixture Corp, C=NL'
$thumbprint = '0123456789abcdef0123456789abcdef01234567'
$signature = [pscustomobject]@{
Status = [System.Management.Automation.SignatureStatus]::Valid
SignatureType = 'Authenticode'
SignerCertificate = [pscustomobject]@{
Subject = $subject
Thumbprint = $thumbprint
}
TimeStamperCertificate = [pscustomobject]@{ Subject = 'CN=Timestamp Fixture' }
}
Assert-ExpectedAuthenticodeSignature $signature '' $subject 'subject fixture'
Assert-ExpectedAuthenticodeSignature $signature $thumbprint '' 'thumbprint fixture'
$rotatedThumbprint = 'fedcba9876543210fedcba9876543210fedcba98'
$previousReceiptIdentity = [pscustomobject]@{
signerSubject = $subject
signerThumbprint = $thumbprint
}
$candidateReceiptIdentity = [pscustomobject]@{
signerSubject = $subject
signerThumbprint = $rotatedThumbprint
}
$lifecycleReceipt = [pscustomobject]@{
previousInstaller = $previousReceiptIdentity
previousInstalledApp = $previousReceiptIdentity
installer = $candidateReceiptIdentity
installedApp = $candidateReceiptIdentity
}
Assert-LifecycleReceiptApprovedSigner $lifecycleReceipt '' $subject
Expect-Rejection {
Assert-LifecycleReceiptApprovedSigner $lifecycleReceipt $thumbprint ''
} 'legacy certifier rotated candidate'
$processInfo = [System.Diagnostics.ProcessStartInfo]::new()
$protectedIdentityNames = @(
'WINDOWS_CODESIGN_APPROVED_SUBJECT',
'WINDOWS_CODESIGN_APPROVED_THUMBPRINT',
'WAGGLE_APPROVED_CODESIGN_SUBJECT',
'WAGGLE_APPROVED_CODESIGN_THUMBPRINT',
'WAGGLE_CODESIGN_SUBJECT',
'WAGGLE_CODESIGN_THUMBPRINT'
)
foreach ($name in $protectedIdentityNames) {
$processInfo.Environment[$name] = 'must-not-reach-installed-process'
}
$processInfo.Environment['WAGGLE_NON_CONTROL_FIXTURE'] = 'preserve'
Remove-CertificationControlEnvironment $processInfo
foreach ($name in $protectedIdentityNames) {
if ($processInfo.Environment.ContainsKey($name)) {
throw "Protected signer identity environment escaped certification: $name"
}
}
if ($processInfo.Environment['WAGGLE_NON_CONTROL_FIXTURE'] -cne 'preserve') {
throw 'Unrelated application environment was removed'
}
Expect-Rejection {
Assert-ExpectedAuthenticodeSignature $signature '' '' 'missing binding'
} 'missing signer binding'
Expect-Rejection {
Assert-ExpectedAuthenticodeSignature $signature $thumbprint $subject 'ambiguous binding'
} 'ambiguous signer binding'
Expect-Rejection {
Assert-ExpectedAuthenticodeSignature $signature '' $subject.ToLowerInvariant() 'wrong subject'
} 'wrong-case signer subject'
$signature.SignatureType = 'Catalog'
Expect-Rejection {
Assert-ExpectedAuthenticodeSignature $signature '' $subject 'catalog signature'
} 'non-embedded signature'
`;
try {
fs.writeFileSync(
probePath,
`${certifier.slice(helperStart, helperEnd)}\n${certifier.slice(environmentHelperStart, environmentHelperEnd)}\n${fixtureSource}`,
'utf-8',
);
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
if (result.status !== 0) {
throw new Error(`Certifier signer identity probe failed: ${result.stderr || result.stdout}`);
}
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
);
it.runIf(process.platform === 'win32')(
'release publisher binds release identity and exact asset bytes',
() => {
const publisher = fs
.readFileSync(path.join(ROOT, 'scripts', 'publish-windows-release.ps1'), 'utf-8')
.replace(/\r\n/g, '\n');
const helperStart = publisher.indexOf('function Assert-ExactReleaseAssets {');
const helperEnd = publisher.indexOf(
'\nfunction Assert-ManagedModelAndMemoryEvidence {',
helperStart,
);
expect(helperStart).toBeGreaterThanOrEqual(0);
expect(helperEnd).toBeGreaterThan(helperStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-release-bytes-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const fixtureSource = String.raw`
function Expect-Rejection {
param([scriptblock]$Action, [string]$Label)
$rejected = $false
try { & $Action } catch { $rejected = $true }
if (-not $rejected) { throw "$Label was accepted" }
}
$expectedDirectory = New-Item -ItemType Directory -Path (
Join-Path $PSScriptRoot 'expected'
)
$changedDirectory = New-Item -ItemType Directory -Path (
Join-Path $PSScriptRoot 'changed'
)
$expectedPath = Join-Path $expectedDirectory.FullName 'asset.bin'
$changedPath = Join-Path $changedDirectory.FullName 'asset.bin'
[System.IO.File]::WriteAllText($expectedPath, 'AAAA')
[System.IO.File]::WriteAllText($changedPath, 'BBBB')
$manifest = New-ReleaseAssetManifest @((Get-Item -LiteralPath $expectedPath))
Assert-ReleaseAssetFileMatchesManifest $expectedPath $manifest[0] 'unchanged local asset'
Expect-Rejection {
Assert-ReleaseAssetFileMatchesManifest $changedPath $manifest[0] 'same-size changed asset'
} 'same-name-size content substitution'
Set-ReadOnlyCreatedReleaseId 'release-A'
Expect-Rejection {
$script:createdReleaseId = 'release-B'
} 'read-only created release id reassignment'
if ($script:createdReleaseId -cne 'release-A') {
throw 'Read-only created release id changed'
}
$env:RUNNER_TEMP = Join-Path $PSScriptRoot 'runner'
New-Item -ItemType Directory -Path $env:RUNNER_TEMP | Out-Null
$remoteRelease = [pscustomobject]@{
assets = @([pscustomobject]@{ name = 'asset.bin' })
}
$script:fakeGhAssetPath = $expectedPath
function gh {
if ($args.Count -ne 5 -or
[string]$args[0] -cne 'release' -or
[string]$args[1] -cne 'download' -or
[string]$args[3] -cne '--dir') {
throw 'Unexpected fake gh invocation'
}
Copy-Item -LiteralPath $script:fakeGhAssetPath -Destination (
Join-Path ([string]$args[4]) 'asset.bin'
)
$global:LASTEXITCODE = 0
}
Assert-RemoteReleaseAssetContents 'v0.2.0' $remoteRelease $manifest 'fake-valid'
$script:fakeGhAssetPath = $changedPath
Expect-Rejection {
Assert-RemoteReleaseAssetContents 'v0.2.0' $remoteRelease $manifest 'fake-upload'
} 'same-name-size remote content substitution'
$created = [pscustomobject]@{
id = 'release-A'
tagName = 'v0.2.0'
name = 'Waggle v0.2.0'
isDraft = $true
isPrerelease = $false
}
$substituted = [pscustomobject]@{
id = 'release-B'
tagName = 'v0.2.0'
name = 'Waggle v0.2.0'
isDraft = $true
isPrerelease = $false
}
Assert-ReleaseIdentity $created 'release-A' 'v0.2.0' $true 'created release'
Expect-Rejection {
Assert-ReleaseIdentity $substituted 'release-A' 'v0.2.0' $true 'substituted release'
} 'release id substitution'
`;
try {
fs.writeFileSync(
probePath,
`${publisher.slice(helperStart, helperEnd)}\n${fixtureSource}`,
'utf-8',
);
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
if (result.status !== 0) {
throw new Error(
`Release byte-integrity probe failed: ${result.stderr || result.stdout}`,
);
}
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
);
it('release and PR macOS builds pin each target to a matching runner architecture', () => {
for (const workflowName of ['release.yml', 'tauri-build-pr.yml']) {
const workflow = fs.readFileSync(
path.join(ROOT, '.github', 'workflows', workflowName),
'utf-8',
);
expect(workflow).toContain('target: aarch64-apple-darwin');
expect(workflow).toContain('arch: arm64');
expect(workflow).toContain('runner: macos-15');
expect(workflow).toContain('target: x86_64-apple-darwin');
expect(workflow).toContain('arch: x64');
expect(workflow).toContain('runner: macos-15-intel');
expect(workflow).toContain('Verify runner architecture');
}
});
it('release workflow does NOT publish a broken (empty-signature) updater manifest', () => {
// The update-manifest job was removed with the updater config: it published
// latest.json with empty signatures, which every client would reject. Re-add
// it together with real updater signing (see tauri.conf updater note).
const workflow = fs.readFileSync(
path.join(ROOT, '.github', 'workflows', 'release.yml'),
'utf-8',
);
// No active `update-manifest:` job (a re-enable note in comments is fine).
expect(workflow).not.toMatch(/^\s*update-manifest:/m);
});
it('release workflow stages sidecar dependencies before packaging', () => {
// P0-2: the packaged sidecar require()s esbuild-externalized deps that must
// be staged into resources/node_modules or it dies with MODULE_NOT_FOUND.
const workflow = fs.readFileSync(
path.join(ROOT, '.github', 'workflows', 'release.yml'),
'utf-8',
);
expect(workflow).toContain('stage-sidecar-deps');
});
it('Windows desktop workflows verify isolated packaged hook lifecycles after staging', () => {
const workflows = [
{
name: 'release.yml',
windowsJob: ' build-windows-prebuilt:',
nextJob: ' sign-windows:',
},
{
name: 'tauri-build-pr.yml',
windowsJob: ' verify-windows:',
nextJob: ' verify-macos:',
},
];
for (const { name, windowsJob, nextJob } of workflows) {
const workflow = fs.readFileSync(
path.join(ROOT, '.github', 'workflows', name),
'utf-8',
);
const windowsStart = workflow.indexOf(windowsJob);
const nextStart = workflow.indexOf(nextJob, windowsStart);
expect(windowsStart).toBeGreaterThanOrEqual(0);
expect(nextStart).toBeGreaterThan(windowsStart);
const windowsSteps = workflow.slice(windowsStart, nextStart);
const stageIndex = windowsSteps.indexOf('node scripts/stage-sidecar-deps.mjs');
const lifecycleIndex = windowsSteps.indexOf('hook-packages-runtime.test.ts');
expect(stageIndex).toBeGreaterThanOrEqual(0);
expect(lifecycleIndex).toBeGreaterThan(stageIndex);
expect(windowsSteps).toContain('WAGGLE_VERIFY_STAGED_HOOK_RUNTIME');
expect(windowsSteps).toContain('runs staged Tauri hook lifecycles');
}
});
it('PR Windows workflow certifies the locally built NSIS lifecycle before upload', () => {
const workflow = fs.readFileSync(
path.join(ROOT, '.github', 'workflows', 'tauri-build-pr.yml'),
'utf-8',
);
const windowsStart = workflow.indexOf(' verify-windows:');
const macStart = workflow.indexOf('\n verify-macos:', windowsStart);
expect(windowsStart).toBeGreaterThanOrEqual(0);
expect(macStart).toBeGreaterThan(windowsStart);
const windowsSteps = workflow.slice(windowsStart, macStart);
const buildIndex = windowsSteps.indexOf('Build Tauri (Windows)');
const certificateIndex = windowsSteps.indexOf('Certify Windows Solo installer lifecycle');
const uploadIndex = windowsSteps.indexOf('Upload Windows artifacts');
expect(buildIndex).toBeGreaterThanOrEqual(0);
expect(certificateIndex).toBeGreaterThan(buildIndex);
expect(uploadIndex).toBeGreaterThan(certificateIndex);
expect(windowsSteps).toContain('--bundles nsis');
expect(windowsSteps).toContain('npm ci --prefix app --ignore-scripts');
expect(windowsSteps).toContain('node node_modules/@tauri-apps/cli/tauri.js build');
expect(windowsSteps).toContain('-ExpectedSourceRevision $env:GITHUB_SHA');
expect(windowsSteps).not.toContain('-RequireAuthenticodeSignature');
expect(windowsSteps).not.toContain('-VerifyManagedModel');
expect(windowsSteps).not.toContain('-RequireVersionToVersionUpgrade');
expect(windowsSteps).not.toContain('-PreviousInstallerPath');
});
it('PR Windows workflow reports the exact worktree mutation boundary around Tauri', () => {
const workflow = fs.readFileSync(
path.join(ROOT, '.github', 'workflows', 'tauri-build-pr.yml'),
'utf-8',
);
const parsedWorkflow = parseYaml(workflow) as {
jobs?: Record<
string,
{
steps?: Array<{
name?: string;
id?: string;
if?: unknown;
run?: string;
'continue-on-error'?: unknown;
}>;
}
>;
};
const windowsSteps = parsedWorkflow.jobs?.['verify-windows']?.steps ?? [];
const namedStep = (name: string) => {
const matches = windowsSteps.filter((step) => step.name === name);
expect(matches).toHaveLength(1);
return matches[0]!;
};
const preBuild = namedStep('Verify repository cleanliness before Tauri build');
const build = namedStep('Build Tauri (Windows)');
const postBuild = namedStep('Report repository changes after Tauri build');
const certificate = namedStep('Certify Windows Solo installer lifecycle');
expect(windowsSteps.indexOf(preBuild)).toBeLessThan(windowsSteps.indexOf(build));
expect(windowsSteps.indexOf(build)).toBeLessThan(windowsSteps.indexOf(postBuild));
expect(windowsSteps.indexOf(postBuild)).toBeLessThan(windowsSteps.indexOf(certificate));
expect(build.id).toBe('tauri-build-windows');
expect(postBuild.if).toBe(
"${{ always() && steps.tauri-build-windows.outcome != 'skipped' }}",
);
for (const diagnosticStep of [preBuild, postBuild]) {
const run = diagnosticStep.run ?? '';
expect([
...run.matchAll(/git status --porcelain=v1 --untracked-files=all/g),
]).toHaveLength(1);
expect(run).toContain('if ($LASTEXITCODE -ne 0)');
expect(run).toContain('if ($sourceStatus.Count -ne 0)');
expect(run).not.toMatch(/git\s+(?:reset|clean|checkout|restore|stash)\b/i);
expect(run).not.toMatch(/\b(?:Remove-Item|Clear-Content|Set-Content)\b/i);
expect(diagnosticStep['continue-on-error']).toBeUndefined();
}
const postBuildRun = postBuild.run ?? '';
expect(postBuildRun).toContain(
'$trackedPaths = @(& git diff --name-only --diff-filter=ACDMRTUXB)',
);
expect(postBuildRun).toContain('& git rev-parse "HEAD:$trackedPath"');
expect(postBuildRun).toContain('& git rev-parse ":$trackedPath"');
expect(postBuildRun).toContain('Get-FileHash -LiteralPath $trackedPath -Algorithm SHA256');
expect(postBuildRun).toContain('& git diff --numstat -- $trackedPath');
expect(postBuildRun).not.toContain('git diff --no-ext-diff');
expect(postBuildRun).not.toContain('$diffLines');
expect(postBuildRun.indexOf('$trackedPaths = @(')).toBeLessThan(
postBuildRun.indexOf('throw "Windows Tauri build mutated repository worktree.'),
);
});
it.runIf(process.platform === 'win32')(
'installer certifier reports every dirty tracked and untracked path without mutation',
() => {
const certifier = fs
.readFileSync(path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'), 'utf-8')
.replace(/\r\n/g, '\n');
const helperStart = certifier.indexOf('function Assert-CleanRepositoryWorktree {');
const helperEnd = certifier.indexOf(
'\nfunction Test-CertificateTimestamp {',
helperStart,
);
expect(helperStart).toBeGreaterThanOrEqual(0);
expect(helperEnd).toBeGreaterThan(helperStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-source-clean-'));
const repositoryRoot = path.join(probeRoot, 'repository');
const probePath = path.join(probeRoot, 'probe.ps1');
const runGit = (args: string[]) => spawnSync('git', args, {
cwd: repositoryRoot,
encoding: 'utf-8',
timeout: 30_000,
windowsHide: true,
});
const status = () => runGit([
'status',
'--porcelain=v1',
'--untracked-files=all',
]);
try {
fs.mkdirSync(repositoryRoot, { recursive: true });
expect(runGit(['init']).status).toBe(0);
fs.writeFileSync(path.join(repositoryRoot, 'tracked.txt'), 'clean\n', 'utf-8');
expect(runGit(['add', 'tracked.txt']).status).toBe(0);
expect(runGit([
'-c',
'user.name=Waggle Fixture',
'-c',
'user.email=fixture@waggle.invalid',
'commit',
'-m',
'fixture',
]).status).toBe(0);
fs.writeFileSync(
probePath,
`${certifier.slice(helperStart, helperEnd)}\nAssert-CleanRepositoryWorktree -GitExecutable 'git' -RepositoryRoot $args[0]\n`,
'utf-8',
);
const cleanResult = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath, repositoryRoot],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
expect(cleanResult.status, cleanResult.stderr || cleanResult.stdout).toBe(0);
fs.writeFileSync(path.join(repositoryRoot, 'tracked.txt'), 'dirty\n', 'utf-8');
fs.mkdirSync(path.join(repositoryRoot, 'nested'), { recursive: true });
fs.writeFileSync(
path.join(repositoryRoot, 'nested', 'untracked.txt'),
'untracked\n',
'utf-8',
);
const before = status();
expect(before.status, before.stderr || before.stdout).toBe(0);
const trackedBefore = fs.readFileSync(path.join(repositoryRoot, 'tracked.txt'));
const untrackedBefore = fs.readFileSync(
path.join(repositoryRoot, 'nested', 'untracked.txt'),
);
const dirtyResult = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath, repositoryRoot],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
const dirtyOutput = `${dirtyResult.stdout ?? ''}\n${dirtyResult.stderr ?? ''}`;
expect(dirtyResult.status).not.toBe(0);
expect(dirtyOutput).toContain(' M tracked.txt');
expect(dirtyOutput).toContain('?? nested/untracked.txt');
const after = status();
expect(after.status, after.stderr || after.stdout).toBe(0);
expect(after.stdout).toBe(before.stdout);
expect(fs.readFileSync(path.join(repositoryRoot, 'tracked.txt'))).toEqual(
trackedBefore,
);
expect(
fs.readFileSync(path.join(repositoryRoot, 'nested', 'untracked.txt')),
).toEqual(untrackedBefore);
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
60_000,
);
it('PR desktop verification runs when either Windows workflow changes', () => {
const workflow = fs.readFileSync(
path.join(ROOT, '.github', 'workflows', 'tauri-build-pr.yml'),
'utf-8',
);
expect([...workflow.matchAll(/\.github\/workflows\/release\.yml/g)]).toHaveLength(2);
expect([...workflow.matchAll(/\.github\/workflows\/tauri-build-pr\.yml/g)]).toHaveLength(2);
expect([...workflow.matchAll(/'scripts\/\*\*'/g)]).toHaveLength(2);
const windowsJobStart = workflow.indexOf(' verify-windows:');
const windowsJobEnd = workflow.indexOf('\n verify-macos:', windowsJobStart);
expect(windowsJobStart).toBeGreaterThanOrEqual(0);
expect(windowsJobEnd).toBeGreaterThan(windowsJobStart);
const windowsJob = workflow.slice(windowsJobStart, windowsJobEnd);
expect(windowsJob).toContain('runs-on: windows-latest');
expect([
...windowsJob.matchAll(/- name: Verify Windows release-mode and publication guards/g),
]).toHaveLength(1);
expect(windowsJob).toContain('shell: pwsh');
expect(windowsJob).toContain("WAGGLE_REQUIRE_PWSH7: '1'");
expect(windowsJob).toContain(
'packages/server/tests/tauri-config.test.ts -t "CI/CD Configuration"',
);
expect(windowsJob.indexOf('- name: Install dependencies')).toBeLessThan(
windowsJob.indexOf('- name: Verify Windows release-mode and publication guards'),
);
expect(
windowsJob.indexOf('- name: Verify Windows release-mode and publication guards'),
).toBeLessThan(windowsJob.indexOf('- name: Install locked Tauri CLI'));
});
it('desktop workflows pin every third-party action to a full commit SHA', () => {
for (const name of ['release.yml', 'tauri-build-pr.yml']) {
const workflow = fs.readFileSync(
path.join(ROOT, '.github', 'workflows', name),
'utf-8',
);
const actionRefs = [...workflow.matchAll(/uses:\s+[^@\s]+@([^\s#]+)/g)]
.map((match) => match[1]);
expect(actionRefs.length).toBeGreaterThan(0);
for (const actionRef of actionRefs) {
expect(actionRef).toMatch(/^[0-9a-f]{40}$/);
}
}
});
it('Windows installer certificate is fail-closed across isolated boot, repair, and uninstall', () => {
const script = fs.readFileSync(
path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'),
'utf-8',
);
expect(script.startsWith('#Requires -Version 7.0')).toBe(true);
expect(script).toContain('Set-StrictMode -Version Latest');
expect(script).toContain('"/S /D=$installDir"');
expect(script).toContain('function Assert-SafeReceiptPath');
expect(script).toContain('Assert-SafeReceiptPath $ReceiptPath');
expect(script).toContain('function Reserve-CertificateReceiptPath');
expect(script).toContain(
'$receiptReservation = Reserve-CertificateReceiptPath $ReceiptPath',
);
expect(script).toContain(
'Write-CertificateReceipt $receiptReservation $receiptJson',
);
expect(script).toContain('Receipt path already exists; refusing to overwrite');
expect(script).toContain('Receipt parent must not be a reparse point');
expect(script).not.toContain('Set-Content -LiteralPath $ReceiptPath');
expect(
script.indexOf('$receiptReservation = Reserve-CertificateReceiptPath $ReceiptPath'),
).toBeLessThan(
script.indexOf('$scratchOwnershipMarker = New-CertificateScratchRoot'),
);
expect(script).toContain('function New-CertificateScratchRoot');
expect(script).toContain('function Remove-CertificateScratchRoot');
expect(script).toContain('[System.IO.FileMode]::CreateNew');
expect(script).toContain(
'$scratchOwnershipMarker = New-CertificateScratchRoot $scratchRoot $runId',
);
expect(script).toContain(
'Remove-CertificateScratchRoot $scratchRoot $scratchOwnershipMarker $runId',
);
expect(script).not.toContain(
'New-Item -ItemType Directory -Path $scratchRoot -Force | Out-Null',
);
expect(script).not.toContain(
'Remove-Item -LiteralPath $resolvedRoot -Recurse -Force',
);
expect(script).not.toContain(
'Remove-Item -LiteralPath $scratchRoot -Recurse -Force',
);
expect(script).toContain("$env:WAGGLE_PORT = '3333'");
expect(script).toContain('Assert-TcpPortAvailable 3333');
expect(script).toContain("$profileDataDir = Join-Path $env:USERPROFILE '.waggle'");
expect(script.indexOf('Assert-TcpPortAvailable 3333')).toBeLessThan(
script.indexOf('New-Item -ItemType Directory -Path $profileDataDir'),
);
expect(script).toContain('$dataDir = $profileDataDir');
expect(script).not.toContain("$dataDir = Join-Path $scratchRoot 'data'");
expect(script).not.toContain('$env:WAGGLE_DATA_DIR = $dataDir');
expect(script).toContain("'OPENROUTER_API_KEY'");
expect(script).toContain("resources\\node.exe");
expect(script).toContain("resources\\service.js");
expect(script).toContain("resources\\marketplace.db");
expect(script).not.toContain('--install-links');
expect(script).toContain("$offlinePackageTar = Join-Path $isolationPath 'tar.exe'");
expect(script).toContain(
"$offlinePackageArchive = Join-Path $scratchRoot 'waggle-offline-install-probe-1.0.0.tgz'",
);
expect(script).toContain('Invoke-RawProcess $offlinePackageTar');
expect(script).toContain('-- $offlinePackageArchive 2>&1');
expect(script).toContain(
'Bundled npm installed the local offline package as a reparse point.',
);
expect(script).toContain('prepare-ran.txt');
expect(script).toContain('prepack-ran.txt');
expect(script).toContain('install-ran.txt');
expect(script).toContain("$receipt.Contains('scratchCleanupError')");
expect(script).toContain("Join-Path $dataDir 'marketplace.db'");
const jsonRequestHelper = script.slice(
script.indexOf('function Invoke-JsonRequest {'),
script.indexOf('\nfunction Invoke-JsonPostRequest {'),
);
expect(jsonRequestHelper).toContain(
'[ValidateRange(1, 30)] [int]$TimeoutSeconds = 5',
);
expect(jsonRequestHelper).toContain('-TimeoutSec $TimeoutSeconds');
const marketplaceProbeStart = script.indexOf(
'$marketplace = Invoke-JsonRequest',
);
const marketplaceProbe = script.slice(
marketplaceProbeStart,
script.indexOf('$marketplacePackages =', marketplaceProbeStart),
);
expect(marketplaceProbe).toContain('-TimeoutSeconds 30');
expect(script).toContain(
'$baseUrl/api/marketplace/search?type=mcp&source=mcp_registry&limit=100',
);
expect(script).toContain('marketplaceResourceSha256');
expect(script).toContain("$receipt.checks['marketplaceResource']");
expect(script).toContain("$receipt.checks['marketplaceApi']");
expect(script).toContain('Same-version repair did not restore resources/marketplace.db');
expect(script).toContain('/v1/health/liveliness');
expect(script).toContain(
'$proxy = Invoke-BuiltInProxyLivenessProbe -Uri "$baseUrl/v1/health/liveliness"',
);
expect(script).toContain('/api/auth/session-token');
expect(script).toContain('$BaseUrl/api/workspaces');
expect(script).toContain('$BaseUrl/api/memory/frames?extract=false');
expect(script).toContain('New-CertificateLifecycleData');
expect(script).toContain('Assert-CertificateLifecycleData');
expect(script).toContain('Get-CertificateDataManifest');
expect(script).toContain('Assert-CertificateDataManifest');
expect(script).toContain('Get-CertificateDataManifestDigest');
expect(script).toContain('Get-CertificateRelativePath');
expect(script).toContain('function Get-ExternalProfileRootSnapshot');
expect(script).toContain('function Assert-ExternalProfileRootsUnchanged');
expect(script).toContain('Get-ChildItem -LiteralPath $parentPath -Force');
expect(script).toContain("Join-Path $env:USERPROFILE '.hive-mind'");
expect(script).toContain("Join-Path $env:USERPROFILE '.ollama'");
expect(script).toContain('ConvertTo-Json -InputObject @($manifest)');
expect(script).toContain('$externalProfileRootsPreProven = $true');
expect(script).toContain("$receipt.checks['externalProfileRootsUnchanged'] = $true");
expect(script).toContain("$receipt['externalProfileIsolationError']");
expect(script).toContain("$receipt.Contains('externalProfileIsolationError')");
for (const cacheVariable of [
'OLLAMA_MODELS',
'HF_HOME',
'HF_HUB_CACHE',
'TRANSFORMERS_CACHE',
'XDG_CACHE_HOME',
]) {
expect(script).toContain(`'${cacheVariable}'`);
}
expect(script).not.toContain('[System.IO.Path]::GetRelativePath');
expect(script).toContain("$receipt.checks['defaultProfileDataDir']");
expect(script).toContain("$receipt.checks['realWorkspaceAndMemorySeeded']");
expect(script).toContain("$receipt.checks['upgradeRealWorkspaceAndMemoryPreserved']");
expect(script).toContain("$receipt.checks['repairRealWorkspaceAndMemoryPreserved']");
expect(script).toContain("$receipt.checks['uninstallRealWorkspaceAndMemoryPreserved']");
expect(script).toContain('Remove-CertificateProfileData');
expect(script).not.toContain('Remove-CertificateProfileMarker');
expect(script).not.toContain('$_.path -cne $markerRelativePath');
const finalUninstallerCleanup = script.match(
/if \(Test-Path -LiteralPath \$uninstaller -PathType Leaf\) \{\s*try \{([\s\S]*?)Invoke-RawProcess \$uninstaller/,
)?.[1];
expect(finalUninstallerCleanup).toBeDefined();
const shutdownProofReset =
finalUninstallerCleanup?.indexOf('$runtimeConfirmedStopped = $false') ?? -1;
const preUninstallProcessAssertion =
finalUninstallerCleanup?.indexOf('Assert-NoForeignWaggleProcesses') ?? -1;
expect(shutdownProofReset).toBeGreaterThanOrEqual(0);
expect(preUninstallProcessAssertion).toBeGreaterThanOrEqual(0);
expect(shutdownProofReset).toBeLessThan(preUninstallProcessAssertion);
expect(script).toContain("$baseUrl/api/chat");
expect(script).toContain('No AI model is ready');
expect(script).toContain("$receipt.checks['noModelChatSetupRequired']");
expect(script).toContain("$baseUrl/api/tier");
expect(script).toContain("$receipt.certifiedTier = 'FREE'");
expect(script).toContain("$receipt.checks['soloTier']");
expect(script).toContain("$receipt.checks['previousSoloTier']");
expect(script).toContain("$receipt.checks['repairSoloTier']");
expect(script).toMatch(
/if \(-not \$RequireVersionToVersionUpgrade\) \{[\s\S]*?\$chatProbeMessage/,
);
expect(script).toContain('unauthenticatedProtectedRoute');
expect(script).toContain("'WAGGLE_TRUST_LOCALHOST'");
expect(script).toContain("'WAGGLE_SQLITE_VEC_PATH'");
expect(script).toContain("'ONNXRUNTIME_NODE_BINDING_PATH'");
expect(script).toContain("'VOYAGE_API_KEY'");
expect(script).toContain("'EMBEDDING_PROVIDER'");
expect(script).toContain('environmentSnapshot');
expect(script).toContain('environmentRestored');
expect(script).toContain("$isolationPath = Join-Path $scratchRoot 'isolated-path'");
expect(script).toContain('$env:PATH = $isolationPath');
expect(script).not.toContain('$env:PATH = "$env:SystemRoot\\System32;$env:SystemRoot"');
expect(script).toContain('/api/embedding/status');
expect(script).toContain('/api/local-inference/status');
expect(script).toContain('/api/local-inference/bootstrap');
expect(script).toContain('/api/local-inference/pull');
expect(script).toContain('[switch]$VerifyManagedModel');
expect(script).toContain("[Environment]::GetFolderPath('System')");
expect(script).toContain("@('tar.exe', 'taskkill.exe')");
expect(script).toContain("$receipt.checks['windowsInboxTools']");
expect(script).toContain('$managedOperationTimeoutSeconds = 3600');
expect(script).toContain('$receipt.managedModelVerified = $true');
expect(script).toContain("$receipt.checks['managedModelChat']");
expect(script).toContain('$baseUrl/v1/chat/completions');
expect(script).toContain('model = "ollama/$managedModelName"');
expect(script).toContain("$receipt.checks['managedModelProxyRestartChat']");
expect(script).toContain("$receipt.checks['previousManagedModelSeeded']");
expect(script).toContain("$receipt.checks['upgradeManagedModelPreserved']");
expect(script).toContain("$receipt.checks['repairManagedModelDigestPreserved']");
expect(script).toContain('managedModelDigest');
expect(script).toContain('managedRuntimeCleanup');
expect(script).toContain('Stop-InstalledProcesses $appExecutable $serviceScript $managedRuntimeRoot');
expect(script).toContain('dockerRequired');
expect(script).toContain('sameVersionRepair');
expect(script).toContain('$firstProcess.HasExited');
expect(script).toContain('$secondProcess.HasExited');
expect(script).toContain('Wait-ForInstalledRuntimeStop');
expect(script).toContain('Assert-NoForeignWaggleProcesses');
expect(script).toContain('function Assert-CertificateUninstallPostconditions');
const uninstallPostconditionCalls = [
...script.matchAll(/^\s+Assert-CertificateUninstallPostconditions\s+`/gm),
];
expect(uninstallPostconditionCalls).toHaveLength(2);
const outerFinallyStart = script.lastIndexOf('} finally {');
const successUninstallStart = script.indexOf(
"$receipt.checks['uninstallerCleanup'] = $true",
);
expect(successUninstallStart).toBeGreaterThanOrEqual(0);
expect(outerFinallyStart).toBeGreaterThan(successUninstallStart);
expect(
script.slice(successUninstallStart, outerFinallyStart),
).toContain('Assert-CertificateUninstallPostconditions `');
expect(script.slice(outerFinallyStart)).toContain(
'Assert-CertificateUninstallPostconditions `',
);
const uninstallPostconditionHelper = script.match(
/function Assert-CertificateUninstallPostconditions \{([\s\S]*?)\r?\n\}/,
)?.[1];
expect(uninstallPostconditionHelper).toBeDefined();
expect(uninstallPostconditionHelper).toContain('Wait-ForPathState $InstallDir $false');
expect(uninstallPostconditionHelper).toContain(
'Wait-ForPathState $UninstallRegistry $false',
);
expect(uninstallPostconditionHelper).toContain(
'Wait-ForPathState $ProductRegistry $false',
);
expect(uninstallPostconditionHelper).toContain(
'Test-RegistryValue $RunRegistry $RunRegistryValue',
);
expect(uninstallPostconditionHelper).toContain('Wait-ForPathState $shortcut $false');
expect(uninstallPostconditionHelper).toContain('Wait-ForInstalledRuntimeStop');
expect(uninstallPostconditionHelper).toContain(
'-ManagedRuntimeRoot $ManagedRuntimeRoot -AdditionalPorts $AdditionalPorts',
);
expect(uninstallPostconditionHelper).toContain('Assert-NoForeignWaggleProcesses');
expect(uninstallPostconditionHelper).toContain('Assert-TcpPortAvailable $Port');
expect(script).toContain('foreignProcessCollisionGuard');
expect(script).not.toMatch(/Get-CimInstance[^\r\n]+-ErrorAction\s+SilentlyContinue/);
expect(script).toContain('Stop-StartedProcessTree');
expect(script).toContain('"/PID $($Process.Id) /T /F"');
expect(script).toContain('repairRegistrations');
expect(script).toContain('runRegistryCollisionGuard');
expect(script).toContain('UninstallString');
expect(script).toContain("Invoke-RawProcess $registeredUninstaller '/S'");
expect(script).toContain('Wait-ForPathState $uninstallRegistry $false 30');
expect(script).toContain("HKCU:\\Software\\egzakta\\Waggle");
expect(script).toContain('Remove-CertificateProductRegistry');
expect(script).toContain('Clear-AbandonedCertificateProductRegistry');
expect(script).toContain('certificateRegistryCleanup');
expect(script).toContain('profileDataDeletionAbsent');
expect(script).toContain('baseAppDataDeletionNeutralized');
expect(script).toContain('profileDataPathPreserved');
expect(script).toContain('configuredDataDirPreserved');
expect(script).not.toContain('uninstallPreservedData');
expect(script).not.toContain('embeddingModelVerified');
expect(script).toContain('RequireAuthenticodeSignature');
expect(script).toContain('ExpectedSignerThumbprint');
expect(script).toContain('ExpectedSignerSubject');
expect(script).toContain('Exactly one expected signer identity binding is required');
expect(script).toContain('function Assert-LifecycleReceiptApprovedSigner');
expect([
...script.matchAll(/^\s+Assert-LifecycleReceiptApprovedSigner `$/gm),
]).toHaveLength(1);
expect(script).toContain('[System.StringComparison]::Ordinal');
expect(script).not.toContain(
'CN=EGZAKTA DOO BEOGRAD, O=EGZAKTA DOO BEOGRAD, L=Amsterdam, C=NL',
);
expect(script).toContain('ExpectedSourceRevision');
expect(script).toContain('function Get-SidecarProvenance');
expect(script).toContain('Packaged resources/service.js does not match a clean sidecar rebuild.');
expect(script).toContain("$receipt.checks['sidecarSourceProvenance']");
expect(script).toContain('$receipt.evidence.sidecarBundleSha256');
expect(script).toContain('$receipt.evidence.sidecarProvenanceSha256');
expect(script).toContain('$receipt.evidence.sidecarSourceInputCount');
expect(script).toContain('RequireVersionToVersionUpgrade');
expect(script).toContain('PreviousInstallerPath');
expect(script).toContain('ExpectedPreviousInstallerSha256');
expect(script).toContain('ExpectedPreviousVersion');
expect(script).toContain('ExpectedPreviousSourceRevision');
expect(script).toContain('ExpectedCandidateInstallerSha256');
expect(script).toContain('ExpectedCandidateVersion');
expect(script).toContain('version-to-version-upgrade');
expect(script).toContain('Previous installer SHA-256 must be exactly 64 hexadecimal characters.');
expect(script).toContain('Candidate installer SHA-256 must be exactly 64 hexadecimal characters.');
expect(script).toContain('Previous source revision must be exactly 40 hexadecimal characters.');
expect(script).toContain('Previous installer and candidate installer must be distinct files.');
expect(script).toContain('Candidate version must be newer than the previous version.');
expect(script).toContain("$receipt.checks['previousInstallerHash']");
expect(script).toContain("$receipt.checks['previousInstallerAuthenticodeSignature']");
expect(script).toContain("$receipt.checks['previousInstalledAppAuthenticodeSignature']");
expect(script).toContain("$receipt.checks['versionOrder']");
expect(script).toContain("$receipt.checks['versionToVersionUpgrade']");
expect(script).toContain("$receipt.checks['upgradeSameInstallDirectory']");
expect(script).toContain("$receipt.checks['upgradeConfiguredDataPreserved']");
expect(script).toContain("$receipt.checks['upgradeProfileDataPreserved']");
expect(script).toContain("$receipt.checks['upgradeVaultKeyPreserved']");
expect(script).toContain("$receipt.checks['relaunchAfterUpgrade']");
expect(script).toContain('Candidate installer before upgrade');
expect(script).toContain('Candidate installer after upgrade');
expect(script).toContain('Candidate installer before repair');
expect(script).toContain('Candidate installer after repair');
expect(script).toContain('previousSourceRevision = $ExpectedPreviousSourceRevision');
expect(script).toContain('Remove-CertificationControlEnvironment');
expect(script).toContain("'^(?:ACTIONS_|GITHUB_|RUNNER_|WAGGLE_UPGRADE_BASE_)'");
expect(script).toContain("'GH_TOKEN', 'GITHUB_TOKEN'");
expect(script).toContain("'WINDOWS_CODESIGN_APPROVED_SUBJECT'");
expect(script).toContain("'WINDOWS_CODESIGN_APPROVED_THUMBPRINT'");
expect(script).toContain("'WAGGLE_APPROVED_CODESIGN_SUBJECT'");
expect(script).toContain("'WAGGLE_CODESIGN_SUBJECT'");
expect(script).toContain("$receipt.checks['candidateInstallerHash']");
const previousInstallIndex = script.indexOf('Invoke-RawProcess $PreviousInstallerPath');
const previousLaunchIndex = script.indexOf('$previousProcess = Start-InstalledApp');
const candidateInstallIndex = script.indexOf('Invoke-RawProcess $InstallerPath', previousInstallIndex);
const candidateLaunchIndex = script.indexOf('$firstProcess = Start-InstalledApp');
const candidateRepairIndex = script.lastIndexOf('Invoke-RawProcess $InstallerPath');
const previousSoloTierIndex = script.indexOf("$receipt.checks['previousSoloTier']");
const previousManagedModelSeedIndex = script.indexOf(
"$receipt.checks['previousManagedModelSeeded']",
);
const upgradeManagedModelPreservedIndex = script.indexOf(
"$receipt.checks['upgradeManagedModelPreserved']",
);
const managedModelProxyRestartIndex = script.indexOf(
"$receipt.checks['managedModelProxyRestartChat']",
);
const repairSoloTierIndex = script.indexOf("$receipt.checks['repairSoloTier']");
const repairManagedModelDigestIndex = script.indexOf(
"$receipt.checks['repairManagedModelDigestPreserved']",
);
const uninstallIndex = script.indexOf("Invoke-RawProcess $registeredUninstaller '/S'");
expect(previousInstallIndex).toBeGreaterThanOrEqual(0);
expect(previousLaunchIndex).toBeGreaterThan(previousInstallIndex);
expect(previousSoloTierIndex).toBeGreaterThan(previousLaunchIndex);
expect(previousManagedModelSeedIndex).toBeGreaterThan(previousSoloTierIndex);
expect(previousManagedModelSeedIndex).toBeLessThan(candidateInstallIndex);
expect(candidateInstallIndex).toBeGreaterThan(previousLaunchIndex);
expect(candidateLaunchIndex).toBeGreaterThan(candidateInstallIndex);
expect(upgradeManagedModelPreservedIndex).toBeGreaterThan(candidateLaunchIndex);
expect(upgradeManagedModelPreservedIndex).toBeLessThan(candidateRepairIndex);
expect(candidateRepairIndex).toBeGreaterThan(candidateLaunchIndex);
expect(repairSoloTierIndex).toBeGreaterThan(candidateRepairIndex);
expect(repairManagedModelDigestIndex).toBeGreaterThan(repairSoloTierIndex);
expect(repairManagedModelDigestIndex).toBeLessThan(managedModelProxyRestartIndex);
expect(repairSoloTierIndex).toBeLessThan(managedModelProxyRestartIndex);
expect(managedModelProxyRestartIndex).toBeGreaterThan(candidateRepairIndex);
expect(managedModelProxyRestartIndex).toBeLessThan(uninstallIndex);
expect(uninstallIndex).toBeGreaterThan(candidateRepairIndex);
expect(script).toContain('sourceFilesClean');
expect(script).toContain('status --porcelain=v1 --untracked-files=all');
expect(script).toMatch(
/\$gitCommand\s*=\s*Get-Command git -CommandType Application -ErrorAction SilentlyContinue\s*\|\s*Select-Object -First 1/,
);
expect(script).toContain('schemaVersion = 4');
expect(script).toContain('-UseBasicParsing');
expect(script).toContain('authenticodeStatus');
expect(script).toContain('signerThumbprint');
expect(script).toContain('TimeStamperCertificate');
expect(script).toContain('timestampAuthorityThumbprint');
expect(script).toContain('SignatureType');
expect(script).toContain('portable embedded Authenticode signature');
expect(script).toContain('installedAppAuthenticodeSignature');
expect(script).toContain('Installed Waggle executable');
expect(script).toContain('certifierSha256');
expect(script).toContain('installerHookSha256');
expect(script).toContain('generatedInstallerScriptSha256');
expect(script).toContain('generatedInstallerInclude');
expect(script).toContain('$installerHookFile.LastWriteTimeUtc');
expect(script).toContain('!macro\\s+NSIS_HOOK_POSTUNINSTALL\\b');
expect(script).toContain('!include\\s+"(?<path>[^"]+)"\\s*$');
expect(script).not.toContain("$generatedInstallerContent.Contains('NSIS_HOOK_POSTUNINSTALL')");
expect(script).not.toContain("$receipt.checks['builtInProxy']");
expect(script).not.toContain("$receipt.checks['uninstallCleanup']");
expect(script).toContain("$receipt.checks['uninstallerCleanup']");
expect(script).toContain('embeddingPayloadReady');
expect(script).toContain('Assert-VaultKeyAclRestricted');
expect(script).toContain("Join-Path $dataDir '.vault-key'");
expect(script).toContain('AreAccessRulesProtected');
expect(script).toContain('[Security.Principal.WindowsIdentity]::GetCurrent().User');
expect(script).toContain("$receipt.checks['vaultKeyAclRestricted']");
expect(script).toContain('sourceRevision');
expect(script).toContain('certificateRunId');
expect(script).toContain('$desktopShortcut');
expect(script).toContain('$startMenuShortcuts');
expect(script).toContain('Assert-SafeScratchRoot');
expect(script).not.toMatch(/Get-Process\s+(?:-Name\s+)?['"]?waggle/i);
expect(script.lastIndexOf(
'Remove-CertificateScratchRoot $scratchRoot $scratchOwnershipMarker $runId',
))
.toBeLessThan(script.lastIndexOf('$receipt | ConvertTo-Json'));
});
it.runIf(process.platform === 'win32')(
'Windows installer external-profile proof detects created and changed roots',
() => {
const script = fs
.readFileSync(
path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'),
'utf-8',
)
.replace(/\r\n/g, '\n');
const helperStart = script.indexOf('function Assert-True {');
const helperEnd = script.indexOf('\nfunction Get-HttpStatusCode {', helperStart);
expect(helperStart).toBeGreaterThanOrEqual(0);
expect(helperEnd).toBeGreaterThan(helperStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-profile-proof-'));
const probePath = path.join(probeRoot, 'profile-proof.ps1');
const escapedRoot = probeRoot.replace(/'/g, "''");
const fixtureSource = `
$fixtureRoot = '${escapedRoot}'
$absentRoot = Join-Path $fixtureRoot 'absent-root'
$absentSnapshot = Get-ExternalProfileRootSnapshot -Name '.absent' -Path $absentRoot
if ($absentSnapshot.existedBefore) { throw 'Absent fixture was reported present' }
Set-Content -LiteralPath $absentRoot -Value 'unexpected file' -Encoding UTF8
$fileMutationRejected = $false
try { Assert-ExternalProfileRootsUnchanged @($absentSnapshot) } catch { $fileMutationRejected = $true }
if (-not $fileMutationRejected) { throw 'External file root was accepted as absent' }
Remove-Item -LiteralPath $absentRoot -Force
New-Item -ItemType Directory -Path $absentRoot | Out-Null
$absentMutationRejected = $false
try { Assert-ExternalProfileRootsUnchanged @($absentSnapshot) } catch { $absentMutationRejected = $true }
if (-not $absentMutationRejected) { throw 'Created external root was accepted' }
Remove-Item -LiteralPath $absentRoot -Recurse -Force
$junctionRoot = Join-Path $fixtureRoot 'dangling-junction'
$junctionSnapshot = Get-ExternalProfileRootSnapshot -Name '.junction' -Path $junctionRoot
$junctionTarget = Join-Path $fixtureRoot 'junction-target'
New-Item -ItemType Directory -Path $junctionTarget | Out-Null
New-Item -ItemType Junction -Path $junctionRoot -Target $junctionTarget | Out-Null
Remove-Item -LiteralPath $junctionTarget -Recurse -Force
$junctionMutationRejected = $false
try { Assert-ExternalProfileRootsUnchanged @($junctionSnapshot) } catch { $junctionMutationRejected = $true }
if (-not $junctionMutationRejected) { throw 'Dangling junction was accepted as absent' }
Remove-Item -LiteralPath $junctionRoot -Force
$emptyRoot = Join-Path $fixtureRoot 'empty-root'
New-Item -ItemType Directory -Path $emptyRoot | Out-Null
$emptySnapshot = Get-ExternalProfileRootSnapshot -Name '.empty' -Path $emptyRoot
if ([string]::IsNullOrWhiteSpace([string]$emptySnapshot.manifestSha256)) {
throw 'Empty external root did not receive a stable manifest digest'
}
Assert-ExternalProfileRootsUnchanged @($emptySnapshot)
$presentRoot = Join-Path $fixtureRoot 'present-root'
New-Item -ItemType Directory -Path $presentRoot | Out-Null
Set-Content -LiteralPath (Join-Path $presentRoot 'sentinel.txt') -Value 'before' -Encoding UTF8
$presentSnapshot = Get-ExternalProfileRootSnapshot -Name '.present' -Path $presentRoot
Assert-ExternalProfileRootsUnchanged @($presentSnapshot)
Set-Content -LiteralPath (Join-Path $presentRoot 'sentinel.txt') -Value 'after' -Encoding UTF8
$contentMutationRejected = $false
try { Assert-ExternalProfileRootsUnchanged @($presentSnapshot) } catch { $contentMutationRejected = $true }
if (-not $contentMutationRejected) { throw 'Changed external root was accepted' }
`;
try {
fs.writeFileSync(
probePath,
`${script.slice(helperStart, helperEnd)}\n${fixtureSource}`,
'utf-8',
);
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
if (result.status !== 0) {
throw new Error(
`Windows external-profile proof probe failed: ${result.stderr || result.stdout}`,
);
}
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
);
it.runIf(process.platform === 'win32')(
'Windows installer timestamp validation survives JSON date coercion under non-US culture',
() => {
const script = fs
.readFileSync(
path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'),
'utf-8',
)
.replace(/\r\n/g, '\n');
const helperStart = script.indexOf('function Test-CertificateTimestamp {');
const helperEnd = script.indexOf(
'\nfunction Assert-ExpectedAuthenticodeSignature {',
helperStart,
);
expect(helperStart).toBeGreaterThanOrEqual(0);
expect(helperEnd).toBeGreaterThan(helperStart);
expect(script).toContain('Test-CertificateTimestamp $frame.timestamp');
expect(script).toContain('Test-CertificateTimestamp $workspace.created');
expect(script).not.toContain('TryParse([string]$frame.timestamp');
expect(script).not.toContain('TryParse([string]$workspace.created');
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-cert-time-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const fixtureSource = String.raw`
$culture = [Globalization.CultureInfo]::GetCultureInfo('sr-Latn-RS')
[Threading.Thread]::CurrentThread.CurrentCulture = $culture
[Threading.Thread]::CurrentThread.CurrentUICulture = $culture
$coercedTimestamp = [datetime]::Parse(
'2026-07-31T23:24:03.123Z',
[Globalization.CultureInfo]::InvariantCulture,
[Globalization.DateTimeStyles]::RoundtripKind
)
$legacyParsed = [DateTimeOffset]::MinValue
if ([DateTimeOffset]::TryParse([string]$coercedTimestamp, [ref]$legacyParsed)) {
throw 'Fixture no longer reproduces the culture-sensitive cast failure'
}
if (-not (Test-CertificateTimestamp $coercedTimestamp)) {
throw 'A valid JSON-coerced DateTime was rejected'
}
if (-not (Test-CertificateTimestamp '2026-07-31T23:24:03.123Z')) {
throw 'A valid ISO timestamp string was rejected'
}
foreach ($invalid in @($null, '', 'not-a-timestamp')) {
if (Test-CertificateTimestamp $invalid) {
throw 'An invalid timestamp was accepted'
}
}
`;
try {
fs.writeFileSync(
probePath,
`${script.slice(helperStart, helperEnd)}\n${fixtureSource}`,
'utf-8',
);
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
if (result.status !== 0) {
throw new Error(
`Windows installer timestamp probe failed: ${result.stderr || result.stdout}`,
);
}
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
);
it.runIf(process.platform === 'win32')(
'Windows installer certificate preserves sentinels when receipt paths are unsafe',
() => {
const script = fs
.readFileSync(
path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'),
'utf-8',
)
.replace(/\r\n/g, '\n');
const helperStart = script.indexOf('function Assert-SafeReceiptPath {');
const helperEnd = script.indexOf(
'\nfunction Assert-SafeScratchRoot {',
helperStart + 1,
);
expect(helperStart).toBeGreaterThanOrEqual(0);
expect(helperEnd).toBeGreaterThan(helperStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-cert-receipt-'));
const outsideRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-cert-outside-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const existingReceipt = path.join(probeRoot, 'existing.json');
const hardlinkTarget = path.join(probeRoot, 'hardlink-target.json');
const hardlinkReceipt = path.join(probeRoot, 'hardlink.json');
const junctionParent = path.join(probeRoot, 'receipt-parent');
const outsideSentinel = path.join(outsideRoot, 'sentinel.txt');
fs.writeFileSync(existingReceipt, 'existing-receipt-sentinel', 'utf-8');
fs.writeFileSync(hardlinkTarget, 'hardlink-sentinel', 'utf-8');
fs.linkSync(hardlinkTarget, hardlinkReceipt);
fs.writeFileSync(outsideSentinel, 'outside-sentinel', 'utf-8');
fs.symlinkSync(outsideRoot, junctionParent, 'junction');
const fixtureSource = String.raw`
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
function Assert-True {
param([Parameter(Mandatory = $true)] [bool]$Condition, [Parameter(Mandatory = $true)] [string]$Message)
if (-not $Condition) { throw $Message }
}
function Expect-Rejection {
param([scriptblock]$Action, [string]$Label)
$rejected = $false
try { & $Action } catch { $rejected = $true }
if (-not $rejected) { throw "$Label was accepted" }
}
$existingReceipt = Join-Path $PSScriptRoot 'existing.json'
$hardlinkReceipt = Join-Path $PSScriptRoot 'hardlink.json'
$hardlinkTarget = Join-Path $PSScriptRoot 'hardlink-target.json'
$junctionReceipt = Join-Path (Join-Path $PSScriptRoot 'receipt-parent') 'receipt.json'
$reservedReceipt = Join-Path $PSScriptRoot 'reserved.json'
Expect-Rejection { Assert-SafeReceiptPath $existingReceipt } 'existing receipt'
Expect-Rejection { Reserve-CertificateReceiptPath $hardlinkReceipt } 'hardlink receipt'
Expect-Rejection { Assert-SafeReceiptPath $junctionReceipt } 'junction receipt parent'
$reservation = Reserve-CertificateReceiptPath $reservedReceipt
Expect-Rejection { Reserve-CertificateReceiptPath $reservedReceipt } 'second receipt reservation'
Write-CertificateReceipt $reservation 'reserved-receipt'
if ((Get-Content -Raw -LiteralPath $existingReceipt) -cne 'existing-receipt-sentinel') {
throw 'Existing receipt sentinel changed'
}
if ((Get-Content -Raw -LiteralPath $hardlinkTarget) -cne 'hardlink-sentinel') {
throw 'Hardlink receipt sentinel changed'
}
if ((Get-Content -Raw -LiteralPath $reservedReceipt) -cne 'reserved-receipt') {
throw 'Reserved receipt content was not written through its owned handle'
}
if ((Get-Content -Raw -LiteralPath '${outsideSentinel.replaceAll('\\', '\\\\')}') -cne 'outside-sentinel') {
throw 'Outside sentinel changed'
}
if (Test-Path -LiteralPath $junctionReceipt) {
throw 'Receipt was written through the junction'
}
`;
try {
fs.writeFileSync(
probePath,
`${script.slice(helperStart, helperEnd)}\n${fixtureSource}`,
'utf-8',
);
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
if (result.status !== 0) {
throw new Error(
`Windows installer receipt safety probe failed: ${result.stderr || result.stdout}`,
);
}
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
fs.rmSync(outsideRoot, { recursive: true, force: true });
}
},
);
it.runIf(process.platform === 'win32')(
'Windows installer certificate owns scratch roots before guarded cleanup',
() => {
const script = fs
.readFileSync(
path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'),
'utf-8',
)
.replace(/\r\n/g, '\n');
const manifestStart = script.indexOf('function Get-CertificateRelativePath {');
const manifestEnd = script.indexOf(
'\nfunction Assert-CertificateDataManifest {',
manifestStart,
);
const scratchStart = script.indexOf('function Assert-SafeScratchRoot {');
const scratchEnd = script.indexOf(
'\nfunction Remove-CertificateProductRegistry {',
scratchStart,
);
expect(manifestStart).toBeGreaterThanOrEqual(0);
expect(manifestEnd).toBeGreaterThan(manifestStart);
expect(scratchStart).toBeGreaterThanOrEqual(0);
expect(scratchEnd).toBeGreaterThan(scratchStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-cert-scratch-'));
const outsideRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-cert-owned-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const fixtureSource = String.raw`
function Assert-True {
param([Parameter(Mandatory = $true)] [bool]$Condition, [Parameter(Mandatory = $true)] [string]$Message)
if (-not $Condition) { throw $Message }
}
function Expect-Rejection {
param([scriptblock]$Action, [string]$Label)
$rejected = $false
try { & $Action } catch { $rejected = $true }
if (-not $rejected) { throw "$Label was accepted" }
}
$existingRunId = '11111111111111111111111111111111'
$existingRoot = Join-Path $PSScriptRoot "waggle-installer-cert-$existingRunId"
New-Item -ItemType Directory -Path $existingRoot | Out-Null
$existingSentinel = Join-Path $existingRoot 'sentinel.txt'
Set-Content -NoNewline -LiteralPath $existingSentinel -Value 'existing-root-sentinel'
Expect-Rejection {
New-CertificateScratchRoot $existingRoot $existingRunId
} 'pre-existing scratch root'
if ((Get-Content -Raw -LiteralPath $existingSentinel) -cne 'existing-root-sentinel') {
throw 'Pre-existing scratch sentinel changed'
}
$validRunId = '22222222222222222222222222222222'
$validRoot = Join-Path $PSScriptRoot "waggle-installer-cert-$validRunId"
$validMarker = New-CertificateScratchRoot $validRoot $validRunId
if ((Split-Path -Leaf $validMarker) -cne ".waggle-installer-certificate-owner-$validRunId") {
throw 'Scratch ownership marker name is not exact'
}
if ((Get-Content -Raw -LiteralPath $validMarker) -cne $validRunId) {
throw 'Scratch ownership marker content is not exact'
}
Set-Content -NoNewline -LiteralPath (Join-Path $validRoot 'owned.txt') -Value 'owned'
$nestedRoot = New-Item -ItemType Directory -Path (Join-Path $validRoot 'nested')
Set-Content -NoNewline -LiteralPath (Join-Path $nestedRoot 'owned.txt') -Value 'owned'
Remove-CertificateScratchRoot $validRoot $validMarker $validRunId
if (Test-Path -LiteralPath $validRoot) {
throw 'Owned scratch root was not removed'
}
$tamperedRunId = '33333333333333333333333333333333'
$tamperedRoot = Join-Path $PSScriptRoot "waggle-installer-cert-$tamperedRunId"
$tamperedMarker = New-CertificateScratchRoot $tamperedRoot $tamperedRunId
$tamperedSentinel = Join-Path $tamperedRoot 'sentinel.txt'
Set-Content -NoNewline -LiteralPath $tamperedMarker -Value 'wrong-owner'
Set-Content -NoNewline -LiteralPath $tamperedSentinel -Value 'tampered-root-sentinel'
Expect-Rejection {
Remove-CertificateScratchRoot $tamperedRoot $tamperedMarker $tamperedRunId
} 'tampered ownership marker'
if ((Get-Content -Raw -LiteralPath $tamperedSentinel) -cne 'tampered-root-sentinel') {
throw 'Tampered scratch sentinel changed'
}
$reparseRunId = '44444444444444444444444444444444'
$reparseRoot = Join-Path $PSScriptRoot "waggle-installer-cert-$reparseRunId"
$reparseMarker = New-CertificateScratchRoot $reparseRoot $reparseRunId
$outsideRoot = '${outsideRoot.replaceAll('\\', '\\\\')}'
$outsideSentinel = Join-Path $outsideRoot 'sentinel.txt'
Set-Content -NoNewline -LiteralPath $outsideSentinel -Value 'outside-sentinel'
New-Item -ItemType Junction -Path (Join-Path $reparseRoot 'outside') -Target $outsideRoot |
Out-Null
Expect-Rejection {
Remove-CertificateScratchRoot $reparseRoot $reparseMarker $reparseRunId
} 'scratch child reparse point'
if ((Get-Content -Raw -LiteralPath $outsideSentinel) -cne 'outside-sentinel') {
throw 'Outside scratch sentinel changed'
}
`;
try {
fs.writeFileSync(
probePath,
[
script.slice(manifestStart, manifestEnd),
script.slice(scratchStart, scratchEnd),
fixtureSource,
].join('\n'),
'utf-8',
);
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{
encoding: 'utf-8',
timeout: 30_000,
windowsHide: true,
env: { ...process.env, TEMP: probeRoot, TMP: probeRoot },
},
);
if (result.status !== 0) {
throw new Error(
`Windows installer scratch safety probe failed: ${result.stderr || result.stdout}`,
);
}
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
fs.rmSync(outsideRoot, { recursive: true, force: true });
}
},
);
it('accepts Tauri generated NSIS hook dispatch while binding the exact custom include', () => {
const hookPath = path.join(TAURI_DIR, 'nsis', 'installer.nsi');
const generatedFixture = [
`!include "${hookPath}"`,
'!ifmacrodef NSIS_HOOK_POSTUNINSTALL',
' !insertmacro NSIS_HOOK_POSTUNINSTALL',
'!endif',
'!ifmacrodef NSIS_HOOK_PREUNINSTALL',
' !insertmacro NSIS_HOOK_PREUNINSTALL',
'!endif',
].join('\n');
const includes = [...generatedFixture.matchAll(/^\s*!include\s+"([^"]+)"\s*$/gim)]
.map((match) => path.resolve(match[1]));
expect(generatedFixture).toContain('!ifmacrodef NSIS_HOOK_POSTUNINSTALL');
expect(generatedFixture).toContain('!ifmacrodef NSIS_HOOK_PREUNINSTALL');
expect(includes.filter((candidate) => candidate.toLowerCase() === hookPath.toLowerCase()))
.toHaveLength(1);
});
it('guards the real Windows external-agent lane from ambient authority and server reuse', () => {
const script = fs.readFileSync(
path.join(ROOT, 'scripts', 'test-windows-external-agents.ps1'),
'utf-8',
);
const hookSpec = fs.readFileSync(
path.join(ROOT, 'tests', 'e2e', 'launcher-real-hook-lifecycle.spec.ts'),
'utf-8',
);
const toolSpec = fs.readFileSync(
path.join(ROOT, 'tests', 'e2e', 'launcher-real-tool-lifecycle.spec.ts'),
'utf-8',
);
const playwrightConfig = fs.readFileSync(
path.join(ROOT, 'playwright.config.ts'),
'utf-8',
);
expect(script).toContain('[string[]]$HostIds = @()');
expect(script).toContain("[string]$ReceiptDir = ''");
expect(script).toContain("[string]$RunnerNode = ''");
expect(script).toContain("'WAGGLE_E2E_HOST_IDS'");
expect(script).toContain(
"Set-ProcessEnvironment -Name 'WAGGLE_E2E_HOST_IDS' -Value $requestedHostIds",
);
expect(script).toContain('HostIds cannot contain empty values.');
expect(script).toContain('$emptyHostIds.Count -gt 0');
expect(script).toContain('HostIds cannot contain duplicate values:');
expect(script).toContain("'--retries=0'");
expect(script).toContain('$playwrightOutput = Join-Path $runRoot "playwright-$ReceiptName"');
expect(script).toContain('& $script:runnerNodePath $script:playwrightCli @playwrightArgs');
expect(script).toContain("'PLAYWRIGHT_JSON_OUTPUT_FILE'");
expect(script).toContain("'--reporter=list,json'");
expect(script).toContain('"$ReceiptName-report.json"');
expect(playwrightConfig).toContain(
"url: new URL('/health', e2eBaseURL).toString()",
);
expect(playwrightConfig).not.toContain('port: e2ePort');
for (const spec of [hookSpec, toolSpec]) {
expect(spec).toContain('WAGGLE_E2E_HOST_IDS');
expect(spec).toContain('Unknown WAGGLE_E2E_HOST_IDS');
expect(spec).toContain('Invalid WAGGLE_E2E_HOST_IDS: empty host ID.');
expect(spec).toContain('Duplicate WAGGLE_E2E_HOST_IDS:');
}
expect(toolSpec).toContain('every explicitly requested host must be installed and healthy');
expect(toolSpec).toContain(
"results.filter(result => result.status === 'unavailable').map(result => result.id)",
);
const strictToolAssertionIndex = toolSpec.indexOf(
'every explicitly requested host must be installed and healthy',
);
const toolFinallyIndex = toolSpec.indexOf('} finally {', strictToolAssertionIndex);
const toolReceiptIndex = toolSpec.indexOf(
"testInfo.attach('windows-external-tool-route-summary'",
toolFinallyIndex,
);
const receiptCleanupFinallyIndex = toolSpec.indexOf(
'} finally {',
toolReceiptIndex,
);
const toolKillIndex = toolSpec.indexOf(
"request.post('/api/tools/kill'",
receiptCleanupFinallyIndex,
);
expect(toolFinallyIndex).toBeGreaterThan(strictToolAssertionIndex);
expect(toolReceiptIndex).toBeGreaterThan(toolFinallyIndex);
expect(receiptCleanupFinallyIndex).toBeGreaterThan(toolReceiptIndex);
expect(toolKillIndex).toBeGreaterThan(receiptCleanupFinallyIndex);
for (const name of [
'CLAUDE_CODE_OAUTH_TOKEN', 'OPENAI_ACCESS_TOKEN', 'GITHUB_TOKEN',
'STRIPE_SECRET_KEY', 'DATABASE_URL', 'SSH_AUTH_SOCK', 'GIT_ASKPASS',
'HTTPS_PROXY', 'AWS_SHARED_CREDENTIALS_FILE',
'GOOGLE_APPLICATION_CREDENTIALS', 'KUBECONFIG', 'DOCKER_CONFIG',
'NODE_OPTIONS', 'RENDER_API_KEY',
]) {
expect(script, name).toContain(`'${name}'`);
expect(toolSpec, name).toContain(`'${name}'`);
}
expect(script).toContain('$ambientSecretVariables');
expect(script).toContain('$secretNamePattern');
expect(script).toContain("$rawReceiptRoot = Join-Path $runRoot 'raw-receipts'");
expect(script).toContain('Publish-SafeReceipt');
expect(script).toContain('Expected reporter receipt was not created');
expect(script).toContain("kind = 'playwright-summary'");
expect(script).toContain("kind = 'vitest-summary'");
expect(script).toContain('Unknown reporter receipt schema');
expect(script).toContain('Reporter receipt did not prove an exact successful lane');
expect(script).toContain('Reporter receipt did not bind the expected test specification');
expect(script).toContain('Safe receipt identity mismatch');
expect(script).toContain('Safe receipt host roster mismatch');
expect(script).toContain('Safe receipt target already exists');
expect(script).toContain('Receipt contains absolute host paths');
expect(script).toContain('[Convert]::FromBase64String');
expect(script).toContain('captured secret values found for environment variables');
expect(script).toContain('function Resolve-ReceiptLayout');
expect(script).toContain('StagingRoot = Join-Path $parent (');
expect(script).toContain('$receiptLayout = Resolve-ReceiptLayout -RequestedReceiptDir $ReceiptDir');
expect(script).toContain('$receiptStagingOwned = $false');
expect(script).toContain('$receiptStagingOwned = $true');
expect(script).toContain('Publish-ReceiptSet');
expect(script).toContain('[IO.Directory]::Move($StagingRoot, $FinalRoot)');
expect(script).not.toContain("Set-ProcessEnvironment -Name 'PLAYWRIGHT_JSON_OUTPUT_FILE' -Value $receiptPath");
expect(script).toContain("'WAGGLE_E2E_REUSE_EXISTING_SERVER'");
expect(script).toContain(
"Set-ProcessEnvironment -Name 'WAGGLE_E2E_REUSE_EXISTING_SERVER' -Value '0'",
);
for (const name of [
'USERPROFILE', 'HOME', 'HOMEDRIVE', 'HOMEPATH', 'APPDATA', 'LOCALAPPDATA',
'CLAUDE_CONFIG_DIR', 'CODEX_HOME', 'HERMES_HOME', 'HERMES_PROFILE',
]) {
expect(script).toContain(`'${name}'`);
}
expect(script).toContain(
'$environmentToRestore = @($profileVariables + $secretVariables + ' +
'$runnerVariables | Select-Object -Unique)',
);
const isolatedHermesHome = (
"Set-ProcessEnvironment -Name 'HERMES_HOME' " +
"-Value (Join-Path $hookProfile '.hermes')"
);
expect(script).toContain(isolatedHermesHome);
expect(script.indexOf(isolatedHermesHome)).toBeLessThan(
script.indexOf(
"Invoke-PlaywrightLane -Spec 'tests/e2e/launcher-real-hook-lifecycle.spec.ts'",
),
);
expect(script).toContain('$authenticatedHermesLease = $null');
expect(script).toContain('Refusing to overwrite an existing Hermes authenticated profile');
expect(script).toContain('function New-OwnedHermesProfile');
expect(script).toContain('function Remove-OwnedHermesProfile');
expect(script).toContain('Hermes authenticated profile ownership verification failed');
expect(script).toContain('$profileCreateExitCode = $LASTEXITCODE');
expect(script).toContain('Complete-AuthenticatedIsolationCleanup `');
expect(script).toContain('-HermesLease $authenticatedHermesLease `');
expect(script).toContain('-SourceAuthEvidence $sourceAuthEvidence `');
expect(script).toContain('ReceiptDir must be a fresh path owned by this run');
const hookLaneIndex = script.indexOf(
"Invoke-PlaywrightLane -Spec 'tests/e2e/launcher-real-hook-lifecycle.spec.ts'",
);
const successfulRestoreIndex = script.indexOf(
"foreach ($name in $profileVariables) { Restore-ProcessEnvironment -Name $name }",
hookLaneIndex,
);
const realToolLaneIndex = script.indexOf(
"Invoke-PlaywrightLane -Spec 'tests/e2e/launcher-real-tool-lifecycle.spec.ts'",
);
expect(successfulRestoreIndex).toBeGreaterThan(hookLaneIndex);
expect(successfulRestoreIndex).toBeLessThan(realToolLaneIndex);
const failureRestoreIndex = script.lastIndexOf(
"foreach ($name in $environmentToRestore) { Restore-ProcessEnvironment -Name $name }",
);
const outerFinallyIndex = script.lastIndexOf('} finally {', failureRestoreIndex);
expect(failureRestoreIndex).toBeGreaterThan(outerFinallyIndex);
expect(failureRestoreIndex).toBeLessThan(
script.indexOf('Remove-VerifiedTempTree -Target $runRoot', failureRestoreIndex),
);
expect(script.indexOf('Publish-ReceiptSet -StagingRoot $receiptStagingRoot')).toBeGreaterThan(
script.indexOf('Remove-VerifiedTempTree -Target $runRoot', failureRestoreIndex),
);
});
it.runIf(process.platform === 'win32')(
'projects external-agent reporter output into strict path-free receipts',
() => {
const runner = fs.readFileSync(
path.join(ROOT, 'scripts', 'test-windows-external-agents.ps1'),
'utf-8',
).replace(/\r\n/g, '\n');
const helperStart = runner.indexOf('function Assert-NoReparsePointInPath');
const helperEnd = runner.indexOf('\nfunction Get-FreeLoopbackPort', helperStart);
expect(helperStart).toBeGreaterThanOrEqual(0);
expect(helperEnd).toBeGreaterThan(helperStart);
const helperSource = runner.slice(helperStart, helperEnd);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-agent-receipt-probe-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const fixtureSource = String.raw`
$ErrorActionPreference = 'Stop'
$repoRoot = 'C:\Users\Tester\repo'
$runRoot = Join-Path $PSScriptRoot 'owned-run'
$rawReceiptRoot = Join-Path $runRoot 'raw-receipts'
$receiptRoot = Join-Path $PSScriptRoot 'published-receipts'
$receiptStagingRoot = Join-Path $PSScriptRoot '.published-receipts.staging-probe'
$null = New-Item -ItemType Directory -Path $rawReceiptRoot -Force
$null = New-Item -ItemType Directory -Path $receiptStagingRoot
$secretVariables = @('WAGGLE_PROBE_API_KEY')
$originalEnvironment = @{ WAGGLE_PROBE_API_KEY = 'probe-secret-value-6f34a0' }
$receiptHostIds = @('claude-code', 'codex', 'hermes')
$authenticatedHostIds = @('claude-code', 'codex', 'hermes')
function Assert-Probe([bool]$Condition, [string]$Message) {
if (-not $Condition) { throw $Message }
}
function Write-ProbeJson([string]$Path, $Value) {
[IO.File]::WriteAllText($Path, ($Value | ConvertTo-Json -Depth 10), [Text.UTF8Encoding]::new($false))
}
function Assert-RejectedReceipt(
$Value,
[string]$Label,
[string]$ExpectedKind = 'playwright-summary',
[string]$ExpectedSpec = 'tests/e2e/launcher-real-hook-lifecycle.spec.ts'
) {
$token = [guid]::NewGuid().ToString('N')
$rawPath = Join-Path $rawReceiptRoot "$token.raw.json"
$safePath = Join-Path $receiptStagingRoot "$token-report.json"
Write-ProbeJson $rawPath $Value
$rejected = $false
try {
Publish-SafeReceipt -RawReceiptPath $rawPath -SafeReceiptPath $safePath -ExpectedKind $ExpectedKind -ExpectedSpec $ExpectedSpec -ReceiptLane $token -ExpectedHostIds $receiptHostIds
} catch { $rejected = $true }
Assert-Probe $rejected "$Label was accepted"
Assert-Probe (-not (Test-Path -LiteralPath $rawPath)) "$Label raw receipt was retained"
Assert-Probe (-not (Test-Path -LiteralPath $safePath)) "$Label safe receipt was published"
}
function New-PassingPlaywrightReceipt(
[string]$Spec = 'tests/e2e/launcher-real-hook-lifecycle.spec.ts'
) {
[pscustomobject]@{
configFile = Join-Path $repoRoot 'playwright.config.ts'
config = [pscustomobject]@{ rootDir = Join-Path $repoRoot 'tests' }
stats = [pscustomobject]@{ expected = 1; unexpected = 0; flaky = 0; skipped = 0 }
suites = @([pscustomobject]@{
file = $Spec.Substring('tests/'.Length)
attachments = @([pscustomobject]@{
body = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes('D:\private\tool.exe probe-secret-value-6f34a0'))
})
})
}
}
$unownedSentinel = Join-Path $receiptStagingRoot 'unowned-sentinel.txt'
[IO.File]::WriteAllText($unownedSentinel, 'preserve-me', [Text.UTF8Encoding]::new($false))
Remove-VerifiedReceiptStaging $receiptStagingRoot $receiptRoot $false
Assert-Probe ([IO.File]::ReadAllText($unownedSentinel) -ceq 'preserve-me') 'Unowned staging collision was deleted'
Remove-Item -LiteralPath $unownedSentinel -Force
$playwrightRawPath = Join-Path $rawReceiptRoot 'hooks.raw.json'
$playwrightPath = Join-Path $receiptStagingRoot 'hooks-report.json'
Write-ProbeJson $playwrightRawPath (New-PassingPlaywrightReceipt)
Publish-SafeReceipt -RawReceiptPath $playwrightRawPath -SafeReceiptPath $playwrightPath -ExpectedKind 'playwright-summary' -ExpectedSpec 'tests/e2e/launcher-real-hook-lifecycle.spec.ts' -ReceiptLane 'hooks' -ExpectedHostIds $receiptHostIds
Assert-Probe (-not (Test-Path -LiteralPath $playwrightRawPath)) 'Playwright raw receipt survived projection'
$playwrightText = [IO.File]::ReadAllText($playwrightPath)
$playwright = $playwrightText | ConvertFrom-Json
Assert-Probe ($playwright.kind -ceq 'playwright-summary') 'Playwright projection kind mismatch'
Assert-Probe ($playwright.success -is [bool] -and $playwright.success) 'Playwright projection did not prove success'
Assert-Probe ($playwright.spec -ceq 'tests/e2e/launcher-real-hook-lifecycle.spec.ts') 'Playwright spec identity missing'
Assert-Probe (($playwright.hostIds -join ',') -ceq ($receiptHostIds -join ',')) 'Playwright host roster missing'
Assert-Probe (-not $playwrightText.Contains('C:\Users')) 'Direct host path survived projection'
Assert-Probe (-not $playwrightText.Contains('probe-secret-value-6f34a0')) 'Secret survived projection'
Assert-Probe (-not $playwrightText.Contains('body')) 'Base64 attachment survived projection'
$toolsRawPath = Join-Path $rawReceiptRoot 'tools.raw.json'
$toolsPath = Join-Path $receiptStagingRoot 'tools-report.json'
Write-ProbeJson $toolsRawPath (New-PassingPlaywrightReceipt 'tests/e2e/launcher-real-tool-lifecycle.spec.ts')
Publish-SafeReceipt -RawReceiptPath $toolsRawPath -SafeReceiptPath $toolsPath -ExpectedKind 'playwright-summary' -ExpectedSpec 'tests/e2e/launcher-real-tool-lifecycle.spec.ts' -ReceiptLane 'tools' -ExpectedHostIds $receiptHostIds
$vitestRawPath = Join-Path $rawReceiptRoot 'authenticated-tasks.raw.json'
$vitestPath = Join-Path $receiptStagingRoot 'authenticated-tasks-report.json'
$vitest = [pscustomobject]@{
success = $true
numTotalTestSuites = 2; numPassedTestSuites = 2; numFailedTestSuites = 0; numPendingTestSuites = 0
numTotalTests = 1; numPassedTests = 1; numFailedTests = 0; numPendingTests = 0; numTodoTests = 0
testResults = @([pscustomobject]@{ name = 'C:\Users\Tester\repo\tests\integration\external-agent-collaboration.live.test.ts' })
}
Write-ProbeJson $vitestRawPath $vitest
Publish-SafeReceipt -RawReceiptPath $vitestRawPath -SafeReceiptPath $vitestPath -ExpectedKind 'vitest-summary' -ExpectedSpec 'tests/integration/external-agent-collaboration.live.test.ts' -ReceiptLane 'authenticated-tasks' -ExpectedHostIds $authenticatedHostIds -HermesProvider 'openai-codex' -HermesModel 'gpt-5.5'
Assert-Probe (-not (Test-Path -LiteralPath $vitestRawPath)) 'Vitest raw receipt survived projection'
$vitestProjection = [IO.File]::ReadAllText($vitestPath) | ConvertFrom-Json
Assert-Probe ($vitestProjection.kind -ceq 'vitest-summary') 'Vitest projection kind mismatch'
Assert-Probe ($vitestProjection.passedTests -eq 1) 'Vitest exact pass count was not retained'
Assert-Probe ($vitestProjection.hermesProvider -ceq 'openai-codex') 'Vitest Hermes provider identity missing'
Assert-Probe ($vitestProjection.hermesModel -ceq 'gpt-5.5') 'Vitest Hermes model identity missing'
Remove-Item -LiteralPath $vitestPath -Force
Assert-RejectedReceipt (New-PassingPlaywrightReceipt 'tests/e2e/launcher-real-tool-lifecycle.spec.ts') 'Mismatched Playwright specification'
$spoofedPlaywright = New-PassingPlaywrightReceipt 'tests/e2e/launcher-real-tool-lifecycle.spec.ts'
$spoofedPlaywright.suites[0].attachments += [pscustomobject]@{
note = 'tests/e2e/launcher-real-hook-lifecycle.spec.ts'
}
Assert-RejectedReceipt $spoofedPlaywright 'Spoofed Playwright specification'
Assert-RejectedReceipt (New-PassingPlaywrightReceipt) 'Mismatched reporter kind' 'vitest-summary' 'tests/e2e/launcher-real-hook-lifecycle.spec.ts'
$spoofedVitest = $vitest | ConvertTo-Json -Depth 10 | ConvertFrom-Json
$spoofedVitest.testResults[0].name = 'C:\Users\Tester\repo\tests\integration\unrelated.test.ts'
$spoofedVitest.testResults[0] | Add-Member -NotePropertyName note -NotePropertyValue 'tests/integration/external-agent-collaboration.live.test.ts'
Assert-RejectedReceipt $spoofedVitest 'Spoofed Vitest specification' 'vitest-summary' 'tests/integration/external-agent-collaboration.live.test.ts'
$extraResultVitest = $vitest | ConvertTo-Json -Depth 10 | ConvertFrom-Json
$extraResultVitest.testResults += [pscustomobject]@{
name = 'C:\Users\Tester\repo\tests\integration\unrelated.test.ts'
}
Assert-RejectedReceipt $extraResultVitest 'Extra Vitest result file' 'vitest-summary' 'tests/integration/external-agent-collaboration.live.test.ts'
$skipped = New-PassingPlaywrightReceipt
$skipped.stats.expected = 0
$skipped.stats.skipped = 1
Assert-RejectedReceipt $skipped 'Skipped Playwright receipt'
$missingPlaywrightField = New-PassingPlaywrightReceipt
$missingPlaywrightField.stats.PSObject.Properties.Remove('flaky')
Assert-RejectedReceipt $missingPlaywrightField 'Omitted Playwright field'
$stringPlaywrightCounts = New-PassingPlaywrightReceipt
$stringPlaywrightCounts.stats.expected = '1'
$stringPlaywrightCounts.stats.unexpected = '0'
$stringPlaywrightCounts.stats.flaky = '0'
$stringPlaywrightCounts.stats.skipped = '0'
Assert-RejectedReceipt $stringPlaywrightCounts 'String Playwright counts'
$failedPlaywrightCast = New-PassingPlaywrightReceipt
$failedPlaywrightCast.stats.expected = 'not-a-number'
Assert-RejectedReceipt $failedPlaywrightCast 'Invalid Playwright count'
$stringVitestBoolean = $vitest | ConvertTo-Json -Depth 10 | ConvertFrom-Json
$stringVitestBoolean.success = 'false'
Assert-RejectedReceipt $stringVitestBoolean 'String Vitest boolean' 'vitest-summary' 'tests/integration/external-agent-collaboration.live.test.ts'
$stringVitestCount = $vitest | ConvertTo-Json -Depth 10 | ConvertFrom-Json
$stringVitestCount.numTotalTests = '1'
Assert-RejectedReceipt $stringVitestCount 'String Vitest count' 'vitest-summary' 'tests/integration/external-agent-collaboration.live.test.ts'
$missingVitestField = $vitest | ConvertTo-Json -Depth 10 | ConvertFrom-Json
$missingVitestField.PSObject.Properties.Remove('numTodoTests')
Assert-RejectedReceipt $missingVitestField 'Omitted Vitest field' 'vitest-summary' 'tests/integration/external-agent-collaboration.live.test.ts'
Assert-RejectedReceipt ([pscustomobject]@{ success = $true }) 'Malformed reporter schema'
$invalidJsonPath = Join-Path $rawReceiptRoot 'invalid-json-report.json'
$invalidSafePath = Join-Path $receiptStagingRoot 'invalid-json-report.json'
[IO.File]::WriteAllText($invalidJsonPath, '{', [Text.UTF8Encoding]::new($false))
$invalidJsonRejected = $false
try {
Publish-SafeReceipt -RawReceiptPath $invalidJsonPath -SafeReceiptPath $invalidSafePath -ExpectedKind 'playwright-summary' -ExpectedSpec 'tests/e2e/launcher-real-hook-lifecycle.spec.ts' -ReceiptLane 'invalid-json' -ExpectedHostIds $receiptHostIds
} catch { $invalidJsonRejected = $true }
Assert-Probe $invalidJsonRejected 'Invalid reporter JSON was accepted'
Assert-Probe (-not (Test-Path -LiteralPath $invalidJsonPath)) 'Invalid raw JSON receipt was retained'
Assert-Probe (-not (Test-Path -LiteralPath $invalidSafePath)) 'Invalid JSON produced a safe receipt'
$collisionStage = Join-Path $PSScriptRoot '.published-receipts.staging-collision'
$null = New-Item -ItemType Directory -Path $collisionStage
$savedStagingRoot = $receiptStagingRoot
$receiptStagingRoot = $collisionStage
$collisionRawPath = Join-Path $rawReceiptRoot 'collision.raw.json'
$collisionSafePath = Join-Path $collisionStage 'collision-report.json'
Write-ProbeJson $collisionRawPath (New-PassingPlaywrightReceipt)
[IO.File]::WriteAllText($collisionSafePath, 'sentinel', [Text.UTF8Encoding]::new($false))
$writeRejected = $false
try {
Publish-SafeReceipt -RawReceiptPath $collisionRawPath -SafeReceiptPath $collisionSafePath -ExpectedKind 'playwright-summary' -ExpectedSpec 'tests/e2e/launcher-real-hook-lifecycle.spec.ts' -ReceiptLane 'collision' -ExpectedHostIds $receiptHostIds
} catch { $writeRejected = $true }
Assert-Probe $writeRejected 'Projection write failure was accepted'
Assert-Probe (-not (Test-Path -LiteralPath $collisionRawPath)) 'Raw receipt survived projection collision'
Assert-Probe ([IO.File]::ReadAllText($collisionSafePath) -ceq 'sentinel') 'Existing safe receipt was overwritten'
$receiptStagingRoot = $savedStagingRoot
Remove-Item -LiteralPath $collisionStage -Recurse -Force
$missingStage = Join-Path $PSScriptRoot '.published-receipts.staging-missing'
$null = New-Item -ItemType Directory -Path $missingStage
Copy-Item -LiteralPath $playwrightPath -Destination (Join-Path $missingStage 'hooks-report.json')
$missingFinal = Join-Path $PSScriptRoot 'missing-final'
$missingRejected = $false
try { Publish-ReceiptSet $missingStage $missingFinal @('hooks-report.json', 'tools-report.json') } catch { $missingRejected = $true }
Assert-Probe $missingRejected 'Incomplete receipt set was published'
Assert-Probe (-not (Test-Path -LiteralPath $missingFinal)) 'Incomplete final receipt directory exists'
$extraStage = Join-Path $PSScriptRoot '.published-receipts.staging-extra'
$null = New-Item -ItemType Directory -Path $extraStage
Copy-Item -LiteralPath $playwrightPath -Destination (Join-Path $extraStage 'hooks-report.json')
Copy-Item -LiteralPath $toolsPath -Destination (Join-Path $extraStage 'tools-report.json')
Copy-Item -LiteralPath $toolsPath -Destination (Join-Path $extraStage 'unexpected-report.json')
$extraFinal = Join-Path $PSScriptRoot 'extra-final'
$extraRejected = $false
try { Publish-ReceiptSet $extraStage $extraFinal @('hooks-report.json', 'tools-report.json') } catch { $extraRejected = $true }
Assert-Probe $extraRejected 'Receipt set with an extra file was published'
Assert-Probe (-not (Test-Path -LiteralPath $extraFinal)) 'Extra final receipt directory exists'
$outsideReceiptParent = Join-Path $PSScriptRoot 'outside-receipt-parent'
$receiptJunction = Join-Path $PSScriptRoot 'receipt-parent-junction'
$unsafeFinal = Join-Path $receiptJunction 'unsafe-final'
$unsafeStage = Join-Path $receiptJunction '.unsafe-final.staging-probe'
$null = New-Item -ItemType Directory -Path $outsideReceiptParent
$null = New-Item -ItemType Junction -Path $receiptJunction -Target $outsideReceiptParent
$null = New-Item -ItemType Directory -Path $unsafeStage
$outsideSentinel = Join-Path $unsafeStage 'preserve-me.txt'
[IO.File]::WriteAllText($outsideSentinel, 'preserve-me', [Text.UTF8Encoding]::new($false))
$junctionCleanupRejected = $false
try { Remove-VerifiedReceiptStaging $unsafeStage $unsafeFinal $true } catch {
$junctionCleanupRejected = $_.Exception.Message -like '*reparse point*'
}
Assert-Probe $junctionCleanupRejected 'Receipt cleanup traversed a reparse ancestor'
Assert-Probe ([IO.File]::ReadAllText($outsideSentinel) -ceq 'preserve-me') 'Receipt cleanup deleted outside content'
Publish-ReceiptSet $receiptStagingRoot $receiptRoot @('hooks-report.json', 'tools-report.json')
Assert-Probe (Test-Path -LiteralPath $receiptRoot -PathType Container) 'Exact receipt set was not published'
Assert-Probe (-not (Test-Path -LiteralPath $receiptStagingRoot)) 'Staging directory survived atomic publication'
$publishedNames = @(Get-ChildItem -LiteralPath $receiptRoot -File | ForEach-Object Name | Sort-Object)
Assert-Probe (($publishedNames -join ',') -ceq 'hooks-report.json,tools-report.json') 'Published receipt set was not exact'
Assert-Probe (@(Get-ChildItem -LiteralPath $rawReceiptRoot -File).Count -eq 0) 'Raw reporter receipts survived'
`;
try {
fs.writeFileSync(probePath, `${helperSource}\n${fixtureSource}`, 'utf-8');
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
expect(result.status, result.stderr || result.stdout).toBe(0);
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
40_000,
);
it.runIf(process.platform === 'win32')(
'normalizes trailing-separator Windows receipt layout to an atomic sibling',
() => {
const runner = fs.readFileSync(
path.join(ROOT, 'scripts', 'test-windows-external-agents.ps1'),
'utf-8',
).replace(/\r\n/g, '\n');
const functionStart = runner.indexOf('function Resolve-ReceiptLayout');
const functionEnd = runner.indexOf('\n$repoRoot', functionStart);
expect(functionStart).toBeGreaterThanOrEqual(0);
expect(functionEnd).toBeGreaterThan(functionStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-receipt-layout-probe-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const fixtureSource = String.raw`
$ErrorActionPreference = 'Stop'
$expectedRoot = Join-Path $PSScriptRoot 'receipts'
$requestedRoot = $expectedRoot + [IO.Path]::DirectorySeparatorChar
$layout = Resolve-ReceiptLayout -RequestedReceiptDir $requestedRoot
if (-not $layout.Root.Equals($expectedRoot, [StringComparison]::OrdinalIgnoreCase)) { throw 'Receipt root was not normalized' }
if (-not $layout.Parent.Equals($PSScriptRoot, [StringComparison]::OrdinalIgnoreCase)) { throw 'Receipt parent was not the direct sibling parent' }
if (-not [IO.Path]::GetDirectoryName($layout.StagingRoot).Equals($PSScriptRoot, [StringComparison]::OrdinalIgnoreCase)) { throw 'Receipt staging was not a sibling' }
if (-not [IO.Path]::GetFileName($layout.StagingRoot).StartsWith('.receipts.staging-', [StringComparison]::Ordinal)) { throw 'Receipt staging name was not owned' }
if (Test-Path -LiteralPath $expectedRoot) { throw 'Final receipt directory was created during layout' }
`;
try {
fs.writeFileSync(probePath, `${runner.slice(functionStart, functionEnd)}\n${fixtureSource}`, 'utf-8');
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
expect(result.status, result.stderr || result.stdout).toBe(0);
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
40_000,
);
it.runIf(process.platform === 'win32')(
'preserves a colliding authenticated Hermes profile without invoking its CLI',
() => {
const runner = fs.readFileSync(
path.join(ROOT, 'scripts', 'test-windows-external-agents.ps1'),
'utf-8',
).replace(/\r\n/g, '\n');
const functionStart = runner.indexOf('function Assert-NoReparsePointInPath');
const functionEnd = runner.indexOf('\nfunction Get-ReceiptStrings', functionStart);
expect(functionStart).toBeGreaterThanOrEqual(0);
expect(functionEnd).toBeGreaterThan(functionStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-hermes-collision-probe-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const fixtureSource = String.raw`
$ErrorActionPreference = 'Stop'
$profilesRoot = Join-Path $PSScriptRoot 'profiles'
$profileName = 'wagglee2ecollision'
$profileHome = Join-Path $profilesRoot $profileName
$null = New-Item -ItemType Directory -Path $profileHome
$sentinel = Join-Path $profileHome 'sentinel.txt'
[IO.File]::WriteAllText($sentinel, 'preserve-me', [Text.UTF8Encoding]::new($false))
$script:hermesInvocations = @()
function hermes {
$script:hermesInvocations += ($args -join ' ')
throw 'Hermes CLI must not run for a profile collision'
}
$lease = $null
$rejected = $false
try { $lease = New-OwnedHermesProfile -ProfilesRoot $profilesRoot -ProfileName $profileName -OwnedRoot $PSScriptRoot }
catch { $rejected = $_.Exception.Message -like '*Refusing to overwrite*' }
finally { if ($null -ne $lease) { Remove-OwnedHermesProfile -Lease $lease } }
if (-not $rejected) { throw 'Colliding Hermes profile was not rejected' }
if ($script:hermesInvocations.Count -ne 0) { throw 'Hermes CLI was invoked for a collision' }
if (-not (Test-Path -LiteralPath $profileHome -PathType Container)) { throw 'Colliding profile was deleted' }
if ([IO.File]::ReadAllText($sentinel) -cne 'preserve-me') { throw 'Colliding profile sentinel changed' }
if (@(Get-ChildItem -LiteralPath $profilesRoot -Force).Count -ne 1) { throw 'Unexpected profile artifact was created' }
`;
try {
fs.writeFileSync(probePath, `${runner.slice(functionStart, functionEnd)}\n${fixtureSource}`, 'utf-8');
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
expect(result.status, result.stderr || result.stdout).toBe(0);
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
40_000,
);
it.runIf(process.platform === 'win32')(
'never deletes an unsealed Hermes profile after setup failure',
() => {
const runner = fs.readFileSync(
path.join(ROOT, 'scripts', 'test-windows-external-agents.ps1'),
'utf-8',
).replace(/\r\n/g, '\n');
const functionStart = runner.indexOf('function Assert-NoReparsePointInPath');
const functionEnd = runner.indexOf('\nfunction Invoke-NativePreflight', functionStart);
expect(functionStart).toBeGreaterThanOrEqual(0);
expect(functionEnd).toBeGreaterThan(functionStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-hermes-seal-probe-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const fixtureSource = String.raw`
$ErrorActionPreference = 'Stop'
$profilesRoot = Join-Path $PSScriptRoot 'profiles'
$profileName = 'wagglee2esealfailure'
$profileHome = Join-Path $profilesRoot $profileName
$script:hermesInvocations = @()
$script:failDuringCreate = $false
function Write-HermesOwnershipMarker {
throw 'forced ownership marker failure'
}
function hermes {
$script:hermesInvocations += ($args -join ' ')
if ($args[0] -eq 'profile' -and $args[1] -eq 'create') {
$null = New-Item -ItemType Directory -Path $profileHome
if ($script:failDuringCreate) {
[IO.File]::WriteAllText((Join-Path $profileHome 'competing-sentinel.txt'), 'preserve-me')
throw 'forced terminating create failure'
}
$global:LASTEXITCODE = 0
return
}
if ($args[0] -eq 'profile' -and $args[1] -eq 'delete') {
Remove-Item -LiteralPath $profileHome -Recurse -Force
$global:LASTEXITCODE = 0
return
}
throw 'Unexpected Hermes CLI call'
}
$rejected = $false
try {
$null = New-OwnedHermesProfile -ProfilesRoot $profilesRoot -ProfileName $profileName -OwnedRoot $PSScriptRoot
} catch {
$rejected = $_.Exception.Message -like '*forced ownership marker failure*'
}
if (-not $rejected) { throw 'Hermes ownership seal failure was not preserved' }
if (-not (Test-Path -LiteralPath $profileHome -PathType Container)) { throw 'Unsealed Hermes profile was deleted' }
Remove-Item -LiteralPath $profileHome -Recurse -Force
$profileName = 'wagglee2ecreatefailure'
$profileHome = Join-Path $profilesRoot $profileName
$script:failDuringCreate = $true
$createRejected = $false
try {
$null = New-OwnedHermesProfile -ProfilesRoot $profilesRoot -ProfileName $profileName -OwnedRoot $PSScriptRoot
} catch {
$createRejected = $_.Exception.Message -like '*forced terminating create failure*'
}
if (-not $createRejected) { throw 'Terminating Hermes create failure was not preserved' }
if (-not (Test-Path -LiteralPath $profileHome -PathType Container)) { throw 'Competing Hermes profile was deleted' }
if ([IO.File]::ReadAllText((Join-Path $profileHome 'competing-sentinel.txt')) -cne 'preserve-me') {
throw 'Competing Hermes profile sentinel changed'
}
if (($script:hermesInvocations -join '|') -cne
'profile create wagglee2esealfailure --no-alias --no-skills|profile create wagglee2ecreatefailure --no-alias --no-skills') {
throw 'Hermes setup failure invoked an unowned delete'
}
`;
try {
fs.writeFileSync(probePath, `${runner.slice(functionStart, functionEnd)}\n${fixtureSource}`, 'utf-8');
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
expect(result.status, result.stderr || result.stdout).toBe(0);
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
40_000,
);
it.runIf(process.platform === 'win32')(
'checks source auth invariants even when Hermes profile cleanup fails',
() => {
const runner = fs.readFileSync(
path.join(ROOT, 'scripts', 'test-windows-external-agents.ps1'),
'utf-8',
).replace(/\r\n/g, '\n');
const functionStart = runner.indexOf('function Assert-NoReparsePointInPath');
const functionEnd = runner.indexOf('\nfunction Get-ReceiptStrings', functionStart);
expect(functionStart).toBeGreaterThanOrEqual(0);
expect(functionEnd).toBeGreaterThan(functionStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-auth-cleanup-probe-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const fixtureSource = String.raw`
$ErrorActionPreference = 'Stop'
$script:hashChecks = 0
$ownedRoot = Join-Path $PSScriptRoot 'owned-profile'
$claudeCopy = Join-Path $ownedRoot '.claude\.credentials.json'
$codexCopy = Join-Path $ownedRoot '.codex\auth.json'
$hermesCopy = Join-Path $ownedRoot 'hermes-root\profiles\probe\auth.json'
$null = New-Item -ItemType Directory -Path ([IO.Path]::GetDirectoryName($claudeCopy)) -Force
$null = New-Item -ItemType Directory -Path ([IO.Path]::GetDirectoryName($codexCopy)) -Force
$null = New-Item -ItemType Directory -Path ([IO.Path]::GetDirectoryName($hermesCopy)) -Force
[IO.File]::WriteAllText($claudeCopy, 'claude-secret-copy')
[IO.File]::WriteAllText($codexCopy, 'codex-secret-copy')
[IO.File]::WriteAllText($hermesCopy, 'hermes-secret-copy')
function Set-ProcessEnvironment { }
function Restore-ProcessEnvironment { }
function Remove-OwnedHermesProfile { throw 'forced Hermes cleanup failure' }
function Get-FileHash {
$script:hashChecks += 1
return [pscustomobject]@{ Hash = 'expected-hash' }
}
$failure = $null
$lease = [pscustomobject]@{ ProfileName = 'probe' }
$evidence = @(
[pscustomobject]@{ Path = 'claude-auth'; Hash = 'expected-hash' },
[pscustomobject]@{ Path = 'codex-auth'; Hash = 'expected-hash' },
[pscustomobject]@{ Path = 'hermes-auth'; Hash = 'expected-hash' }
)
try {
Complete-AuthenticatedIsolationCleanup -HermesLease $lease -SourceAuthEvidence $evidence -ProfileVariables @() -IsolatedAuthPaths @($claudeCopy, $codexCopy, $hermesCopy) -OwnedRoot $ownedRoot
} catch {
$failure = $_.Exception.Message
}
if (Test-Path -LiteralPath $claudeCopy) { throw 'Claude authentication copy survived explicit cleanup' }
if (Test-Path -LiteralPath $codexCopy) { throw 'Codex authentication copy survived explicit cleanup' }
if (Test-Path -LiteralPath $hermesCopy) { throw 'Hermes authentication copy survived explicit cleanup' }
$copySource = Join-Path $PSScriptRoot 'source-auth.json'
$outsideAuthRoot = Join-Path $PSScriptRoot 'outside-auth-root'
$redirectedAuthParent = Join-Path $ownedRoot 'redirected-auth'
[IO.File]::WriteAllText($copySource, 'copy-source')
$null = New-Item -ItemType Directory -Path $outsideAuthRoot
$null = New-Item -ItemType Junction -Path $redirectedAuthParent -Target $outsideAuthRoot
Remove-Item -LiteralPath $outsideAuthRoot -Recurse -Force
$copyRejected = $false
try {
Copy-IsolatedAuthenticationFile -Source $copySource -Destination (Join-Path $redirectedAuthParent 'auth.json') -OwnedRoot $ownedRoot
} catch {
$copyRejected = $_.Exception.Message -like '*reparse point*'
}
if (-not $copyRejected) { throw 'Authentication copy did not reject a dangling reparse ancestor' }
if ([IO.File]::Exists((Join-Path $outsideAuthRoot 'auth.json'))) { throw 'Authentication copy escaped through a reparse ancestor' }
if ($script:hashChecks -ne 3) { throw 'Source auth hashes were skipped after cleanup failure' }
if ($failure -notlike '*forced Hermes cleanup failure*') {
throw 'Aggregated cleanup failure omitted the Hermes error'
}
`;
try {
fs.writeFileSync(probePath, `${runner.slice(functionStart, functionEnd)}\n${fixtureSource}`, 'utf-8');
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
expect(result.status, result.stderr || result.stdout).toBe(0);
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
40_000,
);
it.runIf(process.platform === 'win32')(
'builds a shell-free Codex auth shim that preserves literal task arguments',
() => {
const runner = fs.readFileSync(
path.join(ROOT, 'scripts', 'test-windows-external-agents.ps1'),
'utf-8',
).replace(/\r\n/g, '\n');
const functionStart = runner.indexOf('function Assert-NoReparsePointInPath');
const functionEnd = runner.indexOf('\nfunction New-OwnedHermesProfile', functionStart);
expect(functionStart).toBeGreaterThanOrEqual(0);
expect(functionEnd).toBeGreaterThan(functionStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-codex-shim-probe-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const nodePath = process.execPath.replaceAll("'", "''");
const fixtureSource = String.raw`
$ErrorActionPreference = 'Stop'
$fakeNpm = Join-Path $PSScriptRoot 'fake-npm'
$realEntry = Join-Path $fakeNpm 'node_modules\@openai\codex\bin\codex.js'
$null = New-Item -ItemType Directory -Path ([IO.Path]::GetDirectoryName($realEntry))
$realEntrySource = @'
const fs = require('node:fs');
fs.writeFileSync(process.env.PROBE_OUTPUT, JSON.stringify({ codexHome: process.env.CODEX_HOME, args: process.argv.slice(2) }));
'@
[IO.File]::WriteAllText($realEntry, $realEntrySource, [Text.UTF8Encoding]::new($false))
$realCmd = @'
@ECHO off
SET "_prog=node"
"%_prog%" "%dp0%\node_modules\@openai\codex\bin\codex.js" %*
'@
[IO.File]::WriteAllText((Join-Path $fakeNpm 'codex.cmd'), $realCmd, [Text.ASCIIEncoding]::new())
$env:PATH = $fakeNpm + [IO.Path]::PathSeparator + $env:PATH
$resolvedProbeCommand = Get-Command codex.cmd -CommandType Application -ErrorAction Stop |
Select-Object -First 1
$resolvedProbeItem = Get-Item -LiteralPath $resolvedProbeCommand.Source -Force
if ($resolvedProbeItem.PSIsContainer -or ($resolvedProbeItem.Attributes -band [IO.FileAttributes]::ReparsePoint)) {
throw "Fake Codex command was unsafe before helper: $($resolvedProbeCommand.Source) attrs=$($resolvedProbeItem.Attributes) dir=$($resolvedProbeItem.PSIsContainer)"
}
$ownedRoot = Join-Path $PSScriptRoot 'owned'
$codexHome = Join-Path $ownedRoot '.codex'
$shim = New-IsolatedCodexShim -ShimRoot (Join-Path $ownedRoot 'bin') -CodexHome $codexHome -OwnedRoot $ownedRoot
$shimText = [IO.File]::ReadAllText($shim.Shim)
if (-not $shimText.Contains('"%_prog%" "%dp0%\codex-isolated.mjs" %*')) { throw 'Generated shim was not npm-shaped' }
$env:PROBE_OUTPUT = Join-Path $PSScriptRoot 'result.json'
$arguments = @('literal%value&still-one', '-C', 'D:\work & data')
& '${nodePath}' $shim.Launcher @arguments
if ($LASTEXITCODE -ne 0) { throw 'Isolated Codex launcher failed' }
$result = [IO.File]::ReadAllText($env:PROBE_OUTPUT) | ConvertFrom-Json
if (-not $result.codexHome.Equals($codexHome, [StringComparison]::OrdinalIgnoreCase)) { throw 'CODEX_HOME was not isolated' }
if (($result.args -join '|') -cne ($arguments -join '|')) { throw 'Codex arguments changed during forwarding' }
`;
try {
fs.writeFileSync(probePath, `${runner.slice(functionStart, functionEnd)}\n${fixtureSource}`, 'utf-8');
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
expect(result.status, result.stderr || result.stdout).toBe(0);
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
40_000,
);
it.runIf(process.platform === 'win32')(
'removes owned Windows temp trees containing long Claude session paths',
() => {
const runner = fs.readFileSync(
path.join(ROOT, 'scripts', 'test-windows-external-agents.ps1'),
'utf-8',
).replace(/\r\n/g, '\n');
const functionStart = runner.indexOf('function Remove-VerifiedTempTree');
const functionEnd = runner.indexOf('\nfunction Invoke-PlaywrightLane', functionStart);
expect(functionStart).toBeGreaterThanOrEqual(0);
expect(functionEnd).toBeGreaterThan(functionStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-long-cleanup-probe-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const fixtureSource = String.raw`
$ErrorActionPreference = 'Stop'
$env:TEMP = $PSScriptRoot
$tempBase = $PSScriptRoot
function Start-Sleep { param([int]$Milliseconds) }
function ConvertTo-ExtendedPath([string]$Path) {
$full = [IO.Path]::GetFullPath($Path)
if ($full.StartsWith('\\')) { return '\\?\UNC\' + $full.Substring(2) }
return '\\?\' + $full
}
$target = Join-Path $PSScriptRoot 'owned-long-tree'
$nested = $target
while ((Join-Path $nested 'session.jsonl').Length -le 265) {
$nested = Join-Path $nested ('claude-session-' + ('x' * 40))
}
$extendedTarget = ConvertTo-ExtendedPath $target
$extendedNested = ConvertTo-ExtendedPath $nested
$extendedFile = ConvertTo-ExtendedPath (Join-Path $nested 'session.jsonl')
$null = [IO.Directory]::CreateDirectory($extendedNested)
[IO.File]::WriteAllText($extendedFile, '{}', [Text.UTF8Encoding]::new($false))
if (-not [IO.File]::Exists($extendedFile)) { throw 'Long-path fixture was not created' }
Remove-VerifiedTempTree -Target $target
if ([IO.Directory]::Exists($extendedTarget)) { throw 'Long-path temp tree survived cleanup' }
`;
try {
fs.writeFileSync(
probePath,
`${runner.slice(functionStart, functionEnd)}\n${fixtureSource}`,
'utf-8',
);
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
expect(result.status, result.stderr || result.stdout).toBe(0);
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
40_000,
);
it.runIf(process.platform === 'win32')(
'accepts successful authentication status emitted on stderr by Windows CLIs',
() => {
const runner = fs.readFileSync(
path.join(ROOT, 'scripts', 'test-windows-external-agents.ps1'),
'utf-8',
).replace(/\r\n/g, '\n');
const functionStart = runner.indexOf('function Invoke-NativePreflight');
const functionEnd = runner.indexOf('\nfunction Get-ReceiptStrings', functionStart);
expect(functionStart).toBeGreaterThanOrEqual(0);
expect(functionEnd).toBeGreaterThan(functionStart);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-auth-status-probe-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const nodePath = process.execPath.replaceAll("'", "''");
const fixtureSource = String.raw`
$ErrorActionPreference = 'Stop'
$script:runnerNodePath = '${nodePath}'
Invoke-NativePreflight -FilePath $script:runnerNodePath -ArgumentList @('-e', "process.stderr.write('Logged in using ChatGPT'); process.exit(0)") -FailureMessage 'status failed'
$rejected = $false
try {
Invoke-NativePreflight -FilePath $script:runnerNodePath -ArgumentList @('-e', "process.stderr.write('Authentication failed'); process.exit(7)") -FailureMessage 'status failed'
} catch {
$rejected = $_.Exception.Message -ceq 'status failed'
}
if (-not $rejected) { throw 'Non-zero authentication status was accepted' }
`;
try {
fs.writeFileSync(
probePath,
`${runner.slice(functionStart, functionEnd)}\n${fixtureSource}`,
'utf-8',
);
const result = spawnSync(
'powershell.exe',
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
expect(result.status, result.stderr || result.stdout).toBe(0);
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
40_000,
);
it.runIf(process.platform === 'win32')(
'keeps Playwright raw output in the owned temp tree without ReceiptDir',
() => {
const runner = fs.readFileSync(
path.join(ROOT, 'scripts', 'test-windows-external-agents.ps1'),
'utf-8',
).replace(/\r\n/g, '\n');
const functionStart = runner.indexOf('function Invoke-PlaywrightLane');
const functionEnd = runner.indexOf('\nfunction Invoke-VitestLane', functionStart);
expect(functionStart).toBeGreaterThanOrEqual(0);
expect(functionEnd).toBeGreaterThan(functionStart);
const functionSource = runner.slice(functionStart, functionEnd);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-playwright-output-probe-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const fakeRunner = path.join(probeRoot, 'fake-node.cmd');
const fixtureSource = String.raw`
$ErrorActionPreference = 'Stop'
$runRoot = Join-Path $PSScriptRoot 'owned-run'
$null = New-Item -ItemType Directory -Path $runRoot
$receiptRoot = $null
$receiptStagingRoot = $null
$rawReceiptRoot = Join-Path $runRoot 'raw-receipts'
$script:runnerNodePath = Join-Path $PSScriptRoot 'fake-node.cmd'
$script:playwrightCli = 'fake-playwright-cli.js'
function Get-FreeLoopbackPort { 45678 }
function Set-ProcessEnvironment([string]$Name, [AllowNull()][string]$Value) {}
function Publish-SafeReceipt([string]$RawReceiptPath, [string]$SafeReceiptPath) { throw 'Unexpected receipt publisher call' }
$laneFailed = $false
try {
Invoke-PlaywrightLane -Spec 'fake.spec.ts' -DataDir (Join-Path $runRoot 'data') -ReceiptName 'hooks'
} catch {
$laneFailed = $true
}
if (-not $laneFailed) { throw 'Failing fake Playwright runner was accepted' }
$arguments = [IO.File]::ReadAllText((Join-Path $PSScriptRoot 'args.txt'))
$expectedOutput = Join-Path $runRoot 'playwright-hooks'
if (-not $arguments.Contains('--output')) { throw 'Playwright output flag was omitted without ReceiptDir' }
if (-not $arguments.Contains($expectedOutput)) { throw 'Playwright output escaped the owned run root' }
if ($arguments.Contains('test-results')) { throw 'Playwright default output directory remained reachable' }
`;
try {
fs.writeFileSync(fakeRunner, '@echo off\r\n> "%~dp0args.txt" echo %*\r\nexit /b 1\r\n', 'utf-8');
fs.writeFileSync(probePath, `${functionSource}\n${fixtureSource}`, 'utf-8');
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
expect(result.status, result.stderr || result.stdout).toBe(0);
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
40_000,
);
it('hard-disables the legacy authenticated Windows external-agent task seal before any auth or temp work', () => {
const script = fs.readFileSync(
path.join(ROOT, 'scripts', 'test-windows-external-agents.ps1'),
'utf-8',
).replace(/\r\n/g, '\n');
expect(script).toContain('[switch]$AuthenticatedTasks');
const guard = [
'if ($AuthenticatedTasks) {',
" throw 'AuthenticatedTasks is disabled; use scripts/test-windows-official-auth-canaries.ps1 for no-copy user-auth evidence.'",
'}',
].join('\n');
const guardIndex = script.indexOf(guard);
expect(guardIndex).toBeGreaterThan(-1);
for (const protectedMarker of [
"$repoRoot = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot '..')).Path",
'$runRoot = Join-Path $tempBase',
'$sourceClaudeCredentials =',
'Copy-IsolatedAuthenticationFile',
"Set-ProcessEnvironment -Name 'USERPROFILE' -Value $authenticatedProfileRoot",
"Invoke-VitestLane -Spec 'tests/integration/external-agent-collaboration.live.test.ts'",
]) {
const protectedIndex = script.indexOf(protectedMarker);
expect(protectedIndex, protectedMarker).toBeGreaterThan(-1);
expect(guardIndex, protectedMarker).toBeLessThan(protectedIndex);
}
expect(script).toContain(
"Invoke-PlaywrightLane -Spec 'tests/e2e/launcher-real-hook-lifecycle.spec.ts'",
);
expect(script).toContain(
"Invoke-PlaywrightLane -Spec 'tests/e2e/launcher-real-tool-lifecycle.spec.ts'",
);
});
it('Windows installer shutdown checks listeners instead of rejecting TCP TIME_WAIT', () => {
const script = fs.readFileSync(
path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'),
'utf8',
);
const shutdownHelper = script.match(
/function Wait-ForInstalledRuntimeStop \{([\s\S]*?)\r?\n\}/,
)?.[1];
expect(shutdownHelper).toBeDefined();
expect(script).toContain('function Test-TcpPortHasListener');
expect(shutdownHelper).toContain('Test-TcpPortHasListener $_');
expect(shutdownHelper).not.toContain('Test-TcpPortAvailable $_');
});
it('keeps the three-agent live collaboration contract regression-locked', () => {
const liveSpec = fs.readFileSync(
path.join(ROOT, 'tests', 'integration', 'external-agent-collaboration.live.test.ts'),
'utf-8',
);
expect(liveSpec).toContain(
"const REQUIRED_TOOLS = ['claude-code', 'codex', 'hermes'] as const;",
);
expect(liveSpec).not.toContain('context.skip(');
expect(liveSpec).toContain("{ toolId: 'claude-code', workspaceIds: [sourceWorkspaceId], access: 'read-only' }");
expect(liveSpec).toContain("{ toolId: 'codex', workspaceIds: [sourceWorkspaceId], access: 'read-only' }");
expect(liveSpec).toContain("{ toolId: 'hermes', workspaceIds: [sourceWorkspaceId], access: 'native' }");
expect(liveSpec).toContain("{ toolId: 'hermes', workspaceIds: [synthesisWorkspaceId], access: 'native' }");
expect(liveSpec).toContain('workspaceDigest(sourceWorkspaceDir)');
expect(liveSpec).toContain('workspaceDigest(synthesisWorkspaceDir)');
expect(liveSpec).toContain('summary.trim(), diagnostic).toBe(expectedCanaryLine)');
expect(liveSpec).toContain("summary.trim(), diagnostic).toBe('NO_LOCAL_CANARY')");
expect(liveSpec).toContain("expect(synthesis?.executor.toolId).toBe('hermes')");
expect(liveSpec).not.toContain("'openclaw'");
expect(liveSpec).toContain("memoryRefs.status === 'complete'");
expect(liveSpec).toContain("new AgentRunRegistry(path.join(dataDir, 'agent-runs.json'))");
expect(liveSpec).not.toContain('result: run.result');
});
it('pins standalone Codex in the no-copy official-auth canary contract', () => {
const script = fs.readFileSync(
path.join(ROOT, 'scripts', 'test-windows-official-auth-canaries.ps1'),
'utf-8',
).replace(/\r\n/g, '\n');
const denialProof = fs.readFileSync(
path.join(ROOT, 'scripts', 'verify-codex-tool-denial.mjs'),
'utf-8',
).replace(/\r\n/g, '\n');
expect(script).toContain("[string]$CodexModel = 'gpt-5.5'");
expect(script).toContain("$executionAcknowledgement = 'I_ACKNOWLEDGE_3_OFFICIAL_AUTH_CALLS'");
expect(script).toContain("$codexExe = Resolve-Application -Name 'codex.exe'");
expect(script).toContain('codexResolved = $true');
expect(script).toContain("codexInstaller = Join-Path $repoRoot 'packages\\hive-mind-hooks-codex\\dist\\bin\\codex-hooks.js'");
expect(script).toContain("codexSessionStart = Join-Path $repoRoot 'packages\\hive-mind-hooks-codex\\dist\\hooks\\session-start.js'");
expect(script).toContain("codexUserPromptSubmit = Join-Path $repoRoot 'packages\\hive-mind-hooks-codex\\dist\\hooks\\user-prompt-submit.js'");
expect(script).toContain("codexStop = Join-Path $repoRoot 'packages\\hive-mind-hooks-codex\\dist\\hooks\\stop.js'");
expect(script).toContain("codexPreCompact = Join-Path $repoRoot 'packages\\hive-mind-hooks-codex\\dist\\hooks\\pre-compact.js'");
expect(script).toContain("codexToolDenial = Join-Path $repoRoot 'scripts\\verify-codex-tool-denial.mjs'");
expect(script).toContain("-ArgumentList @($artifactPaths.codexInstaller, 'verify')");
expect(script).toContain('$codexHookPasses -lt 9');
expect(script).toContain('Codex hook verification did not satisfy the 9-check contract.');
expect(script).toContain("-ArgumentList @('login', 'status')");
expect(script).toContain('Logged in using ChatGPT');
expect(script).toContain(
'Codex is not authenticated through the required first-party ChatGPT client session.',
);
expect(script).toContain("'--codex-exe', $codexExe");
expect(script).toContain("'--hive-mind-cli', $artifactPaths.hiveMindCli");
expect(script).toContain("'--receipt-dir', $codexProofDir");
expect(script).toContain("'--expected-head', $ExpectedHead");
expect(script).toContain("'--model', $CodexModel");
expect(script).toContain("'--windows-powershell', $windowsPowerShell");
expect(script).toContain("'--workspace', $codexWorkspace");
expect(script).toContain("'--execute-paid'");
expect(script).toContain("'--marker', $codexMarker");
expect(script).toContain("'--ack', 'I_ACKNOWLEDGE_1_CODEX_OFFICIAL_AUTH_CALL'");
expect(script).toContain('Codex zero-cost tool-denial proof and official-auth canary');
expect(script).toContain('function Assert-JsonBoolean');
expect(script).toContain('function Assert-JsonInteger');
expect(script).toContain('function Assert-CodexToolDenialProof');
expect(script).toContain('Assert-CodexToolDenialProof -Proof $codexDenialProof');
expect(script).toContain('Invoke-CodexProofValidatorSelfTest');
expect(script).toContain("$fixture.schemaVersion = '1'");
expect(script).toContain('$fixture.pass = 1');
expect(script).toContain('$fixture.hooks.extraCount = 1');
expect(script).toContain('$fixture.green.sensitiveDataObserved = $true');
expect(script).toContain('$fixture.paidInvocation.toolEventsObserved = 1');
expect(script).toContain("-Marker $codexMarker -Source 'codex' -SessionId $codexSessionId");
expect(script).toContain('modelCalls = 3');
expect(script).toContain('authStatusCalls = 3');
expect(script).toContain('authFilesReadByHarness = 0');
expect(script).toContain('authFilesCopied = 0');
expect(script).toContain('authContentsSerialized = $false');
expect(script).toContain(
'codexAlternativeEnvironmentNamesBlanked = @($codexAlternativeAuthNames)',
);
expect(script).toContain('method = \'chatgpt\'');
expect(script).toContain('paidModelCallsRequired = 1');
expect(script).toContain('usageReceiptRequired = $false');
expect(script).toContain('preCallCostCapAvailable = $false');
expect(script).toContain('markerSha256 = Get-Sha256Text $codexMarker');
expect(script).toContain('sessionIdSha256 = Get-Sha256Text $codexSessionId');
expect(script).toContain('stdoutBytes = $codexRaw.StdoutBytes');
expect(script).toContain('stdoutSha256 = $codexRaw.StdoutSha256');
expect(script).toContain('stderrBytes = $codexRaw.StderrBytes');
expect(script).toContain('stderrSha256 = $codexRaw.StderrSha256');
expect(script).toContain('reportSha256 = $codexReportSha256');
expect(script).toContain('invocationArgumentsSha256 = [string]$codexDenialProof.invocation.argumentsSha256');
expect(script).toContain('hookGraphSha256 = [string]$codexDenialProof.hooks.graphSha256');
expect(script).toContain('modelCatalogSha256 = [string]$codexDenialProof.paidInvocation.modelCatalogSha256');
expect(script).toContain('paidThreadParamsSha256 = [string]$codexDenialProof.paidInvocation.threadParamsSha256');
expect(script).toContain('paidTurnParamsSha256 = [string]$codexDenialProof.paidInvocation.turnParamsSha256');
expect(script).toContain('mcpBoundarySha256 = [string]$codexDenialProof.mcpBoundary.postPaidSha256');
expect(script).toContain('packagedHookArtifactsSha256 = [string]$codexDenialProof.hooks.artifactsSha256');
expect(script).toContain('windowsPowerShellSha256 = [string]$codexDenialProof.artifacts.windowsPowerShellSha256');
for (const feature of [
'shell_tool',
'unified_exec',
'apps',
'browser_use',
'browser_use_external',
'browser_use_full_cdp_access',
'computer_use',
'image_generation',
'in_app_browser',
'multi_agent',
'multi_agent_v2',
'goals',
'skill_search',
'tool_suggest',
'workspace_dependencies',
'skill_mcp_dependency_install',
'plugins',
'plugin_sharing',
'remote_plugin',
'mentions_v2',
]) {
expect(denialProof).toContain(`'${feature}'`);
}
expect(denialProof).toContain("args.push('--disable', feature)");
expect(denialProof).toContain("'web_search=\"disabled\"'");
expect(denialProof).toContain("'tools.update_plan.enabled=false'");
expect(denialProof).toContain("'tools.experimental_request_user_input.enabled=false'");
expect(denialProof).toContain("'orchestrator.skills.enabled=false'");
expect(denialProof).toContain("'orchestrator.mcp.enabled=false'");
expect(denialProof).toContain('apply_patch_tool_type = null');
expect(denialProof).toContain('use_responses_lite = false');
expect(denialProof).toContain('dynamicTools: []');
expect(denialProof).toContain('environments: []');
expect(denialProof).toContain('allowProviderModelFallback: false');
expect(denialProof).toContain(
'...(options.useDefaultEnvironmentForControl ? {} : { environments: [] })',
);
expect(denialProof).toContain('useDefaultEnvironmentForControl: true');
expect(denialProof).toContain("const controlModel = `waggle-control-${sha256(model).slice(0, 16)}`");
expect(denialProof).toContain('selectedCapabilityRoots: []');
expect(denialProof).toContain("matcher='*'");
expect(denialProof).toContain("permissionDecision: 'deny'");
expect(denialProof).toContain('permissionDecisionReason: DENIAL_REASON');
expect(denialProof).toContain("hook.eventName === 'preToolUse'");
expect(denialProof).toContain("JSON.stringify(redTools) === JSON.stringify(['view_image'])");
expect(denialProof).toContain('sealedRequest.additionalToolCount === 0');
expect(denialProof).toContain('sealedRequest.topLevelToolsIsArray');
expect(denialProof).toContain('assertExactHookGraph');
expect(denialProof).toContain('buildExpectedWaggleHooks');
expect(denialProof).toContain('hook.commandSha256 === expectedWaggleCommands.get(hook.eventName)');
expect(denialProof).toContain("hookStateEntries.push(`'${key}'={enabled=false}`)");
expect(denialProof).toContain("hookStateEntries.push(`'${key}'={enabled=true,trusted_hash='${currentHash}'}`)");
expect(denialProof).toContain("`hooks.state={${hookStateEntries.join(',')}}`");
expect(denialProof).toContain('hooks.state=<sha256:');
expect(denialProof).not.toContain("hooks.state.'${key}'");
expect(denialProof).toContain('readConfiguredMcpServerNames');
expect(denialProof).toContain('captureMcpBoundary');
expect(denialProof).toContain('assertSameMcpBoundary');
expect(denialProof).toContain('verifySourceSnapshot');
expect(denialProof).toContain('await options.beforeTurn()');
expect(denialProof).toContain('artifactsUnchanged: false');
expect(denialProof).toContain('function buildMcpInventoryArguments()');
expect(denialProof).toContain(
'runChecked(codexExecutable, buildMcpInventoryArguments(), {',
);
expect(denialProof).toContain("`mcp_servers={${mcpServerEntries.join(',')}}`");
expect(denialProof).toContain('mcp_servers=<sha256:');
expect(script).toContain('mcpServerCount = [int]$codexDenialProof.invocation.mcpServerCount');
expect(script).toContain('mcpServerNamesSha256 = [string]$codexDenialProof.invocation.mcpServerNamesSha256');
expect(denialProof).toContain('extras.every((hook) => !hook.enabled)');
expect(denialProof).toContain('verifyWindowsPowerShell');
expect(denialProof).toContain('model_reasoning_effort="low"');
expect(denialProof).toContain('model_provider="openai"');
expect(denialProof).not.toContain('model_providers.openai.');
expect(denialProof).not.toContain('waggle_chatgpt');
const allowedNotificationPolicyStart = denialProof.indexOf(
'const ALLOWED_NOTIFICATION_METHODS = new Set([',
);
const allowedNotificationPolicy = denialProof.slice(
allowedNotificationPolicyStart,
denialProof.indexOf(']);', allowedNotificationPolicyStart) + 3,
);
expect(allowedNotificationPolicy).toContain("'remoteControl/status/changed'");
expect(allowedNotificationPolicy).not.toContain("'model/rerouted'");
expect(denialProof).toContain("entry.message?.method === 'model/rerouted'");
expect(denialProof).toContain('const FAIL_CLOSED_PROJECT_TRUST_WARNING =');
expect(denialProof).toContain('function isFailClosedProjectTrustWarning(notification)');
expect(denialProof).toContain(
"const allowedKeys = new Set(['details', 'path', 'range', 'summary']);",
);
expect(denialProof).toContain('if (!keys.every((key) => allowedKeys.has(key))) return false;');
expect(denialProof).toContain("if (lines.at(-1) !== '') return false;");
expect(denialProof).toContain('&& !isFailClosedProjectTrustWarning(entry)');
const auditFailureInvariantStart = denialProof.indexOf(
'const EVENT_AUDIT_FAILURE_INVARIANTS = new Set([',
);
const auditFailureInvariants = denialProof.slice(
auditFailureInvariantStart,
denialProof.indexOf(']);', auditFailureInvariantStart) + 3,
);
for (const invariant of [
'failure-notification',
'wrong-scope',
'model-reroute',
'unknown-notification-method',
'unknown-item-type',
'forbidden-tool-item',
'agent-message-cardinality',
]) {
expect(auditFailureInvariants).toContain(`'${invariant}'`);
}
const auditFailureKeysStart = denialProof.indexOf(
'const EVENT_AUDIT_FAILURE_KEYS = [',
);
const auditFailureKeys = denialProof.slice(
auditFailureKeysStart,
denialProof.indexOf('];', auditFailureKeysStart) + 2,
);
for (const key of [
'invariant',
'notificationCount',
'failureEventsObserved',
'wrongScopeEventsObserved',
'rerouteEventsObserved',
'unknownNotificationEventsObserved',
'unknownItemEventsObserved',
'toolEventsObserved',
'notificationGraphSha256',
'rejectedMethodSha256',
'rejectedItemTypeSha256',
]) {
expect(auditFailureKeys).toContain(`'${key}'`);
}
expect(denialProof).toContain('eventAuditFailure: null');
expect(denialProof).toContain(
'report.eventAuditFailure = sanitizeEventAuditFailure(error?.eventAuditFailure);',
);
expect(denialProof).toContain('sensitiveDataObserved: false');
expect(denialProof).toContain('paidCalls: 0');
expect(denialProof).not.toContain('dangerously-bypass-hook-trust');
const receiptSource = script.slice(script.indexOf('$receipt = [ordered]@{'));
expect(receiptSource).not.toContain('$codexAuthText');
expect(receiptSource).not.toContain('marker = $codexMarker');
expect(receiptSource).not.toContain('sessionId = $codexSessionId');
expect(script).not.toContain('$sourceCodexAuth');
expect(script).not.toContain('$isolatedCodexAuth');
expect(script).not.toContain("Join-Path $env:CODEX_HOME 'auth.json'");
expect(script).not.toContain('Copy-Item');
expect(script).not.toContain('rawStdout = $codexRaw.Stdout');
expect(script).not.toContain('rawStderr = $codexRaw.Stderr');
expect(script).not.toContain('rawAuthOutput =');
expect(script).not.toContain('$codexPrompt');
expect(script).not.toContain('$invalidCodexLines');
const helperSelfTest = spawnSync(
process.execPath,
[path.join(ROOT, 'scripts', 'verify-codex-tool-denial.mjs'), '--self-test'],
{ cwd: ROOT, encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
expect(helperSelfTest.status, helperSelfTest.stderr).toBe(0);
expect(JSON.parse(helperSelfTest.stdout)).toMatchObject({
pass: true,
paidCalls: 0,
cases: 54,
});
if (process.platform === 'win32') {
const validatorSelfTest = spawnSync(
powershellProbeExecutable(),
[
'-NoLogo',
'-NoProfile',
'-NonInteractive',
'-File',
path.join(ROOT, 'scripts', 'test-windows-official-auth-canaries.ps1'),
'-ExpectedHead',
'0000000000000000000000000000000000000000',
'-ReceiptDir',
path.join(os.tmpdir(), 'unused-waggle-codex-proof-validator-self-test'),
'-CodexProofValidatorSelfTest',
],
{ cwd: ROOT, encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
expect(validatorSelfTest.status, validatorSelfTest.stderr).toBe(0);
expect(JSON.parse(validatorSelfTest.stdout)).toMatchObject({
pass: true,
paidCalls: 0,
cases: 52,
});
}
});
it('stages Codex official setup before any model invocation', () => {
const script = fs.readFileSync(
path.join(ROOT, 'scripts', 'test-windows-official-auth-canaries.ps1'),
'utf-8',
).replace(/\r\n/g, '\n');
const denialProof = fs.readFileSync(
path.join(ROOT, 'scripts', 'verify-codex-tool-denial.mjs'),
'utf-8',
).replace(/\r\n/g, '\n');
expect(denialProof).toContain('const CANARY_STAGES = new Set([');
for (const stage of [
'app-server-spawn',
'initialize',
'hooks-list',
'pre-turn-boundary',
'thread-start',
'turn-start',
'turn-completed',
'event-audit',
'app-server-close',
'post-turn-invariants',
]) {
expect(denialProof).toContain(`'${stage}'`);
}
expect(denialProof).toContain('function sanitizeProtocolCode(value)');
expect(denialProof).toContain('value >= -2_147_483_648');
expect(denialProof).toContain('value <= 2_147_483_647');
expect(denialProof).toContain('const FAILURE_NOTIFICATION_METHODS = new Set([');
for (const method of [
'error',
'warning',
'guardianWarning',
'configWarning',
'deprecationNotice',
]) {
expect(denialProof).toContain(`'${method}'`);
}
for (const method of [
'account/updated',
'mcpServer/startupStatus/updated',
'model/safetyBuffering/updated',
'model/verification',
'thread/name/updated',
'thread/settings/updated',
'turn/moderationMetadata',
]) {
expect(denialProof).toContain(`'${method}'`);
}
expect(denialProof).not.toContain("'rawResponse/completed'");
expect(denialProof).not.toContain("'rawResponseItem/completed'");
expect(denialProof).toContain("const setupOnly = flags['setup-only'] === true;");
expect(denialProof).toContain('if (options.setupOnly) {');
expect(denialProof).toContain('modelCalls: 0');
expect(denialProof).toContain('turnStartCalls: 0');
expect(denialProof).toContain("completedStage: 'thread-start'");
expect(denialProof).toContain('failureStage: report.diagnostic.failureStage');
expect(denialProof).toContain('protocolCode: report.diagnostic.protocolCode');
const setupBranchStart = denialProof.indexOf('if (options.setupOnly) {');
const paidTurnStart = denialProof.indexOf("client.send({ method: 'turn/start'", setupBranchStart);
expect(setupBranchStart).toBeGreaterThan(-1);
expect(paidTurnStart).toBeGreaterThan(setupBranchStart);
expect(denialProof.slice(setupBranchStart, paidTurnStart)).not.toContain("method: 'turn/start'");
const closeCall = denialProof.indexOf('await client.close();', setupBranchStart);
const finalAudit = denialProof.indexOf('const finalEvents = eventAudit(', closeCall);
const finalProtocolCheck = denialProof.indexOf(
"'Codex app-server protocol failed after close'",
finalAudit,
);
expect(closeCall).toBeGreaterThan(setupBranchStart);
expect(finalAudit).toBeGreaterThan(closeCall);
expect(finalProtocolCheck).toBeGreaterThan(finalAudit);
expect(denialProof).toContain(
'proof: { executed: false, paidCalls: 0, pass: null }',
);
expect(denialProof).toContain(
'report.proof = { executed: true, paidCalls: 0, pass: true };',
);
expect(denialProof).toContain('proofStateSatisfied(report.proof, setupOnly)');
expect(script).toContain('function Assert-CodexSetupPreflight');
expect(script).toContain('function Assert-CodexFailureStage');
expect(script).toContain('function Assert-NullableProtocolCode');
expect(script).toContain("'--setup-only'");
expect(script).toContain('$codexSetupRaw = Invoke-CapturedProcess');
expect(script).toContain('Assert-CodexSetupPreflight');
expect(script).toContain('stage = $failureStage');
expect(script).toContain('protocolCode = $protocolCode');
expect(script).toContain(
"Assert-JsonBoolean -Value $Report.proof.executed -Expected $false `",
);
expect(script).toContain("if ($null -ne $Report.proof.pass) {");
expect(script).not.toContain("-Label 'Codex setup offline proof pass'");
const codexAuth = script.indexOf('$codexAuthRaw = Invoke-CapturedProcess');
const hermesAuth = script.indexOf('$hermesAuthRaw = Invoke-CapturedProcess');
const codexSetup = script.indexOf('$codexSetupRaw = Invoke-CapturedProcess');
const claudeMarker = script.indexOf('$claudeMarker =');
const claudeRun = script.indexOf('$claudeRaw = Invoke-CapturedProcess');
const codexRun = script.indexOf('$codexRaw = Invoke-CapturedProcess');
const hermesRun = script.indexOf('$hermesRaw = Invoke-CapturedProcess');
expect(codexAuth).toBeGreaterThan(-1);
expect(hermesAuth).toBeGreaterThan(codexAuth);
expect(codexSetup).toBeGreaterThan(hermesAuth);
expect(claudeMarker).toBeGreaterThan(codexSetup);
expect(claudeRun).toBeGreaterThan(claudeMarker);
expect(codexRun).toBeGreaterThan(claudeRun);
expect(hermesRun).toBeGreaterThan(codexRun);
});
it('preserves only a whitelisted Codex diagnostic after a non-zero child', () => {
const script = fs.readFileSync(
path.join(ROOT, 'scripts', 'test-windows-official-auth-canaries.ps1'),
'utf-8',
).replace(/\r\n/g, '\n');
const denialProof = fs.readFileSync(
path.join(ROOT, 'scripts', 'verify-codex-tool-denial.mjs'),
'utf-8',
).replace(/\r\n/g, '\n');
expect(denialProof).toContain('function sanitizeTurnFailure');
expect(denialProof).toContain('turnFailure: null');
expect(denialProof).toContain('report.turnFailure = error?.turnFailure ?? null');
expect(denialProof).toContain("client.notification('turn/completed', (entry) => (");
expect(denialProof).toContain('entry.message?.params?.threadId === threadId');
expect(denialProof).toContain('entry.message?.params?.turn?.id === turnId');
expect(denialProof).toContain('turnFailure: report.turnFailure');
expect(script).toContain('function Assert-SanitizedCodexTurnFailure');
expect(script).toContain('function New-SanitizedCodexFailureReceipt');
expect(script).toContain("kind = 'windows-official-auth-codex-failure'");
expect(script).toContain("Join-Path $receiptLayout.Staging 'official-auth-failure.json'");
expect(script).toContain('turnFailure = Assert-SanitizedCodexTurnFailure');
expect(script).not.toContain('failureReceipt.rawStdout');
expect(script).not.toContain('failureReceipt.rawStderr');
expect(script).not.toContain('failureReceipt.message');
expect(script).not.toContain('failureReceipt.additionalDetails');
const codexRun = script.indexOf('$codexRaw = Invoke-CapturedProcess');
const failureBranch = script.indexOf(
'if ($codexRaw.TimedOut -or $codexRaw.ExitCode -ne 0)',
codexRun,
);
const cleanup = script.indexOf('Remove-OwnedDirectory -Path $tempRoot', failureBranch);
const failureWrite = script.indexOf("'official-auth-failure.json'", cleanup);
const publish = script.indexOf('$published = $true', failureWrite);
const nonZero = script.indexOf('Assert-ProcessPassed -Result $codexRaw', publish);
expect(codexRun).toBeGreaterThan(-1);
expect(failureBranch).toBeGreaterThan(codexRun);
expect(cleanup).toBeGreaterThan(failureBranch);
expect(failureWrite).toBeGreaterThan(cleanup);
expect(publish).toBeGreaterThan(failureWrite);
expect(nonZero).toBeGreaterThan(publish);
});
it('release workflow builds packages before bundling the desktop sidecar', () => {
// Release builds must follow the same package -> sidecar ordering as the
// PR Tauri verification lane, otherwise tag artifacts can ship stale or
// missing workspace dist outputs even when PR verification was green.
const workflow = fs.readFileSync(
path.join(ROOT, '.github', 'workflows', 'release.yml'),
'utf-8',
);
const buildPackageIndexes = [...workflow.matchAll(/npm run build:packages/g)].map(
(match) => match.index ?? -1,
);
const sidecarIndexes = [...workflow.matchAll(/node scripts\/build-sidecar\.mjs/g)].map(
(match) => match.index ?? -1,
);
expect(buildPackageIndexes).toHaveLength(sidecarIndexes.length);
expect(sidecarIndexes).toHaveLength(2);
for (const [index, sidecarIndex] of sidecarIndexes.entries()) {
expect(buildPackageIndexes[index]).toBeLessThan(sidecarIndex);
}
});
it('release publication requires the verified Windows vault-key ACL receipt', () => {
const publisher = fs.readFileSync(
path.join(ROOT, 'scripts', 'publish-windows-release.ps1'),
'utf-8',
);
expect(publisher).toMatch(/\$cleanRequiredChecks\s*=\s*@\([\s\S]*'vaultKeyAclRestricted'[\s\S]*\)/);
expect(publisher).toMatch(/\$upgradeRequiredChecks\s*=\s*@\([\s\S]*'vaultKeyAclRestricted'[\s\S]*\)/);
});
it('release publication requires external profile isolation evidence', () => {
const publisher = fs.readFileSync(
path.join(ROOT, 'scripts', 'publish-windows-release.ps1'),
'utf-8',
);
expect(publisher).toMatch(
/\$cleanRequiredChecks\s*=\s*@\([\s\S]*'externalProfileRootsUnchanged'[\s\S]*\)/,
);
expect(publisher).toMatch(
/\$upgradeRequiredChecks\s*=\s*@\([\s\S]*'externalProfileRootsUnchanged'[\s\S]*\)/,
);
});
it('release publication requires real default-profile workspace and memory lifecycle evidence', () => {
const publisher = fs.readFileSync(
path.join(ROOT, 'scripts', 'publish-windows-release.ps1'),
'utf-8',
);
const cleanRequiredChecks = publisher.match(
/\$cleanRequiredChecks\s*=\s*@\(([\s\S]*?)\r?\n\s*\)/,
)?.[1];
const upgradeRequiredChecks = publisher.match(
/\$upgradeRequiredChecks\s*=\s*@\(([\s\S]*?)\r?\n\s*\)/,
)?.[1];
expect(cleanRequiredChecks).toBeDefined();
expect(upgradeRequiredChecks).toBeDefined();
for (const check of [
'defaultProfileDataDir',
'realWorkspaceAndMemorySeeded',
'repairRealWorkspaceAndMemoryPreserved',
'uninstallRealWorkspaceAndMemoryPreserved',
'certificateProfileCleanup',
]) {
expect(cleanRequiredChecks).toContain(`'${check}'`);
expect(upgradeRequiredChecks).toContain(`'${check}'`);
}
expect(upgradeRequiredChecks).toContain("'upgradeRealWorkspaceAndMemoryPreserved'");
expect(publisher).toContain('lifecycleData.workspaceId');
expect(publisher).toContain('lifecycleData.personalFrameId');
expect(publisher).toContain('lifecycleData.workspaceFrameId');
expect(publisher).toContain('lifecycleData.preUninstallManifestEntryCount');
expect(publisher).toContain('lifecycleData.preUninstallManifestSha256');
expect(publisher).toContain('lifecycleData.postUninstallManifestSha256');
expect(publisher).toContain('unchanged uninstall manifest');
});
it.runIf(process.platform === 'win32')(
'release receipt guards reject stringified schema versions and truthy non-booleans',
() => {
const publisher = fs
.readFileSync(path.join(ROOT, 'scripts', 'publish-windows-release.ps1'), 'utf-8')
.replace(/\r\n/g, '\n');
const envelopeStart = publisher.indexOf(
'function Assert-PassingWindowsCertificateReceipt {',
);
const checkStart = publisher.indexOf(
'function Assert-PassingWindowsCertificateCheck {',
);
const verifierStart = publisher.indexOf(
'\nfunction Assert-ExactReleaseAssets {',
checkStart,
);
expect(envelopeStart).toBeGreaterThanOrEqual(0);
expect(checkStart).toBeGreaterThan(envelopeStart);
expect(verifierStart).toBeGreaterThan(checkStart);
expect([
...publisher.matchAll(
/^function Assert-PassingWindowsCertificateReceipt \{/gm,
),
]).toHaveLength(1);
expect([
...publisher.matchAll(
/^function Assert-PassingWindowsCertificateCheck \{/gm,
),
]).toHaveLength(1);
const probeRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-receipt-types-'));
const probePath = path.join(probeRoot, 'probe.ps1');
const helperSource = publisher.slice(envelopeStart, verifierStart);
const fixtureSource = String.raw`
function Expect-Rejection {
param([scriptblock]$Action, [string]$Label)
$rejected = $false
try { & $Action } catch { $rejected = $true }
if (-not $rejected) { throw "$Label was accepted" }
}
$good = '{"schemaVersion":4,"certificationMode":"same-version-repair","status":"passed","checks":{"proof":true}}' | ConvertFrom-Json
$longVersion = '{"schemaVersion":4,"certificationMode":"same-version-repair","status":"passed","checks":{"proof":true}}' | ConvertFrom-Json
$longVersion.schemaVersion = [long]4
$stringVersion = '{"schemaVersion":"4","certificationMode":"same-version-repair","status":"passed","checks":{"proof":true}}' | ConvertFrom-Json
$wrongVersion = '{"schemaVersion":3,"certificationMode":"same-version-repair","status":"passed","checks":{"proof":true}}' | ConvertFrom-Json
$missingMode = '{"schemaVersion":4,"status":"passed","checks":{"proof":true}}' | ConvertFrom-Json
$wrongMode = '{"schemaVersion":4,"certificationMode":"version-to-version-upgrade","status":"passed","checks":{"proof":true}}' | ConvertFrom-Json
$numericMode = '{"schemaVersion":4,"certificationMode":1,"status":"passed","checks":{"proof":true}}' | ConvertFrom-Json
$missingStatus = '{"schemaVersion":4,"certificationMode":"same-version-repair","checks":{"proof":true}}' | ConvertFrom-Json
$wrongStatus = '{"schemaVersion":4,"certificationMode":"same-version-repair","status":"failed","checks":{"proof":true}}' | ConvertFrom-Json
$numericStatus = '{"schemaVersion":4,"certificationMode":"same-version-repair","status":1,"checks":{"proof":true}}' | ConvertFrom-Json
$stringCheck = '{"schemaVersion":4,"certificationMode":"same-version-repair","status":"passed","checks":{"proof":"true"}}' | ConvertFrom-Json
$numericCheck = '{"schemaVersion":4,"certificationMode":"same-version-repair","status":"passed","checks":{"proof":1}}' | ConvertFrom-Json
$falseCheck = '{"schemaVersion":4,"certificationMode":"same-version-repair","status":"passed","checks":{"proof":false}}' | ConvertFrom-Json
$missingCheck = '{"schemaVersion":4,"certificationMode":"same-version-repair","status":"passed","checks":{}}' | ConvertFrom-Json
Assert-PassingWindowsCertificateReceipt $good 'same-version-repair' 'good fixture'
Assert-PassingWindowsCertificateReceipt $longVersion 'same-version-repair' 'PowerShell 7 integer fixture'
Assert-PassingWindowsCertificateCheck $good 'proof' 'good fixture'
Expect-Rejection { Assert-PassingWindowsCertificateReceipt $stringVersion 'same-version-repair' 'string version' } 'string version'
Expect-Rejection { Assert-PassingWindowsCertificateReceipt $wrongVersion 'same-version-repair' 'wrong version' } 'wrong version'
Expect-Rejection { Assert-PassingWindowsCertificateReceipt $missingMode 'same-version-repair' 'missing mode' } 'missing mode'
Expect-Rejection { Assert-PassingWindowsCertificateReceipt $wrongMode 'same-version-repair' 'wrong mode' } 'wrong mode'
Expect-Rejection { Assert-PassingWindowsCertificateReceipt $numericMode 'same-version-repair' 'numeric mode' } 'numeric mode'
Expect-Rejection { Assert-PassingWindowsCertificateReceipt $missingStatus 'same-version-repair' 'missing status' } 'missing status'
Expect-Rejection { Assert-PassingWindowsCertificateReceipt $wrongStatus 'same-version-repair' 'wrong status' } 'wrong status'
Expect-Rejection { Assert-PassingWindowsCertificateReceipt $numericStatus 'same-version-repair' 'numeric status' } 'numeric status'
Expect-Rejection { Assert-PassingWindowsCertificateCheck $stringCheck 'proof' 'string check' } 'string check'
Expect-Rejection { Assert-PassingWindowsCertificateCheck $numericCheck 'proof' 'numeric check' } 'numeric check'
Expect-Rejection { Assert-PassingWindowsCertificateCheck $falseCheck 'proof' 'false check' } 'false check'
Expect-Rejection { Assert-PassingWindowsCertificateCheck $missingCheck 'proof' 'missing check' } 'missing check'
`;
try {
fs.writeFileSync(probePath, `${helperSource}\n${fixtureSource}`, 'utf-8');
const result = spawnSync(
powershellProbeExecutable(),
['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath],
{ encoding: 'utf-8', timeout: 30_000, windowsHide: true },
);
if (result.status !== 0) {
throw new Error(`Receipt type probe failed: ${result.stderr || result.stdout}`);
}
} finally {
fs.rmSync(probeRoot, { recursive: true, force: true });
}
},
);
it.runIf(process.platform === 'win32')(
'executes sidecar source installed-bundle and publication provenance gates',
() => {
const certifier = fs
.readFileSync(path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'), 'utf8')
.replace(/\r\n/g, '\n');
const publisher = fs
.readFileSync(path.join(ROOT, 'scripts', 'publish-windows-release.ps1'), 'utf8')
.replace(/\r\n/g, '\n');
const sliceFunctions = (source: string, start: string, end: string) => {
const startIndex = source.indexOf(start);
const endIndex = source.indexOf(end, startIndex + start.length);
expect(startIndex).toBeGreaterThanOrEqual(0);
expect(endIndex).toBeGreaterThan(startIndex);
return source.slice(startIndex, endIndex);
};
const assertTrue = sliceFunctions(
certifier,
'function Assert-True {',
'\nfunction Get-HttpStatusCode {',
);
const sidecarHelpers = sliceFunctions(
certifier,
'function Get-SidecarProvenance {',
'\nfunction Get-ExternalProfileRootSnapshot {',
);
const publisherHelper = sliceFunctions(
publisher,
'function Assert-ReceiptSourceHashes {',
'\nfunction Assert-ReleaseDoesNotExist {',
);
const fixtureRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'waggle-sidecar-binding-'));
const sourceContents = new Map<string, string>([
['package-lock.json', '{"lockfileVersion":3}\n'],
['package.json', '{"name":"binding-fixture"}\n'],
['packages/server/package.json', '{"name":"@waggle/server"}\n'],
['packages/server/src/local/service.ts', 'export const fixture = true;\n'],
['packages/server/tsconfig.json', '{"extends":"../../tsconfig.base.json"}\n'],
['scripts/build-sidecar.mjs', 'export {};\n'],
['tsconfig.base.json', '{"compilerOptions":{"target":"ES2022"}}\n'],
]);
const writeRelative = (relative: string, content: string | Buffer) => {
const target = path.join(fixtureRoot, ...relative.split('/'));
fs.mkdirSync(path.dirname(target), { recursive: true });
fs.writeFileSync(target, content);
return target;
};
const hash = (value: string | Buffer) => createHash('sha256').update(value).digest('hex');
const inputs = () => [...sourceContents.keys()]
.sort((left, right) => left < right ? -1 : left > right ? 1 : 0)
.map((relative) => ({
path: relative,
sha256: hash(fs.readFileSync(path.join(fixtureRoot, ...relative.split('/')))),
}));
const serviceBytes = (revision: string, payload: string) => {
const payloadBytes = Buffer.from(payload, 'utf8');
const manifest = {
schemaVersion: 1,
sourceRevision: revision,
entryPoint: 'packages/server/src/local/service.ts',
sourceInputs: inputs(),
bundlePayload: { sizeBytes: payloadBytes.byteLength, sha256: hash(payloadBytes) },
};
return Buffer.concat([
Buffer.from(
`// Waggle-Sidecar-Provenance: ${Buffer.from(JSON.stringify(manifest)).toString('base64')}\n`,
'utf8',
),
payloadBytes,
]);
};
const run = (command: string, args: string[], cwd = fixtureRoot) => {
const result = spawnSync(command, args, {
cwd,
encoding: 'utf8',
timeout: 60_000,
windowsHide: true,
});
expect(result.status, result.stderr || result.stdout).toBe(0);
return result;
};
try {
for (const [relative, content] of sourceContents) writeRelative(relative, content);
run('git', ['init']);
run('git', ['config', 'user.email', 'sidecar-fixture@waggle.invalid']);
run('git', ['config', 'user.name', 'Waggle Fixture']);
run('git', ['add', '--', ...sourceContents.keys()]);
run('git', ['commit', '-m', 'fixture']);
const revision = run('git', ['rev-parse', 'HEAD']).stdout.trim();
const packagedPath = writeRelative('packaged-service.js', serviceBytes(revision, 'ok\n'));
const installedPath = writeRelative('installed-service.js', serviceBytes(revision, 'ok\n'));
const changedBundlePath = writeRelative(
'changed-bundle.js',
serviceBytes(revision, 'changed\n'),
);
const wrongRevisionPath = writeRelative(
'wrong-revision.js',
serviceBytes('b'.repeat(40), 'ok\n'),
);
const tamperedPath = writeRelative(
'tampered-service.js',
Buffer.concat([serviceBytes(revision, 'ok\n'), Buffer.from('tampered\n')]),
);
const probePath = writeRelative(
'sidecar-probe.ps1',
`${String.raw`param(
[string]$Mode,
[string]$RepositoryRoot,
[string]$ExpectedRevision,
[string]$PackagedPath,
[string]$InstalledPath,
[string]$ChangedBundlePath,
[string]$WrongRevisionPath,
[string]$TamperedPath
)
`}${assertTrue}\n${sidecarHelpers}\n${String.raw`
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
function Expect-Rejection {
param([scriptblock]$Action, [string]$Label)
$rejected = $false
try { & $Action } catch { $rejected = $true }
if (-not $rejected) { throw "$Label was accepted" }
}
$git = (Get-Command git -CommandType Application -ErrorAction Stop | Select-Object -First 1).Source
if ($Mode -eq 'clean') {
$packaged = Get-SidecarProvenance $PackagedPath
$installed = Get-SidecarProvenance $InstalledPath
Assert-SidecarBundleBinding -Packaged $packaged -Installed $installed
Assert-SidecarSourceBinding -Provenance $packaged -RepositoryRoot $RepositoryRoot -ExpectedRevision $ExpectedRevision -GitExecutable $git
} elseif ($Mode -eq 'bundle-rejections') {
$packaged = Get-SidecarProvenance $PackagedPath
$changed = Get-SidecarProvenance $ChangedBundlePath
$wrongRevision = Get-SidecarProvenance $WrongRevisionPath
Expect-Rejection { Assert-SidecarBundleBinding -Packaged $packaged -Installed $changed } 'Changed bundle'
Expect-Rejection { Assert-SidecarBundleBinding -Packaged $packaged -Installed $wrongRevision } 'Changed provenance revision'
$wrongCount = Get-SidecarProvenance $InstalledPath
$wrongCount.sourceInputCount = [int]$wrongCount.sourceInputCount + 1
Expect-Rejection { Assert-SidecarBundleBinding -Packaged $packaged -Installed $wrongCount } 'Changed input count'
Expect-Rejection { Get-SidecarProvenance $TamperedPath | Out-Null } 'Tampered payload'
} elseif ($Mode -eq 'source-rejection') {
$provenance = Get-SidecarProvenance $PackagedPath
Expect-Rejection { Assert-SidecarSourceBinding -Provenance $provenance -RepositoryRoot $RepositoryRoot -ExpectedRevision $ExpectedRevision -GitExecutable $git } 'Dirty or wrong-revision source'
} else {
throw 'Unknown probe mode'
}
`}`,
'utf8',
);
const powershell = powershellProbeExecutable();
const probe = (mode: string, sourcePath = packagedPath) => run(
powershell,
[
'-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', probePath,
'-Mode', mode,
'-RepositoryRoot', fixtureRoot,
'-ExpectedRevision', revision,
'-PackagedPath', sourcePath,
'-InstalledPath', installedPath,
'-ChangedBundlePath', changedBundlePath,
'-WrongRevisionPath', wrongRevisionPath,
'-TamperedPath', tamperedPath,
],
);
probe('clean');
probe('bundle-rejections');
const configRelative = 'packages/server/tsconfig.json';
fs.appendFileSync(
path.join(fixtureRoot, ...configRelative.split('/')),
'// dirty transform config\n',
);
const dirtyServicePath = writeRelative(
'dirty-source-service.js',
serviceBytes(revision, 'ok\n'),
);
probe('source-rejection', dirtyServicePath);
probe('source-rejection', wrongRevisionPath);
const releaseInstaller = writeRelative(
'target/release/bundle/nsis/Waggle.exe',
'installer',
);
const generatedInstaller = writeRelative(
'target/release/nsis/installer.nsi',
'generated installer',
);
const certifierFixture = writeRelative(
'scripts/certify-windows-installer.ps1',
'certifier',
);
const hookFixture = writeRelative('app/src-tauri/nsis/installer.nsi', 'hook');
const currentSidecar = writeRelative(
'app/src-tauri/resources/service.js',
serviceBytes(revision, 'ok\n'),
);
const firstLine = fs.readFileSync(currentSidecar).subarray(
0,
fs.readFileSync(currentSidecar).indexOf(0x0a),
).toString('utf8');
const provenanceBytes = Buffer.from(
firstLine.slice('// Waggle-Sidecar-Provenance: '.length),
'base64',
);
const receiptPath = writeRelative(
'receipt.json',
JSON.stringify({
evidence: {
certifierSha256: hash(fs.readFileSync(certifierFixture)),
installerHookSha256: hash(fs.readFileSync(hookFixture)),
generatedInstallerScriptSha256: hash(fs.readFileSync(generatedInstaller)),
sidecarBundleSha256: hash(fs.readFileSync(currentSidecar)),
sidecarProvenanceSha256: hash(provenanceBytes),
sidecarSourceRevision: revision,
sidecarSourceInputCount: inputs().length,
},
}),
);
const publisherProbePath = writeRelative(
'publisher-probe.ps1',
`${String.raw`param([string]$FixtureRoot, [string]$InstallerPath, [string]$ReceiptPath, [string]$SourceRevision)
`}${publisherHelper}\n${String.raw`
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
Set-Location -LiteralPath $FixtureRoot
function Expect-Rejection {
param([scriptblock]$Action, [string]$Label)
$rejected = $false
try { & $Action } catch { $rejected = $true }
if (-not $rejected) { throw "$Label was accepted" }
}
$installer = Get-Item -LiteralPath $InstallerPath
$receipt = Get-Content -Raw -LiteralPath $ReceiptPath | ConvertFrom-Json
Assert-ReceiptSourceHashes @($receipt) $installer $SourceRevision
foreach ($property in @('sidecarBundleSha256', 'sidecarProvenanceSha256', 'sidecarSourceRevision', 'sidecarSourceInputCount')) {
$changed = ($receipt | ConvertTo-Json -Depth 8 | ConvertFrom-Json)
if ($property -eq 'sidecarSourceInputCount') { $changed.evidence.$property = [int]$changed.evidence.$property + 1 }
elseif ($property -eq 'sidecarSourceRevision') { $changed.evidence.$property = ('f' * 40) }
else { $changed.evidence.$property = ('0' * 64) }
Expect-Rejection { Assert-ReceiptSourceHashes @($changed) $installer $SourceRevision } "Changed $property receipt"
}
$sidecarPath = Join-Path $FixtureRoot 'app/src-tauri/resources/service.js'
$original = [System.IO.File]::ReadAllBytes($sidecarPath)
[System.IO.File]::AppendAllText($sidecarPath, 'tampered')
try {
Expect-Rejection { Assert-ReceiptSourceHashes @($receipt) $installer $SourceRevision } 'Changed current bundle'
} finally {
[System.IO.File]::WriteAllBytes($sidecarPath, $original)
}
`}`,
'utf8',
);
run(
powershell,
[
'-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', publisherProbePath,
'-FixtureRoot', fixtureRoot,
'-InstallerPath', releaseInstaller,
'-ReceiptPath', receiptPath,
'-SourceRevision', revision,
],
);
} finally {
fs.rmSync(fixtureRoot, { recursive: true, force: true });
}
},
120_000,
);
});
describe('Windows installer certifier timeout contract', () => {
it('honors one bounded JSON GET timeout override and still fails closed', async () => {
if (process.platform !== 'win32') return;
const pwsh = powershellProbeExecutable();
const script = fs.readFileSync(
path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'),
'utf-8',
);
const helperStart = script.indexOf('function Invoke-JsonRequest {');
const helperEnd = script.indexOf('\nfunction Invoke-JsonPostRequest {');
expect(helperStart).toBeGreaterThanOrEqual(0);
expect(helperEnd).toBeGreaterThan(helperStart);
const helper = script.slice(helperStart, helperEnd);
let responseDelayMs = 1_200;
const server = http.createServer((_request, response) => {
setTimeout(() => {
response.writeHead(200, { 'content-type': 'application/json' });
response.end('{"ok":true}');
}, responseDelayMs);
});
await new Promise<void>((resolve) => server.listen(0, '127.0.0.1', resolve));
const address = server.address();
if (!address || typeof address === 'string') {
server.close();
throw new Error('Could not bind delayed loopback probe server');
}
const uri = `http://127.0.0.1:${address.port}/`;
const runProbe = (timeoutSeconds: number) =>
new Promise<void>((resolve, reject) => {
execFile(
pwsh,
[
'-NoLogo',
'-NoProfile',
'-NonInteractive',
'-Command',
`${helper}\n$result = Invoke-JsonRequest -Uri '${uri}' -Headers @{} -TimeoutSeconds ${timeoutSeconds}\nif (-not $result.ok) { throw 'Unexpected JSON payload' }`,
],
{ encoding: 'utf-8', timeout: 10_000, windowsHide: true },
(error) => (error ? reject(error) : resolve()),
);
});
try {
await expect(runProbe(2)).resolves.toBeUndefined();
responseDelayMs = 1_500;
await expect(runProbe(1)).rejects.toBeDefined();
} finally {
await new Promise<void>((resolve, reject) => {
server.close((error) => (error ? reject(error) : resolve()));
});
}
});
it('retries one transient built-in proxy liveness timeout and stays bounded', async () => {
if (process.platform !== 'win32') return;
const pwsh = powershellProbeExecutable();
const script = fs.readFileSync(
path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'),
'utf-8',
);
const helperStart = script.indexOf('function Invoke-JsonRequest {');
const helperEnd = script.indexOf('\nfunction Invoke-JsonPostRequest {');
expect(helperStart).toBeGreaterThanOrEqual(0);
expect(helperEnd).toBeGreaterThan(helperStart);
const helpers = script.slice(helperStart, helperEnd);
expect(helpers).toContain('function Invoke-BuiltInProxyLivenessProbe {');
expect(helpers).toContain('[int]$AttemptTimeoutSeconds = 5');
expect(helpers).toContain('[int]$MaxAttempts = 2');
const runProbe = (mode: 'recover' | 'fail') =>
new Promise<void>((resolve, reject) => {
const stub = mode === 'recover'
? `
$script:requestCount = 0
function Invoke-JsonRequest {
param([string]$Uri, [int]$TimeoutSeconds)
$script:requestCount += 1
if ($script:requestCount -eq 1) { throw 'simulated timeout' }
return [pscustomobject]@{ status = 'healthy' }
}
$result = Invoke-BuiltInProxyLivenessProbe -Uri 'http://127.0.0.1:1/' -AttemptTimeoutSeconds 1 -MaxAttempts 2 -RetryDelayMilliseconds 0
if ($result.status -cne 'healthy') { throw 'Unexpected liveness payload' }
if ($script:requestCount -ne 2) { throw "Expected two liveness requests, got $script:requestCount" }
`
: `
$script:requestCount = 0
function Invoke-JsonRequest {
param([string]$Uri, [int]$TimeoutSeconds)
$script:requestCount += 1
throw 'simulated timeout'
}
$failed = $false
try {
[void](Invoke-BuiltInProxyLivenessProbe -Uri 'http://127.0.0.1:1/' -AttemptTimeoutSeconds 1 -MaxAttempts 2 -RetryDelayMilliseconds 0)
} catch {
$failed = $true
if ($_.Exception.Message -cne 'simulated timeout') { throw }
}
if (-not $failed) { throw 'Persistent liveness failure was not rethrown' }
if ($script:requestCount -ne 2) { throw "Expected two liveness requests, got $script:requestCount" }
`;
execFile(
pwsh,
[
'-NoLogo',
'-NoProfile',
'-NonInteractive',
'-Command',
`${helpers}\n${stub}`,
],
{ encoding: 'utf-8', timeout: 10_000, windowsHide: true },
(error) => (error ? reject(error) : resolve()),
);
});
await expect(runProbe('recover')).resolves.toBeUndefined();
await expect(runProbe('fail')).resolves.toBeUndefined();
});
it('retries only transient desktop session bootstrap failures and preserves the service log', async () => {
if (process.platform !== 'win32') return;
const pwsh = powershellProbeExecutable();
const script = fs.readFileSync(
path.join(ROOT, 'scripts', 'certify-windows-installer.ps1'),
'utf-8',
);
const helperStart = script.indexOf('function Invoke-JsonRequest {');
const helperEnd = script.indexOf('\nfunction Invoke-JsonPostRequest {');
expect(helperStart).toBeGreaterThanOrEqual(0);
expect(helperEnd).toBeGreaterThan(helperStart);
const helpers = script.slice(helperStart, helperEnd);
const sessionHelperStart = helpers.indexOf('function Invoke-SessionTokenBootstrapProbe {');
expect(sessionHelperStart).toBeGreaterThanOrEqual(0);
const sessionHelper = helpers.slice(sessionHelperStart);
expect(sessionHelper).toContain('[int]$AttemptTimeoutSeconds = 5');
expect(sessionHelper).toContain('[int]$MaxAttempts = 2');
expect(script).toContain(
'$tokenResponse = Invoke-SessionTokenBootstrapProbe `',
);
expect(script).toContain(
"-Headers @{ 'x-waggle-desktop-bootstrap' = $bootstrapToken }",
);
expect(script).toContain("$serviceLog = Join-Path $dataDir 'logs\\service.log'");
const runProbe = (mode: 'recover' | 'persistent' | 'forbidden') =>
new Promise<void>((resolve, reject) => {
const stub = `
$script:requests = @()
function Invoke-JsonRequest {
param([string]$Uri, [hashtable]$Headers, [int]$TimeoutSeconds)
$script:requests += [pscustomobject]@{
Uri = $Uri
Bootstrap = [string]$Headers['x-waggle-desktop-bootstrap']
TimeoutSeconds = $TimeoutSeconds
}
if ('${mode}' -eq 'recover' -and $script:requests.Count -gt 1) {
return [pscustomobject]@{ token = 'certifier-session-token' }
}
if ('${mode}' -eq 'forbidden') {
$exception = [System.Exception]::new('simulated HTTP 403')
$exception | Add-Member -NotePropertyName Response -NotePropertyValue (
[pscustomobject]@{ StatusCode = 403 }
)
throw $exception
}
throw [System.Threading.Tasks.TaskCanceledException]::new('simulated timeout')
}
$failed = $false
try {
$result = Invoke-SessionTokenBootstrapProbe -Uri 'http://127.0.0.1:1/api/auth/session-token' -Headers @{ 'x-waggle-desktop-bootstrap' = 'sentinel-bootstrap' } -AttemptTimeoutSeconds 1 -MaxAttempts 2 -RetryDelayMilliseconds 0
if ('${mode}' -ne 'recover') { throw 'Expected session bootstrap failure' }
if ($result.token -cne 'certifier-session-token') { throw 'Unexpected token payload' }
} catch {
$failed = $true
if ('${mode}' -eq 'recover') { throw }
if ('${mode}' -eq 'forbidden' -and [int]$_.Exception.Response.StatusCode -ne 403) { throw }
}
if ('${mode}' -ne 'recover' -and -not $failed) { throw 'Failure was not rethrown' }
$expectedCount = if ('${mode}' -eq 'forbidden') { 1 } else { 2 }
if ($script:requests.Count -ne $expectedCount) {
throw "Expected $expectedCount session bootstrap requests, got $($script:requests.Count)"
}
foreach ($request in $script:requests) {
if ($request.Uri -cne 'http://127.0.0.1:1/api/auth/session-token') { throw 'Session bootstrap URI was not forwarded' }
if ($request.Bootstrap -cne 'sentinel-bootstrap') { throw 'Session bootstrap header was not forwarded' }
if ($request.TimeoutSeconds -ne 1) { throw 'Session bootstrap timeout was not forwarded' }
}
`;
execFile(
pwsh,
[
'-NoLogo',
'-NoProfile',
'-NonInteractive',
'-Command',
`Set-StrictMode -Version Latest\n${helpers}\n${stub}`,
],
{ encoding: 'utf-8', timeout: 10_000, windowsHide: true },
(error) => (error ? reject(error) : resolve()),
);
});
await expect(runProbe('recover')).resolves.toBeUndefined();
await expect(runProbe('persistent')).resolves.toBeUndefined();
await expect(runProbe('forbidden')).resolves.toBeUndefined();
});
});
describe('Playwright Visual Regression Setup', () => {
it('playwright.config.ts exists', () => {
const conf = path.join(ROOT, 'playwright.config.ts');
expect(fs.existsSync(conf)).toBe(true);
const content = fs.readFileSync(conf, 'utf-8');
expect(content).toContain('maxDiffPixelRatio');
expect(content).toContain('localhost:3333');
expect(content).not.toContain('npx tsx packages/server/src/local/start.ts');
});
it('starts the E2E server with the same Node runtime without shadowing external tool PATH', () => {
const conf = path.join(ROOT, 'playwright.config.ts');
const tsxCli = path.join(ROOT, 'node_modules', 'tsx', 'dist', 'cli.mjs');
const probeSource = `
(async () => {
process.execPath = process.env.WAGGLE_PROBE_NODE_EXEC;
const { default: config } = await import(${JSON.stringify(pathToFileURL(conf).href)});
const webServer = Array.isArray(config.webServer)
? config.webServer[0]
: config.webServer;
const pathKey = Object.keys(webServer.env)
.find((key) => key.toLowerCase() === 'path');
console.log(JSON.stringify({
command: webServer.command,
reuseExistingServer: webServer.reuseExistingServer,
timeout: webServer.timeout,
nodeValue: webServer.env.WAGGLE_E2E_NODE_EXEC,
pathValue: webServer.env[pathKey],
secretValue: webServer.env.WAGGLE_PROBE_AMBIENT_API_KEY,
}));
})();
`;
const adversarialNodePaths = process.platform === 'win32'
? [
process.execPath,
'C:\\Program Files\\Node %PATH% & safe\\node.exe',
'C:\\Node (QA) !bang!\\node.exe',
]
: [
process.execPath,
'/opt/Node $HOME `touch nope` & safe/node',
'/opt/Node (QA) !bang!/node',
];
for (const nodePath of adversarialNodePaths) {
const result = spawnSync(
process.execPath,
[tsxCli, '--eval', probeSource],
{
cwd: ROOT,
encoding: 'utf-8',
env: {
...process.env,
WAGGLE_E2E_SKIP_LITELLM: '1',
WAGGLE_E2E_REUSE_EXISTING_SERVER: '0',
WAGGLE_PROBE_NODE_EXEC: nodePath,
WAGGLE_PROBE_AMBIENT_API_KEY: 'must-not-enter-playwright-config',
},
timeout: 30_000,
windowsHide: true,
},
);
expect(result.status, result.stderr || result.stdout).toBe(0);
const output = result.stdout.trim().split(/\r?\n/).at(-1);
const webServer = JSON.parse(output ?? '{}') as {
command?: string;
reuseExistingServer?: boolean;
timeout?: number;
nodeValue?: string;
pathValue?: string;
secretValue?: string;
};
const nodeReference = process.platform === 'win32'
? '"%WAGGLE_E2E_NODE_EXEC%"'
: '"$WAGGLE_E2E_NODE_EXEC"';
expect(webServer.command).toBe(
`npm run build:all && ${nodeReference} `
+ 'node_modules/tsx/dist/cli.mjs packages/server/src/local/start.ts --skip-litellm',
);
expect(webServer.command).not.toContain(nodePath);
expect(webServer.reuseExistingServer).toBe(false);
expect(webServer.timeout).toBe(600_000);
expect(webServer.nodeValue).toBe(nodePath);
expect(webServer.pathValue).toBeUndefined();
expect(webServer.secretValue).toBeUndefined();
}
});
it('visual test spec exists with 14 test cases (7 views x 2 themes)', () => {
const spec = path.join(ROOT, 'tests', 'visual', 'views.spec.ts');
expect(fs.existsSync(spec)).toBe(true);
const content = fs.readFileSync(spec, 'utf-8');
expect(content).toContain('Dark Mode');
expect(content).toContain('Light Mode');
// 7 views defined
expect(content).toContain('chat');
expect(content).toContain('memory');
expect(content).toContain('events');
expect(content).toContain('capabilities');
expect(content).toContain('cockpit');
expect(content).toContain('mission-control');
expect(content).toContain('settings');
});
});