Commit Graph
662 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 5.5 eb36a54c44 perf(sys-svc-compose-ca): stop probing images on the swarm no-wrapper path
render_override gathered the metadata of every image (docker image inspect, a pull when missing, a docker run probe) before it checked wrap, and the swarm handler's --no-wrapper path threw the result away, because image_meta is read only behind 'if not wrap: continue'. The gather now runs only when wrap is true, so the swarm override is unchanged byte for byte. It pulled again the externals that registry_sync had just removed (WordPress#0 run 41303726270: 275 s over 64 calls).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 16:14:01 +01:00
kevinveenbirkenbachandClaude Opus 5.5 e66c635fb6 perf(sys-svc-container): roll a single-replica swarm service without a stagger delay
swarmkit sleeps update_config.delay after the last slot too and then monitors for delay + 1s, so a one-replica service paid about 21 s per rollout for nothing to stagger (database stacks converged in 32 s instead of 8 s in WordPress#0's update pass of run 41303726270, about 400 s per row). A service whose replicas line is 'replicas: 1' now rolls with delay 0s; several replicas keep service_update_delay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 12:45:15 +01:00
kevinveenbirkenbachandClaude Opus 5.5 d6151aa559 fix(web-app-bigbluebutton): publish every container port once, on the proxy's upstream host
BBB's upstream compose template publishes nginx's 48081/48082/48087 on 127.0.0.1 and on 10.7.7.1. On Arch, Docker's nftables backend with the userland proxy off writes one identical 'MASQ TO OWN PORT' rule per binding and the second fails with 'rule exists' (moby 60109b06fb, PR #54031, first released in 29.10.0), so compose up failed in Moodle#3 of run 41303726270. compose_mods keeps only bindings on services.bigbluebutton.upstream_host or without a host address; nothing in the platform uses the loopback ones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 12:34:22 +01:00
kevinveenbirkenbachandClaude Opus 5.5 486d85c29f perf(web-app-docs): claim a build only for a free slot and skip current translations
The builder handed every queued marker straight to its worker pool, whose own FIFO let a background latest build run ahead of the deployed:de build a visitor waited on (40-81 min in docs#1 of run 41303726270). A marker is now claimed only while a slot is free. build_language dequeues a translation that is already current instead of rebuilding it for 2-3 h on a duplicate request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 12:31:03 +01:00
kevinveenbirkenbachandClaude Opus 5.5 4f20a57a7e fix(web-app-docs): look at the shared volume again before answering 'Building'
On the swarm NFS volume a docs replica keeps a failed lookup until the parent's cached attributes expire, so a site another replica just renamed into place stayed invisible to it and it served the 202 'Building' page (lang en) after a sibling had answered 200 (docs#1 of run 41303726270). recheck_servable() lists the parent to force close-to-open revalidation and is called only on the path that would answer 202; ordinary page requests pay nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 12:27:05 +01:00
kevinveenbirkenbachandClaude Opus 5.5 cfc8cbb8fe fix(web-app-wazuh): give the manager room for the vulnerability feed and name failing API calls
At 2g the vulnerability-detection feed update thrashed the manager cgroup until the kernel OOM-killed wazuh-modulesd; Wazuh restarts no daemon, so the API answered every call with HTTP 500 (error 1017) and the API administrator grant failed in the update pass of run 41303726270 (Wazuh#1, swarm). The manager gets mem_limit 4g, and api_administrators.py raises '<METHOD> <path> answered HTTP <code>: <body>' instead of a bare 500 so a dead daemon shows up by name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 12:23:53 +01:00
kevinveenbirkenbachandClaude Opus 5.5 23c3da94cd Merge the ERPNext standard price lists into staging/alphaserver
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 17:28:07 +01:00
kevinveenbirkenbachandClaude Opus 5.5 a394d4bf6b fix(svc-net-wireguard): dial every endpoint at the IPv4 address it resolves to
The mesh is IPv4 only (60-byte header, IPv4 pools), yet wg.conf handed
wg the endpoint name, and wg dials the first getaddrinfo answer, an AAAA
on a dual-stack name. A host with broken IPv6 then never handshook
(alphaserver, 2026-11-01). Resolve every dialled endpoint with getent
ahostsv4 on the dialling host, render that literal, measure the path MTU
against it, and fail before rendering when a name has no IPv4 address.
Also set the tunnel MTU on a live interface, since wg syncconf drops it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 16:53:01 +01:00
kevinveenbirkenbachandClaude Opus 5.5 ac4a8f45e2 fix(web-app-erpnext): seed the standard price lists the skipped setup wizard creates
The deploy bypasses ERPNext's setup wizard and with it install_defaults, so a site without the store's GUI fixtures had no Standard Selling or Standard Buying price list and every Item Price insert failed with "Could not find Price List: Standard Selling". company.py now creates both after the Company, insert-if-missing, with the wizard's selling and buying flags and the Company's own currency; Price List.on_update fills the Selling and Buying Settings defaults.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 16:45:53 +01:00
kevinveenbirkenbachandClaude Opus 5.5 0aa5d1386b fix(web-app-erpnext): seed the tree roots the skipped setup wizard creates
The deploy bypasses ERPNext's setup wizard and with it install_fixtures, so a site without the store's GUI fixtures had no root Item Group and every consumer creating one failed with "Could not find Parent Item Group: All Item Groups". company.py now seeds All Item Groups, All Customer Groups and All Supplier Groups as root groups, insert-if-missing like All Territories.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 13:51:07 +01:00
kevinveenbirkenbach 8e3aac5cae Merge branch 'fix/web-app-erpnext/api-bot-extra-roles' into feature/store-i18n 2026-11-01 12:34:41 +01:00
kevinveenbirkenbachandClaude Opus 5.5 4afa1183c1 feat(web-app-erpnext): grant consumer-declared roles to the API bot
Consumers that build on the ERPNext site from their own repositories (web-app-cst-store, web-app-cst-security-check) now declare the roles they need on erpnext-api-bot in services.erpnext.api_bot.extra_roles instead of granting them themselves. Every deploy grants them beside System Manager and the Server Scripts role, creating an empty Role first when the site does not hold it yet, so this role stays the only writer of the bot's roles and keys. Port of the api-bot part of 067 from feature/iam-profile-rbac (3e5acbd104).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:32:42 +01:00
kevinveenbirkenbachandClaude Opus 5.5 4f03e7f9f8 fix(web-app-stalwart): create accounts without credentials while SSO is on
Under SSO the OIDC directory is the authentication directory, and Stalwart refuses any password credential for its accounts ("Cannot set credentials for accounts in an external directory"). Every create carried one, so an account added after SSO was switched on never came into existence: the echoserver deploy failed on the keycloakbootstrap bot right after the 0.16 to 1.x migration, and a new person would have been skipped silently. Under SSO the create now carries no credentials and the password update is skipped; existing accounts come back as primaryKeyViolation with their id, as without SSO. Any remaining refusal fails the deploy. Closes the accounts entry of the role's TODO.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 12:11:03 +01:00
kevinveenbirkenbach ca722a00b7 Merge branch 'fix/web-app-dashboard/build-once' into feature/store-i18n 2026-11-01 10:05:32 +01:00
kevinveenbirkenbachandClaude Opus 5.5 c1d1d377c6 fix(web-app-dashboard): build the dashboard image once for all network instances
Every network instance (dashboard, dashboard-onion) carried the full build block, so compose built the same dashboard_custom tag twice in parallel. In CI run 41261531965 (odoo#0) dockerd 29.9.2 died with SIGSEGV inside BuildKit during that double build and stopped the stack. Now only the first instance builds; its siblings run the same tag with pull_policy never in compose, the pattern bookwyrm, espocrm and openproject use. Swarm builds, labels and pushes the image once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 09:58:58 +01:00
kevinveenbirkenbach 7e3c290d51 Merge branch 'feature/stalwart/forward-platform-admin-mail' into feature/store-i18n 2026-11-01 09:42:13 +01:00
kevinveenbirkenbachandClaude Opus 5.5 629fe2375d style(tests): apply ruff format to test_migrate_v016
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 09:42:06 +01:00
kevinveenbirkenbach d2443e3451 Merge branch 'fix/web-app-stalwart/migrate-verify' into feature/store-i18n
# Conflicts:
#	roles/web-app-stalwart/files/shell/migrate_v016.sh
2026-11-01 09:35:07 +01:00
kevinveenbirkenbachandClaude Opus 5.5 33b635bca7 test: satisfy the role-file SPOT and cached-read lints in two new tests
test_openproject_redirect_uris builds the vars path from ROLE_FILE_VARS_MAIN, and test_store_migration_job reads its tempdir stub log under a cache-read nocheck, because the log is rewritten between reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 09:33:20 +01:00
kevinveenbirkenbachandClaude Opus 5.5 bd233bdb96 fix(web-app-stalwart): migrate 0.16 stores with stalwart-migrate 1.0.4 and verify every account
stalwart-migrate 1.0.0 failed the final verify on echoserver (6 rows) and galaxyserver (2 rows), all x:BlockedIp entries that expire when the tool starts 1.x, so a final run could never pass; 1.0.0 to 1.0.3 also skip accounts without a change counter. The pin moves to 1.0.4, final runs with --verify-full instead of a sample of 16 accounts, and a failed final restarts 0.16 and prints the error and verify rows of the new report phase, since final-report.txt is only written by a passing run. The README describes how to read the rows and when to start over.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 09:26:59 +01:00
kevinveenbirkenbach fb284f797c Merge branch 'perf/ci/nextcloud7-budget' into feature/store-i18n 2026-11-01 09:20:19 +01:00
kevinveenbirkenbach d6530ca3fe Merge commit 'e277edf6e7' into feature/store-i18n 2026-11-01 09:20:09 +01:00
kevinveenbirkenbachandClaude Opus 5.5 b386119642 perf(email): resolve only the requested key in lookup('email')
Every lookup('email') resolved all 15 settings. On swarm workers and the nfs-server of Tor rows that took 22-26 s per call, even for tasks that only read external or timeout and then skip (CI run 41261531965, Nextcloud#7: ~600 s over both passes, the job ran out of its budget). The lookup takes key= now and stops after that entry; the four call sites and mail_recipient that need only external or timeout use it. Without key= the result is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 09:19:28 +01:00
kevinveenbirkenbachandClaude Opus 5.5 e277edf6e7 fix(web-app-keycloak): close self-service email takeover
Users could change their Keycloak email without verification, and every deploy stamped any address an inventory user held as verified. An address no Keycloak account holds (for example erpnext-api-bot@) could thus be claimed and reach apps that link SSO logins by email. The user profile now lets only admins edit the email, and email_verified.py stamps only an address that equals the inventory address.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 08:57:17 +01:00
kevinveenbirkenbachandClaude Opus 5.5 925809c377 Merge branch 'fix/web-app-nextcloud/openproject-oauth-roundtrip' into feature/store-i18n
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 08:43:54 +01:00
kevinveenbirkenbachandClaude Opus 5.5 c3f482f23f fix(web-app-nextcloud): register the OpenProject redirect URI of every Nextcloud network
CI run 41261531965 Nextcloud#3 (multi network) tested Nextcloud on its onion address. integration_openproject builds redirect_uri from the request host, so it sent http://next.cloud.<onion>.onion/.../oauth-redirect, but ensure_nextcloud_storage.rb registered only the URIs built from the canonical NEXTCLOUD_URL; Doorkeeper answered every /oauth/authorize with 400 invalid_redirect_uri (proxy log: 6x 400, OpenProject web log status=400 user=6, trace page 'The requested redirect uri ... doesn't match client redirect URI').

NEXTCLOUD_NETWORK_BASE_URLS comes from lookup('network_urls', NEXTCLOUD_URL), like the Zammad and GitLab base URLs, and reaches the provisioning input as nextcloud_base_urls; the script registers every base URL with the apps/ and index.php/apps/ paths, canonical first, and the base URLs feed the converge digest so an install switched to multi network re-provisions. Clearnet-only and tor-only rows register the same string as before. Zammad, GitLab and Mattermost integrations still register only the canonical URI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 08:43:41 +01:00
kevinveenbirkenbachandClaude Opus 5.5 5c2bf23063 fix(web-app-stalwart): run the 0.16 store migration as a polled async job under a lock
galaxyserver deploy -6 ran the migration as one plain command for 28:30 and then lost its SSH channel (ServerAlive 15x3 ends it after 45 s of silence): the deploy ended UNREACHABLE while the script kept running on the host unobserved, possibly through final, which stops Stalwart and swaps the databases.

The task now runs migrate.sh as an async job polled every STALWART_MIGRATE_ASYNC_POLL (60 s); each poll is a short new SSH call and a failed poll is retried, so a dropped connection no longer ends the deploy. The budget STALWART_MIGRATE_ASYNC_TIME is lookup('timeout', 21600) (6 h, scaled by TIMEOUT_FACTOR); past it Ansible kills the job and the task fails loudly. Every phase but status takes a non-blocking flock on migrate-v016/migrate.lock and stops while another run holds it or a stalwart-migrate container of an earlier run still runs, so two migrations never touch the same store and dump. A kill inside final leaves Stalwart stopped and the next run refused while the orphan container lives.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 08:39:36 +01:00
kevinveenbirkenbachandClaude Opus 5.5 03217e415d Merge branch 'fix/web-app-nextcloud/swarm-init-gate' into feature/store-i18n
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 02:13:19 +01:00
kevinveenbirkenbachandClaude Opus 5.5 a0c36d6e38 fix(web-app-nextcloud): evaluate occ status's exit code in the init gate
Gate pass 23 failed tests/lint/filesystem/shell/test_no_or_true.py on init-gate.sh: occ_status swallowed every exit code with || true. It now returns 0 with the status on success and maps 1 (occ error), 124 (timeout) and 255 (php fatal while the tree is copied or upgraded) to an empty status, the not-ready state both slots already handle. Any other code, such as 127 from a missing su, timeout or php, ends the gate with that code and a message instead of waiting forever. Both slots now call occ_status directly so that exit reaches the gate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 02:12:57 +01:00
kevinveenbirkenbachandClaude Opus 5.5 812d2329a7 Merge branch 'fix/web-app-nextcloud/swarm-init-gate' into feature/store-i18n
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 01:39:40 +01:00
kevinveenbirkenbachandClaude Opus 5.5 93e0e83d7b fix(web-app-nextcloud): fail fast when slot 1 finds a half-finished install
In swarm CI run 41206003651 (Nextcloud#11) the first occ maintenance:install failed on a config.php lock after the upstream entrypoint had already copied version.php. Upstream skips the install whenever version.php exists and never retries, so the replacement task served an uninstalled Nextcloud that occ status still reported as healthy, and slots 2 and 3 waited for installed: true until converge gave up after about 25 minutes.

Slot 1, and compose where TASK_SLOT is unset, now exits 1 with the cause and the recovery when version.php and occ exist, the init lock is free and occ status prints installed: false. The task crash-loops and the stack readiness check ends the deploy within minutes with that message in the service log. occ status runs with a 120 s timeout in both branches. Why the lock failed on NFS is not addressed here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 01:32:08 +01:00
kevinveenbirkenbachandClaude Opus 5.5 5861e8694c Merge branch 'fix/platform-admin/ensure-on-existing-installs' into feature/store-i18n
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 01:21:43 +01:00
kevinveenbirkenbachandClaude Opus 5.5 cc70de8f28 fix(platform-admin): create platformadmin on existing installs in six roles
Matomo, SuiteCRM, WordPress, MediaWiki, Joomla and Listmonk only realigned an existing admin login, so existing installs without platformadmin stopped the deploy. Each admin step now creates the account next to the old admin when it is missing and realigns it when it is an admin.

A platformadmin that exists without admin rights fails with its cause and remedy. MediaWiki alone promotes it, and only while SSO is the sole login and its confirmed email matches: there the account can only come from Keycloak's preferred_username. SuiteCRM keeps native login under SAML and lets users rename themselves, Listmonk's OIDC never creates that login, and Joomla's Keycloak plugin rewrites groups on every sign-in, so none of them promote.

Matomo, SuiteCRM and WordPress write through php://stdout and php://stderr: PHP 8.2 defines no STDOUT/STDERR for code fed on stdin. MediaWiki's account probe lives in files/sql/admin_state.sql and receives name and email as hex literals. A lint checks that each role's admin step creates a missing admin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 01:21:20 +01:00
kevinveenbirkenbachandClaude Opus 5.5 c1cd4325d6 fix(stalwart): harden the platform admin forward after the skeptic round
The users cache no longer demands a mailbox on every host (a workstation
inventory without mail broke every users lookup) and skips forwards that
are still unrendered Jinja; a non-mapping target names itself. Stalwart now
enforces the mailbox where it consumes the forward. Under SSO 16_forwards
skips ReloadSettings, which would open the OIDC issuer before Keycloak runs;
the OIDC restart applies the limits. The routing probe treats transient
IMAP/SMTP errors as not yet within the same budget and only checks forwards
in Stalwart's own rounds, so the 67 roles that deploy it as mail provider
keep skipping it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 23:55:09 +01:00
kevinveenbirkenbachandClaude Opus 5.5 bbd8ad2764 feat(stalwart): forward the platform administrator's mail to the administrator
System mail now goes to platformadmin@, a mailbox nobody reads. The users
cache already carries a per-user forward and Stalwart already writes a
redirect :copy Sieve script per forwarding account; stalwart_user_forwards
feeds the first into the second for every user Stalwart has an account
for, merged with inventory forwards. platform_administrator forwards to
administrator, keeping its own copy. The users cache now rejects forwards
to unknown users, to users without a mailbox, and forward loops.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 22:43:00 +01:00
kevinveenbirkenbachandClaude Opus 5.5 89063972a6 perf(test-e2e-playwright): order Playwright passes by meta/tests.yml run_after
A role's playwright.run_after names the roles its pass runs after; the new
playwright_order lookup reads it through role_tests (which now renders
Jinja with the queried role as application_id) and orders the round with
a stable topological sort, so only constrained roles move. web-app-docs
runs after every other invokable role: in CI run 41206003651 (Discourse#2)
its pass waited 3126 s for the docs server's Sphinx build while stalwart,
bigbluebutton, jitsi and prometheus (~400 s) queued behind it. Cycles,
self references, unknown roles and non-list values fail loudly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 21:41:55 +01:00
kevinveenbirkenbachandClaude Opus 5.5 edf75b49dc refactor(web-app-keycloak): group the RBAC REST scripts in files/python/rbac
Gate pass 15 rejected rbac_reconcile.py and rbac_realm_groups.py as a prefix group. They are now rbac/reconcile.py and rbac/realm_groups.py with mirrored tests; the shared rest_script runner copies a script from its subpath and stages and runs it under its file name next to keycloak_admin.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 19:40:58 +01:00
kevinveenbirkenbach 8a1c076f14 Merge branch 'perf/web-app-keycloak/rbac-groups-batch' into feature/store-i18n 2026-10-31 19:13:58 +01:00
kevinveenbirkenbachandClaude Opus 5.5 2ad6968246 test(web-app-weblate): keep the stand-ins next to the package tests
Gate pass 14 rejected the parent-relative imports (ruff TID252) the moved weblate_network tests used for _stand_ins; the helper now sits in the same test package and test_settings_override imports it downward.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 19:13:53 +01:00
kevinveenbirkenbachandClaude Opus 5.5 7d983fc66c perf(web-app-keycloak): reconcile the realm RBAC groups in one batched pass
The realm RBAC step ran one kcadm round trip per group path and member through ensure_group_path_members.sh, about 609 s per XWiki job. A Python helper now reads the realm's groups and memberships once, computes the missing paths and members, and applies only the difference in one run; each failing item still fails loud and names itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 19:07:32 +01:00
kevinveenbirkenbach 2b9773bd03 Merge branch 'fix/web-app-magento/two-factor-toggle-race' into feature/store-i18n 2026-10-31 19:01:06 +01:00
kevinveenbirkenbach fcc2441247 Merge branch 'fix/web-svc-collabora/onion-frame-ancestors' into feature/store-i18n 2026-10-31 19:00:59 +01:00
kevinveenbirkenbach e11e2817df Merge branch 'fix/web-app-docs/builder-timeout-and-prepared-glob' into feature/store-i18n
# Conflicts:
#	roles/web-app-docs/README.md
#	roles/web-app-docs/files/python/infinito_docs/build_queue.py
2026-10-31 19:00:53 +01:00
kevinveenbirkenbachandClaude Opus 5.5 ced411d0de fix(web-app-magento): toggle the two-factor modules only when their state is wrong
Magento 2.4.8 wipes generated/ on every module:enable or module:disable, decided by the command name alone, and the role ran the toggle on every deploy. On CI Magento#0's update pass a Prometheus probe rendered a page during that wipe and wrote new generated classes into it, so rmdir failed and the deploy died. The role now reads module:status --enabled first and only flips the modules in the wrong state; on a fresh install the toggle runs before nginx starts routing to PHP, and a real flip also reloads nginx.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 18:58:00 +01:00
kevinveenbirkenbachandClaude Opus 5.5 bdc7408357 test(sys-svc-webserver-core): stub IS_SWARM_MODE for the access-log render
The access-log test from main (#1322) rendered nginx.conf.j2 with DEPLOYMENT_MODE, while store-i18n's template reads IS_SWARM_MODE, so every case failed with an undefined variable after the main merge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 18:56:30 +01:00
kevinveenbirkenbachandClaude Opus 5.5 42983ded11 refactor(web-app-weblate): ship the network modules as the weblate_network package
Gate passes 12 and 13 rejected the prefix-grouped weblate_network_*.py modules, the stand_ins.py test helper and unmirrored test paths. The modules are now weblate_network/strategy.py and middleware.py, mounted as a namespace package under /app/infinito and referenced by their dotted package names; the helper is _stand_ins.py and the module tests mirror the package.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 18:55:29 +01:00
kevinveenbirkenbachandClaude Opus 5.5 fa7555d2eb fix(web-app-docs): keep only the three release tags opened last on disk
Publishing tag v1.2.3 globbed prepared/v1.* and deleted every other v1.x tag's prepared tree, including one a parallel slot could be cloning from. With the exact glob each opened tag would keep its ~2.3 GB site and ~1 GB prepared tree forever, which 66 tags and a crawler following the version switcher turn into a full disk. Requests now stamp opened/<tag>, and after every build the builder moves out, under the slot lock, every tag beyond the three opened last that is neither queued nor building; latest and deployed always stay, and a dropped tag rebuilds on its next visit. The builder also clears scratch a killed predecessor left.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 18:49:11 +01:00
kevinveenbirkenbachandClaude Opus 5.5 5d2410f7e9 fix(web-svc-collabora): let every Nextcloud network sibling frame the editor
The onion Nextcloud page frames the clearnet Collabora editor, but the proxy's frame-ancestors only allowed 'self' and *.DOMAIN_PRIMARY, which matches neither the onion host nor its http scheme, so Chrome blocked the iframe and the editor websocket never opened. Collabora now adds every Nextcloud network origin, each with its own scheme, to its frame-ancestors through webserver_csp_whitelist_extra_by_app before the proxy stack renders.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 18:42:09 +01:00
kevinveenbirkenbach e96dae47c2 Merge branch 'fix/web-app-weblate/onion-handover' into feature/store-i18n 2026-10-31 18:24:09 +01:00
kevinveenbirkenbachandClaude Opus 5.5 54eccfcee6 feat(web-app-weblate): serve clearnet and onion from one instance
Weblate built every absolute URL, the social-auth redirect and the CSRF origin from WEBLATE_SITE_DOMAIN, so the onion sibling either redirected to clearnet or failed the OIDC round trip. A settings override swaps in a network-aware social strategy and proxy middleware that take scheme and host from the request, drops the forced HTTPS redirect the http onion vhost cannot satisfy, and ALLOWED_HOSTS now lists every network sibling plus the container name and loopback. The two modules are separate because social_django loads the strategy at app-ready before defining load_strategy, which weblate.middleware imports back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 18:23:59 +01:00