/** * Console Vault projection — fingerprints only; resolution; blast radius. */ import { describe, expect, test } from "bun:test"; import { memoryVaultDriver } from "../../drivers/index.ts"; import { createVaultRuntime, fingerprintSecretSync, vault } from "../../elements/vault.ts"; import { createMemoryJournalStore, type JournalRun } from "../../kernel/journal.ts"; import type { Manifest } from "../../manifest/types.ts"; import { assertNoSecretLeak, blastRadiusOf, createVaultContract, probeVaultBackend, projectVaultList, readersOf, resolveVaultDriverId, rotateVaultValue, setVaultValue, toConsoleVaultStatus, } from "./vault.ts"; import type { VaultStatus } from "../../elements/vault/types.ts"; const SECRET = "sk_live_console_vault_test_do_not_leak"; function manifest(): Manifest { return { oke: "1.0", app: "vault-test", vault: { STRIPE_KEY: { description: "Payments", rotate: "90d", }, PUBLIC_APP_URL: { description: "Public origin", sensitive: false, }, }, flows: { "payments.charge": { trigger: { http: { method: "POST", path: "/charge" } }, effects: { secrets: ["STRIPE_KEY"] }, }, "site.render": { trigger: { http: { method: "GET", path: "/" } }, effects: { secrets: ["PUBLIC_APP_URL"] }, }, }, }; } async function runtime() { const rt = createVaultRuntime({ secrets: [ vault.secret("STRIPE_KEY", { description: "Payments", rotate: "90d" }), vault.config("PUBLIC_APP_URL", { description: "Public origin" }), ], chain: [ { driver: memoryVaultDriver, source: "driver", options: { secrets: { STRIPE_KEY: SECRET, PUBLIC_APP_URL: "https://app.example.com", }, }, }, ], now: () => 1_700_000_000_000, }); await rt.boot(); return rt; } describe("projectVaultList", () => { test("secrets are fingerprinted; config is cleartext; never leaks secret", async () => { const rt = await runtime(); const { secrets, env } = await projectVaultList({ manifest: manifest(), runtime: rt, env: "test", peerFingerprints: { STRIPE_KEY: { staging: fingerprintSecretSync(SECRET) }, }, }); expect(env).toBe("test"); const stripe = secrets.find((s) => s.name === "STRIPE_KEY"); const pub = secrets.find((s) => s.name === "PUBLIC_APP_URL"); expect(stripe?.sensitive).toBe(true); expect(stripe?.fingerprint).toBe(fingerprintSecretSync(SECRET)); expect(stripe?.cleartext).toBeNull(); expect(stripe?.readers).toEqual(["payments.charge"]); expect(stripe?.sharedFingerprintEnvs).toContain("staging"); expect(pub?.sensitive).toBe(false); expect(pub?.cleartext).toBe("https://app.example.com"); expect(pub?.fingerprint).toBeNull(); assertNoSecretLeak(stripe!, [SECRET]); assertNoSecretLeak(pub!, [SECRET]); expect(JSON.stringify(secrets)).not.toContain(SECRET); }); test("resolution chain shows which layer won", async () => { const rt = createVaultRuntime({ secrets: [vault.secret("KEY")], allowDevFallbacks: true, chain: [ { driver: memoryVaultDriver, source: "process.env", options: { secrets: {} }, }, { driver: memoryVaultDriver, source: ".env.local", options: { secrets: { KEY: "from-local" } }, }, { driver: memoryVaultDriver, source: "driver", options: { secrets: { KEY: "from-driver" } }, }, ], }); await rt.boot(); const { secrets } = await projectVaultList({ manifest: null, runtime: rt, env: "test", }); const row = secrets.find((s) => s.name === "KEY"); expect(row?.winner).toBe(".env.local"); expect(row?.resolution.find((s) => s.source === ".env.local")?.won).toBe(true); expect(row?.resolution.find((s) => s.source === "driver")?.present).toBe(true); expect(row?.resolution.find((s) => s.source === "driver")?.won).toBe(false); }); test("last-read is recorded on runtime read", async () => { const rt = await runtime(); expect(rt.lastReadAt("STRIPE_KEY")).toBeUndefined(); rt.read("STRIPE_KEY"); expect(rt.lastReadAt("STRIPE_KEY")).toBe(1_700_000_000_000); const { secrets } = await projectVaultList({ manifest: manifest(), runtime: rt, env: "test", }); expect(secrets.find((s) => s.name === "STRIPE_KEY")?.lastReadAt).toBe(1_700_000_000_000); }); test("blast radius queries journal — count + longest wake", async () => { const readers = readersOf(manifest(), "STRIPE_KEY"); const now = 1_000_000; const runs: JournalRun[] = [ { id: "r1", flow: "payments.charge", input: {}, status: "sleeping", entries: [], wakeAt: now + 5_000, createdAt: now, updatedAt: now, }, { id: "r2", flow: "payments.charge", input: {}, status: "sleeping", entries: [], wakeAt: now + 60_000, createdAt: now, updatedAt: now, }, { id: "r3", flow: "site.render", input: {}, status: "sleeping", entries: [], wakeAt: now + 999_999, createdAt: now, updatedAt: now, }, { id: "r4", flow: "payments.charge", input: {}, status: "completed", entries: [], createdAt: now, updatedAt: now, }, ]; const blast = blastRadiusOf(runs, readers, now); expect(blast.count).toBe(2); expect(blast.longestWakeAt).toBe(now + 60_000); expect(blast.longestOutstandingMs).toBe(60_000); expect([...blast.runIds].sort()).toEqual(["r1", "r2"]); const journal = createMemoryJournalStore(runs); const rt = await runtime(); const { secrets } = await projectVaultList({ manifest: manifest(), runtime: rt, journal, env: "test", now: () => now, }); expect(secrets.find((s) => s.name === "STRIPE_KEY")?.blastRadius.count).toBe(2); }); }); describe("backend badge", () => { const builtinStatus: VaultStatus = { sealed: true, initialized: true, masterKeyPresent: true, kekVersion: 2, secretCount: 3, sealCount: 1, lastSealedAt: new Date(1_700_000_100_000), lastUnsealedAt: new Date(1_700_000_000_000), rewrapTargetKekVersion: 3, }; test("driver id comes from config, falling back to framework defaults", () => { expect(resolveVaultDriverId(null, "dev")).toBe("env"); expect(resolveVaultDriverId(null, "test")).toBe("memory"); expect(resolveVaultDriverId(null, "prod")).toBe("vault"); expect(resolveVaultDriverId({ drivers: { vault: { dev: "managed" } } }, "dev")).toBe("managed"); expect(resolveVaultDriverId({ drivers: { vault: { dev: "builtin" } } }, "dev")).toBe("vault"); // An unknown id is a boot concern — the Console still renders. expect(resolveVaultDriverId({ drivers: { vault: { dev: "nope" } } }, "dev")).toBe("env"); expect( resolveVaultDriverId({ drivers: { vault: { dev: ["open", "bao"].join("") } } }, "dev"), ).toBe("env"); }); test("managed backend reports the provider id", async () => { const backend = await probeVaultBackend({ config: { drivers: { vault: { dev: "managed" } } }, env: "dev", processEnv: { OKE_VAULT_PROVIDER: "aws-secrets-manager" }, }); expect(backend.provider).toBe("aws-secrets-manager"); }); test("list stays on declared contracts — not every process.env key", async () => { const rt = createVaultRuntime({ secrets: [vault.config("PUBLIC_APP_URL")], chain: [ { driver: memoryVaultDriver, source: "process.env", options: { secrets: { PUBLIC_APP_URL: "https://app.example.com", PATH: "/usr/bin" } }, }, ], }); await rt.boot(); const { secrets } = await projectVaultList({ manifest: { oke: "1.0", app: "vault-test", vault: { PUBLIC_APP_URL: { sensitive: false } }, }, runtime: rt, env: "test", }); expect(secrets.map((s) => s.name)).toEqual(["PUBLIC_APP_URL"]); }); test("non-builtin driver reports its id and no status", async () => { const backend = await probeVaultBackend({ config: { drivers: { vault: { dev: "managed" } } }, env: "dev", processEnv: {}, }); expect(backend).toEqual({ driverId: "managed", builtin: false, status: null, unavailable: null, provider: null, }); }); test("builtin status is JSON-safe and sealed follows the master key", async () => { const sealed = await probeVaultBackend({ config: { drivers: { vault: { dev: "vault" } } }, env: "dev", processEnv: {}, loadStatus: async () => builtinStatus, }); expect(sealed.builtin).toBe(true); expect(sealed.status).toEqual({ ...toConsoleVaultStatus(builtinStatus), sealed: true, }); expect(sealed.status?.lastUnsealedAt).toBe(1_700_000_000_000); expect(sealed.status?.rewrapTargetKekVersion).toBe(3); const unsealed = await probeVaultBackend({ config: { drivers: { vault: { dev: "vault" } } }, env: "dev", processEnv: { OKE_VAULT_MASTER_KEY: "a-base64-key" }, loadStatus: async () => builtinStatus, }); expect(unsealed.status?.sealed).toBe(false); }); test("an unreachable builtin backend degrades to a reason, never a throw", async () => { const backend = await probeVaultBackend({ config: { drivers: { vault: { dev: "vault" } } }, env: "dev", processEnv: {}, loadStatus: async () => { throw new Error("relation oke_vault_status does not exist"); }, }); expect(backend.status).toBeNull(); expect(backend.unavailable).toContain("oke_vault_status"); }); test("builtin backend with no SQL configured says so instead of spinning PGlite", async () => { const backend = await probeVaultBackend({ config: { drivers: { vault: { dev: "vault" } } }, env: "dev", processEnv: {}, }); expect(backend.status).toBeNull(); expect(backend.unavailable).toContain("DATABASE_URL"); }); test("the projection passes the backend through untouched", async () => { const rt = await runtime(); const backend = await probeVaultBackend({ config: { drivers: { vault: { dev: "memory" } } }, env: "dev", processEnv: {}, }); const listed = await projectVaultList({ manifest: manifest(), runtime: rt, env: "test", backend, }); expect(listed.backend).toEqual(backend); const unprobed = await projectVaultList({ manifest: manifest(), runtime: rt, env: "test", }); expect(unprobed.backend).toBeNull(); }); }); describe("set / rotate", () => { test("set updates fingerprint and never returns value", async () => { const rt = await runtime(); const before = rt.fingerprint("STRIPE_KEY"); const result = setVaultValue(rt, { name: "STRIPE_KEY", value: "sk_rotated_value_xyz", }); expect(result.name).toBe("STRIPE_KEY"); expect(result.fingerprint).not.toBe(before); expect(result.fingerprint).toBe(fingerprintSecretSync("sk_rotated_value_xyz")); expect(JSON.stringify(result)).not.toContain("sk_rotated_value_xyz"); }); test("rotate is the same write path", async () => { const rt = await runtime(); const result = rotateVaultValue(rt, { name: "STRIPE_KEY", value: "sk_new", }); expect(result.fingerprint).toBe(fingerprintSecretSync("sk_new")); }); }); describe("create from Console", () => { test("adds an overlay contract without leaking the value", async () => { const { mkdtemp } = await import("node:fs/promises"); const { tmpdir } = await import("node:os"); const { join } = await import("node:path"); const dir = await mkdtemp(join(tmpdir(), "oke-vault-create-")); const rt = await runtime(); const result = await createVaultContract(rt, dir, manifest(), { name: "ISSUE_PEPPER", kind: "secret", value: "pepper_do_not_leak", rotate: "never", description: "Id pepper", }); expect(result.name).toBe("ISSUE_PEPPER"); expect(result.fingerprint).toBe(fingerprintSecretSync("pepper_do_not_leak")); expect(JSON.stringify(result)).not.toContain("pepper_do_not_leak"); const listed = await projectVaultList({ manifest: manifest(), runtime: rt, cwd: dir, env: "test", }); const row = listed.secrets.find((s) => s.name === "ISSUE_PEPPER"); expect(row).toMatchObject({ kind: "secret", origin: "console", rotate: "never", }); expect(listed.secrets.some((s) => s.name === "STRIPE_KEY" && s.origin === "source")).toBe(true); await expect( createVaultContract(rt, dir, manifest(), { name: "STRIPE_KEY", kind: "secret", value: "nope", }), ).rejects.toThrow(/already declared/); }); });