build(ssh): gate runtime release stages

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Jinwoo-H
2026-07-15 00:47:46 -04:00
co-authored by Orca
parent be32653a7b
commit 6f13e94f8a
8 changed files with 937 additions and 39 deletions
@@ -143,6 +143,10 @@ jobs:
node --check config/scripts/ssh-relay-runtime-windows-signature-verification.test.mjs
node --check config/scripts/ssh-relay-runtime-windows-source-signature-verification.mjs
node --check config/scripts/ssh-relay-runtime-windows-source-signature-verification.test.mjs
node --check config/scripts/ssh-relay-runtime-release-stage-gate.mjs
node --check config/scripts/ssh-relay-runtime-release-stage-gate.test.mjs
node --check config/scripts/ssh-relay-runtime-draft-recovery.mjs
node --check config/scripts/ssh-relay-runtime-draft-recovery.test.mjs
pnpm exec vitest run --config config/vitest.config.ts \
config/scripts/ssh-relay-node-release-verification.test.mjs \
config/scripts/ssh-relay-node-tar-inspection.test.mjs \
@@ -164,6 +168,8 @@ jobs:
config/scripts/ssh-relay-runtime-macos-signature-verification.test.mjs \
config/scripts/ssh-relay-runtime-windows-signature-verification.test.mjs \
config/scripts/ssh-relay-runtime-windows-source-signature-verification.test.mjs \
config/scripts/ssh-relay-runtime-release-stage-gate.test.mjs \
config/scripts/ssh-relay-runtime-draft-recovery.test.mjs \
config/scripts/ssh-relay-runtime-closure.test.mjs \
config/scripts/ssh-relay-runtime-pty-smoke.test.mjs \
config/scripts/ssh-relay-runtime-reproducibility.test.mjs \
@@ -479,6 +485,14 @@ jobs:
if ($LASTEXITCODE -ne 0) { throw 'runtime Windows source signature verification script syntax check failed' }
node --check config/scripts/ssh-relay-runtime-windows-source-signature-verification.test.mjs
if ($LASTEXITCODE -ne 0) { throw 'runtime Windows source signature verification test syntax check failed' }
node --check config/scripts/ssh-relay-runtime-release-stage-gate.mjs
if ($LASTEXITCODE -ne 0) { throw 'runtime release stage gate syntax check failed' }
node --check config/scripts/ssh-relay-runtime-release-stage-gate.test.mjs
if ($LASTEXITCODE -ne 0) { throw 'runtime release stage gate test syntax check failed' }
node --check config/scripts/ssh-relay-runtime-draft-recovery.mjs
if ($LASTEXITCODE -ne 0) { throw 'runtime draft recovery syntax check failed' }
node --check config/scripts/ssh-relay-runtime-draft-recovery.test.mjs
if ($LASTEXITCODE -ne 0) { throw 'runtime draft recovery test syntax check failed' }
pnpm exec vitest run --config config/vitest.config.ts `
config/scripts/ssh-relay-node-release-verification.test.mjs `
config/scripts/ssh-relay-node-tar-inspection.test.mjs `
@@ -500,6 +514,8 @@ jobs:
config/scripts/ssh-relay-runtime-macos-signature-verification.test.mjs `
config/scripts/ssh-relay-runtime-windows-signature-verification.test.mjs `
config/scripts/ssh-relay-runtime-windows-source-signature-verification.test.mjs `
config/scripts/ssh-relay-runtime-release-stage-gate.test.mjs `
config/scripts/ssh-relay-runtime-draft-recovery.test.mjs `
config/scripts/ssh-relay-runtime-closure.test.mjs `
config/scripts/ssh-relay-runtime-pty-smoke.test.mjs `
config/scripts/ssh-relay-runtime-reproducibility.test.mjs `
@@ -0,0 +1,89 @@
const SHA256_PATTERN = /^sha256:[0-9a-f]{64}$/u
const TAG_PATTERN = /^v\d+\.\d+\.\d+(?:-rc\.\d+(?:\.[0-9A-Za-z]+)?)?$/u
const COMMIT_PATTERN = /^[0-9a-f]{40}$/u
const MANAGED_ASSET_PREFIX = 'orca-ssh-relay-runtime-'
function assertObject(value, label) {
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
throw new Error(`SSH relay runtime draft recovery ${label} must be an object`)
}
}
function normalizeAsset(value, label) {
assertObject(value, label)
if (typeof value.name !== 'string' || value.name.length === 0 || value.name.length > 240) {
throw new Error(`SSH relay runtime draft recovery ${label} has an invalid name`)
}
if (typeof value.sha256 !== 'string' || !SHA256_PATTERN.test(value.sha256)) {
throw new Error(`SSH relay runtime draft recovery ${label} has an invalid sha256`)
}
if (!Number.isSafeInteger(value.size) || value.size <= 0) {
throw new Error(`SSH relay runtime draft recovery ${label} has an invalid size`)
}
return { name: value.name, sha256: value.sha256, size: value.size }
}
function uniqueAssets(values, label) {
if (!Array.isArray(values)) {
throw new Error(`SSH relay runtime draft recovery ${label} must be an array`)
}
const names = new Set()
return values.map((value) => {
const asset = normalizeAsset(value, label)
if (names.has(asset.name)) {
throw new Error(
`SSH relay runtime draft recovery ${label} has a duplicate asset: ${asset.name}`
)
}
names.add(asset.name)
return asset
})
}
function sameAsset(left, right) {
return left.name === right.name && left.sha256 === right.sha256 && left.size === right.size
}
export function planSshRelayRuntimeDraftRecovery({ tag, sourceCommit, expectedAssets, draft }) {
if (typeof tag !== 'string' || !TAG_PATTERN.test(tag)) {
throw new Error('SSH relay runtime draft recovery tag is invalid')
}
if (typeof sourceCommit !== 'string' || !COMMIT_PATTERN.test(sourceCommit)) {
throw new Error('SSH relay runtime draft recovery source commit is invalid')
}
assertObject(draft, 'draft')
if (draft.state !== 'draft') {
// Why: recovery may fill an existing private draft, never alter already published bytes.
throw new Error('SSH relay runtime release must remain draft during recovery')
}
if (draft.tag !== tag) {
throw new Error('SSH relay runtime recovered draft tag does not match the requested release')
}
if (draft.sourceCommit !== sourceCommit) {
throw new Error('SSH relay runtime recovered draft source commit does not match')
}
const expected = uniqueAssets(expectedAssets, 'expected assets')
if (expected.some((asset) => !asset.name.startsWith(MANAGED_ASSET_PREFIX))) {
throw new Error('SSH relay runtime draft recovery expected an unmanaged asset')
}
const expectedByName = new Map(expected.map((asset) => [asset.name, asset]))
const existing = uniqueAssets(draft.assets, 'draft assets')
const reusableNames = new Set()
for (const asset of existing) {
const expectedAsset = expectedByName.get(asset.name)
if (!expectedAsset) {
if (asset.name.startsWith(MANAGED_ASSET_PREFIX)) {
throw new Error(`SSH relay runtime draft has an unexpected managed asset: ${asset.name}`)
}
continue
}
if (!sameAsset(asset, expectedAsset)) {
throw new Error(`SSH relay runtime draft immutable bytes disagree: ${asset.name}`)
}
reusableNames.add(asset.name)
}
return {
reusableAssets: expected.filter((asset) => reusableNames.has(asset.name)),
uploadAssets: expected.filter((asset) => !reusableNames.has(asset.name))
}
}
@@ -0,0 +1,80 @@
import { describe, expect, it } from 'vitest'
import { planSshRelayRuntimeDraftRecovery } from './ssh-relay-runtime-draft-recovery.mjs'
const TAG = 'v1.5.0-rc.1'
const COMMIT = 'a'.repeat(40)
function asset(name, digit) {
return { name, sha256: `sha256:${digit.repeat(64)}`, size: 1024 }
}
function fixture() {
const expectedAssets = [
asset('orca-ssh-relay-runtime-v1-linux-x64-glibc-a.tar.xz', '1'),
asset('orca-ssh-relay-runtime-v1-win32-x64-b.zip', '2'),
asset('orca-ssh-relay-runtime-manifest.json', '3'),
asset('orca-ssh-relay-runtime-manifest.sig', '4')
]
return {
tag: TAG,
sourceCommit: COMMIT,
expectedAssets,
draft: { state: 'draft', tag: TAG, sourceCommit: COMMIT, assets: [] }
}
}
describe('SSH relay runtime draft recovery', () => {
it('plans all immutable assets for a new empty draft', () => {
const input = fixture()
expect(planSshRelayRuntimeDraftRecovery(input)).toEqual({
reusableAssets: [],
uploadAssets: input.expectedAssets
})
})
it('reuses only exact immutable bytes from the same draft and source commit', () => {
const input = fixture()
input.draft.assets = [
structuredClone(input.expectedAssets[0]),
asset('orca-windows-setup.exe', '9')
]
expect(planSshRelayRuntimeDraftRecovery(input)).toEqual({
reusableAssets: [input.expectedAssets[0]],
uploadAssets: input.expectedAssets.slice(1)
})
})
it('rejects changed, empty, duplicate, or unexpected managed assets', () => {
const changed = fixture()
changed.draft.assets = [{ ...changed.expectedAssets[0], sha256: `sha256:${'f'.repeat(64)}` }]
expect(() => planSshRelayRuntimeDraftRecovery(changed)).toThrow(/immutable bytes disagree/i)
const empty = fixture()
empty.draft.assets = [{ ...empty.expectedAssets[0], size: 0 }]
expect(() => planSshRelayRuntimeDraftRecovery(empty)).toThrow(/invalid size/i)
const duplicate = fixture()
duplicate.draft.assets = [inputAsset(duplicate), inputAsset(duplicate)]
expect(() => planSshRelayRuntimeDraftRecovery(duplicate)).toThrow(/duplicate/i)
const unexpected = fixture()
unexpected.draft.assets = [asset('orca-ssh-relay-runtime-v1-unknown.zip', '8')]
expect(() => planSshRelayRuntimeDraftRecovery(unexpected)).toThrow(/unexpected managed asset/i)
})
it.each([
[{ state: 'published' }, 'must remain draft'],
[{ tag: 'v1.5.0-rc.2' }, 'tag'],
[{ sourceCommit: 'b'.repeat(40) }, 'source commit']
])('rejects unsafe recovered draft state %o', (override, message) => {
const input = fixture()
Object.assign(input.draft, override)
expect(() => planSshRelayRuntimeDraftRecovery(input)).toThrow(message)
})
})
function inputAsset(input) {
return structuredClone(input.expectedAssets[0])
}
@@ -0,0 +1,288 @@
import { sshRelayRuntimeCompatibility } from './ssh-relay-runtime-compatibility.mjs'
const SHA256_PATTERN = /^sha256:[0-9a-f]{64}$/u
const ASSET_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,239}$/u
const MAX_ARCHIVE_BYTES = 100 * 1024 * 1024
const SUCCESS_FIELDS = ['id', 'outcome', 'attempts', 'elapsedMs', 'output']
const OUTCOMES = new Set(['success', 'failed', 'timed-out', 'cancelled', 'retry-exhausted'])
// Why: these mirror current release ceilings, but signing is single-attempt so approval cannot
// accidentally authorize a second set of bytes after a timeout or service failure.
export const SSH_RELAY_RUNTIME_RELEASE_LIMITS = Object.freeze({
build: Object.freeze({ maxAttempts: 3, timeoutMs: 30 * 60_000 }),
sign: Object.freeze({ maxAttempts: 1, timeoutMs: 4 * 60 * 60_000 }),
aggregate: Object.freeze({ maxAttempts: 1, timeoutMs: 15 * 60_000 }),
upload: Object.freeze({ maxAttempts: 3, timeoutMs: 15 * 60_000 }),
readback: Object.freeze({ maxAttempts: 3, timeoutMs: 15 * 60_000 })
})
function assertObject(value, label) {
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
throw new Error(`SSH relay runtime release ${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 release ${label} has unexpected or missing fields`)
}
}
function assertSha256(value, label) {
if (typeof value !== 'string' || !SHA256_PATTERN.test(value)) {
throw new Error(`SSH relay runtime release ${label} must be a lowercase sha256 identity`)
}
}
function assertAssetName(value, label) {
if (typeof value !== 'string' || !ASSET_NAME_PATTERN.test(value)) {
throw new Error(`SSH relay runtime release ${label} has an invalid asset name`)
}
}
function assertSize(value, label, maximum = MAX_ARCHIVE_BYTES) {
if (!Number.isSafeInteger(value) || value <= 0 || value > maximum) {
throw new Error(`SSH relay runtime release ${label} has an invalid size`)
}
}
function normalizeRuntimeAsset(value, tupleId, label) {
assertExactFields(value, ['tupleId', 'name', 'sha256', 'contentId', 'size'], label)
if (value.tupleId !== tupleId) {
throw new Error(`SSH relay runtime release ${label} has the wrong tuple`)
}
assertAssetName(value.name, label)
assertSha256(value.sha256, `${label} sha256`)
assertSha256(value.contentId, `${label} content ID`)
assertSize(value.size, label)
return { ...value }
}
function normalizeReleaseFile(value, expectedName, label, maximum) {
assertExactFields(value, ['name', 'sha256', 'size'], label)
if (value.name !== expectedName) {
throw new Error(`SSH relay runtime release ${label} has an unexpected name`)
}
assertSha256(value.sha256, `${label} sha256`)
assertSize(value.size, label, maximum)
return { ...value }
}
function stageKind(id) {
if (id.startsWith('build:')) {
return 'build'
}
if (id.startsWith('sign:')) {
return 'sign'
}
return id
}
function failureMessage(stage) {
if (stage.outcome === 'timed-out') {
return `${stage.id} timed out`
}
if (stage.outcome === 'retry-exhausted') {
return `${stage.id} reached retry exhaustion`
}
return `${stage.id} ${stage.outcome}`
}
function normalizeSuccessfulStage(stage) {
assertExactFields(stage, SUCCESS_FIELDS, 'stage result')
if (typeof stage.id !== 'string' || stage.id.length === 0) {
throw new Error('SSH relay runtime release stage ID is invalid')
}
if (!OUTCOMES.has(stage.outcome)) {
throw new Error(`SSH relay runtime release ${stage.id} has an unknown outcome`)
}
const limits = SSH_RELAY_RUNTIME_RELEASE_LIMITS[stageKind(stage.id)]
if (!limits) {
throw new Error(`SSH relay runtime release has an unexpected stage: ${stage.id}`)
}
if (
!Number.isSafeInteger(stage.attempts) ||
stage.attempts < 1 ||
stage.attempts > limits.maxAttempts
) {
throw new Error(`SSH relay runtime release ${stage.id} exceeds its attempt budget`)
}
if (
!Number.isSafeInteger(stage.elapsedMs) ||
stage.elapsedMs < 0 ||
stage.elapsedMs > limits.timeoutMs
) {
throw new Error(`SSH relay runtime release ${stage.id} exceeds its time budget`)
}
if (stage.outcome !== 'success') {
throw new Error(`SSH relay runtime release ${failureMessage(stage)}`)
}
return stage
}
function normalizeTupleIds(tupleIds, label, { allowEmpty = false } = {}) {
if (!Array.isArray(tupleIds) || (!allowEmpty && tupleIds.length === 0)) {
throw new Error(
`SSH relay runtime release ${label} must be ${allowEmpty ? 'an array' : 'a non-empty array'}`
)
}
const seen = new Set()
return tupleIds.map((tupleId) => {
if (!Object.hasOwn(sshRelayRuntimeCompatibility, tupleId)) {
throw new Error(`SSH relay runtime release ${label} contains an unknown tuple: ${tupleId}`)
}
if (seen.has(tupleId)) {
throw new Error(`SSH relay runtime release ${label} contains a duplicate tuple: ${tupleId}`)
}
seen.add(tupleId)
return tupleId
})
}
function sameAssets(actual, expected) {
return JSON.stringify(actual) === JSON.stringify(expected)
}
function assertAssetChain(actual, expected, label) {
if (!Array.isArray(actual) || !sameAssets(actual, expected)) {
throw new Error(
`SSH relay runtime release ${label} assets disagree with prior immutable output`
)
}
}
function collectStages(stages, expectedIds) {
if (!Array.isArray(stages)) {
throw new Error('SSH relay runtime release stages must be an array')
}
const expected = new Set(expectedIds)
const byId = new Map()
for (const stage of stages) {
assertObject(stage, 'stage result')
if (typeof stage.id !== 'string' || !expected.has(stage.id)) {
throw new Error(`SSH relay runtime release has an unexpected stage: ${String(stage.id)}`)
}
if (byId.has(stage.id)) {
throw new Error(`SSH relay runtime release has a duplicate stage: ${stage.id}`)
}
byId.set(stage.id, normalizeSuccessfulStage(stage))
}
for (const id of expectedIds) {
if (!byId.has(id)) {
throw new Error(`SSH relay runtime release is missing required stage: ${id}`)
}
}
return byId
}
function expectedSigningTuples(candidateTupleIds) {
return candidateTupleIds.filter(
(tupleId) => tupleId.startsWith('darwin-') || tupleId.startsWith('win32-')
)
}
function assertUniqueAssetNames(assets) {
const names = new Set()
for (const asset of assets) {
if (names.has(asset.name)) {
throw new Error(`SSH relay runtime release has a duplicate asset name: ${asset.name}`)
}
names.add(asset.name)
}
}
export function evaluateSshRelayRuntimeReleaseStages({
candidateTupleIds,
signingTupleIds,
stages
}) {
const candidates = normalizeTupleIds(candidateTupleIds, 'candidate tuples')
const signing = normalizeTupleIds(signingTupleIds, 'signing tuples', { allowEmpty: true })
const requiredSigning = expectedSigningTuples(candidates)
if (!sameAssets(signing, requiredSigning)) {
// Why: macOS and Windows candidates cannot bypass the returned native-signing boundary.
throw new Error('SSH relay runtime release signing tuples do not match platform policy')
}
const expectedStageIds = [
...candidates.map((tupleId) => `build:${tupleId}`),
...signing.map((tupleId) => `sign:${tupleId}`),
'aggregate',
'upload',
'readback'
]
const stageResults = collectStages(stages, expectedStageIds)
const builds = new Map()
for (const tupleId of candidates) {
builds.set(
tupleId,
normalizeRuntimeAsset(
stageResults.get(`build:${tupleId}`).output,
tupleId,
`build:${tupleId} output`
)
)
}
const finalByTuple = new Map(builds)
for (const tupleId of signing) {
const output = stageResults.get(`sign:${tupleId}`).output
assertExactFields(output, ['approval', 'inputSha256', 'asset'], `sign:${tupleId} output`)
if (output.approval !== 'approved') {
const reason =
output.approval === 'denied'
? 'approval was denied'
: output.approval === 'timed-out'
? 'approval timed out'
: 'approval is absent'
throw new Error(`SSH relay runtime release sign:${tupleId} ${reason}`)
}
if (output.inputSha256 !== builds.get(tupleId).sha256) {
throw new Error(
`SSH relay runtime release sign:${tupleId} unsigned input disagrees with build output`
)
}
const signed = normalizeRuntimeAsset(output.asset, tupleId, `sign:${tupleId} returned asset`)
if (
signed.sha256 === output.inputSha256 ||
signed.contentId === builds.get(tupleId).contentId
) {
throw new Error(
`SSH relay runtime release sign:${tupleId} did not produce a new immutable identity`
)
}
finalByTuple.set(tupleId, signed)
}
const finalRuntimeAssets = candidates.map((tupleId) => finalByTuple.get(tupleId))
assertUniqueAssetNames(finalRuntimeAssets)
const aggregate = stageResults.get('aggregate').output
assertExactFields(aggregate, ['inputAssets', 'manifest', 'signature'], 'aggregate output')
assertAssetChain(aggregate.inputAssets, finalRuntimeAssets, 'aggregate input')
const manifest = normalizeReleaseFile(
aggregate.manifest,
'orca-ssh-relay-runtime-manifest.json',
'aggregate manifest',
1024 * 1024
)
const signature = normalizeReleaseFile(
aggregate.signature,
'orca-ssh-relay-runtime-manifest.sig',
'aggregate manifest signature',
4096
)
const releaseAssets = [...finalRuntimeAssets, manifest, signature]
assertUniqueAssetNames(releaseAssets)
const upload = stageResults.get('upload').output
assertExactFields(upload, ['inputAssets', 'uploadedAssets'], 'upload output')
assertAssetChain(upload.inputAssets, releaseAssets, 'upload input')
assertAssetChain(upload.uploadedAssets, releaseAssets, 'uploaded')
const readback = stageResults.get('readback').output
assertExactFields(readback, ['inputAssets', 'downloadedAssets'], 'readback output')
assertAssetChain(readback.inputAssets, releaseAssets, 'readback input')
assertAssetChain(readback.downloadedAssets, releaseAssets, 'readback downloaded')
return { candidateTupleIds: candidates, finalRuntimeAssets, releaseAssets, publishable: true }
}
@@ -0,0 +1,228 @@
import { describe, expect, it } from 'vitest'
import {
SSH_RELAY_RUNTIME_RELEASE_LIMITS,
evaluateSshRelayRuntimeReleaseStages
} from './ssh-relay-runtime-release-stage-gate.mjs'
const LINUX = 'linux-x64-glibc'
const WINDOWS = 'win32-x64'
const SHA = {
linux: `sha256:${'1'.repeat(64)}`,
windowsUnsigned: `sha256:${'2'.repeat(64)}`,
windowsSigned: `sha256:${'3'.repeat(64)}`,
manifest: `sha256:${'4'.repeat(64)}`,
signature: `sha256:${'5'.repeat(64)}`
}
function asset(tupleId, name, sha256, contentDigit) {
return {
tupleId,
name,
sha256,
contentId: `sha256:${contentDigit.repeat(64)}`,
size: 1024
}
}
function stage(id, output, overrides = {}) {
return {
id,
outcome: 'success',
attempts: 1,
elapsedMs: 1_000,
output,
...overrides
}
}
function successfulFixture() {
const linux = asset(LINUX, 'orca-ssh-relay-runtime-linux.tar.xz', SHA.linux, 'a')
const windowsUnsigned = asset(
WINDOWS,
'orca-ssh-relay-runtime-windows-unsigned.zip',
SHA.windowsUnsigned,
'b'
)
const windowsSigned = asset(
WINDOWS,
'orca-ssh-relay-runtime-windows-signed.zip',
SHA.windowsSigned,
'c'
)
const manifest = {
name: 'orca-ssh-relay-runtime-manifest.json',
sha256: SHA.manifest,
size: 2048
}
const signature = {
name: 'orca-ssh-relay-runtime-manifest.sig',
sha256: SHA.signature,
size: 64
}
const finalRuntimeAssets = [linux, windowsSigned]
const releaseAssets = [...finalRuntimeAssets, manifest, signature]
return {
candidateTupleIds: [LINUX, WINDOWS],
signingTupleIds: [WINDOWS],
stages: [
stage(`build:${LINUX}`, linux),
stage(`build:${WINDOWS}`, windowsUnsigned),
stage(`sign:${WINDOWS}`, {
approval: 'approved',
inputSha256: windowsUnsigned.sha256,
asset: windowsSigned
}),
stage('aggregate', {
inputAssets: structuredClone(finalRuntimeAssets),
manifest: structuredClone(manifest),
signature: structuredClone(signature)
}),
stage('upload', {
inputAssets: structuredClone(releaseAssets),
uploadedAssets: structuredClone(releaseAssets)
}),
stage('readback', {
inputAssets: structuredClone(releaseAssets),
downloadedAssets: structuredClone(releaseAssets)
})
]
}
}
function stageById(fixture, id) {
return fixture.stages.find((entry) => entry.id === id)
}
describe('SSH relay runtime release stage gate', () => {
it('pins finite release-stage retry and timeout ceilings', () => {
expect(SSH_RELAY_RUNTIME_RELEASE_LIMITS).toEqual({
build: { maxAttempts: 3, timeoutMs: 30 * 60_000 },
sign: { maxAttempts: 1, timeoutMs: 4 * 60 * 60_000 },
aggregate: { maxAttempts: 1, timeoutMs: 15 * 60_000 },
upload: { maxAttempts: 3, timeoutMs: 15 * 60_000 },
readback: { maxAttempts: 3, timeoutMs: 15 * 60_000 }
})
})
it('accepts only a complete immutable build-sign-aggregate-upload-readback chain', () => {
const result = evaluateSshRelayRuntimeReleaseStages(successfulFixture())
expect(result.candidateTupleIds).toEqual([LINUX, WINDOWS])
expect(result.finalRuntimeAssets.map((entry) => entry.tupleId)).toEqual([LINUX, WINDOWS])
expect(result.releaseAssets.map((entry) => entry.name)).toEqual([
'orca-ssh-relay-runtime-linux.tar.xz',
'orca-ssh-relay-runtime-windows-signed.zip',
'orca-ssh-relay-runtime-manifest.json',
'orca-ssh-relay-runtime-manifest.sig'
])
expect(result.publishable).toBe(true)
})
it('does not invent a signing stage for a Linux-only candidate set', () => {
const fixture = successfulFixture()
fixture.candidateTupleIds = [LINUX]
fixture.signingTupleIds = []
fixture.stages = fixture.stages.filter(
(entry) => entry.id !== `build:${WINDOWS}` && entry.id !== `sign:${WINDOWS}`
)
const linux = structuredClone(stageById(fixture, `build:${LINUX}`).output)
const aggregate = stageById(fixture, 'aggregate').output
aggregate.inputAssets = [structuredClone(linux)]
const releaseAssets = [linux, aggregate.manifest, aggregate.signature]
Object.assign(stageById(fixture, 'upload').output, {
inputAssets: structuredClone(releaseAssets),
uploadedAssets: structuredClone(releaseAssets)
})
Object.assign(stageById(fixture, 'readback').output, {
inputAssets: structuredClone(releaseAssets),
downloadedAssets: structuredClone(releaseAssets)
})
expect(evaluateSshRelayRuntimeReleaseStages(fixture).finalRuntimeAssets).toEqual([linux])
})
it('requires signing for every macOS and Windows candidate and forbids it for Linux', () => {
const missing = successfulFixture()
missing.signingTupleIds = []
expect(() => evaluateSshRelayRuntimeReleaseStages(missing)).toThrow(/platform policy/i)
const extra = successfulFixture()
extra.signingTupleIds = [WINDOWS, LINUX]
expect(() => evaluateSshRelayRuntimeReleaseStages(extra)).toThrow(/platform policy/i)
})
it.each([
['timed-out', 'timed out'],
['retry-exhausted', 'retry exhaustion'],
['failed', 'failed'],
['cancelled', 'cancelled']
])('fails closed when a build is %s', (outcome, message) => {
const fixture = successfulFixture()
Object.assign(stageById(fixture, `build:${LINUX}`), { outcome, output: undefined })
expect(() => evaluateSshRelayRuntimeReleaseStages(fixture)).toThrow(message)
})
it.each([
['pending', 'approval is absent'],
['denied', 'approval was denied'],
['timed-out', 'approval timed out']
])('fails closed when signing approval is %s', (approval, message) => {
const fixture = successfulFixture()
stageById(fixture, `sign:${WINDOWS}`).output.approval = approval
expect(() => evaluateSshRelayRuntimeReleaseStages(fixture)).toThrow(message)
})
it('rejects signing failure, unsigned input drift, and incomplete returned output', () => {
const failed = successfulFixture()
Object.assign(stageById(failed, `sign:${WINDOWS}`), { outcome: 'failed', output: undefined })
expect(() => evaluateSshRelayRuntimeReleaseStages(failed)).toThrow(/sign:win32-x64 failed/i)
const drifted = successfulFixture()
stageById(drifted, `sign:${WINDOWS}`).output.inputSha256 = SHA.linux
expect(() => evaluateSshRelayRuntimeReleaseStages(drifted)).toThrow(/unsigned input/i)
const incomplete = successfulFixture()
delete stageById(incomplete, `sign:${WINDOWS}`).output.asset.sha256
expect(() => evaluateSshRelayRuntimeReleaseStages(incomplete)).toThrow(/missing fields|sha256/i)
})
it('enforces bounded attempts and elapsed time even for success results', () => {
const retried = successfulFixture()
stageById(retried, 'upload').attempts = SSH_RELAY_RUNTIME_RELEASE_LIMITS.upload.maxAttempts + 1
expect(() => evaluateSshRelayRuntimeReleaseStages(retried)).toThrow(/attempt budget/i)
const slow = successfulFixture()
stageById(slow, 'aggregate').elapsedMs =
SSH_RELAY_RUNTIME_RELEASE_LIMITS.aggregate.timeoutMs + 1
expect(() => evaluateSshRelayRuntimeReleaseStages(slow)).toThrow(/time budget/i)
})
it('rejects missing, duplicate, and unexpected stage results', () => {
const missing = successfulFixture()
missing.stages = missing.stages.filter((entry) => entry.id !== 'readback')
expect(() => evaluateSshRelayRuntimeReleaseStages(missing)).toThrow(/missing.*readback/i)
const duplicate = successfulFixture()
duplicate.stages.push(structuredClone(duplicate.stages[0]))
expect(() => evaluateSshRelayRuntimeReleaseStages(duplicate)).toThrow(/duplicate/i)
const unexpected = successfulFixture()
unexpected.stages.push(stage('sign:linux-x64-glibc', {}))
expect(() => evaluateSshRelayRuntimeReleaseStages(unexpected)).toThrow(/unexpected/i)
})
it('rejects aggregate, upload, or read-back byte drift', () => {
for (const [id, field] of [
['aggregate', 'inputAssets'],
['upload', 'uploadedAssets'],
['readback', 'downloadedAssets']
]) {
const fixture = successfulFixture()
stageById(fixture, id).output[field][0].sha256 = SHA.windowsUnsigned
expect(() => evaluateSshRelayRuntimeReleaseStages(fixture)).toThrow(/asset.*disagree/i)
}
})
})
@@ -95,9 +95,15 @@ describe('SSH relay runtime artifact workflow', () => {
expect(
source.match(/ssh-relay-runtime-windows-signature-verification\.test\.mjs/g)
).toHaveLength(4)
expect(
source.match(/ssh-relay-runtime-windows-source-signature-verification\.test\.mjs/g)
).toHaveLength(4)
for (const moduleName of [
'windows-source-signature-verification',
'release-stage-gate',
'draft-recovery'
]) {
const script = `ssh-relay-runtime-${moduleName}`
expect(source.split(`${script}.test.mjs`)).toHaveLength(5)
expect(source.split(`node --check config/scripts/${script}.mjs`)).toHaveLength(3)
}
expect(
source.match(/node --check config\/scripts\/ssh-relay-runtime-native-signing-plan\.mjs/g)
).toHaveLength(2)
@@ -128,11 +134,6 @@ describe('SSH relay runtime artifact workflow', () => {
/node --check config\/scripts\/ssh-relay-runtime-windows-signature-verification\.mjs/g
)
).toHaveLength(2)
expect(
source.match(
/node --check config\/scripts\/ssh-relay-runtime-windows-source-signature-verification\.mjs/g
)
).toHaveLength(2)
expect(
source.match(/node --check config\/scripts\/ssh-relay-runtime-closure\.mjs/g)
).toHaveLength(2)
@@ -1,6 +1,6 @@
# SSH Relay Runtime Distribution — Short Implementation Checklist
Last updated: 2026-07-14
Last updated: 2026-07-15
Use this file to track the project. The
[detailed evidence ledger](./2026-07-14-ssh-relay-github-release-implementation-checklist.md)
@@ -48,9 +48,16 @@ complete a box.
[29387668264](https://github.com/stablyai/orca/actions/runs/29387668264): credential-free Windows
final-tree-first Authenticode policy contracts execute under Node 24 on all six native jobs.
This is contract proof, not proof of real SignPath returns or native trust.
- Proven locally: target-native official-Node and preserved-upstream Windows source-signature
verification contracts. Exact x64/arm64 `Valid` signer reports are the active CI gate; real
SignPath returns and missing oldest-floor snapshots remain separately gated.
- Proven locally and on native x64/arm64 Windows jobs in exact-head run
[29388734922](https://github.com/stablyai/orca/actions/runs/29388734922): official Node and both
preserved Microsoft ConPTY files report `Valid`; downloaded reports match the exact identity,
hashes, subjects, thumbprints, and signing-stage selection
(`E-M3-WINDOWS-SOURCE-SIGNATURE-CI-001`). PR Checks
[29388734935](https://github.com/stablyai/orca/actions/runs/29388734935) and Golden E2E
[29388734914](https://github.com/stablyai/orca/actions/runs/29388734914) are green at `be32653a7`.
The artifact workflow remains red only for the declared Windows arm64 floor mismatch (hosted
build 26200 versus required 26100). Real SignPath returns and missing oldest-floor snapshots
remain separately gated.
- Next external proof: kernel 4.18, macOS 13.5, Windows arm64 build 26100, and native signing/trust.
- No tuple is enabled; every SSH transfer/runtime and rollout cell remains open.
@@ -87,6 +94,10 @@ complete a box.
### WP3 — Release build and signing
- [ ] **In progress — 2026-07-15, Codex implementation owner:** add disconnected credential-free
fail-closed release/signing DAG contracts before production workflow wiring. Local red/green,
full SSH-relay, type, lint, formatting, and native-job wiring gates pass under
`E-M4-RELEASE-DAG-LOCAL-001`; exact-head CI is next.
- [ ] Add target-native runtime jobs as desktop release prerequisites.
- [ ] Add native signing jobs; hash only the returned signed bytes.
- [ ] Add a fail-closed aggregate and immutable manifest-signing job.
@@ -7,9 +7,9 @@ This file is the detailed evidence ledger. Use the tracker above for project sta
work; keep exact commands, runner identities, hashes, metrics, and residual gaps here.
Date created: 2026-07-14<br>
Last updated: 2026-07-14<br>
Current phase: Milestone 3 / Work Package 2 oldest-supported-baseline and native-trust proof — **In progress — 2026-07-14, Codex implementation owner**; exact-head run [29373507297](https://github.com/stablyai/orca/actions/runs/29373507297) passes all six target-native build, smoke, exact clean-build equality, upload, SBOM, license, provenance, runner/toolchain, and prohibited-content cells, and direct inspection of every downloaded payload passes exact archive/subject hashes, archive-scoped SPDX identity, one-owner-per-file, dependency, commit/run/builder/runner, tool-version/hash, and closure assertions (E-M3-METADATA-CI-001); Windows x64/arm64 record strict `MSVC 14.44.35207` identities and distinct exact linker SHA-256 values despite the Git-for-Windows PATH collision; the all-six metadata/provenance gate is closed, while oldest-baseline execution, native signing/trust, cross-family remotes, and measured legacy baselines remain open; production/default behavior and every tuple state remain unchanged; no bundled-runtime path is enabled and no artifact is published<br>
Session checkpoint: **In progress — 2026-07-14, Codex implementation owner** — credential-free macOS post-sign strict-codesign and signer-policy verification contracts are locally green under E-M3-MACOS-SIGNATURE-LOCAL-001 and pass under Node 24 on all six target-native jobs in exact-head run 29386372366 under E-M3-MACOS-SIGNATURE-CI-001. E-M3-WINDOWS-SIGNATURE-LOCAL-RED-001 proves the final Windows Authenticode policy verifier was absent; its final-tree-first implementation and POSIX/PowerShell workflow contracts pass locally under E-M3-WINDOWS-SIGNATURE-LOCAL-001 and under Node 24 on all six target-native jobs in exact-head run 29387668264 under E-M3-WINDOWS-SIGNATURE-CI-001. Target-native official-Node and preserved-upstream source-signature verification is implemented at `6ef2943de` and locally green under E-M3-WINDOWS-SOURCE-SIGNATURE-LOCAL-001; exact x64/arm64 `Valid` reports are the active gate. Real Apple/SignPath signing, returned production signatures, Gatekeeper/notarization, Defender/WDAC, missing exact-floor snapshots, and native trust remain separately gated. Nothing is published or enabled, and legacy remains the production default.<br>
Last updated: 2026-07-15<br>
Current phase: Milestone 4 / Work Package 3 credential-free release/signing DAG failure contracts — **In progress — 2026-07-15, Codex implementation owner**. Work Package 2's target-native Windows official-Node and preserved-upstream source-signature gate is closed under E-M3-WINDOWS-SOURCE-SIGNATURE-CI-001. Exact-floor gaps and real native signing/trust remain open external gates, so the active package is limited to disconnected fail-closed release-DAG contracts and tests; it may not publish, connect desktop consumers, or enable a tuple. Production/default behavior is unchanged, no bundled-runtime path is enabled, and no artifact is published.<br>
Session checkpoint: **In progress — 2026-07-15, Codex implementation owner** — exact-head artifact jobs 87267322867 and 87267322870 in run [29388734922](https://github.com/stablyai/orca/actions/runs/29388734922) passed target-native Windows source-signature verification and uploaded independently inspected reports under E-M3-WINDOWS-SOURCE-SIGNATURE-CI-001. PR Checks [29388734935](https://github.com/stablyai/orca/actions/runs/29388734935) and Golden E2E [29388734914](https://github.com/stablyai/orca/actions/runs/29388734914) are green at exact head `be32653a7`; the artifact run's only failure is the retained Windows arm64 build-26200-versus-26100 floor gate. E-M4-RELEASE-DAG-LOCAL-RED-001 proves the disconnected release-stage and draft-recovery modules were absent; their implementation and native-workflow test wiring now pass locally under E-M4-RELEASE-DAG-LOCAL-001. Exact-head CI for the new package is the active gate. Real Apple/SignPath signing, returned production signatures, Gatekeeper/notarization, Defender/WDAC, missing exact-floor snapshots, and native trust remain separately gated. Nothing is published or enabled, and legacy remains the production default.<br>
Primary design: [SSH relay GitHub Release plan](./2026-07-14-ssh-relay-github-release-plan.html)<br>
Motivating issues: [#8450](https://github.com/stablyai/orca/issues/8450), [#1693](https://github.com/stablyai/orca/issues/1693)
@@ -64,7 +64,16 @@ same change as the work it records.
E-M2-CONTRACT-001, and E-M2-CI-001. They remain isolated in stacked draft PR
[#8728](https://github.com/stablyai/orca/pull/8728) at implementation commit `b9d80a4cb`; no
deploy/resolver call site is connected and no tuple is enabled.
- Active package: Work Package 2 target-native runtime assembly, archive inspection, executable
- Active package: Work Package 3 credential-free release/signing DAG failure contracts. The package
must model fail-closed build, approval, signing, aggregate, upload, read-back, and recovered-draft
outcomes without credentials, production workflow wiring, publication, desktop consumers, or
tuple enablement. No Milestone 4 box is checked until an implemented contract and exact tests exist.
- Completed Work Package 2 gate: target-native Windows source-signature reports from exact-head
artifact jobs 87267322867 and 87267322870 were independently downloaded and matched to their
identities and signing-stage reports under E-M3-WINDOWS-SOURCE-SIGNATURE-CI-001. PR Checks
29388734935 and Golden E2E 29388734914 are green. Exact floors and real native signing/trust remain
open, so Work Package 2 as a whole is not complete and no tuple is enabled.
- Historical Work Package 2 progression: target-native runtime assembly, archive inspection, executable
smoke, SBOM, and provenance only. The Windows x64/arm64 artifact candidate and portability
corrections are implemented through `b6903b220`, with bounded smoke diagnostics in `3aab5aff8`,
explicit PTY smoke settlement in `ddf28eb8d`, and bounded active-resource diagnostics in
@@ -86,7 +95,7 @@ same change as the work it records.
window, exited normally, and uploaded unpublished evidence (E-M3-WINDOWS-CI-001). This package
may produce test artifacts but must not publish, resolve, transfer, install, launch, or enable
them.
- Active evidence gate: the immutable Node v24.18.0 contract, pinned release key, bounded verifier,
- Historical evidence progression: the immutable Node v24.18.0 contract, pinned release key, bounded verifier,
and artifact-only CLI are locally green under E-M3-NODE-RED-001 and E-M3-NODE-PROVENANCE-001.
E-M3-RUNTIME-LOCAL-001 additionally proves one unpublished Linux arm64 glibc assembly, exact-tree
archive inspection, deterministic repack, bundled Node 24.18.0 execution, real patched PTY, and
@@ -176,12 +185,11 @@ same change as the work it records.
per-target opt-in selects bundled-preferred behavior, and implementing the setting does not
authorize default-on rollout or legacy removal (E-M1-ROLLOUT-DECISION-001).
- Legacy fallback removal: not authorized.
- Next required action: implement purpose-named oldest-supported-baseline verification and its
artifact-only workflow cells. Use GitHub-hosted native runners where they satisfy the declared
floor, add static libc/libstdc++/kernel eligibility oracles where execution alone is insufficient,
and keep unavailable macOS/Windows snapshot and native-trust cells explicitly open rather than
substituting newer runners. Preserve the artifact-only boundary, legacy/default path, and every
tuple's disabled state.
- Next required action: implement and prove the disconnected credential-free release/signing DAG
failure contract, including timeout, retry exhaustion, absent/denied approval, signing failure,
incomplete output, and recovered-draft cases. Keep real native-signing credentials, endpoint trust,
missing exact-floor snapshots, production workflow wiring, publication, desktop consumers, and
every tuple's enabled state outside this slice.
## Non-Negotiable Invariants
@@ -1445,16 +1453,16 @@ Baseline measurements must be captured before product behavior changes.
Update status and evidence as work begins. Do not combine these into one large behavior switch.
| Work package | Scope | Default behavior change | Status | PR/evidence |
| ------------------------- | ------------------------------------------------------------------------------------------ | --------------------------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| 0. #8450 legacy fix | Coherent Node/npm selection and live repro | Fixes legacy selection only | Complete and CI-green in draft PR #8724 | E-M0-UNIT-002, E-M0-LIVE-002, E-M0-STATIC-002, E-M0-PR-001, E-M0-CI-001 |
| 1. Contract and selectors | Manifest schema, identity, platform/libc selection, hostile inputs | None | Complete and CI-green in draft PR #8728 | `b9d80a4cb`; E-M2-RED-001, E-M2-CONTRACT-001, E-M2-CI-001 |
| 2. Runtime builds | Per-tuple assembly, native smoke, SBOM/provenance/signing | None | Draft PR #8741; native closure green; metadata local; trust pending | `26bbd7b67`; E-M3-RUNTIME-CLOSURE-CI-001, E-M3-METADATA-LOCAL-001 |
| 3. Release publication | Prerequisite DAG, embedded manifest, draft upload/read-back gates | Asset-only | Not started | — |
| 4. Desktop resolver/cache | Verified download, extraction, cache, offline behavior | None/forced mode only | Not started | — |
| 5. Transfer/install | Bounded transports, structured sentinel, bundled launch behind per-target Beta/forced mode | Per-target opt-in only | Not started | — |
| 6. Fallback/diagnostics | Abort-and-join state machine, mode isolation, reason codes, target-mode configuration/UI | Per-target Beta only | Not started | — |
| 7. Live gates/rollout | Matrix, security, performance, release promotion | Per-tuple staged | Not started | — |
| Work package | Scope | Default behavior change | Status | PR/evidence |
| ------------------------- | ------------------------------------------------------------------------------------------ | --------------------------- | --------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| 0. #8450 legacy fix | Coherent Node/npm selection and live repro | Fixes legacy selection only | Complete and CI-green in draft PR #8724 | E-M0-UNIT-002, E-M0-LIVE-002, E-M0-STATIC-002, E-M0-PR-001, E-M0-CI-001 |
| 1. Contract and selectors | Manifest schema, identity, platform/libc selection, hostile inputs | None | Complete and CI-green in draft PR #8728 | `b9d80a4cb`; E-M2-RED-001, E-M2-CONTRACT-001, E-M2-CI-001 |
| 2. Runtime builds | Per-tuple assembly, native smoke, SBOM/provenance/signing | None | Draft PR #8741; native build/source trust green; real signing/trust pending | `be32653a7`; E-M3-METADATA-CI-001, E-M3-WINDOWS-SOURCE-SIGNATURE-CI-001 |
| 3. Release publication | Prerequisite DAG, embedded manifest, draft upload/read-back gates | Asset-only | **In progress — 2026-07-15, Codex implementation owner** | E-M4-RELEASE-DAG-LOCAL-001; exact-head CI pending |
| 4. Desktop resolver/cache | Verified download, extraction, cache, offline behavior | None/forced mode only | Not started | — |
| 5. Transfer/install | Bounded transports, structured sentinel, bundled launch behind per-target Beta/forced mode | Per-target opt-in only | Not started | — |
| 6. Fallback/diagnostics | Abort-and-join state machine, mode isolation, reason codes, target-mode configuration/UI | Per-target Beta only | Not started | — |
| 7. Live gates/rollout | Matrix, security, performance, release promotion | Per-tuple staged | Not started | — |
Every PR must document:
@@ -1514,6 +1522,11 @@ focused commands as their scripts/tests are introduced.
- [x] `pnpm exec vitest run --config config/vitest.config.ts config/scripts/ssh-relay-*.test.mjs` (E-M3-RUNTIME-CLOSURE-LOCAL-001; 68 local artifact-contract tests plus static reuse of six prior candidate archives; new target-native builder execution remains pending)
- [x] `pnpm exec vitest run --config config/vitest.config.ts config/scripts/ssh-relay-*.test.mjs && pnpm run typecheck && pnpm run lint && pnpm run check:max-lines-ratchet` (E-M3-METADATA-LOCAL-001; 76 local artifact-contract tests, typecheck, full lint, reliability gates, localization gates, and max-lines ratchet; native metadata/toolchain proof remains pending)
### Milestone 4 commands added
- [x] `pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1 config/scripts/ssh-relay-runtime-release-stage-gate.test.mjs config/scripts/ssh-relay-runtime-draft-recovery.test.mjs` (E-M4-RELEASE-DAG-LOCAL-RED-001, E-M4-RELEASE-DAG-LOCAL-001; disconnected credential-free stage/recovery contract only)
- [x] `pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1 config/scripts/ssh-relay-runtime-release-stage-gate.test.mjs config/scripts/ssh-relay-runtime-draft-recovery.test.mjs config/scripts/ssh-relay-runtime-workflow.test.mjs` (E-M4-RELEASE-DAG-LOCAL-001; static native-job wiring only, no real release/signing execution)
### Commands/scripts that must be added or formally identified
- [x] Manifest/schema/identity/signature/selector unit-test command. (E-M2-CONTRACT-001)
@@ -1521,8 +1534,9 @@ focused commands as their scripts/tests are introduced.
- [x] Per-tuple POSIX archive inspection and native smoke command. (E-M3-RUNTIME-LOCAL-001; Windows command remains open)
- [ ] Embedded-manifest extraction/comparison command for every packaged app.
- [ ] Draft release relay-asset completeness/read-back command.
- [ ] Release-DAG failure rehearsal covering native signing, aggregate, timeout/retry/manual approval,
and recovered draft behavior.
- [ ] Live release-DAG failure rehearsal covering native signing, aggregate, timeout/retry/manual
approval, and recovered draft behavior. The disconnected contract is implemented under
E-M4-RELEASE-DAG-LOCAL-001; real workflow/service evidence remains open.
- [ ] Hostile-archive and cache fault suite.
- [ ] Full-size transfer memory/cancellation suite for SFTP, POSIX system SSH, and Windows system SSH.
- [ ] Remote primitive/binary-fidelity suite for missing commands, BusyBox variants, no-tar POSIX,
@@ -8662,6 +8676,175 @@ diff --check`.
runner logs, and keep returned-byte/native-trust boxes unchecked until the separately gated real
SignPath and endpoint checks pass.
### E-M3-WINDOWS-SOURCE-SIGNATURE-CI-001 — Native Windows source signatures match retained identity
- Date: 2026-07-15
- Owner: Codex implementation owner
- Source: exact head `be32653a7b77eeaed168d91b790fc2e006b438db`; artifact run
[29388734922](https://github.com/stablyai/orca/actions/runs/29388734922), PR Checks
[29388734935](https://github.com/stablyai/orca/actions/runs/29388734935), and Golden E2E
[29388734914](https://github.com/stablyai/orca/actions/runs/29388734914).
- Native jobs:
- `win32-x64`: job
[87267322870](https://github.com/stablyai/orca/actions/runs/29388734922/job/87267322870),
GitHub-hosted `windows-2022`, resolved `win22` image `20260706.237.1`, native `X64`,
runner `GitHub Actions 1000055156`; PASS in 5 minutes 23 seconds. Its combined two-build,
verify, smoke, compare, signing-stage, and source-signature step ran for 3 minutes 45 seconds.
- `win32-arm64`: job
[87267322867](https://github.com/stablyai/orca/actions/runs/29388734922/job/87267322867),
GitHub-hosted `windows-11-arm`, resolved `win11-arm64` image `20260706.102.1`, native `ARM64`,
runner `GitHub Actions 1000055154`; PASS in 11 minutes 7 seconds. Its combined two-build,
verify, smoke, compare, signing-stage, and source-signature step ran for 5 minutes 30 seconds.
- The workflow does not time the three source-signature probes separately. Each probe retains the
implemented 30-second process timeout and 64-KiB output bound; the combined step timings above
are the narrowest exact native timing available from this run.
- Artifact retrieval and identity command:
```sh
gh run download 29388734922 --repo stablyai/orca \
--name ssh-relay-runtime-win32-x64 --dir <exclusive-x64-directory>
gh run download 29388734922 --repo stablyai/orca \
--name ssh-relay-runtime-win32-arm64 --dir <exclusive-arm64-directory>
node --input-type=module -e '<bounded identity/signing-report comparison>' <artifact-directory>
shasum -a 256 <artifact-directory>/*.source-signatures.json
wc -c <artifact-directory>/*.source-signatures.json
```
- Result: PASS. Each artifact contains exactly one identity, archive, SPDX statement, provenance
statement, signing-stage report, and source-signature report. The bounded comparison requires one
report, exact tuple/content identity, exactly three verified files, one `official-node`, two
`preserved-upstream`, identity-entry hash equality for every verified file, and exact preserved
subject/thumbprint equality with the authenticated signing-stage report.
- Retained report identities:
- x64 report: 1,401 bytes, SHA-256
`9ceb6b3dadf85ea7d338dbd11e1397e58b83455842378f3465ccb945b5ec0805`, source content ID
`sha256:7ddad668780ce5b2592d86afcebf9d897172bdf07c618ae238b5d51eebfe1596`.
- arm64 report: 1,403 bytes, SHA-256
`5a63a7f31d64cc6a8b825461e9729f59f0176d8d03293fa0ce2c05df39734d22`, source content ID
`sha256:2955cec7f22447a1303dad548df6c2fa2470b62ba1d70924b8b169e718a7701e`.
- Exact native signer evidence:
- Both official Node files report `Valid` with subject
`CN=OpenJS Foundation, O=OpenJS Foundation, L=San Francisco, S=California, C=US` and thumbprint
`CECD9673E955CA766047DD43706D31E48A6BD3B5`. The x64 Node hash is
`sha256:9a4eb5f1c29c6a2e93852ead46b999e284a6a5ca8bab4d4e241d587d025a52de`; arm64 is
`sha256:c7225670c3f477778e18c43a55867f7a0d76468221245e5981ab80eb953c8102`.
- Every preserved file reports `Valid` with subject
`CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US`. x64
`OpenConsole.exe` and `conpty.dll` use thumbprint
`3F56A45111684D454E231CFDC4DA5C8D370F9816`. Arm64 `OpenConsole.exe` uses
`F5877012FBD62FABCBDC8D8CEE9C9585BA30DF79`; arm64 `conpty.dll` uses
`3F56A45111684D454E231CFDC4DA5C8D370F9816`.
- Concurrent regression result: PR Checks and both Golden E2E jobs completed successfully at the
exact head. The artifact run concluded `failure` solely because its separate Windows arm64
oldest-baseline job observed `10.0.26200` rather than the exact required build `26100`, after the
runtime itself passed bundled Node, PTY, watcher, and settlement smoke in 8,275.5554 ms with a
49,852,416-byte RSS measurement. This is the retained
E-M3-WINDOWS-ARM64-BASELINE-CI-RED-001 gap, not a source-signature failure.
- Does not prove: real SignPath returned Orca signatures, final-tree Authenticode trust, Defender or
WDAC policy, Windows arm64 build 26100, macOS trust, draft release aggregation/read-back, SSH
transfer/install, fallback/performance, or an enabled tuple. Nothing was published or connected to
production behavior.
### E-M4-RELEASE-DAG-LOCAL-RED-001 — Missing release-stage and draft-recovery gates fail imports
- Date: 2026-07-15
- Owner: Codex implementation owner
- Source: exact implementation base `be32653a7b77eeaed168d91b790fc2e006b438db` plus the two new
uncommitted purpose-named test files.
- Command:
```sh
pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1 \
config/scripts/ssh-relay-runtime-release-stage-gate.test.mjs \
config/scripts/ssh-relay-runtime-draft-recovery.test.mjs
```
- Result: expected RED in 346 ms. Both suites fail before collecting tests with
`ERR_MODULE_NOT_FOUND` for `ssh-relay-runtime-release-stage-gate.mjs` and
`ssh-relay-runtime-draft-recovery.mjs`.
- Oracle proved: the current worktree has no reusable contract that requires a complete immutable
build → native-signing approval/return → aggregate/manifest-signature → upload → authenticated
read-back chain, and no contract that permits same-draft recovery only for exact already-uploaded
runtime bytes.
- Does not prove: implementation, workflow wiring, GitHub release behavior, signing-service behavior,
a real draft recovery, publication, desktop embedding, SSH behavior, or an enabled tuple.
- Correction: implement bounded exact-stage validation and hash/size-bound same-draft reuse as
disconnected credential-free modules; retain every production/default and tuple state unchanged.
### E-M4-RELEASE-DAG-LOCAL-001 — Fail-closed release stages and same-draft recovery pass locally
- Date: 2026-07-15
- Owner: Codex implementation owner
- Source: uncommitted implementation based on exact head
`be32653a7b77eeaed168d91b790fc2e006b438db`.
- Runner/remote/network: local macOS 26.2 build 25C56 arm64, Node v26.0.0 and pnpm 10.24.0. No
GitHub release, signing service, credential, approval environment, SSH remote, publication, or
production consumer was used. The repository emits its expected Node-24 engine warning.
- Commands:
```sh
node --check config/scripts/ssh-relay-runtime-release-stage-gate.mjs
node --check config/scripts/ssh-relay-runtime-release-stage-gate.test.mjs
node --check config/scripts/ssh-relay-runtime-draft-recovery.mjs
node --check config/scripts/ssh-relay-runtime-draft-recovery.test.mjs
/usr/bin/time -l pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1 \
config/scripts/ssh-relay-runtime-release-stage-gate.test.mjs \
config/scripts/ssh-relay-runtime-draft-recovery.test.mjs
pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1 \
config/scripts/ssh-relay-runtime-release-stage-gate.test.mjs \
config/scripts/ssh-relay-runtime-draft-recovery.test.mjs \
config/scripts/ssh-relay-runtime-workflow.test.mjs
pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1 \
config/scripts/ssh-relay-*.test.mjs
pnpm run typecheck
pnpm run lint
pnpm run check:max-lines-ratchet
pnpm exec oxfmt --check \
.github/workflows/ssh-relay-runtime-artifacts.yml \
config/scripts/ssh-relay-runtime-release-stage-gate.mjs \
config/scripts/ssh-relay-runtime-release-stage-gate.test.mjs \
config/scripts/ssh-relay-runtime-draft-recovery.mjs \
config/scripts/ssh-relay-runtime-draft-recovery.test.mjs \
config/scripts/ssh-relay-runtime-workflow.test.mjs \
docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist.md \
docs/reference/plans/2026-07-14-ssh-relay-github-release-implementation-checklist-summary.md
git diff --check
```
- Result: PASS. The two purpose-named suites pass 2 files/21 tests in 245 ms; `/usr/bin/time -l`
records 0.91 seconds wall time, 131,825,664-byte maximum RSS, zero swaps, and 95,933,720-byte peak
memory footprint for the Vitest process tree. The workflow-inclusive focus passes 3 files/27
tests; the final complete SSH-relay suite passes 33 files/184 tests in 8.52 seconds. All four syntax
checks, typecheck, full lint/reliability/localization/bundled-skill gates, max-lines (355
grandfathered suppressions and no new bypass), focused formatting, and `git diff --check` pass.
Lint emits only existing unrelated warnings.
- Stage oracle: candidate tuples must use exact supported identities; every candidate requires one
bounded successful build, every macOS/Windows candidate requires one single-attempt approved
native-signing return that changes immutable identity, and Linux cannot invent a signing stage.
Aggregate inputs must exactly equal final per-tuple outputs and produce bounded manifest/signature
assets. Upload and authenticated read-back must reproduce the complete ordered hash/size chain.
Missing, duplicate, unexpected, failed, cancelled, timed-out, retry-exhausted, over-budget,
approval-absent, approval-denied, approval-timed-out, input-drifted, incomplete, or byte-drifted
results fail closed.
- Bound policy: build is at most 30 minutes and three attempts; native signing is one attempt and at
most four hours; aggregate is one attempt and 15 minutes; upload and read-back are each at most
three attempts and 15 minutes. Signing is deliberately single-attempt so one approval cannot
silently authorize a second set of bytes after timeout or service failure.
- Recovery oracle: only the same draft tag and exact 40-hex source commit may be resumed. Existing
managed assets are reusable only when name, SHA-256, and non-zero size exactly match expected
immutable output. Changed, empty, duplicate, unexpected managed, published, cross-tag, and
cross-commit states fail closed; unrelated desktop assets are ignored rather than overwritten.
- Workflow oracle: both POSIX and Windows artifact jobs syntax-check and execute the new suites under
the same Node 24 native job families. The workflow retains read-only contents permission and has
no release, signing credential, or publication authority.
- Does not prove: a real native-signing approval/timeout, signing-service retry behavior, a real
aggregate or signed manifest, upload/read-back through GitHub's draft release API, recovered-draft
execution, desktop prerequisites/embedding, native trust, SSH transfer/install, fallback,
performance, or an enabled tuple. Production release workflow wiring remains absent.
- Follow-up: run the contract on all six native jobs at the exact implementation head, then add the
credential-free aggregate-input/read-back implementation without connecting publication or a
desktop consumer.
## Accepted Gaps
No product gap is accepted merely because it appears in this list. Each entry requires explicit
@@ -8719,10 +8902,12 @@ The project is not complete until every applicable item below is checked with ev
## Next Required Action
Provision or select qualifying exact-floor execution for Linux kernel 4.18, macOS 13.5, and Windows
arm64 build 26100 without weakening their oracles; in parallel, implement and prove target-native
macOS/Windows signing and trust as the next independent artifact-only capability. Keep every tuple
disabled and do not connect an artifact consumer until the applicable baseline and trust cells pass.
Run the disconnected credential-free release/signing DAG and draft-recovery contracts on all six
native jobs at the exact implementation head. If green, implement the next artifact-only
aggregate-input/read-back capability without release publication or a desktop consumer. In parallel,
provision qualifying exact-floor execution for Linux kernel 4.18, macOS 13.5, and Windows arm64 build
26100 and real macOS/Windows signing and trust. Keep every tuple disabled until the applicable
baseline and trust cells pass.
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