/** Offline operator-only issuer proposal. Never imported by runtime/startup. * Effective key/registry ACL isolation is required before deployment acceptance; * mode bits and possession of CLI arguments do not establish that isolation. */ import { createPrivateKey, createPublicKey, sign } from "node:crypto" import { mkdir, open, realpath } from "node:fs/promises" import path from "node:path" import { z } from "zod" import { DATABASE_SOURCE_SIGNATURE_DOMAINS, sourceBindingBodySchema, sourceBindingBytes, sourceBindingCanonical, sourceBindingSha256, readDatabaseSourceBindingRegistry, type DatabaseSourceDeploymentPin } from "../src/db/database-source-binding.js" const requestSchema = sourceBindingBodySchema.omit({ format: true, ordinal: true }) export type DatabaseSourceOperatorRequest = z.infer function outside(parent: string, child: string) { const relative = path.relative(parent, child) return !!relative && (relative.startsWith(".." + path.sep) || relative === ".." || path.isAbsolute(relative)) } export async function provisionDatabaseSourceBindingOffline(options: { request: DatabaseSourceOperatorRequest; privateKeyFile: string; outputDirectory: string; previousPin?: DatabaseSourceDeploymentPin }) { const request = requestSchema.parse(options.request) const privatePath = await realpath(options.privateKeyFile), output = path.resolve(options.outputDirectory) const parent = await realpath(path.dirname(output)) if (parent !== path.dirname(output) || !outside(output, privatePath)) throw Error("Private operator key must be outside new registry, without ambiguous parent links") const stat = await open(privatePath, "r") let privateBytes: Buffer try { const meta = await stat.stat(); if (!meta.isFile() || meta.size < 1 || meta.size > 8192) throw Error("Bounded operator private key required"); privateBytes = await stat.readFile() } finally { await stat.close() } const privateKey = createPrivateKey(privateBytes); privateBytes.fill(0) if (privateKey.type !== "private" || privateKey.asymmetricKeyType !== "ed25519") throw Error("Independent Ed25519 operator key required") const publicKey = createPublicKey(privateKey), spki = publicKey.export({ type: "spki", format: "der" }) const publicKeySpkiSha256 = sourceBindingSha256(spki) const previous = options.previousPin ? await readDatabaseSourceBindingRegistry(options.previousPin) : undefined if (previous && (previous.body.installationId !== request.installationId || previous.body.sourceIdentityId !== request.sourceIdentityId || previous.publicKeySpkiSha256 !== publicKeySpkiSha256 || previous.body.generation === request.generation || previous.body.ordinal >= Number.MAX_SAFE_INTEGER)) throw Error("Previous current head/identity/key or distinct new generation required") const body = sourceBindingBodySchema.parse({ ...request, format: "database-source-binding-v1", ordinal: previous ? previous.body.ordinal + 1 : 1 }) const signed = (domain: string, payload: unknown) => sourceBindingBytes({ body: payload, signature: sign(null, Buffer.from(domain + sourceBindingCanonical(payload)), privateKey).toString("base64url") }) const bindingBytes = signed(DATABASE_SOURCE_SIGNATURE_DOMAINS.binding, body), bindingSha256 = sourceBindingSha256(bindingBytes) const head = { format: "database-source-registry-head-v1", installationId: body.installationId, sourceIdentityId: body.sourceIdentityId, generation: body.generation, ordinal: body.ordinal, bindingSha256, previousHeadSha256: previous?.headSha256 ?? null } const headBytes = signed(DATABASE_SOURCE_SIGNATURE_DOMAINS.head, head), currentHeadSha256 = sourceBindingSha256(headBytes) // No recursive mkdir and no existing-state adoption. A partial output remains // for explicit operator review; uncertainty is never retried/overwritten. await mkdir(output, { mode: 0o700 }) const publish = async (filename: string, bytes: Buffer | string) => { const handle = await open(path.join(output, filename), "wx", 0o600) try { await handle.writeFile(bytes); await handle.sync() } finally { await handle.close() } } await publish("operator-public.pem", publicKey.export({ type: "spki", format: "pem" })) await publish("binding-" + bindingSha256 + ".json", bindingBytes) await publish("head-" + currentHeadSha256 + ".json", headBytes) const deploymentPin = { registryDirectory: output, installationId: body.installationId, publicKeySpkiSha256, currentHeadSha256 } // Public review artifact only; not installed into any application config. await publish("proposed-deployment-pin.json", sourceBindingBytes(deploymentPin)) return Object.freeze({ deploymentPin: Object.freeze(deploymentPin), keyIsolationVerified: false as const, platformProtectionVerified: false as const, generationAuthenticated: false as const, readyAuthorized: false as const }) } export async function databaseSourceBindingOperatorCli(args: string[]) { const allowed = new Set(["request", "private-key", "output", "previous-pin"]), values = new Map() for (const arg of args) { const match = /^--([a-z-]+)=(.+)$/.exec(arg) if (!match || !allowed.has(match[1]) || values.has(match[1])) throw Error("Exact explicit offline operator arguments required") values.set(match[1], match[2]) } if (!["request", "private-key", "output"].every(key => values.has(key))) throw Error("Missing explicit offline operator arguments") const boundedJson = async (filename: string) => { const handle = await open(filename, "r") try { const stat = await handle.stat(); if (!stat.isFile() || stat.size < 1 || stat.size > 8192) throw Error("Bounded operator input required"); return JSON.parse(await handle.readFile("utf8")) as unknown } finally { await handle.close() } } const request = requestSchema.parse(await boundedJson(values.get("request")!)) const previousPin = values.has("previous-pin") ? await boundedJson(values.get("previous-pin")!) as DatabaseSourceDeploymentPin : undefined return provisionDatabaseSourceBindingOffline({ request, privateKeyFile: values.get("private-key")!, outputDirectory: values.get("output")!, previousPin }) }