Files
computer-playbook/docs/requirements/018-playwright-ldap-coverage.md
T
kevinveenbirkenbachandClaude Opus 4.7 16bdbf03d7 docs: fix repo-wide drift against documentation.md style rules
Three classes of drift cleaned up across 85 .md files:

- Em-dashes: replaced ` — ` with the contextually correct separator
  (colon for `term: explanation`, period to split clauses across
  sentences/source lines, parentheses for asides, semicolon for
  tight-linked continuations). Two intentional exceptions remain
  in `docs/contributing/documentation.md` (the rule literal) and
  inside a fenced ```sh block in `docs/contributing/actions/debugging/ci.md`.
- SPOT self-labels: rewrote "This is the SPOT for X" to describe
  the subject directly ("This directory holds X" / "This file
  describes X"). Cross-references to other artefacts' canonical
  role remain unchanged.
- Heading-emoji position: moved leading-emoji headings (`# 🧩 Title`)
  to trailing position (`# Title 🧩`) per the headline rule that
  emojis MUST come after the title text.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 20:12:07 +02:00

8.6 KiB

018 - Playwright LDAP authentication coverage

User Story

As a contributor maintaining the per-role Playwright suite, I want every role whose meta/services.yml declares ldap.enabled (literal true or the dynamic "{{ 'svc-db-openldap' in group_names }}" form) to ship a Playwright scenario that exercises the LDAP-bind login path end-to-end, so that the LDAP variant of the role's authentication stack is verified independently from its OIDC counterpart.

Context

006 - Service-gated Playwright tests established the skipUnlessServiceEnabled(<service>) contract: scenarios gate on <SERVICE>_SERVICE_ENABLED flags so a deploy with SERVICES_DISABLED=<service> reports skipped instead of failed. 004 - Generic RBAC auto-provisioning plus 017 - Biber RBAC coverage extend that contract to RBAC-aware non-admin scenarios.

Today most role specs gate their authenticated scenarios on oidc only, even when the role's meta/services.yml also declares ldap.enabled and a dedicated LDAP auth plugin / driver is wired in. Consequence: a deploy with SERVICES_DISABLED=oidc (LDAP-only mode) makes every authenticated scenario skip, leaving the LDAP path untested. The matrix-deploy variant lists in meta/variants.yml typically include an LDAP-only variant exactly to exercise that branch (see e.g. web-app-opencloud/meta/variants.yml where variant 1 sets ldap.enabled: true with oidc.enabled: false), but the corresponding spec scenario does not exist yet.

web-app-opencloud is the trigger role for this requirement: its services.yml was migrated to the dynamic-flag form for ldap.enabled, both variants pin the LDAP branch on, but files/playwright.spec.js has only test.skip(!oidcEnabled, …) gates. Closing the gap consistently across the role tree is what this requirement tracks.

Acceptance Criteria

Policy

  • Any role whose meta/services.yml declares ldap.enabled (literal true or the dynamic "{{ 'svc-db-openldap' in group_names }}" form per test_dynamic_flags.py) AND ships an authenticated Playwright spec MUST include at least one scenario that drives the role's LDAP-bind login path end-to-end. The test MUST NOT route through Keycloak: it MUST hit whatever in-app LDAP auth surface the role exposes (Joomla core LDAP plugin, Jenkins LDAP security realm, OpenCloud LDAP basic-auth driver, Mattermost AD/LDAP login, etc.).
  • The LDAP scenario MUST be gated via skipUnlessServiceEnabled('ldap') so a deploy with SERVICES_DISABLED=ldap reports the scenario as skipped: LDAP_SERVICE_ENABLED=false, never failed.
  • A role that ships BOTH oidc.enabled and ldap.enabled scenarios MUST keep them as separate test bodies. Combining the two flags in a single scenario is forbidden. The matrix-deploy variants exist precisely to drive each branch in isolation, and bundling them defeats the variant matrix.
  • The LDAP scenario MUST exercise BOTH the canonical admin user and the canonical non-admin RBAC user biber (per 017). A role that only asserts the admin path under LDAP MUST flag the biber follow-up in its README until it is added.
  • LDAP-driven persona scenarios MUST live INSIDE the persona bodies named biber: <flow> and administrator: <flow> per 019 Rule 3; the per-persona LDAP gate is added via a separate skipUnlessServiceEnabled('ldap') call inside the existing persona body, not as a parallel ungated test. The persona-naming lint test_naming.py is the role-closure gate; an additional ungated ldap login test next to the personas is forbidden by 019 Rule 5.

Env contract

  • If the spec needs to know whether LDAP is enabled at runtime, it MUST read the LDAP_SERVICE_ENABLED flag exclusively through the service-gating.js helper from 006. Direct process.env.LDAP_SERVICE_ENABLED reads in the spec are forbidden.
  • No role MAY ship a role-local <ROLE>_LDAP_ENABLED env key as a workaround for the helper. The test_playwright_env_keys_used.py lint MUST stay green: any custom flag that survives must be consumed by the spec, otherwise it is dead config.

Per-role audit

The list below was produced by grepping each role's meta/services.yml for an ldap block with enabled set to something other than false. Each checkbox MUST be closed by reading the spec end to end, deciding whether the role exposes a test-drivable LDAP auth surface, and then either adding the LDAP scenario OR documenting in the commit message why the role is exempt (e.g. the LDAP integration is consumer-side only, with no Playwright- reachable login UI).

In-scope: LDAP scenario MUST be added

Out of scope: no LDAP scenario

The following declare an LDAP block but legitimately do not expose a test-drivable LDAP login surface (consumer-side only, infrastructural, or already covered by their own service-level test). Closing each item is a NOOP unless a stale env key shows up.

  • web-app-keycloak: IS the OIDC provider; LDAP federation is tested via Keycloak's own user-storage spec, not via a per-role Playwright surface.
  • web-app-fusiondirectory: IS the LDAP admin UI; its admin login already covers the LDAP bind path by construction.
  • svc-db-openldap: backend service with no end-user UI; covered by integration tests, not Playwright.

Verification

  • After every role-local change test_playwright_env_keys_used.py MUST stay green.
  • A run with SERVICES_DISABLED=oidc (LDAP-only mode) MUST produce at least one passed LDAP scenario per role marked above as in-scope, never an empty-skip pass.
  • A run with SERVICES_DISABLED=ldap MUST report every LDAP scenario as skipped: LDAP_SERVICE_ENABLED=false, never failed.
  • A grep process.env\.LDAP_SERVICE_ENABLED over the spec tree (excluding roles/test-e2e-playwright/files/service-gating.js) MUST return zero hits, proving every spec routes its LDAP gate through the helper rather than reading the flag directly.

See Also