feat: unify installation model catalog

This commit is contained in:
Codex
2026-09-02 18:45:33 +02:00
parent ae053961a3
commit 7b7927bfe5
169 changed files with 3696 additions and 4572 deletions
+9 -27
View File
@@ -14,11 +14,6 @@ function fakeService(): PiManagementService {
config: { provider: "zai", model: "glm-5.2", reasoning: "medium" },
checkedAt: "2026-08-05T10:00:00.000Z",
})),
options: vi.fn(async () => ({
providers: ["zai"], models: [{ provider: "zai", id: "glm-5.2" }],
reasoning: ["low", "medium", "high"], checkedAt: "2026-08-05T10:00:00.000Z",
})),
configure: vi.fn(async (value) => ({ ...value, updatedAt: "2026-08-05T10:00:00.000Z" })),
test: vi.fn(async () => ({ ready: true, checkedAt: "2026-08-05T10:00:00.000Z" })),
logs: vi.fn(async () => ({ lines: ["Pi smoke check succeeded"], checkedAt: "2026-08-05T10:00:00.000Z" })),
};
@@ -106,24 +101,17 @@ test("loopback-only AUTH_MODE=none may read the sanitized Pi status", async () =
});
// A local implicit administrator has pi.manage, but a browser origin still cannot borrow that
// authority to mutate local configuration or trigger provider work.
// authority to trigger provider work.
test("loopback-only management rejects cross-origin writes for its local administrator", async () => {
const service = fakeService();
const app = appWith(service);
try {
const configured = await app.inject({
method: "PUT", url: "/pi-management/config",
headers: { host: "127.0.0.1:8080", origin: "https://evil.example" },
payload: { provider: "zai", model: "glm-5.2", reasoning: "high" },
});
const smoke = await app.inject({
method: "POST", url: "/pi-management/test",
headers: { host: "127.0.0.1:8080", origin: "https://evil.example" },
});
expect(configured.statusCode).toBe(403);
expect(smoke.statusCode).toBe(403);
expect(service.configure).not.toHaveBeenCalled();
expect(service.test).not.toHaveBeenCalled();
} finally {
await app.close();
@@ -132,14 +120,13 @@ test("loopback-only management rejects cross-origin writes for its local adminis
// Catches an origin guard that also blocks the same-origin Docker frontend or non-browser local
// lifecycle clients that do not send Origin.
test("loopback-only management preserves same-origin frontend and origin-less local writes", async () => {
test("loopback-only management preserves same-origin and origin-less smoke checks", async () => {
const service = fakeService();
const app = appWith(service);
try {
const sameOrigin = await app.inject({
method: "PUT", url: "/pi-management/config",
method: "POST", url: "/pi-management/test",
headers: { host: "127.0.0.1:8080", origin: "http://127.0.0.1:8080" },
payload: { provider: "zai", model: "glm-5.2", reasoning: "high" },
});
const lifecycleClient = await app.inject({ method: "POST", url: "/pi-management/test" });
@@ -150,25 +137,20 @@ test("loopback-only management preserves same-origin frontend and origin-less lo
}
});
// Catches route wiring that bypasses closed service validation or gives the browser a Docker/image
// lifecycle endpoint rather than only installation-default configuration and diagnostics.
test("trusted admins receive only configuration, smoke, options, and log endpoints", async () => {
// Catches a regression that reintroduces a browser-writable provider/model source.
test("trusted admins receive only status, smoke, and log endpoints", async () => {
const service = fakeService();
const app = appWith(service, exposedServerEnv);
try {
const options = await app.inject({ method: "GET", url: "/pi-management/options", headers: adminHeaders });
const configured = await app.inject({
method: "PUT", url: "/pi-management/config", headers: adminHeaders,
payload: { provider: "zai", model: "glm-5.2", reasoning: "high" },
});
const status = await app.inject({ method: "GET", url: "/pi-management/status", headers: adminHeaders });
const smoke = await app.inject({ method: "POST", url: "/pi-management/test", headers: adminHeaders });
const logs = await app.inject({ method: "GET", url: "/pi-management/logs", headers: adminHeaders });
expect(options.statusCode).toBe(200);
expect(configured.statusCode).toBe(200);
expect(configured.json()).toMatchObject({ provider: "zai", model: "glm-5.2", reasoning: "high" });
expect(status.statusCode).toBe(200);
expect(smoke.statusCode).toBe(200);
expect(logs.statusCode).toBe(200);
expect((await app.inject({ method: "GET", url: "/pi-management/options", headers: adminHeaders })).statusCode).toBe(404);
expect((await app.inject({ method: "PUT", url: "/pi-management/config", headers: adminHeaders })).statusCode).toBe(404);
expect(app.printRoutes()).not.toContain("update");
expect(app.printRoutes()).not.toContain("rollback");
} finally {