Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/workflows/release-windows-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ on:
- 'scripts/npm-spawn.mjs'
- 'scripts/generate-third-party-notices.mjs'
- 'scripts/generate-windows-cargo-notices.mjs'
# The packaged worker and its Windows boundary driver are built from
# these sources, so changes here must reach the packaged lifecycle gate.
- 'apps/desktop/scripts/copy-runtime-filesystem-worker.mjs'
- 'packages/runtime/scripts/build-filesystem-worker.mjs'
- 'packages/runtime/src/filesystem-worker/**'
- 'packages/runtime/src/sandbox/**'
- 'packages/runtime/src/path-containment.ts'
- 'packages/runtime/src/sandbox-boundary-path.ts'
- 'packages/core/src/permission-profile.ts'
- 'packages/core/src/permission-profile-compiler.ts'
- 'experiments/windows-sandbox/launcher/**'
- 'experiments/windows-sandbox/*.ps1'
- '.gitattributes'
Expand Down
29 changes: 29 additions & 0 deletions scripts/ci-test-plan.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,35 @@ test('the packaged Windows gate owns Runtime Host candidate election changes', (
assert.match(workflow, /'packages\/runtime-host\/src\/client\/launcher\.ts'/u);
});

test('the packaged Windows gate triggers on packaged sandbox inputs', () => {
const workflow = readWorkflow('release-windows-check.yml');

for (const path of [
'apps/desktop/scripts/copy-runtime-filesystem-worker.mjs',
'packages/runtime/scripts/build-filesystem-worker.mjs',
'packages/runtime/src/filesystem-worker/**',
'packages/runtime/src/sandbox/**',
'packages/runtime/src/path-containment.ts',
'packages/runtime/src/sandbox-boundary-path.ts',
'packages/core/src/permission-profile.ts',
'packages/core/src/permission-profile-compiler.ts',
]) {
assert.ok(workflow.includes(` - '${path}'`), path);
}
});

test('pull-request and release lanes share the packaged sandbox lifecycle verifier', () => {
for (const name of ['release-windows-check.yml', 'release.yml']) {
assert.match(readWorkflow(name), /npm run verify:windows-x64/u, name);
}

const verifier = readFileSync(new URL('verify-windows-x64.mjs', import.meta.url), 'utf8');
assert.match(
verifier,
/await verifyPackagedWindowsSandboxLifecycle\(sandboxExecutable, \{ run \}\)/u,
);
});

test('specialized platform workflows stay reachable without pull requests', () => {
const cli = readWorkflow('cli-package-validation.yml');
const baseline = readWorkflow('windows-baseline.yml');
Expand Down
36 changes: 36 additions & 0 deletions scripts/verify-windows-harness.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
waitForUsableRenderer,
} from './verify-packaged-app.mjs';
import { waitForInstalledProductVersion } from './verify-windows-autoupdate.mjs';
import { verifyPackagedWindowsSandboxLifecycle } from './verify-windows-x64.mjs';
import {
deleteUninstallRegistrationForInstall,
readUninstallDisplayVersionsForInstall,
Expand Down Expand Up @@ -82,6 +83,41 @@ it('scopes rollback registration reads and deletion to the fixture uninstaller',
assert.match(calls[1].args.at(-1), /Remove-Item -LiteralPath \$_\.Path/u);
});

it('runs packaged sandbox lifecycle evidence against the exact shipped broker', async () => {
const calls = [];
const sandboxExecutable = 'C:\\release\\resources\\windows-sandbox\\maka-windows-sandbox.exe';

await verifyPackagedWindowsSandboxLifecycle(sandboxExecutable, {
run: async (command, args) => {
calls.push({ command, args });
return { stdout: '', stderr: '' };
},
});

assert.deepEqual(
calls.map(({ command, args }) => ({
command,
script: args[2].replaceAll('\\', '/').split('/').at(-1),
launcherFlag: args[3],
launcher: args[4],
})),
[
{
command: 'pwsh',
script: 'appcontainer-smoke.ps1',
launcherFlag: '-LauncherPath',
launcher: sandboxExecutable,
},
{
command: 'pwsh',
script: 'acl-recovery-smoke.ps1',
launcherFlag: '-LauncherPath',
launcher: sandboxExecutable,
},
],
);
});

it('uses the product SemVer contract throughout Windows release verification', () => {
assert.equal(installerVersion('Maka-1.2.3-beta.2-win-x64.exe'), '1.2.3-beta.2');
assert.equal(bumpedAutoupdateVersion('1.2.3-beta.2'), '1.2.3');
Expand Down
18 changes: 18 additions & 0 deletions scripts/verify-windows-x64.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,21 @@ export function assertWindowsProductVersion(productVersion, expectedVersion) {
}
}

export async function verifyPackagedWindowsSandboxLifecycle(
sandboxExecutable,
{ run = runCommandFromRepo } = {},
) {
for (const script of ['appcontainer-smoke.ps1', 'acl-recovery-smoke.ps1']) {
await run('pwsh', [
'-NoProfile',
'-File',
join(repoRoot, 'experiments', 'windows-sandbox', script),
'-LauncherPath',
sandboxExecutable,
]);
}
}

// The Windows build is unsigned, so the only architecture evidence in the
// artifact is the PE header of the executable itself.
export async function readPeMachine(path) {
Expand Down Expand Up @@ -204,6 +219,9 @@ export async function verifyPackagedWindowsApp(
sandboxExecutable,
]);

step('verifying packaged sandbox lifecycle recovery');
await verifyPackagedWindowsSandboxLifecycle(sandboxExecutable, { run });

step('running real filesystem-worker operations through the packaged app');
// The evidence executes the packaged artifacts themselves: the packaged
// broker, the packaged Electron executable as the worker runtime and the
Expand Down