Add a per-deployment Matomo tracking scope, defaulting to per-subdomain:
- services.matomo.tracking.scope 'sub' (default) registers one Matomo site per
consumer subdomain with an isolated cookie; 'root' keeps the prior behaviour
of one shared site per registrable base domain with cross-subdomain linking.
- sys-front-inj-matomo derives matomo_site_domain (full host vs registrable
base) and the shared matomo_site_url from it; getSitesId / addSite and the
tracking snippet (setCookieDomain / setDomains / enableCrossDomainLinking) all
follow the scope.
- The matomo Playwright env emits MATOMO_TRACKING_SCOPE; the SitesManager test
matches the consumer's full host in 'sub' and its base domain in 'root'.
- variants.yml variant 0 sets scope=root so the matrix exercises both flavours
(every other deploy runs the sub default).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Break the single 457-line playwright.spec.js into topic files discovered by the
harness testMatch "**/*.@(spec|test).js", mirroring the pihole / gitea layout:
- _shared.js env vars, the setup hook, loginAsAdmin, attachDiagnostics,
hostOf / baseDomainOf and the MATOMO_TARGET_ROLES_JSON list
- playwright.spec.js CSP + canonical-domain smoke (filename kept; harness asserts it)
- auth.spec.js admin login/logout and biber denied at the admin surface
- tracking.spec.js SitesManager site registration and per-consumer _paq injection
- persona-flows.spec.js guest / biber / admin universal-logout flows
Test logic is unchanged: same titles, selectors, regexes, timeouts and
assertions (verified by title parity and an adversarial diff against HEAD). The
only behavioural delta is that the extracted loginAsAdmin waits for the username
field to be visible before filling, which the SitesManager login previously
skipped (hardening only). The duplicated admin-login form-fill and the old
beforeEach are now the shared loginAsAdmin and setupMatomoPage.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>