3d8a256d52
Auth.js v5 manages token.jti internally and overwrites it after the jwt callback. Storing our session UUID in token.sid ensures the value we persist in active_sessions matches what the signed cookie carries. - jwt callback: token.sid = jti (was token.jti) - session callback: read from token.sid - signOut event: falls back to token.jti for backward compat with any sessions created before this change Also adds Playwright dev-system test suite (playwright.dev.config.ts + e2e/dev-system/) that validates login, session registry health, and RBAC enforcement against the running localhost:3100 dev server. Co-Authored-By: claude-flow <ruv@ruv.net>
46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
import { expect, type Page } from "@playwright/test";
|
|
|
|
/** Dev-system credentials — these exist in the planarchy.dev seed data */
|
|
export const DEV_USERS = {
|
|
admin: { email: "admin@planarchy.dev", password: "admin123" },
|
|
manager: { email: "manager@planarchy.dev", password: "manager123" },
|
|
viewer: { email: "viewer@planarchy.dev", password: "viewer123" },
|
|
} as const;
|
|
|
|
export async function signIn(page: Page, email: string, password: string) {
|
|
await page.goto("/auth/signin");
|
|
await page.fill('input[type="email"]', email);
|
|
await page.fill('input[type="password"]', password);
|
|
await page.click('button[type="submit"]');
|
|
await expect(page).toHaveURL(/\/(dashboard|resources)/, { timeout: 15000 });
|
|
}
|
|
|
|
export async function signOut(page: Page) {
|
|
await page.goto("/auth/signout");
|
|
// Wait for redirect back to signin
|
|
await page.waitForURL(/\/auth\/signin/, { timeout: 10000 });
|
|
}
|
|
|
|
/**
|
|
* Intercept all tRPC batch responses and assert none return HTTP 401.
|
|
* Returns a list of intercepted tRPC paths that were called.
|
|
*/
|
|
export async function assertNoTrpc401s(page: Page, action: () => Promise<void>) {
|
|
const failures: string[] = [];
|
|
|
|
page.on("response", (response) => {
|
|
if (response.url().includes("/api/trpc/") && response.status() === 401) {
|
|
const url = new URL(response.url());
|
|
failures.push(url.pathname + url.search.slice(0, 80));
|
|
}
|
|
});
|
|
|
|
await action();
|
|
|
|
if (failures.length > 0) {
|
|
throw new Error(
|
|
`tRPC 401 responses detected (session registry / auth broken):\n${failures.join("\n")}`,
|
|
);
|
|
}
|
|
}
|