fix(build): derive the pack-boot CLI token against the smoke's DATA_DIR (#15147)
Some checks failed
Publish to Docker Hub / Resolve Docker release metadata (push) Has been cancelled
Release-Green (continuous) / Validate active release branch (push) Has been cancelled
Release-Green (continuous) / Validate main branch (push) Has been cancelled
Release-Green (continuous) / Bank ratchet shrinks (push) Has been cancelled
Release-Green (continuous) / Baseline headroom (push) Has been cancelled
Lock released branch / lock-branch (push) Has been cancelled
Lock released branch / guard-no-push-after-release (push) Has been cancelled
Release acceptance / Release acceptance (push) Has been cancelled
OpenSSF Scorecard / Scorecard analysis (push) Has been cancelled
Publish to Docker Hub / Build Docker (linux/amd64) (push) Has been cancelled
Publish to Docker Hub / Build Docker (linux/arm64) (push) Has been cancelled
Publish to Docker Hub / Publish multi-arch manifests (push) Has been cancelled

Release-captain fix (v3.8.51 release PR #11442, Package Artifact / dast-smoke): since #13909 the packaged CLI token salt lives in the instance DATA_DIR, but the pack-boot and install-upgrade smokes derived the token without it, so the server rejected the CLI and served the anonymous health view (no version). The smokes now pass their isolated DATA_DIR. New unit test red→green; end-to-end with the CI next-build artifact: version 3.8.51, whoami 200. No production code changed.
This commit is contained in:
Diego Rodrigues de Sa e Souza 2026-09-29 18:26:15 -03:00 • committed by GitHub
parent dfb563d5d9
commit 2f42a9ac19
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 47 additions and 7 deletions

View file

@ -76,7 +76,9 @@ const INTERNAL_SERVICE_HEADER = "x-omniroute-internal-service-token";
* packaged CLI. Sent alongside the internal-service token so a build that only honours one
* of the two still answers with the full payload.
*/
function derivePackagedCliToken(prefix) {
// The CLI token salt lives under <DATA_DIR> (#13679/#13909): derive against the DATA_DIR the
// probed server boots on, or the token never matches.
function derivePackagedCliToken(prefix, dataDir) {
const cliModuleUrl = pathToFileURL(
path.join(packageRootFor(prefix), "bin", "cli", "utils", "cliToken.mjs")
).href;
@ -89,7 +91,7 @@ function derivePackagedCliToken(prefix) {
"import(process.argv[1]).then(async m => process.stdout.write(await m.getCliToken()))",
cliModuleUrl,
],
{ encoding: "utf8", env: { ...process.env } }
{ encoding: "utf8", env: { ...process.env, DATA_DIR: dataDir } }
).trim();
} catch {
// A truncated/broken install cannot derive a token. Returning null keeps the boot
@ -176,7 +178,7 @@ async function bootAndProbe({ prefix, dataDir, port, expectVersion, label }) {
if (!fs.existsSync(binPath)) {
return { ok: false, failures: [`${label}: bin not found at ${binPath}`], tail: [] };
}
const cliToken = derivePackagedCliToken(prefix);
const cliToken = derivePackagedCliToken(prefix, dataDir);
const probeHeaders = {
[INTERNAL_SERVICE_HEADER]: INTERNAL_SERVICE_TOKEN,
...(cliToken ? { "x-omniroute-cli-token": cliToken } : {}),

View file

@ -311,7 +311,13 @@ function spawnServer(binPath, port, dataDir) {
return { child, tail };
}
function derivePackagedCliToken(packageRoot) {
/**
* Derive the loopback machine token exactly as the installed CLI would for this install.
* Since #13679/#13909 the token salt is per-install, persisted under <DATA_DIR>, so the
* derivation MUST see the same DATA_DIR the server boots on — otherwise the CLI resolves
* a different salt, the server rejects the token and health serves the anonymous view.
*/
export function derivePackagedCliToken(packageRoot, dataDir) {
const cliModuleUrl = pathToFileURL(
path.join(packageRoot, "bin", "cli", "utils", "cliToken.mjs")
).href;
@ -323,7 +329,7 @@ function derivePackagedCliToken(packageRoot) {
"import(process.argv[1]).then(async m => process.stdout.write(await m.getCliToken()))",
cliModuleUrl,
],
{ encoding: "utf8", env: { ...process.env } }
{ encoding: "utf8", env: { ...process.env, DATA_DIR: dataDir } }
).trim();
}
@ -454,7 +460,7 @@ async function main() {
const dataDir = path.join(tmp, "data");
fs.mkdirSync(dataDir, { recursive: true });
const binPath = path.join(prefix, "bin", "omniroute");
const packagedCliToken = derivePackagedCliToken(packageRoot);
const packagedCliToken = derivePackagedCliToken(packageRoot, dataDir);
// BOOT #1 — boot, prove the forced sql.js tier, PATCH a setting, then shut down cleanly
// so the sql.js adapter's graceful persist actually lands on disk. The in-flow stopChild

View file

@ -1,7 +1,8 @@
import { test } from "node:test";
import assert from "node:assert/strict";
import { createHmac } from "node:crypto";
import { readFileSync } from "node:fs";
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
import os from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import {
@ -15,6 +16,7 @@ import {
evaluateMachineTokenAuth,
evaluateSqlJsRoundTrip,
evaluateRestartPersistence,
derivePackagedCliToken,
} from "../../scripts/check/check-pack-boot.mjs";
// WS1.2 (T1, v3.8.49 quality plan) — pure-function guards for the tarball boot-smoke
@ -244,3 +246,33 @@ test("source guard: final shutdown only deletes the workspace after a CONFIRMED
"stopChild/waitForHealthy must read authoritative exit state, not a stale boolean"
);
});
// #13679/#13909 made the CLI token salt per-install, persisted under <DATA_DIR>. The
// smoke boots the server on an isolated DATA_DIR, so the token it sends must be derived
// against that SAME DATA_DIR — derived without it, the CLI resolves a different salt,
// the server rejects the token, and /api/monitoring/health answers the anonymous view
// ("version undefined", release PR #11442 Package Artifact).
test("derivePackagedCliToken derives the token against the server's DATA_DIR salt", () => {
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
const dataDir = mkdtempSync(path.join(os.tmpdir(), "pack-boot-cli-token-"));
const otherDataDir = mkdtempSync(path.join(os.tmpdir(), "pack-boot-cli-token-other-"));
const savedCliSalt = process.env.OMNIROUTE_CLI_SALT;
delete process.env.OMNIROUTE_CLI_SALT;
try {
const token = derivePackagedCliToken(repoRoot, dataDir);
assert.match(token, /^[0-9a-f]{64}$/);
assert.equal(
existsSync(path.join(dataDir, "cli-token-salt.json")),
true,
"the salt must be established inside the smoke's DATA_DIR"
);
// Stable for the same DATA_DIR, different for another install's DATA_DIR.
assert.equal(derivePackagedCliToken(repoRoot, dataDir), token);
assert.notEqual(derivePackagedCliToken(repoRoot, otherDataDir), token);
} finally {
if (savedCliSalt === undefined) delete process.env.OMNIROUTE_CLI_SALT;
else process.env.OMNIROUTE_CLI_SALT = savedCliSalt;
rmSync(dataDir, { recursive: true, force: true });
rmSync(otherDataDir, { recursive: true, force: true });
}
});