import { existsSync, rmSync } from "node:fs"; import { mkdtemp } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { afterEach, describe, expect, test } from "vitest"; import type { DashboardDocument } from "$lib/model"; import { genericDashboardFixture } from "$lib/model/fixtures/generic"; import { createDashboardStore, type DashboardStore } from "$lib/server/db/dashboard-store"; import { AgentConfigAuthorizationError, authorizeAgentConfigRequest, handleAgentDashboardRequest, previewDashboardChanges, publishDashboardChanges, rollbackDashboardRevision, type AgentDashboardOperation, type JsonPatchOperation, } from "."; const stores: DashboardStore[] = []; const tempRoots: string[] = []; afterEach(() => { stores.splice(0).forEach((store) => store.close()); tempRoots.splice(0).forEach((path) => rmSync(path, { force: true, recursive: true })); }); describe("agent dashboard configuration API", () => { test("previews typed dashboard operations with an RFC 6902-compatible patch", () => { const operations = exampleOperations(); const result = previewDashboardChanges(genericDashboardFixture, operations); expect(result.ok).toBe(true); if (!result.ok) throw new Error("expected preview success"); expect(result.document.serviceGroups[0]?.id).toBe("edge"); expect(result.document.serviceGroups[0]?.services[0]).toMatchObject({ id: "edge-router", datasource: { type: "external", adapter: "http-status", reference: "GET https://edge.example.test/api/status", }, }); expect(result.document.layout.telemetry).toEqual([ "service-uptime", "edge-latency", "queue-depth", ]); expect(genericDashboardFixture.serviceGroups.map((group) => group.id)).toEqual([ "core-services", ]); expect(result.patch.length).toBeGreaterThan(0); expect(result.patch.every((operation) => operation.path.startsWith("/"))).toBe(true); expect(result.patch.map((operation) => operation.op)).toContain("add"); }); test("returns structured repairable errors for invalid operations", () => { const result = previewDashboardChanges(genericDashboardFixture, [ { type: "add_service", groupId: "missing-group", service: exampleService(), }, ]); expect(result.ok).toBe(false); if (result.ok) throw new Error("expected preview failure"); expect(result.errors).toEqual([ expect.objectContaining({ code: "group_not_found", operationIndex: 0, path: "/serviceGroups", }), ]); }); test("rejects unsupported target-specific mutations", () => { const datasourceResult = previewDashboardChanges(genericDashboardFixture, [ { type: "connect_datasource", target: { kind: "statusItem", stripId: "runtime", id: "status" }, datasource: { type: "external", adapter: "http-status", reference: "GET https://status.example.test/api", }, }, ]); expect(datasourceResult.ok).toBe(false); if (datasourceResult.ok) throw new Error("expected datasource failure"); expect(datasourceResult.errors[0]).toMatchObject({ code: "unsupported_target", operationIndex: 0, path: "/statusStrips", }); const thresholdResult = previewDashboardChanges(genericDashboardFixture, [ { type: "set_status_rule", target: { kind: "service", id: "identity" }, thresholds: { warning: 1 }, }, ]); expect(thresholdResult.ok).toBe(false); if (thresholdResult.ok) throw new Error("expected threshold failure"); expect(thresholdResult.errors[0]).toMatchObject({ code: "unsupported_target", operationIndex: 0, path: "/serviceGroups", }); }); test("removes status strip items through the shared remove operation", () => { const result = previewDashboardChanges(genericDashboardFixture, [ { type: "remove_item", target: { kind: "statusItem", stripId: "runtime", id: "sync" }, }, ]); expect(result.ok).toBe(true); if (!result.ok) throw new Error("expected remove success"); expect(result.document.statusStrips[0]?.items.map((item) => item.id)).toEqual([ "status", ]); expect(result.patch.map((operation) => operation.op)).toContain("remove"); }); test("returns RFC 6902-applicable patches for multiple array removals", () => { const result = previewDashboardChanges(genericDashboardFixture, [ { type: "remove_item", target: { kind: "statusItem", stripId: "runtime", id: "status" }, }, { type: "remove_item", target: { kind: "statusItem", stripId: "runtime", id: "sync" }, }, ]); expect(result.ok).toBe(true); if (!result.ok) throw new Error("expected remove success"); expect( result.patch .filter((operation) => operation.op === "remove") .map((operation) => operation.path), ).toEqual(["/statusStrips/0/items/1", "/statusStrips/0/items/0"]); expect(applyJsonPatch(genericDashboardFixture, result.patch)).toMatchObject({ statusStrips: [{ items: [] }], }); }); test("rejects ambiguous service and status targets", () => { const duplicateDocument = documentWithDuplicateNestedIds(); const connect = previewDashboardChanges(duplicateDocument, [ { type: "connect_datasource", target: { kind: "service", id: "identity" }, datasource: { type: "external", adapter: "http-status", reference: "GET https://identity.example.test/health", }, }, ]); expect(connect.ok).toBe(false); if (connect.ok) throw new Error("expected ambiguous service failure"); expect(connect.errors[0]).toMatchObject({ code: "ambiguous_target", operationIndex: 0, path: "/serviceGroups", }); const remove = previewDashboardChanges(duplicateDocument, [ { type: "remove_item", target: { kind: "service", id: "identity" }, }, ]); expect(remove.ok).toBe(false); if (remove.ok) throw new Error("expected ambiguous removal failure"); expect(remove.errors[0]).toMatchObject({ code: "ambiguous_target", operationIndex: 0, path: "/serviceGroups", }); const status = previewDashboardChanges(duplicateDocument, [ { type: "set_status_rule", target: { kind: "statusItem", id: "status" }, value: "Healthy", }, ]); expect(status.ok).toBe(false); if (status.ok) throw new Error("expected ambiguous status failure"); expect(status.errors[0]).toMatchObject({ code: "ambiguous_target", operationIndex: 0, path: "/statusStrips", }); }); test("rejects create_dashboard when it is not the first operation", () => { const result = previewDashboardChanges(genericDashboardFixture, [ { type: "remove_item", target: { kind: "telemetry", id: "queue-depth" }, }, { type: "create_dashboard", document: genericDashboardFixture, }, ]); expect(result.ok).toBe(false); if (result.ok) throw new Error("expected sequence failure"); expect(result.errors[0]).toMatchObject({ code: "invalid_operation_sequence", operationIndex: 1, path: "/1", }); }); test("publishes valid operations as a persisted dashboard revision", async () => { const { dbPath, store } = await createTestStore(); const seed = store.seedDashboardIfEmpty(genericDashboardFixture, { actor: "seed", message: "initial dashboard", }); const result = publishDashboardChanges(store, exampleOperations(), { actor: "agent", message: "add edge router", }); expect(result.ok).toBe(true); if (!result.ok) throw new Error("expected publish success"); expect(existsSync(dbPath)).toBe(true); expect(result.revision.operation).toBe("commit"); expect(result.revision.actor).toBe("agent"); expect(result.revision.message).toBe("add edge router"); expect(result.previousRevisionId).toBe(seed.id); expect(result.patch.length).toBeGreaterThan(0); expect(store.getActiveDashboard()?.document.serviceGroups[0]?.id).toBe("edge"); expect(store.listRevisions()).toHaveLength(2); }); test("does not publish invalid operations", async () => { const { store } = await createTestStore(); const seed = store.seedDashboardIfEmpty(genericDashboardFixture, { actor: "seed", }); const result = publishDashboardChanges(store, [ { type: "remove_item", target: { kind: "telemetry", id: "missing-metric" }, }, ]); expect(result.ok).toBe(false); if (result.ok) throw new Error("expected publish failure"); expect(result.errors[0]).toMatchObject({ code: "item_not_found", operationIndex: 0, }); expect(store.getActiveDashboard()?.currentRevisionId).toBe(seed.id); expect(store.listRevisions()).toHaveLength(1); }); test("rolls back through the agent-safe revision path", async () => { const { store } = await createTestStore(); const seed = store.seedDashboardIfEmpty(genericDashboardFixture, { actor: "seed", }); const publish = publishDashboardChanges(store, exampleOperations(), { actor: "agent", }); expect(publish.ok).toBe(true); const rollback = rollbackDashboardRevision(store, seed.id, { actor: "agent", message: "restore previous dashboard", }); expect(rollback.operation).toBe("rollback"); expect(rollback.actor).toBe("agent"); expect(rollback.sourceRevisionId).toBe(seed.id); expect(store.getActiveDashboard()?.document.metadata.title).toBe("Operations Console"); expect(store.listRevisions().map((revision) => revision.operation)).toEqual([ "rollback", "commit", "seed", ]); }); test("authenticates agent configuration requests with a shared token", () => { const authorized = new Request("https://dimensionlab.test/api/agent/dashboard", { headers: { authorization: "Bearer shared-secret" }, }); const rejected = new Request("https://dimensionlab.test/api/agent/dashboard"); expect(authorizeAgentConfigRequest(authorized, "shared-secret")).toEqual({ ok: true, }); expect(() => authorizeAgentConfigRequest(rejected, "shared-secret")).toThrow( AgentConfigAuthorizationError, ); expect(() => authorizeAgentConfigRequest(authorized, "")).toThrow( AgentConfigAuthorizationError, ); }); test("handles preview, publish, and rollback requests through the HTTP adapter", async () => { const { store } = await createTestStore(); const seed = store.seedDashboardIfEmpty(genericDashboardFixture, { actor: "seed", }); const preview = await handleAgentDashboardRequest( jsonRequest({ action: "preview_changes", operations: exampleOperations(), }), { store, token: "shared-secret" }, ); expect(preview.status).toBe(200); expect(await preview.json()).toMatchObject({ ok: true, action: "preview_changes", patch: expect.any(Array), }); expect(store.listRevisions()).toHaveLength(1); const publish = await handleAgentDashboardRequest( jsonRequest({ action: "publish_changes", actor: "agent", message: "publish edge router", operations: exampleOperations(), }), { store, token: "shared-secret" }, ); expect(publish.status).toBe(200); expect(await publish.json()).toMatchObject({ ok: true, action: "publish_changes", revision: { operation: "commit", actor: "agent" }, }); expect(store.listRevisions()).toHaveLength(2); const rollback = await handleAgentDashboardRequest( jsonRequest({ action: "rollback_revision", actor: "agent", revisionId: seed.id, }), { store, token: "shared-secret" }, ); expect(rollback.status).toBe(200); expect(await rollback.json()).toMatchObject({ ok: true, action: "rollback_revision", revision: { operation: "rollback", sourceRevisionId: seed.id }, }); }); test("returns a structured error for unknown rollback revisions", async () => { const { store } = await createTestStore(); store.seedDashboardIfEmpty(genericDashboardFixture, { actor: "seed", }); const rollback = await handleAgentDashboardRequest( jsonRequest({ action: "rollback_revision", actor: "agent", revisionId: "missing-revision", }), { store, token: "shared-secret" }, ); expect(rollback.status).toBe(404); expect(await rollback.json()).toMatchObject({ ok: false, errors: [ { code: "revision_not_found", path: "/revisionId", }, ], }); }); test("previews create_dashboard requests against an empty store", async () => { const { store } = await createTestStore(); const preview = await handleAgentDashboardRequest( jsonRequest({ action: "preview_changes", operations: [ { type: "create_dashboard", document: genericDashboardFixture, }, ], }), { store, token: "shared-secret" }, ); expect(preview.status).toBe(200); expect(await preview.json()).toMatchObject({ ok: true, action: "preview_changes", document: { metadata: { title: "Operations Console", }, }, }); expect(store.listRevisions()).toHaveLength(0); }); }); async function createTestStore() { const root = await mkdtemp(join(tmpdir(), "dimensionlab-agent-config-")); tempRoots.push(root); const dbPath = join(root, "dashboard.sqlite"); const store = createDashboardStore({ databaseUrl: `file:${dbPath}`, }); stores.push(store); return { dbPath, store }; } function exampleOperations(): AgentDashboardOperation[] { return [ { type: "add_section", section: { id: "edge", title: "Edge", layout: "list", }, }, { type: "add_service", groupId: "edge", service: exampleService(), }, { type: "add_metric_card", card: { id: "edge-latency", label: "Edge Latency", value: { kind: "latency", value: 12, precision: 0 }, severity: "ok", detail: "p95", datasource: { type: "external", adapter: "prometheus", reference: "histogram_quantile(0.95, edge_request_duration_seconds_bucket)", }, }, position: { afterId: "service-uptime" }, }, { type: "connect_datasource", target: { kind: "service", groupId: "edge", id: "edge-router", }, datasource: { type: "external", adapter: "http-status", reference: "GET https://edge.example.test/api/status", }, }, { type: "set_status_rule", target: { kind: "telemetry", id: "edge-latency" }, thresholds: { warning: 50, danger: 100 }, }, { type: "arrange_item", area: "serviceGroups", id: "edge", index: 0, }, ]; } function exampleService() { return { id: "edge-router", label: "Edge Router", description: "Ingress and routing", icon: "mdi:router-network", severity: "ok" as const, detail: "pending datasource", datasource: { type: "placeholder" as const, reason: "health adapter pending" }, link: { href: "https://edge.example.test", label: "Open Edge Router", external: true, }, }; } function documentWithDuplicateNestedIds(): DashboardDocument { const document = structuredClone(genericDashboardFixture); document.layout.serviceGroups.push("secondary-services"); document.serviceGroups.push({ id: "secondary-services", title: "Secondary Services", layout: "list", services: [ { ...document.serviceGroups[0].services[0], label: "Shadow Identity", }, ], }); document.layout.statusStrips.push("secondary-runtime"); document.statusStrips.push({ id: "secondary-runtime", items: [ { ...document.statusStrips[0].items[0], value: "Healthy", }, ], }); return document; } function applyJsonPatch(value: T, patch: JsonPatchOperation[]): T { const next = structuredClone(value); for (const operation of patch) { const { parent, key } = jsonPointerTarget(next, operation.path); if (operation.op === "remove") { if (Array.isArray(parent)) { parent.splice(Number(key), 1); } else { delete parent[key]; } } else if (operation.op === "add") { if (Array.isArray(parent)) { parent.splice(Number(key), 0, operation.value); } else { parent[key] = operation.value; } } else if (operation.op === "replace") { if (Array.isArray(parent)) { parent[Number(key)] = operation.value; } else { parent[key] = operation.value; } } } return next; } function jsonPointerTarget(value: unknown, path: string) { const segments = path .split("/") .slice(1) .map((segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~")); const key = segments.pop(); if (key === undefined) throw new Error(`Invalid JSON pointer: ${path}`); let parent = value as Record | unknown[]; for (const segment of segments) { parent = Array.isArray(parent) ? (parent[Number(segment)] as Record | unknown[]) : (parent[segment] as Record | unknown[]); } return { parent, key }; } function jsonRequest(body: unknown) { return new Request("https://dimensionlab.test/api/agent/dashboard", { body: JSON.stringify(body), headers: { authorization: "Bearer shared-secret", "content-type": "application/json", }, method: "POST", }); }