const { execFile } = require("node:child_process"); const { createHash } = require("node:crypto"); const { chmod, mkdtemp, mkdir, rm, symlink, writeFile, readFile } = require("node:fs/promises"); const os = require("node:os"); const path = require("node:path"); const { pathToFileURL } = require("node:url"); const { promisify } = require("node:util"); const execFileAsync = promisify(execFile); const ROOT_DIR = path.resolve(__dirname, "../../../.."); const PREFLIGHT = path.join(ROOT_DIR, "deploy/trialrun/preflight-remote.sh"); const AGGREGATE_PREFLIGHT = path.join(ROOT_DIR, "deploy/trialrun/check-existing-deployment.sh"); const REFRESH_HELPER = path.join(ROOT_DIR, "scripts/refresh-deployment-contract.sh"); const REFRESH_INSTALLER = path.join(ROOT_DIR, "deploy/trialrun/install-deployment-contract-refresh.sh"); const PRODUCTION_PREFLIGHT = path.join(ROOT_DIR, "deploy/trialrun/production-preflight.mjs"); const PRODUCTION_PREFLIGHT_REMOTE = path.join(ROOT_DIR, "deploy/trialrun/production-preflight-remote.sh"); const PRODUCTION_IDENTITY_BOOTSTRAP = path.join(ROOT_DIR, "deploy/trialrun/production-identity-bootstrap.mjs"); const PRODUCTION_IDENTITY_BOOTSTRAP_REMOTE = path.join(ROOT_DIR, "deploy/trialrun/production-identity-bootstrap-remote.sh"); describe("deployment safety contract", () => { let fixtureRoot; let remoteDir; let envFile; let postgresDir; let storageDir; beforeEach(async () => { fixtureRoot = await mkdtemp(path.join(os.tmpdir(), "hyb-oa-deploy-safety-")); remoteDir = path.join(fixtureRoot, "app"); envFile = path.join(remoteDir, "deploy/trialrun/.env"); postgresDir = path.join(fixtureRoot, "postgres"); storageDir = path.join(fixtureRoot, "storage"); await mkdir(path.join(remoteDir, "server"), { recursive: true }); await mkdir(path.join(remoteDir, "deploy/trialrun"), { recursive: true }); await mkdir(postgresDir, { recursive: true }); await mkdir(storageDir, { recursive: true }); await writeFile(path.join(remoteDir, "server/package.json"), "{}\n"); await writeFile(path.join(remoteDir, "deploy/trialrun/docker-compose.yml"), "services: {}\n"); await writeFile(envFile, "APP_ORIGIN=https://example.invalid\n", { mode: 0o600 }); await writeFile(path.join(postgresDir, "PG_VERSION"), "16\n"); }); afterEach(async () => { await rm(fixtureRoot, { recursive: true, force: true }); }); function preflight(overrides = {}) { return execFileAsync("bash", [PREFLIGHT], { env: { ...process.env, REMOTE_DIR: remoteDir, REMOTE_ENV_FILE: envFile, COMPOSE_FILE: "deploy/trialrun/docker-compose.yml", POSTGRES_DATA_DIR: postgresDir, STORAGE_HOST_DIR: storageDir, DEPLOY_DATA_MODE: "existing", SYNC_ENV: "0", ...overrides, }, }); } it("accepts a complete existing deployment contract", async () => { await expect(preflight()).resolves.toMatchObject({ stdout: expect.stringContaining("[remote-preflight][PASS]") }); }); it("rejects a config directory masquerading as the repository root", async () => { await expect(preflight({ REMOTE_DIR: path.join(remoteDir, "deploy/trialrun") })).rejects.toMatchObject({ code: 1 }); }); it("rejects a missing or symbolic remote env before synchronization", async () => { await rm(envFile); await expect(preflight()).rejects.toMatchObject({ code: 1 }); await symlink(path.join(remoteDir, "missing.env"), envFile); await expect(preflight()).rejects.toMatchObject({ code: 1 }); }); it("rejects invalid existing data directories", async () => { await rm(path.join(postgresDir, "PG_VERSION")); await expect(preflight()).rejects.toMatchObject({ code: 1 }); }); it("runs remote preflight before rsync and reads existing contracts from systemd", async () => { const deploy = await require("node:fs/promises").readFile(path.join(ROOT_DIR, "deploy/trialrun/deploy.sh"), "utf8"); const wrapper = await require("node:fs/promises").readFile(path.join(ROOT_DIR, "deploy/trialrun/deploy-existing.sh"), "utf8"); expect(deploy.indexOf("REMOTE_PREFLIGHT_SCRIPT")).toBeGreaterThanOrEqual(0); expect(deploy.indexOf('>>> 3. 同步前只读校验远端部署合同')).toBeLessThan(deploy.indexOf("rsync -az --delete")); expect(deploy.indexOf('>>> 3. 同步前只读校验远端部署合同')).toBeLessThan(deploy.indexOf("mkdir -p '${REMOTE_DIR}'")); expect(wrapper).toContain("check-existing-deployment.sh"); expect(wrapper.indexOf("check-existing-deployment.sh")).toBeLessThan(wrapper.indexOf('bash "$ROOT_DIR/deploy/trialrun/deploy.sh"')); expect(wrapper).not.toContain("docker inspect"); expect(wrapper).not.toContain("working_dir"); expect(wrapper).toContain("DEPLOY_DATA_MODE=existing"); expect(wrapper).toContain("SYNC_ENV=0"); expect(wrapper).toContain("DEPLOY_DEFER_FINAL_SUCCESS=1"); expect(wrapper).toContain("DEPLOY_STATUS_OUTPUT_MODE=quiet"); expect(deploy).toContain("DEPLOY_STATUS_OUTPUT_MODE"); expect(deploy).toContain("DEPLOY_STATUS_OUTPUT_MODE='${DEPLOY_STATUS_OUTPUT_MODE}'"); expect(wrapper).toContain("生产部署验证不接受未进入上游的提交"); expect(wrapper).toContain("部署后 migration status 与目标只读复核"); expect(wrapper).toContain('EXPECTED_PENDING_MIGRATIONS=""'); expect(wrapper.indexOf('EXPECTED_PENDING_MIGRATIONS=""')).toBeGreaterThan( wrapper.indexOf('bash "$ROOT_DIR/deploy/trialrun/deploy.sh"'), ); expect(wrapper.indexOf('ssh "$DEPLOY_REFRESH_SERVER" refresh')).toBeGreaterThan(wrapper.indexOf('bash "$ROOT_DIR/deploy/trialrun/deploy.sh"')); expect(wrapper).toContain("DEPLOYED_BUT_CONTRACT_REFRESH_FAILED"); }); it("requires production target identity and pending migration allowlist before deploy.sh", async () => { const wrapper = await readFile(path.join(ROOT_DIR, "deploy/trialrun/deploy-existing.sh"), "utf8"); const preflight = await readFile(PRODUCTION_PREFLIGHT, "utf8"); const remote = await readFile(PRODUCTION_PREFLIGHT_REMOTE, "utf8"); const bootstrap = await readFile(PRODUCTION_IDENTITY_BOOTSTRAP, "utf8"); expect(wrapper).toContain("EXPECTED_PRODUCTION_ORIGIN"); expect(wrapper).toContain("EXPECTED_PRODUCTION_DB_NAME_SHA256"); expect(wrapper).toContain("EXPECTED_PENDING_MIGRATIONS"); expect(wrapper).toContain("EXPECTED_DEPLOY_SERVER"); expect(wrapper).toContain("EXPECTED_REMOTE_DIR"); expect(wrapper).toContain("EXPECTED_COMPOSE_PROJECT_NAME"); expect(wrapper).toContain("PRODUCTION_READ_ONLY_PREFLIGHT"); expect(wrapper.indexOf('node "$ROOT_DIR/$PRODUCTION_PREFLIGHT_SCRIPT"')).toBeLessThan( wrapper.indexOf('bash "$ROOT_DIR/deploy/trialrun/deploy.sh"'), ); expect(wrapper.indexOf('if [[ "${PRODUCTION_READ_ONLY_PREFLIGHT:-0}" == "1" ]]')).toBeLessThan( wrapper.indexOf('bash "$ROOT_DIR/deploy/trialrun/deploy.sh"'), ); expect(preflight).toContain("CANDIDATE_MIGRATIONS_CSV"); expect(preflight).toContain("PRISMA_STATUS_OUTPUT_MISSING"); expect(preflight).toContain("PRISMA_STATUS_OUTPUT_UNREADABLE"); expect(preflight).toContain("CANDIDATE_COMMIT_MISSING"); expect(preflight).not.toContain("rev-parse"); expect(preflight).toContain("redacted datasource line"); expect(preflight).toContain("PRODUCTION_PREFLIGHT_REPORT_NOT_FRESH"); expect(preflight.lastIndexOf("printStableRemoteSummary(stdout)")).toBeLessThan( preflight.lastIndexOf("assertRemotePreflightResult({"), ); expect(preflight.indexOf("reportRef=${reportRef(reportDir)}")).toBeLessThan( preflight.lastIndexOf("assertRemotePreflightResult({"), ); expect(remote).toContain("PRISMA_STATUS_BEGIN"); expect(remote).toContain("PROD_MIGRATION_STATUS_UNKNOWN_PENDING"); expect(remote).toContain("logged_failure"); expect(remote).toContain("PROD_DATABASE_URL_HOST_NON_PRODUCTION_IDENTITY"); expect(remote).toContain("PROD_TARGET_BUILD_SHA_MISMATCH"); expect(remote).toContain('FROM "_prisma_migrations"'); expect(remote).toContain("rollbackWindow=OPEN"); expect(remote).not.toMatch(/\b(prisma migrate reset|prisma db push|prisma migrate resolve)\b/); expect(remote.indexOf("PRISMA_STATUS_BEGIN")).toBeLessThan(remote.indexOf("_prisma_migrations")); expect(bootstrap.indexOf("assertContractForOriginVerification")).toBeLessThan( bootstrap.indexOf("verifyOriginIdentity(identity, contract, expectedOrigin);"), ); expect(bootstrap.indexOf("verifyOriginIdentity(identity, contract, expectedOrigin);")).toBeLessThan( bootstrap.indexOf("const expectedRemoteDir = contract.REMOTE_DIR"), ); expect(bootstrap.indexOf("const expectedRemoteDir = contract.REMOTE_DIR")).toBeLessThan( bootstrap.indexOf("const databaseIdentityHash = bootstrapDatabaseIdentityHash"), ); expect(bootstrap.indexOf('if (identityOnly === "1")')).toBeLessThan( bootstrap.indexOf("const databaseIdentityHash = bootstrapDatabaseIdentityHash"), ); expect(bootstrap.indexOf("const databaseIdentityHash = bootstrapDatabaseIdentityHash")).toBeLessThan( bootstrap.indexOf("spawnSync(\"bash\", [DEPLOY_EXISTING_SCRIPT]"), ); }); it("rejects loopback/staging production identities without invoking SSH", async () => { const target = await import(pathToFileURL(PRODUCTION_PREFLIGHT).href); expect(() => target.validateProductionOrigin("https://127.0.0.1")).toThrowError( expect.objectContaining({ code: "PROD_TARGET_ORIGIN_NON_PRODUCTION_IDENTITY" }), ); expect(() => target.validateProductionOrigin("https://staging.example.com")).toThrowError( expect.objectContaining({ code: "PROD_TARGET_ORIGIN_NON_PRODUCTION_IDENTITY" }), ); expect(() => target.validateProductionOrigin("https://0.0.0.0")).toThrowError( expect.objectContaining({ code: "PROD_TARGET_ORIGIN_NON_PRODUCTION_IDENTITY" }), ); expect(() => target.validateProductionOrigin("https://[::ffff:127.0.0.1]")).toThrowError( expect.objectContaining({ code: "PROD_TARGET_ORIGIN_NON_PRODUCTION_IDENTITY" }), ); expect(() => target.validateProductionDbName("hyb_oa_regression")).toThrowError( expect.objectContaining({ code: "PROD_TARGET_DB_NON_PRODUCTION_IDENTITY" }), ); expect(() => target.validateExactProductionIdentity({ deployServer: "deploy.production.invalid", remoteDir: "/srv/hyb-oa-trialrun", composeProjectName: "hyb-oa-trialrun", expectedDeployServer: "deploy.production.invalid", expectedRemoteDir: "/srv/hyb-oa-trialrun", expectedComposeProjectName: "hyb-oa-trialrun", })).not.toThrow(); expect(() => target.validateExactProductionIdentity({ deployServer: "deploy.production.invalid", remoteDir: "/srv/hyb-oa-trialrun", composeProjectName: "hyb-oa-trialrun", expectedDeployServer: "deploy.production.invalid", expectedRemoteDir: "/srv/different", expectedComposeProjectName: "hyb-oa-trialrun", })).toThrowError(expect.objectContaining({ code: "REMOTE_DIR_MISMATCH" })); expect(() => target.validateExactProductionIdentity({ deployServer: "deploy.production.invalid", remoteDir: "/srv/hyb-oa-trialrun", composeProjectName: "hyb-oa-trialrun", expectedDeployServer: "different.production.invalid", expectedRemoteDir: "/srv/hyb-oa-trialrun", expectedComposeProjectName: "hyb-oa-trialrun", })).toThrowError(expect.objectContaining({ code: "DEPLOY_SERVER_MISMATCH" })); expect(() => target.validateExactProductionIdentity({ deployServer: "deploy.production.invalid", remoteDir: "/srv/hyb-oa-trialrun", composeProjectName: "hyb-oa-trialrun", expectedDeployServer: "deploy.production.invalid", expectedRemoteDir: "/srv/hyb-oa-trialrun", expectedComposeProjectName: "different", })).toThrowError(expect.objectContaining({ code: "COMPOSE_PROJECT_NAME_MISMATCH" })); expect(() => target.validateExactProductionIdentity({ deployServer: "deploy.production.invalid", remoteDir: "/srv/hyb-oa-trialrun", composeProjectName: "hyb-oa-trialrun", expectedDeployServer: "deploy.production.invalid", expectedRemoteDir: "/srv/hyb-oa-trialrun", })).toThrowError(expect.objectContaining({ code: "EXPECTED_COMPOSE_PROJECT_NAME_MISSING" })); expect(() => target.validateExactProductionIdentity({ deployServer: "deploy.staging.invalid", remoteDir: "/srv/hyb-oa-trialrun", composeProjectName: "hyb-oa-trialrun", expectedDeployServer: "deploy.staging.invalid", expectedRemoteDir: "/srv/hyb-oa-trialrun", expectedComposeProjectName: "hyb-oa-trialrun", })).toThrowError(expect.objectContaining({ code: "DEPLOY_SERVER_NON_PRODUCTION_IDENTITY" })); expect(() => target.validatePrismaStatusText("")).toThrowError( expect.objectContaining({ code: "PRISMA_STATUS_OUTPUT_UNREADABLE" }), ); expect(() => target.validatePrismaStatusText("unexpected output")).toThrowError( expect.objectContaining({ code: "PRISMA_STATUS_OUTPUT_UNREADABLE" }), ); }); it.each([ { name: "prefers a remote safety code when the marker is missing", status: 1, stdout: "", stderr: "[production-preflight][PAUSED] code=PROD_DATABASE_IDENTITY_MISMATCH", rawStatus: null, expectedCode: "PROD_DATABASE_IDENTITY_MISMATCH", }, { name: "prefers a remote safety code when the marker exists", status: 1, stdout: "[production-preflight][PAUSED] code=PROD_MIGRATION_STATUS_FAILED", stderr: "", rawStatus: "Database schema is up to date!", expectedCode: "PROD_MIGRATION_STATUS_FAILED", }, { name: "fails closed when a remote failure has no parseable code", status: 1, stdout: "remote command failed", stderr: "ssh exited unexpectedly", rawStatus: null, expectedCode: "PRODUCTION_PREFLIGHT_REMOTE_FAILED", }, { name: "requires the Prisma marker after a successful remote exit", status: 0, stdout: "[production-preflight][PASS] target_identity", stderr: "", rawStatus: null, expectedCode: "PRISMA_STATUS_OUTPUT_MISSING", }, ])("$name", async ({ status, stdout, stderr, rawStatus, expectedCode }) => { const target = await import(pathToFileURL(PRODUCTION_PREFLIGHT).href); expect(() => target.assertRemotePreflightResult({ status, stdout, stderr, rawStatus })).toThrowError( expect.objectContaining({ code: expectedCode }), ); }); it("captures a redacted pre-status evidence copy from a controlled SSH fixture", async () => { const fakeBin = path.join(fixtureRoot, "bin"); const reportDir = path.join(fixtureRoot, "report"); const sshCapture = path.join(fixtureRoot, "ssh-command.txt"); await mkdir(fakeBin, { recursive: true }); await mkdir(reportDir, { recursive: true }); await writeFile(path.join(reportDir, "prisma-migrate-status.txt"), "stale PASS\n"); const fakeSsh = path.join(fakeBin, "ssh"); await writeFile( fakeSsh, [ "#!/usr/bin/env node", "require('node:fs').writeFileSync(process.env.FAKE_SSH_CAPTURE, process.argv.slice(2).join(' '));", "process.stdout.write('[production-preflight][PASS] target_identity\\n');", "process.stdout.write('[production-preflight][PRISMA_STATUS_BEGIN]\\n');", "process.stdout.write('Datasource \\\"db\\\": PostgreSQL database \\\"hyb_oa\\\" at \\\"db.internal:5432\\\"\\n');", "process.stdout.write('Database schema is up to date!\\n');", "process.stdout.write('[production-preflight][PRISMA_STATUS_END] exit=0\\n');", "process.stdout.write('[production-preflight][PASS] migration_reconciliation pending=none\\n');", "process.stdout.write('[production-preflight][PASS] rollbackWindow=OPEN terminatedRows=0\\n');", ].join("\n"), { mode: 0o700 }, ); await chmod(fakeSsh, 0o700); const candidateCommit = require("node:child_process") .execFileSync("git", ["rev-parse", "HEAD"], { cwd: ROOT_DIR, encoding: "utf8" }) .trim(); const result = await execFileAsync("node", [PRODUCTION_PREFLIGHT], { cwd: ROOT_DIR, env: { ...process.env, PATH: `${fakeBin}${path.delimiter}${process.env.PATH}`, DEPLOY_SERVER: "deploy.production.invalid", REMOTE_DIR: remoteDir, REMOTE_ENV_FILE: envFile, COMPOSE_FILE: "deploy/trialrun/docker-compose.yml", COMPOSE_PROJECT_NAME: "hyb-oa-trialrun", POSTGRES_DATA_DIR: postgresDir, STORAGE_HOST_DIR: storageDir, EXPECTED_PRODUCTION_ORIGIN: "https://oa.hyinda.com", EXPECTED_PRODUCTION_DB_NAME_SHA256: createHash("sha256").update("hyb_oa", "utf8").digest("hex"), EXPECTED_PENDING_MIGRATIONS: "", EXPECTED_DEPLOY_SERVER: "deploy.production.invalid", EXPECTED_REMOTE_DIR: remoteDir, EXPECTED_COMPOSE_PROJECT_NAME: "hyb-oa-trialrun", CANDIDATE_COMMIT: candidateCommit, PRODUCTION_PREFLIGHT_REPORT_DIR: reportDir, FAKE_SSH_CAPTURE: sshCapture, }, }); const statusEvidence = await readFile(path.join(reportDir, "prisma-migrate-status.txt"), "utf8"); const sshCommand = await readFile(sshCapture, "utf8"); expect(result.stdout).toContain("[production-preflight][PASS]"); expect(statusEvidence).toContain("Database schema is up to date!"); expect(statusEvidence).toContain("[redacted datasource line]"); expect(statusEvidence).not.toContain("hyb_oa"); expect(statusEvidence).not.toContain("db.internal:5432"); expect(result.stdout).not.toContain("oa.hyinda.com"); expect(result.stdout).not.toContain("hyb_oa"); expect(sshCommand).not.toContain("oa.hyinda.com"); expect(sshCommand).not.toContain("hyb_oa"); expect(sshCommand).toContain("EXPECTED_PRODUCTION_ORIGIN_SHA256"); expect(sshCommand).toContain("EXPECTED_PRODUCTION_DB_NAME_SHA256"); expect(sshCommand).toContain(`BUILD_SHA='${candidateCommit}'`); expect(sshCommand).toContain(`VITE_BUILD_SHA='${candidateCommit.slice(0, 12)}'`); }); it("bootstraps only an exact historical identity and a unique refresh probe", async () => { const bootstrap = await import(pathToFileURL(PRODUCTION_IDENTITY_BOOTSTRAP).href); const historicalTarget = [ 'DEPLOY_SERVER="${DEPLOY_SERVER:-deploy.production.invalid}"', 'REMOTE_DIR="${REMOTE_DIR:-/srv/hyb-oa-trialrun}"', ].join("\n"); const historicalProject = [ 'REMOTE_DIR="${REMOTE_DIR:-/srv/hyb-oa-trialrun}"', 'COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-hyb-oa-trialrun}"', ].join("\n"); expect(bootstrap.parseHistoricalDeploymentIdentity(historicalTarget, historicalProject)).toEqual({ deployServer: "deploy.production.invalid", composeProjectName: "hyb-oa-trialrun", }); expect(bootstrap.selectUniqueRefreshTarget([ { target: "ordinary", status: 1, stdout: "" }, { target: "refresh", status: 0, stdout: "[deployment-contract-refresh][PASS] probe\n" }, ])).toBe("refresh"); expect(() => bootstrap.selectUniqueRefreshTarget([])).toThrowError( expect.objectContaining({ code: "REFRESH_IDENTITY_NOT_FOUND" }), ); expect(() => bootstrap.selectUniqueRefreshTarget([ { target: "refresh-a", status: 0, stdout: "[deployment-contract-refresh][PASS] probe" }, { target: "refresh-b", status: 0, stdout: "[deployment-contract-refresh][PASS] probe" }, ])).toThrowError(expect.objectContaining({ code: "REFRESH_IDENTITY_NOT_UNIQUE" })); const contract = bootstrap.parseDeploymentContract([ "REMOTE_DIR=/srv/hyb-oa-trialrun", "REMOTE_ENV_FILE=/srv/hyb-oa-trialrun/deploy/trialrun/.env", "COMPOSE_FILE=deploy/trialrun/docker-compose.yml", "COMPOSE_PROJECT_NAME=hyb-oa-trialrun", "POSTGRES_DATA_DIR=/srv/data/postgres", "STORAGE_HOST_DIR=/srv/data/storage", ].join(" ")); expect(() => bootstrap.assertContractForOriginVerification( bootstrap.parseHistoricalDeploymentIdentity(historicalTarget, historicalProject), contract, )).not.toThrow(); const relocatedContract = { ...contract, REMOTE_DIR: "/srv/current-production", REMOTE_ENV_FILE: "/srv/current-production/deploy/trialrun/.env", }; expect(() => bootstrap.assertContractForOriginVerification( bootstrap.parseHistoricalDeploymentIdentity(historicalTarget, historicalProject), relocatedContract, )).not.toThrow(); expect(() => bootstrap.assertContractForOriginVerification( bootstrap.parseHistoricalDeploymentIdentity(historicalTarget, historicalProject), { ...contract, COMPOSE_PROJECT_NAME: "different" }, )).toThrowError(expect.objectContaining({ code: "SYSTEMD_COMPOSE_PROJECT_MISMATCH" })); expect(() => bootstrap.assertContractForOriginVerification( bootstrap.parseHistoricalDeploymentIdentity(historicalTarget, historicalProject), { ...contract, REMOTE_ENV_FILE: "/srv/different/.env" }, )).toThrowError(expect.objectContaining({ code: "SYSTEMD_REMOTE_ENV_FILE_MISMATCH" })); const bootstrapSource = await readFile(PRODUCTION_IDENTITY_BOOTSTRAP, "utf8"); const remoteSource = await readFile(PRODUCTION_IDENTITY_BOOTSTRAP_REMOTE, "utf8"); expect(bootstrapSource).not.toContain("console.log(databaseIdentityHash)"); expect(bootstrapSource).not.toContain("console.log(identity)"); expect(remoteSource).toContain("DB_SHA256"); expect(remoteSource).not.toContain("DB_BASE64"); expect(remoteSource).not.toContain("prisma migrate status"); expect(remoteSource.indexOf('IDENTITY_BOOTSTRAP_MODE" == "origin"')).toBeLessThan( remoteSource.indexOf("actual_db_name="), ); }); it("verifies both origin samples before reading the remote database name", async () => { const fakeBin = path.join(fixtureRoot, "origin-bin"); await mkdir(fakeBin, { recursive: true }); await writeFile(path.join(fakeBin, "docker"), [ "#!/usr/bin/env bash", "set -euo pipefail", "joined=\"$*\"", "if [[ \"$1\" == compose && \"${2:-}\" == version ]]; then exit 0; fi", "if [[ \"$1\" == ps ]]; then printf 'server1\\n'; exit 0; fi", "if [[ \"$1\" == inspect ]]; then printf 'APP_ORIGIN=https://example.invalid\\n'; exit 0; fi", "printf 'unexpected fake docker call: %s\\n' \"$joined\" >&2", "exit 97", "", ].join("\n"), { mode: 0o700 }); await chmod(path.join(fakeBin, "docker"), 0o700); const hash = createHash("sha256").update("https://example.invalid", "utf8").digest("hex"); const runBootstrapRemote = (mode) => execFileAsync("bash", [PRODUCTION_IDENTITY_BOOTSTRAP_REMOTE], { cwd: remoteDir, env: { ...process.env, PATH: `${fakeBin}${path.delimiter}${process.env.PATH}`, IDENTITY_BOOTSTRAP_MODE: mode, REMOTE_DIR: remoteDir, REMOTE_ENV_FILE: envFile, COMPOSE_FILE: "deploy/trialrun/docker-compose.yml", COMPOSE_PROJECT_NAME: "hyb-oa-trialrun", EXPECTED_PRODUCTION_ORIGIN_SHA256: hash, }, }); await expect(runBootstrapRemote("origin")).resolves.toMatchObject({ stdout: "[production-identity-bootstrap][PASS] origin_identity\n", }); await expect(runBootstrapRemote("database")).rejects.toMatchObject({ stderr: expect.stringContaining("PROD_TARGET_DB_NAME_MISSING"), }); }); it("runs the remote gate against synthetic status and migration history", async () => { const fakeBin = path.join(fixtureRoot, "remote-bin"); await mkdir(fakeBin, { recursive: true }); await writeFile(path.join(remoteDir, "deploy/trialrun/.env"), [ "APP_ORIGIN=https://oa.example.com", "POSTGRES_DB=production_db", "POSTGRES_USER=synthetic_user", "NODE_ENV=production", "COOKIE_SECURE=true", "", ].join("\n"), { mode: 0o600 }); await writeFile(path.join(fakeBin, "docker"), [ "#!/usr/bin/env bash", "set -euo pipefail", "joined=\"$*\"", "mode=\"${FAKE_REMOTE_MODE:-happy}\"", "if [[ \"$1\" == compose && \"${2:-}\" == version ]]; then exit 0; fi", "if [[ \"$1\" == ps ]]; then", " if [[ \"$joined\" == *service=server* ]]; then printf 'server1\\n'; else printf 'db1\\n'; fi", " exit 0", "fi", "if [[ \"$1\" == inspect ]]; then printf 'NODE_ENV=production\\nCOOKIE_SECURE=true\\nAPP_ORIGIN=https://oa.example.com\\n'; exit 0; fi", "if [[ \"$joined\" == *' config'* ]]; then exit 0; fi", "if [[ \"$joined\" == *' exec '* && \"$joined\" == *' sh -lc '* ]]; then", " case \"$mode\" in", " pending) printf 'Following migration have not yet been applied:\\n20260807193001_followup_migration\\n'; exit 1 ;;", " unknown) printf 'Following migration have not yet been applied:\\n20260807193002_unknown_migration\\n'; exit 1 ;;", " *) printf 'Database schema is up to date!\\n'; exit 0 ;;", " esac", "fi", "if [[ \"$joined\" == *' exec '* && \"$joined\" == *' node -e '* ]]; then", " printf 'db.internal\\nproduction_db\\n'; exit 0", "fi", "if [[ \"$joined\" == *'SELECT current_database()'* ]]; then printf 'production_db\\n'; exit 0; fi", "if [[ \"$joined\" == *'_prisma_migrations'* ]]; then", " case \"$mode\" in", " pending) printf '20260807193000_contract_registry_termination_workspace|applied\\n';;", " logs) printf '20260807193000_contract_registry_termination_workspace|logged_failure\\n';;", " *) printf '20260807193000_contract_registry_termination_workspace|applied\\n20260807193001_followup_migration|applied\\n';;", " esac", " exit 0", "fi", "if [[ \"$joined\" == *'contract_registry'* ]]; then printf '0\\n'; exit 0; fi", "printf 'unexpected fake docker call: %s\\n' \"$joined\" >&2", "exit 97", "", ].join("\n"), { mode: 0o700 }); await chmod(path.join(fakeBin, "docker"), 0o700); const hash = (value) => createHash("sha256").update(value, "utf8").digest("hex"); const buildSha = "a".repeat(40); const runRemote = (mode, expectedPending = "", buildOverrides = {}) => execFileAsync("bash", [PRODUCTION_PREFLIGHT_REMOTE], { cwd: remoteDir, env: { ...process.env, PATH: `${fakeBin}${path.delimiter}${process.env.PATH}`, FAKE_REMOTE_MODE: mode, REMOTE_DIR: remoteDir, REMOTE_ENV_FILE: envFile, COMPOSE_FILE: "deploy/trialrun/docker-compose.yml", COMPOSE_PROJECT_NAME: "hyb-oa-trialrun", POSTGRES_DATA_DIR: postgresDir, STORAGE_HOST_DIR: storageDir, EXPECTED_PRODUCTION_ORIGIN_SHA256: hash("https://oa.example.com"), EXPECTED_PRODUCTION_DB_NAME_SHA256: hash("production_db"), BUILD_SHA: buildSha, VITE_BUILD_SHA: buildSha.slice(0, 12), CANDIDATE_MIGRATIONS_CSV: "20260807193000_contract_registry_termination_workspace,20260807193001_followup_migration", EXPECTED_PENDING_MIGRATIONS_CSV: expectedPending, ...buildOverrides, }, }); const result = await runRemote("happy"); expect(result.stdout).toContain("target_identity"); expect(result.stdout).toContain("migration_reconciliation pending=none"); expect(result.stdout).toContain("rollbackWindow=OPEN"); const pendingResult = await runRemote("pending", "20260807193001_followup_migration"); expect(pendingResult.stdout).toContain("migration_reconciliation pending=20260807193001_followup_migration"); await expect(runRemote("unknown")).rejects.toMatchObject({ stderr: expect.stringContaining("PROD_MIGRATION_STATUS_UNKNOWN_PENDING"), }); await expect(runRemote("logs")).rejects.toMatchObject({ stderr: expect.stringContaining("PROD_MIGRATION_FAILED_OR_ROLLED_BACK"), }); await expect(runRemote("happy", "", { BUILD_SHA: "a".repeat(39) })).rejects.toMatchObject({ stderr: expect.stringContaining("PROD_TARGET_BUILD_SHA_INVALID"), }); await expect(runRemote("happy", "", { VITE_BUILD_SHA: "a".repeat(7) })).rejects.toMatchObject({ stderr: expect.stringContaining("PROD_TARGET_VITE_BUILD_SHA_INVALID"), }); await expect(runRemote("happy", "", { VITE_BUILD_SHA: "b".repeat(12) })).rejects.toMatchObject({ stderr: expect.stringContaining("PROD_TARGET_BUILD_SHA_MISMATCH"), }); }); it("aggregates preflight checks and keeps the root helper self-contained", async () => { const aggregate = await require("node:fs/promises").readFile(AGGREGATE_PREFLIGHT, "utf8"); const helper = await require("node:fs/promises").readFile(REFRESH_HELPER, "utf8"); const installer = await require("node:fs/promises").readFile(REFRESH_INSTALLER, "utf8"); expect(aggregate).toContain("set -uo pipefail"); expect(aggregate).not.toMatch(/^set\s+-[A-Za-z]*e[A-Za-z]*(?:\s|$)/m); expect(aggregate).toContain("CHECK_NAMES=("); expect(aggregate).toContain("root_ssh_identity"); expect(aggregate).toContain("refresh_program"); expect(helper).toContain("SSH_ORIGINAL_COMMAND"); expect(helper).toContain("20-active-build.conf"); expect(helper).toContain("refresh_program_integrity_invalid"); expect(helper).not.toContain("eval "); expect(helper).not.toContain("bash -c"); expect(helper).not.toContain("REMOTE_DIR/"); expect(installer).toContain("dedicated key already has unmanaged or unrestricted root authorization"); expect(installer).toContain("no-agent-forwarding,no-port-forwarding,no-X11-forwarding,no-pty,no-user-rc"); expect(installer).toContain("managed forced-command marker is malformed"); }); it("keeps immutable build args after stable dependency layers", async () => { const dockerfile = await require("node:fs/promises").readFile(path.join(ROOT_DIR, "deploy/trialrun/Dockerfile"), "utf8"); expect(dockerfile.indexOf("RUN apk add --no-cache bash curl")).toBeLessThan(dockerfile.indexOf("ARG VITE_BUILD_SHA")); expect(dockerfile.indexOf("RUN cd client && npm ci")).toBeLessThan(dockerfile.indexOf("ARG VITE_BUILD_SHA")); expect(dockerfile.indexOf("RUN cd server && npm ci")).toBeLessThan(dockerfile.indexOf("ARG BUILD_SHA")); }); it("keeps deployment smoke output free of raw account and external identifiers", async () => { const seed = await require("node:fs/promises").readFile(path.join(ROOT_DIR, "server/src/scripts/seed-trialrun.js"), "utf8"); const external = await require("node:fs/promises").readFile(path.join(ROOT_DIR, "server/src/scripts/smoke-external-deps.js"), "utf8"); const runtime = await require("node:fs/promises").readFile(path.join(ROOT_DIR, "server/src/scripts/smoke-trialrun-runtime.js"), "utf8"); expect(seed).not.toContain("${adminEmail}"); expect(seed).not.toContain("${adminPhone}"); expect(seed).not.toContain("${result.password}"); expect(seed).not.toContain("generateOneTimePassword"); expect(external).not.toContain("corpId=${config.wecomCorpId}"); expect(external).not.toContain("redirectUri=${config.wecomRedirectUri}"); expect(external).not.toContain("from=${config.emailFrom}"); expect(runtime).not.toContain("${adminEmployee.employee_no}"); }); it("keeps the formal payment batch baseline enabled and restores QA caller state", async () => { const envExample = await require("node:fs/promises").readFile(path.join(ROOT_DIR, "deploy/trialrun/.env.example"), "utf8"); const runtime = await require("node:fs/promises").readFile(path.join(ROOT_DIR, "server/src/scripts/smoke-trialrun-runtime.js"), "utf8"); const shortWindow = await require("node:fs/promises").readFile(path.join(ROOT_DIR, "scripts/qa/run-p2-fin-live-window.sh"), "utf8"); const enableWindow = await require("node:fs/promises").readFile(path.join(ROOT_DIR, "scripts/qa/run-fin-prod-enable-window.sh"), "utf8"); const liveSpec = await require("node:fs/promises").readFile(path.join(ROOT_DIR, "client/tests/e2e/manual/p2-fin-live-payment-batch.spec.ts"), "utf8"); expect(envExample).toMatch(/^PAYMENT_BATCH_ENABLED=true$/m); expect(runtime).toContain("PAYMENT_BATCH_ENABLED: 'true'"); expect(runtime).toContain("FEATURE_FLAG_KEYS.paymentBatch"); expect(shortWindow).toContain("restore-caller-flag-snapshot"); expect(shortWindow).toContain("P2_FIN_LIVE_ALREADY_ON='$ALREADY_ON_MODE'"); expect(enableWindow).toContain("restore-caller-flag-snapshot"); expect(liveSpec).toContain("restoreFlagSnapshot"); expect(liveSpec).not.toContain("forcePaymentBatchOff"); expect(shortWindow).not.toContain("force_payment_batch_flag_off"); expect(enableWindow).not.toContain("force_payment_batch_flag_off"); }); });