feat: secure organization provider credentials

This commit is contained in:
2026-07-10 22:04:43 +08:00
parent e049cb6880
commit 848f913597
51 changed files with 3280 additions and 230 deletions
@@ -4,6 +4,15 @@ import { tmpdir } from "node:os";
import { join, resolve } from "node:path";
import { promisify } from "node:util";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import {
DEFAULT_ORG_ID,
prisma,
resetDb,
testSecretEnvelope,
TEST_SECRET_KEY,
TEST_SECRET_KEY_ID,
} from "./helpers.js";
import { ProviderConnectionService } from "../../src/connections/providerConnections.js";
const execFileAsync = promisify(execFile);
const TEST_DATABASE_URL = "postgresql://paradigm:paradigm@127.0.0.1:5432/cph_hub_test";
@@ -16,6 +25,7 @@ describe("deployment preflight CLI", () => {
let marker: string;
beforeEach(async () => {
await resetDb();
root = await mkdtemp(join(tmpdir(), "cph-deployment-preflight-"));
baseDir = join(root, "deploy");
hubDir = join(baseDir, "current", "hub");
@@ -93,6 +103,23 @@ describe("deployment preflight CLI", () => {
expect(result.stderr).toContain("PostgreSQL authenticated query failed for DATABASE_URL");
});
it("rejects a structurally valid keyring that cannot authenticate stored envelopes", async () => {
await prismaActorForEnvelope();
const workspaceRoot = join(persistentDir, "workspaces");
const fixture = await createFixture({
workspaceRoot,
marker,
keyringKey: Buffer.alloc(32, "wrong"),
});
const result = await runCli(fixture.args);
expect(result.exitCode).toBe(1);
expect(result.stderr).toContain("stored provider envelope verification failed");
expect(result.stderr).toContain("secret envelope authentication failed");
expect(result.stderr).not.toContain("stored-envelope-secret");
});
it("loads the actual Hub dependency graph and queries PostgreSQL in the runtime probe", async () => {
const result = await execFileAsync(
resolve("node_modules/.bin/tsx"),
@@ -138,6 +165,7 @@ describe("deployment preflight CLI", () => {
marker: string;
pgIsReadyScript?: string;
databaseUrl?: string;
keyringKey?: Buffer;
}): Promise<{ args: string[] }> {
const binDir = join(root, "bin");
const cphBin = join(binDir, "cph");
@@ -147,6 +175,7 @@ describe("deployment preflight CLI", () => {
const runuserBin = join(binDir, "runuser");
const setprivBin = join(binDir, "setpriv");
const envFile = join(root, "platform.env");
const keyringFile = join(root, "secret-keyring.json");
await Promise.all([
mkdir(binDir, { recursive: true }),
mkdir(join(hubDir, "dist"), { recursive: true }),
@@ -180,15 +209,17 @@ describe("deployment preflight CLI", () => {
`const { appendFileSync } = require("node:fs");\nappendFileSync(${JSON.stringify(options.marker)}, "service-prisma\\n");\n`,
),
writeFile(join(hubDir, "prisma", "schema.prisma"), "// fixture\n"),
writeFile(keyringFile, JSON.stringify({
version: 1,
activeKeyId: TEST_SECRET_KEY_ID,
keys: { [TEST_SECRET_KEY_ID]: (options.keyringKey ?? TEST_SECRET_KEY).toString("base64") },
}), { mode: 0o600 }),
]);
await writeFile(
envFile,
[
"NODE_ENV=production",
`DATABASE_URL=${options.databaseUrl ?? TEST_DATABASE_URL}`,
"ANTHROPIC_BASE_URL=https://openrouter.ai/api",
"ANTHROPIC_AUTH_TOKEN=provider-token",
"ANTHROPIC_API_KEY=",
"FEISHU_APP_ID=cli_app_id",
"FEISHU_APP_SECRET=feishu-app-secret",
"FEISHU_BOT_OPEN_ID=ou_bot",
@@ -207,6 +238,8 @@ describe("deployment preflight CLI", () => {
args: [
"--env-file",
envFile,
"--keyring-file",
keyringFile,
"--node-bin",
process.execPath,
"--runuser-bin",
@@ -236,6 +269,20 @@ describe("deployment preflight CLI", () => {
],
};
}
async function prismaActorForEnvelope(): Promise<void> {
await prisma.user.create({ data: { id: "preflight-admin", feishuOpenId: "ou_preflight", displayName: "Preflight" } });
await prisma.organizationMembership.create({
data: { organizationId: DEFAULT_ORG_ID, userId: "preflight-admin", role: "ADMIN" },
});
await new ProviderConnectionService(prisma, testSecretEnvelope, async () => {}).rotateByok({
organizationId: DEFAULT_ORG_ID,
providerId: "openrouter",
actorUserId: "preflight-admin",
baseUrl: "https://provider.example/api",
authToken: "stored-envelope-secret",
});
}
});
async function executable(path: string, contents: string): Promise<void> {