refactor(settings): adopt environment-only runtime secret flow

This commit is contained in:
2026-03-30 19:55:06 +02:00
parent fed7aa5b61
commit a19d2cbae0
19 changed files with 757 additions and 172 deletions
@@ -150,6 +150,7 @@ function createToolContext(
describe("assistant import/export and dispo tools", () => {
beforeEach(() => {
vi.clearAllMocks();
vi.unstubAllEnvs();
apiRateLimiter.reset();
totpValidateMock.mockReset();
vi.mocked(approveEstimateVersion).mockReset();
@@ -288,6 +289,67 @@ describe("assistant import/export and dispo tools", () => {
expect(JSON.parse(result.content)).toEqual({ configured: true });
});
it("treats environment-backed AI configuration as configured for assistant checks", async () => {
vi.stubEnv("OPENAI_API_KEY", "env-secret");
const ctx = createToolContext(
{
systemSettings: {
findUnique: vi.fn().mockResolvedValue({
aiProvider: "openai",
azureOpenAiDeployment: "gpt-4o-mini",
azureOpenAiApiKey: null,
}),
},
},
{ userRole: SystemRole.USER },
);
const result = await executeTool("get_ai_configured", "{}", ctx);
expect(JSON.parse(result.content)).toEqual({ configured: true });
});
it("clears legacy runtime secrets through the real settings router path", async () => {
const findUnique = vi.fn().mockResolvedValue({
azureOpenAiApiKey: "db-openai",
azureDalleApiKey: null,
geminiApiKey: "db-gemini",
smtpPassword: null,
anonymizationSeed: "db-seed",
});
const update = vi.fn().mockResolvedValue({ id: "singleton" });
const auditCreate = vi.fn().mockResolvedValue(undefined);
const ctx = createToolContext(
{
systemSettings: {
findUnique,
update,
},
auditLog: {
create: auditCreate,
},
},
{ userRole: SystemRole.ADMIN },
);
const result = await executeTool("clear_stored_runtime_secrets", "{}", ctx);
expect(JSON.parse(result.content)).toEqual({
ok: true,
clearedFields: ["azureOpenAiApiKey", "geminiApiKey", "anonymizationSeed"],
});
expect(update).toHaveBeenCalledWith({
where: { id: "singleton" },
data: {
azureOpenAiApiKey: null,
geminiApiKey: null,
anonymizationSeed: null,
},
});
expect(auditCreate).toHaveBeenCalled();
});
it("masks webhook secrets in assistant responses", async () => {
const ctx = createToolContext(
{