Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/integrations/omp-yaml-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,12 @@ export function patchOmpYamlSource(

let patched = `${text.slice(0, startOffset)}${text.slice(endOffset)}`;
if (mutation.removeEmptyProviders) {
const remaining = Bun.YAML.parse(patched) as { providers?: unknown } | null;
let remaining: { providers?: unknown } | null;
try {
remaining = Bun.YAML.parse(patched) as { providers?: unknown } | null;
} catch {
return null;
}
if (remaining && Object.hasOwn(remaining, "providers")) {
const provider = remaining.providers;
const empty = provider === null || (
Expand Down
17 changes: 17 additions & 0 deletions tests/integrations-writer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,23 @@ describe("OMP source preservation", () => {
if (!result.ok) expect(result.reason).toBe("unsafe");
expect(readFileSync(configPath, "utf8")).toBe(edited);
});

test("refuses disable when removing the managed block would break a YAML alias", () => {
const configPath = installOmp();
expect(applyIntegration(input({ clientId: "omp" })).ok).toBe(true);
const edited = readFileSync(configPath, "utf8")
.replace(" baseUrl:", " baseUrl: &opencodex_url")
.concat("settings:\n inheritedBase: *opencodex_url\n");
Comment thread
coderabbitai[bot] marked this conversation as resolved.
expect(edited).toContain(" baseUrl: &opencodex_url");
writeFileSync(configPath, edited);

const journalBefore = store.listOperations("omp");
const result = disableIntegration(input({ clientId: "omp" }));
expect(result.ok).toBe(false);
if (!result.ok) expect(result.reason).toBe("unsafe");
expect(readFileSync(configPath, "utf8")).toBe(edited);
expect(store.listOperations("omp")).toEqual(journalBefore);
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.
});

describe("restore", () => {
Expand Down
30 changes: 30 additions & 0 deletions tests/management-integration-routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ function installHermes(): string {
return spec.configPath(routeEnv, home);
}

function installOmp(): string {
const spec = INTEGRATION_CLIENTS.omp;
const dir = spec.detectDir(routeEnv, home);
mkdirSync(dir, { recursive: true });
return spec.configPath(routeEnv, home);
}

function hermesConfigPath(): string {
return INTEGRATION_CLIENTS.hermes.configPath(routeEnv, home);
}
Expand Down Expand Up @@ -412,6 +419,29 @@ function bookkeeping(): Pick<IntegrationIO, "appendJournal" | "putRecord" | "dro
}

describe("refusals", () => {
test("invalid OMP alias removal returns unsafe without changing bytes or journal", async () => {
const configPath = installOmp();
expect((await put("omp", true)).status).toBe(200);
const edited = readFileSync(configPath, "utf8")
.replace(" baseUrl:", " baseUrl: &opencodex_url")
.concat("settings:\n inheritedBase: *opencodex_url\n");
expect(edited).toContain(" baseUrl: &opencodex_url");
writeFileSync(configPath, edited);
const journalBefore = store.listOperations("omp");

const response = await put("omp", false);
expect(response.status).toBe(409);
expect(await response.json()).toMatchObject({
error: "integration config is unsafe",
code: "integration_unsafe",
clientId: "omp",
state: "unsafe",
reason: "unsafe",
});
expect(readFileSync(configPath, "utf8")).toBe(edited);
expect(store.listOperations("omp")).toEqual(journalBefore);
});

test("conflict rejects disable without changing a managed-field edit", async () => {
const configPath = installHermes();
expect((await put("hermes", true)).status).toBe(200);
Expand Down
Loading