mirror of
https://github.com/stablyai/orca.git
synced 2026-10-24 16:03:45 +00:00
* feat(ssh): wire rung B to the glibc 2.17 compat runtime; gate rung C vault on full node:sqlite - COMPAT_RELAY_RUNTIMES lists linux-x64-glibc217; rung B plans the compat slot and compat pinned Node when glibc is below 2.28 or rung A refused with libc_floor/missing_lib. - The relay version folds the compat runtime's executable hash; refusals are cached per runtime. - The orcad template stages an optional linux-x64-glibc217 target (base package + compat node-pty slot + compat runtime marker); the verifier and materializer accept it. - node-pty slot loader falls back to the compat slot when the default slot is missing or needs a newer glibc. - Runtime store GC keeps the compat pin beside the default one on every relay connect. - hasNodeSqliteReaderApi (DatabaseSync + backup) gates relay session search and the relay OpenCode reader, which now names the host Node version in its unavailable reason; the SSH vault reader installs the compat Node on old-glibc hosts and uploads nothing when no pinned Node can run. - Rung D: a remembered noexec reports home_noexec and never advises installing Node. * fix(ssh): re-prove a replayed noexec after rung D so allowing exec recovers the host * fix(ssh): keep the rung B compat runtime pinned in the relay-connect store GC * test(ssh): mock deployment-target facts in the Windows OpenCode runtime tests * ci(ssh): build the glibc 2.17 compat slot for the hostile-host matrix; CentOS 7 lands on rung B --------- Co-authored-by: m4air <m4air@m4airs-Air.localdomain> Co-authored-by: m4air <m4air@Mac.localdomain>
124 lines
3.8 KiB
TypeScript
124 lines
3.8 KiB
TypeScript
/** Turns one ladder step into a relay plan, or a classified refusal the ladder steps past. */
|
|
import type { SshConnection } from './ssh-connection'
|
|
import { planHostNodeAddonRelay, type PrebuiltRelayPlan } from './ssh-relay-host-node-addons'
|
|
import {
|
|
PinnedRelayFallbackError,
|
|
planPinnedNodeRelay,
|
|
resolvePinnedRelayTargetFacts
|
|
} from './ssh-relay-pinned-node'
|
|
import { rungBCompatRuntimeFor, type RelayRuntimeStep } from './ssh-relay-runtime-ladder'
|
|
import type { RelayRuntimeLadderRun } from './ssh-relay-runtime-resolution'
|
|
import type { RemoteHostPlatform } from './ssh-remote-platform'
|
|
import type { OrcadDeploymentTargetFacts } from './orcad-deployment-target'
|
|
|
|
type StepPlanOptions = {
|
|
conn: SshConnection
|
|
host: RemoteHostPlatform
|
|
baseVersion: string
|
|
step: RelayRuntimeStep
|
|
run: RelayRuntimeLadderRun
|
|
signal?: AbortSignal
|
|
}
|
|
|
|
/** Resolved once per ladder pass; every rung above legacy keys on the same answer. */
|
|
async function ladderTargetFacts(options: StepPlanOptions): Promise<OrcadDeploymentTargetFacts> {
|
|
const { run } = options
|
|
if (run.facts) {
|
|
return run.facts
|
|
}
|
|
const facts = await resolvePinnedRelayTargetFacts(options)
|
|
if ('kind' in facts) {
|
|
throw new PinnedRelayFallbackError(
|
|
facts.fallbackReason ?? 'target_unresolved',
|
|
'the host libc answer was not recognised'
|
|
)
|
|
}
|
|
run.facts = facts
|
|
return facts
|
|
}
|
|
|
|
/** Undefined for the host-npm path; throws `PinnedRelayFallbackError` when a rung cannot run. */
|
|
export async function planRelayRuntimeStep(
|
|
options: StepPlanOptions
|
|
): Promise<PrebuiltRelayPlan | undefined> {
|
|
const { conn, host, baseVersion, step, run, signal } = options
|
|
run.host = host
|
|
switch (step) {
|
|
case 'legacy':
|
|
return undefined
|
|
case 'A': {
|
|
const facts = await ladderTargetFacts(options)
|
|
const plan = await planPinnedNodeRelay({
|
|
conn,
|
|
host,
|
|
baseVersion,
|
|
targetId: run.targetId,
|
|
facts,
|
|
persistedRefusal: (known) => run.persistedPinnedRefusal(known),
|
|
signal
|
|
})
|
|
if (plan.kind === 'host-node') {
|
|
throw new PinnedRelayFallbackError(
|
|
plan.fallbackReason ?? 'artifacts_unavailable',
|
|
'Orca-managed Node cannot run here',
|
|
plan.remembered === true
|
|
)
|
|
}
|
|
return plan
|
|
}
|
|
case 'B': {
|
|
if (host.os === 'win32') {
|
|
throw new PinnedRelayFallbackError(
|
|
'runtime_unavailable',
|
|
'no compat runtime serves Windows'
|
|
)
|
|
}
|
|
const facts = await ladderTargetFacts(options)
|
|
// run.lastRefusal is rung A's: B is entered only by stepping down from A.
|
|
const compat = rungBCompatRuntimeFor(facts, run.lastRefusal)
|
|
if (!compat) {
|
|
throw new PinnedRelayFallbackError(
|
|
'runtime_unavailable',
|
|
'no compat runtime serves this host'
|
|
)
|
|
}
|
|
const plan = await planPinnedNodeRelay({
|
|
conn,
|
|
host,
|
|
baseVersion,
|
|
targetId: run.targetId,
|
|
facts,
|
|
compat: { target: compat.runtimeTarget, glibcFloor: compat.glibcFloor },
|
|
signal
|
|
})
|
|
if (plan.kind === 'host-node') {
|
|
throw new PinnedRelayFallbackError(
|
|
plan.fallbackReason ?? 'artifacts_unavailable',
|
|
`compat runtime ${compat.id} cannot run here`,
|
|
plan.remembered === true
|
|
)
|
|
}
|
|
return plan
|
|
}
|
|
case 'C': {
|
|
if (host.os === 'win32') {
|
|
throw new PinnedRelayFallbackError(
|
|
'windows_host_unsupported',
|
|
'Windows hosts have no host-Node addon relay'
|
|
)
|
|
}
|
|
const plan = await planHostNodeAddonRelay({
|
|
conn,
|
|
host,
|
|
facts: await ladderTargetFacts(options),
|
|
baseVersion,
|
|
signal
|
|
})
|
|
run.hostNode = plan.hostNode.version
|
|
return plan
|
|
}
|
|
case 'D':
|
|
throw new Error('Rung D has no relay to plan')
|
|
}
|
|
}
|