fix(activity): an ad-hoc run's row is one run's, a rollback keeps a run whole, Back reads one entry's filters

- The channel-backfill row says "running" from the runs this process has open, not from the table:
  a row whose outcome failed to write no longer reads as running until a restart. The run still
  going leads the row, so a newer run's outcome never sits under the older one's channel.
- Migration 0109's downgrade carries every run's trigger, spend and start in the audit row, and the
  upgrade restores them: a manual run whose admin was deleted stays manual.
- Back/Forward is read by the page's one popstate listener, both halves in one render; the server
  log adopts its half during that render, so no read goes out with one entry's filters and the
  other's range.
- The server log's failed facets use the other tabs' words (the menus may be short); the accounts
  message shows only when the menu really lacks them.
This commit is contained in:
2026-10-18 17:32:22 +02:00
parent fad656988a
commit 13b7577d9f
12 changed files with 188 additions and 72 deletions
@@ -295,6 +295,14 @@ describe("AdminLogs", () => {
expect((await screen.findByRole("alert")).textContent).toContain("adminLogs.olderFailed");
});
it("facets that failed say the filter menus may be short, in the other tabs' words", async () => {
logsMock.mockResolvedValue({ items: [row(1)], accounts: {}, next_cursor: null });
facetsMock.mockRejectedValue(new Error("500"));
renderConsole();
await waitFor(() => expect(lines()).toHaveLength(1));
expect((await screen.findByRole("alert")).textContent).toContain("activity.filtersFailed");
});
it("offers no older page while a filter change loads", async () => {
let landErrors!: (page: LogPage) => void;
logsMock.mockImplementation((q) =>