diff --git a/.github/workflows/ssh-relay-runtime-artifacts.yml b/.github/workflows/ssh-relay-runtime-artifacts.yml
index f58cadb26c0..52e7101ccc0 100644
--- a/.github/workflows/ssh-relay-runtime-artifacts.yml
+++ b/.github/workflows/ssh-relay-runtime-artifacts.yml
@@ -168,6 +168,9 @@ jobs:
node --check config/scripts/ssh-relay-runtime-manifest-signing-handoff.test.mjs
node --check config/scripts/ssh-relay-runtime-manifest-seed-signing.mjs
node --check config/scripts/ssh-relay-runtime-manifest-seed-signing.test.mjs
+ node --check config/scripts/ssh-relay-runtime-manifest-artifact-collection.mjs
+ node --check config/scripts/ssh-relay-runtime-manifest-aggregate-command.mjs
+ node --check config/scripts/ssh-relay-runtime-manifest-aggregate-command.test.mjs
node --check config/scripts/ssh-relay-runtime-manifest-aggregate.mjs
node --check config/scripts/ssh-relay-runtime-manifest-aggregate.test.mjs
node --check config/scripts/ssh-relay-runtime-manifest-tuple.mjs
@@ -215,6 +218,7 @@ jobs:
config/scripts/ssh-relay-runtime-manifest-assembly.test.mjs \
config/scripts/ssh-relay-runtime-manifest-signing-handoff.test.mjs \
config/scripts/ssh-relay-runtime-manifest-seed-signing.test.mjs \
+ config/scripts/ssh-relay-runtime-manifest-aggregate-command.test.mjs \
config/scripts/ssh-relay-runtime-manifest-aggregate.test.mjs \
config/scripts/ssh-relay-runtime-manifest-tuple.test.mjs \
config/scripts/ssh-relay-runtime-post-sign-metadata.test.mjs \
@@ -585,6 +589,12 @@ jobs:
if ($LASTEXITCODE -ne 0) { throw 'runtime manifest seed signing syntax check failed' }
node --check config/scripts/ssh-relay-runtime-manifest-seed-signing.test.mjs
if ($LASTEXITCODE -ne 0) { throw 'runtime manifest seed signing test syntax check failed' }
+ node --check config/scripts/ssh-relay-runtime-manifest-artifact-collection.mjs
+ if ($LASTEXITCODE -ne 0) { throw 'runtime manifest artifact collection syntax check failed' }
+ node --check config/scripts/ssh-relay-runtime-manifest-aggregate-command.mjs
+ if ($LASTEXITCODE -ne 0) { throw 'runtime manifest aggregate command syntax check failed' }
+ node --check config/scripts/ssh-relay-runtime-manifest-aggregate-command.test.mjs
+ if ($LASTEXITCODE -ne 0) { throw 'runtime manifest aggregate command test syntax check failed' }
node --check config/scripts/ssh-relay-runtime-manifest-aggregate.mjs
if ($LASTEXITCODE -ne 0) { throw 'runtime manifest aggregate syntax check failed' }
node --check config/scripts/ssh-relay-runtime-manifest-aggregate.test.mjs
@@ -650,6 +660,7 @@ jobs:
config/scripts/ssh-relay-runtime-manifest-assembly.test.mjs `
config/scripts/ssh-relay-runtime-manifest-signing-handoff.test.mjs `
config/scripts/ssh-relay-runtime-manifest-seed-signing.test.mjs `
+ config/scripts/ssh-relay-runtime-manifest-aggregate-command.test.mjs `
config/scripts/ssh-relay-runtime-manifest-aggregate.test.mjs `
config/scripts/ssh-relay-runtime-manifest-tuple.test.mjs `
config/scripts/ssh-relay-runtime-post-sign-metadata.test.mjs `
diff --git a/config/scripts/ssh-relay-runtime-manifest-aggregate-command.mjs b/config/scripts/ssh-relay-runtime-manifest-aggregate-command.mjs
new file mode 100644
index 00000000000..4bc3f018908
--- /dev/null
+++ b/config/scripts/ssh-relay-runtime-manifest-aggregate-command.mjs
@@ -0,0 +1,401 @@
+import { createHash } from 'node:crypto'
+import { lstat, mkdir, readFile, realpath, rm, writeFile } from 'node:fs/promises'
+import { basename, dirname, join, resolve } from 'node:path'
+import { pathToFileURL } from 'node:url'
+
+import { collectSshRelayRuntimeManifestArtifacts } from './ssh-relay-runtime-manifest-artifact-collection.mjs'
+import {
+ finalizeSshRelayRuntimeManifestAggregate,
+ prepareSshRelayRuntimeManifestAggregate
+} from './ssh-relay-runtime-manifest-aggregate.mjs'
+import {
+ decodeSshRelayRuntimeManifestSigningRequestArtifact,
+ encodeSshRelayRuntimeManifestSigningRequestArtifact
+} from './ssh-relay-runtime-manifest-seed-signing.mjs'
+import { sshRelayRuntimeManifestKeyId } from './ssh-relay-runtime-manifest-signing-handoff.mjs'
+
+const MAX_JSON_BYTES = 48 * 1024 * 1024
+const SOURCE_SHA = /^[0-9a-f]{40}$/u
+const TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/u
+const BASE64 = /^[A-Za-z0-9+/]+={0,2}$/u
+const DIGEST = /^sha256:[0-9a-f]{64}$/u
+const PREPARED_FIELDS = [
+ 'acceptedKeysSha256',
+ 'createdAt',
+ 'inputTuples',
+ 'inputTuplesSha256',
+ 'relayProtocolVersion',
+ 'releaseTag',
+ 'schemaVersion',
+ 'signingRequest',
+ 'sourceSha',
+ 'unsignedManifest'
+]
+
+function assertObject(value, label) {
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
+ throw new Error(`SSH relay runtime manifest aggregate command ${label} must be an object`)
+ }
+}
+
+function assertExactFields(value, fields, label) {
+ assertObject(value, label)
+ const actual = Object.keys(value).sort()
+ const expected = [...fields].sort()
+ if (JSON.stringify(actual) !== JSON.stringify(expected)) {
+ throw new Error(`SSH relay runtime manifest aggregate command ${label} has invalid fields`)
+ }
+}
+
+function sha256(bytes) {
+ return `sha256:${createHash('sha256').update(bytes).digest('hex')}`
+}
+
+function canonicalJson(value) {
+ return Buffer.from(`${JSON.stringify(value)}\n`, 'utf8')
+}
+
+function parseReleaseTag(tag) {
+ for (const [pattern, channel] of [
+ [/^v(\d+\.\d+\.\d+)$/u, 'stable'],
+ [/^v(\d+\.\d+\.\d+-rc\.\d+)$/u, 'rc'],
+ [/^v(\d+\.\d+\.\d+-rc\.\d+\.perf)$/u, 'perf']
+ ]) {
+ const match = pattern.exec(tag)
+ if (match) {
+ return { tag, version: match[1], channel }
+ }
+ }
+ throw new Error('SSH relay runtime manifest aggregate command release tag is invalid')
+}
+
+function commandIdentity(input) {
+ if (!SOURCE_SHA.test(input.sourceSha ?? '')) {
+ throw new Error('SSH relay runtime manifest aggregate command source SHA is invalid')
+ }
+ const release = parseReleaseTag(input.releaseTag)
+ if (
+ typeof input.createdAt !== 'string' ||
+ !TIMESTAMP.test(input.createdAt) ||
+ new Date(input.createdAt).toISOString() !== input.createdAt
+ ) {
+ throw new Error('SSH relay runtime manifest aggregate command timestamp is invalid')
+ }
+ if (!Number.isSafeInteger(input.relayProtocolVersion) || input.relayProtocolVersion <= 0) {
+ throw new Error('SSH relay runtime manifest aggregate command protocol version is invalid')
+ }
+ return {
+ sourceSha: input.sourceSha,
+ releaseTag: input.releaseTag,
+ createdAt: input.createdAt,
+ relayProtocolVersion: input.relayProtocolVersion,
+ build: { ...release, relayProtocolVersion: input.relayProtocolVersion }
+ }
+}
+
+async function readBoundedJson(path, label) {
+ const before = await lstat(path, { bigint: true })
+ if (
+ !before.isFile() ||
+ before.isSymbolicLink() ||
+ before.size <= 0n ||
+ before.size > BigInt(MAX_JSON_BYTES)
+ ) {
+ throw new Error(
+ `SSH relay runtime manifest aggregate command ${label} must be bounded regular JSON`
+ )
+ }
+ try {
+ const bytes = await readFile(path)
+ const after = await lstat(path, { bigint: true })
+ if (
+ before.dev !== after.dev ||
+ before.ino !== after.ino ||
+ before.size !== after.size ||
+ before.mtimeNs !== after.mtimeNs ||
+ before.ctimeNs !== after.ctimeNs
+ ) {
+ throw new Error('file changed while reading')
+ }
+ return JSON.parse(bytes.toString('utf8'))
+ } catch (error) {
+ throw new Error(
+ `SSH relay runtime manifest aggregate command ${label} is invalid JSON: ${error.message}`
+ )
+ }
+}
+
+function decodeCanonicalBase64(value, label, expectedSize) {
+ if (typeof value !== 'string' || !BASE64.test(value)) {
+ throw new Error(`SSH relay runtime manifest aggregate command ${label} is not canonical base64`)
+ }
+ const bytes = Buffer.from(value, 'base64')
+ if (bytes.length !== expectedSize || bytes.toString('base64') !== value) {
+ throw new Error(
+ `SSH relay runtime manifest aggregate command ${label} must contain ${expectedSize} bytes`
+ )
+ }
+ return bytes
+}
+
+async function readAcceptedKeys(path) {
+ const document = await readBoundedJson(resolve(path), 'accepted keys')
+ assertExactFields(document, ['keys', 'schemaVersion'], 'accepted keys')
+ if (
+ document.schemaVersion !== 1 ||
+ !Array.isArray(document.keys) ||
+ document.keys.length === 0 ||
+ document.keys.length > 4
+ ) {
+ throw new Error('SSH relay runtime manifest aggregate command accepted keys are invalid')
+ }
+ const seen = new Set()
+ const artifactKeys = document.keys
+ .map((key, index) => {
+ assertExactFields(key, ['keyId', 'publicKeyBase64'], `accepted key ${index}`)
+ const publicKey = decodeCanonicalBase64(key.publicKeyBase64, 'accepted public key', 32)
+ const keyId = sshRelayRuntimeManifestKeyId(publicKey)
+ if (!DIGEST.test(key.keyId ?? '') || key.keyId !== keyId || seen.has(keyId)) {
+ throw new Error(
+ 'SSH relay runtime manifest aggregate command accepted key identity is invalid'
+ )
+ }
+ seen.add(keyId)
+ return { keyId, publicKeyBase64: key.publicKeyBase64, publicKey }
+ })
+ .sort((left, right) => (left.keyId < right.keyId ? -1 : left.keyId > right.keyId ? 1 : 0))
+ const serialized = artifactKeys.map(({ keyId, publicKeyBase64 }) => ({ keyId, publicKeyBase64 }))
+ return {
+ acceptedKeys: artifactKeys.map(({ keyId, publicKey }) => ({ keyId, publicKey })),
+ sha256: sha256(canonicalJson({ schemaVersion: 1, keys: serialized }))
+ }
+}
+
+async function exclusiveOutputDirectory(outputDirectory) {
+ const absolute = resolve(outputDirectory)
+ const parent = resolve(await realpath(dirname(absolute)))
+ const parentMetadata = await lstat(parent)
+ if (!parentMetadata.isDirectory() || parentMetadata.isSymbolicLink()) {
+ throw new Error('SSH relay runtime manifest aggregate command output parent must be real')
+ }
+ const output = resolve(parent, basename(absolute))
+ try {
+ await lstat(output)
+ } catch (error) {
+ if (error.code === 'ENOENT') {
+ return output
+ }
+ throw error
+ }
+ throw new Error(
+ 'SSH relay runtime manifest aggregate command requires an exclusive output directory'
+ )
+}
+
+function assertReceiptBindings(bindings, prepared) {
+ const tuples = new Map(prepared.unsignedManifest.tuples.map((tuple) => [tuple.tupleId, tuple]))
+ for (const binding of bindings) {
+ if (tuples.get(binding.tupleId)?.contentId !== binding.contentId) {
+ throw new Error(
+ `SSH relay runtime manifest aggregate command receipt content drifted: ${binding.tupleId}`
+ )
+ }
+ }
+}
+
+function preparedArtifact(identity, acceptedKeysSha256, prepared) {
+ return {
+ schemaVersion: 1,
+ sourceSha: identity.sourceSha,
+ releaseTag: identity.releaseTag,
+ createdAt: identity.createdAt,
+ relayProtocolVersion: identity.relayProtocolVersion,
+ acceptedKeysSha256,
+ inputTuples: prepared.inputTuples,
+ inputTuplesSha256: prepared.inputTuplesSha256,
+ unsignedManifest: prepared.unsignedManifest,
+ signingRequest: encodeSshRelayRuntimeManifestSigningRequestArtifact(prepared.signingRequest)
+ }
+}
+
+async function collectAndPrepare(input, output, identity, signal) {
+ const stagingDirectory = join(output, 'aggregate-input')
+ await mkdir(stagingDirectory)
+ const bindings = await collectSshRelayRuntimeManifestArtifacts({
+ artifactsDirectory: input.artifactsDirectory,
+ stagingDirectory,
+ signal
+ })
+ const prepared = await prepareSshRelayRuntimeManifestAggregate({
+ inputDirectory: stagingDirectory,
+ build: identity.build,
+ createdAt: identity.createdAt,
+ tupleInputs: bindings.map(({ aggregateInput }) => aggregateInput),
+ signal
+ })
+ assertReceiptBindings(bindings, prepared)
+ return prepared
+}
+
+export async function prepareSshRelayRuntimeManifestAggregateCommand(input) {
+ const identity = commandIdentity(input)
+ // Why: public-key policy must be valid before canonical bytes can leave this boundary.
+ const keys = await readAcceptedKeys(input.acceptedKeysPath)
+ const output = await exclusiveOutputDirectory(input.outputDirectory)
+ let created = false
+ try {
+ await mkdir(output, { mode: 0o700 })
+ created = true
+ const prepared = await collectAndPrepare(input, output, identity, input.signal)
+ const artifact = preparedArtifact(identity, keys.sha256, prepared)
+ await writeFile(join(output, 'prepared-aggregate.json'), canonicalJson(artifact), {
+ flag: 'wx',
+ mode: 0o600
+ })
+ await writeFile(join(output, 'signing-request.json'), canonicalJson(artifact.signingRequest), {
+ flag: 'wx',
+ mode: 0o600
+ })
+ await rm(join(output, 'aggregate-input'), { recursive: true, force: true })
+ return prepared
+ } catch (error) {
+ if (created) {
+ await rm(output, { recursive: true, force: true })
+ }
+ throw error
+ }
+}
+
+function normalizePreparedArtifact(value) {
+ assertExactFields(value, PREPARED_FIELDS, 'prepared aggregate')
+ if (value.schemaVersion !== 1 || !DIGEST.test(value.acceptedKeysSha256 ?? '')) {
+ throw new Error('SSH relay runtime manifest aggregate command prepared aggregate is invalid')
+ }
+ decodeSshRelayRuntimeManifestSigningRequestArtifact(value.signingRequest)
+ return value
+}
+
+function sameJson(left, right) {
+ return JSON.stringify(left) === JSON.stringify(right)
+}
+
+export async function finalizeSshRelayRuntimeManifestAggregateCommand(input) {
+ const identity = commandIdentity(input)
+ const keys = await readAcceptedKeys(input.acceptedKeysPath)
+ const prior = normalizePreparedArtifact(
+ await readBoundedJson(
+ join(resolve(input.preparedDirectory), 'prepared-aggregate.json'),
+ 'prepared aggregate'
+ )
+ )
+ const signingResult = await readBoundedJson(resolve(input.signingResultPath), 'signing result')
+ assertExactFields(signingResult, ['keyId', 'signature'], 'signing result')
+ const output = await exclusiveOutputDirectory(input.outputDirectory)
+ let created = false
+ try {
+ await mkdir(output, { mode: 0o700 })
+ created = true
+ const prepared = await collectAndPrepare(input, output, identity, input.signal)
+ const current = preparedArtifact(identity, keys.sha256, prepared)
+ if (!sameJson(prior, current)) {
+ throw new Error('SSH relay runtime manifest aggregate command prepared receipt drifted')
+ }
+ const finalized = finalizeSshRelayRuntimeManifestAggregate({
+ prepared,
+ signingResults: [signingResult],
+ acceptedKeys: keys.acceptedKeys
+ })
+ const assets = join(output, 'assets')
+ const evidence = join(output, 'evidence')
+ await Promise.all([mkdir(assets), mkdir(evidence)])
+ await writeFile(join(assets, finalized.manifestAsset.name), finalized.bytes, {
+ flag: 'wx',
+ mode: 0o600
+ })
+ await writeFile(
+ join(evidence, 'manifest-aggregate.json'),
+ canonicalJson({
+ schemaVersion: 1,
+ sourceSha: identity.sourceSha,
+ releaseTag: identity.releaseTag,
+ acceptedKeysSha256: keys.sha256,
+ inputTuplesSha256: finalized.inputTuplesSha256,
+ manifestAsset: finalized.manifestAsset
+ }),
+ { flag: 'wx', mode: 0o600 }
+ )
+ await rm(join(output, 'aggregate-input'), { recursive: true, force: true })
+ return finalized
+ } catch (error) {
+ if (created) {
+ await rm(output, { recursive: true, force: true })
+ }
+ throw error
+ }
+}
+
+export function parseSshRelayRuntimeManifestAggregateCommandArguments(argv) {
+ const command = argv[0]
+ if (command !== 'prepare' && command !== 'finalize') {
+ throw new Error('SSH relay runtime manifest aggregate command requires prepare or finalize')
+ }
+ const fields = new Map([
+ ['--artifacts-directory', 'artifactsDirectory'],
+ ['--accepted-keys', 'acceptedKeysPath'],
+ ['--output-directory', 'outputDirectory'],
+ ['--source-sha', 'sourceSha'],
+ ['--release-tag', 'releaseTag'],
+ ['--created-at', 'createdAt'],
+ ['--relay-protocol-version', 'relayProtocolVersion'],
+ ['--prepared-directory', 'preparedDirectory'],
+ ['--signing-result', 'signingResultPath']
+ ])
+ const result = { command }
+ for (let index = 1; index < argv.length; index += 2) {
+ const field = fields.get(argv[index])
+ const value = argv[index + 1]
+ if (!field || !value || value.startsWith('--') || result[field]) {
+ throw new Error(
+ `Invalid SSH relay runtime manifest aggregate command argument: ${argv[index]}`
+ )
+ }
+ result[field] = field === 'relayProtocolVersion' ? Number(value) : value
+ }
+ const required = [
+ 'artifactsDirectory',
+ 'acceptedKeysPath',
+ 'outputDirectory',
+ 'sourceSha',
+ 'releaseTag',
+ 'createdAt',
+ 'relayProtocolVersion'
+ ]
+ if (command === 'finalize') {
+ required.push('preparedDirectory', 'signingResultPath')
+ }
+ for (const field of required) {
+ if (!result[field]) {
+ throw new Error(`Missing SSH relay runtime manifest aggregate command argument: ${field}`)
+ }
+ }
+ return result
+}
+
+async function main() {
+ const options = parseSshRelayRuntimeManifestAggregateCommandArguments(process.argv.slice(2))
+ const operation =
+ options.command === 'prepare'
+ ? prepareSshRelayRuntimeManifestAggregateCommand
+ : finalizeSshRelayRuntimeManifestAggregateCommand
+ const result = await operation(options)
+ process.stdout.write(`${JSON.stringify({ inputTuplesSha256: result.inputTuplesSha256 })}\n`)
+}
+
+if (process.argv[1] && pathToFileURL(resolve(process.argv[1])).href === import.meta.url) {
+ main().catch((error) => {
+ process.stderr.write(
+ `SSH relay runtime manifest aggregate command failed: ${error.stack ?? error}\n`
+ )
+ process.exitCode = 1
+ })
+}
diff --git a/config/scripts/ssh-relay-runtime-manifest-aggregate-command.test.mjs b/config/scripts/ssh-relay-runtime-manifest-aggregate-command.test.mjs
new file mode 100644
index 00000000000..16e9fb78f7c
--- /dev/null
+++ b/config/scripts/ssh-relay-runtime-manifest-aggregate-command.test.mjs
@@ -0,0 +1,420 @@
+import { createHash } from 'node:crypto'
+import { lstat, mkdir, mkdtemp, readFile, rm, symlink, writeFile } from 'node:fs/promises'
+import { tmpdir } from 'node:os'
+import { join } from 'node:path'
+
+import nacl from 'tweetnacl'
+import { afterEach, describe, expect, it } from 'vitest'
+
+import { createSshRelayArtifactTestManifest } from '../../src/main/ssh/ssh-relay-artifact-test-manifest.ts'
+import { verifySshRelayArtifactManifest } from '../../src/main/ssh/ssh-relay-manifest-signature.ts'
+import { sshRelayRuntimeCompatibility } from './ssh-relay-runtime-compatibility.mjs'
+import { computeSshRelayRuntimeContentId } from './ssh-relay-runtime-identity.mjs'
+import {
+ finalizeSshRelayRuntimeManifestAggregateCommand,
+ parseSshRelayRuntimeManifestAggregateCommandArguments,
+ prepareSshRelayRuntimeManifestAggregateCommand
+} from './ssh-relay-runtime-manifest-aggregate-command.mjs'
+import {
+ encodeSshRelayRuntimeManifestSigningRequestArtifact,
+ signSshRelayRuntimeManifestRequest
+} from './ssh-relay-runtime-manifest-seed-signing.mjs'
+import { sshRelayRuntimeManifestKeyId } from './ssh-relay-runtime-manifest-signing-handoff.mjs'
+
+const temporaryDirectories = []
+const keyPair = nacl.sign.keyPair.fromSeed(Uint8Array.from({ length: 32 }, (_, index) => index))
+const TUPLES = [
+ 'linux-x64-glibc',
+ 'linux-arm64-glibc',
+ 'darwin-x64',
+ 'darwin-arm64',
+ 'win32-x64',
+ 'win32-arm64'
+]
+
+function digest(bytes) {
+ return `sha256:${createHash('sha256').update(bytes).digest('hex')}`
+}
+
+function fileReference(name, bytes) {
+ return { name, size: bytes.length, sha256: digest(bytes) }
+}
+
+function watcherPackage(tupleId) {
+ return tupleId.startsWith('linux-')
+ ? `@parcel/watcher-linux-${tupleId.split('-')[1]}-glibc`
+ : `@parcel/watcher-${tupleId}`
+}
+
+function nativeEntry(path, role, marker) {
+ return {
+ path,
+ type: 'file',
+ role,
+ size: marker.length,
+ mode: 0o755,
+ sha256: digest(marker)
+ }
+}
+
+function tupleFor(tupleId) {
+ const tuple = structuredClone(createSshRelayArtifactTestManifest().tuples[0])
+ const [os, architecture] = tupleId.split('-')
+ tuple.tupleId = tupleId
+ tuple.os = os
+ tuple.architecture = architecture
+ tuple.compatibility = structuredClone(sshRelayRuntimeCompatibility[tupleId])
+ const packageName = watcherPackage(tupleId)
+ tuple.entries = tuple.entries.map((entry) => {
+ const next = structuredClone(entry)
+ next.path = next.path.replace('@parcel/watcher-linux-x64-glibc', packageName)
+ if (next.role === 'node') {
+ next.path = os === 'win32' ? 'bin/node.exe' : 'bin/node'
+ }
+ return next
+ })
+ if (os === 'darwin') {
+ tuple.entries.push(
+ nativeEntry(
+ 'node_modules/node-pty/build/Release/spawn-helper',
+ 'native-runtime',
+ `${tupleId}:spawn-helper`
+ )
+ )
+ }
+ if (os === 'win32') {
+ tuple.entries = tuple.entries.filter((entry) => entry.role !== 'node-pty-native')
+ tuple.entries.push(
+ { path: 'node_modules/node-pty/build/Release/conpty', type: 'directory', mode: 0o755 },
+ nativeEntry(
+ 'node_modules/node-pty/build/Release/conpty.node',
+ 'node-pty-native',
+ `${tupleId}:conpty-node`
+ ),
+ nativeEntry(
+ 'node_modules/node-pty/build/Release/conpty_console_list.node',
+ 'node-pty-native',
+ `${tupleId}:console-list`
+ ),
+ nativeEntry(
+ 'node_modules/node-pty/build/Release/conpty/OpenConsole.exe',
+ 'native-runtime',
+ `${tupleId}:open-console`
+ ),
+ nativeEntry(
+ 'node_modules/node-pty/build/Release/conpty/conpty.dll',
+ 'native-runtime',
+ `${tupleId}:conpty-dll`
+ )
+ )
+ }
+ const nativeRoles = new Set([
+ 'node',
+ 'node-pty-native',
+ 'parcel-watcher-native',
+ 'native-runtime'
+ ])
+ tuple.nativeVerification = {
+ policy:
+ os === 'linux'
+ ? 'linux-hash-only-v1'
+ : os === 'darwin'
+ ? 'apple-developer-id-v1'
+ : 'signpath-authenticode-v1',
+ tool: { name: 'fixture-verifier', version: '1.0.0' },
+ verifiedAt: '2026-07-15T00:00:00.000Z',
+ files: tuple.entries
+ .filter((entry) => entry.type === 'file' && nativeRoles.has(entry.role))
+ .map(({ path, sha256 }) => ({ path, sha256 }))
+ }
+ const files = tuple.entries.filter((entry) => entry.type === 'file')
+ tuple.archive.fileCount = files.length
+ tuple.archive.expandedSize = files.reduce((total, entry) => total + entry.size, 0)
+ tuple.metadataAssets.sbom.name = `orca-ssh-relay-runtime-${tupleId}.spdx.json`
+ tuple.metadataAssets.provenance.name = `orca-ssh-relay-runtime-${tupleId}.provenance.json`
+ tuple.contentId = computeSshRelayRuntimeContentId(tuple)
+ const extension = os === 'win32' ? 'zip' : 'tar.xz'
+ tuple.archive.name = `orca-ssh-relay-runtime-v1-${tupleId}-${tuple.contentId.slice(7)}.${extension}`
+ return tuple
+}
+
+async function writeTupleArtifact(root, tupleId) {
+ const tuple = tupleFor(tupleId)
+ const archiveBytes = Buffer.from(`${tupleId}:archive`)
+ const sbomBytes = Buffer.from(`${JSON.stringify({ spdxVersion: 'SPDX-2.3', tupleId })}\n`)
+ const provenanceBytes = Buffer.from(`${JSON.stringify({ _type: 'in-toto', tupleId })}\n`)
+ tuple.archive.size = archiveBytes.length
+ tuple.archive.sha256 = digest(archiveBytes)
+ tuple.metadataAssets.sbom = fileReference(tuple.metadataAssets.sbom.name, sbomBytes)
+ tuple.metadataAssets.provenance = fileReference(
+ tuple.metadataAssets.provenance.name,
+ provenanceBytes
+ )
+ const descriptorBytes = Buffer.from(
+ `${JSON.stringify({ schemaVersion: 1, tuple }, null, 2)}\n`,
+ 'utf8'
+ )
+ const input = {
+ tupleId,
+ descriptor: fileReference(
+ `orca-ssh-relay-runtime-${tupleId}.manifest-tuple.json`,
+ descriptorBytes
+ ),
+ archive: fileReference(tuple.archive.name, archiveBytes),
+ sbom: { ...tuple.metadataAssets.sbom },
+ provenance: { ...tuple.metadataAssets.provenance }
+ }
+ const artifactName = tupleId.startsWith('linux-')
+ ? `ssh-relay-runtime-${tupleId}`
+ : `ssh-relay-runtime-signed-${tupleId}`
+ const artifactRoot = join(root, artifactName)
+ const assetsRoot = tupleId.startsWith('linux-') ? artifactRoot : join(artifactRoot, 'assets')
+ const evidenceRoot = tupleId.startsWith('linux-') ? artifactRoot : join(artifactRoot, 'evidence')
+ await mkdir(assetsRoot, { recursive: true })
+ await mkdir(evidenceRoot, { recursive: true })
+ await Promise.all([
+ writeFile(join(assetsRoot, input.descriptor.name), descriptorBytes),
+ writeFile(join(assetsRoot, input.archive.name), archiveBytes),
+ writeFile(join(assetsRoot, input.sbom.name), sbomBytes),
+ writeFile(join(assetsRoot, input.provenance.name), provenanceBytes)
+ ])
+ const receipt = tupleId.startsWith('linux-')
+ ? { tupleId, contentId: tuple.contentId, verification: {}, aggregateInput: input }
+ : {
+ tupleId,
+ sourceContentId: tuple.contentId,
+ finalContentId: tuple.contentId,
+ returnedFiles: [],
+ nativeVerification: tuple.nativeVerification,
+ smoke: {},
+ metadata: {},
+ aggregateInput: input
+ }
+ const suffix = tupleId.startsWith('linux-') ? 'linux-finalization' : 'finalization'
+ await writeFile(join(evidenceRoot, `${tupleId}.${suffix}.json`), `${JSON.stringify(receipt)}\n`)
+ return { artifactRoot, assetsRoot, evidenceRoot, input, tuple }
+}
+
+async function fixture() {
+ const root = await mkdtemp(join(tmpdir(), 'orca-manifest-command-'))
+ temporaryDirectories.push(root)
+ const artifactsDirectory = join(root, 'artifacts')
+ await mkdir(artifactsDirectory)
+ const tuples = []
+ for (const tupleId of TUPLES) {
+ tuples.push(await writeTupleArtifact(artifactsDirectory, tupleId))
+ }
+ const acceptedKeysPath = join(root, 'accepted-keys.json')
+ const acceptedKeys = {
+ schemaVersion: 1,
+ keys: [
+ {
+ keyId: sshRelayRuntimeManifestKeyId(keyPair.publicKey),
+ publicKeyBase64: Buffer.from(keyPair.publicKey).toString('base64')
+ }
+ ]
+ }
+ await writeFile(acceptedKeysPath, `${JSON.stringify(acceptedKeys)}\n`)
+ return {
+ root,
+ artifactsDirectory,
+ acceptedKeysPath,
+ acceptedKeys,
+ tuples,
+ prepareOutput: join(root, 'prepared'),
+ finalOutput: join(root, 'final'),
+ sourceSha: 'a'.repeat(40),
+ releaseTag: 'v1.4.140-rc.1',
+ createdAt: '2026-07-15T01:02:03.000Z',
+ relayProtocolVersion: 1
+ }
+}
+
+function commandInput(value, outputDirectory = value.prepareOutput) {
+ return {
+ artifactsDirectory: value.artifactsDirectory,
+ acceptedKeysPath: value.acceptedKeysPath,
+ outputDirectory,
+ sourceSha: value.sourceSha,
+ releaseTag: value.releaseTag,
+ createdAt: value.createdAt,
+ relayProtocolVersion: value.relayProtocolVersion
+ }
+}
+
+afterEach(async () => {
+ await Promise.all(
+ temporaryDirectories
+ .splice(0)
+ .map((directory) => rm(directory, { recursive: true, force: true }))
+ )
+})
+
+describe('SSH relay runtime manifest aggregate filesystem command', () => {
+ it('independently recollects six receipt-bound artifacts around signature-only handoff', async () => {
+ const value = await fixture()
+ const prepared = await prepareSshRelayRuntimeManifestAggregateCommand(commandInput(value))
+ const requestArtifact = JSON.parse(
+ await readFile(join(value.prepareOutput, 'signing-request.json'), 'utf8')
+ )
+ expect(requestArtifact).toEqual(
+ encodeSshRelayRuntimeManifestSigningRequestArtifact(prepared.signingRequest)
+ )
+ const signingResult = signSshRelayRuntimeManifestRequest({
+ requestArtifact,
+ seedBase64: Buffer.from(keyPair.secretKey.subarray(0, 32)).toString('base64')
+ })
+ const signingResultPath = join(value.root, 'signing-result.json')
+ await writeFile(signingResultPath, `${JSON.stringify(signingResult)}\n`)
+ const finalized = await finalizeSshRelayRuntimeManifestAggregateCommand({
+ ...commandInput(value, value.finalOutput),
+ preparedDirectory: value.prepareOutput,
+ signingResultPath
+ })
+
+ expect(finalized.manifest.tuples.map((tuple) => tuple.tupleId)).toEqual(TUPLES.toSorted())
+ expect(
+ verifySshRelayArtifactManifest(finalized.manifest, [
+ { keyId: value.acceptedKeys.keys[0].keyId, publicKey: keyPair.publicKey }
+ ])
+ ).toEqual(finalized.manifest)
+ const finalEntries = (await lstat(value.finalOutput)).isDirectory()
+ expect(finalEntries).toBe(true)
+ await expect(lstat(join(value.finalOutput, 'aggregate-input'))).rejects.toMatchObject({
+ code: 'ENOENT'
+ })
+ })
+
+ it('rejects missing, extra, mutated, duplicate, and receipt-drifted artifact inputs', async () => {
+ const missing = await fixture()
+ await rm(missing.tuples[0].artifactRoot, { recursive: true })
+ await expect(
+ prepareSshRelayRuntimeManifestAggregateCommand(commandInput(missing))
+ ).rejects.toThrow(/missing|unexpected/i)
+
+ const extra = await fixture()
+ await mkdir(join(extra.artifactsDirectory, 'ssh-relay-runtime-extra'))
+ await expect(
+ prepareSshRelayRuntimeManifestAggregateCommand(commandInput(extra))
+ ).rejects.toThrow(/missing|unexpected/i)
+
+ const mutated = await fixture()
+ await writeFile(
+ join(mutated.tuples[1].assetsRoot, mutated.tuples[1].input.archive.name),
+ 'drift'
+ )
+ await expect(
+ prepareSshRelayRuntimeManifestAggregateCommand(commandInput(mutated))
+ ).rejects.toThrow(/size|sha-?256|changed/i)
+
+ const receiptDrift = await fixture()
+ const receiptPath = join(receiptDrift.tuples[2].evidenceRoot, `${TUPLES[2]}.finalization.json`)
+ const document = JSON.parse(await readFile(receiptPath, 'utf8'))
+ document.tupleId = TUPLES[3]
+ await writeFile(receiptPath, `${JSON.stringify(document)}\n`)
+ await expect(
+ prepareSshRelayRuntimeManifestAggregateCommand(commandInput(receiptDrift))
+ ).rejects.toThrow(/receipt|tuple/i)
+
+ const duplicate = await fixture()
+ const duplicateReceiptPath = join(
+ duplicate.tuples[1].evidenceRoot,
+ `${TUPLES[1]}.linux-finalization.json`
+ )
+ const duplicateReceipt = JSON.parse(await readFile(duplicateReceiptPath, 'utf8'))
+ duplicateReceipt.aggregateInput.archive.name = duplicate.tuples[0].input.archive.name
+ await writeFile(duplicateReceiptPath, `${JSON.stringify(duplicateReceipt)}\n`)
+ await expect(
+ prepareSshRelayRuntimeManifestAggregateCommand(commandInput(duplicate))
+ ).rejects.toThrow(/duplicate/i)
+ })
+
+ it.skipIf(process.platform === 'win32')('rejects linked finalization receipts', async () => {
+ const linked = await fixture()
+ const receipt = join(linked.tuples[0].evidenceRoot, `${TUPLES[0]}.linux-finalization.json`)
+ const realReceipt = `${receipt}.real`
+ await writeFile(realReceipt, await readFile(receipt))
+ await rm(receipt)
+ await symlink(realReceipt, receipt)
+ await expect(
+ prepareSshRelayRuntimeManifestAggregateCommand(commandInput(linked))
+ ).rejects.toThrow(/regular|symbolic|link/i)
+ })
+
+ it('validates accepted keys before exposing a request and removes partial final output', async () => {
+ const invalidKeys = await fixture()
+ invalidKeys.acceptedKeys.keys[0].publicKeyBase64 = Buffer.alloc(31).toString('base64')
+ await writeFile(invalidKeys.acceptedKeysPath, JSON.stringify(invalidKeys.acceptedKeys))
+ await expect(
+ prepareSshRelayRuntimeManifestAggregateCommand(commandInput(invalidKeys))
+ ).rejects.toThrow(/public key|32 bytes|accepted key/i)
+ await expect(lstat(invalidKeys.prepareOutput)).rejects.toMatchObject({ code: 'ENOENT' })
+
+ const invalidSignature = await fixture()
+ await prepareSshRelayRuntimeManifestAggregateCommand(commandInput(invalidSignature))
+ const signingResultPath = join(invalidSignature.root, 'signing-result.json')
+ await writeFile(
+ signingResultPath,
+ JSON.stringify({
+ keyId: invalidSignature.acceptedKeys.keys[0].keyId,
+ signature: Buffer.alloc(64).toString('base64')
+ })
+ )
+ await expect(
+ finalizeSshRelayRuntimeManifestAggregateCommand({
+ ...commandInput(invalidSignature, invalidSignature.finalOutput),
+ preparedDirectory: invalidSignature.prepareOutput,
+ signingResultPath
+ })
+ ).rejects.toThrow(/signature/i)
+ await expect(lstat(invalidSignature.finalOutput)).rejects.toMatchObject({ code: 'ENOENT' })
+ })
+
+ it('rejects prepared handoff drift, cancellation, and incomplete CLI arguments', async () => {
+ const drifted = await fixture()
+ const prepared = await prepareSshRelayRuntimeManifestAggregateCommand(commandInput(drifted))
+ const requestArtifact = encodeSshRelayRuntimeManifestSigningRequestArtifact(
+ prepared.signingRequest
+ )
+ const signingResultPath = join(drifted.root, 'signing-result.json')
+ await writeFile(
+ signingResultPath,
+ JSON.stringify({
+ ...signSshRelayRuntimeManifestRequest({
+ requestArtifact,
+ seedBase64: Buffer.from(keyPair.secretKey.subarray(0, 32)).toString('base64')
+ })
+ })
+ )
+ const preparedPath = join(drifted.prepareOutput, 'prepared-aggregate.json')
+ const preparedDocument = JSON.parse(await readFile(preparedPath, 'utf8'))
+ preparedDocument.sourceSha = 'b'.repeat(40)
+ await writeFile(preparedPath, `${JSON.stringify(preparedDocument)}\n`)
+ await expect(
+ finalizeSshRelayRuntimeManifestAggregateCommand({
+ ...commandInput(drifted, drifted.finalOutput),
+ preparedDirectory: drifted.prepareOutput,
+ signingResultPath
+ })
+ ).rejects.toThrow(/prepared|drift/i)
+ await expect(lstat(drifted.finalOutput)).rejects.toMatchObject({ code: 'ENOENT' })
+
+ const cancelled = await fixture()
+ const controller = new AbortController()
+ controller.abort(new Error('cancel aggregate collection'))
+ await expect(
+ prepareSshRelayRuntimeManifestAggregateCommand({
+ ...commandInput(cancelled),
+ signal: controller.signal
+ })
+ ).rejects.toThrow(/cancel aggregate collection/i)
+ await expect(lstat(cancelled.prepareOutput)).rejects.toMatchObject({ code: 'ENOENT' })
+
+ expect(() => parseSshRelayRuntimeManifestAggregateCommandArguments(['prepare'])).toThrow(
+ /missing/i
+ )
+ expect(() =>
+ parseSshRelayRuntimeManifestAggregateCommandArguments(['finalize', '--unknown', 'value'])
+ ).toThrow(/invalid/i)
+ })
+})
diff --git a/config/scripts/ssh-relay-runtime-manifest-artifact-collection.mjs b/config/scripts/ssh-relay-runtime-manifest-artifact-collection.mjs
new file mode 100644
index 00000000000..23e120f1da3
--- /dev/null
+++ b/config/scripts/ssh-relay-runtime-manifest-artifact-collection.mjs
@@ -0,0 +1,236 @@
+import { constants } from 'node:fs'
+import { copyFile, lstat, readFile, readdir } from 'node:fs/promises'
+import { basename, join, resolve } from 'node:path'
+
+const MAX_RECEIPT_BYTES = 32 * 1024 * 1024
+const SAFE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,239}$/u
+const DIGEST = /^sha256:[0-9a-f]{64}$/u
+const INPUT_FIELDS = ['archive', 'descriptor', 'provenance', 'sbom', 'tupleId']
+const FILE_FIELDS = ['name', 'sha256', 'size']
+
+export const SSH_RELAY_RUNTIME_MANIFEST_ARTIFACTS = Object.freeze([
+ {
+ tupleId: 'linux-x64-glibc',
+ artifactName: 'ssh-relay-runtime-linux-x64-glibc',
+ layout: 'flat'
+ },
+ {
+ tupleId: 'linux-arm64-glibc',
+ artifactName: 'ssh-relay-runtime-linux-arm64-glibc',
+ layout: 'flat'
+ },
+ {
+ tupleId: 'darwin-x64',
+ artifactName: 'ssh-relay-runtime-signed-darwin-x64',
+ layout: 'signed'
+ },
+ {
+ tupleId: 'darwin-arm64',
+ artifactName: 'ssh-relay-runtime-signed-darwin-arm64',
+ layout: 'signed'
+ },
+ {
+ tupleId: 'win32-x64',
+ artifactName: 'ssh-relay-runtime-signed-win32-x64',
+ layout: 'signed'
+ },
+ {
+ tupleId: 'win32-arm64',
+ artifactName: 'ssh-relay-runtime-signed-win32-arm64',
+ layout: 'signed'
+ }
+])
+
+function assertObject(value, label) {
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
+ throw new Error(`SSH relay runtime manifest artifact ${label} must be an object`)
+ }
+}
+
+function assertExactFields(value, fields, label) {
+ assertObject(value, label)
+ const actual = Object.keys(value).sort()
+ const expected = [...fields].sort()
+ if (JSON.stringify(actual) !== JSON.stringify(expected)) {
+ throw new Error(`SSH relay runtime manifest artifact ${label} has invalid fields`)
+ }
+}
+
+function stableState(before, after) {
+ return (
+ before.dev === after.dev &&
+ before.ino === after.ino &&
+ before.size === after.size &&
+ before.mtimeNs === after.mtimeNs &&
+ before.ctimeNs === after.ctimeNs
+ )
+}
+
+async function realDirectory(path, label) {
+ const metadata = await lstat(path)
+ if (!metadata.isDirectory() || metadata.isSymbolicLink()) {
+ throw new Error(`SSH relay runtime manifest artifact ${label} must be a real directory`)
+ }
+ return resolve(path)
+}
+
+async function readStableJson(path, label, signal) {
+ signal?.throwIfAborted()
+ const before = await lstat(path, { bigint: true })
+ if (
+ !before.isFile() ||
+ before.isSymbolicLink() ||
+ before.size <= 0n ||
+ before.size > BigInt(MAX_RECEIPT_BYTES)
+ ) {
+ throw new Error(`SSH relay runtime manifest artifact ${label} must be bounded regular JSON`)
+ }
+ const bytes = await readFile(path, { signal })
+ const after = await lstat(path, { bigint: true })
+ if (!stableState(before, after)) {
+ throw new Error(`SSH relay runtime manifest artifact ${label} changed while reading`)
+ }
+ try {
+ return JSON.parse(bytes.toString('utf8'))
+ } catch (error) {
+ throw new Error(
+ `SSH relay runtime manifest artifact ${label} is invalid JSON: ${error.message}`
+ )
+ }
+}
+
+function normalizeFile(value, label) {
+ assertExactFields(value, FILE_FIELDS, label)
+ if (
+ typeof value.name !== 'string' ||
+ basename(value.name) !== value.name ||
+ !SAFE_NAME.test(value.name)
+ ) {
+ throw new Error(`SSH relay runtime manifest artifact ${label} has an unsafe name`)
+ }
+ if (!DIGEST.test(value.sha256)) {
+ throw new Error(`SSH relay runtime manifest artifact ${label} has an invalid SHA-256`)
+ }
+ if (!Number.isSafeInteger(value.size) || value.size <= 0) {
+ throw new Error(`SSH relay runtime manifest artifact ${label} has an invalid size`)
+ }
+ return { name: value.name, sha256: value.sha256, size: value.size }
+}
+
+function normalizeAggregateInput(value, expectedTupleId) {
+ assertExactFields(value, INPUT_FIELDS, `${expectedTupleId} aggregate input`)
+ if (value.tupleId !== expectedTupleId) {
+ throw new Error(`SSH relay runtime manifest artifact receipt tuple drifted: ${expectedTupleId}`)
+ }
+ return {
+ tupleId: expectedTupleId,
+ descriptor: normalizeFile(value.descriptor, `${expectedTupleId} descriptor`),
+ archive: normalizeFile(value.archive, `${expectedTupleId} archive`),
+ sbom: normalizeFile(value.sbom, `${expectedTupleId} SBOM`),
+ provenance: normalizeFile(value.provenance, `${expectedTupleId} provenance`)
+ }
+}
+
+function receiptBinding(receipt, artifact) {
+ assertObject(receipt, `${artifact.tupleId} finalization receipt`)
+ if (receipt.tupleId !== artifact.tupleId) {
+ throw new Error(
+ `SSH relay runtime manifest artifact receipt tuple drifted: ${artifact.tupleId}`
+ )
+ }
+ const contentId = artifact.layout === 'flat' ? receipt.contentId : receipt.finalContentId
+ if (!DIGEST.test(contentId ?? '')) {
+ throw new Error(
+ `SSH relay runtime manifest artifact receipt content drifted: ${artifact.tupleId}`
+ )
+ }
+ return {
+ tupleId: artifact.tupleId,
+ contentId,
+ aggregateInput: normalizeAggregateInput(receipt.aggregateInput, artifact.tupleId)
+ }
+}
+
+async function copyStableFile(source, destination, file, signal) {
+ signal?.throwIfAborted()
+ const before = await lstat(source, { bigint: true })
+ if (!before.isFile() || before.isSymbolicLink()) {
+ throw new Error(
+ `SSH relay runtime manifest artifact input is not the declared regular file: ${file.name}`
+ )
+ }
+ if (before.size !== BigInt(file.size)) {
+ throw new Error(`SSH relay runtime manifest artifact input size mismatch: ${file.name}`)
+ }
+ await copyFile(source, destination, constants.COPYFILE_EXCL)
+ const after = await lstat(source, { bigint: true })
+ if (!stableState(before, after)) {
+ throw new Error(`SSH relay runtime manifest artifact input changed while copying: ${file.name}`)
+ }
+}
+
+async function assertExactArtifactDirectories(root) {
+ const entries = await readdir(root, { withFileTypes: true })
+ const actual = entries.map((entry) => entry.name).sort()
+ const expected = SSH_RELAY_RUNTIME_MANIFEST_ARTIFACTS.map(
+ ({ artifactName }) => artifactName
+ ).sort()
+ if (JSON.stringify(actual) !== JSON.stringify(expected)) {
+ throw new Error(
+ 'SSH relay runtime manifest artifact root has missing or unexpected directories'
+ )
+ }
+ for (const entry of entries) {
+ if (!entry.isDirectory() || entry.isSymbolicLink()) {
+ throw new Error(`SSH relay runtime manifest artifact is not a real directory: ${entry.name}`)
+ }
+ }
+}
+
+export async function collectSshRelayRuntimeManifestArtifacts({
+ artifactsDirectory,
+ stagingDirectory,
+ signal
+}) {
+ const root = await realDirectory(resolve(artifactsDirectory), 'root')
+ const staging = await realDirectory(resolve(stagingDirectory), 'staging directory')
+ await assertExactArtifactDirectories(root)
+ const names = new Set()
+ const bindings = []
+ for (const artifact of SSH_RELAY_RUNTIME_MANIFEST_ARTIFACTS) {
+ signal?.throwIfAborted()
+ const artifactRoot = await realDirectory(
+ join(root, artifact.artifactName),
+ artifact.artifactName
+ )
+ const assetsRoot =
+ artifact.layout === 'flat'
+ ? artifactRoot
+ : await realDirectory(join(artifactRoot, 'assets'), `${artifact.tupleId} assets`)
+ const evidenceRoot =
+ artifact.layout === 'flat'
+ ? artifactRoot
+ : await realDirectory(join(artifactRoot, 'evidence'), `${artifact.tupleId} evidence`)
+ const suffix = artifact.layout === 'flat' ? 'linux-finalization' : 'finalization'
+ const receipt = await readStableJson(
+ join(evidenceRoot, `${artifact.tupleId}.${suffix}.json`),
+ `${artifact.tupleId} receipt`,
+ signal
+ )
+ const binding = receiptBinding(receipt, artifact)
+ for (const file of [
+ binding.aggregateInput.descriptor,
+ binding.aggregateInput.archive,
+ binding.aggregateInput.sbom,
+ binding.aggregateInput.provenance
+ ]) {
+ if (names.has(file.name)) {
+ throw new Error(`SSH relay runtime manifest artifact has a duplicate file: ${file.name}`)
+ }
+ names.add(file.name)
+ await copyStableFile(join(assetsRoot, file.name), join(staging, file.name), file, signal)
+ }
+ bindings.push(binding)
+ }
+ return bindings
+}
diff --git a/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist-summary.md b/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist-summary.md
index 8d895aaeafc..6fb74adf9c0 100644
--- a/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist-summary.md
+++ b/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist-summary.md
@@ -242,8 +242,11 @@ complete a box.
signing remains blocked and no release, desktop, publication, or tuple consumer is connected.
The missing-workflow/seed-signer RED is
`E-M4-PROTECTED-MANIFEST-WORKFLOW-LOCAL-RED-001`; the seed signer is locally green under
- `E-M4-PROTECTED-MANIFEST-SEED-LOCAL-001`, while the filesystem aggregate command and workflow
- remain open.
+ `E-M4-PROTECTED-MANIFEST-SEED-LOCAL-001` and all-six exact-head CI is closed by
+ `E-M4-PROTECTED-MANIFEST-SEED-CI-001`. The filesystem prepare/finalize command is locally
+ green under `E-M4-MANIFEST-AGGREGATE-COMMAND-LOCAL-RED-001` and
+ `E-M4-MANIFEST-AGGREGATE-COMMAND-LOCAL-001`; exact-head CI and the callable workflow remain
+ open.
- [ ] Embed the exact signed manifest and accepted keys in each desktop build.
- [ ] Upload to a draft release, read back, re-hash, and execute the downloaded archives.
- [ ] Test timeouts, retries, approval denial, signing failure, partial output, and draft recovery.
diff --git a/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist.md b/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist.md
index 50e1eb39676..2986ee50794 100644
--- a/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist.md
+++ b/docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist.md
@@ -9,7 +9,7 @@ work; keep exact commands, runner identities, hashes, metrics, and residual gaps
Date created: 2026-07-14
Last updated: 2026-07-15
Current phase: Milestone 4 / Work Package 3 disconnected aggregate and protected manifest-signing workflow contract — **In progress — 2026-07-15, Codex implementation owner**. Linux aggregate-ready finalization is closed locally and on exact-head native x64/arm64 runners under E-M4-LINUX-FINALIZATION-LOCAL-RED-001, E-M4-LINUX-FINALIZATION-LOCAL-001, and E-M4-LINUX-FINALIZATION-CI-001. The active package must consume only the six exact aggregate-ready outputs, prepare canonical bytes credential-free, expose only those bytes to the tag-restricted `relay-runtime-manifest-signing` environment, accept only key ID plus Ed25519 signature, reconstruct and verify before final output, and fail closed on missing/extra/mutated inputs, approval/secret/signing failure, timeout, or partial output. It remains callable and disconnected. Release-cut, desktop builds, publication, and every tuple stay disconnected; production/default behavior is unchanged.
-Session checkpoint: **In progress — 2026-07-15, Codex implementation owner** — exact-head run 29419759256 at `91f59d19e5251fb7b6c9f6d397cd9cd82b43cbdf` passes all six native builds, both Linux userland supplements, and Windows x64 baseline. Windows arm64 fails only the retained build-floor gate after successful runtime verification (hosted 26200 versus required 26100). Downloaded artifacts 8344803641 and 8344824674 contain the expected Linux x64/arm64 descriptors and finalization receipts, whose tuple/content/archive/metadata bindings and smoke/resource metrics were inspected under E-M4-LINUX-FINALIZATION-CI-001. Golden E2E and replacement PR Checks pass. The protected seed signer is now locally green under E-M4-PROTECTED-MANIFEST-WORKFLOW-LOCAL-RED-001 and E-M4-PROTECTED-MANIFEST-SEED-LOCAL-001: canonical request serialization, exact base64 32-byte seed validation, signature-only output, drift/symlink rejection, and exclusive failure cleanup pass, and both native contract families execute the tests. The callable workflow remains intentionally absent/red while the filesystem prepare/finalize command is implemented next. No signing credential, aggregate workflow, release consumer, publication path, desktop consumer, tuple enablement, or production/default change is connected. Legacy remains the production default, and merge to `main` remains prohibited.
+Session checkpoint: **In progress — 2026-07-15, Codex implementation owner** — protected seed-signer exact-head CI is closed by E-M4-PROTECTED-MANIFEST-SEED-CI-001 at pushed head `4180e04ac4e732f082dc576af69364325a678d2b`: all six native build jobs, PR Checks, and Golden E2E pass, with the artifact workflow red only for the retained Windows arm64 build-floor mismatch. The exclusive six-artifact filesystem command is locally green under E-M4-MANIFEST-AGGREGATE-COMMAND-LOCAL-RED-001 and E-M4-MANIFEST-AGGREGATE-COMMAND-LOCAL-001. Exact-head CI for that command is the next checkpoint, after which the still-red callable workflow may be implemented. No signing credential, aggregate workflow, release consumer, publication path, desktop consumer, tuple enablement, or production/default change is connected. Legacy remains the production default, and merge to `main` remains prohibited.
Primary design: [SSH relay GitHub Release plan](./2026-07-14-ssh-relay-github-release-plan.html)
Motivating issues: [#8450](https://github.com/stablyai/orca/issues/8450), [#1693](https://github.com/stablyai/orca/issues/1693)
@@ -10776,6 +10776,96 @@ typecheck` passes in 1.88 seconds wall. Full `pnpm run lint` passes in 9.26 seco
receipt/path/mutation/accepted-key/signature/partial-output failures, before adding the callable
workflow.
+### E-M4-MANIFEST-AGGREGATE-COMMAND-LOCAL-RED-001 — Six-artifact filesystem command is absent
+
+- Date: 2026-07-15
+- Owner: Codex implementation owner
+- Source: uncommitted purpose-named test atop pushed head
+ `4180e04ac4e732f082dc576af69364325a678d2b`; draft PR #8741.
+- Runner/remote/network: local macOS 26.2 arm64, Node v26.0.0 and pnpm 10.24.0. Generated local
+ fixtures only; no Actions runner, GitHub Environment, seed, release, desktop consumer, SSH host,
+ publication, or enabled tuple.
+- Command: `pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1
+config/scripts/ssh-relay-runtime-manifest-aggregate-command.test.mjs`.
+- Result: expected FAIL, 1 suite / 0 tests collected in 225 ms. The only failure is module
+ resolution for absent `config/scripts/ssh-relay-runtime-manifest-aggregate-command.mjs`.
+- Oracle proved: there is no file-based boundary that collects only the exact two flattened Linux
+ and four signed native artifacts, binds finalization receipts and accepted public keys, exposes
+ canonical bytes without credentials, independently recollects after signature return, verifies
+ the signature, and removes partial output on failure. The test defines missing/extra directory,
+ symlink, mutation, receipt drift, invalid-key, invalid-signature, and cleanup failures.
+- Does not prove: implementation, real downloaded artifact inputs, Actions execution, protected
+ signing, publication, desktop embedding, SSH behavior, or an enabled tuple.
+- Follow-up: implement the command and make this suite green before adding the callable workflow.
+
+### E-M4-PROTECTED-MANIFEST-SEED-CI-001 — Seed signer passes all six native contract families
+
+- Date: 2026-07-15
+- Owner: Codex implementation owner
+- Source: exact pushed head `4180e04ac4e732f082dc576af69364325a678d2b`; draft PR #8741.
+- Workflow: [SSH Relay Runtime Artifacts run 29422587380](https://github.com/stablyai/orca/actions/runs/29422587380),
+ 14:13:18Z–14:27:59Z. The workflow conclusion is the expected failure solely because Windows
+ arm64 hosted build 26200 does not equal the separately required build 26100 after successful
+ runtime execution.
+- Native jobs: Linux arm64 87376626186, Linux x64 87376626194, macOS x64 87376626222, Windows arm64
+ 87376626264, macOS arm64 87376626297, and Windows x64 87376626317 all pass. Linux/macOS report 48
+ files / 251 tests; Windows reports 49 files / 246 passed and nine skipped of 255. The delta from
+ the prior package is the protected seed-signing purpose suite under Node 24.18.0 on every family.
+- Supplemental gates: Linux x64 87378044229, Linux arm64 87378044358, and Windows x64 87379238862
+ pass. Windows arm64 87379238661 fails only the retained 26200-versus-26100 floor assertion.
+- Adjacent regressions: [PR Checks 29422587487](https://github.com/stablyai/orca/actions/runs/29422587487)
+ job 87376597444 passes from 14:13:22Z–14:26:30Z. [Golden E2E 29422587419](https://github.com/stablyai/orca/actions/runs/29422587419)
+ passes macOS job 87376596910 and Linux job 87376596912.
+- Oracle proved: canonical request serialization and seed-signing failure contracts execute under
+ repository Node 24 on all target-native runner families without regressing builds, packaged
+ smoke, full PR checks, or Golden E2E.
+- Does not prove: a real protected environment/seed, approval, filesystem aggregate command CI,
+ callable aggregate workflow, native signing/trust, oldest Windows arm64/macOS/Linux kernel
+ floors, publication, desktop embedding, SSH behavior, or an enabled tuple.
+- Follow-up: checkpoint the locally green filesystem aggregate command and require it on the same
+ six native families before implementing the callable workflow.
+
+### E-M4-MANIFEST-AGGREGATE-COMMAND-LOCAL-001 — Six-artifact prepare/finalize boundary passes locally
+
+- Date: 2026-07-15
+- Owner: Codex implementation owner
+- Source: local implementation atop pushed head
+ `4180e04ac4e732f082dc576af69364325a678d2b`; draft PR #8741.
+- Runner/remote/network: local macOS 26.2 arm64, Node v26.0.0 and pnpm 10.24.0. Six generated
+ aggregate-ready fixture directories and an in-memory Ed25519 test seed only; no Actions runner,
+ GitHub Environment, production key, release, desktop consumer, SSH host, publication, or enabled
+ tuple.
+- Focused command: `pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1
+config/scripts/ssh-relay-runtime-manifest-aggregate-command.test.mjs` — PASS, 1 file / 4 tests in
+ 409 ms Vitest. A final cross-platform split rerun passes 1 file / 5 tests in 504 ms, preserving
+ the symlink case on POSIX while leaving all other hostile cases active on Windows. The suite covers
+ exact six-directory enumeration, flattened Linux versus signed
+ `assets/` + `evidence/` layouts, stable exclusive copies, finalization receipts, content and
+ descriptor bindings, duplicate names/tuples, missing/extra directories, symlinks, mutation,
+ invalid accepted keys, prepared drift, cancellation, invalid signatures, and failure cleanup.
+- Broad release command: `rg --files config/scripts | rg
+'/ssh-relay.*[.]test[.]mjs$' | rg -v
+'ssh-relay-runtime-manifest-signing-workflow[.]test[.]mjs$' | xargs /usr/bin/time -l pnpm exec
+ vitest run --config config/vitest.config.ts --maxWorkers=1` — PASS, 50 files / 260 tests in 8.68
+ seconds Vitest / 9.56 seconds wall, 189,104,128-byte maximum RSS, 96,130,448-byte peak footprint,
+ zero swaps. The preceding unfiltered 51-file run passes all implemented suites and fails only the
+ recorded absent-workflow RED; its pre-split count was 50 files / 259 tests.
+- Desktop parity and static gates: manifest schema/signature/release-asset parity passes 3 files / 48
+ tests; `pnpm run typecheck`, `node --check`, focused oxlint/formatting, and full `pnpm run lint`
+ pass. Full lint reports all 41 reliability gates, the 355-entry max-lines ratchet, bundled-skill,
+ localization catalog/parity, and localization coverage green; 26 warnings remain only in
+ untouched existing files.
+- Oracle proved: accepted public keys are validated and hash-bound before a request is exposed. The
+ preparation phase copies and verifies only the four declared files from each exact finalization
+ receipt into exclusive staging. Finalization independently recollects all six inputs, compares
+ the complete prepared receipt/request, verifies the returned key/signature, emits the manifest
+ and evidence exclusively, and removes staging/partial output on every tested failure.
+- Does not prove: actual downloaded native artifact directories, Node 24/native CI, a real protected
+ signer/environment/approval, the callable workflow, native signing/trust, publication, desktop
+ embedding, SSH behavior, or an enabled tuple.
+- Follow-up: checkpoint and push this command, require it on all six exact-head native jobs, then
+ implement the still-red callable workflow without connecting release or product consumers.
+
## Accepted Gaps
No product gap is accepted merely because it appears in this list. Each entry requires explicit
@@ -10834,16 +10924,14 @@ The project is not complete until every applicable item below is checked with ev
## Next Required Action
-Checkpoint the locally proven protected seed signer and require its contract on all six native test
-families. Then implement the exclusive filesystem prepare/finalize command that collects only the
-six exact aggregate-ready artifacts, binds receipts and accepted public keys, serializes canonical
-bytes without credentials, reconstructs after signature return, and removes partial output on every
-failure. Only after that command is green may the still-red callable workflow isolate the base64
-32-byte seed in the tag-restricted `relay-runtime-manifest-signing` environment. The environment,
-accepted production keys, and secret remain unprovisioned, so live signing evidence must stay
-BLOCKED. Keep Windows arm64 build 26100, macOS 13.5, Linux kernel 4.18, release-cut, desktop builds,
-publication, and every tuple separately gated. Do not merge to `main`; retain every
-production/default gate.
+Checkpoint the locally proven filesystem prepare/finalize command and require its purpose suite on
+all six exact-head native test families. After that CI evidence is green, implement the still-red
+callable workflow so only canonical request bytes and the base64 32-byte seed enter the
+tag-restricted `relay-runtime-manifest-signing` environment, while credential-free preparation and
+final reconstruction independently download the six exact artifacts. The environment, accepted
+production keys, and secret remain unprovisioned, so live signing evidence must stay BLOCKED. Keep
+Windows arm64 build 26100, macOS 13.5, Linux kernel 4.18, release-cut, desktop builds, publication,
+and every tuple separately gated. Do not merge to `main`; retain every production/default gate.
Cross-family Layer B targets, the protected manifest-signing environment, oldest-baseline/native-
trust cells, and the paired legacy performance baseline remain release/default-path blockers. No