fix(apps): tolerate stale activity API

Use the omitted-window contract for all-time activity so mixed-version restarts do not reject the page, and remove the obsolete audit footer.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-08-20 21:20:02 +00:00
1 parent 5f7926a5d5
commit ad8f869278
4 files changed
+40 -7

No files matched your search

+34
View File
@@ -0,0 +1,34 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
const mockApi = vi.hoisted(() => ({
get: vi.fn(),
}));
vi.mock("./client", () => ({
api: mockApi,
}));
import { toolsApi } from "./tools";
describe("toolsApi.listActivity", () => {
beforeEach(() => {
mockApi.get.mockReset();
mockApi.get.mockResolvedValue({ events: [], nextCursor: null });
});
it("uses the omitted-window contract for all-time activity", async () => {
await toolsApi.listActivity("company-1", { window: "all", limit: 50 });
expect(mockApi.get).toHaveBeenCalledWith(
"/tool-gateway/audit?companyId=company-1&limit=50",
);
});
it("sends bounded activity windows explicitly", async () => {
await toolsApi.listActivity("company-1", { window: "30d", limit: 50 });
expect(mockApi.get).toHaveBeenCalledWith(
"/tool-gateway/audit?companyId=company-1&window=30d&limit=50",
);
});
});
+4 -1
View File
@@ -470,7 +470,10 @@ export const toolsApi = {
if (params.app) search.set("app", params.app);
if (params.agent) search.set("agent", params.agent);
if (params.outcome) search.set("outcome", params.outcome);
if (params.window) search.set("window", params.window);
// Omitting the window is the API's canonical all-time request. This also
// keeps the page usable during a rolling restart against an older server
// that does not recognize the newer explicit `all` value.
if (params.window && params.window !== "all") search.set("window", params.window);
if (params.search) search.set("search", params.search);
if (params.cursor) search.set("cursor", params.cursor);
search.set("limit", String(params.limit ?? 50));
+2 -2
View File
@@ -125,14 +125,14 @@ describe("AuditTab", () => {
});
}
it("renders humanized sentences, the outcome chip, and the footer note", async () => {
it("renders humanized sentences and the outcome chip without the old footer note", async () => {
await render();
expect(container.textContent).toContain("Fable");
expect(container.textContent).toContain("Send Email");
expect(container.textContent).toContain("Gmail");
expect(container.textContent).toContain("Blocked");
expect(container.textContent).toContain("Recorded by Paperclip — entries can't be edited.");
expect(container.textContent).not.toContain("Recorded by Paperclip — entries can't be edited.");
expect(listActivityMock).toHaveBeenCalledWith("company-1", expect.objectContaining({ window: "all" }));
// Vocabulary gate: no raw tool ID or ops terms in the sentence list.
expect(container.textContent).not.toContain("mail:send_email");
-4
View File
@@ -514,10 +514,6 @@ export function AuditTab({ companyId }: { companyId: string }) {
</Button>
</div>
) : null}
<p className="text-xs text-muted-foreground">
Recorded by Paperclip — entries can't be edited. Sensitive values are never stored.
</p>
</div>
);
}