feat: consolidate database management work

Add catalog-owned logical relationships and runtime snapshots, extend the database-management UI and validation coverage, and document the updated operational workflow.

Keep active sensitive-generation status in a tooltip and indicator, and update the layout E2E to follow the history action in its new database-scoped location.
This commit is contained in:
Codex
2026-09-01 14:46:55 +02:00
parent f586152636
commit 076c9742c5
73 changed files with 6966 additions and 610 deletions
@@ -16,7 +16,7 @@ const regularUser: AuthenticatedUser = {
};
const adminUser: AuthenticatedUser = {
...regularUser, subject: "alice-id", roles: ["admin"] as const,
permissions: ["session.use", "session.read_all", "pi.manage"] as const, isAdmin: true,
permissions: ["session.use", "session.read_all", "workspace.manage", "workspace.secrets.manage", "database.manage", "pi.manage"] as const, isAdmin: true,
};
function wrap(user: AuthenticatedUser = regularUser) {
@@ -95,7 +95,8 @@ test("regular users load only their sessions and never see administrator control
wrap();
await screen.findByText("Attiva uno");
expect(scope).toBe("mine");
expect(screen.queryByRole("button", { name: "All sessions" })).not.toBeInTheDocument();
expect(screen.queryByRole("button", { name: "Administration" })).not.toBeInTheDocument();
expect(screen.queryByRole("tab", { name: "All sessions" })).not.toBeInTheDocument();
expect(screen.queryByText(/administrator view/i)).not.toBeInTheDocument();
});
@@ -115,17 +116,25 @@ test("Pi management preserves the open session summary and the model activity ti
http.post("/api/sessions/:id/resume", () => resumeResult("s1")),
http.get("/api/sessions/:id", () => HttpResponse.json({ phase: 4 })),
);
wrap();
wrap(adminUser);
await user.click(await screen.findByText("Attiva uno"));
expect(await screen.findByRole("complementary", { name: "Session summary" })).toHaveTextContent("Domanda originale");
await user.click(screen.getByRole("button", { name: "Administration" }));
await user.click(screen.getByRole("button", { name: "Pi management" }));
expect(await screen.findByRole("heading", { name: "Pi management" })).toBeVisible();
const dialog = screen.getByRole("dialog", { name: "Pi management" });
const workArea = screen.getByTestId("conversation-column");
const sessionNavigation = screen.getByRole("complementary", { name: "Session navigation" });
const piManagement = within(sessionNavigation).getByRole("button", { name: "Pi management" });
const newSession = within(sessionNavigation).getByRole("button", { name: "New session" });
expect(workArea).toContainElement(dialog);
expect(sessionNavigation).not.toContainElement(dialog);
expect(piManagement).toHaveAttribute("aria-current", "page");
expect(piManagement).toHaveAttribute("aria-expanded", "true");
expect(piManagement).toHaveAttribute("data-navigation-state", "current");
expect(newSession).toHaveAttribute("data-navigation-state", "available");
expect(newSession).not.toHaveAttribute("aria-current");
const preservedSummary = screen.getByRole("complementary", { name: "Session summary" });
expect(preservedSummary).not.toHaveAttribute("aria-hidden", "true");
expect(preservedSummary).toHaveTextContent("Attiva uno");
@@ -133,6 +142,10 @@ test("Pi management preserves the open session summary and the model activity ti
await waitFor(() => {
expect(screen.getByRole("complementary", { name: "Session summary" })).toHaveTextContent("Domanda originale");
});
expect(newSession).toHaveAttribute("aria-current", "page");
expect(newSession).toHaveAttribute("data-navigation-state", "current");
expect(piManagement).toHaveAttribute("aria-expanded", "false");
expect(piManagement).toHaveAttribute("data-navigation-state", "available");
await user.click(screen.getByRole("button", { name: "Resume" }));
await screen.findByRole("button", { name: "Show model activity" });
@@ -160,17 +173,66 @@ test("administrators can explicitly switch to all sessions and see owners", asyn
}),
);
wrap(adminUser);
await screen.findByRole("button", { name: "All sessions" });
expect(screen.getByRole("button", { name: "My sessions" })).toHaveAttribute("aria-pressed", "true");
expect(screen.getByRole("button", { name: "All sessions" })).toHaveAttribute("aria-pressed", "false");
await userEvent.click(screen.getByRole("button", { name: "All sessions" }));
const tablist = await screen.findByRole("tablist", { name: "Session scope" });
const mySessions = within(tablist).getByRole("tab", { name: "My sessions" });
const allSessions = within(tablist).getByRole("tab", { name: "All sessions" });
expect(mySessions).toHaveAttribute("aria-selected", "true");
expect(mySessions).toHaveAttribute("aria-controls", "session-scope-panel");
expect(mySessions).toHaveAttribute("tabindex", "0");
expect(mySessions).toHaveAttribute("data-tab-state", "active");
expect(mySessions).toHaveClass("bg-[oklch(var(--nav-active))]");
expect(allSessions).toHaveAttribute("aria-selected", "false");
expect(allSessions).toHaveAttribute("aria-controls", "session-scope-panel");
expect(allSessions).toHaveAttribute("tabindex", "-1");
expect(allSessions).toHaveAttribute("data-tab-state", "inactive");
expect(allSessions).toHaveClass("border-border", "bg-card");
expect(allSessions).not.toHaveClass("border-transparent", "bg-transparent");
expect(screen.getByRole("tabpanel")).toHaveAttribute("aria-labelledby", "session-scope-mine-tab");
await userEvent.click(allSessions);
await waitFor(() => expect(scope).toBe("all"));
expect(screen.getByRole("button", { name: "My sessions" })).toHaveAttribute("aria-pressed", "false");
expect(screen.getByRole("button", { name: "All sessions" })).toHaveAttribute("aria-pressed", "true");
expect(mySessions).toHaveAttribute("aria-selected", "false");
expect(mySessions).toHaveAttribute("data-tab-state", "inactive");
expect(allSessions).toHaveAttribute("aria-selected", "true");
expect(allSessions).toHaveAttribute("data-tab-state", "active");
expect(allSessions).toHaveClass("bg-[oklch(var(--nav-active))]");
expect(screen.getByRole("tabpanel")).toHaveAttribute("aria-labelledby", "session-scope-all-tab");
expect(await screen.findByText("Administrator view: all sessions")).toBeInTheDocument();
expect(screen.getByText("Owner: Bob")).toBeInTheDocument();
});
test("session scope tabs support roving keyboard navigation", async () => {
let scope = "";
server.use(http.get("/api/sessions", ({ request }) => {
scope = new URL(request.url).searchParams.get("scope") ?? "";
return HttpResponse.json(LIST);
}));
wrap(adminUser);
const user = userEvent.setup();
const tablist = await screen.findByRole("tablist", { name: "Session scope" });
const mySessions = within(tablist).getByRole("tab", { name: "My sessions" });
const allSessions = within(tablist).getByRole("tab", { name: "All sessions" });
mySessions.focus();
await user.keyboard("{ArrowRight}");
await waitFor(() => expect(scope).toBe("all"));
expect(allSessions).toHaveFocus();
expect(allSessions).toHaveAttribute("aria-selected", "true");
expect(mySessions).toHaveAttribute("tabindex", "-1");
await user.keyboard("{ArrowLeft}");
await waitFor(() => expect(scope).toBe("mine"));
expect(mySessions).toHaveFocus();
expect(mySessions).toHaveAttribute("aria-selected", "true");
await user.keyboard("{End}");
expect(allSessions).toHaveFocus();
expect(allSessions).toHaveAttribute("aria-selected", "true");
await user.keyboard("{Home}");
expect(mySessions).toHaveFocus();
expect(mySessions).toHaveAttribute("aria-selected", "true");
});
test("administrator confirms before deleting a same-named user's session", async () => {
let deletes = 0;
server.use(
@@ -187,7 +249,7 @@ test("administrator confirms before deleting a same-named user's session", async
}),
);
wrap(adminUser);
await userEvent.click(await screen.findByRole("button", { name: "All sessions" }));
await userEvent.click(await screen.findByRole("tab", { name: "All sessions" }));
await screen.findByText("Owner: Alice");
await userEvent.click(screen.getByRole("checkbox", { name: "Select Attiva uno" }));
await userEvent.click(screen.getByRole("button", { name: "Delete 1 selected sessions" }));
@@ -213,7 +275,7 @@ test("administrator confirms before archiving a same-named user's session", asyn
}),
);
wrap(adminUser);
await userEvent.click(await screen.findByRole("button", { name: "All sessions" }));
await userEvent.click(await screen.findByRole("tab", { name: "All sessions" }));
await screen.findByText("Owner: Alice");
await userEvent.click(screen.getByRole("button", { name: "Session actions" }));
await userEvent.click(await screen.findByText("Archive"));