import { describe, expect, test } from "bun:test"; import { createSystemConfig, createTenantConfig, createUserConfig } from "../../config-helpers"; import type { FeatureDefinition } from "../../types"; import { validateConfigKeyAllowPerRequest, validateConfigKeyComputed, validateConfigKeyPiiEncrypted, } from "../config-deps"; function fakeFeature(configKeys: FeatureDefinition["configKeys"]): FeatureDefinition { return { name: "test-feature", configKeys } as unknown as FeatureDefinition; } describe("validateConfigKeyComputed", () => { test("rejects computed + backing:secrets (encrypted-at-rest via backing, not the encrypted flag)", () => { const feature = fakeFeature({ apiKey: createSystemConfig("text", { backing: "secrets", computed: async () => "x" }), }); expect(() => validateConfigKeyComputed(feature)).toThrow(/mutually exclusive/); }); test("rejects computed + encrypted:true", () => { const feature = fakeFeature({ apiKey: createSystemConfig("text", { encrypted: true, computed: async () => "x" }), }); expect(() => validateConfigKeyComputed(feature)).toThrow(/mutually exclusive/); }); test("allows computed without encryption", () => { const feature = fakeFeature({ apiKey: createSystemConfig("text", { computed: async () => "x" }), }); expect(() => validateConfigKeyComputed(feature)).not.toThrow(); }); }); describe("validateConfigKeyAllowPerRequest", () => { test("rejects allowPerRequest + backing:secrets on a number key", () => { const feature = fakeFeature({ rateLimit: createSystemConfig("number", { backing: "secrets", allowPerRequest: true }), }); expect(() => validateConfigKeyAllowPerRequest(feature)).toThrow( /may not be set via query-params/, ); }); }); describe("validateConfigKeyPiiEncrypted (kumiko-platform#231/#459)", () => { test("allows piiEncrypted on a tenant-scoped text key", () => { const feature = fakeFeature({ billingAddress: createTenantConfig("text", { piiEncrypted: true }), }); expect(() => validateConfigKeyPiiEncrypted(feature)).not.toThrow(); }); test("allows piiEncrypted on a user-scoped text key", () => { const feature = fakeFeature({ phoneNumber: createUserConfig("text", { piiEncrypted: true }), }); expect(() => validateConfigKeyPiiEncrypted(feature)).not.toThrow(); }); test("rejects piiEncrypted on a non-text key", () => { const feature = fakeFeature({ rateLimit: { ...createTenantConfig("number"), piiEncrypted: true }, }); expect(() => validateConfigKeyPiiEncrypted(feature)).toThrow( /piiEncrypted.*only applies to text keys/, ); }); test("rejects piiEncrypted + scope:system", () => { const feature = fakeFeature({ apiKey: createSystemConfig("text", { piiEncrypted: true }), }); expect(() => validateConfigKeyPiiEncrypted(feature)).toThrow(/piiEncrypted.*scope="system"/); }); test("rejects piiEncrypted + encrypted", () => { const feature = fakeFeature({ iban: createTenantConfig("text", { piiEncrypted: true, encrypted: true }), }); expect(() => validateConfigKeyPiiEncrypted(feature)).toThrow(/piiEncrypted=true and encrypted/); }); test("rejects piiEncrypted + backing:secrets", () => { const feature = fakeFeature({ iban: { ...createTenantConfig("text", { piiEncrypted: true }), backing: "secrets" as const }, }); expect(() => validateConfigKeyPiiEncrypted(feature)).toThrow(/piiEncrypted=true and encrypted/); }); });