mirror of
https://github.com/stablyai/orca.git
synced 2026-10-25 16:03:53 +00:00
ci: add protected relay manifest seed signer
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
@@ -166,6 +166,8 @@ jobs:
|
||||
node --check config/scripts/ssh-relay-runtime-manifest-assembly.test.mjs
|
||||
node --check config/scripts/ssh-relay-runtime-manifest-signing-handoff.mjs
|
||||
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-aggregate.mjs
|
||||
node --check config/scripts/ssh-relay-runtime-manifest-aggregate.test.mjs
|
||||
node --check config/scripts/ssh-relay-runtime-manifest-tuple.mjs
|
||||
@@ -212,6 +214,7 @@ jobs:
|
||||
config/scripts/ssh-relay-runtime-draft-readback.test.mjs \
|
||||
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.test.mjs \
|
||||
config/scripts/ssh-relay-runtime-manifest-tuple.test.mjs \
|
||||
config/scripts/ssh-relay-runtime-post-sign-metadata.test.mjs \
|
||||
@@ -578,6 +581,10 @@ jobs:
|
||||
if ($LASTEXITCODE -ne 0) { throw 'runtime manifest signing handoff syntax check failed' }
|
||||
node --check config/scripts/ssh-relay-runtime-manifest-signing-handoff.test.mjs
|
||||
if ($LASTEXITCODE -ne 0) { throw 'runtime manifest signing handoff test syntax check failed' }
|
||||
node --check config/scripts/ssh-relay-runtime-manifest-seed-signing.mjs
|
||||
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-aggregate.mjs
|
||||
if ($LASTEXITCODE -ne 0) { throw 'runtime manifest aggregate syntax check failed' }
|
||||
node --check config/scripts/ssh-relay-runtime-manifest-aggregate.test.mjs
|
||||
@@ -642,6 +649,7 @@ jobs:
|
||||
config/scripts/ssh-relay-runtime-draft-readback.test.mjs `
|
||||
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.test.mjs `
|
||||
config/scripts/ssh-relay-runtime-manifest-tuple.test.mjs `
|
||||
config/scripts/ssh-relay-runtime-post-sign-metadata.test.mjs `
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
import { lstat, mkdir, readFile, realpath, rm, writeFile } from 'node:fs/promises'
|
||||
import { basename, dirname, resolve } from 'node:path'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
|
||||
import nacl from 'tweetnacl'
|
||||
|
||||
import {
|
||||
createSshRelayRuntimeManifestSigningRequest,
|
||||
sshRelayRuntimeManifestKeyId
|
||||
} from './ssh-relay-runtime-manifest-signing-handoff.mjs'
|
||||
|
||||
const REQUEST_FIELDS = [
|
||||
'algorithm',
|
||||
'payloadBase64',
|
||||
'payloadSha256',
|
||||
'payloadSize',
|
||||
'schemaVersion'
|
||||
]
|
||||
const MAX_REQUEST_ARTIFACT_BYTES = 48 * 1024 * 1024
|
||||
const BASE64_PATTERN = /^[A-Za-z0-9+/]+={0,2}$/u
|
||||
|
||||
function assertObject(value, label) {
|
||||
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
||||
throw new Error(`SSH relay runtime manifest seed signing ${label} must be an object`)
|
||||
}
|
||||
}
|
||||
|
||||
function assertExactFields(value, fields, label) {
|
||||
assertObject(value, label)
|
||||
const actual = Object.keys(value).sort()
|
||||
const expected = [...fields].sort()
|
||||
if (actual.length !== expected.length || actual.some((key, index) => key !== expected[index])) {
|
||||
throw new Error(
|
||||
`SSH relay runtime manifest seed signing ${label} has unexpected or missing fields`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
function decodeCanonicalBase64(value, label) {
|
||||
if (typeof value !== 'string' || !BASE64_PATTERN.test(value)) {
|
||||
throw new Error(`SSH relay runtime manifest seed signing ${label} is not canonical base64`)
|
||||
}
|
||||
const bytes = Buffer.from(value, 'base64')
|
||||
if (bytes.length === 0 || bytes.toString('base64') !== value) {
|
||||
throw new Error(`SSH relay runtime manifest seed signing ${label} is not canonical base64`)
|
||||
}
|
||||
return bytes
|
||||
}
|
||||
|
||||
function validateInMemoryRequest(request) {
|
||||
assertExactFields(
|
||||
request,
|
||||
['algorithm', 'canonicalBytes', 'payloadSha256', 'payloadSize'],
|
||||
'request'
|
||||
)
|
||||
if (!Buffer.isBuffer(request.canonicalBytes) && !(request.canonicalBytes instanceof Uint8Array)) {
|
||||
throw new Error('SSH relay runtime manifest seed signing request payload must be bytes')
|
||||
}
|
||||
const expected = createSshRelayRuntimeManifestSigningRequest(request.canonicalBytes)
|
||||
if (
|
||||
request.algorithm !== expected.algorithm ||
|
||||
request.payloadSha256 !== expected.payloadSha256 ||
|
||||
request.payloadSize !== expected.payloadSize
|
||||
) {
|
||||
throw new Error('SSH relay runtime manifest seed signing request binding is inconsistent')
|
||||
}
|
||||
return expected
|
||||
}
|
||||
|
||||
export function encodeSshRelayRuntimeManifestSigningRequestArtifact(request) {
|
||||
const parsed = validateInMemoryRequest(request)
|
||||
return {
|
||||
schemaVersion: 1,
|
||||
algorithm: parsed.algorithm,
|
||||
payloadBase64: parsed.canonicalBytes.toString('base64'),
|
||||
payloadSha256: parsed.payloadSha256,
|
||||
payloadSize: parsed.payloadSize
|
||||
}
|
||||
}
|
||||
|
||||
export function decodeSshRelayRuntimeManifestSigningRequestArtifact(artifact) {
|
||||
assertExactFields(artifact, REQUEST_FIELDS, 'request artifact')
|
||||
if (artifact.schemaVersion !== 1 || artifact.algorithm !== 'ed25519-v1') {
|
||||
throw new Error(
|
||||
'SSH relay runtime manifest seed signing request artifact schema is unsupported'
|
||||
)
|
||||
}
|
||||
const canonicalBytes = decodeCanonicalBase64(artifact.payloadBase64, 'request payload')
|
||||
const request = createSshRelayRuntimeManifestSigningRequest(canonicalBytes)
|
||||
if (
|
||||
artifact.payloadSize !== request.payloadSize ||
|
||||
artifact.payloadSha256 !== request.payloadSha256
|
||||
) {
|
||||
throw new Error(
|
||||
'SSH relay runtime manifest seed signing request artifact binding is inconsistent'
|
||||
)
|
||||
}
|
||||
return request
|
||||
}
|
||||
|
||||
function decodeSeed(seedBase64) {
|
||||
const seed = decodeCanonicalBase64(seedBase64, 'seed')
|
||||
if (seed.length !== nacl.sign.seedLength) {
|
||||
throw new Error('SSH relay runtime manifest signing seed must contain exactly 32 bytes')
|
||||
}
|
||||
return seed
|
||||
}
|
||||
|
||||
export function signSshRelayRuntimeManifestRequest({ requestArtifact, seedBase64 }) {
|
||||
const request = decodeSshRelayRuntimeManifestSigningRequestArtifact(requestArtifact)
|
||||
const pair = nacl.sign.keyPair.fromSeed(decodeSeed(seedBase64))
|
||||
return {
|
||||
keyId: sshRelayRuntimeManifestKeyId(pair.publicKey),
|
||||
signature: Buffer.from(nacl.sign.detached(request.canonicalBytes, pair.secretKey)).toString(
|
||||
'base64'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export async function readSshRelayRuntimeManifestSigningRequestArtifact(path) {
|
||||
const metadata = await lstat(path)
|
||||
if (
|
||||
!metadata.isFile() ||
|
||||
metadata.isSymbolicLink() ||
|
||||
metadata.size <= 0 ||
|
||||
metadata.size > MAX_REQUEST_ARTIFACT_BYTES
|
||||
) {
|
||||
throw new Error('SSH relay runtime manifest signing request must be a bounded regular file')
|
||||
}
|
||||
let artifact
|
||||
try {
|
||||
artifact = JSON.parse(await readFile(path, 'utf8'))
|
||||
} catch (error) {
|
||||
throw new Error(`SSH relay runtime manifest signing request is invalid JSON: ${error.message}`)
|
||||
}
|
||||
decodeSshRelayRuntimeManifestSigningRequestArtifact(artifact)
|
||||
return artifact
|
||||
}
|
||||
|
||||
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 signing output parent must be a real directory')
|
||||
}
|
||||
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 signing requires an exclusive absent output directory'
|
||||
)
|
||||
}
|
||||
|
||||
export async function writeSshRelayRuntimeManifestSigningResult({
|
||||
requestArtifact,
|
||||
seedBase64,
|
||||
outputDirectory
|
||||
}) {
|
||||
const result = signSshRelayRuntimeManifestRequest({ requestArtifact, seedBase64 })
|
||||
const output = await exclusiveOutputDirectory(outputDirectory)
|
||||
let created = false
|
||||
try {
|
||||
await mkdir(output, { mode: 0o700 })
|
||||
created = true
|
||||
// Why: the protected job may return only the authenticated key identity and detached signature.
|
||||
await writeFile(joinResultPath(output), `${JSON.stringify(result)}\n`, {
|
||||
flag: 'wx',
|
||||
mode: 0o600
|
||||
})
|
||||
return result
|
||||
} catch (error) {
|
||||
if (created) {
|
||||
await rm(output, { recursive: true, force: true })
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
function joinResultPath(output) {
|
||||
return resolve(output, 'signing-result.json')
|
||||
}
|
||||
|
||||
export function parseSshRelayRuntimeManifestSeedSigningArguments(argv) {
|
||||
const options = {}
|
||||
const fields = new Map([
|
||||
['--request', 'requestPath'],
|
||||
['--output-directory', 'outputDirectory']
|
||||
])
|
||||
for (let index = 0; index < argv.length; index += 2) {
|
||||
const field = fields.get(argv[index])
|
||||
const value = argv[index + 1]
|
||||
if (!field || !value || value.startsWith('--') || options[field]) {
|
||||
throw new Error(`Invalid SSH relay runtime manifest seed signing argument: ${argv[index]}`)
|
||||
}
|
||||
options[field] = resolve(value)
|
||||
}
|
||||
for (const field of fields.values()) {
|
||||
if (!options[field]) {
|
||||
throw new Error(`Missing SSH relay runtime manifest seed signing argument: ${field}`)
|
||||
}
|
||||
}
|
||||
return options
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const options = parseSshRelayRuntimeManifestSeedSigningArguments(process.argv.slice(2))
|
||||
const requestArtifact = await readSshRelayRuntimeManifestSigningRequestArtifact(
|
||||
options.requestPath
|
||||
)
|
||||
const result = await writeSshRelayRuntimeManifestSigningResult({
|
||||
requestArtifact,
|
||||
seedBase64: process.env.SSH_RELAY_RUNTIME_MANIFEST_SEED,
|
||||
outputDirectory: options.outputDirectory
|
||||
})
|
||||
process.stdout.write(`${JSON.stringify({ keyId: result.keyId })}\n`)
|
||||
}
|
||||
|
||||
if (process.argv[1] && pathToFileURL(resolve(process.argv[1])).href === import.meta.url) {
|
||||
main().catch((error) => {
|
||||
process.stderr.write(
|
||||
`SSH relay runtime manifest seed signing failed: ${error.stack ?? error}\n`
|
||||
)
|
||||
process.exitCode = 1
|
||||
})
|
||||
}
|
||||
|
||||
export const SSH_RELAY_RUNTIME_MANIFEST_SEED_SIGNING_LIMITS = Object.freeze({
|
||||
maximumRequestArtifactBytes: MAX_REQUEST_ARTIFACT_BYTES
|
||||
})
|
||||
@@ -0,0 +1,152 @@
|
||||
import { mkdtemp, readFile, rm, 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 { assembleCanonicalSshRelayRuntimeManifest } from './ssh-relay-runtime-manifest-assembly.mjs'
|
||||
import {
|
||||
createSshRelayRuntimeManifestSigningRequest,
|
||||
finalizeSshRelayRuntimeManifestSigningHandoff,
|
||||
sshRelayRuntimeManifestKeyId
|
||||
} from './ssh-relay-runtime-manifest-signing-handoff.mjs'
|
||||
import {
|
||||
decodeSshRelayRuntimeManifestSigningRequestArtifact,
|
||||
encodeSshRelayRuntimeManifestSigningRequestArtifact,
|
||||
signSshRelayRuntimeManifestRequest,
|
||||
writeSshRelayRuntimeManifestSigningResult
|
||||
} from './ssh-relay-runtime-manifest-seed-signing.mjs'
|
||||
|
||||
const temporaryDirectories = []
|
||||
const seed = Uint8Array.from({ length: 32 }, (_, index) => index)
|
||||
const seedBase64 = Buffer.from(seed).toString('base64')
|
||||
const keyPair = nacl.sign.keyPair.fromSeed(seed)
|
||||
|
||||
function request() {
|
||||
const { signatures: _signatures, ...unsigned } = createSshRelayArtifactTestManifest()
|
||||
const canonical = assembleCanonicalSshRelayRuntimeManifest(unsigned).canonicalBytes
|
||||
return createSshRelayRuntimeManifestSigningRequest(canonical)
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(
|
||||
temporaryDirectories.splice(0).map((path) => rm(path, { recursive: true, force: true }))
|
||||
)
|
||||
})
|
||||
|
||||
describe('SSH relay runtime protected manifest seed signing', () => {
|
||||
it('round-trips a bounded canonical request and returns only key ID plus signature', () => {
|
||||
const source = request()
|
||||
const artifact = encodeSshRelayRuntimeManifestSigningRequestArtifact(source)
|
||||
const decoded = decodeSshRelayRuntimeManifestSigningRequestArtifact(artifact)
|
||||
const result = signSshRelayRuntimeManifestRequest({ requestArtifact: artifact, seedBase64 })
|
||||
|
||||
expect(decoded).toEqual(source)
|
||||
expect(Object.keys(artifact).sort()).toEqual([
|
||||
'algorithm',
|
||||
'payloadBase64',
|
||||
'payloadSha256',
|
||||
'payloadSize',
|
||||
'schemaVersion'
|
||||
])
|
||||
expect(result).toEqual({
|
||||
keyId: sshRelayRuntimeManifestKeyId(keyPair.publicKey),
|
||||
signature: Buffer.from(nacl.sign.detached(source.canonicalBytes, keyPair.secretKey)).toString(
|
||||
'base64'
|
||||
)
|
||||
})
|
||||
expect(
|
||||
finalizeSshRelayRuntimeManifestSigningHandoff({
|
||||
request: decoded,
|
||||
signingResults: [result],
|
||||
acceptedKeys: [{ keyId: result.keyId, publicKey: keyPair.publicKey }]
|
||||
}).manifest.signatures
|
||||
).toEqual([{ algorithm: 'ed25519-v1', ...result }])
|
||||
})
|
||||
|
||||
it.each([
|
||||
['', /seed/i],
|
||||
['not-base64', /seed|base64/i],
|
||||
[`${seedBase64}\n`, /seed|base64/i],
|
||||
[Buffer.alloc(31).toString('base64'), /32 bytes|seed/i],
|
||||
[Buffer.alloc(33).toString('base64'), /32 bytes|seed/i]
|
||||
])('rejects a malformed or non-canonical seed without a result', (candidate, message) => {
|
||||
expect(() =>
|
||||
signSshRelayRuntimeManifestRequest({
|
||||
requestArtifact: encodeSshRelayRuntimeManifestSigningRequestArtifact(request()),
|
||||
seedBase64: candidate
|
||||
})
|
||||
).toThrow(message)
|
||||
})
|
||||
|
||||
it('rejects request field, size, hash, canonical-byte, and base64 drift', () => {
|
||||
const valid = encodeSshRelayRuntimeManifestSigningRequestArtifact(request())
|
||||
const cases = [
|
||||
{ ...valid, extra: true },
|
||||
{ ...valid, algorithm: 'rsa-v1' },
|
||||
{ ...valid, payloadSize: valid.payloadSize + 1 },
|
||||
{ ...valid, payloadSha256: `sha256:${'f'.repeat(64)}` },
|
||||
{ ...valid, payloadBase64: `${valid.payloadBase64}\n` },
|
||||
{ ...valid, payloadBase64: Buffer.from('{}').toString('base64'), payloadSize: 2 }
|
||||
]
|
||||
for (const artifact of cases) {
|
||||
expect(() =>
|
||||
signSshRelayRuntimeManifestRequest({ requestArtifact: artifact, seedBase64 })
|
||||
).toThrow()
|
||||
}
|
||||
})
|
||||
|
||||
it('writes only an exclusive bounded result and removes partial output on failure', async () => {
|
||||
const root = await mkdtemp(join(tmpdir(), 'orca-runtime-manifest-seed-signing-'))
|
||||
temporaryDirectories.push(root)
|
||||
const outputDirectory = join(root, 'result')
|
||||
const result = await writeSshRelayRuntimeManifestSigningResult({
|
||||
requestArtifact: encodeSshRelayRuntimeManifestSigningRequestArtifact(request()),
|
||||
seedBase64,
|
||||
outputDirectory
|
||||
})
|
||||
expect(
|
||||
JSON.parse(await readFile(join(outputDirectory, 'signing-result.json'), 'utf8'))
|
||||
).toEqual(result)
|
||||
await expect(
|
||||
writeSshRelayRuntimeManifestSigningResult({
|
||||
requestArtifact: encodeSshRelayRuntimeManifestSigningRequestArtifact(request()),
|
||||
seedBase64,
|
||||
outputDirectory
|
||||
})
|
||||
).rejects.toThrow(/exclusive|absent/i)
|
||||
|
||||
const failed = join(root, 'failed')
|
||||
await expect(
|
||||
writeSshRelayRuntimeManifestSigningResult({
|
||||
requestArtifact: { invalid: true },
|
||||
seedBase64,
|
||||
outputDirectory: failed
|
||||
})
|
||||
).rejects.toThrow()
|
||||
await expect(readFile(join(failed, 'signing-result.json'))).rejects.toMatchObject({
|
||||
code: 'ENOENT'
|
||||
})
|
||||
})
|
||||
|
||||
it('rejects a symlinked request path before reading CLI input', async () => {
|
||||
const root = await mkdtemp(join(tmpdir(), 'orca-runtime-manifest-seed-signing-'))
|
||||
temporaryDirectories.push(root)
|
||||
const target = join(root, 'request.json')
|
||||
const linked = join(root, 'linked.json')
|
||||
await writeFile(
|
||||
target,
|
||||
JSON.stringify(encodeSshRelayRuntimeManifestSigningRequestArtifact(request()))
|
||||
)
|
||||
await expect(
|
||||
import('node:fs/promises').then(({ symlink }) => symlink(target, linked))
|
||||
).resolves.toBeUndefined()
|
||||
const { readSshRelayRuntimeManifestSigningRequestArtifact } =
|
||||
await import('./ssh-relay-runtime-manifest-seed-signing.mjs')
|
||||
await expect(readSshRelayRuntimeManifestSigningRequestArtifact(linked)).rejects.toThrow(
|
||||
/regular file|symlink/i
|
||||
)
|
||||
})
|
||||
})
|
||||
+4
@@ -240,6 +240,10 @@ complete a box.
|
||||
hash-bound descriptors/receipts. The active slice is the callable, disconnected aggregate and
|
||||
protected Ed25519-signing workflow contract. The environment/seed are not provisioned, so live
|
||||
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.
|
||||
- [ ] 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.
|
||||
|
||||
+82
-9
@@ -9,7 +9,7 @@ work; keep exact commands, runner identities, hashes, metrics, and residual gaps
|
||||
Date created: 2026-07-14<br>
|
||||
Last updated: 2026-07-15<br>
|
||||
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.<br>
|
||||
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 passes. PR Checks attempt 1 exposed one unrelated terminal-routing assertion after 29,944 tests passed; the focused test passes locally and exact-head attempt 2 passes all 29,945 tests, unpacked build, and packaged CLI smoke under E-M4-LINUX-FINALIZATION-PR-CHECKS-RED-001 and E-M4-LINUX-FINALIZATION-PR-CHECKS-001. 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.<br>
|
||||
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.<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)
|
||||
|
||||
@@ -10704,6 +10704,78 @@ through command-finished foreground confirmation` receives `csi-u` instead of `a
|
||||
- Follow-up: checkpoint the Linux finalization evidence and start the disconnected aggregate and
|
||||
protected manifest-signing workflow RED.
|
||||
|
||||
### E-M4-PROTECTED-MANIFEST-WORKFLOW-LOCAL-RED-001 — Callable protected signing workflow is absent
|
||||
|
||||
- Date: 2026-07-15
|
||||
- Owner: Codex implementation owner
|
||||
- Source: uncommitted purpose-named test atop pushed head
|
||||
`e5dfffaaa2df55b221c5ee30699ff8fe814b91aa`; draft PR #8741.
|
||||
- Runner/remote/network: local macOS 26.2 arm64, Node v26.0.0 and pnpm 10.24.0. Static repository
|
||||
workflow-source read only; no Actions runner, environment approval, secret, signer, artifact
|
||||
download, release, desktop consumer, SSH host, or enabled tuple.
|
||||
- Command:
|
||||
`/usr/bin/time -l pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1 config/scripts/ssh-relay-runtime-manifest-signing-workflow.test.mjs`.
|
||||
- Result: expected FAIL, 1 file / 1 test in 182 ms Vitest / 0.89 seconds wall,
|
||||
131,743,744-byte maximum RSS, 95,966,656-byte peak footprint, zero swaps. The only failure is
|
||||
`ENOENT` for `.github/workflows/ssh-relay-runtime-manifest-signing.yml`.
|
||||
- Seed-signer prerequisite RED:
|
||||
`/usr/bin/time -l pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1 config/scripts/ssh-relay-runtime-manifest-seed-signing.test.mjs`
|
||||
— expected FAIL before collection because
|
||||
`config/scripts/ssh-relay-runtime-manifest-seed-signing.mjs` is absent; 196 ms Vitest / 0.90
|
||||
seconds wall, 132,022,272-byte maximum RSS, 96,228,776-byte peak footprint, zero swaps. The test
|
||||
defines canonical request serialization, exact 32-byte base64 seed handling, signature-only
|
||||
output, request/seed drift rejection, exclusive output cleanup, and symlink rejection.
|
||||
- Oracle proved: no callable workflow currently enforces the required three-stage boundary: exact
|
||||
six-artifact credential-free preparation; one protected `relay-runtime-manifest-signing` job with
|
||||
the sole seed reference and signature-only output; then credential-free reconstruction and final
|
||||
verification. The RED also requires SHA-pinned actions, strict timeouts, no wildcard artifact
|
||||
merge, read-only permissions, and complete release/desktop/rehearsal disconnection.
|
||||
- Does not prove: implementation, signer seed validation, file-based prepare/finalize behavior,
|
||||
Actions execution, environment protection, real signatures, publication, desktop embedding, SSH
|
||||
behavior, or an enabled tuple.
|
||||
- Follow-up: implement the seed signer and exclusive filesystem prepare/finalize commands with
|
||||
hostile-input tests, then add the callable workflow and make this contract green without
|
||||
connecting any consumer.
|
||||
|
||||
### E-M4-PROTECTED-MANIFEST-SEED-LOCAL-001 — Protected seed signer passes locally
|
||||
|
||||
- Date: 2026-07-15
|
||||
- Owner: Codex implementation owner
|
||||
- Source: local implementation atop pushed head `e5dfffaaa2df55b221c5ee30699ff8fe814b91aa`;
|
||||
draft PR #8741.
|
||||
- Runner/remote/network: local macOS 26.2 arm64, Node v26.0.0 and pnpm 10.24.0. Test-only in-memory
|
||||
Ed25519 seeds and local temporary files; no GitHub Environment, Actions secret, release, desktop
|
||||
consumer, publication, SSH host, or enabled tuple.
|
||||
- Focused command:
|
||||
`/usr/bin/time -l pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1 config/scripts/ssh-relay-runtime-manifest-seed-signing.test.mjs config/scripts/ssh-relay-runtime-manifest-signing-handoff.test.mjs config/scripts/ssh-relay-runtime-manifest-assembly.test.mjs`
|
||||
— PASS, 3 files / 20 tests in 638 ms Vitest / 1.30 seconds wall, 188,612,608-byte maximum RSS,
|
||||
96,163,336-byte peak footprint, zero swaps.
|
||||
- Broad release command excluding the deliberately still-red workflow-source test:
|
||||
`/usr/bin/time -l pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1 $(rg --files config/scripts | rg '/ssh-relay.*\\.test\\.mjs$' | rg -v 'ssh-relay-runtime-manifest-signing-workflow\\.test\\.mjs$')`
|
||||
— PASS, 49 files / 255 tests in 8.54 seconds Vitest / 9.46 seconds wall,
|
||||
188,858,368-byte maximum RSS, 96,523,568-byte peak footprint, zero swaps. The unfiltered 50-file
|
||||
run passes the same 49 files / 255 tests and fails only the recorded missing-workflow RED.
|
||||
- Desktop parity:
|
||||
`/usr/bin/time -l pnpm exec vitest run --config config/vitest.config.ts --maxWorkers=1 src/main/ssh/ssh-relay-artifact-schema.test.ts src/main/ssh/ssh-relay-manifest-signature.test.ts src/main/ssh/ssh-relay-release-asset.test.ts`
|
||||
— PASS, 3 files / 48 tests in 493 ms Vitest / 1.12 seconds wall, 131,858,432-byte maximum RSS,
|
||||
96,032,120-byte peak footprint, zero swaps.
|
||||
- Static results: `node --check`, focused `oxlint`, and focused `oxfmt --check` pass. `pnpm run
|
||||
typecheck` passes in 1.88 seconds wall. Full `pnpm run lint` passes in 9.26 seconds wall with all 41
|
||||
reliability gates, the 355-entry max-lines ratchet, bundled-skill, localization catalog/parity,
|
||||
and localization coverage gates; all 26 warnings are in untouched existing files.
|
||||
- Oracle proved: request artifacts contain only the exact canonical payload plus algorithm/hash/size
|
||||
bindings; malformed fields, noncanonical base64, payload drift, and noncanonical manifest bytes
|
||||
fail. Only a canonical base64 32-byte seed is accepted. Output contains exactly key ID plus the
|
||||
detached 64-byte signature, is created in an exclusive directory, and is removed on failure.
|
||||
Symlinked request files are rejected. Both POSIX and Windows native artifact contract families now
|
||||
syntax-check and run the purpose suite without exposing a secret.
|
||||
- Does not prove: a real GitHub Environment or seed, reviewer approval, the filesystem aggregate
|
||||
prepare/finalize boundary, the callable workflow, Actions execution, publication, desktop
|
||||
embedding, SSH behavior, or an enabled tuple.
|
||||
- Follow-up: implement the exclusive six-artifact filesystem prepare/finalize command, including
|
||||
receipt/path/mutation/accepted-key/signature/partial-output failures, before adding the callable
|
||||
workflow.
|
||||
|
||||
## Accepted Gaps
|
||||
|
||||
No product gap is accepted merely because it appears in this list. Each entry requires explicit
|
||||
@@ -10762,14 +10834,15 @@ The project is not complete until every applicable item below is checked with ev
|
||||
|
||||
## Next Required Action
|
||||
|
||||
Checkpoint E-M4-LINUX-FINALIZATION-CI-001 and the green PR Checks replacement. Then begin a
|
||||
purpose-named RED for the callable, disconnected aggregate/immutable-manifest workflow: consume all
|
||||
six exact aggregate-ready artifacts, prepare canonical bytes without credentials, isolate the
|
||||
base64 32-byte seed in the tag-restricted `relay-runtime-manifest-signing` environment, return only
|
||||
key ID plus signature, reconstruct and verify before emitting final output, and remove partial
|
||||
output on every failure. The environment 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
|
||||
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.
|
||||
|
||||
Cross-family Layer B targets, the protected manifest-signing environment, oldest-baseline/native-
|
||||
|
||||
Reference in New Issue
Block a user