Files
goodbuddy/build/remote-runtime-bundle.cjs
T
mesalogo c8db340cc7 fix: prevent runtime permission stalls and Agent reconnect failures
Execute could stall on workspace-external access or native child-session
permissions, while structured questions could be lost or answered incorrectly.
Route owned OpenCode descendant interactions, correct Continue question and
custom-answer handling, and resolve DSH Execute ACP permissions without a
second approval. Ask remains read-only and unrelated sessions stay isolated.

Restore the required DSH session projection service. Reuse offline OpenCode
configuration by plugin version, remove unused npm shims from remote payloads,
normalize dependency modes, and accept real compound descriptors up to 4 MiB.
Fix intermittent Agent attach rejection and closed-handshake waits.

Add focused and real-Runtime regressions, document interaction boundaries and
validation evidence, and include the existing application/tool navigation
design drafts. Those navigation changes are design-only, not implemented UI.

Validation: full suite 3597 passed, 0 failed, 61 skipped across 338 files;
typecheck, lint, release-note verification, whitespace and relative-link checks
passed. Current-source Linux x64 installation, Ask/Execute, native subagent
external writes, reconnect and stop/bootstrap passed with 10 completed real
model calls, 13 native endpoint tests and 20 consecutive handshakes.
System sleep/wake and release CI packaging remain unverified.

Release note: 修复 Execute 访问工作区外目录或运行原生子代理时卡在权限等待的问题,并恢复 OpenCode 与 Continue 结构化问答的正确转交。修复远程 Agent 安装与重连失败;Ask 仍保持只读,任意终端密码或业务确认不会自动代答。
2026-09-08 11:34:45 +08:00

1070 lines
32 KiB
JavaScript

const { createHash, createPublicKey, sign, verify } = require("node:crypto");
const {
chmodSync,
closeSync,
cpSync,
copyFileSync,
existsSync,
lstatSync,
mkdirSync,
mkdtempSync,
openSync,
readFileSync,
readSync,
readdirSync,
renameSync,
rmSync,
statSync,
writeFileSync,
} = require("node:fs");
const { tmpdir } = require("node:os");
const {
basename,
dirname,
join,
posix,
relative,
resolve,
sep,
} = require("node:path");
const tar = require("tar");
const { targetName, assertTargetBinary } = require("./agent-build-target.cjs");
const {
preflightRegisteredProductionKey,
} = require("./signing-key-preflight.cjs");
const { prepareBundledOpenCodeConfig } = require("./opencode-config.cjs");
const root = join(__dirname, "..");
const supportedArchitectures = Object.freeze(["x64", "arm64"]);
const manifestFileName = "manifest.json";
const signatureFileName = "manifest.sig";
const signingPrivateKeyEnvironment = "GOODBUDDY_SIGNING_PRIVATE_KEY";
const signingKeyIdEnvironment = "GOODBUDDY_SIGNING_KEY_ID";
const signatureDomain = Buffer.from(
"GoodBuddy Remote Runtime Bundle Manifest Signature v1\0",
"utf8",
);
const profileDigests = Object.freeze({
adapter:
"sha256:ac7696abe504bbea444d8ad80dd8faa96437e6dbb27ed987ce46e1045f3dd365",
acp: "sha256:0e3764ab897258bc0234162357c2eefc3faeb9918080ae81b60e2084ed7996a6",
});
const fixedLimits = Object.freeze({
maximumPromptRuntimeMilliseconds: 10 * 60 * 1000,
maximumPromptInputBytes: 16 * 1024 * 1024,
maximumPromptOutputBytes: 8 * 1024 * 1024,
});
function readJson(filePath, description) {
try {
return JSON.parse(readFileSync(filePath, "utf8"));
} catch (error) {
throw new Error(
`${description} is missing or invalid: ${
error instanceof Error ? error.message : String(error)
}`,
{ cause: error },
);
}
}
function readRemoteRuntimeLock(projectRoot = root) {
const lock = readJson(
join(projectRoot, "remote-runtime-lock.json"),
"Remote Runtime lock",
);
const runtime = lock?.runtimes?.opencode;
if (
lock?.formatVersion !== 1 ||
runtime?.version !== "1.18.29" ||
runtime.provider !== "opencode" ||
runtime.entrypoint !== "bin/opencode" ||
runtime.entrypointIdentity !== "opencode-acp" ||
JSON.stringify(runtime.argvPrefix) !== JSON.stringify(["acp"]) ||
!Number.isSafeInteger(runtime.protocol?.major) ||
!Number.isSafeInteger(runtime.protocol?.minor)
) {
throw new Error("Remote Runtime lock contract is invalid");
}
for (const architecture of supportedArchitectures) {
const target = runtime.targets?.[architecture];
if (
typeof target?.package !== "string" ||
typeof target.integrity !== "string" ||
!/^sha512-[A-Za-z0-9+/]{86}==$/u.test(target.integrity)
) {
throw new Error(`Remote Runtime lock target is invalid: ${architecture}`);
}
}
return lock;
}
function readTrustedKeyRegistry(projectRoot = root) {
const registry = readJson(
join(projectRoot, "resources", "agent-release-keys.json"),
"Runtime trusted key registry",
);
if (
registry?.formatVersion !== 1 ||
!Array.isArray(registry.keys) ||
!Array.isArray(registry.revocations)
) {
throw new Error("Runtime trusted key registry contract is invalid");
}
const keyIds = new Set();
for (const key of registry.keys) {
if (
typeof key?.keyId !== "string" ||
!/^[a-z0-9][a-z0-9._-]{0,63}$/u.test(key.keyId) ||
keyIds.has(key.keyId) ||
typeof key.publicKeySpkiBase64 !== "string" ||
!["production", "test"].includes(key.environment)
) {
throw new Error("Runtime trusted key registry entry is invalid");
}
const publicKey = createPublicKey({
key: Buffer.from(key.publicKeySpkiBase64, "base64"),
format: "der",
type: "spki",
});
if (publicKey.asymmetricKeyType !== "ed25519") {
throw new Error(`Runtime trusted key is not Ed25519: ${key.keyId}`);
}
keyIds.add(key.keyId);
}
return registry;
}
function sha256(contents) {
return createHash("sha256").update(contents).digest("hex");
}
function sha512FileIntegrity(filePath) {
const hash = createHash("sha512");
const descriptor = openSync(filePath, "r");
const chunk = Buffer.allocUnsafe(1024 * 1024);
try {
while (true) {
const bytesRead = readSync(descriptor, chunk, 0, chunk.byteLength, null);
if (bytesRead === 0) {
break;
}
hash.update(chunk.subarray(0, bytesRead));
}
} finally {
closeSync(descriptor);
}
return `sha512-${hash.digest("base64")}`;
}
function sha256FileSync(filePath) {
return sha256(readFileSync(filePath));
}
function canonicalJson(value) {
if (
value === null ||
typeof value === "boolean" ||
typeof value === "string"
) {
return JSON.stringify(value);
}
if (typeof value === "number") {
if (!Number.isFinite(value)) {
throw new Error("Canonical Runtime value is not finite");
}
return JSON.stringify(Object.is(value, -0) ? 0 : value);
}
if (Array.isArray(value)) {
return `[${value.map(canonicalJson).join(",")}]`;
}
if (
typeof value !== "object" ||
Object.getPrototypeOf(value) !== Object.prototype
) {
throw new Error("Canonical Runtime value is not plain JSON");
}
return `{${Object.keys(value)
.sort()
.map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`)
.join(",")}}`;
}
function digestCanonicalOperation({ method, scope, payload }) {
return `sha256:${sha256(
Buffer.from(canonicalJson({ method, payload, scope }), "utf8"),
)}`;
}
function digestRuntimeBundleIdentity(manifest) {
const { bundleDigest: _bundleDigest, ...identity } = manifest;
void _bundleDigest;
return digestCanonicalOperation({
method: "runtime/bundleIdentity",
scope: {
kind: "installation",
installationId: manifest.runtimeId,
},
payload: identity,
});
}
function digestRuntimeBundleManifest(manifest) {
return digestCanonicalOperation({
method: "runtime/bundleManifest",
scope: {
kind: "installation",
installationId: manifest.runtimeId,
},
payload: manifest,
});
}
function canonicalManifestBytes(manifest) {
return Buffer.from(`${JSON.stringify(manifest, null, 2)}\n`, "utf8");
}
function signaturePayload(manifestBytes) {
return Buffer.concat([signatureDomain, manifestBytes]);
}
function publicKeySpkiBase64(key) {
return createPublicKey(key)
.export({ format: "der", type: "spki" })
.toString("base64");
}
function productionSigningIdentity(environment = process.env) {
const keyId = environment[signingKeyIdEnvironment];
const privateKey = environment[signingPrivateKeyEnvironment];
if (!keyId || !privateKey) {
throw new Error(
`${signingKeyIdEnvironment} and ${signingPrivateKeyEnvironment} are required to sign the bundled Runtime`,
);
}
return { keyId, privateKey };
}
function trustedKeyForSigning(
signingIdentity,
registry,
verificationEnvironment,
) {
const record = registry.keys.find(
(key) => key.keyId === signingIdentity.keyId,
);
if (!record) {
throw new Error(
`Runtime signing key is not registered: ${signingIdentity.keyId}`,
);
}
if (
verificationEnvironment === "production" &&
record.environment !== "production"
) {
throw new Error(
`Runtime signing key is not registered for production: ${record.keyId}`,
);
}
if (
registry.revocations.some((revocation) => revocation.keyId === record.keyId)
) {
throw new Error("Runtime signing key is outside its trusted interval");
}
if (
publicKeySpkiBase64(signingIdentity.privateKey) !==
record.publicKeySpkiBase64
) {
throw new Error(
"Runtime signing private key does not match the trusted registry",
);
}
return record;
}
function preflightProductionSigningKey(options = {}) {
const projectRoot = options.projectRoot ?? root;
const environment = options.environment ?? process.env;
const keyId = options.keyId ?? environment[signingKeyIdEnvironment];
const registry = options.registry ?? readTrustedKeyRegistry(projectRoot);
return preflightRegisteredProductionKey({
component: "GoodBuddy",
keyId,
registry,
missingKeyIdMessage: `${signingKeyIdEnvironment} is not configured; provision the production GoodBuddy signing key ID before building a release`,
});
}
function assertSafeManifestPath(filePath) {
if (
typeof filePath !== "string" ||
filePath.length === 0 ||
filePath.length > 240 ||
filePath.includes("\\") ||
filePath.includes("\0") ||
posix.isAbsolute(filePath) ||
filePath
.split("/")
.some((part) => part.length === 0 || part === "." || part === "..")
) {
throw new Error(`Unsafe Runtime manifest path: ${String(filePath)}`);
}
}
function compareUtf8(left, right) {
return Buffer.compare(Buffer.from(left, "utf8"), Buffer.from(right, "utf8"));
}
function listFiles(directory) {
const files = [];
const pending = [directory];
while (pending.length > 0) {
const current = pending.pop();
const entries = readdirSync(current, {
withFileTypes: true,
}).sort((left, right) => compareUtf8(right.name, left.name));
for (const entry of entries) {
const absolutePath = join(current, entry.name);
if (entry.isSymbolicLink()) {
throw new Error(
`Runtime bundle cannot contain a symlink: ${absolutePath}`,
);
}
if (entry.isDirectory()) {
pending.push(absolutePath);
} else if (entry.isFile()) {
files.push(absolutePath);
} else {
throw new Error(
`Runtime bundle contains an unsupported file: ${absolutePath}`,
);
}
}
}
return files.sort(compareUtf8);
}
function posixRelative(directory, filePath) {
return relative(directory, filePath).split(sep).join("/");
}
function modeString(filePath) {
return (statSync(filePath).mode & 0o777).toString(8).padStart(4, "0");
}
function assertElfArchitecture(
filePath,
expectedArchitecture,
platform = "linux",
) {
assertTargetBinary(filePath, expectedArchitecture, platform, "Runtime");
}
function validateManifestShape(manifest) {
if (
manifest?.formatVersion !== 2 ||
manifest.product !== "GoodBuddy" ||
manifest.runtimeId !== "opencode" ||
manifest.runtimeVersion !== "1.18.29" ||
manifest.provider !== "opencode" ||
!(
manifest.platform === "linux" ||
(manifest.platform === "darwin" && manifest.architecture === "arm64")
) ||
!supportedArchitectures.includes(manifest.architecture) ||
typeof manifest.signingKeyId !== "string" ||
!/^sha256:[a-f0-9]{64}$/u.test(manifest.bundleDigest) ||
!/^sha256:[a-f0-9]{64}$/u.test(manifest.adapterDigest) ||
!/^sha256:[a-f0-9]{64}$/u.test(manifest.acpCapabilitiesDigest) ||
!Array.isArray(manifest.files) ||
!Array.isArray(manifest.licenses) ||
!Array.isArray(manifest.allowedEnvironmentNames)
) {
throw new Error("Runtime manifest contract is invalid");
}
if (
!Number.isSafeInteger(manifest.limits?.maximumPromptRuntimeMilliseconds) ||
manifest.limits.maximumPromptRuntimeMilliseconds < 1 ||
!Number.isSafeInteger(manifest.limits.maximumPromptInputBytes) ||
manifest.limits.maximumPromptInputBytes < 1 ||
!Number.isSafeInteger(manifest.limits.maximumPromptOutputBytes) ||
manifest.limits.maximumPromptOutputBytes < 0 ||
Object.keys(manifest.limits).length !== 3 ||
"quotas" in manifest
) {
throw new Error("Runtime manifest limits contract is invalid");
}
if (
manifest.entrypoint?.identity !== "opencode-acp" ||
manifest.entrypoint.path !== "bin/opencode" ||
!/^[a-f0-9]{64}$/u.test(manifest.entrypoint.sha256) ||
JSON.stringify(manifest.entrypoint.argvPrefix) !== JSON.stringify(["acp"])
) {
throw new Error("Runtime manifest entrypoint is invalid");
}
}
function trustedKeyForManifest(manifest, registry, verificationEnvironment) {
const key = registry.keys.find(
(candidate) => candidate.keyId === manifest.signingKeyId,
);
if (!key) {
throw new Error(
`Runtime manifest uses an unknown signing key: ${manifest.signingKeyId}`,
);
}
if (
verificationEnvironment === "production" &&
key.environment !== "production"
) {
throw new Error(
`Production Runtime verification rejects non-production key: ${key.keyId}`,
);
}
if (
registry.revocations.some((revocation) => revocation.keyId === key.keyId)
) {
throw new Error("Runtime signing key is outside its trusted interval");
}
return key;
}
function assertManifestMatchesLock(
manifest,
lock,
architecture,
platform = "linux",
) {
const expected = lock.runtimes.opencode;
const target =
expected.targets[
platform === "linux" ? architecture : targetName(architecture, platform)
];
if (
manifest.runtimeId !== "opencode" ||
manifest.runtimeVersion !== expected.version ||
manifest.provider !== expected.provider ||
manifest.platform !== platform ||
manifest.architecture !== architecture ||
manifest.sourcePackage?.name !== target.package ||
manifest.sourcePackage.integrity !== target.integrity ||
manifest.entrypoint.path !== expected.entrypoint ||
manifest.entrypoint.identity !== expected.entrypointIdentity ||
JSON.stringify(manifest.entrypoint.argvPrefix) !==
JSON.stringify(expected.argvPrefix) ||
JSON.stringify(manifest.allowedEnvironmentNames) !==
JSON.stringify(expected.allowedEnvironmentNames) ||
manifest.protocol?.major !== expected.protocol.major ||
manifest.protocol?.minor !== expected.protocol.minor ||
manifest.adapterDigest !== profileDigests.adapter ||
manifest.acpCapabilitiesDigest !== profileDigests.acp
) {
throw new Error(
"Runtime manifest does not match the locked OpenCode profile",
);
}
}
function verifyBundleDirectory(bundleDirectoryInput, options = {}) {
const bundleDirectory = resolve(bundleDirectoryInput);
const projectRoot = options.projectRoot ?? root;
const lock = options.lock ?? readRemoteRuntimeLock(projectRoot);
const registry = options.registry ?? readTrustedKeyRegistry(projectRoot);
const architecture = options.architecture;
const platform = options.platform ?? "linux";
targetName(architecture, platform);
const manifestBytes = readFileSync(join(bundleDirectory, manifestFileName));
const signatureText = readFileSync(
join(bundleDirectory, signatureFileName),
"utf8",
);
if (!/^[A-Za-z0-9+/]{86}==\n$/u.test(signatureText)) {
throw new Error("Runtime detached signature encoding is invalid");
}
const manifest = JSON.parse(manifestBytes.toString("utf8"));
validateManifestShape(manifest);
if (!canonicalManifestBytes(manifest).equals(manifestBytes)) {
throw new Error("Runtime manifest is not in canonical deterministic form");
}
assertManifestMatchesLock(manifest, lock, architecture, platform);
const environment = options.verificationEnvironment ?? "production";
const key = trustedKeyForManifest(manifest, registry, environment);
const publicKey = createPublicKey({
key: Buffer.from(key.publicKeySpkiBase64, "base64"),
format: "der",
type: "spki",
});
const signatureBytes = Buffer.from(signatureText.trim(), "base64");
if (
signatureBytes.length !== 64 ||
!verify(null, signaturePayload(manifestBytes), publicKey, signatureBytes)
) {
throw new Error("Runtime manifest signature verification failed");
}
if (digestRuntimeBundleIdentity(manifest) !== manifest.bundleDigest) {
throw new Error("Runtime bundle identity digest does not match");
}
if (
options.requireDigestDirectory !== false &&
basename(bundleDirectory) !== manifest.bundleDigest.slice("sha256:".length)
) {
throw new Error(
"Runtime bundle digest does not match its managed directory",
);
}
const declared = new Set();
for (const file of manifest.files) {
assertSafeManifestPath(file.path);
if (
declared.has(file.path) ||
!Number.isSafeInteger(file.size) ||
file.size < 0 ||
!/^[a-f0-9]{64}$/u.test(file.sha256) ||
!["0644", "0755"].includes(file.mode)
) {
throw new Error(`Runtime manifest file entry is invalid: ${file.path}`);
}
declared.add(file.path);
const filePath = join(bundleDirectory, ...file.path.split("/"));
const stat = lstatSync(filePath);
if (!stat.isFile() || stat.isSymbolicLink()) {
throw new Error(`Runtime payload is not a regular file: ${file.path}`);
}
if (stat.size !== file.size) {
throw new Error(`Runtime payload size mismatch: ${file.path}`);
}
if (sha256FileSync(filePath) !== file.sha256) {
throw new Error(`Runtime payload hash mismatch: ${file.path}`);
}
if (
options.enforceFilesystemMode !== false &&
process.platform !== "win32" &&
modeString(filePath) !== file.mode
) {
throw new Error(`Runtime payload mode mismatch: ${file.path}`);
}
}
const actual = new Set(
listFiles(bundleDirectory).map((filePath) =>
posixRelative(bundleDirectory, filePath),
),
);
const expected = new Set([...declared, manifestFileName, signatureFileName]);
if (
actual.size !== expected.size ||
[...actual].some((filePath) => !expected.has(filePath))
) {
throw new Error("Runtime bundle contains undeclared or missing files");
}
for (const license of manifest.licenses) {
assertSafeManifestPath(license.path);
if (!declared.has(license.path)) {
throw new Error("Runtime manifest license is not declared");
}
}
if (
!declared.has(manifest.entrypoint.path) ||
manifest.entrypoint.sha256 !==
manifest.files.find((file) => file.path === manifest.entrypoint.path)
?.sha256
) {
throw new Error("Runtime entrypoint payload is missing");
}
assertElfArchitecture(
join(bundleDirectory, ...manifest.entrypoint.path.split("/")),
architecture,
platform,
);
return {
bundleDirectory,
manifest,
manifestDigest: digestRuntimeBundleManifest(manifest),
};
}
function lockedArchive(lock, architecture, archivePath, platform = "linux") {
const input = resolveLockedRuntimeInput(lock, architecture, platform);
if (!archivePath || !existsSync(archivePath)) {
throw new Error(`Locked OpenCode archive is required: ${input.archive}`);
}
if (!statSync(archivePath).isFile()) {
throw new Error(`Runtime archive is not a file: ${archivePath}`);
}
if (basename(archivePath) !== input.archive) {
throw new Error(
`Runtime archive filename mismatch: expected ${input.archive}`,
);
}
const actualIntegrity = sha512FileIntegrity(archivePath);
if (actualIntegrity !== input.integrity) {
throw new Error(
`Runtime archive integrity mismatch for ${targetName(architecture)}`,
);
}
return lock.runtimes.opencode.targets[
platform === "linux" ? architecture : targetName(architecture, platform)
];
}
function resolveLockedRuntimeInput(lock, architecture, platform = "linux") {
targetName(architecture, platform);
const runtime = lock.runtimes.opencode;
const target =
runtime.targets[
platform === "linux" ? architecture : targetName(architecture, platform)
];
return {
packageName: target.package,
version: runtime.version,
integrity: target.integrity,
archive: `${target.package}-${runtime.version}.tgz`,
};
}
function createManifest(bundleDirectory, metadata) {
const files = listFiles(bundleDirectory)
.filter((filePath) => {
const name = posixRelative(bundleDirectory, filePath);
return name !== manifestFileName && name !== signatureFileName;
})
.map((filePath) => {
const path = posixRelative(bundleDirectory, filePath);
assertSafeManifestPath(path);
return {
path,
size: statSync(filePath).size,
sha256: sha256FileSync(filePath),
mode: path === "bin/opencode" ? "0755" : "0644",
};
});
const entrypoint = files.find((file) => file.path === "bin/opencode");
if (!entrypoint) {
throw new Error("Runtime entrypoint is missing");
}
const initial = {
formatVersion: 2,
product: "GoodBuddy",
runtimeId: "opencode",
runtimeVersion: metadata.runtime.version,
provider: metadata.runtime.provider,
platform: metadata.platform ?? "linux",
architecture: metadata.architecture,
signingKeyId: metadata.signingKeyId,
bundleDigest: `sha256:${"0".repeat(64)}`,
adapterDigest: profileDigests.adapter,
sourcePackage: metadata.sourcePackage,
entrypoint: {
identity: metadata.runtime.entrypointIdentity,
path: metadata.runtime.entrypoint,
sha256: entrypoint.sha256,
argvPrefix: metadata.runtime.argvPrefix,
},
files,
licenses: [
{
package: "opencode-ai",
version: metadata.runtime.version,
spdx: "MIT",
path: "licenses/opencode-MIT.txt",
},
],
allowedEnvironmentNames: metadata.runtime.allowedEnvironmentNames,
protocol: metadata.runtime.protocol,
acpCapabilitiesDigest: profileDigests.acp,
limits: fixedLimits,
};
return {
...initial,
bundleDigest: digestRuntimeBundleIdentity(initial),
};
}
function defaultOutputRoot(projectRoot = root) {
return join(projectRoot, ".remote-runtime-resources");
}
function bundleDirectory(outputRoot, architecture, digest, platform = "linux") {
return join(
outputRoot,
targetName(architecture, platform),
"opencode",
digest.slice("sha256:".length),
);
}
function buildRuntimeBundle(options) {
const projectRoot = options.projectRoot ?? root;
const architecture = options.architecture;
const platform = options.platform ?? "linux";
const lock = options.lock ?? readRemoteRuntimeLock(projectRoot);
const runtime = lock.runtimes.opencode;
const sourcePackage = lockedArchive(
lock,
architecture,
options.runtimeArchive,
platform,
);
const registry = options.registry ?? readTrustedKeyRegistry(projectRoot);
const signingIdentity =
options.testSigningIdentity ??
options.signingIdentity ??
productionSigningIdentity(options.environment ?? process.env);
const verificationEnvironment = options.testSigningIdentity
? "test"
: "production";
trustedKeyForSigning(signingIdentity, registry, verificationEnvironment);
const outputRoot = options.outputRoot ?? defaultOutputRoot(projectRoot);
mkdirSync(outputRoot, { recursive: true });
const staging = mkdtempSync(
join(outputRoot, `.stage-${targetName(architecture)}-`),
);
const extracted = mkdtempSync(
join(tmpdir(), `goodbuddy-opencode-${targetName(architecture)}-`),
);
try {
tar.x({
file: options.runtimeArchive,
cwd: extracted,
sync: true,
strict: true,
filter(path) {
return (
path === "package/package.json" || path === "package/bin/opencode"
);
},
});
const sourceMetadata = readJson(
join(extracted, "package", "package.json"),
"OpenCode source package metadata",
);
if (
sourceMetadata.name !== sourcePackage.package &&
sourceMetadata.name !== sourcePackage.name
) {
// The lock target itself carries the canonical package name.
if (sourceMetadata.name !== sourcePackage.package) {
throw new Error("OpenCode source package name does not match the lock");
}
}
if (sourceMetadata.version !== runtime.version) {
throw new Error(
"OpenCode source package version does not match the lock",
);
}
mkdirSync(join(staging, "bin"), { mode: 0o700 });
copyFileSync(
join(extracted, "package", "bin", "opencode"),
join(staging, "bin", "opencode"),
);
chmodSync(join(staging, "bin", "opencode"), 0o755);
assertElfArchitecture(
join(staging, "bin", "opencode"),
architecture,
platform,
);
const configTemplate = prepareBundledOpenCodeConfig(projectRoot);
const configDestination = join(staging, "config", "opencode");
cpSync(configTemplate, configDestination, {
recursive: true,
// npm CLI shims are not used by the imported plugin and may be symlinks.
filter: (source) => basename(source) !== ".bin",
});
for (const file of listFiles(configDestination)) {
chmodSync(file, 0o644);
}
mkdirSync(join(staging, "licenses"), { mode: 0o700 });
copyFileSync(
join(projectRoot, "node_modules", "opencode-ai", "LICENSE"),
join(staging, "licenses", "opencode-MIT.txt"),
);
chmodSync(join(staging, "licenses", "opencode-MIT.txt"), 0o644);
const manifest = createManifest(staging, {
platform,
architecture,
runtime,
sourcePackage: {
name: sourcePackage.package,
integrity: sourcePackage.integrity,
},
signingKeyId: signingIdentity.keyId,
});
const manifestBytes = canonicalManifestBytes(manifest);
const signatureBytes = sign(
null,
signaturePayload(manifestBytes),
signingIdentity.privateKey,
);
writeFileSync(join(staging, manifestFileName), manifestBytes, {
mode: 0o644,
});
writeFileSync(
join(staging, signatureFileName),
`${signatureBytes.toString("base64")}\n`,
{ mode: 0o644 },
);
chmodSync(join(staging, manifestFileName), 0o644);
chmodSync(join(staging, signatureFileName), 0o644);
const destination = bundleDirectory(
outputRoot,
architecture,
manifest.bundleDigest,
platform,
);
mkdirSync(dirname(destination), { recursive: true, mode: 0o700 });
if (existsSync(destination)) {
const existing = verifyBundleDirectory(destination, {
platform,
projectRoot,
architecture,
lock,
registry,
verificationEnvironment,
enforceFilesystemMode: options.enforceFilesystemMode,
});
if (canonicalJson(existing.manifest) !== canonicalJson(manifest)) {
throw new Error(
"Existing Runtime digest directory has different content",
);
}
return existing;
}
chmodSync(staging, 0o700);
renameSync(staging, destination);
return verifyBundleDirectory(destination, {
platform,
projectRoot,
architecture,
lock,
registry,
verificationEnvironment,
enforceFilesystemMode: options.enforceFilesystemMode,
});
} finally {
rmSync(staging, { recursive: true, force: true });
rmSync(extracted, { recursive: true, force: true });
}
}
function createRuntimeArchive(bundleDirectoryInput, archivePath) {
const directory = resolve(bundleDirectoryInput);
const entries = listFiles(directory)
.map((filePath) => posixRelative(directory, filePath))
.sort(compareUtf8);
mkdirSync(dirname(archivePath), { recursive: true });
rmSync(archivePath, { force: true });
tar.c(
{
cwd: directory,
file: archivePath,
sync: true,
portable: true,
noPax: true,
mtime: new Date(0),
},
entries,
);
}
function importRuntimeArchive(archivePath, options) {
if (!existsSync(archivePath)) {
throw new Error(`Runtime artifact archive is missing: ${archivePath}`);
}
const projectRoot = options.projectRoot ?? root;
const architecture = options.architecture;
const outputRoot = options.outputRoot ?? defaultOutputRoot(projectRoot);
mkdirSync(outputRoot, { recursive: true });
const staging = mkdtempSync(
join(outputRoot, `.import-${targetName(architecture)}-`),
);
try {
tar.x({
cwd: staging,
file: archivePath,
sync: true,
strict: true,
preservePaths: false,
});
const verified = verifyBundleDirectory(staging, {
...options,
projectRoot,
architecture,
requireDigestDirectory: false,
});
const destination = bundleDirectory(
outputRoot,
architecture,
verified.manifest.bundleDigest,
);
mkdirSync(dirname(destination), { recursive: true, mode: 0o700 });
if (existsSync(destination)) {
return verifyBundleDirectory(destination, {
...options,
projectRoot,
architecture,
});
}
chmodSync(staging, 0o700);
renameSync(staging, destination);
return verifyBundleDirectory(destination, {
...options,
projectRoot,
architecture,
});
} finally {
rmSync(staging, { recursive: true, force: true });
}
}
function findOnlyBundle(outputRoot, architecture) {
const runtimeRoot = join(outputRoot, targetName(architecture), "opencode");
const entries = existsSync(runtimeRoot)
? readdirSync(runtimeRoot, { withFileTypes: true })
.filter((entry) => entry.isDirectory())
.map((entry) => join(runtimeRoot, entry.name))
: [];
if (entries.length !== 1) {
throw new Error(
`Expected exactly one built Runtime bundle for ${targetName(architecture)}`,
);
}
return entries[0];
}
function redactSecrets(value, environment = process.env) {
let output = String(value);
for (const secret of [
environment[signingPrivateKeyEnvironment],
environment[signingKeyIdEnvironment],
]) {
if (secret && secret.length >= 4) {
output = output.split(secret).join("[redacted]");
}
}
return output.replace(
/-----BEGIN PRIVATE KEY-----[\s\S]*?-----END PRIVATE KEY-----/gu,
"[redacted private key]",
);
}
function parseArguments(argv) {
const command = argv[0];
const options = {};
const allowed = new Set([
"--arch",
"--runtime-archive",
"--archive",
"--output-root",
"--bundle",
]);
for (let index = 1; index < argv.length; index += 2) {
const flag = argv[index];
const value = argv[index + 1];
if (!allowed.has(flag) || !value) {
throw new Error("Invalid Remote Runtime bundle argument");
}
options[
flag
.slice(2)
.replace(/-([a-z])/gu, (_match, value) => value.toUpperCase())
] = value;
}
if (!["build", "import", "verify", "preflight"].includes(command)) {
throw new Error(
"Usage: remote-runtime-bundle.cjs <build|import|verify|preflight> --arch <x64|arm64>",
);
}
if (command === "preflight") {
return { command };
}
targetName(options.arch);
return { command, ...options };
}
function main(argv = process.argv.slice(2)) {
const options = parseArguments(argv);
if (options.command === "preflight") {
const record = preflightProductionSigningKey();
console.log(
`Production GoodBuddy signing preflight passed for bundled Runtime: ${record.keyId}`,
);
return;
}
const outputRoot = options.outputRoot
? resolve(options.outputRoot)
: defaultOutputRoot();
if (options.command === "build") {
const verified = buildRuntimeBundle({
architecture: options.arch,
runtimeArchive: resolve(options.runtimeArchive ?? ""),
outputRoot,
});
const archivePath = options.archive
? resolve(options.archive)
: join(
root,
"dist",
"remote-runtime-bundles",
`goodbuddy-opencode-${targetName(options.arch)}.tar`,
);
createRuntimeArchive(verified.bundleDirectory, archivePath);
console.log(
`Remote Runtime bundle built and verified: ${targetName(options.arch)}`,
);
return;
}
if (options.command === "import") {
importRuntimeArchive(resolve(options.archive ?? ""), {
architecture: options.arch,
outputRoot,
});
console.log(
`Remote Runtime bundle imported and verified: ${targetName(options.arch)}`,
);
return;
}
verifyBundleDirectory(
options.bundle
? resolve(options.bundle)
: findOnlyBundle(outputRoot, options.arch),
{ architecture: options.arch },
);
console.log(`Remote Runtime bundle verified: ${targetName(options.arch)}`);
}
module.exports = {
buildRuntimeBundle,
bundleDirectory,
canonicalJson,
canonicalManifestBytes,
createManifest,
createRuntimeArchive,
defaultOutputRoot,
digestRuntimeBundleIdentity,
digestRuntimeBundleManifest,
fixedLimits,
importRuntimeArchive,
preflightProductionSigningKey,
profileDigests,
publicKeySpkiBase64,
readRemoteRuntimeLock,
readTrustedKeyRegistry,
redactSecrets,
resolveLockedRuntimeInput,
signaturePayload,
supportedArchitectures,
targetName,
verifyBundleDirectory,
};
if (require.main === module) {
try {
main();
} catch (error) {
console.error(
redactSecrets(error instanceof Error ? error.message : String(error)),
);
process.exitCode = 1;
}
}