Over Tor the redirect chain behind a login/logout/OIDC click routinely exceeds Playwright's fixed 30s action timeout, so the click throws before the flow's scaled waits run. Sweep all role Playwright suites and the shared persona helpers: give every navigation/auth-transition click an onion-scaled timeout (.click({ timeout: resolveTimeout(30_000) })) and route the remaining raw millisecond literals (timeout options, waitForTimeout, sleep-promise setTimeout, positional wait args) through resolveTimeout. Local UI clicks (menus, toggles, modal dismissals, DOM clicks inside evaluate) stay untouched.
Two new lints keep it that way: test_no_raw_timeout_literals forbids raw numeric timeout literals in Playwright specs (opt-out: nocheck: raw-timeout), test_persona_clicks_scaled requires every click in the shared persona auth flows to carry a resolveTimeout timeout (opt-out: nocheck: unscaled-click).
Verified: node --check on all 133 changed JS files, all 13 playwright lints green, make autoformat clean, make test green (2745+196+163+4 tests OK).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SeaweedFS is a server-side S3 backend for its consumers; only the
filer/master admin UIs are browser-facing. Split them into a `frontend`
service that stays off on onion nodes ('svc-net-tor' in group_names):
- frontend disabled: no nginx proxy container, no filer/master vhosts,
no oauth2 SSO sidecar; the S3 API vhost is unaffected
- stale filer/master vhosts from earlier frontend-enabled deploys are
removed so the site-wide CSP health probe stops hitting dead domains
- csp_skip_domains additionally skips canonicals a disabled service
declares via services.<name>.domains (defense in depth)
- UI personas (admin/biber/guest/storage-buckets) gate on the
FRONTEND_SERVICE_ENABLED flag; tor variants dropped (backend role)
Verified on the onion node: 4/4 UI specs skip, S3 API reachable, CSP
health check green, matrix S3 media consumer unaffected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the global TIMEOUT_FACTOR and a shared timeouts.js helper: resolveTimeout(base) scales by TIMEOUT_FACTOR and, over a .onion target, an extra multiplier, so Tor's per-request latency no longer trips hard-coded timeouts. Migrate every raw timeout in the specs (timeout:/timeout=/setTimeout/waitForTimeout) to resolveTimeout, stage the helper in all three staging paths, and add test_no_raw_timeouts to forbid raw numeric timeouts. Clearnet behaviour is unchanged (factor 1: resolveTimeout(N) === N).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Three deploy-validated fixes for the oauth2-gated Filer/Master UIs: (1) make filer the primary canonical domain so the oauth2-proxy redirect_url/callback lands on a gated domain instead of the ungated S3 api host; (2) point the sso-proxy upstream at the unique container name seaweedfs-proxy (and give the nginx proxy that hostname) so it no longer resolves a foreign app's generic 'proxy' container over a shared network, which had round-robined admin traffic to nextcloud; (3) decode the playwright env via the shared decodeDotenvQuotedValue so the administrator password's escaped characters are read correctly.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a database-style object-store abstraction: the objstore lookup resolves the active engine (seaweedfs|minio) per consumer and yields a uniform S3 payload, objstore_secret_key is auto-generated like database_password, sys-svc-objstore delegates per-consumer provisioning to the resolved provider's objstore_init entrypoint (lazy-loading the provider when it was not preloaded), and compose/network/volume plumbing supports both a shared central instance and an embedded storage-only instance per consumer.
Add the web-app-seaweedfs provider role: Filer and Master UIs behind the admin-only oauth2-proxy via a role-local nginx and proxy.conf.j2 (S3 API domain stays ungated, admin UIs deny with 403 when SSO is disabled), per-consumer S3 identities from s3.json, idempotent bucket provisioning via weed shell, a /24 on the central-provider subnet range, Playwright coverage for admin/biber/guest plus consumer bucket existence, and unit tests for the objstore lookup and the per-engine compose volumes.
Mark web-app-minio lifecycle: unsupported, move its mc client image into a dedicated services.client entry, align it with the objstore credential contract, and make its consumer provisioning idempotent.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>