test(e2e): cover the two guard-surface gaps found in the full-suite audit
Audit of all 12 e2e specs for the 'green-but-vacuous' class that broke
Grafana's SSO. The suite is otherwise sound (incident-driven, leakage-based);
two real coverage gaps surfaced:
- notebook.franksdank.cloud (open-notebook, deployed 2026-10-19) was a guarded
vhost in NEITHER the 13-/14- GUARDED lists NOR any dedicated spec. A broken
upstream would stay invisible - the exact 17-hermes class. Added to the 14-
guard audit (unauth -> authentik gate, 'Open Notebook' leak marker) plus a
new 21- that proves authenticated reachability to open-notebook's own login
through the guard chain, with a positive app marker.
- prometheus.franksdank.cloud was only ever asserted '<500 and not a login
wall' (13-/11-), which a 404 also passes. New 22- adds the app-is-really-
there proof 20- gives Grafana: SSO handoff + its own /api/v1/status/buildinfo
answers {status:success}.
Both specs wired into the standard project (playwright testMatch), which the
e2e_scaffold bats gate enforces. Verified live against the fleet; full bats
suite green.
This commit is contained in:
1 parent
7d85fed1c9
commit
ab06e4c221
4 files changed
+93
-3
No files matched your search
@@ -0,0 +1,52 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
|
||||
// open-notebook (notebook.franksdank.cloud), deployed 2026-10-19, is a guarded
|
||||
// vhost whose outpost (notebook-proxy) fronts an app with its OWN password
|
||||
// login - the same shape as hermes (17-) and OpenWebUI (18-): the guard chain
|
||||
// (Anubis PoW -> authentik outpost) must hand off to the app, and the app's own
|
||||
// login page is the expected landing. Until now this host appeared in neither
|
||||
// the 13-/14- GUARDED lists nor any dedicated spec, so a broken upstream would
|
||||
// have stayed invisible - the exact 17-hermes "uncovered vhost" failure class.
|
||||
// 14- now covers the unauthenticated gate; this spec owns authenticated
|
||||
// reachability with a POSITIVE app marker, not just "not a login wall".
|
||||
|
||||
const VHOST = "https://notebook.franksdank.cloud/";
|
||||
const CHALLENGE = "Making sure you're not a bot";
|
||||
|
||||
test("notebook vhost reaches the open-notebook app through the guard chain", async ({ page }) => {
|
||||
test.setTimeout(180_000);
|
||||
await page.goto(VHOST);
|
||||
|
||||
// The Anubis proof-of-work clears in a real browser and the outpost hands off
|
||||
// to the app; the user must never be parked on an authentik flow.
|
||||
await expect
|
||||
.poll(async () => !(await page.locator("body").innerText()).includes(CHALLENGE), { timeout: 90_000 })
|
||||
.toBe(true);
|
||||
await expect
|
||||
.poll(() => new URL(page.url()).hostname, { timeout: 60_000 })
|
||||
.toBe("notebook.franksdank.cloud");
|
||||
expect(
|
||||
new URL(page.url()).pathname.startsWith("/if/"),
|
||||
"must not be parked on an authentik flow",
|
||||
).toBe(false);
|
||||
expect(
|
||||
await page.locator('input[name="uidField"]').count(),
|
||||
"must not show the authentik login form",
|
||||
).toBe(0);
|
||||
|
||||
// Positive identity: the page really is open-notebook's own login, not a
|
||||
// Caddy error or the IdP shell. The app answering its own login is the pass.
|
||||
await expect(page, "destination title must be Open Notebook").toHaveTitle(/open notebook/i, {
|
||||
timeout: 30_000,
|
||||
});
|
||||
await expect(page.locator("body"), "open-notebook login marker").toContainText(
|
||||
/enter your password/i,
|
||||
{ timeout: 30_000 },
|
||||
);
|
||||
const body = await page.locator("body").innerText();
|
||||
expect(body, "must not leak the IdP flow shell").not.toContain("Powered by authentik");
|
||||
expect(body, "must not be a Caddy upstream error").not.toContain("Bad Gateway");
|
||||
|
||||
const resp = await page.request.get(VHOST);
|
||||
expect(resp.status(), "open-notebook must answer, not error").toBeLessThan(500);
|
||||
});
|
||||
Reference in new issue
Block a user