OverviewFilesCommitsIssuesDocsReleasesPeers

P2P-Hiverelay / test / unit / fleet-updater-gateway.test.js

1041 lines · javascript ref:
import test from 'brittle'
import {
  chmodSync,
  existsSync,
  linkSync,
  mkdirSync,
  mkdtempSync,
  readFileSync,
  realpathSync,
  rmSync,
  statSync,
  symlinkSync,
  writeFileSync
} from 'node:fs'
import { spawnSync } from 'node:child_process'
import { tmpdir } from 'node:os'
import path from 'node:path'

const updaterPath = path.resolve('fleet/updater.sh')
const targetSha = 'c'.repeat(40)
const priorSha = 'd'.repeat(40)
const appKey = 'a'.repeat(64)
const contentSha256 = 'b'.repeat(64)
const nginxSha256 = 'e'.repeat(64)
const operatorContractSha256 = 'f'.repeat(64)
const fingerprint256 = Array(32).fill('AA').join(':')
const origin = 'https://manifest-app.hive.test'

function executable (filename, source) {
  writeFileSync(filename, source)
  chmodSync(filename, 0o755)
}

function fixture (t) {
  const root = realpathSync(mkdtempSync(path.join(tmpdir(), 'hr-updater-gateway-')))
  const bin = path.join(root, 'bin')
  const repo = path.join(root, 'repo')
  const scripts = path.join(repo, 'scripts')
  const scriptLibrary = path.join(scripts, 'lib')
  const gitLog = path.join(root, 'git.log')
  const systemctlLog = path.join(root, 'systemctl.log')
  const restartCount = path.join(root, 'restart-count')
  const resolverArgs = path.join(root, 'resolver-args.log')
  const controlResolverArgs = path.join(root, 'control-resolver-args.log')
  const preflightArgs = path.join(root, 'preflight-args.log')
  const preflightEnv = path.join(root, 'preflight-env.log')
  const verifierArgs = path.join(root, 'verifier-args.log')
  const opsPreflightArgs = path.join(root, 'ops-preflight-args.log')
  const opsVerifierArgs = path.join(root, 'ops-verifier-args.log')
  const quarantineArgs = path.join(root, 'quarantine-args.log')
  const quarantineVerifierArgs = path.join(root, 'quarantine-verifier-args.log')
  const disabledConfigVerifierArgs = path.join(root, 'disabled-config-verifier-args.log')
  const syncLog = path.join(root, 'sync.log')
  const syncCount = path.join(root, 'sync-count')
  const envFile = path.join(root, 'hiverelay.env')
  const updaterConf = path.join(root, 'hiverelay-updater.conf')
  const allowedSigners = path.join(root, 'allowed-signers')
  const evidence = path.join(root, 'gateway-evidence.json')
  const gatewayConfig = path.join(root, 'gateway.json')
  const opsEvidence = path.join(root, 'gateway-ops-evidence.json')
  const certificate = path.join(root, 'fullchain.pem')
  const certificateKey = path.join(root, 'privkey.pem')
  const certificateRoot = path.join(root, 'letsencrypt')
  const ssBinary = path.join(root, 'ss')
  const nginxConfig = path.join(root, 'hiverelay-public-apps.conf')
  const nginxBinary = path.join(root, 'nginx')
  const nginxBinaryLog = path.join(root, 'nginx-binary.log')
  const ssBinaryLog = path.join(root, 'ss-binary.log')
  const hostileExecutionLog = path.join(root, 'hostile-execution.log')
  const quarantine = path.join(root, 'quarantine-public-gateway')
  const quarantineBackup = path.join(root, 'hiverelay-public-apps.conf.pre-quarantine')
  const operatorContract = path.join(repo, 'fleet', 'public-hive-gateway-operators', 'stable-1.json')
  const releaseManifest = path.join(repo, 'fleet', 'public-hive-gateway-release.json')
  const quarantineSource = `#!/bin/sh
for arg in "$@"; do printf '%s\\n' "$arg"; done > "$FAKE_QUARANTINE_ARGS"
exit "$FAKE_QUARANTINE_STATUS"
`

  mkdirSync(bin)
  mkdirSync(scripts, { recursive: true })
  mkdirSync(scriptLibrary, { recursive: true })
  mkdirSync(path.join(repo, 'fleet', 'public-hive-gateway-operators'), { recursive: true })
  mkdirSync(certificateRoot)
  writeFileSync(path.join(repo, 'package.json'), '{"version":"1.2.2"}\n')
  writeFileSync(path.join(scripts, 'resolve-signed-fleet-channel.mjs'), '// fixture\n')
  writeFileSync(path.join(scripts, 'resolve-public-hive-gateway-node.mjs'), '// fixture\n')
  writeFileSync(path.join(scripts, 'preflight-public-hive-gateway.mjs'), '// fixture\n')
  writeFileSync(path.join(scripts, 'verify-public-hive-gateway-evidence.mjs'), '// fixture\n')
  writeFileSync(path.join(scripts, 'preflight-public-hive-gateway-ops.mjs'), '// fixture\n')
  writeFileSync(path.join(scripts, 'verify-public-hive-gateway-ops-evidence.mjs'), '// fixture\n')
  writeFileSync(path.join(scripts, 'verify-public-hive-gateway-quarantine.mjs'), '// fixture\n')
  writeFileSync(path.join(scripts, 'verify-public-hive-gateway-disabled-config.mjs'), '// fixture\n')
  writeFileSync(path.join(scriptLibrary, 'public-hive-gateway-quarantine-authority.mjs'), '// fixture\n')
  writeFileSync(path.join(scriptLibrary, 'public-hive-gateway-release-manifest.mjs'), '// fixture\n')
  writeFileSync(path.join(scriptLibrary, 'public-hive-gateway-policy.mjs'), '// fixture\n')
  writeFileSync(path.join(repo, 'fleet', 'quarantine-public-gateway.sh'), quarantineSource)
  writeFileSync(releaseManifest, '{"schema":"fixture"}\n')
  writeFileSync(operatorContract, '{"schema":"fixture"}\n')
  writeFileSync(envFile, 'HIVERELAY_API_KEY=fixture-secret\n')
  writeFileSync(updaterConf, `CHANNEL=stable\nRELAY_NAME=stable-1\nREPO_DIR=${repo}\n`)
  writeFileSync(allowedSigners, 'release@example.invalid ssh-ed25519 fixture\n')
  writeFileSync(evidence, '{"schema":"stale-valid-evidence"}\n')
  writeFileSync(gatewayConfig, '{}\n')
  writeFileSync(opsEvidence, '{"schema":"stale-valid-ops-evidence"}\n')
  writeFileSync(certificate, 'fixture certificate\n')
  writeFileSync(certificateKey, 'fixture key\n')
  writeFileSync(nginxConfig, '# installed edge fixture\n')
  executable(nginxBinary, '#!/bin/sh\nprintf \'%s\\n\' "$*" >> "$FAKE_NGINX_BINARY_LOG"\nexit 0\n')
  executable(ssBinary, '#!/bin/sh\nprintf \'%s\\n\' "$*" >> "$FAKE_SS_BINARY_LOG"\nexit 0\n')

  executable(path.join(bin, 'curl'), `#!/bin/sh
case "$*" in
  */health*)
    count=0
    [ ! -f "$FAKE_RESTART_COUNT" ] || count="$(cat "$FAKE_RESTART_COUNT")"
    if [ "$count" -ge 2 ]; then version="$FAKE_CURRENT_VERSION"; else version="$FAKE_TARGET_VERSION"; fi
    printf '{"running":true,"version":"%s"}\\n' "$version"
    ;;
  *) printf '{"stable":"v1.2.3"}\\n' ;;
esac
`)
  executable(path.join(bin, 'flock'), `#!/bin/sh
exit "${'$'}{FAKE_FLOCK_STATUS:-0}"
`)
  executable(path.join(bin, 'sync'), `#!/bin/sh
count=0
[ ! -f "$FAKE_SYNC_COUNT" ] || count="$(cat "$FAKE_SYNC_COUNT")"
count=$((count + 1))
printf '%s\n' "$count" > "$FAKE_SYNC_COUNT"
printf '%s\n' "$*" >> "$FAKE_SYNC_LOG"
[ "$count" != "${'$'}{FAKE_SYNC_FAIL_AT:-0}" ]
`)
  executable(path.join(bin, 'git'), `#!/bin/sh
printf '%s\\n' "$*" >> "$FAKE_GIT_LOG"
case "$1" in
  diff|fetch) exit 0 ;;
  checkout)
    case "$*" in
      *" $FAKE_TARGET_TAG") exit "$FAKE_TARGET_CHECKOUT_STATUS" ;;
    esac
    exit "$FAKE_PRIOR_CHECKOUT_STATUS"
    ;;
  status) exit 0 ;;
  ls-files)
    [ "$2" != "-v" ] || printf 'H package.json\nH scripts/resolve-public-hive-gateway-node.mjs\n'
    exit 0
    ;;
  cat-file)
    if [ "$2" = "-t" ]; then printf 'tag\\n'; exit 0; fi
    if [ "$2" = "-e" ]; then [ "$FAKE_MANIFEST_PRESENT" = "1" ]; exit $?; fi
    ;;
  rev-parse)
    case "$*" in
      *refs/tags*) printf '%s\\n' "$FAKE_TARGET_SHA" ;;
      *) printf '%s\\n' "$FAKE_CURRENT_SHA" ;;
    esac
    exit 0
    ;;
  ls-tree)
    case "$*" in
      *fleet/quarantine-public-gateway.sh*)
        printf 'fleet/quarantine-public-gateway.sh\n'
        exit 0
        ;;
      *scripts/verify-public-hive-gateway-quarantine.mjs*)
        printf 'scripts/verify-public-hive-gateway-quarantine.mjs\n'
        exit 0
        ;;
      *scripts/lib/public-hive-gateway-quarantine-authority.mjs*)
        printf 'scripts/lib/public-hive-gateway-quarantine-authority.mjs\n'
        exit 0
        ;;
      *scripts/lib/public-hive-gateway-release-manifest.mjs*)
        printf 'scripts/lib/public-hive-gateway-release-manifest.mjs\n'
        exit 0
        ;;
      *scripts/lib/public-hive-gateway-policy.mjs*)
        printf 'scripts/lib/public-hive-gateway-policy.mjs\n'
        exit 0
        ;;
      *fleet/public-hive-gateway-operators/stable-1.json*)
        printf 'fleet/public-hive-gateway-operators/stable-1.json\n'
        exit 0
        ;;
    esac
    [ "$FAKE_MANIFEST_TREE_STATUS" = "0" ] || exit "$FAKE_MANIFEST_TREE_STATUS"
    present="$FAKE_MANIFEST_PRESENT"
    if [ "$3" = "$FAKE_CURRENT_SHA" ] && [ -n "$FAKE_SOURCE_MANIFEST_PRESENT" ]; then
      present="$FAKE_SOURCE_MANIFEST_PRESENT"
    elif [ "$3" = "$FAKE_TARGET_SHA" ] && [ -n "$FAKE_TARGET_MANIFEST_PRESENT" ]; then
      present="$FAKE_TARGET_MANIFEST_PRESENT"
    fi
    [ "$present" != "1" ] || printf 'fleet/public-hive-gateway-release.json\\n'
    exit 0
    ;;
  show)
    case "$*" in
      *fleet/quarantine-public-gateway.sh*)
        cat "$FAKE_REPO/fleet/quarantine-public-gateway.sh"
        exit 0
        ;;
      *scripts/verify-public-hive-gateway-quarantine.mjs*)
        cat "$FAKE_REPO/scripts/verify-public-hive-gateway-quarantine.mjs"
        exit 0
        ;;
      *scripts/lib/public-hive-gateway-quarantine-authority.mjs*)
        cat "$FAKE_REPO/scripts/lib/public-hive-gateway-quarantine-authority.mjs"
        exit 0
        ;;
      *scripts/lib/public-hive-gateway-release-manifest.mjs*)
        cat "$FAKE_REPO/scripts/lib/public-hive-gateway-release-manifest.mjs"
        exit 0
        ;;
      *scripts/lib/public-hive-gateway-policy.mjs*)
        cat "$FAKE_REPO/scripts/lib/public-hive-gateway-policy.mjs"
        exit 0
        ;;
      *fleet/public-hive-gateway-operators/stable-1.json*)
        printf '%s\n' "$FAKE_OPERATOR_CONTRACT"
        exit 0
        ;;
    esac
    [ "$FAKE_MANIFEST_SHOW_STATUS" = "0" ] || exit "$FAKE_MANIFEST_SHOW_STATUS"
    printf '%s\\n' "$FAKE_GATEWAY_MANIFEST"
    exit 0
    ;;
esac
case "$*" in
  *verify-tag*) printf 'Good "git" signature\\n'; exit "$FAKE_VERIFY_TAG_STATUS" ;;
esac
exit 0
`)
  executable(path.join(bin, 'systemctl'), `#!/bin/sh
printf '%s\\n' "$*" >> "$FAKE_SYSTEMCTL_LOG"
if [ "$1" = "restart" ]; then
  count=0
  [ ! -f "$FAKE_RESTART_COUNT" ] || count="$(cat "$FAKE_RESTART_COUNT")"
  count=$((count + 1))
  printf '%s\\n' "$count" > "$FAKE_RESTART_COUNT"
  if [ "$count" = "${'$'}{FAKE_SYSTEMCTL_FAIL_RESTART_AT:-0}" ]; then
    exit "${'$'}{FAKE_SYSTEMCTL_RESTART_STATUS:-1}"
  fi
fi
exit 0
`)
  executable(path.join(bin, 'timeout'), `#!/bin/sh
shift
exec "$@"
`)
  executable(path.join(bin, 'node'), `#!/bin/sh
script="$1"
shift
case "$script" in
  */resolve-signed-fleet-channel.mjs)
    for arg in "$@"; do printf '%s\n' "$arg"; done > "$FAKE_CONTROL_RESOLVER_ARGS"
    printf 'resolved\tv1.2.3\t%s\t%s\t%s\n' "$FAKE_TARGET_SHA" "$FAKE_CONTROL_COMMIT" "$FAKE_CONTROL_TIP"
    exit "$FAKE_CONTROL_RESOLVER_STATUS"
    ;;
  */resolve-public-hive-gateway-node.mjs)
    for arg in "$@"; do printf '%s\\n' "$arg"; done > "$FAKE_RESOLVER_ARGS"
    selected="$FAKE_GATEWAY_CONTRACT"
    previous=""
    for arg in "$@"; do
      if [ "$previous" = "--release-target" ] && [ "$arg" = "$FAKE_CURRENT_VERSION_TAG" ] &&
        [ -n "$FAKE_SOURCE_GATEWAY_CONTRACT" ]; then
        selected="$FAKE_SOURCE_GATEWAY_CONTRACT"
      fi
      previous="$arg"
    done
    printf '%s\\n' "$selected"
    exit "$FAKE_RESOLVER_STATUS"
    ;;
  */preflight-public-hive-gateway.mjs)
    for arg in "$@"; do printf '%s\\n' "$arg"; done > "$FAKE_PREFLIGHT_ARGS"
    printf '%s\\n' "$HIVERELAY_API_KEY" > "$FAKE_PREFLIGHT_ENV"
    if [ "$FAKE_PREFLIGHT_RUN_NGINX" = 1 ]; then "$FAKE_NGINX_BINARY" -T; fi
    if [ "$FAKE_PREFLIGHT_REPLACE_NGINX" = 1 ]; then
      replacement="$FAKE_NGINX_BINARY.replacement"
      printf '%s\\n' '#!/bin/sh' 'printf nginx-hostile >> "$FAKE_HOSTILE_EXECUTION_LOG"' > "$replacement"
      chmod 0755 "$replacement"
      mv -f "$replacement" "$FAKE_NGINX_BINARY"
    fi
    exit "$FAKE_PREFLIGHT_STATUS"
    ;;
  */verify-public-hive-gateway-evidence.mjs)
    for arg in "$@"; do printf '%s\\n' "$arg"; done > "$FAKE_VERIFIER_ARGS"
    exit "$FAKE_VERIFIER_STATUS"
    ;;
  */preflight-public-hive-gateway-ops.mjs)
    for arg in "$@"; do printf '%s\\n' "$arg"; done > "$FAKE_OPS_PREFLIGHT_ARGS"
    if [ "$FAKE_OPS_RUN_SS" = 1 ]; then "$FAKE_SS_BINARY" -H -lntup; fi
    if [ "$FAKE_OPS_REPLACE_SS" = 1 ]; then
      replacement="$FAKE_SS_BINARY.replacement"
      printf '%s\\n' '#!/bin/sh' 'printf ss-hostile >> "$FAKE_HOSTILE_EXECUTION_LOG"' > "$replacement"
      chmod 0755 "$replacement"
      mv -f "$replacement" "$FAKE_SS_BINARY"
    fi
    exit "$FAKE_OPS_PREFLIGHT_STATUS"
    ;;
  */verify-public-hive-gateway-ops-evidence.mjs)
    for arg in "$@"; do printf '%s\\n' "$arg"; done > "$FAKE_OPS_VERIFIER_ARGS"
    exit "$FAKE_OPS_VERIFIER_STATUS"
    ;;
  */verify-public-hive-gateway-quarantine.mjs)
    for arg in "$@"; do printf '%s\n' "$arg"; done > "$FAKE_QUARANTINE_VERIFIER_ARGS"
    exit "$FAKE_QUARANTINE_VERIFIER_STATUS"
    ;;
  */verify-public-hive-gateway-disabled-config.mjs)
    for arg in "$@"; do printf '%s\n' "$arg"; done > "$FAKE_DISABLED_CONFIG_VERIFIER_ARGS"
    exit "$FAKE_DISABLED_CONFIG_VERIFIER_STATUS"
    ;;
esac
exit 97
`)
  executable(quarantine, quarantineSource)

  t.teardown(() => rmSync(root, { recursive: true, force: true }))

  const contract = [
    'cohort',
    'blind-substrate-public-v1',
    origin,
    '127.0.0.1',
    appKey,
    '/index.html',
    contentSha256,
    '7',
    fingerprint256,
    nginxSha256,
    'public-t1-gateway',
    operatorContractSha256
  ].join('\t')
  const env = {
    ...process.env,
    PATH: `${bin}:${process.env.PATH || ''}`,
    TMPDIR: root,
    HOME: root,
    HIVERELAY_REPO_DIR: repo,
    HIVERELAY_GIT_BIN: path.join(bin, 'git'),
    HIVERELAY_UPDATER_CONF: updaterConf,
    HIVERELAY_CONTROL_STATE: path.join(root, 'control-state', 'channel.json'),
    HIVERELAY_ENV_FILE: envFile,
    HIVERELAY_ALLOWED_SIGNERS: allowedSigners,
    HIVERELAY_HEALTH_TIMEOUT: '1',
    HIVERELAY_PUBLIC_GATEWAY_PROBE_CONFIG: gatewayConfig,
    HIVERELAY_PUBLIC_GATEWAY_PROBE_NGINX_CONFIG: nginxConfig,
    HIVERELAY_PUBLIC_GATEWAY_PROBE_NGINX_BINARY: nginxBinary,
    HIVERELAY_PUBLIC_GATEWAY_PROBE_EVIDENCE: evidence,
    HIVERELAY_PUBLIC_GATEWAY_OPS_CERTIFICATE: certificate,
    HIVERELAY_PUBLIC_GATEWAY_OPS_CERTIFICATE_KEY: certificateKey,
    HIVERELAY_PUBLIC_GATEWAY_OPS_CERTIFICATE_ROOT: certificateRoot,
    HIVERELAY_PUBLIC_GATEWAY_OPS_SS_BINARY: ssBinary,
    HIVERELAY_PUBLIC_GATEWAY_OPS_EVIDENCE: opsEvidence,
    HIVERELAY_PUBLIC_GATEWAY_PROBE_PUBLIC_SUFFIX_READY: '0',
    HIVERELAY_PUBLIC_GATEWAY_QUARANTINE_COMMAND: quarantine,
    HIVERELAY_PUBLIC_GATEWAY_QUARANTINE_BACKUP: quarantineBackup,
    // These retired, mutable selectors must never override the signed manifest.
    HIVERELAY_PUBLIC_GATEWAY_PROBE_ORIGIN: 'https://attacker.invalid/',
    HIVERELAY_PUBLIC_GATEWAY_PROBE_CONNECT_ADDRESS: '192.0.2.99',
    HIVERELAY_PUBLIC_GATEWAY_PROBE_APP_KEY: 'f'.repeat(64),
    HIVERELAY_PUBLIC_GATEWAY_PROBE_PATH: '/attacker',
    HIVERELAY_PUBLIC_GATEWAY_PROBE_SHA256: '0'.repeat(64),
    HIVERELAY_PUBLIC_GATEWAY_PROBE_MODE: 'canary',
    FAKE_CURRENT_SHA: targetSha,
    FAKE_NGINX_BINARY: nginxBinary,
    FAKE_SS_BINARY: ssBinary,
    FAKE_NGINX_BINARY_LOG: nginxBinaryLog,
    FAKE_SS_BINARY_LOG: ssBinaryLog,
    FAKE_HOSTILE_EXECUTION_LOG: hostileExecutionLog,
    FAKE_PREFLIGHT_RUN_NGINX: '0',
    FAKE_PREFLIGHT_REPLACE_NGINX: '0',
    FAKE_OPS_RUN_SS: '0',
    FAKE_OPS_REPLACE_SS: '0',
    FAKE_REPO: repo,
    FAKE_TARGET_SHA: targetSha,
    FAKE_CONTROL_COMMIT: '1'.repeat(40),
    FAKE_CONTROL_TIP: '2'.repeat(40),
    FAKE_CONTROL_RESOLVER_STATUS: '0',
    FAKE_CURRENT_VERSION: '1.2.2',
    FAKE_CURRENT_VERSION_TAG: 'v1.2.2',
    FAKE_TARGET_VERSION: '1.2.3',
    FAKE_TARGET_TAG: 'v1.2.3',
    FAKE_GATEWAY_MANIFEST: '{"schema":"fixture"}',
    FAKE_OPERATOR_CONTRACT: '{"schema":"fixture-operator"}',
    FAKE_GATEWAY_CONTRACT: contract,
    FAKE_MANIFEST_PRESENT: '1',
    FAKE_SOURCE_MANIFEST_PRESENT: '',
    FAKE_TARGET_MANIFEST_PRESENT: '',
    FAKE_SOURCE_GATEWAY_CONTRACT: '',
    FAKE_MANIFEST_TREE_STATUS: '0',
    FAKE_MANIFEST_SHOW_STATUS: '0',
    FAKE_VERIFY_TAG_STATUS: '0',
    FAKE_RESOLVER_STATUS: '0',
    FAKE_PREFLIGHT_STATUS: '0',
    FAKE_VERIFIER_STATUS: '0',
    FAKE_OPS_PREFLIGHT_STATUS: '0',
    FAKE_OPS_VERIFIER_STATUS: '0',
    FAKE_QUARANTINE_STATUS: '0',
    FAKE_QUARANTINE_VERIFIER_STATUS: '0',
    FAKE_DISABLED_CONFIG_VERIFIER_STATUS: '0',
    FAKE_TARGET_CHECKOUT_STATUS: '0',
    FAKE_PRIOR_CHECKOUT_STATUS: '0',
    FAKE_SYSTEMCTL_FAIL_RESTART_AT: '0',
    FAKE_SYSTEMCTL_RESTART_STATUS: '1',
    FAKE_FLOCK_STATUS: '0',
    FAKE_SYNC_FAIL_AT: '0',
    FAKE_SYNC_LOG: syncLog,
    FAKE_SYNC_COUNT: syncCount,
    FAKE_GIT_LOG: gitLog,
    FAKE_SYSTEMCTL_LOG: systemctlLog,
    FAKE_RESTART_COUNT: restartCount,
    FAKE_RESOLVER_ARGS: resolverArgs,
    FAKE_CONTROL_RESOLVER_ARGS: controlResolverArgs,
    FAKE_PREFLIGHT_ARGS: preflightArgs,
    FAKE_PREFLIGHT_ENV: preflightEnv,
    FAKE_VERIFIER_ARGS: verifierArgs,
    FAKE_OPS_PREFLIGHT_ARGS: opsPreflightArgs,
    FAKE_OPS_VERIFIER_ARGS: opsVerifierArgs,
    FAKE_QUARANTINE_ARGS: quarantineArgs,
    FAKE_QUARANTINE_VERIFIER_ARGS: quarantineVerifierArgs,
    FAKE_DISABLED_CONFIG_VERIFIER_ARGS: disabledConfigVerifierArgs
  }

  return {
    root,
    bin,
    env,
    evidence,
    gitLog,
    nginxBinary,
    nginxBinaryLog,
    ssBinaryLog,
    hostileExecutionLog,
    nginxConfig,
    certificate,
    certificateKey,
    certificateRoot,
    contract,
    controlResolverArgs,
    gatewayConfig,
    operatorContract,
    opsEvidence,
    opsPreflightArgs,
    opsVerifierArgs,
    preflightArgs,
    preflightEnv,
    quarantineArgs,
    quarantine,
    quarantineVerifierArgs,
    disabledConfigVerifierArgs,
    quarantineBackup,
    releaseManifest,
    repo,
    resolverArgs,
    systemctlLog,
    ssBinary,
    syncLog,
    updaterConf,
    verifierArgs,
    run: (overrides = {}) => spawnSync('bash', [updaterPath], {
      encoding: 'utf8',
      env: { ...env, ...overrides }
    })
  }
}

function argsFrom (filename) {
  return readFileSync(filename, 'utf8').trim().split('\n')
}

function valueAfter (args, flag) {
  const index = args.indexOf(flag)
  return index === -1 ? undefined : args[index + 1]
}

function assertContained (t, f) {
  const invalid = JSON.parse(readFileSync(f.evidence, 'utf8'))
  t.is(invalid.schema, 'hiverelay-public-gateway-evidence-invalid-v1')
  t.is(invalid.releaseTarget, 'v1.2.3')
  t.is(invalid.releaseSha, targetSha)
  t.is(invalid.relay, 'stable-1')
  t.is(statSync(f.evidence).mode & 0o777, 0o600)
  const invalidOps = JSON.parse(readFileSync(f.opsEvidence, 'utf8'))
  t.is(invalidOps.schema, 'hiverelay-public-gateway-operator-readiness-invalid-v1')
  t.is(invalidOps.releaseTarget, 'v1.2.3')
  t.is(invalidOps.releaseSha, targetSha)
  t.is(invalidOps.relay, 'stable-1')
  t.is(invalidOps.operatorContractSha256, operatorContractSha256)
  t.is(statSync(f.opsEvidence).mode & 0o777, 0o600)
  t.alike(argsFrom(f.quarantineArgs), [f.nginxConfig, f.quarantineBackup, f.nginxBinary])
  const verifier = argsFrom(f.quarantineVerifierArgs)
  t.is(valueAfter(verifier, '--expected-digest'), operatorContractSha256)
  t.is(valueAfter(verifier, '--nginx-binary'), f.nginxBinary)
}

test('signed cohort forces preflight and standalone verification from exact manifest bindings', (t) => {
  const f = fixture(t)
  const result = f.run()

  t.is(result.status, 0, result.stderr || result.stdout)
  const preflight = argsFrom(f.preflightArgs)
  t.is(valueAfter(preflight, '--mode'), 'fleet')
  t.is(valueAfter(preflight, '--probe-origin'), origin)
  t.is(valueAfter(preflight, '--connect-address'), '127.0.0.1')
  t.is(valueAfter(preflight, '--app-key'), appKey)
  t.is(valueAfter(preflight, '--path'), '/index.html')
  t.is(valueAfter(preflight, '--expected-sha256'), contentSha256)
  t.is(valueAfter(preflight, '--evidence'), f.evidence)
  t.is(valueAfter(preflight, '--release-target'), 'v1.2.3')
  t.is(valueAfter(preflight, '--release-sha'), targetSha)
  t.absent(preflight.includes('--public-suffix-ready'))
  t.is(readFileSync(f.preflightEnv, 'utf8').trim(), 'fixture-secret')
  t.absent(preflight.includes('fixture-secret'), 'relay API key stays out of child argv')

  const verifier = argsFrom(f.verifierArgs)
  t.is(valueAfter(verifier, '--require-mode'), 'fleet')
  t.is(valueAfter(verifier, '--require-admission-profile'), 'blind-substrate-public-v1')
  t.is(valueAfter(verifier, '--expected-origin'), origin)
  t.is(valueAfter(verifier, '--expected-connect-address'), '127.0.0.1')
  t.is(valueAfter(verifier, '--expected-app-key'), appKey)
  t.is(valueAfter(verifier, '--expected-path'), '/index.html')
  t.is(valueAfter(verifier, '--expected-sha256'), contentSha256)
  t.is(valueAfter(verifier, '--expected-drive-version'), '7')
  t.is(valueAfter(verifier, '--expected-peer-fingerprint256'), fingerprint256)
  t.is(valueAfter(verifier, '--expected-nginx-sha256'), nginxSha256)

  const opsPreflight = argsFrom(f.opsPreflightArgs)
  t.is(valueAfter(opsPreflight, '--mode'), 'fleet')
  t.is(valueAfter(opsPreflight, '--contract'), f.operatorContract)
  t.is(valueAfter(opsPreflight, '--config'), f.gatewayConfig)
  t.is(valueAfter(opsPreflight, '--gateway-evidence'), f.evidence)
  t.is(valueAfter(opsPreflight, '--release-sha'), targetSha)
  t.is(valueAfter(opsPreflight, '--release-manifest'), f.releaseManifest)
  t.is(valueAfter(opsPreflight, '--certificate'), f.certificate)
  t.is(valueAfter(opsPreflight, '--certificate-key'), f.certificateKey)
  t.is(valueAfter(opsPreflight, '--certificate-root'), f.certificateRoot)
  t.is(valueAfter(opsPreflight, '--ss-binary'), f.ssBinary)
  t.ok(opsPreflight.includes('--dns-live'))
  t.is(valueAfter(opsPreflight, '--evidence'), f.opsEvidence)

  const opsVerifier = argsFrom(f.opsVerifierArgs)
  t.is(valueAfter(opsVerifier, '--evidence'), f.opsEvidence)
  t.is(valueAfter(opsVerifier, '--contract'), f.operatorContract)
  t.is(valueAfter(opsVerifier, '--release-manifest'), f.releaseManifest)
  t.is(valueAfter(opsVerifier, '--release-sha'), targetSha)
  t.is(valueAfter(opsVerifier, '--relay'), 'stable-1')
  t.is(valueAfter(opsVerifier, '--expected-contract-sha256'), operatorContractSha256)

  t.alike(argsFrom(f.resolverArgs), [
    '--release-target', 'v1.2.3',
    '--relay', 'stable-1',
    '--channel', 'stable',
    '--require-public-t1'
  ])
  const control = argsFrom(f.controlResolverArgs)
  t.is(valueAfter(control, '--repo'), f.repo)
  t.is(valueAfter(control, '--remote'), 'origin')
  t.is(valueAfter(control, '--branch'), 'main')
  t.is(valueAfter(control, '--channel'), 'stable')
  t.is(valueAfter(control, '--installed-head'), targetSha)
  t.absent(readFileSync(f.gitLog, 'utf8').includes('checkout'))
  t.absent(readFileSync(f.systemctlLog, 'utf8').includes('restart'))
  t.absent(existsSync(f.quarantineArgs))
  t.ok(result.stdout.includes('up-to-date at v1.2.3'))
})

test('signed control resolver failure stops before tag policy or gateway execution', (t) => {
  const f = fixture(t)
  const result = f.run({ FAKE_CONTROL_RESOLVER_STATUS: '31' })
  t.not(result.status, 0)
  t.ok(result.stdout.includes('signed fleet channel control resolution failed'))
  t.ok(existsSync(f.controlResolverArgs))
  t.absent(existsSync(f.resolverArgs))
  t.absent(existsSync(f.preflightArgs))
  t.absent(readFileSync(f.gitLog, 'utf8').includes('verify-tag'))
})

test('up-to-date preflight failure invalidates evidence and quarantines only public edge', (t) => {
  const f = fixture(t)
  const result = f.run({ FAKE_PREFLIGHT_STATUS: '23' })

  t.not(result.status, 0)
  t.ok(result.stdout.includes('public edge quarantined; management API left running'))
  assertContained(t, f)
  t.absent(existsSync(f.verifierArgs), 'failed preflight never reaches evidence acceptance')
  t.absent(readFileSync(f.gitLog, 'utf8').includes('checkout'))
  t.absent(readFileSync(f.systemctlLog, 'utf8').includes('restart'))
  t.absent(readFileSync(f.systemctlLog, 'utf8').includes('stop'))
})

test('up-to-date evidence binding failure also triggers containment', (t) => {
  const f = fixture(t)
  const result = f.run({ FAKE_VERIFIER_STATUS: '24' })

  t.not(result.status, 0)
  t.ok(result.stdout.includes('public edge quarantined'))
  assertContained(t, f)
  t.ok(existsSync(f.preflightArgs))
  t.ok(existsSync(f.verifierArgs))
})

test('public-t1 ops preflight and verifier failures both invalidate evidence and contain the edge', (t) => {
  const preflightFailure = fixture(t)
  const failedPreflight = preflightFailure.run({ FAKE_OPS_PREFLIGHT_STATUS: '25' })
  t.not(failedPreflight.status, 0)
  t.ok(failedPreflight.stdout.includes('operator preflight failed'))
  t.ok(existsSync(preflightFailure.opsPreflightArgs))
  t.absent(existsSync(preflightFailure.opsVerifierArgs))
  assertContained(t, preflightFailure)

  const verifierFailure = fixture(t)
  const failedVerifier = verifierFailure.run({ FAKE_OPS_VERIFIER_STATUS: '26' })
  t.not(failedVerifier.status, 0)
  t.ok(failedVerifier.stdout.includes('ops evidence does not match'))
  t.ok(existsSync(verifierFailure.opsPreflightArgs))
  t.ok(existsSync(verifierFailure.opsVerifierArgs))
  assertContained(t, verifierFailure)
})

test('public-t1 profile, digest, contract, and ss posture fail closed before ops execution', (t) => {
  const malformedDigest = fixture(t)
  const malformedFields = malformedDigest.contract.split('\t')
  malformedFields[11] = '-'
  const malformedResult = malformedDigest.run({ FAKE_GATEWAY_CONTRACT: malformedFields.join('\t') })
  t.not(malformedResult.status, 0)
  t.ok(malformedResult.stdout.includes('requires a canonical operator contract digest'))
  t.absent(existsSync(malformedDigest.preflightArgs))
  t.absent(existsSync(malformedDigest.opsPreflightArgs))

  const unknownProfile = fixture(t)
  const unknownFields = unknownProfile.contract.split('\t')
  unknownFields[10] = 'public-t2-gateway'
  const unknownResult = unknownProfile.run({ FAKE_GATEWAY_CONTRACT: unknownFields.join('\t') })
  t.not(unknownResult.status, 0)
  t.ok(unknownResult.stdout.includes('deployment profile is unsupported'))
  t.absent(existsSync(unknownProfile.preflightArgs))

  const missingContract = fixture(t)
  rmSync(missingContract.operatorContract)
  const missingResult = missingContract.run()
  t.not(missingResult.status, 0)
  t.ok(missingResult.stdout.includes('operator contract is missing or unsafe'))
  t.ok(existsSync(missingContract.verifierArgs), 'base gateway evidence is verified before ops posture')
  t.absent(existsSync(missingContract.opsPreflightArgs))
  assertContained(t, missingContract)

  const linkedContract = fixture(t)
  rmSync(linkedContract.operatorContract)
  symlinkSync(linkedContract.releaseManifest, linkedContract.operatorContract)
  const linkedResult = linkedContract.run()
  t.not(linkedResult.status, 0)
  t.ok(linkedResult.stdout.includes('operator contract is missing or unsafe'))
  t.absent(existsSync(linkedContract.opsPreflightArgs))
  assertContained(t, linkedContract)

  const unsafeSs = fixture(t)
  rmSync(unsafeSs.ssBinary)
  symlinkSync('/bin/true', unsafeSs.ssBinary)
  const unsafeSsResult = unsafeSs.run()
  t.not(unsafeSsResult.status, 0)
  t.ok(unsafeSsResult.stdout.includes('ss binary is missing or unsafe') ||
    unsafeSsResult.stdout.includes('gateway ss binary path must be canonical') ||
    unsafeSsResult.stdout.includes('gateway ss binary is not a regular executable'))
  t.absent(existsSync(unsafeSs.opsPreflightArgs))
  assertContained(t, unsafeSs)
})

test('enabled legacy cohort is rejected by the updater activation path', (t) => {
  const f = fixture(t)
  const fields = f.contract.split('\t')
  fields[10] = 'legacy'
  fields[11] = '-'
  const result = f.run({ FAKE_GATEWAY_CONTRACT: fields.join('\t') })
  t.not(result.status, 0)
  t.ok(result.stdout.includes('must use public-t1-gateway'))
  t.absent(existsSync(f.preflightArgs))
  t.absent(existsSync(f.verifierArgs))
  t.absent(existsSync(f.opsPreflightArgs))
  t.absent(existsSync(f.opsVerifierArgs))
  t.is(JSON.parse(readFileSync(f.opsEvidence, 'utf8')).schema, 'stale-valid-ops-evidence')
})

test('cohort missing local config fails closed and still attempts edge containment', (t) => {
  const f = fixture(t)
  const result = f.run({ HIVERELAY_PUBLIC_GATEWAY_PROBE_CONFIG: '' })

  t.not(result.status, 0)
  t.ok(result.stdout.includes('requires explicit config, nginx config, and nginx binary paths'))
  t.absent(existsSync(f.preflightArgs))
  assertContained(t, f)
})

test('containment reports partial failure but never preserves stale evidence', (t) => {
  const f = fixture(t)
  const result = f.run({ FAKE_PREFLIGHT_STATUS: '23', FAKE_QUARANTINE_STATUS: '9' })

  t.not(result.status, 0)
  t.ok(result.stdout.includes('containment incomplete'))
  t.ok(result.stdout.includes('management service was not stopped'))
  const invalid = JSON.parse(readFileSync(f.evidence, 'utf8'))
  t.is(invalid.schema, 'hiverelay-public-gateway-evidence-invalid-v1')
  t.ok(existsSync(f.quarantineArgs), 'quarantine is attempted independently of evidence invalidation')
  t.absent(readFileSync(f.systemctlLog, 'utf8').includes('restart'))
})

test('new public-t1 release failure quarantines the edge before management rollback', (t) => {
  const f = fixture(t)
  const result = f.run({
    FAKE_CURRENT_SHA: priorSha,
    FAKE_PREFLIGHT_STATUS: '23'
  })

  t.not(result.status, 0)
  const git = readFileSync(f.gitLog, 'utf8')
  const systemctl = readFileSync(f.systemctlLog, 'utf8')
  t.ok(git.includes('checkout --quiet v1.2.3'))
  t.ok(git.includes(`checkout --quiet ${priorSha}`))
  t.ok(argsFrom(f.resolverArgs).includes('--require-public-t1'),
    'the updater never activates a historical legacy cohort')
  t.is(systemctl.split('\n').filter(line => line === 'restart hiverelay').length, 2)
  assertContained(t, f)
  t.ok(result.stdout.includes('management rollback OK'))
  t.ok(result.stdout.includes('public edge remains quarantined pending refreshed previous-release'))
})

test('gateway posture is never evaluated before target tag trust', (t) => {
  const f = fixture(t)
  const result = f.run({ HIVERELAY_ALLOWED_SIGNERS: path.join(path.dirname(f.evidence), 'missing-signers') })

  t.not(result.status, 0)
  t.ok(result.stdout.includes('refusing target release'))
  t.absent(existsSync(f.resolverArgs))
  t.absent(existsSync(f.preflightArgs))
  t.absent(existsSync(f.verifierArgs))
  t.absent(existsSync(f.quarantineArgs))
  t.is(JSON.parse(readFileSync(f.evidence, 'utf8')).schema, 'stale-valid-evidence')
})

test('target-tree or manifest-object failure cannot degrade a cohort into legacy mode', (t) => {
  const treeFailure = fixture(t)
  const treeResult = treeFailure.run({ FAKE_MANIFEST_TREE_STATUS: '2' })
  t.not(treeResult.status, 0)
  t.ok(treeResult.stdout.includes('could not inspect exact target tree'))
  t.absent(existsSync(treeFailure.resolverArgs))
  t.absent(existsSync(treeFailure.preflightArgs))

  const objectFailure = fixture(t)
  const objectResult = objectFailure.run({ FAKE_MANIFEST_SHOW_STATUS: '3' })
  t.not(objectResult.status, 0)
  t.ok(objectResult.stdout.includes('could not read public gateway manifest from exact target'))
  t.absent(existsSync(objectFailure.resolverArgs))
  t.absent(existsSync(objectFailure.preflightArgs))
})

test('signed noncohort and legacy targets remain ordinary health-only no-ops', (t) => {
  const f = fixture(t)

  const noncohort = f.run({ FAKE_GATEWAY_CONTRACT: 'ordinary\tnoncohort' })
  t.is(noncohort.status, 0, noncohort.stderr || noncohort.stdout)
  t.ok(noncohort.stdout.includes('posture=noncohort'))
  t.absent(existsSync(f.preflightArgs))
  t.absent(existsSync(f.verifierArgs))
  t.absent(existsSync(f.quarantineArgs))
  t.absent(existsSync(f.systemctlLog), 'ordinary no-op does not read the API key or restart service')

  rmSync(f.resolverArgs, { force: true })
  const legacy = f.run({ FAKE_MANIFEST_PRESENT: '0' })
  t.is(legacy.status, 0, legacy.stderr || legacy.stdout)
  t.ok(legacy.stdout.includes('uses legacy health only'))
  t.absent(existsSync(f.resolverArgs), 'missing manifest does not execute manifest parser')
})

test('active public-t1 source retires only after quarantine, durable tombstones, and explicit disabled config', (t) => {
  const f = fixture(t)
  const result = f.run({
    FAKE_CURRENT_SHA: priorSha,
    FAKE_GATEWAY_CONTRACT: 'ordinary\tnoncohort',
    FAKE_SOURCE_GATEWAY_CONTRACT: f.contract,
    FAKE_SOURCE_MANIFEST_PRESENT: '1',
    FAKE_TARGET_MANIFEST_PRESENT: '1'
  })
  t.is(result.status, 0, result.stderr || result.stdout)
  t.ok(result.stdout.includes('source public-t1 gateway is leaving its signed cohort'))
  t.ok(result.stdout.includes('public gateway retired green'))
  const git = readFileSync(f.gitLog, 'utf8')
  t.ok(git.indexOf('show ' + priorSha + ':scripts/verify-public-hive-gateway-quarantine.mjs') <
    git.indexOf('checkout --quiet v1.2.3'), 'current-release verifier closure is frozen before target checkout')
  t.ok(existsSync(f.quarantineArgs))
  t.alike(argsFrom(f.disabledConfigVerifierArgs), [f.gatewayConfig])
  const synced = readFileSync(f.syncLog, 'utf8')
  t.ok(synced.includes(`-f ${f.evidence}`))
  t.ok(synced.includes(`-f ${f.opsEvidence}`))
  t.is(readFileSync(f.systemctlLog, 'utf8').trim().split('\n').filter(line => line === 'restart hiverelay').length, 1)
})

test('retirement blocks checkout on missing disabled proof and succeeds on retry, including legacy target', (t) => {
  const f = fixture(t)
  const base = {
    FAKE_CURRENT_SHA: priorSha,
    FAKE_GATEWAY_CONTRACT: 'ordinary\tnoncohort',
    FAKE_SOURCE_GATEWAY_CONTRACT: f.contract,
    FAKE_SOURCE_MANIFEST_PRESENT: '1',
    FAKE_TARGET_MANIFEST_PRESENT: '0'
  }
  const blocked = f.run({ ...base, FAKE_DISABLED_CONFIG_VERIFIER_STATUS: '41' })
  t.not(blocked.status, 0)
  t.ok(blocked.stdout.includes('operator config remains active'))
  t.absent(readFileSync(f.gitLog, 'utf8').includes('checkout --quiet'), 'no target bytes execute before disabled proof')
  t.ok(existsSync(f.quarantineArgs), 'failed retirement remains edge-contained')

  const retried = f.run(base)
  t.is(retried.status, 0, retried.stderr || retried.stdout)
  t.ok(readFileSync(f.gitLog, 'utf8').includes('checkout --quiet v1.2.3'))
  t.ok(retried.stdout.includes('public gateway retired green'))
})

test('retirement checkout/restart failures restore the exact prior SHA while leaving containment in place', (t) => {
  const checkout = fixture(t)
  const base = {
    FAKE_CURRENT_SHA: priorSha,
    FAKE_GATEWAY_CONTRACT: 'ordinary\tnoncohort',
    FAKE_SOURCE_GATEWAY_CONTRACT: checkout.contract,
    FAKE_SOURCE_MANIFEST_PRESENT: '1',
    FAKE_TARGET_MANIFEST_PRESENT: '1'
  }
  const checkoutFailure = checkout.run({ ...base, FAKE_TARGET_CHECKOUT_STATUS: '9' })
  t.not(checkoutFailure.status, 0)
  const checkoutGit = readFileSync(checkout.gitLog, 'utf8')
  t.ok(checkoutGit.includes('checkout --quiet v1.2.3'))
  t.ok(checkoutGit.includes(`checkout --quiet ${priorSha}`))
  t.ok(existsSync(checkout.quarantineArgs))

  const restart = fixture(t)
  const restartFailure = restart.run({
    ...base,
    FAKE_SOURCE_GATEWAY_CONTRACT: restart.contract,
    FAKE_SYSTEMCTL_FAIL_RESTART_AT: '1'
  })
  t.not(restartFailure.status, 0)
  t.ok(restartFailure.stdout.includes('management service restart failed'))
  t.ok(readFileSync(restart.gitLog, 'utf8').includes(`checkout --quiet ${priorSha}`))
  t.is(readFileSync(restart.systemctlLog, 'utf8').trim().split('\n').filter(line => line.startsWith('restart ')).length, 2,
    'failed activation and rollback each attempt one management restart')
  t.ok(existsSync(restart.quarantineArgs))
})

test('rollback restart failure is critical and never reported healthy', (t) => {
  const f = fixture(t)
  const result = f.run({
    FAKE_CURRENT_SHA: priorSha,
    FAKE_PREFLIGHT_STATUS: '23',
    FAKE_SYSTEMCTL_FAIL_RESTART_AT: '2'
  })
  t.not(result.status, 0)
  t.ok(result.stdout.includes('rollback checkout was restored but management service restart failed'))
  t.absent(result.stdout.includes('management rollback OK'))
})

test('evidence invalidation sync failures are explicit and still force edge containment', (t) => {
  const f = fixture(t)
  const result = f.run({ FAKE_PREFLIGHT_STATUS: '23', FAKE_SYNC_FAIL_AT: '2' })
  t.not(result.status, 0)
  t.ok(result.stdout.includes('could not invalidate stale public gateway evidence'))
  t.ok(existsSync(f.quarantineArgs), 'durability failure cannot leave the public edge open')
  t.ok(existsSync(f.quarantineVerifierArgs), 'live quarantine proof still runs after tombstone sync failure')
})

test('updater rejects unsafe executable boundaries and asks trusted nginx to close when possible', (t) => {
  const writable = fixture(t)
  chmodSync(writable.quarantine, 0o777)
  const writableResult = writable.run({ FAKE_PREFLIGHT_STATUS: '23' })
  t.not(writableResult.status, 0)
  t.ok(writableResult.stdout.includes('gateway quarantine command must be executable and not group/world writable'),
    writableResult.stdout)
  t.ok(readFileSync(writable.nginxBinaryLog, 'utf8').includes('-s stop'))
  t.absent(existsSync(writable.quarantineArgs), 'untrusted helper bytes never execute')

  const linked = fixture(t)
  linkSync(linked.quarantine, path.join(linked.root, 'quarantine-hardlink'))
  const linkedResult = linked.run({ FAKE_PREFLIGHT_STATUS: '23' })
  t.not(linkedResult.status, 0)
  t.ok(linkedResult.stdout.includes('gateway quarantine command must have exactly one link'))
  t.ok(readFileSync(linked.nginxBinaryLog, 'utf8').includes('-s stop'))

  const unsafeNginx = fixture(t)
  writeFileSync(unsafeNginx.nginxBinary, '#!/bin/sh\nprintf nginx-hostile >> "$FAKE_HOSTILE_EXECUTION_LOG"\n')
  chmodSync(unsafeNginx.nginxBinary, 0o777)
  const nginxResult = unsafeNginx.run({ FAKE_PREFLIGHT_STATUS: '23' })
  t.not(nginxResult.status, 0)
  t.ok(nginxResult.stdout.includes('gateway nginx binary must be executable and not group/world writable'))
  t.absent(existsSync(unsafeNginx.quarantineArgs))
  t.absent(existsSync(unsafeNginx.preflightArgs), 'unsafe nginx bytes fail before the preflight child')
  t.absent(existsSync(unsafeNginx.hostileExecutionLog), 'unsafe nginx bytes never execute')

  const staleHelper = fixture(t)
  writeFileSync(staleHelper.quarantine, '#!/bin/sh\nexit 0\n')
  chmodSync(staleHelper.quarantine, 0o755)
  const staleResult = staleHelper.run({ FAKE_PREFLIGHT_STATUS: '23' })
  t.not(staleResult.status, 0)
  t.ok(staleResult.stdout.includes('differs from the signed current-release helper bytes'))
  t.absent(existsSync(staleHelper.quarantineArgs), 'old root-owned helper bytes never execute')
  t.ok(readFileSync(staleHelper.nginxBinaryLog, 'utf8').includes('-s stop'))
})

test('updater trusts nginx and ss before first execution and rejects unsafe parents and links', (t) => {
  const writableSs = fixture(t)
  writeFileSync(writableSs.ssBinary, '#!/bin/sh\nprintf ss-hostile >> "$FAKE_HOSTILE_EXECUTION_LOG"\n')
  chmodSync(writableSs.ssBinary, 0o777)
  const writableSsResult = writableSs.run()
  t.not(writableSsResult.status, 0)
  t.ok(writableSsResult.stdout.includes('gateway ss binary must be executable and not group/world writable'))
  t.absent(existsSync(writableSs.preflightArgs))
  t.absent(existsSync(writableSs.hostileExecutionLog), 'unsafe ss bytes never execute')

  for (const [property, label] of [['nginxBinary', 'nginx'], ['ssBinary', 'ss']]) {
    const linked = fixture(t)
    linkSync(linked[property], path.join(linked.root, `${label}-hardlink`))
    const linkedResult = linked.run()
    t.not(linkedResult.status, 0)
    t.ok(linkedResult.stdout.includes(`gateway ${label} binary must have exactly one link`))
    t.absent(existsSync(linked.preflightArgs), `${label} hardlink fails before preflight`)

    const symlinked = fixture(t)
    const hostile = path.join(symlinked.root, `${label}-hostile`)
    executable(hostile, '#!/bin/sh\nprintf hostile >> "$FAKE_HOSTILE_EXECUTION_LOG"\n')
    rmSync(symlinked[property])
    symlinkSync(hostile, symlinked[property])
    const symlinkResult = symlinked.run()
    t.not(symlinkResult.status, 0)
    t.ok(symlinkResult.stdout.includes(`gateway ${label} binary is not a regular executable`))
    t.absent(existsSync(symlinked.preflightArgs), `${label} symlink fails before preflight`)
    t.absent(existsSync(symlinked.hostileExecutionLog), `${label} symlink target never executes`)
  }

  const writableParent = fixture(t)
  const writableRuntime = path.join(writableParent.root, 'writable-runtime')
  const writableNginx = path.join(writableRuntime, 'nginx')
  mkdirSync(writableRuntime)
  executable(writableNginx, '#!/bin/sh\nprintf \'%s\\n\' "$*" >> "$FAKE_NGINX_BINARY_LOG"\nexit 0\n')
  chmodSync(writableRuntime, 0o777)
  const writableParentResult = writableParent.run({
    HIVERELAY_PUBLIC_GATEWAY_PROBE_NGINX_BINARY: writableNginx,
    FAKE_NGINX_BINARY: writableNginx
  })
  t.not(writableParentResult.status, 0)
  t.ok(writableParentResult.stdout.includes('gateway nginx binary parent is group/world writable'))
  t.absent(existsSync(writableParent.preflightArgs), 'writable parent fails before either binary can execute')
  t.absent(existsSync(writableParent.nginxBinaryLog))
  t.absent(existsSync(writableParent.ssBinaryLog))

  for (const [property, envName, fakeName, label] of [
    ['nginxBinary', 'HIVERELAY_PUBLIC_GATEWAY_PROBE_NGINX_BINARY', 'FAKE_NGINX_BINARY', 'nginx'],
    ['ssBinary', 'HIVERELAY_PUBLIC_GATEWAY_OPS_SS_BINARY', 'FAKE_SS_BINARY', 'ss']
  ]) {
    const linkedAncestor = fixture(t)
    const ancestor = path.join(linkedAncestor.root, `${label}-ancestor-link`)
    symlinkSync(linkedAncestor.root, ancestor)
    const lexicalPath = path.join(ancestor, path.basename(linkedAncestor[property]))
    const result = linkedAncestor.run({
      [envName]: lexicalPath,
      [fakeName]: lexicalPath
    })
    t.not(result.status, 0)
    t.ok(result.stdout.includes(`gateway ${label} binary path must be canonical and contain no symlink ancestors`))
    t.absent(existsSync(linkedAncestor.preflightArgs), `${label} ancestor link fails before preflight`)
    t.absent(existsSync(linkedAncestor.hostileExecutionLog), `${label} ancestor swap cannot execute hostile bytes`)
  }
})

test('updater detects nginx and ss replacement races before later use', (t) => {
  const nginx = fixture(t)
  const nginxResult = nginx.run({
    FAKE_PREFLIGHT_RUN_NGINX: '1',
    FAKE_PREFLIGHT_REPLACE_NGINX: '1'
  })
  t.not(nginxResult.status, 0)
  t.ok(nginxResult.stdout.includes('gateway nginx binary identity changed after its trusted snapshot'))
  t.ok(readFileSync(nginx.nginxBinaryLog, 'utf8').includes('-T'), 'only the snapshotted nginx executes')
  t.absent(existsSync(nginx.hostileExecutionLog), 'replacement nginx is never used for containment')
  t.absent(existsSync(nginx.quarantineArgs))

  const ss = fixture(t)
  const ssResult = ss.run({
    FAKE_OPS_RUN_SS: '1',
    FAKE_OPS_REPLACE_SS: '1'
  })
  t.not(ssResult.status, 0)
  t.ok(ssResult.stdout.includes('gateway ss binary identity changed after its trusted snapshot'))
  t.ok(readFileSync(ss.ssBinaryLog, 'utf8').includes('-H -lntup'), 'only the snapshotted ss executes')
  t.absent(existsSync(ss.hostileExecutionLog), 'replacement ss never executes')
  t.absent(existsSync(ss.opsVerifierArgs), 'ops evidence cannot be accepted after ss replacement')
})

test('updater lock fails closed for held, missing, unsafe, or symlinked lock authority', (t) => {
  const held = fixture(t)
  const heldResult = held.run({ FAKE_FLOCK_STATUS: '1' })
  t.is(heldResult.status, 0)
  t.ok(heldResult.stdout.includes('another run in progress'))
  t.absent(existsSync(held.controlResolverArgs))

  const missing = fixture(t)
  rmSync(path.join(missing.bin, 'flock'))
  const missingResult = missing.run({ PATH: missing.bin })
  t.not(missingResult.status, 0)
  t.absent(existsSync(missing.controlResolverArgs))

  for (const kind of ['symlink', 'writable']) {
    const f = fixture(t)
    const lockRoot = path.join(f.root, `locks-${kind}`)
    mkdirSync(lockRoot)
    const lock = path.join(lockRoot, `hiverelay-updater-${process.geteuid?.() ?? process.getuid()}`)
    if (kind === 'symlink') symlinkSync(f.repo, lock)
    else { mkdirSync(lock); chmodSync(lock, 0o777) }
    const result = f.run({ TMPDIR: lockRoot })
    t.not(result.status, 0)
    t.ok(result.stdout.includes('lock directory'))
    t.absent(existsSync(f.controlResolverArgs))
  }
})

test('missing or malformed relay identity stops before target resolution', (t) => {
  const f = fixture(t)
  writeFileSync(f.updaterConf, 'CHANNEL=stable\n')
  const missing = f.run()
  t.not(missing.status, 0)
  t.ok(missing.stdout.includes('RELAY_NAME is required'))
  t.absent(existsSync(f.gitLog))

  writeFileSync(f.updaterConf, 'CHANNEL=stable\nRELAY_NAME=bad relay\n')
  const malformed = f.run()
  t.not(malformed.status, 0)
  t.ok(malformed.stdout.includes('invalid RELAY_NAME'))
  t.absent(existsSync(f.gitLog))

  writeFileSync(f.updaterConf, 'RELAY_NAME=stable-1\n')
  const missingChannel = f.run()
  t.not(missingChannel.status, 0)
  t.ok(missingChannel.stdout.includes('CHANNEL is required'))
  t.absent(existsSync(f.gitLog))
})