6f9142027 gave twelve consumer specs the onion skip that nextcloud already
carried, and mastodon is the one it missed. `git show 6f9142027 --stat` names no
mastodon file, and no commit on any ref ever added the gate to the role:
`git log --all -S'isOnionTarget' -- roles/web-app-mastodon/` is empty. Measured
before this change, the role reported 0 occurrences of isOnionTarget while
matrix, nextcloud and taiga reported 2 each; thirteen roles carried the skip,
now fourteen do.
The gap is not cosmetic, because the gate the spec did have guards the wrong
thing. skipUnlessServiceEnabled("seaweedfs") asks about the BACKEND service,
which is enabled on a Tor node; the filer's browser surface is not. The spec
therefore ran, and adminLoginFiler navigated to the clearnet filer host. On a
node whose Tor network is a private chutney instance with no clearnet exit that
host does not answer 404 -- it hangs, and Playwright reported net::ERR_TIMED_OUT.
The skip has to come before the backend gate for that reason, which is where the
thirteen siblings put it and where this change puts it. The message string is
byte-identical to theirs.
Not verified by a run: what is proven is the parity with thirteen siblings and
the domain derivation in timeouts.js:15-17, not an observed skip.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
75 commits: the socialhome role reimplemented against the project it actually
deploys, native-login specs for funkwhale and shopware, a window.open IdP
handoff and a settings-link fallback in the shared persona helpers, a swarm
converge budget that gives up on a terminal task, and a long tail of role
fixes.
Eleven conflicts. The shared persona helpers (keycloak.js, logout.js) take the
incoming structure — they gained real behaviour this branch never had — with
this branch's resolveTimeout convention re-applied over it and
confirmKeycloakLogoutIfPrompted re-attached at every return point; without it
the Keycloak SSO session outlives the logout. playwright.config.js keeps this
branch's version: both sides set actionTimeout, but ours routes through an env
var and 15s is too short behind an onion. socialhome's spec takes the incoming
content — 2dbd6eb10 found the role described the wrong upstream project
entirely — and keeps gotoOnion and expectHstsWhenTls, since demanding HSTS over
a plaintext onion is a false failure. Both READMEs were regenerated rather than
merged by hand.
Three collisions arrived with no conflict marker at all, because each side
changed a different place in a different file:
- group_vars/all/18_swarm.yml declared swarm_stack_converge_retries twice.
Same value, so nothing breaks today; editing the documented one would have
silently changed nothing.
- svc-net-tor and web-app-socialhome both claimed 192.168.74.0/24. Socialhome,
the newer role, moves to 192.168.75.0/24.
- web-app-socialhome/meta/schema.yml arrived as a new file, so ef5ea7cb5's
rename never saw it. Its credential would not have resolved and the role
would have deployed with an unusable administrator account.
The incoming specs also needed this branch's conventions: raw timeouts wrapped,
four page.goto calls routed through gotoOnion, a request.get given an
onion-aware timeout, and 21 roles marked playwright-service-flag over the tor
block this branch added to them.
make quality green on the merge result.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The scenario never authenticated. It went to /auth/sign_in and then only
checked whether the URL had reached openid-connect/auth, on the assumption
that OMNIAUTH_ONLY=true makes Mastodon redirect into the OIDC chain. It does
not — Mastodon renders its own login page carrying an /auth/auth/openid_connect
link, so the condition was always false, performKeycloakLogin never ran, and
the run continued unauthenticated until it failed 1.5 min later on a missing
avatar input.
Route through clickOidcLoginLink first, exactly as personas/admin.js does; its
provider-shaped selector matches Mastodon's link. The persona logout tests on
this same role were already green through that helper — the spec had bypassed
it and rebuilt the condition by hand.
With the login repaired, a second defect surfaced behind it: newer Mastodon
moved profile editing to /profile/edit and left /settings/profile as a notice
page with no avatar input. Follow the pointer link when it is present, so the
spec still works against older builds.
Both causes come from the Playwright error-context snapshots, not from reading
the code: the first showed Mastodon's login page, the second the logged-in
settings navigation plus the relocation notice.
Verified: make compose-playwright role=web-app-mastodon pw="--grep seaweedfs"
=> 1 passed (30.3s), previously 3 x 1.5 min timeout. The check uploads and then
polls the Filer UI until a new bucket object appears, so Mastodon -> SeaweedFS
is proven end to end.
Also drops the file-header paragraph, whose OMNIAUTH_ONLY claim was the false
premise the broken conditional was built on.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The role's env template shipped no persona flags, so both authenticated
personas ran unconditionally. Every CI variant is deployed, and variant 1 pins
services.sso.enabled false -- there the administrator has nothing to log into:
tasks/05_administrator.yml creates the account with `tootctl accounts create`,
which neither sets nor returns a password, so ADMIN_PASSWORD (the Keycloak
secret) cannot drive Mastodon's native /auth/sign_in. biber is worse off: no
Mastodon account is provisioned for him at all, and the OIDC sign-in wired at
templates/env.j2:61-72 is the only path that would create one. Both flags now
follow services.sso.enabled, in the same ternary web-app-baserow already uses.
files/playwright/test-seaweedfs.js gated only on seaweedfs, but it drives the
same admin journey -- Keycloak sign-in, /settings/profile, avatar upload.
services.sso.enabled and services.seaweedfs.enabled are independent
group-membership expressions, so an inventory carrying seaweedfs without
keycloak was a hard failure. It now skips when the administrator persona is
blocked.
meta/services.yml carried `# nocheck: playwright-service-flag — object store,
no Playwright surface` above the seaweedfs key. The commit that added
test-seaweedfs.js made that false, and the suppression was dead anyway: the env
template declares SEAWEEDFS_SERVICE_ENABLED, so test_env_services_match never
needed an exemption. Deleted rather than reworded.
Two nocheck rationales asserted things that are not true: that mail delivery is
"covered by the sys-svc-mail integration tests" -- no such tests exist, the
coverage is web-app-mailu's own spec -- and that the shared CSP helper asserts
the CSS injector's origin, which personas/utils/csp.js:96 refutes with
`if (!host) continue` since no consumer role renders CSS_BASE_URL.
Not verified: test-seaweedfs.js has still never run against a live stack. Its
selectors were authored against upstream Mastodon's UI without execution; the
new guard only keeps it out of the variant where it could not pass, and says
nothing about whether it passes in the variant where it now runs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
test_has_spec.py forces every roles/web-app-* to ship a Playwright spec and
calls a missing one a hard error, because the persona contract must never be
silently absent from the deploy capstone. Nothing forced the other half. The
runner discovers roles by rglob('templates/playwright.env.j2')
(discover_playwright_roles.py:53), so a spec without that file is staged
nowhere and executed never.
21 of 76 web-app roles were in exactly that state. Verified rather than
inferred: running the discovery filter directly returns 61 roles and none of
the 21 is among them, `make compose-playwright` refuses without a rendered
.env from a prior deploy, and `git log --all` on those paths shows the file
never existed on any branch -- the single hit is web-app-gitlab on a fork
branch. Their specs have never run once. 15 of the 21 deploy in CI today,
reporting green while their only functional verification never fires.
The new lint mirrors test_has_spec and carries a per-role opt-out that is
used nowhere: uniform beats exceptions.
Every one of the 21 now has a template written against its own
meta/services.yml rather than a shared skeleton -- espocrm splits
ADMIN_PASSWORD from ADMIN_NATIVE_PASSWORD because OIDC_ALLOW_ADMIN_USER
leaves both login paths open, the four permanently auth-less roles declare
their personas blocked instead of shipping a knowingly-red spec, and
web-app-mastodon gained a real test-seaweedfs.js because no honest
suppression existed for a role that does route Paperclip to S3.
web-app-magento moves pre-alpha -> alpha here: it now has a spec that runs,
which is what the lifecycle gate is about.
Six meta/services.yml files change only where adding a template falsified an
existing suppression -- gitlab and shopware both claimed the role 'ships no
templates/playwright.env.j2', which stopped being true in this commit.
Not resolved here, and the adversarial review says so plainly: the specs are
enabled, not proven. None has executed against a live stack. The review found
three classes of defect that land in follow-up commits rather than being
smuggled in silently -- persona blocks that are missing or should be tied to
sso.enabled, eleven suppressions naming a sys-svc-mail test suite that does
not exist, and eight claiming a CSP assertion that cannot fire because no
consumer role renders CSS_BASE_URL.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>