Ctrl K
ComunidadGuías…

src/domain/vps-build-state.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { INSTALL_ROOT, SHARED_ROOT_MARKER_PATH, SHARED_ROOT_MARKER_CONTENT } from "./safety.js";

export const VPS_OPERATION_LOCKS = Object.freeze({
  model: `${INSTALL_ROOT}/.local-model-operation.lock`,
  supergrok: `${INSTALL_ROOT}/.supergrok-operation.lock`,
  claude: `${INSTALL_ROOT}/.claude-operation.lock`,
  oauth: `${INSTALL_ROOT}/.openai-oauth-operation.lock`,
});
const quote = value => `'${value.replaceAll("'", "'\\''")}'`;

// The pinned build inputs exist for these CPUs only. A CPU Docker did not report is never refused.
const SUPPORTED_CPUS = new Set(["x86_64", "aarch64"]);
export function requireSupportedVpsCpu(host, product) {
  if (typeof host?.arch === "string" && !SUPPORTED_CPUS.has(host.arch)) {
    throw Object.assign(new Error(`${product} needs a 64-bit Intel or AMD (x86_64) or ARM (aarch64) server. This server reports another CPU type, so the install would fail. Nothing was changed.`),
      { code: "vps_host_unsupported_cpu" });
  }
}
const identityPattern = /^\d+:\d+$/u;
function validate(lock, identity) {
  if (!Object.values(VPS_OPERATION_LOCKS).includes(lock) ||
      (identity !== undefined && !identityPattern.test(identity))) {
    throw new TypeError("Invalid VPS operation lock identity.");
  }
}

// These are Linux host guards, not a defence against a concurrently hostile root.
// No user-controlled paths or file contents enter the generated cleanup program.
const rootGuard = `[ -d /docker ] && [ ! -L /docker ] && [ "$(stat -c %u /docker)" = 0 ] && [ $((0$(stat -c %a /docker) & 022)) -eq 0 ] && [ -d ${INSTALL_ROOT} ] && [ ! -L ${INSTALL_ROOT} ] && [ "$(stat -c %u ${INSTALL_ROOT})" = 0 ] && [ $((0$(stat -c %a ${INSTALL_ROOT}) & 022)) -eq 0 ] && [ ! -L ${SHARED_ROOT_MARKER_PATH} ] && [ -f ${SHARED_ROOT_MARKER_PATH} ] && [ "$(stat -c %u:%h ${SHARED_ROOT_MARKER_PATH})" = 0:1 ] && [ $((0$(stat -c %a ${SHARED_ROOT_MARKER_PATH}) & 022)) -eq 0 ] && [ "$(stat -c %s ${SHARED_ROOT_MARKER_PATH})" = ${Buffer.byteLength(SHARED_ROOT_MARKER_CONTENT)} ] && [ "$(cat ${SHARED_ROOT_MARKER_PATH})" = ${quote(SHARED_ROOT_MARKER_CONTENT.trim())} ]`;
const noMount = path => `awk -v p=${quote(path)} '$5 == p || index($5, p "/") == 1 { found = 1 } END { exit found ? 1 : 0 }' /proc/self/mountinfo`;
function lockGuard(lock, identity) {
  validate(lock, identity);
  return `${rootGuard} && [ ! -L ${lock} ] && [ -d ${lock} ] && [ "$(stat -c %u:%a ${lock})" = 0:700 ] && [ "$(stat -c '%d:%i' ${lock})" = ${quote(identity)} ] && ${noMount(lock)}`;
}

// Sign-in polls and cancels take this lock without a final confirmation, so taking or resuming
// a lock never changes the shared folder's mode. Confirmed writes do that themselves.
export function createVpsLockCommand(lock) {
  validate(lock);
  return `${rootGuard} && umask 077 && mkdir ${lock} && [ "$(stat -c %u:%a ${lock})" = 0:700 ] && ${noMount(lock)} && stat -c '%d:%i' ${lock}`;
}

export function inspectVpsResumeLockCommand(lock) {
  validate(lock);
  return `${rootGuard} || exit 73; if [ ! -e ${lock} ] && [ ! -L ${lock} ]; then printf none; else [ ! -L ${lock} ] && [ -d ${lock} ] && [ "$(stat -c %u:%a ${lock})" = 0:700 ] && ${noMount(lock)} && [ -z "$(find ${lock} -mindepth 1 -maxdepth 1 -print -quit)" ] && stat -c '%d:%i' ${lock}; fi`;
}

export function claimVpsResumeLockCommand(lock, identity) {
  return `${lockGuard(lock, identity)} && [ -z "$(find ${lock} -mindepth 1 -maxdepth 1 -print -quit)" ] && umask 077 && mkdir ${lock}/recovery && stat -c '%d:%i' ${lock}/recovery`;
}

export function releaseVpsResumeClaimCommand(lock, identity, claimIdentity) {
  validate(lock, claimIdentity);
  return `${lockGuard(lock, identity)} && [ ! -L ${lock}/recovery ] && [ -d ${lock}/recovery ] && [ "$(stat -c '%d:%i:%u:%a' ${lock}/recovery)" = '${claimIdentity}:0:700' ] && rmdir ${lock}/recovery`;
}

export function releaseVpsLockCommand(lock, identity) {
  return `${lockGuard(lock, identity)} && rmdir ${lock}`;
}

export function createVpsBuildStateCommand(lock, identity) {
  return `${lockGuard(lock, identity)} && umask 077 && mkdir ${lock}/buildx && [ "$(stat -c %u:%a ${lock}/buildx)" = 0:700 ] && stat -c '%d:%i' ${lock}/buildx`;
}

export function scopeVpsBuildCommand(lock, identity, stateIdentity, command) {
  validate(lock, stateIdentity);
  if (typeof command !== "string" || !command.startsWith("docker compose ") ||
      /[\r\n\0]/u.test(command) || !/(?: build | run -d )/u.test(command)) {
    throw new TypeError("Only a generated build-capable Compose command may use temporary build state.");
  }
  return `${lockGuard(lock, identity)} && [ ! -L ${lock}/buildx ] && [ -d ${lock}/buildx ] && [ "$(stat -c %u:%a ${lock}/buildx)" = 0:700 ] && [ "$(stat -c '%d:%i' ${lock}/buildx)" = ${quote(stateIdentity)} ] && BUILDX_CONFIG=${quote(`${lock}/buildx`)} BUILDX_BUILDER=default DOCKER_BUILDKIT=1 COMPOSE_BAKE=false ${command}`;
}

export function cleanupVpsBuildStateCommand(lock, identity, stateIdentity) {
  validate(lock, stateIdentity);
  const state = `${lock}/buildx`;
  // Two passes: refuse the entire tree before unlinking anything, then recheck
  // each exact inode immediately before unlink/rmdir. Never follow symlinks,
  // cross a mount (including same-device bind mounts), or remove special files.
  return `${lockGuard(lock, identity)} || exit 73
state=${quote(state)}
expected=${quote(stateIdentity)}
state_guard() {
  ${lockGuard(lock, identity)} && [ ! -L "$state" ] && [ -d "$state" ] && [ "$(stat -c %u:%a "$state")" = 0:700 ] && [ "$(stat -c '%d:%i' "$state")" = "$expected" ]
}
walk() (
  path=$1; depth=$2; action=$3
  [ "$depth" -le 16 ] && [ ! -L "$path" ] || exit 1
  metadata=$(stat -c '%d:%i:%u:%h:%a' -- "$path") || exit 1
  oldIFS=$IFS; IFS=:; set -- $metadata; IFS=$oldIFS
  [ "$1" = "\${expected%%:*}" ] && [ "$3" = 0 ] && [ $((0$5 & 022)) -eq 0 ] || exit 1
  if [ -d "$path" ]; then
    for child in "$path"/* "$path"/.[!.]* "$path"/..?*; do
      if [ ! -e "$child" ] && [ ! -L "$child" ]; then continue; fi
      walk "$child" "$((depth + 1))" "$action" || exit 1
    done
    if [ "$action" = remove ]; then
      state_guard && [ ! -L "$path" ] && [ -d "$path" ] && [ "$(stat -c '%d:%i:%u:%a' -- "$path")" = "$1:$2:$3:$5" ] && rmdir -- "$path" || exit 1
    fi
  elif [ -f "$path" ] && [ "$4" = 1 ]; then
    if [ "$action" = remove ]; then
      state_guard && [ ! -L "$path" ] && [ -f "$path" ] && [ "$(stat -c '%d:%i:%u:%h:%a' -- "$path")" = "$metadata" ] && rm -- "$path" || exit 1
    fi
  else
    exit 1
  fi
)
state_guard && walk "$state" 0 check && walk "$state" 0 remove || exit 73`;
}