Files
computer-playbook/roles/web-app-bluesky/files/playwright/test-biber-persona.js
kevinveenbirkenbachandClaude Opus 4.7 e331951efc feat(web-app-bluesky): native admin login when oauth2 is disabled + spec split
Bridge the architectural gap that left bluesky without any usable login
path when services.oauth2.enabled is false. The login-broker stays the
upstream when OIDC is on (broker auto-provisions PDS accounts via the
encrypted-app-password handoff). When OIDC is off, the broker is bypassed
and the stock social-app is served directly; the PDS administrator is
provisioned by Ansible so the operator can sign in with handle+password.

Routing (tasks/01_core.yml):
- Front-proxy http_port now picks `BLUESKY_BROKER_PORT` when
  services.oauth2.enabled is true, `BLUESKY_WEB_PORT` (social-app)
  otherwise. Previously the broker was always upstream, so variant-1
  deploys returned a `Refusing handoff` 401 on every request.

PDS provisioning (tasks/07_native_admin.yml, new):
- uri_retry waits on PDS `/xrpc/_health`, then POSTs createAccount with
  `kc-administrator.<handle-domain>` (PDS rejects bare `administrator`
  as a reserved handle, hence the `kc-` prefix the broker already uses
  for OIDC-derived accounts).
- Idempotent: 200 = changed, 400 with "Handle already taken" = ok.
- Gated on `BLUESKY_WEB_ENABLED and not services.oauth2.enabled`.

Broker hardening (files/login-broker/server.js):
- 401 response (missing `X-Forwarded-User`) now `text/html` instead of
  `text/plain`. Headless Chromium does not fire `DOMContentLoaded`
  reliably on non-HTML 401 documents — Playwright `page.goto(...,
  { waitUntil: "domcontentloaded" })` hung the full 60s test timeout in
  the variant-1 guest-persona test.

Playwright spec (files/playwright/):
- Split single-file playwright.spec.js (203 lines) into _shared.js +
  seven test-*.js modules following the matrix/taiga/nextcloud/pixelfed
  pattern. Each scenario is now individually grep-able from the
  reporter output.
- Add test-native-admin.js: verifies broker bypass (landing body
  contains `<title>Bluesky</title>`, NOT `Refusing handoff`) plus PDS
  createSession returns 200 + accessJwt for the deployed admin handle.
  Uses Playwright's APIRequestContext directly — driving the stock
  social-app login UI (hosting-provider switcher + welcome modal +
  React form state) was too brittle.

Vars + env (vars/main.yml, templates/playwright.env.j2):
- `BLUESKY_ADMIN_HANDLE` and `BLUESKY_PDS_INTERNAL_URL` added for the
  Ansible task.
- `ADMIN_HANDLE` and `PDS_BASE_URL` exposed to Playwright env.

Verification:
- Variant 1 (live, in-container): 3 passed, 4 skipped, 0 failed.
- Variant 0 / Variant 2: spec bodies unchanged from pre-refactor,
  Ansible conditional invariant on the OIDC-on branch — but not
  re-deployed for live verification.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:13:08 +02:00

8 lines
196 B
JavaScript

const { test } = require("@playwright/test");
exports.register = function (shared) {
test("biber: app → universal logout", async ({ page }) => {
await shared.runBiberFlow(page);
});
};