Ctrl K
ComunidadGuías…

src/services/local-n8n-sidecar-installer.js

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

Archivo original ↗Preguntar a KiBot
import { createHash, randomBytes as createRandomBytes, randomUUID } from "node:crypto";
import * as defaultFileSystem from "node:fs/promises";
import { homedir } from "node:os";
import { basename, dirname, isAbsolute, join, resolve } from "node:path";

import {
  LOCAL_N8N_SIDECAR_ENDPOINT,
  LOCAL_N8N_SIDECAR_HOSTNAME,
  LOCAL_N8N_SIDECAR_TARGET,
  createLocalN8nSidecarComposeFile,
  createLocalN8nSidecarDockerfile,
  createLocalN8nSidecarDockerignore,
  normalizeLocalN8nSidecarPlan,
  validateDockerObjectId,
} from "../domain/local-n8n-sidecar.js";
import {
  safeSiwcCatalogFailure, safeSiwcRuntimeFailure,
  validateSiwcAuthBinding, validateSiwcRegistrationId,
} from "../domain/safety.js";
import { validateDockerName } from "../domain/validation.js";
import { readCodexImagesCliResult } from "../domain/codex-images.js";
import {
  runLocalProcess,
  lockDownLocalPath,
  validateLocalDockerHost,
} from "../infrastructure/local-process.js";
import { collectSiwcRuntimeAssets } from "./siwc-runtime-assets.js";
import {
  finishAuthHandoff, prepareAuthHandoff, readAuthHandoff, readPendingAuthHandoff, readRegistration, listRegistrations,
  validateSiwcBackgroundConsent, validateSiwcHostId,
} from "./siwc-session.mjs";
import {
  acquireLocalIntegrationLifecycleLock,
  settleLocalIntegrationLifecycleOperation,
  fingerprintLocalSiwcFiles, fingerprintLocalSiwcResources, localSiwcFinalizationFailure,
  localSiwcStagingPath, readLocalSiwcStaging, readLocalSiwcResumeAuthBinding,
  assertNoLocalSiwcOneOffContainers,
} from "./local-integration-lifecycle-lock.js";
import { usageRecordFromCli } from "./model-discovery.mjs";

const COMPOSE_FILENAME = "docker-compose.yml";
const MANAGED_MARKER = ".managed-by-relmio.json";
const ROOT_MARKER = ".managed-by-relmio-root.json";
const ROOT_MARKER_SCHEMA_VERSION = 1;
const MARKER_SCHEMA_VERSION = 2;
const PROJECT_PREFIX = "relmio-n8n-openai-oauth";
const SERVICE_NAME = "openai-oauth";
const MAX_DISCOVERED_CONTAINERS = 100;
const MAX_DOCKER_METADATA_BYTES = 1024 * 1024;
const DOCKER_IMAGE_DIGEST_PATTERN = /^sha256:[a-f0-9]{64}$/u;
const DOCKER_SELECTION_VARIABLES = new Set([
  "BUILDKIT_HOST",
  "DOCKER_CERT_PATH",
  "DOCKER_CONFIG",
  "DOCKER_CONTEXT",
  "DOCKER_HOST",
  "DOCKER_TLS_VERIFY",
]);
const SIWC_ASSET_PATHS = new Set([
  "gateway/openai-oauth-sidecar.mjs", "gateway/codex-chat.js",
  "gateway/codex-app-server.mjs", "services/siwc-session.mjs",
  "services/siwc-handoff.mjs", "infrastructure/local-process.js",
  "services/local-integration-lifecycle-lock.js", "services/codex-images.mjs", "services/model-discovery.mjs",
  "infrastructure/process-identity.js",
]);
const OFFICIAL_N8N_IMAGE = /^(?:(?:(?:docker\.n8n\.io|docker\.io)\/)?n8nio\/n8n)(?::[A-Za-z0-9_.-]{1,128})?(?:@sha256:[a-f0-9]{64})?$/u;
const VERIFIER_SCRIPT = [
  '(async()=>{let key="";for await(const chunk of process.stdin){key+=chunk;',
  'if(key.length>128)process.exit(1)}',
  'const headers={Authorization:"Bearer "+key};',
  'const [health,models]=await Promise.all([fetch("http://n8n-openai-oauth:10531/health"),',
  'fetch("http://n8n-openai-oauth:10531/v1/models",{headers})]);',
  'if(!health.ok||!models.ok)process.exit(1);',
  'process.stdout.write(JSON.stringify(await models.json()))})().catch(()=>process.exit(1));',
].join("");

function isMissing(error) {
  return error?.code === "ENOENT";
}

function validateDockerImageDigest(value) {
  if (typeof value !== "string" || !DOCKER_IMAGE_DIGEST_PATTERN.test(value)) {
    throw new TypeError("Local sidecar runtime image identity is invalid.");
  }
  return value;
}

function assertSupportedPlatform(platform) {
  if (typeof platform !== "string" || platform.length === 0) {
    throw new TypeError("The local platform is invalid.");
  }
}

function rejectDockerEnvironmentOverrides(env) {
  if (!env || typeof env !== "object" || Array.isArray(env)) {
    throw new TypeError("The local process environment is invalid.");
  }
  for (const [name, value] of Object.entries(env)) {
    if (
      DOCKER_SELECTION_VARIABLES.has(name.toUpperCase()) &&
      typeof value === "string" &&
      value !== ""
    ) {
      throw new Error(
        "Relmio local sidecars require the selected Docker context without a Docker environment override.",
      );
    }
  }
}

function validateAbsolutePath(value) {
  if (
    typeof value !== "string" ||
    value.trim() === "" ||
    value.includes("\0") ||
    !isAbsolute(value)
  ) {
    throw new TypeError("Relmio local storage path is invalid.");
  }
  return resolve(value);
}

function validateManagedBase(value) {
  const resolved = validateAbsolutePath(value);
  if (basename(resolved) !== ".relmio") {
    throw new TypeError("Relmio local storage path is invalid.");
  }
  return resolved;
}

function validateInstallRoot(value) {
  const resolved = validateAbsolutePath(value);
  if (
    basename(resolved) !== LOCAL_N8N_SIDECAR_TARGET ||
    basename(dirname(resolved)) !== "local" ||
    basename(resolve(resolved, "..", "..")) !== ".relmio"
  ) {
    throw new TypeError("The local n8n sidecar install directory is invalid.");
  }
  return resolved;
}

export async function resolveLocalN8nSidecarInstallRoot({
  env = process.env,
  homeDirectory = homedir(),
  fileSystem = defaultFileSystem,
  platform = process.platform,
} = {}) {
  assertSupportedPlatform(platform);
  const configuredHome =
    typeof env.RELMIO_HOME === "string" && env.RELMIO_HOME.trim() !== ""
      ? env.RELMIO_HOME
      : resolve(homeDirectory, ".relmio");
  const requestedHome = validateManagedBase(configuredHome);
  const requestedParent = dirname(requestedHome);
  let canonicalParent;
  try {
    canonicalParent = await fileSystem.realpath(requestedParent);
  } catch {
    throw new Error("The parent of the Relmio local storage directory is invalid.");
  }
  if (canonicalParent !== resolve(requestedParent)) {
    throw new Error(
      "Relmio refuses a local storage path with a symbolic-link ancestor.",
    );
  }
  return join(canonicalParent, ".relmio", "local", LOCAL_N8N_SIDECAR_TARGET);
}

function localN8nSidecarSnapshot(marker, account = null) {
  const migrationRequired = marker.schemaVersion !== MARKER_SCHEMA_VERSION;
  const connected = !migrationRequired && account?.ownership === "owned" &&
    account?.session === "connected" && account?.planEnabled === true;
  return {
    target: LOCAL_N8N_SIDECAR_TARGET,
    endpoint: LOCAL_N8N_SIDECAR_ENDPOINT,
    auth: {
      configured: connected,
      disclosure: "server-managed",
      ...(!migrationRequired && account ? { account } : {}),
    },
    ...(!migrationRequired ? { registrationId: marker.registrationId } : {}),
    migrationRequired,
    canRefreshCredential: false,
    canRemove: true,
  };
}

function parseSidecarStatusRecord(output, marker) {
  let records;
  try {
    const parsed = JSON.parse(output);
    records = Array.isArray(parsed) ? parsed : [parsed];
  } catch {
    throw new Error("The local sidecar status metadata is invalid.");
  }
  const record = records[0];
  if (
    records.length !== 1 ||
    record?.Name !== `${marker.projectName}-${SERVICE_NAME}-1` ||
    record?.Service !== SERVICE_NAME ||
    typeof record?.State !== "string" ||
    typeof record?.Health !== "string"
  ) {
    throw new Error("The local sidecar status metadata is invalid.");
  }
  assertNoPublishedHostPort(output);
  return record;
}

async function verifyWindowsSidecarStatusPathSecurity({
  fileSystem,
  installRoot,
  platform,
  lockDownPath,
}) {
  if (platform !== "win32") return;
  const relmioHome = resolve(installRoot, "..", "..");
  for (const path of [relmioHome, join(relmioHome, "local"), installRoot]) {
    assertDirectory(await lstatIfExists(fileSystem, path));
    await lockDownPath(path, { platform, verifyOnly: true });
  }
  for (const path of [
    join(relmioHome, ROOT_MARKER),
    join(installRoot, MANAGED_MARKER),
    join(installRoot, COMPOSE_FILENAME),
  ]) {
    const metadata = await lstatIfExists(fileSystem, path);
    if (!metadata?.isFile?.() || metadata.isSymbolicLink()) {
      throw new Error("Relmio refuses an unsafe local sidecar managed file.");
    }
    await lockDownPath(path, {
      platform,
      kind: "file",
      verifyOnly: true,
      verifyEffectiveOwnerOnly: true,
    });
  }
}

export async function getLocalN8nSidecarStatus({
  env = process.env,
  homeDirectory = homedir(),
  fileSystem = defaultFileSystem,
  runProcess = runLocalProcess,
  platform = process.platform,
  lockDownPath = lockDownLocalPath,
} = {}) {
  const absent = {
    target: LOCAL_N8N_SIDECAR_TARGET,
    managed: false,
    state: "absent",
  };
  const unavailable = {
    target: LOCAL_N8N_SIDECAR_TARGET,
    managed: false,
    state: "unavailable",
  };
  try {
    const installRoot = await resolveLocalN8nSidecarInstallRoot({
      env,
      homeDirectory,
      fileSystem,
      platform,
    });
    const staged = await readLocalSiwcStaging({ fileSystem, installRoot, platform, lockDownPath });
    if (staged && staged.checkpoint.stage !== "completed") {
      await fingerprintLocalSiwcFiles({ fileSystem, installRoot, platform, lockDownPath });
      const { installId, registrationId, stage } = staged.checkpoint;
      return { target: LOCAL_N8N_SIDECAR_TARGET, managed: true, state: "staged",
        staging: { installId, registrationId, stage } };
    }
    if (await lstatIfExists(fileSystem, installRoot)) {
      await verifyWindowsSidecarStatusPathSecurity({
        fileSystem,
        installRoot,
        platform,
        lockDownPath,
      });
    }
    const managed = await inspectManagedInstall({ fileSystem, installRoot });
    if (!managed.marker) return absent;
    const marker = validateMarker(managed.marker);
    if (platform === "win32" && marker.schemaVersion === MARKER_SCHEMA_VERSION) {
      for (const relative of [
        "Dockerfile", ".dockerignore", "package.json", "package-lock.json",
        "services/siwc-session.mjs", "services/siwc-handoff.mjs",
        "gateway/openai-oauth-sidecar.mjs", "infrastructure/local-process.js",
        "services/local-integration-lifecycle-lock.js", "services/codex-images.mjs", "services/model-discovery.mjs",
        "infrastructure/process-identity.js",
      ]) {
        const path = join(installRoot, relative);
        const metadata = await lstatIfExists(fileSystem, path);
        // Installs made before the image add-on or model discovery lack these files; verify them whenever present.
        if (!metadata && ["services/codex-images.mjs", "services/model-discovery.mjs"].includes(relative)) continue;
        if (!metadata?.isFile?.() || metadata.isSymbolicLink()) {
          throw new Error("The installed SIWC runtime asset is missing or unsafe.");
        }
        await lockDownPath(path, {
          platform, kind: "file", verifyOnly: true, verifyEffectiveOwnerOnly: true,
        });
      }
    }
    if (marker.schemaVersion === MARKER_SCHEMA_VERSION) {
      await assertManagedSiwcCompose(fileSystem, installRoot, marker);
    }
    const selectedDockerHost = await resolveLocalDockerHost({
      runProcess,
      cwd: installRoot,
      env,
      platform,
    });
    if (selectedDockerHost !== marker.dockerHost) return unavailable;
    if (marker.schemaVersion === MARKER_SCHEMA_VERSION && marker.legacyInstallId) {
      const migrationState = await readLegacyN8nMigrationState(
        fileSystem, installRoot, marker.legacyInstallId,
      );
      if (migrationState !== "transferred") {
        return {
          target: LOCAL_N8N_SIDECAR_TARGET, managed: true, state: "partial",
          snapshot: {
            target: LOCAL_N8N_SIDECAR_TARGET,
            endpoint: LOCAL_N8N_SIDECAR_ENDPOINT,
            auth: { configured: false, disclosure: "server-managed" },
            canRefreshCredential: false, canRemove: true,
            migrationRequired: !marker.previousWasSiwc,
            replacementRequired: !!marker.previousWasSiwc,
            migrationState: migrationState ?? "incomplete",
            legacyResourcesPreserved: true,
          },
        };
      }
    }
    await attestPlanAndAlias({
      plan: marker,
      runProcess,
      cwd: installRoot,
      installId: marker.installId,
      projectName: marker.projectName,
    });
    const ownership = await attestProjectOwnership({
      runProcess,
      cwd: installRoot,
      dockerHost: marker.dockerHost,
      installId: marker.installId,
      projectName: marker.projectName,
      returnDetails: true,
      volumeName: marker.schemaVersion === MARKER_SCHEMA_VERSION ? "siwc-store" : "oauth-auth",
    });
    if (!ownership.exact) {
      return {
        target: LOCAL_N8N_SIDECAR_TARGET,
        managed: true,
        state: "partial",
      };
    }
    if (marker.schemaVersion !== MARKER_SCHEMA_VERSION) {
      const migrationState = await readLegacyN8nMigrationState(
        fileSystem, installRoot, marker.installId,
      );
      if (migrationState === "transferred") {
        throw new Error("The legacy n8n migration metadata is inconsistent.");
      }
      return {
        target: LOCAL_N8N_SIDECAR_TARGET,
        managed: true, state: migrationState ? "partial" : "legacy",
        snapshot: {
          ...localN8nSidecarSnapshot(marker),
          ...(migrationState ? { migrationState, legacyResourcesPreserved: true } : {}),
        },
      };
    }
    const publication = await runOrThrow(
      runProcess,
      {
        file: "docker",
        args: createComposeArgs(marker.projectName, [
          "ps",
          "--all",
          "--format",
          "json",
          SERVICE_NAME,
        ]),
        cwd: installRoot,
        dockerHost: marker.dockerHost,
      },
      "Local sidecar inventory publication check",
    );
    const statusRecord = parseSidecarStatusRecord(publication.stdout, marker);
    const runtime = await inspectOwnedSidecarRuntime({
      runProcess,
      installRoot,
      marker,
    });
    let account = null;
    if (runtime?.running && !runtime.paused &&
        statusRecord.State === "running") {
      try {
        account = (await runSiwcCli({
          runProcess, installRoot, marker, command: "account-live",
        })).account;
        if (account?.registrationId !== marker.registrationId ||
            account?.ownerHostId !== marker.ownerHostId ||
            account?.ownerRuntimeId !== marker.installId ||
            account?.ownership !== "owned") {
          throw new Error("The installed SIWC account cannot be attested.");
        }
      } catch {
        return {
          target: LOCAL_N8N_SIDECAR_TARGET,
          managed: true, state: "partial",
          snapshot: localN8nSidecarSnapshot(marker),
        };
      }
    }
    const snapshot = localN8nSidecarSnapshot(marker, account);
    if (!runtime) {
      return {
        target: LOCAL_N8N_SIDECAR_TARGET,
        managed: true,
        state: "partial",
      };
    }
    if (runtime.paused) {
      return {
        target: LOCAL_N8N_SIDECAR_TARGET,
        managed: true,
        state: "partial",
      };
    }
    if (!runtime.running) {
      return ["created", "exited"].includes(statusRecord.State) &&
        !["starting", "unhealthy"].includes(statusRecord.Health)
        ? {
            target: LOCAL_N8N_SIDECAR_TARGET,
            managed: true,
            state: "stopped",
            snapshot,
          }
        : {
            target: LOCAL_N8N_SIDECAR_TARGET,
            managed: true,
            state: "partial",
          };
    }
    if (
      statusRecord.State !== "running" ||
      statusRecord.Health !== "healthy" ||
      runtime.health !== "healthy"
    ) {
      return {
        target: LOCAL_N8N_SIDECAR_TARGET,
        managed: true,
        state: "partial",
      };
    }
    await verifyRunningSidecar({
      runProcess,
      installRoot,
      plan: marker,
      installId: marker.installId,
      projectName: marker.projectName,
    });
    return {
      target: LOCAL_N8N_SIDECAR_TARGET,
      managed: true,
      state: "healthy",
      snapshot,
    };
  } catch {
    return unavailable;
  }
}

// Read-only: the installed local sidecar's stored request counts, as usageRecordFromCli reads them, or
// undefined when no running SIWC sidecar owned by this install can be attested. Nothing is changed.
export async function getLocalN8nSidecarUsage({
  env = process.env,
  homeDirectory = homedir(),
  fileSystem = defaultFileSystem,
  runProcess = runLocalProcess,
  platform = process.platform,
  lockDownPath = lockDownLocalPath,
} = {}) {
  try {
    const installRoot = await resolveLocalN8nSidecarInstallRoot({ env, homeDirectory, fileSystem, platform });
    if (!await lstatIfExists(fileSystem, installRoot)) return undefined;
    await verifyWindowsSidecarStatusPathSecurity({ fileSystem, installRoot, platform, lockDownPath });
    const managed = await inspectManagedInstall({ fileSystem, installRoot });
    if (!managed.marker) return undefined;
    const marker = validateMarker(managed.marker);
    await assertManagedSiwcCompose(fileSystem, installRoot, marker);
    if (await resolveLocalDockerHost({ runProcess, cwd: installRoot, env, platform }) !== marker.dockerHost) return undefined;
    const runtime = await inspectOwnedSidecarRuntime({ runProcess, installRoot, marker });
    if (!runtime?.running || runtime.paused) return undefined;
    await attestProjectOwnership({ runProcess, cwd: installRoot, dockerHost: marker.dockerHost,
      installId: marker.installId, projectName: marker.projectName });
    return usageRecordFromCli(await runProcess({
      file: "docker",
      args: createComposeArgs(marker.projectName, [
        "exec", "-T", SERVICE_NAME, "node", "/app/services/model-discovery.mjs", "usage",
      ]),
      cwd: installRoot,
      dockerHost: marker.dockerHost,
    }), marker.registrationId);
  } catch {
    return undefined;
  }
}

async function resolveLocalDockerHost({ runProcess, cwd, env, platform }) {
  assertSupportedPlatform(platform);
  rejectDockerEnvironmentOverrides(env);
  const context = await runProcess({
    file: "docker",
    args: [
      "context",
      "inspect",
      "--format",
      "{{json .Endpoints.docker.Host}}",
    ],
    cwd,
  });
  if (context.code !== 0) {
    throw new Error("The selected Docker context could not be inspected.");
  }
  let candidate;
  try {
    candidate = JSON.parse(context.stdout.trim());
  } catch {
    throw new Error("The selected Docker context is not a local Docker daemon.");
  }
  let dockerHost;
  try {
    dockerHost = validateLocalDockerHost(candidate, { platform });
  } catch {
    throw new Error("The selected Docker context is not a local Docker daemon.");
  }
  if (platform === "win32" && dockerHost.startsWith("npipe:")) {
    const selectedContext = await runProcess({ file: "docker", args: ["context", "show"], cwd });
    if (selectedContext.code !== 0 || selectedContext.stdout.trim() !== "desktop-linux") {
      throw new Error("Docker Desktop's local Linux engine must be selected.");
    }
  }
  return dockerHost;
}

async function runOrThrow(runProcess, spec, label) {
  const result = await runProcess(spec);
  if (result.code !== 0) {
    throw new Error(`${label} failed.`);
  }
  return result;
}

function parseJson(value, label) {
  if (
    typeof value !== "string" ||
    value.length === 0 ||
    Buffer.byteLength(value) > MAX_DOCKER_METADATA_BYTES
  ) {
    throw new Error(`${label} returned invalid Docker metadata.`);
  }
  try {
    return JSON.parse(value);
  } catch {
    throw new Error(`${label} returned invalid Docker metadata.`);
  }
}

function parseJsonLines(value, label) {
  if (typeof value !== "string" || Buffer.byteLength(value) > MAX_DOCKER_METADATA_BYTES) {
    throw new Error(`${label} returned invalid Docker metadata.`);
  }
  if (value.trim() === "") {
    return [];
  }
  return value
    .trim()
    .split("\n")
    .map((line) => parseJson(line, label));
}

function validateVersion(value, label) {
  const normalized = typeof value === "string" ? value.trim() : "";
  if (!/^[A-Za-z0-9.+-]{1,64}$/u.test(normalized)) {
    throw new Error(`${label} returned an invalid version.`);
  }
  return normalized;
}

function isOfficialN8nImage(value) {
  return typeof value === "string" && OFFICIAL_N8N_IMAGE.test(value);
}

function parseContainerName(value) {
  const normalized = typeof value === "string" && value.startsWith("/")
    ? value.slice(1)
    : value;
  return validateDockerName(normalized);
}

async function inspectContainer({ runProcess, cwd, dockerHost, containerId }) {
  const result = await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: ["container", "inspect", "--format", "{{json .}}", containerId],
      cwd,
      dockerHost,
    },
    "Docker container inspection",
  );
  return parseJson(result.stdout.trim(), "Docker container inspection");
}

async function inspectNetwork({ runProcess, cwd, dockerHost, networkName }) {
  const result = await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: ["network", "inspect", "--format", "{{json .}}", networkName],
      cwd,
      dockerHost,
    },
    "Docker network inspection",
  );
  return parseJson(result.stdout.trim(), "Docker network inspection");
}

function validateDiscoveredN8nContainer(inspected) {
  const containerId = validateDockerObjectId(inspected?.Id, "n8n container");
  const containerName = parseContainerName(inspected?.Name);
  const image = inspected?.Config?.Image;
  if (!isOfficialN8nImage(image) || inspected?.State?.Running !== true) {
    throw new Error("The selected container is not a running official n8n container.");
  }
  if (
    !inspected.NetworkSettings?.Networks ||
    typeof inspected.NetworkSettings.Networks !== "object" ||
    Array.isArray(inspected.NetworkSettings.Networks)
  ) {
    throw new Error("The selected n8n container network metadata is invalid.");
  }
  return { containerId, containerName, image };
}

function validateSelectedNetwork(inspected, { n8nContainerId, expectedName }) {
  const dockerNetworkId = validateDockerObjectId(
    inspected?.Id,
    "Docker network",
  );
  const networkName = validateDockerName(inspected?.Name);
  if (
    networkName !== expectedName ||
    inspected?.Driver !== "bridge" ||
    inspected?.Scope !== "local" ||
    inspected?.Internal !== false ||
    !inspected?.Containers ||
    typeof inspected.Containers !== "object" ||
    Array.isArray(inspected.Containers) ||
    (n8nContainerId !== undefined && !Object.prototype.hasOwnProperty.call(inspected.Containers, n8nContainerId))
  ) {
    if (inspected?.Internal === true) {
      throw new Error(
        "The selected n8n Docker network has no outbound Internet access. Choose a non-internal Docker network and review a fresh plan.",
      );
    }
    throw new Error("The selected n8n Docker network is invalid.");
  }
  const labels = inspected.Labels;
  return {
    dockerNetworkId,
    networkName,
    disposable:
      labels &&
      typeof labels === "object" &&
      labels["com.relmio.disposable"] === "true",
  };
}

export async function discoverLocalN8nSidecarTargets({
  runProcess = runLocalProcess,
  cwd = process.cwd(),
  env = process.env,
  platform = process.platform,
} = {}) {
  const dockerHost = await resolveLocalDockerHost({
    runProcess,
    cwd,
    env,
    platform,
  });
  const docker = await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: ["version", "--format", "{{.Server.Version}}"],
      cwd,
      dockerHost,
    },
    "Docker version check",
  );
  const compose = await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: ["compose", "version", "--short"],
      cwd,
      dockerHost,
    },
    "Docker Compose version check",
  );
  const listed = await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: ["ps", "--filter", "status=running", "--format", "{{json .}}"],
      cwd,
      dockerHost,
    },
    "n8n container discovery",
  );
  const candidates = parseJsonLines(listed.stdout, "n8n container discovery")
    .filter((entry) => isOfficialN8nImage(entry?.Image))
    .slice(0, MAX_DISCOVERED_CONTAINERS);
  const containers = [];
  for (const candidate of candidates) {
    if (typeof candidate?.ID !== "string" || !/^[a-f0-9]{12,64}$/u.test(candidate.ID)) {
      continue;
    }
    const inspected = await inspectContainer({
      runProcess,
      cwd,
      dockerHost,
      containerId: candidate.ID,
    });
    const container = validateDiscoveredN8nContainer(inspected);
    const networks = [];
    for (const networkName of Object.keys(inspected.NetworkSettings.Networks)) {
      let safeNetworkName;
      try {
        safeNetworkName = validateDockerName(networkName);
      } catch {
        continue;
      }
      if (["bridge", "host", "none"].includes(safeNetworkName)) {
        continue;
      }
      const network = await inspectNetwork({
        runProcess,
        cwd,
        dockerHost,
        networkName: safeNetworkName,
      });
      try {
        networks.push(
          validateSelectedNetwork(network, {
            n8nContainerId: container.containerId,
            expectedName: safeNetworkName,
          }),
        );
      } catch {
        // Discovery omits networks that cannot safely host the private sidecar.
      }
    }
    if (networks.length > 0) {
      containers.push({ ...container, networks });
    }
  }
  return {
    dockerAvailable: true,
    dockerVersion: validateVersion(docker.stdout, "Docker"),
    composeVersion: validateVersion(compose.stdout, "Docker Compose"),
    dockerHost,
    containers,
  };
}

async function lstatIfExists(fileSystem, path) {
  try {
    return await fileSystem.lstat(path);
  } catch (error) {
    if (isMissing(error)) {
      return null;
    }
    throw new Error("Relmio could not inspect its local managed directory.");
  }
}

function assertDirectory(metadata) {
  if (metadata.isSymbolicLink() || !metadata.isDirectory()) {
    throw new Error("Relmio refuses an unsafe local managed directory.");
  }
}

async function writeManagedFile(fileSystem, path, contents, mode) {
  const existing = await lstatIfExists(fileSystem, path);
  if (existing && (existing.isSymbolicLink() || !existing.isFile())) {
    throw new Error("Relmio refuses to replace a non-file in its managed directory.");
  }
  const temporaryPath = `${path}.tmp-${randomUUID()}`;
  try {
    await fileSystem.writeFile(temporaryPath, contents, { flag: "wx", mode });
    await fileSystem.chmod(temporaryPath, mode);
    await fileSystem.rename(temporaryPath, path);
    await fileSystem.chmod(path, mode);
  } catch {
    try {
      await fileSystem.unlink(temporaryPath);
    } catch {
      // The temporary file may not have been created.
    }
    throw new Error("Relmio could not write its local n8n sidecar files.");
  }
}






async function ensurePrivateDirectory(fileSystem, path, platform, lockDownPath) {
  const metadata = await lstatIfExists(fileSystem, path);
  if (metadata) {
    assertDirectory(metadata);
  } else {
    await fileSystem.mkdir(path, { mode: 0o700 });
  }
  await fileSystem.chmod(path, 0o700);
  if (platform === "win32") await lockDownPath(path, { platform });
}

async function inspectManagedInstall({ fileSystem, installRoot, staging }) {
  const relmioHome = resolve(installRoot, "..", "..");
  const localRoot = join(relmioHome, "local");
  const homeMetadata = await lstatIfExists(fileSystem, relmioHome);
  if (!homeMetadata) {
    return { baseExists: false, marker: null, deploymentMode: "installed" };
  }
  assertDirectory(homeMetadata);
  const rootMarkerMetadata = await lstatIfExists(
    fileSystem,
    join(relmioHome, ROOT_MARKER),
  );
  if (
    !rootMarkerMetadata ||
    rootMarkerMetadata.isSymbolicLink() ||
    !rootMarkerMetadata.isFile()
  ) {
    throw new Error(
      "The Relmio local storage directory is not an owned managed root. Nothing was changed.",
    );
  }
  let rootMarker;
  try {
    rootMarker = JSON.parse(
      await fileSystem.readFile(join(relmioHome, ROOT_MARKER), "utf8"),
    );
  } catch {
    throw new Error("The Relmio local managed-root marker is invalid.");
  }
  if (
    rootMarker?.schemaVersion !== ROOT_MARKER_SCHEMA_VERSION ||
    rootMarker?.kind !== "relmio-local-root"
  ) {
    throw new Error("The Relmio local managed-root marker is invalid.");
  }
  for (const path of [localRoot, installRoot]) {
    const metadata = await lstatIfExists(fileSystem, path);
    if (metadata) {
      assertDirectory(metadata);
    }
  }
  const installMetadata = await lstatIfExists(fileSystem, installRoot);
  if (!installMetadata) {
    return { baseExists: true, marker: null, deploymentMode: "installed" };
  }
  if (staging && !(await lstatIfExists(fileSystem, join(installRoot, MANAGED_MARKER)))) {
    return { baseExists: true, marker: null, deploymentMode: "installed" };
  }
  const markerMetadata = await lstatIfExists(
    fileSystem,
    join(installRoot, MANAGED_MARKER),
  );
  if (
    !markerMetadata ||
    markerMetadata.isSymbolicLink() ||
    !markerMetadata.isFile()
  ) {
    throw new Error(
      "The local n8n sidecar directory is unmanaged. Nothing was overwritten.",
    );
  }
  let marker;
  try {
    marker = JSON.parse(
      await fileSystem.readFile(join(installRoot, MANAGED_MARKER), "utf8"),
    );
    validateMarker(marker);
  } catch {
    throw new Error("The local n8n sidecar managed marker is invalid.");
  }
  return { baseExists: true, marker, deploymentMode: "updated" };
}

function validateMarker(marker) {
  const installId =
    typeof marker?.installId === "string" && /^[a-f0-9]{32}$/u.test(marker.installId)
      ? marker.installId
      : null;
  const expectedProjectName = installId ? `${PROJECT_PREFIX}-${installId}` : null;
  if (
    ![1, MARKER_SCHEMA_VERSION].includes(marker?.schemaVersion) ||
    marker?.kind !== "relmio-local-n8n-sidecar" ||
    marker?.target !== LOCAL_N8N_SIDECAR_TARGET ||
    marker?.projectName !== expectedProjectName
  ) {
    throw new TypeError("The local n8n sidecar marker is invalid.");
  }
  validateLocalDockerHost(marker.dockerHost);
  validateDockerObjectId(marker.n8nContainerId, "n8n container");
  validateDockerName(marker.n8nContainerName);
  validateDockerObjectId(marker.dockerNetworkId, "Docker network");
  validateDockerName(marker.networkName);
  if (marker.schemaVersion === MARKER_SCHEMA_VERSION) {
    validateSiwcRegistrationId(marker.registrationId);
    validateSiwcHostId(marker.ownerHostId);
    if (typeof marker.clientId !== "string" || !/^[!-~]{1,256}$/u.test(marker.clientId) ||
        typeof marker.tokenSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(marker.tokenSha256)) {
      throw new TypeError("The local n8n sidecar marker is invalid.");
    }
    if (marker.legacyInstallId !== undefined) {
      if (typeof marker.legacyInstallId !== "string" ||
          !/^[a-f0-9]{32}$/u.test(marker.legacyInstallId) ||
          marker.legacyInstallId === installId) {
        throw new TypeError("The local n8n migration marker is invalid.");
      }
    }
    if (marker.previousWasSiwc !== undefined &&
        (marker.previousWasSiwc !== true || !marker.legacyInstallId)) {
      throw new TypeError("The local n8n replacement marker is invalid.");
    }
  }
  return marker;
}

async function readLegacyN8nMigrationState(fileSystem, installRoot, installId) {
  const legacyRoot = join(installRoot, "legacy");
  const parent = await lstatIfExists(fileSystem, legacyRoot);
  if (!parent) return null;
  assertDirectory(parent);
  const archive = join(legacyRoot, installId);
  const metadata = await lstatIfExists(fileSystem, archive);
  if (!metadata) return null;
  assertDirectory(metadata);
  const journalPath = join(archive, "migration.json");
  const journal = await lstatIfExists(fileSystem, journalPath);
  if (!journal) return "incomplete";
  if (!journal.isFile() || journal.isSymbolicLink() || journal.size > 4096) {
    throw new Error("The local n8n migration journal is unsafe.");
  }
  let record;
  try { record = JSON.parse(await fileSystem.readFile(journalPath, "utf8")); }
  catch { throw new Error("The local n8n migration journal is invalid."); }
  if (record?.schemaVersion !== 1 ||
      record?.reviewedLegacy?.installId !== installId ||
      !["prepared", "stopped", "transferred"].includes(record?.state)) {
    throw new Error("The local n8n migration journal needs manual inspection.");
  }
  return record.state;
}

async function assertManagedSiwcCompose(fileSystem, installRoot, marker) {
  if (marker.schemaVersion !== MARKER_SCHEMA_VERSION) {
    throw new Error("The legacy bridge needs a fresh SIWC sign-in and reviewed migration.");
  }
  const path = join(installRoot, COMPOSE_FILENAME);
  const metadata = await lstatIfExists(fileSystem, path);
  if (!metadata?.isFile?.() || metadata.isSymbolicLink()) {
    throw new Error("The installed SIWC Compose file is missing or unsafe.");
  }
  const expected = createLocalN8nSidecarComposeFile({
    installId: marker.installId,
    networkName: marker.networkName,
    registrationId: marker.registrationId,
    tokenSha256: marker.tokenSha256,
  });
  if (await fileSystem.readFile(path, "utf8") !== expected) {
    throw new Error("The installed SIWC Compose file changed; the owned service was not mutated.");
  }
}

async function initializeManagedDirectories({
  fileSystem,
  installRoot,
  baseExists,
  platform,
  lockDownPath,
}) {
  const relmioHome = resolve(installRoot, "..", "..");
  if (!baseExists) {
    let createdIdentity = null;
    try {
      await fileSystem.mkdir(relmioHome, { mode: 0o700 });
      createdIdentity = await captureFreshDirectoryIdentity(fileSystem, relmioHome);
      await fileSystem.chmod(relmioHome, 0o700);
      if (platform === "win32") await lockDownPath(relmioHome, { platform });
      await writeManagedFile(
        fileSystem,
        join(relmioHome, ROOT_MARKER),
        `${JSON.stringify({
          schemaVersion: ROOT_MARKER_SCHEMA_VERSION,
          kind: "relmio-local-root",
        })}\n`,
        0o600,
      );
    } catch (error) {
      await removeFreshEmptyManagedRoot({
        fileSystem,
        relmioHome,
        createdIdentity,
      });
      throw error;
    }
  }
  await fileSystem.chmod(relmioHome, 0o700);
  if (platform === "win32") await lockDownPath(relmioHome, { platform });
  await ensurePrivateDirectory(fileSystem, join(relmioHome, "local"), platform, lockDownPath);
  await ensurePrivateDirectory(fileSystem, installRoot, platform, lockDownPath);
}

function isDirectoryIdentity(metadata, identity) {
  return (
    metadata !== null &&
    !metadata.isSymbolicLink() &&
    metadata.isDirectory() &&
    identity !== null &&
    metadata.dev === identity.dev &&
    metadata.ino === identity.ino
  );
}

async function captureFreshDirectoryIdentity(fileSystem, path) {
  const metadata = await lstatIfExists(fileSystem, path);
  if (!metadata || metadata.isSymbolicLink() || !metadata.isDirectory()) {
    throw new Error("Relmio could not verify its newly created local storage directory.");
  }
  return { dev: metadata.dev, ino: metadata.ino };
}

async function removeFreshEmptyManagedRoot({
  fileSystem,
  relmioHome,
  createdIdentity,
}) {
  if (!createdIdentity) return;
  try {
    let metadata = await lstatIfExists(fileSystem, relmioHome);
    if (!isDirectoryIdentity(metadata, createdIdentity)) return;
    if ((await fileSystem.readdir(relmioHome)).length !== 0) return;
    metadata = await lstatIfExists(fileSystem, relmioHome);
    if (!isDirectoryIdentity(metadata, createdIdentity)) return;
    await fileSystem.rmdir(relmioHome);
  } catch {
    // Only an exact, still-empty root may be removed during recovery.
  }
}

async function acquireSidecarLock({
  fileSystem,
  getProcessIdentity,
  installRoot,
  lockDownPath,
  now,
  platform,
}) {
  const safeInstallRoot = validateInstallRoot(installRoot);
  const lockPath = join(
    dirname(resolve(safeInstallRoot, "..", "..")),
    ".relmio-local-n8n-openai-oauth.lock",
  );
  return acquireLocalIntegrationLifecycleLock({
    fileSystem,
    getProcessIdentity,
    lockDownPath,
    lockPath,
    now,
    // Lock ownership is local-process state, not the caller's Docker fixture.
    platform: process.platform,
    label: "local n8n OAuth sidecar operation lock",
  });
}

function requireOwnershipLabels(labels, { installId, projectName, service }) {
  if (!labels || typeof labels !== "object" || Array.isArray(labels)) {
    throw new Error("The local sidecar Docker ownership metadata is invalid.");
  }
  if (
    labels["com.docker.compose.project"] !== projectName ||
    labels["io.relmio.managed"] !== "true" ||
    labels["io.relmio.target"] !== LOCAL_N8N_SIDECAR_TARGET ||
    labels["io.relmio.install"] !== installId ||
    (service && labels["com.docker.compose.service"] !== SERVICE_NAME)
  ) {
    throw new Error(
      "A Docker resource uses this Relmio project identity without matching ownership. Nothing was changed.",
    );
  }
}

async function attestProjectOwnership({
  runProcess,
  cwd,
  dockerHost,
  installId,
  projectName,
  returnDetails = false,
  volumeName = "siwc-store",
}) {
  const projectFilter = `label=com.docker.compose.project=${projectName}`;
  const containers = await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: [
        "ps",
        "--all",
        "--no-trunc",
        "--filter",
        projectFilter,
        "--format",
        "{{json .}}",
      ],
      cwd,
      dockerHost,
    },
    "Local sidecar container ownership check",
  );
  const containerRows = parseJsonLines(
    containers.stdout,
    "Local sidecar container ownership check",
  );
  if (containerRows.length > MAX_DISCOVERED_CONTAINERS) {
    throw new Error("The local sidecar container ownership check failed closed.");
  }
  for (const row of containerRows) {
    const containerId = validateDockerObjectId(
      row?.ID,
      "local sidecar container",
    );
    const inspected = await inspectContainer({
      runProcess,
      cwd,
      dockerHost,
      containerId,
    });
    if (inspected?.Id !== containerId) {
      throw new Error("The local sidecar Docker ownership metadata is invalid.");
    }
    requireOwnershipLabels(inspected.Config?.Labels, {
      installId,
      projectName,
      service: true,
    });
  }
  const volumes = await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: ["volume", "ls", "--filter", projectFilter, "--format", "{{json .}}"],
      cwd,
      dockerHost,
    },
    "Local sidecar volume ownership check",
  );
  const volumeRows = parseJsonLines(
    volumes.stdout,
    "Local sidecar volume ownership check",
  );
  if (volumeRows.length > MAX_DISCOVERED_CONTAINERS) {
    throw new Error("The local sidecar volume ownership check failed closed.");
  }
  const volumeNames = [];
  for (const row of volumeRows) {
    const volumeName = validateDockerName(row?.Name);
    volumeNames.push(volumeName);
    const inspected = await runOrThrow(
      runProcess,
      {
        file: "docker",
        args: [
          "volume",
          "inspect",
          "--format",
          "{{json .Labels}}",
          volumeName,
        ],
        cwd,
        dockerHost,
      },
      "Local sidecar volume ownership inspection",
    );
    requireOwnershipLabels(
      parseJson(
        inspected.stdout.trim(),
        "Local sidecar volume ownership inspection",
      ),
      { installId, projectName, service: false },
    );
  }
  const imagePresent = await inspectOwnedImageIfPresent({
    runProcess,
    cwd,
    dockerHost,
    installId,
    projectName,
  });
  if (returnDetails) {
    return {
      exact:
        containerRows.length === 1 &&
        volumeNames.length === 1 &&
        volumeNames[0] === `${projectName}_${volumeName}` &&
        imagePresent,
    };
  }
}

async function inspectOwnedImageIfPresent({
  runProcess,
  cwd,
  dockerHost,
  installId,
  projectName,
}) {
  const imageName = `${projectName}:local`;
  const listed = await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: [
        "image",
        "ls",
        "--filter",
        `reference=${imageName}`,
        "--format",
        "{{json .}}",
      ],
      cwd,
      dockerHost,
    },
    "Local sidecar image existence check",
  );
  const rows = parseJsonLines(
    listed.stdout,
    "Local sidecar image existence check",
  );
  if (rows.length === 0) {
    return false;
  }
  if (
    rows.length !== 1 ||
    rows[0]?.Repository !== projectName ||
    rows[0]?.Tag !== "local"
  ) {
    throw new Error("The local sidecar image existence check failed closed.");
  }
  const image = await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: [
        "image",
        "inspect",
        "--format",
        "{{json .Config.Labels}}",
        imageName,
      ],
      cwd,
      dockerHost,
    },
    "Local sidecar image ownership check",
  );
  const labels = parseJson(
    image.stdout.trim(),
    "Local sidecar image ownership check",
  );
  if (
    !labels ||
    labels["io.relmio.managed"] !== "true" ||
    labels["io.relmio.target"] !== LOCAL_N8N_SIDECAR_TARGET ||
    labels["io.relmio.install"] !== installId
  ) {
    throw new Error(
      "A Docker image uses this Relmio project identity without matching ownership. Nothing was changed.",
    );
  }
  return true;
}

function labelsMatchOwnedSidecar(labels, { installId, projectName }) {
  return (
    labels?.["com.docker.compose.project"] === projectName &&
    labels?.["com.docker.compose.service"] === SERVICE_NAME &&
    labels?.["io.relmio.managed"] === "true" &&
    labels?.["io.relmio.target"] === LOCAL_N8N_SIDECAR_TARGET &&
    labels?.["io.relmio.install"] === installId
  );
}

async function attestPlanAndAlias({
  plan,
  runProcess,
  cwd,
  installId,
  projectName,
  attestN8n = true,
}) {
  let n8n;
  if (attestN8n) {
  n8n = await inspectContainer({
    runProcess,
    cwd,
    dockerHost: plan.dockerHost,
    containerId: plan.n8nContainerId,
  });
  const normalizedN8n = validateDiscoveredN8nContainer(n8n);
  const n8nNetwork = n8n.NetworkSettings.Networks?.[plan.networkName];
  if (
    normalizedN8n.containerId !== plan.n8nContainerId ||
    normalizedN8n.containerName !== plan.n8nContainerName ||
    n8nNetwork?.NetworkID !== plan.dockerNetworkId
  ) {
    throw new Error(
      "The selected n8n container changed. Create and confirm a fresh plan.",
    );
  }
  }
  const network = await inspectNetwork({
    runProcess,
    cwd,
    dockerHost: plan.dockerHost,
    networkName: plan.networkName,
  });
  const normalizedNetwork = validateSelectedNetwork(network, {
    n8nContainerId: attestN8n ? plan.n8nContainerId : undefined,
    expectedName: plan.networkName,
  });
  if (normalizedNetwork.dockerNetworkId !== plan.dockerNetworkId) {
    throw new Error(
      "The selected n8n Docker network changed. Create and confirm a fresh plan.",
    );
  }
  const connectedIds = Object.keys(network.Containers);
  if (connectedIds.length > MAX_DISCOVERED_CONTAINERS) {
    throw new Error("The selected n8n Docker network is too large to attest safely.");
  }
  for (const connectedId of connectedIds) {
    validateDockerObjectId(connectedId, "connected container");
    const connected = attestN8n && connectedId === plan.n8nContainerId
      ? n8n
      : await inspectContainer({
          runProcess,
          cwd,
          dockerHost: plan.dockerHost,
          containerId: connectedId,
        });
    const connectedName = parseContainerName(connected?.Name);
    const endpointName = parseContainerName(
      network.Containers?.[connectedId]?.Name,
    );
    const networkState = connected.NetworkSettings?.Networks?.[plan.networkName];
    const ownsReservedIdentity = labelsMatchOwnedSidecar(
      connected.Config?.Labels,
      { installId, projectName },
    );
    if (
      (connectedName === LOCAL_N8N_SIDECAR_HOSTNAME ||
        endpointName === LOCAL_N8N_SIDECAR_HOSTNAME ||
        (Array.isArray(networkState?.Aliases) &&
          networkState.Aliases.includes(LOCAL_N8N_SIDECAR_HOSTNAME))) &&
      !ownsReservedIdentity
    ) {
      throw new Error(
        "The n8n-openai-oauth Docker network alias has a collision. Nothing was changed.",
      );
    }
  }
}

function createComposeArgs(projectName, suffix) {
  if (!new RegExp(`^${PROJECT_PREFIX}-[a-f0-9]{32}$`, "u").test(projectName)) {
    throw new TypeError("The local sidecar Docker project identity is invalid.");
  }
  return [
    "compose",
    "--project-name",
    projectName,
    "--file",
    COMPOSE_FILENAME,
    ...suffix,
  ];
}

async function runSiwcCli({ runProcess, installRoot, marker, command, input }) {
  if (!["host", "accept", "receipt", "account", "account-live", "sign-out", "disable-plan", "enable-plan"].includes(command)) {
    throw new TypeError("The SIWC installation operation is invalid.");
  }
  if (["accept", "receipt"].includes(command)) validateSiwcRegistrationId(marker.registrationId);
  if (command === "receipt" && (!Buffer.isBuffer(input) || input.length > 8192)) {
    throw new TypeError("The handoff receipt request is invalid.");
  }
  const result = await runOrThrow(runProcess, {
    file: "docker",
    args: command === "account-live"
      ? createComposeArgs(marker.projectName, [
          "exec", "-T", SERVICE_NAME, "node", "/app/services/siwc-handoff.mjs", "account",
        ])
      : createComposeArgs(marker.projectName, [
          "run", "--rm", "--no-deps", "-T",
          ...(["accept", "receipt"].includes(command)
            ? ["--env", `RELMIO_REGISTRATION_ID=${marker.registrationId}`] : []),
          "--entrypoint", "node", SERVICE_NAME, "/app/services/siwc-handoff.mjs", command,
        ]),
    cwd: installRoot,
    dockerHost: marker.dockerHost,
    ...(input === undefined ? {} : { input }),
  }, "Local SIWC installation operation");
  if (Buffer.byteLength(result.stdout) > 4096) {
    throw new Error("The SIWC installation returned excessive status data.");
  }
  return parseJson(result.stdout, "SIWC installation status");
}

function parseModels(output) {
  const parsed = parseJson(output.trim(), "Local OAuth model check");
  if (!Array.isArray(parsed?.data)) {
    throw new Error("The local OAuth model response could not be verified.");
  }
  const models = parsed.data
    .map((entry) => entry?.id)
    .filter(
      (id) =>
        typeof id === "string" &&
        id.length > 0 &&
        id.length <= 128 &&
        /^[A-Za-z0-9_.:-]+$/u.test(id),
    );
  return models;
}

function assertNoPublishedHostPort(output) {
  let services;
  try {
    const parsed = JSON.parse(output);
    services = Array.isArray(parsed) ? parsed : [parsed];
  } catch {
    throw new Error("The local sidecar published-port safety check failed.");
  }
  if (services.length !== 1 || !Array.isArray(services[0]?.Publishers)) {
    throw new Error("The local sidecar published-port safety check failed.");
  }
  for (const publisher of services[0].Publishers) {
    if (
      !publisher ||
      !Number.isInteger(publisher.PublishedPort) ||
      typeof publisher.URL !== "string" ||
      publisher.PublishedPort !== 0 ||
      publisher.URL !== ""
    ) {
      throw new Error(
        "Safety check failed: the local sidecar published an unexpected host port.",
      );
    }
  }
}

async function verifyRunningSidecar({
  runProcess,
  installRoot,
  plan,
  installId,
  projectName,
}) {
  const running = await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: createComposeArgs(projectName, [
        "ps",
        "--status",
        "running",
        "--services",
        SERVICE_NAME,
      ]),
      cwd: installRoot,
      dockerHost: plan.dockerHost,
    },
    "Local sidecar status check",
  );
  if (!running.stdout.split(/\s+/u).includes(SERVICE_NAME)) {
    throw new Error("The local n8n sidecar did not reach the running state.");
  }
  const publication = await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: createComposeArgs(projectName, [
        "ps",
        "--format",
        "json",
        SERVICE_NAME,
      ]),
      cwd: installRoot,
      dockerHost: plan.dockerHost,
    },
    "Local sidecar publication check",
  );
  assertNoPublishedHostPort(publication.stdout);
  const containerIdResult = await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: createComposeArgs(projectName, ["ps", "-q", SERVICE_NAME]),
      cwd: installRoot,
      dockerHost: plan.dockerHost,
    },
    "Local sidecar identity check",
  );
  const containerId = validateDockerObjectId(
    containerIdResult.stdout.trim(),
    "local sidecar container",
  );
  const sidecar = await inspectContainer({
    runProcess,
    cwd: installRoot,
    dockerHost: plan.dockerHost,
    containerId,
  });
  const sidecarNetwork = sidecar.NetworkSettings?.Networks?.[plan.networkName];
  if (
    sidecar?.Id !== containerId ||
    sidecar?.State?.Running !== true ||
    !labelsMatchOwnedSidecar(sidecar.Config?.Labels, {
      installId,
      projectName,
    }) ||
    sidecarNetwork?.NetworkID !== plan.dockerNetworkId ||
    !Array.isArray(sidecarNetwork?.Aliases) ||
    !sidecarNetwork.Aliases.includes(LOCAL_N8N_SIDECAR_HOSTNAME)
  ) {
    throw new Error("The local sidecar Docker identity could not be verified.");
  }
  const ports = sidecar.NetworkSettings?.Ports;
  if (
    !ports ||
    typeof ports !== "object" ||
    Array.isArray(ports) ||
    Object.values(ports).some((bindings) => bindings !== null)
  ) {
    throw new Error("The local sidecar published-port safety check failed.");
  }
}

async function verifySidecarCatalog({
  runProcess, installRoot, plan, projectName, clientCredential,
}) {
  const verifier = await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: createComposeArgs(projectName, [
        "run",
        "--rm",
        "--no-deps",
        "-T",
        "--entrypoint",
        "node",
        SERVICE_NAME,
        "-e",
        VERIFIER_SCRIPT,
      ]),
      cwd: installRoot,
      dockerHost: plan.dockerHost,
      input: clientCredential,
    },
    "Local sidecar private-network verification",
  );
  return parseModels(verifier.stdout);
}







async function inspectOwnedSidecarRuntime({
  runProcess,
  installRoot,
  marker,
}) {
  const containerIdResult = await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: createComposeArgs(marker.projectName, [
        "ps",
        "--all",
        "-q",
        SERVICE_NAME,
      ]),
      cwd: installRoot,
      dockerHost: marker.dockerHost,
    },
    "Local sidecar refresh identity check",
  );
  if (containerIdResult.stdout.trim() === "") {
    return null;
  }
  const containerId = validateDockerObjectId(
    containerIdResult.stdout.trim(),
    "local sidecar container",
  );
  const sidecar = await inspectContainer({
    runProcess,
    cwd: installRoot,
    dockerHost: marker.dockerHost,
    containerId,
  });
  const sidecarNetwork = sidecar.NetworkSettings?.Networks?.[marker.networkName];
  const ports = sidecar.NetworkSettings?.Ports;
  let imageId;
  try {
    imageId = validateDockerImageDigest(sidecar?.Image);
  } catch {
    throw new Error("The local sidecar refresh identity could not be verified.");
  }
  if (
    sidecar?.Id !== containerId ||
    sidecar?.Config?.Image !== `${marker.projectName}:local` ||
    typeof sidecar?.State?.Running !== "boolean" ||
    typeof sidecar?.State?.Paused !== "boolean" ||
    !labelsMatchOwnedSidecar(sidecar.Config?.Labels, {
      installId: marker.installId,
      projectName: marker.projectName,
    }) ||
    (sidecarNetwork && sidecarNetwork.NetworkID !== marker.dockerNetworkId) ||
    (sidecar.State.Running && (
      sidecarNetwork?.NetworkID !== marker.dockerNetworkId ||
      !Array.isArray(sidecarNetwork?.Aliases) ||
      !sidecarNetwork.Aliases.includes(LOCAL_N8N_SIDECAR_HOSTNAME)
    )) ||
    (sidecar.State.Running && (!ports || typeof ports !== "object" || Array.isArray(ports))) ||
    (ports && (typeof ports !== "object" || Array.isArray(ports) ||
      Object.values(ports).some((bindings) => bindings !== null)))
  ) {
    throw new Error("The local sidecar refresh identity could not be verified.");
  }
  const logicalVolume = marker.schemaVersion === MARKER_SCHEMA_VERSION ? "siwc-store" : "oauth-auth";
  const destination = marker.schemaVersion === MARKER_SCHEMA_VERSION ? "/home/node/.relmio-siwc" : "/home/node/.codex";
  const mounts = sidecar.Mounts;
  if (!Array.isArray(mounts) || mounts.length !== 1 ||
      mounts[0].Type !== "volume" || mounts[0].Name !== `${marker.projectName}_${logicalVolume}` ||
      mounts[0].Destination !== destination || mounts[0].RW !== true) {
    throw new Error("The owned sidecar credential mount changed.");
  }
  return Object.freeze({
    containerId,
    imageId,
    credentialMount: { type: mounts[0].Type, name: mounts[0].Name, destination: mounts[0].Destination },
    health: sidecar.State.Health?.Status,
    paused: sidecar.State.Paused,
    running: sidecar.State.Running,
  });
}



async function cleanupSidecarProject({
  runProcess,
  installRoot,
  dockerHost,
  projectName,
}) {
  await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: createComposeArgs(projectName, [
        "down",
        "--volumes",
        "--remove-orphans",
      ]),
      cwd: installRoot,
      dockerHost,
    },
    "Local sidecar cleanup",
  );
  const remaining = await runOrThrow(
    runProcess,
    {
      file: "docker",
      args: createComposeArgs(projectName, ["ps", "-q", SERVICE_NAME]),
      cwd: installRoot,
      dockerHost,
    },
    "Local sidecar cleanup verification",
  );
  if (remaining.stdout.trim() !== "") {
    throw new Error("Relmio could not confirm local sidecar cleanup.");
  }
  const projectFilter = `label=com.docker.compose.project=${projectName}`;
  for (const [resource, args, label] of [
    [
      "container",
      ["container", "ls", "--all", "--filter", projectFilter, "--format", "{{json .}}"],
      "containers",
    ],
    [
      "volume",
      ["volume", "ls", "--filter", projectFilter, "--format", "{{json .}}"],
      "credential volumes",
    ],
  ]) {
    const result = await runOrThrow(
      runProcess,
      { file: "docker", args, cwd: installRoot, dockerHost },
      `Local sidecar ${resource} cleanup verification`,
    );
    const records = parseJsonLines(
      result.stdout,
      `Local sidecar ${resource} cleanup verification`,
    );
    if (records.length !== 0) {
      throw new Error(
        `Relmio could not confirm removal of its local sidecar ${label}. The managed directory was kept.`,
      );
    }
  }
}

async function validateReviewedLocalAccount(registration, binding) {
  const record = await readRegistration(registration);
  if (
    record?.registrationId !== binding.registrationId ||
    record?.clientId !== binding.clientId ||
    record?.generation !== binding.generation ||
    record?.owner?.hostId !== binding.ownerHostId ||
    record?.owner?.runtimeId !== binding.ownerRuntimeId ||
    record?.handoff?.state !== "owned" ||
    !record.planEnabled ||
    !record.session?.refreshToken ||
    !record.session?.scopes?.includes("chatgpt.tokens.use.direct")
  ) throw new Error("The selected SIWC account changed. Review the installation again.");
}

async function reviewOwnedN8nReplacement(
  { plan, existingSiwc = false },
  {
    fileSystem = defaultFileSystem, env = process.env,
    homeDirectory = homedir(), runProcess = runLocalProcess,
    platform = process.platform, lockDownPath = lockDownLocalPath,
  } = {},
) {
  assertSupportedPlatform(platform);
  rejectDockerEnvironmentOverrides(env);
  const selected = normalizeLocalN8nSidecarPlan(plan);
  const installRoot = await resolveLocalN8nSidecarInstallRoot({
    env, homeDirectory, fileSystem, platform,
  });
  await verifyWindowsSidecarStatusPathSecurity({
    fileSystem, installRoot, platform, lockDownPath,
  });
  const managed = await inspectManagedInstall({ fileSystem, installRoot });
  const marker = validateMarker(managed.marker);
  if (marker.schemaVersion !== (existingSiwc ? MARKER_SCHEMA_VERSION : 1) ||
      marker.dockerHost !== selected.dockerHost ||
      marker.n8nContainerId !== selected.n8nContainerId ||
      marker.dockerNetworkId !== selected.dockerNetworkId ||
      marker.networkName !== selected.networkName ||
      marker.n8nContainerName !== selected.n8nContainerName) {
    throw new Error("The selected n8n target or old bridge changed before migration.");
  }
  const selectedDockerHost = await resolveLocalDockerHost({
    runProcess, cwd: installRoot, env, platform,
  });
  if (selectedDockerHost !== marker.dockerHost) {
    throw new Error("The selected local Docker context changed.");
  }
  await attestPlanAndAlias({
    plan: selected, runProcess, cwd: installRoot,
    installId: marker.installId, projectName: marker.projectName,
  });
  const ownership = await attestProjectOwnership({
    runProcess, cwd: installRoot, dockerHost: marker.dockerHost,
    installId: marker.installId, projectName: marker.projectName,
    returnDetails: true, volumeName: existingSiwc ? "siwc-store" : "oauth-auth",
  });
  if (!ownership.exact) {
    throw new Error("The old bridge container, image or credential volume is not exactly owned.");
  }
  const runtime = await inspectOwnedSidecarRuntime({
    runProcess, installRoot, marker,
  });
  if (!runtime || runtime.paused) {
    throw new Error("The old bridge refresh writer is missing or ambiguous.");
  }
  const logicalVolume = existingSiwc ? "siwc-store" : "oauth-auth";
  const effective = parseJson((await runOrThrow(runProcess, {
    file: "docker", args: createComposeArgs(marker.projectName, ["config", "--format", "json"]),
    cwd: installRoot, dockerHost: marker.dockerHost,
  }, "Owned sidecar effective Compose check")).stdout, "Owned sidecar effective Compose check");
  const current = effective?.services?.[SERVICE_NAME];
  if (Object.keys(effective?.services ?? {}).length !== (existingSiwc ? 2 : 1) ||
      current?.image !== `${marker.projectName}:local` ||
      current?.volumes?.length !== 1 || current.volumes[0]?.type !== "volume" ||
      current.volumes[0]?.source !== logicalVolume ||
      current.volumes[0]?.target !== runtime.credentialMount.destination ||
      current.volumes[0]?.read_only === true ||
      effective?.volumes?.[logicalVolume]?.name !== runtime.credentialMount.name) {
    throw new Error("The owned sidecar effective credential mapping changed.");
  }
  const volumeIdentity = await readOwnedCredentialVolumeIdentity({
    runProcess, installRoot, marker, volumeName: runtime.credentialMount.name,
  });
  return Object.freeze({
    installId: marker.installId, projectName: marker.projectName,
    dockerHost: marker.dockerHost,
    n8nContainerId: marker.n8nContainerId,
    dockerNetworkId: marker.dockerNetworkId,
    networkName: marker.networkName,
    containerId: runtime.containerId, imageId: runtime.imageId,
    volumeName: runtime.credentialMount.name,
    credentialMount: runtime.credentialMount, volumeIdentity,
    ...(existingSiwc ? {
      registrationId: marker.registrationId,
      ownerHostId: marker.ownerHostId,
    } : {}),
    running: runtime.running,
  });
}

export function reviewLocalN8nLegacyMigration({ plan }, deps = {}) {
  return reviewOwnedN8nReplacement({ plan }, deps);
}

export function reviewLocalN8nSiwcReplacement({ plan }, deps = {}) {
  return reviewOwnedN8nReplacement({ plan, existingSiwc: true }, deps);
}

async function readOwnedCredentialVolumeIdentity({ runProcess, installRoot, marker, volumeName }) {
  validateDockerName(volumeName);
  const volume = parseJson((await runOrThrow(runProcess, {
    file: "docker", args: ["volume", "inspect", "--format", "{{json .}}", volumeName],
    cwd: installRoot, dockerHost: marker.dockerHost,
  }, "Owned credential volume identity check")).stdout, "Owned credential volume identity check");
  requireOwnershipLabels(volume?.Labels, { installId: marker.installId, projectName: marker.projectName, service: false });
  if (volume?.Name !== volumeName || volume.Driver !== "local" ||
      typeof volume.CreatedAt !== "string" || !Number.isFinite(Date.parse(volume.CreatedAt)) ||
      typeof volume.Mountpoint !== "string" || !volume.Mountpoint.startsWith("/") ||
      (volume.Options !== null && Object.keys(volume.Options ?? {}).length !== 0)) {
    throw new Error("The owned credential volume identity changed.");
  }
  return createHash("sha256").update(JSON.stringify({
    name: volume.Name, createdAt: volume.CreatedAt, driver: volume.Driver,
    mountpoint: volume.Mountpoint, options: volume.Options, labels: volume.Labels,
  })).digest("hex");
}

async function attestRetiredN8n({ fileSystem, runProcess, installRoot, binding }) {
  if (!/^[a-f0-9]{32}$/u.test(binding?.installId)) throw new Error("The retired sidecar identity is invalid.");
  const archive = join(installRoot, "legacy", binding.installId);
  const marker = validateMarker(JSON.parse(await fileSystem.readFile(join(archive, MANAGED_MARKER), "utf8")));
  const runtime = await inspectOwnedSidecarRuntime({ runProcess, installRoot: archive, marker });
  if (!runtime || runtime.running || runtime.paused || runtime.containerId !== binding.containerId ||
      runtime.imageId !== binding.imageId ||
      JSON.stringify(runtime.credentialMount) !== JSON.stringify(binding.credentialMount) ||
      await readOwnedCredentialVolumeIdentity({ runProcess, installRoot: archive, marker,
        volumeName: binding.volumeName }) !== binding.volumeIdentity) {
    throw new Error("The retained old sidecar writer or credential volume changed.");
  }
}

export async function reviewLocalN8nSiwcResume(
  { registration, plan: reviewedPlan } = {},
  { fileSystem = defaultFileSystem, env = process.env, homeDirectory = homedir(),
    runProcess = runLocalProcess, platform = process.platform, lockDownPath = lockDownLocalPath } = {},
) {
  rejectDockerEnvironmentOverrides(env);
  const installRoot = await resolveLocalN8nSidecarInstallRoot({ env, homeDirectory, fileSystem, platform });
  const staged = await readLocalSiwcStaging({ fileSystem, installRoot, platform, lockDownPath });
  if (!staged || staged.checkpoint.stage === "completed") throw new Error("There is no interrupted SIWC sidecar to resume.");
  const { checkpoint, checkpointSha256 } = staged;
  let plan = normalizeLocalN8nSidecarPlan(reviewedPlan ?? checkpoint.plan);
  if (reviewedPlan && reviewedPlan.authBinding?.registrationId !== registration?.registrationId) {
    throw new Error("The selected SIWC account does not match the fresh n8n review.");
  }
  for (const field of ["dockerHost", "networkName", "dockerNetworkId"]) {
    if (plan[field] !== checkpoint.plan[field]) throw new Error("The stable SIWC destination changed.");
  }
  if (checkpoint.projectName !== `${PROJECT_PREFIX}-${checkpoint.installId}` ||
      await resolveLocalDockerHost({ runProcess, cwd: homeDirectory, env, platform }) !== checkpoint.dockerHost) {
    throw new Error("The staged SIWC destination changed.");
  }
  await attestProjectOwnership({ runProcess, cwd: homeDirectory, dockerHost: checkpoint.dockerHost,
    installId: checkpoint.installId, projectName: checkpoint.projectName });
  const aliasOwner = checkpoint.reviewedLegacy && !checkpoint.oldStopped ? checkpoint.reviewedLegacy : checkpoint;
  await attestPlanAndAlias({ plan, runProcess, cwd: homeDirectory,
    installId: aliasOwner.installId, projectName: aliasOwner.projectName });
  if (checkpoint.reviewedLegacy && checkpoint.oldStopped) {
    await attestRetiredN8n({ fileSystem, runProcess, installRoot, binding: checkpoint.reviewedLegacy });
  }
  const filesSha256 = await fingerprintLocalSiwcFiles({ fileSystem, installRoot, platform, lockDownPath });
  const resourcesSha256 = await fingerprintLocalSiwcResources({ runProcess, installRoot, checkpoint });
  if (checkpoint.ownerHostId) {
    const { marker } = await inspectManagedInstall({ fileSystem, installRoot });
    if (marker?.installId !== checkpoint.installId || marker?.ownerHostId !== checkpoint.ownerHostId) {
      throw new Error("The staged SIWC owner marker changed.");
    }
    await assertManagedSiwcCompose(fileSystem, installRoot, marker);
  }
  const authBinding = await readLocalSiwcResumeAuthBinding({ checkpoint, registration, readRegistration, readPendingAuthHandoff,
    readReceipt: pending => runSiwcCli({ runProcess, installRoot, marker: checkpoint, command: "receipt",
      input: Buffer.from(JSON.stringify({ handoffId: pending.handoffId, binding: pending.binding, identity: pending.identity })) }) });
  plan = normalizeLocalN8nSidecarPlan({ ...plan, authBinding });
  return { target: LOCAL_N8N_SIDECAR_TARGET, installId: checkpoint.installId,
    registrationId: plan.authBinding.registrationId, stage: checkpoint.stage, plan, checkpointSha256,
    ...(checkpoint.migration ? { migration: checkpoint.migration } : {}),
    filesSha256, resourcesSha256 };
}

export async function reconcileLocalN8nSiwcHandoff(
  { registration, confirmed },
  { fileSystem = defaultFileSystem, env = process.env, homeDirectory = homedir(),
    runProcess = runLocalProcess, platform = process.platform, lockDownPath = lockDownLocalPath,
    getProcessIdentity, lifecycleLockNow = Date.now } = {},
) {
  if (confirmed !== true) throw new Error("Confirm reconciliation of the selected SIWC handoff.");
  validateSiwcRegistrationId(registration?.registrationId);
  rejectDockerEnvironmentOverrides(env);
  const installRoot = await resolveLocalN8nSidecarInstallRoot({ env, homeDirectory, fileSystem, platform });
  const releaseLock = await acquireSidecarLock({ fileSystem, getProcessIdentity, installRoot,
    lockDownPath, now: lifecycleLockNow, platform });
  return settleLocalIntegrationLifecycleOperation({ completionLabel: "Local n8n SIWC handoff reconciliation",
    releaseLock, operation: async () => {
      await fingerprintLocalSiwcFiles({ fileSystem, installRoot, platform, lockDownPath });
      const managed = await inspectManagedInstall({ fileSystem, installRoot });
      const marker = validateMarker(managed.marker);
      if (marker.registrationId !== registration.registrationId) throw new Error("The selected SIWC destination changed.");
      await assertManagedSiwcCompose(fileSystem, installRoot, marker);
      if (await resolveLocalDockerHost({ runProcess, cwd: installRoot, env, platform }) !== marker.dockerHost) {
        throw new Error("The selected Docker context changed.");
      }
      await attestPlanAndAlias({ plan: marker, runProcess, cwd: installRoot,
        installId: marker.installId, projectName: marker.projectName, attestN8n: false });
      await attestProjectOwnership({ runProcess, cwd: installRoot, dockerHost: marker.dockerHost,
        installId: marker.installId, projectName: marker.projectName });
      const source = await readRegistration(registration);
      const pending = await readPendingAuthHandoff(registration);
      const request = pending ?? (source?.handoff?.state === "transferred" ? {
        handoffId: source.handoff.handoffId, binding: source.handoff.receipt.binding,
        target: source.handoff.receipt.binding.target,
        identity: { issuer: source.identity.issuer, clientId: source.clientId, subject: source.identity.subject },
      } : null);
      if (!request || request.target.hostId !== marker.ownerHostId || request.target.runtimeId !== marker.installId) {
        throw new Error("The frozen handoff does not match this destination.");
      }
      let receipt;
      try {
        ({ receipt } = await runSiwcCli({ runProcess, installRoot, marker, command: "receipt",
          input: Buffer.from(JSON.stringify({ handoffId: request.handoffId,
            binding: request.binding, identity: request.identity })) }));
      } catch {
        throw Object.assign(new Error("The SIWC receipt outcome is unresolved. The source remains frozen."), { remoteOutcomeUnknown: true });
      }
      if (receipt === null) {
        await assertNoLocalSiwcOneOffContainers({ runProcess, installRoot,
          dockerHost: marker.dockerHost, projectName: marker.projectName });
        const staged = await readLocalSiwcStaging({ fileSystem, installRoot, platform, lockDownPath });
        if (!staged || staged.checkpoint.registrationId !== registration.registrationId) {
          throw new Error("The original SIWC checkpoint changed.");
        }
        staged.checkpoint.notAccepted = true;
        const path = localSiwcStagingPath(installRoot);
        await writeManagedFile(fileSystem, path, `${JSON.stringify(staged.checkpoint)}\n`, 0o600);
        if (platform === "win32") await lockDownPath(path, { platform, kind: "file" });
        return { outcome: "not-accepted",
          account: (await listRegistrations({ storageRoot: registration.storageRoot })).find(
            account => account.registrationId === registration.registrationId) };
      }
      if (receipt?.handoffId !== request.handoffId ||
          JSON.stringify(receipt.binding) !== JSON.stringify(request.binding)) throw new Error("The SIWC receipt binding changed.");
      return { outcome: "finished", account: await finishAuthHandoff(registration, {
        handoffId: request.handoffId, receipt: receipt.receipt }) };
    } });
}

export async function installLocalN8nSidecar(
  { plan, registration, backgroundConsent, confirmed, migrationConsent, legacyBinding, replacementConsent, existingBinding, resume },
  {
    fileSystem = defaultFileSystem,
    env = process.env,
    homeDirectory = homedir(),
    runProcess = runLocalProcess,
    randomBytes = createRandomBytes,
    platform = process.platform,
    lockDownPath = lockDownLocalPath,
    getProcessIdentity,
    lifecycleLockNow = Date.now,
    collectAssets = collectSiwcRuntimeAssets,
  } = {},
) {
  if (confirmed !== true) {
    throw new Error("Confirm the reviewed private n8n bridge plan before installing.");
  }
  assertSupportedPlatform(platform);
  rejectDockerEnvironmentOverrides(env);
  const selected = normalizeLocalN8nSidecarPlan(plan);
  const binding = validateSiwcAuthBinding(selected.authBinding);
  if (registration?.registrationId !== binding.registrationId || !registration.storageRoot) {
    throw new Error("The selected SIWC account does not match the reviewed bridge.");
  }
  const safeConsent = Object.freeze({
    ...validateSiwcBackgroundConsent(backgroundConsent, { target: "local-n8n" }),
  });
  if (!resume) await validateReviewedLocalAccount(registration, binding);
  const installRoot = await resolveLocalN8nSidecarInstallRoot({
    env, homeDirectory, fileSystem, platform,
  });
  const releaseLock = await acquireSidecarLock({
    fileSystem, getProcessIdentity, installRoot, lockDownPath,
    now: lifecycleLockNow, platform,
  });
  let preservedResult;
  return settleLocalIntegrationLifecycleOperation({
    completionLabel: "Local n8n SIWC sidecar installation",
    releaseLock,
    operation: async () => {
      try {
      const staged = await readLocalSiwcStaging({ fileSystem, installRoot, platform, lockDownPath });
      if (staged && staged.checkpoint.stage !== "completed" && !resume) {
        throw new Error("Review the interrupted SIWC sidecar before resuming.");
      }
      let handoffCommitted = false;
      if (resume) {
        const reviewed = await reviewLocalN8nSiwcResume({ registration, plan: selected },
          { fileSystem, env, homeDirectory, runProcess, platform, lockDownPath });
        if (JSON.stringify(reviewed) !== JSON.stringify(resume) ||
            JSON.stringify(reviewed.plan) !== JSON.stringify(selected)) {
          throw new Error("The reviewed SIWC resume binding changed.");
        }
        const source = await readRegistration(registration);
        if (source?.handoff?.state === "handoff-pending") throw new Error("Reconcile the frozen handoff before resuming.");
        handoffCommitted = source?.handoff?.state === "transferred";
        if (!handoffCommitted) await validateReviewedLocalAccount(registration, binding);
        else if (source.handoff.receipt.binding.target.runtimeId !== staged.checkpoint.installId ||
                 source.handoff.receipt.binding.target.hostId !== staged.checkpoint.ownerHostId) {
          throw new Error("The completed handoff belongs to another destination.");
        }
      }
      const managed = await inspectManagedInstall({ fileSystem, installRoot, staging: staged?.checkpoint });
      const migrating = migrationConsent !== undefined || legacyBinding !== undefined || resume?.migration === "legacy";
      const replacing = replacementConsent !== undefined || existingBinding !== undefined || resume?.migration === "replacement";
      const retiring = migrating || replacing;
      let reviewedLegacy = resume ? staged.checkpoint.reviewedLegacy ?? null : null;
      if (retiring && !(resume && staged.checkpoint.oldStopped)) {
        const expectedSchema = replacing ? MARKER_SCHEMA_VERSION : 1;
        if ((migrating && replacing) ||
            (!resume && migrating && migrationConsent !== true) ||
            (!resume && replacing && replacementConsent !== true) ||
            managed.marker?.schemaVersion !== expectedSchema) {
          throw new Error("Explicit reviewed old-bridge replacement consent is required.");
        }
        const inspect = replacing
          ? reviewLocalN8nSiwcReplacement : reviewLocalN8nLegacyMigration;
        reviewedLegacy = await inspect(
          { plan: selected },
          { fileSystem, env, homeDirectory, runProcess, platform, lockDownPath },
        );
        const expected = resume ? staged.checkpoint.reviewedLegacy : replacing ? existingBinding : legacyBinding;
        for (const field of [
          "installId", "projectName", "dockerHost", "n8nContainerId",
          "dockerNetworkId", "networkName", "containerId", "imageId",
          "volumeName", "volumeIdentity", "running",
          ...(replacing ? ["registrationId", "ownerHostId"] : []),
        ]) {
          if (expected?.[field] !== reviewedLegacy[field]) {
            throw new Error("The reviewed old n8n sidecar identity changed.");
          }
        }
        if (JSON.stringify(expected?.credentialMount) !== JSON.stringify(reviewedLegacy.credentialMount)) {
          throw new Error("The reviewed credential mount changed.");
        }
        if (replacing && reviewedLegacy.registrationId === binding.registrationId) {
          throw new Error("A replacement requires a fresh independently authorized SIWC registration.");
        }
      } else if (managed.marker && !resume) {
        throw new Error("The existing bridge requires a separately reviewed migration or account replacement.");
      }
      const identityBytes = randomBytes(32);
      const capabilityBytes = randomBytes(32);
      if (!Buffer.isBuffer(identityBytes) || identityBytes.length !== 32 ||
          !Buffer.isBuffer(capabilityBytes) || capabilityBytes.length !== 32) {
        throw new Error("Relmio could not generate a strong installation identity and local capability.");
      }
      const installId = resume ? staged.checkpoint.installId : identityBytes.subarray(0, 16).toString("hex");
      if (retiring && installId === reviewedLegacy.installId) {
        throw new Error("The fresh SIWC sidecar identity collided with the old project.");
      }
      const projectName = `${PROJECT_PREFIX}-${installId}`;
      const clientCredential = capabilityBytes.toString("base64url");
      const tokenSha256 = createHash("sha256").update(clientCredential).digest("hex");
      const runtime = { installId, projectName, dockerHost: selected.dockerHost, registrationId: binding.registrationId };
      if (handoffCommitted) {
        const account = (await runSiwcCli({ runProcess, installRoot, marker: runtime, command: "account" })).account;
        if (account?.registrationId !== binding.registrationId || account?.ownerHostId !== staged.checkpoint.ownerHostId ||
            account?.ownerRuntimeId !== installId || account?.ownership !== "owned") {
          throw new Error("The resumed destination account changed.");
        }
        preservedResult = { target: LOCAL_N8N_SIDECAR_TARGET, endpoint: LOCAL_N8N_SIDECAR_ENDPOINT,
          protocol: "openai-v1", clientCredential, credentialShownOnce: true, models: [],
          networkName: selected.networkName, hostPublication: "unknown", account, runtimeState: "unknown" };
      }
      const cwd = dirname(resolve(installRoot, "..", ".."));
      await attestProjectOwnership({
        runProcess, cwd, dockerHost: selected.dockerHost, installId, projectName,
      });
      if (!retiring) {
        await attestPlanAndAlias({
          plan: selected, runProcess, cwd, installId, projectName,
        });
      }
      const checkpoint = resume ? staged.checkpoint : {
        schemaVersion: 1, target: LOCAL_N8N_SIDECAR_TARGET, installId, projectName,
        dockerHost: selected.dockerHost, registrationId: binding.registrationId,
        plan: selected, stage: "staged",
        ...(retiring ? { reviewedLegacy, migration: replacing ? "replacement" : "legacy",
          ...(replacing ? { previousGeneration: existingBinding.expectedGeneration } : {}) } : {}),
      };
      if (resume) {
        if (checkpoint.registrationId !== binding.registrationId) {
          await assertNoLocalSiwcOneOffContainers({ runProcess, installRoot,
            dockerHost: selected.dockerHost, projectName });
        }
        checkpoint.registrationId = binding.registrationId;
        checkpoint.plan = selected;
        checkpoint.notAccepted = false;
      }
      const saveStage = async stage => {
        checkpoint.stage = stage;
        const path = localSiwcStagingPath(installRoot);
        await writeManagedFile(fileSystem, path, `${JSON.stringify(checkpoint)}\n`, 0o600);
        if (platform === "win32") await lockDownPath(path, { platform, kind: "file" });
      };
      await saveStage(checkpoint.stage);
      await initializeManagedDirectories({
        fileSystem, installRoot, baseExists: managed.baseExists, platform, lockDownPath,
      });
      const write = async (path, contents) => {
        const fullPath = join(installRoot, path);
        await writeManagedFile(fileSystem, fullPath, contents, 0o600);
        if (platform === "win32") await lockDownPath(fullPath, { platform, kind: "file" });
      };
      let legacyArchive = retiring ? join(installRoot, "legacy", reviewedLegacy.installId) : null;
      if (retiring && !(resume && checkpoint.oldStopped)) {
        await validateReviewedLocalAccount(registration, binding);
        const inspect = replacing
          ? reviewLocalN8nSiwcReplacement : reviewLocalN8nLegacyMigration;
        const freshPrevious = await inspect(
          { plan: selected },
          { fileSystem, env, homeDirectory, runProcess, platform, lockDownPath },
        );
        for (const field of [
          "installId", "projectName", "dockerHost", "n8nContainerId",
          "dockerNetworkId", "networkName", "containerId", "imageId",
          "volumeName", "volumeIdentity", "running",
          ...(replacing ? ["registrationId", "ownerHostId"] : []),
        ]) {
          if (freshPrevious[field] !== reviewedLegacy[field]) {
            throw new Error("The old n8n sidecar changed before replacement. Review again.");
          }
        }
        if (JSON.stringify(freshPrevious.credentialMount) !== JSON.stringify(reviewedLegacy.credentialMount)) {
          throw new Error("The old credential mount changed before replacement.");
        }
        if (replacing) {
          const old = (await runSiwcCli({
            runProcess, installRoot, marker: managed.marker, command: "account",
          })).account;
          if (old?.registrationId !== reviewedLegacy.registrationId ||
              old?.ownerHostId !== reviewedLegacy.ownerHostId ||
              old?.generation !== (resume ? checkpoint.previousGeneration : existingBinding.expectedGeneration) ||
              old?.session !== "signed-out" || old?.planEnabled !== false) {
            throw new Error("Sign out of the exact old SIWC account before reviewed replacement.");
          }
        }
        const legacyRoot = join(installRoot, "legacy");
        legacyArchive = join(legacyRoot, reviewedLegacy.installId);
        if (!resume && await lstatIfExists(fileSystem, legacyArchive)) {
          throw new Error("A prior n8n sidecar replacement is incomplete. Inspect it before retrying.");
        }
        await ensurePrivateDirectory(fileSystem, legacyRoot, platform, lockDownPath);
        await ensurePrivateDirectory(fileSystem, legacyArchive, platform, lockDownPath);
        const retain = async (filename, contents) => {
          const path = join(legacyArchive, filename);
          await writeManagedFile(fileSystem, path, contents, 0o600);
          if (platform === "win32") await lockDownPath(path, { platform, kind: "file" });
        };
        for (const filename of [
          MANAGED_MARKER, COMPOSE_FILENAME, "Dockerfile", ".dockerignore",
          ...(replacing ? ["package.json", "package-lock.json"] : []),
        ]) {
          const oldPath = join(installRoot, filename);
          const metadata = await lstatIfExists(fileSystem, oldPath);
          if (!metadata?.isFile?.() || metadata.isSymbolicLink() ||
              metadata.size > 1024 * 1024 ||
              (platform !== "win32" && (metadata.mode & 0o077) !== 0)) {
            throw new Error("The old bridge generated files are missing or unsafe.");
          }
          if (platform === "win32") {
            await lockDownPath(oldPath, {
              platform, kind: "file", verifyOnly: true, verifyEffectiveOwnerOnly: true,
            });
          }
          await retain(filename, await fileSystem.readFile(oldPath));
        }
        const oldRuntimePath = join(installRoot, "openai-oauth-sidecar.mjs");
        const oldRuntime = await lstatIfExists(fileSystem, oldRuntimePath);
        if (oldRuntime) {
          if (!oldRuntime.isFile() || oldRuntime.isSymbolicLink() ||
              oldRuntime.size > 1024 * 1024) {
            throw new Error("The old bridge runtime file is unsafe.");
          }
          await retain("openai-oauth-sidecar.mjs", await fileSystem.readFile(oldRuntimePath));
        }
        const journal = async state => retain("migration.json", Buffer.from(
          `${JSON.stringify({
            schemaVersion: 1, state, reviewedLegacy,
            replacementInstallId: installId, previousWasSiwc: replacing,
          })}\n`,
        ));
        await journal("prepared");
        if (reviewedLegacy.running) {
          await runOrThrow(runProcess, {
            file: "docker",
            args: createComposeArgs(reviewedLegacy.projectName, [
              "stop", "--timeout", "30", SERVICE_NAME,
            ]),
            cwd: installRoot, dockerHost: reviewedLegacy.dockerHost,
          }, "Attested old n8n sidecar drain");
        }
        const stoppedPrevious = await inspect(
          { plan: selected },
          { fileSystem, env, homeDirectory, runProcess, platform, lockDownPath },
        );
        for (const field of [
          "installId", "projectName", "dockerHost", "n8nContainerId",
          "dockerNetworkId", "networkName", "containerId", "imageId", "volumeName", "volumeIdentity",
          ...(replacing ? ["registrationId", "ownerHostId"] : []),
        ]) {
          if (stoppedPrevious[field] !== reviewedLegacy[field]) {
            throw new Error("The old sidecar identity changed while stopping. It will not be resumed automatically.");
          }
        }
        if (stoppedPrevious.running) {
          throw new Error("The old credential refresh writer did not stop.");
        }
        if (JSON.stringify(stoppedPrevious.credentialMount) !== JSON.stringify(reviewedLegacy.credentialMount)) {
          throw new Error("The old credential mount changed while stopping.");
        }
        if (replacing) {
          const old = (await runSiwcCli({
            runProcess, installRoot, marker: managed.marker, command: "account",
          })).account;
          if (old?.registrationId !== reviewedLegacy.registrationId ||
              old?.generation !== (resume ? checkpoint.previousGeneration : existingBinding.expectedGeneration) ||
              old?.session !== "signed-out" || old?.planEnabled !== false) {
            throw new Error("The old signed-out SIWC account changed. The retired bridge remains stopped.");
          }
        }
        await journal("stopped");
        checkpoint.oldStopped = true;
        await saveStage("staged");
      }
      if (handoffCommitted) {
        await runOrThrow(runProcess, { file: "docker",
          args: createComposeArgs(projectName, ["stop", "--timeout", "30", SERVICE_NAME]),
          cwd: installRoot, dockerHost: selected.dockerHost }, "Resumed owned sidecar stop");
        const running = await runOrThrow(runProcess, { file: "docker",
          args: createComposeArgs(projectName, ["ps", "--status", "running", "--services", SERVICE_NAME]),
          cwd: installRoot, dockerHost: selected.dockerHost }, "Resumed owned sidecar stopped check");
        if (running.stdout.trim() !== "") throw new Error("The resumed sidecar did not stop.");
      }
      const assets = await collectAssets();
      for (const folder of ["services", "gateway", "infrastructure"]) {
        await ensurePrivateDirectory(fileSystem, join(installRoot, folder), platform, lockDownPath);
      }
      await write("Dockerfile", createLocalN8nSidecarDockerfile({ installId }));
      await write(".dockerignore", createLocalN8nSidecarDockerignore());
      await write("package.json", assets.packageJson);
      await write("package-lock.json", assets.packageLock);
      for (const asset of assets.files) {
        if (!SIWC_ASSET_PATHS.has(asset.path) || !Buffer.isBuffer(asset.contents)) {
          throw new Error("The packaged SIWC runtime assets are invalid.");
        }
        await write(asset.path, asset.contents);
      }
      await write(COMPOSE_FILENAME, createLocalN8nSidecarComposeFile({
        installId, networkName: selected.networkName,
        registrationId: binding.registrationId, tokenSha256,
      }));
      await runOrThrow(runProcess, {
        file: "docker", args: createComposeArgs(projectName, ["config", "--quiet"]),
        cwd: installRoot, dockerHost: selected.dockerHost,
      }, "Local sidecar Compose validation");
      await attestProjectOwnership({
        runProcess, cwd: installRoot, dockerHost: selected.dockerHost,
        installId, projectName,
      });
      await attestPlanAndAlias({
        plan: selected, runProcess, cwd: installRoot, installId, projectName,
      });
      await runOrThrow(runProcess, {
        file: "docker", args: createComposeArgs(projectName, ["build", SERVICE_NAME]),
        cwd: installRoot, dockerHost: selected.dockerHost,
      }, "Local SIWC image build");
      await runOrThrow(runProcess, {
        file: "docker", args: createComposeArgs(projectName, [
          "run", "--rm", "--no-deps", "-T", "credential-seed",
        ]),
        cwd: installRoot, dockerHost: selected.dockerHost,
      }, "Local SIWC private volume initialization");
      const destination = await runSiwcCli({
        runProcess, installRoot, marker: runtime, command: "host",
      });
      validateSiwcHostId(destination?.hostId);
      if (destination.runtimeId !== installId || destination.hostId === binding.ownerHostId ||
          (handoffCommitted && destination.hostId !== checkpoint.ownerHostId)) {
        throw new Error("The local SIWC destination host identity is invalid.");
      }
      await write(MANAGED_MARKER, `${JSON.stringify({
        schemaVersion: MARKER_SCHEMA_VERSION, kind: "relmio-local-n8n-sidecar",
        target: LOCAL_N8N_SIDECAR_TARGET, installId, projectName,
        dockerHost: selected.dockerHost,
        n8nContainerId: selected.n8nContainerId,
        n8nContainerName: selected.n8nContainerName,
        dockerNetworkId: selected.dockerNetworkId,
        networkName: selected.networkName,
        registrationId: binding.registrationId, clientId: binding.clientId,
        ownerHostId: destination.hostId, tokenSha256,
        ...(retiring ? {
          legacyInstallId: reviewedLegacy.installId,
          ...(replacing ? { previousWasSiwc: true } : {}),
        } : {}),
      })}\n`);
      checkpoint.ownerHostId = destination.hostId;
      await saveStage("prepared");
      await attestPlanAndAlias({
        plan: selected, runProcess, cwd: installRoot, installId, projectName,
      });
      let accepted;
      if (handoffCommitted) {
        const account = (await runSiwcCli({ runProcess, installRoot, marker: runtime, command: "account" })).account;
        if (account?.registrationId !== binding.registrationId || account?.ownerHostId !== destination.hostId ||
            account?.ownerRuntimeId !== installId || account?.ownership !== "owned") {
          throw new Error("The resumed SIWC destination account changed.");
        }
        accepted = { account };
      } else {
      await validateReviewedLocalAccount(registration, binding);
      const { handoffId } = await prepareAuthHandoff(registration, {
        expectedGeneration: binding.generation, target: destination, backgroundConsent: safeConsent,
      });
      await saveStage("handoff-pending");
      const contents = await readAuthHandoff(registration, {
        handoffId, expectedGeneration: binding.generation,
      });
      // Acceptance is attempted once; recovery reads its durable receipt.
      try {
        accepted = await runSiwcCli({
          runProcess, installRoot, marker: runtime, command: "accept", input: contents,
        });
      } catch (error) {
        throw Object.assign(new Error("The SIWC transfer outcome is unresolved. The source remains frozen; reconcile the destination before retrying."),
          { remoteOutcomeUnknown: true });
      }
      if (accepted?.handoffId !== handoffId ||
          accepted.account?.registrationId !== binding.registrationId ||
          accepted.account?.ownerHostId !== destination.hostId ||
          accepted.account?.ownerRuntimeId !== installId ||
          accepted.account?.ownership !== "owned") {
        throw new Error("The SIWC handoff receipt or destination account did not match. The source remains frozen.");
      }
      preservedResult = { target: LOCAL_N8N_SIDECAR_TARGET, endpoint: LOCAL_N8N_SIDECAR_ENDPOINT,
        protocol: "openai-v1", clientCredential, credentialShownOnce: true, models: [],
        networkName: selected.networkName, hostPublication: "none",
        account: accepted.account, runtimeState: "stopped" };
      await finishAuthHandoff(registration, { handoffId, receipt: accepted.receipt });
      handoffCommitted = true;
      }
      try {
        await saveStage("transferred");
        await runOrThrow(runProcess, {
          file: "docker",
          args: createComposeArgs(projectName, [
            "up", "-d", "--wait", "--wait-timeout", "90", "--no-deps", SERVICE_NAME,
          ]),
          cwd: installRoot, dockerHost: selected.dockerHost,
        }, "Local SIWC sidecar start");
        await verifyRunningSidecar({
          runProcess, installRoot, plan: selected, installId, projectName,
        });
      } catch (error) {
        let stopped = false;
        try {
          await runOrThrow(runProcess, {
            file: "docker",
            args: createComposeArgs(projectName, [
              "stop", "--timeout", "30", SERVICE_NAME,
            ]),
            cwd: installRoot, dockerHost: selected.dockerHost,
          }, "Unverified sidecar stop");
          const running = await runOrThrow(runProcess, {
            file: "docker",
            args: createComposeArgs(projectName, [
              "ps", "--status", "running", "--services", SERVICE_NAME,
            ]),
            cwd: installRoot, dockerHost: selected.dockerHost,
          }, "Unverified sidecar stopped check");
          stopped = running.stdout.trim() === "";
        } catch {
          // A disconnected Docker operation leaves this owned service uncertain.
        }
        const unsafePublication = /published.*host port/iu.test(error?.message ?? "");
        return {
          target: LOCAL_N8N_SIDECAR_TARGET,
          endpoint: LOCAL_N8N_SIDECAR_ENDPOINT,
          protocol: "openai-v1", clientCredential, credentialShownOnce: true,
          models: [], networkName: selected.networkName,
          hostPublication: stopped ? "none" : "unknown",
          deploymentMode: "partial", account: accepted.account,
          readiness: "unverified", runtimeState: stopped ? "stopped" : "unknown",
          runtimeFailure: unsafePublication
            ? { error: "The sidecar may have published a host port. Inspect it before use.",
                status: 503, recovery: "resolve-handoff" }
            : safeSiwcRuntimeFailure(),
          finalizationFailure: {
            error: "Ownership transferred, but the runtime could not be verified. Save the one-time key and resolve recovery before use.",
            recovery: "resolve-handoff",
          },
          ...(migrating ? { migrationPending: true, legacyRetained: true } : {}),
          ...(replacing ? { replacementPending: true, oldHistoryRetained: true } : {}),
        };
      }
      let models = [];
      let catalogFailure;
      try {
        models = await verifySidecarCatalog({
          runProcess, installRoot, plan: selected, projectName, clientCredential,
        });
      } catch (error) {
        catalogFailure = safeSiwcCatalogFailure(error);
      }
      let account = accepted.account;
      let status;
      try {
        status = await runSiwcCli({
          runProcess, installRoot, marker: runtime, command: "account-live",
        });
      } catch {
        catalogFailure ??= safeSiwcCatalogFailure({
          code: "owner_status_unavailable", recovery: "retry-later",
        });
      }
      if (status) {
        if (status.account?.registrationId !== binding.registrationId ||
            status.account.ownerHostId !== destination.hostId ||
            status.account.ownerRuntimeId !== installId ||
            status.account.ownership !== "owned") {
          return localSiwcFinalizationFailure({
            target: LOCAL_N8N_SIDECAR_TARGET, endpoint: LOCAL_N8N_SIDECAR_ENDPOINT,
            protocol: "openai-v1", clientCredential, credentialShownOnce: true,
            models: [], networkName: selected.networkName, hostPublication: "none",
            account, runtimeState: "running",
          }, "resolve-handoff");
        }
        account = status.account;
      }
      try {
      if (retiring) {
        const journalPath = join(legacyArchive, "migration.json");
        await writeManagedFile(fileSystem, journalPath, Buffer.from(
          `${JSON.stringify({
            schemaVersion: 1, state: "transferred",
            reviewedLegacy, replacementInstallId: installId,
            previousWasSiwc: replacing,
          })}\n`,
        ), 0o600);
        if (platform === "win32") {
          await lockDownPath(journalPath, { platform, kind: "file" });
        }
      }
      await saveStage("completed");
      } catch {
        return localSiwcFinalizationFailure({
          target: LOCAL_N8N_SIDECAR_TARGET, endpoint: LOCAL_N8N_SIDECAR_ENDPOINT,
          protocol: "openai-v1", clientCredential, credentialShownOnce: true,
          models, networkName: selected.networkName, hostPublication: "none",
          account, runtimeState: "running",
          ...(migrating ? { migrationPending: true, legacyRetained: true } : {}),
          ...(replacing ? { replacementPending: true, oldHistoryRetained: true } : {}),
        });
      }
      return {
        target: LOCAL_N8N_SIDECAR_TARGET,
        endpoint: LOCAL_N8N_SIDECAR_ENDPOINT,
        protocol: "openai-v1", clientCredential, credentialShownOnce: true,
        models, networkName: selected.networkName, hostPublication: "none",
        deploymentMode: migrating ? "migrated" : replacing ? "replaced" : "installed", account,
        readiness: catalogFailure ? "unverified" : "verified",
        runtimeState: "running",
        ...(catalogFailure ? { catalogFailure } : {}),
        ...(migrating ? { migratedLegacy: true, legacyRetained: true } : {}),
        ...(replacing ? { replacedAccount: true, oldHistoryRetained: true } : {}),
      };
      } catch (error) {
        if (preservedResult) return localSiwcFinalizationFailure(preservedResult, "resolve-handoff");
        throw error;
      }
    },
  });
}






export async function inspectStoppedLocalN8nSiwcInstallation(
  { registrationId, confirmed },
  {
    fileSystem = defaultFileSystem, env = process.env,
    homeDirectory = homedir(), runProcess = runLocalProcess,
    platform = process.platform, lockDownPath = lockDownLocalPath,
    getProcessIdentity, lifecycleLockNow = Date.now,
  } = {},
) {
  if (confirmed !== true) {
    throw new Error("Confirm inspection of the stopped local n8n SIWC account.");
  }
  validateSiwcRegistrationId(registrationId);
  assertSupportedPlatform(platform);
  rejectDockerEnvironmentOverrides(env);
  const installRoot = await resolveLocalN8nSidecarInstallRoot({
    env, homeDirectory, fileSystem, platform,
  });
  const releaseLock = await acquireSidecarLock({
    fileSystem, getProcessIdentity, installRoot, lockDownPath,
    now: lifecycleLockNow, platform,
  });
  return settleLocalIntegrationLifecycleOperation({
    completionLabel: "Stopped local n8n SIWC inspection",
    releaseLock,
    operation: async () => {
      await verifyWindowsSidecarStatusPathSecurity({
        fileSystem, installRoot, platform, lockDownPath,
      });
      const managed = await inspectManagedInstall({ fileSystem, installRoot });
      const marker = validateMarker(managed.marker);
      if (marker.registrationId !== registrationId) {
        throw new Error("The selected account is not installed in this bridge.");
      }
      await assertManagedSiwcCompose(fileSystem, installRoot, marker);
      const selectedDockerHost = await resolveLocalDockerHost({
        runProcess, cwd: installRoot, env, platform,
      });
      if (selectedDockerHost !== marker.dockerHost) {
        throw new Error("The selected Docker context changed.");
      }
      await attestPlanAndAlias({
        plan: marker, runProcess, cwd: installRoot,
        installId: marker.installId, projectName: marker.projectName,
      });
      const ownership = await attestProjectOwnership({
        runProcess, cwd: installRoot, dockerHost: marker.dockerHost,
        installId: marker.installId, projectName: marker.projectName,
        returnDetails: true,
      });
      if (!ownership.exact) throw new Error("The exact owned bridge is missing.");
      const runtime = await inspectOwnedSidecarRuntime({ runProcess, installRoot, marker });
      if (!runtime || runtime.running || runtime.paused) {
        throw new Error("The owned sidecar is not safely stopped.");
      }
      const account = (await runSiwcCli({
        runProcess, installRoot, marker, command: "account",
      })).account;
      if (account?.registrationId !== registrationId ||
          account?.ownerHostId !== marker.ownerHostId ||
          account?.ownerRuntimeId !== marker.installId ||
          account?.ownership !== "owned") {
        throw new Error("The stopped SIWC account could not be attested.");
      }
      return { account };
    },
  });
}

export async function manageLocalN8nSiwcInstallation(
  { registrationId, action, expectedGeneration, backgroundConsent, confirmed },
  {
    fileSystem = defaultFileSystem, env = process.env,
    homeDirectory = homedir(), runProcess = runLocalProcess,
    platform = process.platform, lockDownPath = lockDownLocalPath,
    getProcessIdentity, lifecycleLockNow = Date.now,
  } = {},
) {
  if (confirmed !== true ||
      !["sign-out", "disable-plan", "enable-plan"].includes(action) ||
      (action === "enable-plan" && backgroundConsent !== true)) {
    throw new Error("Confirm the selected installed SIWC account and background workflow consent.");
  }
  validateSiwcRegistrationId(registrationId);
  if (typeof expectedGeneration !== "string" ||
      !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(expectedGeneration)) {
    throw new TypeError("The selected SIWC account generation is invalid.");
  }
  assertSupportedPlatform(platform);
  rejectDockerEnvironmentOverrides(env);
  const installRoot = await resolveLocalN8nSidecarInstallRoot({
    env, homeDirectory, fileSystem, platform,
  });
  const releaseLock = await acquireSidecarLock({
    fileSystem, getProcessIdentity, installRoot, lockDownPath,
    now: lifecycleLockNow, platform,
  });
  return settleLocalIntegrationLifecycleOperation({
    completionLabel: "Installed local n8n SIWC account operation",
    releaseLock,
    operation: async () => {
      await verifyWindowsSidecarStatusPathSecurity({
        fileSystem, installRoot, platform, lockDownPath,
      });
      const managed = await inspectManagedInstall({ fileSystem, installRoot });
      const marker = validateMarker(managed.marker);
      if (marker.registrationId !== registrationId) {
        throw new Error("The selected SIWC account is not installed in this bridge.");
      }
      await assertManagedSiwcCompose(fileSystem, installRoot, marker);
      const selectedDockerHost = await resolveLocalDockerHost({
        runProcess, cwd: installRoot, env, platform,
      });
      if (selectedDockerHost !== marker.dockerHost) {
        throw new Error("The selected Docker context changed.");
      }
      await attestPlanAndAlias({
        plan: marker, runProcess, cwd: installRoot,
        installId: marker.installId, projectName: marker.projectName,
      });
      const ownership = await attestProjectOwnership({
        runProcess, cwd: installRoot, dockerHost: marker.dockerHost,
        installId: marker.installId, projectName: marker.projectName,
        returnDetails: true,
      });
      if (!ownership.exact) throw new Error("The exact owned sidecar project is missing.");
      const runtime = await inspectOwnedSidecarRuntime({ runProcess, installRoot, marker });
      if (!runtime || runtime.paused) {
        throw new Error("The owned sidecar state is ambiguous; account mutation was not attempted.");
      }
      const before = (await runSiwcCli({
        runProcess, installRoot, marker, command: "account",
      })).account;
      if (before?.registrationId !== registrationId ||
          before?.generation !== expectedGeneration ||
          before?.ownerHostId !== marker.ownerHostId ||
          before?.ownerRuntimeId !== marker.installId ||
          before?.ownership !== "owned") {
        throw new Error("The installed SIWC account changed; review it again.");
      }
      if (action === "enable-plan" &&
          (before.planPermission !== "granted" || before.session !== "connected")) {
        throw new Error("This installed account needs a fresh authorized SIWC sign-in before plan use can resume.");
      }
      // Before the account goes and while the sidecar still runs, as on a VPS: a later sign-in on this
      // volume must not inherit the image sign-in.
      const imagesRevocation = action === "sign-out"
        ? await signOutLocalCodexImages({ runProcess, installRoot, marker, running: runtime.running })
        : undefined;
      await runOrThrow(runProcess, {
        file: "docker",
        args: createComposeArgs(marker.projectName, ["stop", "--timeout", "30", SERVICE_NAME]),
        cwd: installRoot, dockerHost: marker.dockerHost,
      }, "Owned local sidecar stop");
      const stopped = await inspectOwnedSidecarRuntime({ runProcess, installRoot, marker });
      if (!stopped || stopped.containerId !== runtime.containerId ||
          stopped.running || stopped.paused) {
        throw new Error("The owned sidecar did not stop; account mutation was not attempted.");
      }
      const changed = await runSiwcCli({
        runProcess, installRoot, marker, command: action,
        input: Buffer.from(JSON.stringify({
          registrationId, expectedGeneration,
          ...(action === "enable-plan" ? { backgroundConsent: true } : {}),
        })),
      });
      if (changed.account?.registrationId !== registrationId ||
          changed.account?.ownerHostId !== marker.ownerHostId ||
          changed.account?.ownerRuntimeId !== marker.installId ||
          changed.account?.ownership !== "owned") {
        throw new Error("The installed SIWC account result could not be attested.");
      }
      if (action === "enable-plan") {
        if (changed.account.planEnabled !== true ||
            changed.account.planPermission !== "granted") {
          throw new Error("The installed SIWC grant could not be confirmed. The sidecar remains stopped.");
        }
        try {
        await runOrThrow(runProcess, {
          file: "docker",
          args: createComposeArgs(marker.projectName, [
            "up", "-d", "--wait", "--wait-timeout", "90",
            "--no-build", "--no-deps", SERVICE_NAME,
          ]),
          cwd: installRoot, dockerHost: marker.dockerHost,
        }, "Owned SIWC sidecar start");
        await verifyRunningSidecar({
          runProcess, installRoot, plan: marker,
          installId: marker.installId, projectName: marker.projectName,
        });
        } catch {
          let stoppedAfterFailure = false;
          try {
            await runOrThrow(runProcess, { file: "docker",
              args: createComposeArgs(marker.projectName, ["stop", "--timeout", "30", SERVICE_NAME]),
              cwd: installRoot, dockerHost: marker.dockerHost }, "Unverified enabled sidecar stop");
            const verified = await inspectOwnedSidecarRuntime({ runProcess, installRoot, marker });
            stoppedAfterFailure = !!verified && !verified.running && !verified.paused &&
              verified.containerId === runtime.containerId && verified.imageId === runtime.imageId;
          } catch { /* Preserve the unknown runtime outcome. */ }
          throw Object.assign(new Error(stoppedAfterFailure
            ? "The enabled sidecar failed verification and its stopped state was confirmed."
            : "The enabled sidecar outcome is unknown. Inspect and stop the owned service before use."),
          { runtimeStopped: stoppedAfterFailure, remoteOutcomeUnknown: !stoppedAfterFailure });
        }
      }
      return {
        account: changed.account, revocation: changed.revocation,
        runtimeStopped: action !== "enable-plan",
        ...(imagesRevocation === undefined ? {} : { imagesRevocation }),
      };
    },
  });
}

// Best effort: signs out of the image add-on in the running sidecar, or in a one-off container
// when it is stopped, and returns OpenAI's revocation result. "unknown" means the step could not
// run or failed; a sidecar built before the add-on has no image module.
async function signOutLocalCodexImages({ runProcess, installRoot, marker, running }) {
  try {
    const { revocation } = readCodexImagesCliResult(await runProcess({
      file: "docker",
      args: createComposeArgs(marker.projectName, [
        ...(running ? ["exec", "-T", SERVICE_NAME, "node"]
          : ["run", "--rm", "--no-deps", "-T", "--entrypoint", "node", SERVICE_NAME]),
        "/app/services/codex-images.mjs", "sign-out",
      ]),
      cwd: installRoot, dockerHost: marker.dockerHost,
    }));
    return ["confirmed", "unconfirmed", "not-applicable"].includes(revocation) ? revocation : "unknown";
  } catch {
    return "unknown";
  }
}

const CODEX_IMAGES_ACTIONS = new Set(["login-start", "login-poll", "login-cancel", "sign-out"]);
const CODEX_IMAGES_NOT_RUNNING = "The installed SIWC sidecar is not running for the reviewed account.";

// The image add-on's CLI runs in the exact running owned container, one fixed command per action.
// Status, sign-in start and sign-out re-attest the whole owned project; polling and cancelling a
// pending sign-in check only that the container from the status check still runs.
async function runLocalCodexImages(
  { registrationId, action, expectedContainerId },
  {
    fileSystem = defaultFileSystem, env = process.env,
    homeDirectory = homedir(), runProcess = runLocalProcess,
    platform = process.platform, lockDownPath = lockDownLocalPath,
    getProcessIdentity, lifecycleLockNow = Date.now,
  } = {},
) {
  validateSiwcRegistrationId(registrationId);
  assertSupportedPlatform(platform);
  rejectDockerEnvironmentOverrides(env);
  const installRoot = await resolveLocalN8nSidecarInstallRoot({ env, homeDirectory, fileSystem, platform });
  const releaseLock = await acquireSidecarLock({
    fileSystem, getProcessIdentity, installRoot, lockDownPath, now: lifecycleLockNow, platform,
  });
  return settleLocalIntegrationLifecycleOperation({
    completionLabel: "Local n8n Codex image sign-in operation",
    releaseLock,
    operation: async () => {
      await verifyWindowsSidecarStatusPathSecurity({ fileSystem, installRoot, platform, lockDownPath });
      const marker = validateMarker((await inspectManagedInstall({ fileSystem, installRoot })).marker);
      if (marker.registrationId !== registrationId) throw new Error(CODEX_IMAGES_NOT_RUNNING);
      await assertManagedSiwcCompose(fileSystem, installRoot, marker);
      if (await resolveLocalDockerHost({ runProcess, cwd: installRoot, env, platform }) !== marker.dockerHost) {
        throw new Error("The selected Docker context changed.");
      }
      if (["status", "login-start", "sign-out"].includes(action)) {
        await attestPlanAndAlias({
          plan: marker, runProcess, cwd: installRoot,
          installId: marker.installId, projectName: marker.projectName,
        });
        const ownership = await attestProjectOwnership({
          runProcess, cwd: installRoot, dockerHost: marker.dockerHost,
          installId: marker.installId, projectName: marker.projectName, returnDetails: true,
        });
        if (!ownership.exact) throw new Error("The exact owned sidecar project is missing.");
      }
      const runtime = await inspectOwnedSidecarRuntime({ runProcess, installRoot, marker });
      if (!runtime?.running || runtime.paused) throw new Error(CODEX_IMAGES_NOT_RUNNING);
      if (expectedContainerId !== undefined && runtime.containerId !== expectedContainerId) {
        throw new Error("The installed sidecar changed. Check image generation again.");
      }
      const result = await runProcess({
        file: "docker",
        args: createComposeArgs(marker.projectName, [
          "exec", "-T", SERVICE_NAME, "node", "/app/services/codex-images.mjs", action,
        ]),
        cwd: installRoot, dockerHost: marker.dockerHost,
      });
      return {
        ...readCodexImagesCliResult(result, { allowUnavailable: action === "status" }),
        containerId: runtime.containerId,
      };
    },
  });
}

// "unavailable" means the running sidecar predates the image add-on.
export function getLocalN8nCodexImagesStatus({ registrationId }, deps = {}) {
  return runLocalCodexImages({ registrationId, action: "status" }, deps);
}

export async function changeLocalN8nCodexImages(
  { registrationId, action, expectedContainerId, confirmed }, deps = {},
) {
  if (!CODEX_IMAGES_ACTIONS.has(action)) throw new TypeError("The image sign-in action is invalid.");
  if ((action === "login-start" || action === "sign-out") && confirmed !== true) {
    throw new Error("Confirm the Codex image sign-in change for this computer.");
  }
  validateDockerObjectId(expectedContainerId, "reviewed sidecar container");
  return runLocalCodexImages({ registrationId, action, expectedContainerId }, deps);
}

export async function removeLocalN8nSidecar(
  { confirmed },
  {
    fileSystem = defaultFileSystem,
    env = process.env,
    homeDirectory = homedir(),
    runProcess = runLocalProcess,
    platform = process.platform,
    lockDownPath = lockDownLocalPath,
    getProcessIdentity,
    lifecycleLockNow = Date.now,
  } = {},
) {
  if (confirmed !== true) {
    throw new Error("Confirm removal of the managed local n8n bridge.");
  }
  assertSupportedPlatform(platform);
  rejectDockerEnvironmentOverrides(env);
  const installRoot = await resolveLocalN8nSidecarInstallRoot({
    env,
    homeDirectory,
    fileSystem,
    platform,
  });
  const releaseLock = await acquireSidecarLock({
    fileSystem,
    getProcessIdentity,
    installRoot,
    lockDownPath,
    now: lifecycleLockNow,
    platform,
  });
  return settleLocalIntegrationLifecycleOperation({
    completionLabel: "Local n8n OAuth sidecar removal",
    releaseLock,
    operation: async () => {
      await verifyWindowsSidecarStatusPathSecurity({
        fileSystem,
        installRoot,
        platform,
        lockDownPath,
      });
      const managed = await inspectManagedInstall({ fileSystem, installRoot });
    if (!managed.marker) {
      throw new Error("The managed local n8n bridge is not installed.");
    }
    const marker = validateMarker(managed.marker);
    if (marker.legacyInstallId) {
      throw new Error("This bridge retains an offline legacy credential volume and migration archive. Removal needs a separate reviewed cleanup; nothing was deleted.");
    }
    await attestProjectOwnership({
      runProcess,
      cwd: installRoot,
      dockerHost: marker.dockerHost,
      installId: marker.installId,
      projectName: marker.projectName,
    });
    let imagesRevocation;
    if (marker.schemaVersion === MARKER_SCHEMA_VERSION) {
      await assertManagedSiwcCompose(fileSystem, installRoot, marker);
      const status = await runSiwcCli({
        runProcess, installRoot, marker, command: "account",
      });
      if (status.account?.registrationId !== marker.registrationId ||
          status.account?.ownerHostId !== marker.ownerHostId ||
          status.account?.session !== "signed-out" ||
          status.account?.planEnabled !== false) {
        throw new Error("Sign out of the installed SIWC account before removing its protected storage.");
      }
      // The volume delete below would drop a live image refresh token without revoking it. An install
      // made before the add-on has no image module, so it cannot hold an image sign-in.
      if (await lstatIfExists(fileSystem, join(installRoot, "services", "codex-images.mjs"))) {
        const runtime = await inspectOwnedSidecarRuntime({ runProcess, installRoot, marker });
        imagesRevocation = await signOutLocalCodexImages({
          runProcess, installRoot, marker, running: runtime?.running === true && !runtime.paused,
        });
        if (imagesRevocation === "unknown") {
          throw new Error("The image sign-out did not finish, so the bridge and its volume were kept. Try removal again.");
        }
      } else imagesRevocation = "not-applicable";
    }
    await cleanupSidecarProject({
      runProcess,
      installRoot,
      dockerHost: marker.dockerHost,
      projectName: marker.projectName,
    });
    const imageName = `${marker.projectName}:local`;
    if (
      await inspectOwnedImageIfPresent({
        runProcess,
        cwd: installRoot,
        dockerHost: marker.dockerHost,
        installId: marker.installId,
        projectName: marker.projectName,
      })
    ) {
      await runOrThrow(
        runProcess,
        {
          file: "docker",
          args: ["image", "rm", imageName],
          cwd: installRoot,
          dockerHost: marker.dockerHost,
        },
        "Local sidecar image removal",
      );
    }
    await fileSystem.rm(installRoot, { recursive: true, force: false });
      return { removed: true, target: LOCAL_N8N_SIDECAR_TARGET,
        ...(imagesRevocation === undefined ? {} : { imagesRevocation }) };
    },
  });
}