Commit Graph
1953 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Fable 5 26ae8e1c1b fix(fediwall): family-align wall servers to the consuming page
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 20:39:16 +02:00
kevinveenbirkenbachandClaude Fable 5 8c1f64f26f feat(hlth-csp): probe onion vhosts through the node Tor SOCKS proxy
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 20:39:15 +02:00
kevinveenbirkenbachandClaude Opus 4.8 52696e35e0 fix(swarm): pass --insecure so manifest_exists can see the plain-HTTP registry
docker manifest inspect is a pure client command and ignores the daemon's insecure-registries list, so against the swarm-local HTTP registry it reported every existing manifest as missing. The push skip therefore never triggered: each deploy re-pulled every external image over the slow lab NAT, re-pushed it, and the final rmi dropped the engine copy again. With the flag the second and every later sync recognizes cached manifests and completes in seconds, proven live on the kept matrix cluster. The test fake_run learns the timeout keyword the pull sites now pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 19:53:20 +02:00
kevinveenbirkenbach 4ac72f49bc Autoformat 2026-07-18 16:30:52 +02:00
kevinveenbirkenbachandClaude Opus 4.8 cb67adfffa feat(ci): select swarm deploys per variant and split discovery into three mode queries
The discovery SPOT (cli.meta.ci.query) now runs one query shape per mode:
compose and host stay whole-role with variants packed into bundles, swarm
ranks and budget-cuts on per-variant rows and emits role#variant tokens
through apps.sh into variant_bundles, so the cut can pick a subset of a
role's variants and the --matrix view is the selection priority.

Replace the --unique flag with visible dna/clone columns (heaviest role
per dna cluster stays ahead of the cut), add the integrated column and
sort, count host bundles like compose, and give the deploy plan an id
counter, per-variant weights and display-width-aware alignment matching
the matrix renderer. Add i8ma*/i8pa* inspection aliases per mode.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 16:26:30 +02:00
kevinveenbirkenbachandClaude Fable 5 393e0a84df feat(ci): share the discovery query and render a per-mode deploy plan
cli.meta.ci.query is the single source of truth for the app-discovery
query (filter, coverage-first sort, lifecycle envelope, compose
--unique, INFINITO_MAX_JOBS cap with 'auto'); apps.sh shrinks to one
call through it. cli.meta.ci.plan renders one section per deploy mode
in the query's own order (priority line starred, capped regular line,
then the candidates behind the cut), one row per variant, glossary
symbols in the header, with --cli for fixed-width terminal tables.
New glossary symbols: skip, priority, distros, unavailable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 16:26:30 +02:00
kevinveenbirkenbachandClaude Fable 5 9bce39009c feat(ci): derive deploy-matrix slots from the workflow chain
cli.meta.ci.slots statically and conservatively counts every job the
CI run spawns outside the deploy matrices (reusable workflows opened
recursively, static matrices multiplied out, dynamic ones estimated,
worst entry-*.yml overhead included) and splits the remaining
256-job run budget between compose/swarm/host by the _SHARES weights,
with a per-mode floor and _SLOT_OVERRIDES pins. INFINITO_MAX_JOBS
defaults to 'auto', resolved per mode in apps.sh; the host workflow
drops its hardcoded cap. --matrix renders the budget as a table.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 13:03:25 +02:00
kevinveenbirkenbachandClaude Fable 5 d8ec933232 fix(ci): aggregate variant shards worst-first in role statuses
parse_role_statuses collapsed a role's variant shards per mode with
last-write-wins, so one green shard could mask a failed sibling and
--failed retriggers silently skipped the role (gitlab, run 29599179461).
Aggregate worst-first (failure > cancelled > running > success) and let
parse_role_urls link the worst shard.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 13:03:25 +02:00
kevinveenbirkenbachandClaude Opus 4.8 5936d3ba18 fix(csp): CSP token and injected asset agree on the aligned provider scheme
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 02:12:12 +02:00
kevinveenbirkenbachandClaude Opus 4.8 0fb5eb8609 fix(logout): sweep only same-family domains of enabled entities
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 02:12:11 +02:00
kevinveenbirkenbachandClaude Opus 4.8 6e20b94f14 chore: apply autoformat and settings churn from the quality run
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 dbb1a9bd38 chore(seaweedfs): drop the dollar-escape branch and pin the launcher invariants
The sidecar script contains no shell dollars anymore, so the swarm-only replace escape is dead; tests pin the exec-as-PID1 shape and the dollar-free invariant.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 931b393c99 style(tests): wrap the closure literal in the extend-inventory test
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 0b57337032 fix(proxy): reach node-local force_bridge apps via the host gateway under swarm
A force_bridge app (matrix's MDAD flavor) deploys as a node-local compose stack and publishes its local port on its host, while openresty runs as an overlay task whose 127.0.0.1 is its own loopback; the readiness probe died on 502. The proxy_pass lookup now resolves networks.local.force_bridge (trust-tagged for the 2.19 templar, hard-failing on an unrendered template instead of silently falling back to loopback) and keys the decision on the real DEPLOYMENT_MODE, since such apps rewrite the effective mode to compose via compose_mode_force. The upstream becomes host.docker.internal:<local_port> rendered as a literal directive, because the request-time resolver cannot see /etc/hosts entries, and the swarm openresty service maps host.docker.internal to the host gateway like prometheus already does. Non-force_bridge renders stay byte-identical.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 029ce2bd74 fix(swarm-test): gate every backup leg on its inducer's include closure
extend_inventory appended the volume, secrets and nfs backup groups to the test inventory unconditionally, so the DR-drill ran on hosts whose roles declare no backup. For roles whose only volume is backup-disabled (registries, unbound, redis, openresty) the volume drill produced a payload-less generation and failed its non-empty assertion. Each leg now follows the closure of the role that induces it: volume and (transitively, via volume-2-local's secrets_backup consumer) secrets on the app closure, nfs on svc-storage-nfs-server's closure via its nfs_backup consumer. Enumeration confirms no consumer-active role loses its leg; a README documents the group derivation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.8 bce2df6225 fix(tests): use valid application_ids in family-alignment fixtures; autoformat
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 23:44:12 +02:00
kevinveenbirkenbachandClaude Opus 4.8 7d6267c3a6 feat(rdr-domains): redirect the bare onion apex to the homepage on onion nodes
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 23:44:12 +02:00
kevinveenbirkenbachandClaude Opus 4.8 f6174655b1 fix(hlth-webserver): expect the apex only when web-opt-rdr-domains serves it
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 23:44:12 +02:00
kevinveenbirkenbachandClaude Opus 4.8 e0867fb44d feat(lookup): family-align peer refs to the consuming app (cross-family substrate)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 23:44:11 +02:00
kevinveenbirkenbachandClaude Fable 5 a3a8bc92ac feat(readme): filter overview to tested envelope, place under Use it online
The roles overview now lists only tested-envelope roles (lifecycle
alpha/beta/rc/stable/maintenance) and renders below the renamed
'Use it online' section with an introductory sentence. Rename the
former 'Get Started' heading and drop the redundant subsection.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 19:10:01 +02:00
kevinveenbirkenbachandClaude Opus 4.8 0fc18a8a8b fix(diagnostics): stop the local-dump copy from recursing into its own snapshot
The snapshot directory lives under the dump base (both derive from INFINITO_RESCUE_DIAGNOSTICS_DIR), so copytree copied its growing destination into itself until ENAMETOOLONG; the suppressed error left a local-dumps/<stamp>/local-dumps chain that failed the artifact upload of otherwise green jobs (swapfile, wireguard-plain). The copy now ignores the snapshot's own subtree and every ancestor holding it, which also excludes stale sibling snapshots of the same app; a regression test drives real copytree over the production topology.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 19:10:01 +02:00
kevinveenbirkenbachandClaude Fable 5 da598a2d67 feat(readme): roles overview table with homepage/video backfill
Add cli.build.readme.overview (make readme-index / make docs) rendering a
roles overview in the root README: Name, Lifecycle, Homepage, Video,
Description, Integrated with, Install. New info-media lint requires
homepage + video in every invokable role's meta/info.yml (opt out via
'# nocheck: info-media' in meta/main.yml); backfilled 147 roles with
researched, adversarially-verified homepages and official videos.

Retire the 'unsupported' lifecycle value: fold it into 'eol' as a valid
live end-of-life status (shipped but untested/unmaintained) across the
stage lists, symbol glossary, allow-list lint and docs. Retag confluence,
jira, minio, phpldapadmin to eol and magento to pre-alpha.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 19:10:01 +02:00
kevinveenbirkenbachandClaude Opus 4.8 86bb184bfa feat(diagnostics): capture pg_stat_activity for postgres containers in the rescue snapshot
The gitlab dedicated-postgres failure exhausted all 167 non-superuser slots, but the rescue artifact could not show which clients held them. The collector now dumps pg_stat_activity (per-backend rows, query truncated to 120 chars) and a usename/datname/state connection histogram for every container with postgres in its name, via psql over the container's peer-authenticated socket. Runs only in the failure path and capture() never raises, so a non-postgres name match just records the exec error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 19:10:01 +02:00
kevinveenbirkenbachandClaude Fable 5 184beacfd8 feat(cli): retrigger failed roles as priority line
infinito administration deploy ci trigger --failed now dispatches the
failed roles via the priority field and omits the whitelist, so the
priority line reruns them first and the regular line covers the rest.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 19:10:00 +02:00
kevinveenbirkenbachandClaude Opus 4.8 dd0211e31d feat(ci): accept bare run ids in trigger and DRY the retrigger aliases
ci trigger --run now takes a bare run id and resolves it against the current branch's tracking-remote repo; full URLs keep using the owner from the URL. The aliases no longer build run URLs from INFINITO_FORK_REPOSITORY_URL (stale values produced 404s against the wrong owner): a single i8cifail base passes the id or URL through, and i8cire, i8puci, i8manfail and i8manfails compose it (quality gate / sign-push / scope variants).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 19:10:00 +02:00
kevinveenbirkenbachandClaude Opus 4.8 f4172c547a fix(prometheus): exclude swarm-unreachable force_bridge apps at the native_metrics_apps SPOT
A native-metrics app on a node-local force_bridge network cannot be joined or resolved by a swarm-wide prometheus: the stack deploy fails with the network scope error and the scrape job would flap as permanently down. native_metrics_apps now drops those apps at the source (DEPLOYMENT_MODE swarm + networks.local.force_bridge), covering all four call sites (network precreate, compose service networks, external-networks block, scrape include) without per-template guards. DEPLOYMENT_MODE is templated without a default so a missing value fails loudly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 14:44:34 +02:00
kevinveenbirkenbachandClaude Opus 4.8 10a218ed6e fix(nfs): correct volume ownership for non-root NFS-backed containers
Per-volume nfs uid/gid/mode (erpnext/frappe 1000, jenkins 1000, moodle/www-data 33, ejabberd 9000) so NFS-backed named volumes get the container runtime owner. nfs_prep falls back to default(omit) instead of re-forcing root:0755, which reverted the docker copy-up ownership for non-root images on every redeploy. compose_volumes test asserts the x-infinito-nfs marker.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 14:44:34 +02:00
kevinveenbirkenbachandClaude Opus 4.8 4dbaa60707 feat(stages): drive deploy stages from a categories.yml SPOT
roles/categories.yml now declares the ordered 'stages' and a per-category 'stage' (plus run_after and bootstrap). utils/roles/stage.py resolves a role to its stage and exposes stage_groups(); the new stage_groups lookup feeds the 01_constructor / 02_server / 02_workstation / 03_destructor group loops in place of their hardcoded lists. A static invariant test proves the lookup reproduces the exact previous loops, so the rendered plays (and deploy behavior) are unchanged.

cli.meta.roles.order.run orders its main phase by stage as a run_after tiebreak. plugins/filter/invokable_paths tolerates the new sibling 'stages' key, and the invokable-roles wiring test recognizes stage_groups-driven wiring.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 14:44:34 +02:00
Alejandro Roman 889d3a370f fix SPot and issues found 2026-07-16 14:26:11 +02:00
Alejandro Roman f79037b7ac add mermaid and refacotr some code 2026-07-16 11:28:58 +02:00
kevinveenbirkenbachandClaude Opus 4.8 8e685e751f feat(complexity): test_* columns driven by meta/tests.yml skip, wide-safe symbols
meta/services.yml modes states where a role RUNS; a new meta/tests.yml
skip list deactivates TESTING a mode without touching that capability.
The table gains test_compose/test_swarm/test_host columns (base column
minus skip), --filter/--sort and the JSON/YAML payloads know the new
fields, and CI discovery (apps.sh) now filters on test_<mode> == true.
svc-storage-nfs-client is the first consumer and skips all three modes.

Also replaces the nine VS16-based header/lifecycle emojis (like the
old host/jobs/weight symbols) with East-Asian-Wide ones: terminals
render VS16 sequences 2 cells wide while the width model said 1,
shifting every header right of them off its column. A guard test pins
all table symbols to wide, VS16-free codepoints.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 05:20:54 +02:00
kevinveenbirkenbachandClaude Opus 4.8 cd4d0e3e28 refactor(cli): move cli/deploy/runner under cli/administration/deploy
The runner command joins its siblings (dedicated, development) under
cli/administration/deploy; cli/deploy is gone. Makefile, docs and the
requirement links now point at the new path, PROJECT_ROOT climbs one
level further, and the unit tests moved along.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 05:20:54 +02:00
kevinveenbirkenbachandClaude Opus 4.8 16aa00d905 refactor(deploy-cli): split deploy.py into a per-responsibility package
One module per concern, mirroring the inventory/ subpackage layout:
run.py (single deploy pass + env forwarding SPOT), drill.py (recover
drill, host mode exempt, paths from CONTAINER_REPO_ROOT instead of a
hardcoded /opt/src/infinito), purge.py (inter-round cleanup) and
cli.py (arg parsing + round/pass loop, PASS 1/2 deduplicated).

Also extend the comment linter to flag bare string-expression
statements outside docstring position in Python: a triple-quoted
literal floating in a body is a comment in disguise and now runs
through the same validity rules; docstrings and PEP 224 attribute
docstrings stay allowed. Test narration comments moved into method
docstrings accordingly, and the design docs now link deploy/cli.py.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 05:20:54 +02:00
kevinveenbirkenbachandClaude Opus 4.8 b5e5554883 fix(complexity): gate the host column on the lifecycle envelope
compose and swarm columns go through _tested_apps (invokable +
lifecycle envelope + per-mode skip) but host only checked non-stack +
modes.host.enabled, so host CI discovery reacted to every lifecycle:
61 roles instead of the 24 inside the alpha/beta/rc/stable envelope.
Route host through _tested_apps("host") in both the role-level and
per-variant row builders.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 05:20:53 +02:00
kevinveenbirkenbachandClaude Opus 4.8 672e93246b feat(deploy): add host deploy mode + matrix symbol view
Host lane for invokable non-stack roles (drivers, backup, wireguard, swapfile, ...). modes.host.enabled declared on 56 such roles; new lint test_role_host_mode enforces it. The complexity matrix gains a host column (not stack and modes.host.enabled), --deploy-mode host, and host bundles (one per variant); apps.sh accepts INFINITO_DEPLOY_MODE=host and filters host == true. New test-deploy-host.yml workflow (INFINITO_MAX_JOBS=10) deploys discovered host roles via the mode-agnostic ci/all.sh path, wired into ci-orchestrator (modes default 'swarm compose host').

Also: complexity -s/--symbol compact view (emoji-only headers, true/false as check/cross, lifecycle stage symbols, grouped legend with per-entry explanations, display-width aligned); stack column moved after host. scripts/meta/env/load.sh made zsh-compatible by delegating to bash and importing INFINITO_/PYTHON/VENV/PATH back.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 03:44:17 +02:00
kevinveenbirkenbachandClaude Opus 4.8 7a6268fa96 refactor(deploy): replace skip with services modes
Per-role deploy-mode opt-out moves from meta/tests.yml 'skip:' to meta/services.yml <entity>.modes.{compose,swarm}.enabled on the primary entity. get_role_skip now derives from it; get_role_mode_enabled added. A new lint requires every role shipping templates/*compose*.yml.j2 to declare both mode flags. Migrates 107 services.yml and drops 11 skip-only tests.yml. Also removes the variant_status deployability gate so swarm runs one job per variant unconditionally (variant_status.py and deployable_variant_indices deleted, complexity model simplified). Adds the i8matix alias.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 03:44:17 +02:00
kevinveenbirkenbachandClaude Opus 4.8 ee07cd96b2 fix(ci): cap variants per compose job per role instead of globally
The nextcloud compose job bundled variants 2,3 into one runner and
needed ~332min of deploy time against the 300min step budget inside
GitHub's hard 360min job cap; raising the timeout leaves no headroom
for the measured runtime variance and starves the post-steps that
upload artifacts. Add a variant_bundle_size override in meta/tests.yml,
consumed by the variant bundle packer and the complexity report alike,
and set it to 1 for web-app-nextcloud only: eight ~190min jobs with
over 100min of headroom while every other app keeps the global
bundling.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 13:46:23 +02:00
kevinveenbirkenbachandClaude Opus 4.8 768e210c27 fix(compose): keep compose warnings out of pull.py's parsed output
run_cmd merged stderr into stdout, so compose warnings ('variable is
not set', ...) leaked into everything pull.py parses: the yaml config
for pull targets, the config --images fallback list (turning warning
lines into phantom image names), and the pull --help probe. A project
with an unset optional variable then failed the pull step even though
every image was present locally. Capture the streams separately, parse
stdout only, and forward stderr to the log.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 13:46:23 +02:00
Alejandro Roman cb3382f0d5 add test, fix SPOT 2026-07-15 12:53:58 +02:00
kevinveenbirkenbachandClaude Fable 5 15e707e9b2 fix(svc-runner): resolve empty entity name breaking swarm stack naming
get_entity_name('svc-runner') returned '' because the exact-match branch short-circuited on the category path 'svc-runner' before the shorter 'svc-' prefix could strip. The empty entity produced an empty swarm stack name (docker stack deploy "") and SERVICE_NAME '_' in the swarm convergence probe ('no such service: _' -> timeout). Record the exact match as a fallback and keep scanning so a shorter category prefix wins; simulated across all 254 roles, only svc-runner changes ('' -> 'runner').

Re-key roles/svc-runner/meta/services.yml from 'svc-runner' to the entity name 'runner' (services.yml is keyed by primary entity) and its 12 vars lookups, and add proxy.service_key: runner-1 so the swarm probe targets the real service (runner_runner-1) instead of the non-existent runner_runner.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 04:25:51 +02:00
kevinveenbirkenbachandClaude Fable 5 a786c8fcd7 fix(backup): make the DR-drill pull survive rsync version drift and stalls
The backup pull ssh forced-command wrapper exact-matched a fixed rsync --server flag string. rsync 3.4.x renegotiates that flag block (and our own --numeric-ids was added), so the match fell through to the reject echo, which polluted the rsync protocol stream and failed every pull with 'protocol incompatibility (code 2)'. Glob the version-dependent flags while pinning mode and destination, and reject shell metacharacters so the relaxation cannot be abused.

The pull script carried no ssh/rsync timeouts and the oneshot unit inherits the 24h default start timeout, so a stalled provider hung the whole job budget. Add ssh BatchMode/ConnectTimeout/ServerAlive and rsync --timeout so a dead provider fails in seconds and the retry loop reports it.

Add an integration test that routes a real rsync client through the rendered wrapper (the --numeric-ids path) and asserts the pull works and injection is rejected, so future rsync version drift fails in the suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 04:25:50 +02:00
kevinveenbirkenbachandClaude Fable 5 40e553069d refactor(structure): nest prefix-grouped sibling files into subfolders
Move files that share a delimiter-bounded name prefix within a folder (threshold 2) into a subfolder named after the prefix, dropping the prefix from the filename. Covers plugins/filter (docker, generate, has, merge, get/all), env handler subpackages, utils/roles/entity, utils/tests/swarm/write, role SQL/scripts/templates, keycloak/mailu task-includes, shared tasks/utils/load, and CI scripts. Update every import, query_file/script/include_tasks/src/lookup target, compose bind mount, and python -m path to the new locations.

Extend the prefix-grouped-files lint to threshold 2 with dir-level .nocheck and file-head nocheck opt-outs, and skip groups whose shortest member's stem equals the shared prefix. Keep flat only where a loader forbids nesting: WordPress mu-plugins and the docs/requirements namespace. Ansible filter discovery is recursive, so nested filters stay Jinja-resolvable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 20:00:03 +02:00
kevinveenbirkenbachandClaude Opus 4.8 fc0799883f refactor(structure): move prefix-grouped files into named subfolders
Resolve every 3+-file same-prefix group flagged by the new prefix lint
by moving the files into a subfolder named after the shared prefix and
dropping the prefix from the file names, updating all references:

- utils/env/handlers/infinito_*.py -> infinito/ (dir/, package_cache/
  nested a second level); registry imports and the four handler-dir
  globs switched to iter_project_files
- utils/install/lint/ansible_*.py -> ansible/ (aliased imports)
- roles/sys-svc-compose/files/swarm_*.{py,sh} -> files/swarm/
- web-app-erpnext/web-app-zammad files/scripts/apply_*.{py,rb} -> apply/
- web-app-odoo files/sql/{select,update}-* and sql/oidc/{grant,insert,
  select,update}-* -> matching subfolders
- web-app-keycloak tasks/update/05_ldap*.yml -> 05_ldap/ (internal
  includes made role_path-absolute)
- plugins/filter/get_*.py -> plugins/filter/get/ (filter names are the
  filters() dict keys, so Jinja usage is unaffected; ansible discovers
  the one-level-deep subdir)

Ansible lookup dirs, addon dirs and .github/workflows keep their flat
layout (the filename is the public id / GitHub only discovers flat).
Unit tests mirror the new source layout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 20:00:03 +02:00
kevinveenbirkenbachandClaude Opus 4.8 ab3accba3a refactor(paths): derive var-lib subpaths everywhere from the paths SPOT
Add DIR_BACKUPS to utils.paths and INFINITO_DIR_BACKUPS /
INFINITO_DIR_SECRETS env handlers, derive the recover-console constants
(including NFS_EXPORT_STATE) from utils.paths and the nfs export SPOT,
and switch every remaining self-built /var/lib/infinito subpath - the
secrets recover targets, the swarm extras backup source, the users
token-store candidate chain, the CI recover drill, the swarm NFS
diagnostics and the playwright reports dir - to those constants. Tests
consume the env constants directly; narration comments in the touched
files are dropped per the comment lint.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 16:15:27 +02:00
kevinveenbirkenbachandClaude Opus 4.8 e77aae2afe perf(service-loader): single applications-load preload
Flatten a single list term in the service lookup so query(service, [ids]) does one applications load instead of one per id. Precompute the required service ids in sys-service-loader and gate the preload by set membership, collapsing about 30 applications loads into one.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 02:47:40 +02:00
kevinveenbirkenbachandClaude Opus 4.8 75d84af636 feat(recover): unified recover CLI + swarm DR drill via CLI
Add cli.administration.recover: one uniform type/source/target command wrapping each svc-bkp-* role files/recover.py (nfs, volume, secrets, device) plus full for whole-tree recovery. Colon-encoded sources are classified by shape; device supports an on-device subpath, a generation, and remote pull over ssh.

Replace the per-host swarm DR-drill scripts (03/06/07/08_recover_*.sh) with the recover CLI in backup/base.sh. Pass the device on-device subpath relative (the CLI reads absolute segments as the restore-root) and load the applications-free .deploy.yml extras twin on the step-10 redeploy so host_vars credentials survive the -e override.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 02:47:39 +02:00
Alejandro Roman bdeab36bd4 next cloud issues with storage vs mailu 2026-07-14 01:16:31 +02:00
kevinveenbirkenbachandClaude Opus 4.8 21ae788a92 fix(hlth-webserver): skip canonicals of disabled services
A service entry may declare `domains: [<canonical key>, ...]`; when its
`enabled` resolves falsy those canonicals get no vhost (e.g. the seaweedfs
filer/master frontend on an onion node), so probing them can only fail
(TLSV1_UNRECOGNIZED_NAME / ERR_NAME_NOT_RESOLVED). Drop them from the
web-health expectation map. Mirrors the same suppression already added to
the CSP health probe.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 02:34:00 +02:00
kevinveenbirkenbachandClaude Opus 4.8 c8a4320478 feat(lookup): container_hostname — kernel-safe container hostname
`lookup('container_hostname', app)` returns the app's canonical primary
domain when it fits sethostname(2)'s 63-byte cap, else the short entity
name. Onion subdomains (sub.<56-char>.onion) overflow that limit and make
`docker run` fail with "sethostname: invalid argument", killing container
init on onion nodes. Replaces the seven roles that hostname'd their
container on the raw domain (bookwyrm, bridgy-fed, confluence, jira,
postmarks, pretix, xwiki) with the encapsulated lookup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 02:34:00 +02:00
kevinveenbirkenbachandClaude Fable 5 feccc1d916 refactor(registry): make run_after ordering bucket-agnostic
The per-bucket topological sort forbade run_after edges across loader
buckets (later bucket = hard error, earlier = silently ignored), a
leftover from before the service loader owned the preload order. The
sort is now global: an edge orders across any bucket, the name-prefix
bucket only tie-breaks among simultaneously ready roles, and cycle
detection covers the whole graph. The sort lives in the shared
run_after_topological_order helper, and the never-declared preload
flag is gone (run_after is the single ordering source).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 01:47:52 +02:00