Commit Graph
1046 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 5.5 afb82f57a1 feat(web-app-dashboard): let a role name the canonical domain its card opens
The dashboard card of every app opened its primary domain, so Matrix led to the Synapse status page and Stalwart to its admin UI. A role can now declare services.dashboard.card: <key of meta/domains.yml canonical>; docker_cards builds the card URL with lookup('canonical_url', app, key), the Apps menu reuses it, and roles_with_service('dashboard') hands the same domain to the tile e2e spec. Matrix sets card: element, Stalwart card: webmail. Without card nothing changes, and the prometheus/matomo target lists are untouched. A lint requires the key to resolve in the role's own domains.canonical.

The Matrix ansible flavor also sets Synapse's web_client_location to Element through matrix_synapse_configuration_extension_yaml, as the compose flavor already does, so matrix.<domain>/ redirects there. Merge note: feature/iam-profile-rbac defines the same extension variable inside the OIDC block; the next merge must combine both into one block (agreed with that session).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 21:01:06 +01:00
kevinveenbirkenbachandClaude Opus 5.5 8e35d053a2 fix(security): stop seeding demo data on every deploy, gate it on MODE_DEMO
Snipe-IT ran `php artisan db:seed --force` on every deploy. Its upstream
DatabaseSeeder (v8.8.3) truncates users, assets, licenses, orders and
settings, deletes uploads and creates about 2100 users, among them the
superusers `admin` and `snipe`, all with the factory password `password`,
plus a settings row against the public demo LDAP ldap.forumsys.com. Every
redeploy wiped real data and planted known superuser logins.

Decidim ran `rails db:seed` on every deploy with failed_when: false. The
generated seeds call Decidim.seed!, whose participatory-space seeds run in
production too: from the second deploy on they add demo processes and,
once a non-admin user exists, confirmed users with admin, moderator and
valuator roles and the password `decidim123456789`.

Snipe-IT now only creates its settings row when none exists, through
files/php/ensure_settings.php and SNIPE_IT_INITIAL_SETTINGS, and records
what already-seeded installs keep in TODO.md (taken verbatim from
d12b57be90 on feature/store-i18n). Decidim's seed task is gone; the role
creates its organization, pages and admin itself.

MODE_DEMO (group_vars/all/01_modes.yml, default false) brings both demo
seeds back on purpose; Decidim's then runs after the organization exists
and fails loudly. tests/lint/ansible/tasks/test_no_default_database_seeder.py
rejects Laravel's default seeder and Rails db:seed/seed:replant/setup/
reset/prepare unless the task is gated on MODE_DEMO; a Rails task whose
seeds are production-safe carries `# nocheck: default-seeder <reason>`,
which Mastodon does (find_or_create seeds, development-only admin seed).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-24 20:56:00 +02:00
kevinveenbirkenbachandClaude Opus 5.5 dba6aa7407 docs(requirements): add 045 stack service
Records the operator-confirmed design for replacing the sys-stk-full,
sys-stk-backend and sys-stk-front-proxy includes (115 call sites in 94
roles) with one shared `stack` service that sys-service-loader runs once
before the application roles and that processes every application of
the play in one batch: per-role literal `stack` and `openresty` keys,
front proxy and database derived from enabled services, per-domain vhost
data in meta without exceptions, all roles in one change.

The document carries the verified codebase facts with file:line on
origin/main 6997dd3dbb, the ordering and binding constraints, the cost
measured on the echoserver full-6 and full-7 deploys, a target design,
grouped acceptance criteria, validation commands and an implementation
order, so another agent can implement it without this conversation.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-24 19:48:43 +02:00
kevinveenbirkenbachandClaude Opus 5.5 285ce910d2 feat(inventory): reject unread keys and a missing Cloudflare token before the deploy
The Keycloak stage on echoserver ran ten minutes before sys-svc-dns stopped
it with "API.cloudflare.api_token must be set": the inventory still kept the
token under the flat name CLOUDFLARE_API_TOKEN, which nothing reads any
more. The validator that runs before every deploy now catches that class.

- api.py reports a host that selects DNS_PROVIDER: cloudflare without
  API.cloudflare.api_token, with group_vars/all merged under the host_vars
- variables.py reports every top-level key of host_vars and group_vars that
  core does not read: not declared in group_vars or a role's defaults or
  vars, not tested with "is defined" or "| default(", not read by name in a
  plugin, and not a SYSTEM_EMAIL_<KEY> the email lookup builds; a flat
  credential name such as CLOUDFLARE_API_TOKEN names its API.<provider>.<key>
  path; ansible_* keys are exempt

A key that is read in a way the scan cannot see takes
"# nocheck: inventory-variable", documented in suppression.md.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-23 16:18:12 +02:00
kevinveenbirkenbachandClaude Opus 5.5 50fcacb949 test(lint): require become: false on localhost delegations
A delegated task inherits the play's become and runs sudo on the
controller. The lint flags every delegate_to: localhost whose task,
enclosing block or play does not drop become, include apply: blocks
included, and accepts a localhost-become marker for a step that needs
root there. The e2e test roles only stat repository files and pack to
/tmp, so they drop become; the token-store mirror below
/var/lib/infinito and the NFS controller mount keep it with a marker.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-23 09:54:37 +02:00
kevinveenbirkenbachandClaude Opus 5.5 d76c6f5369 docs(requirements): specify automatic major upgrades, a WireGuard compose hub and the full Mailu import
- Automatic major upgrades: PostgreSQL through pg_upgrade --link with a
  reflink copy, Nextcloud one major at a time, the PeerTube migration
  scripts and asset reseed, the OpenProject intermediate major, the Moodle
  and Joomla upgrade paths, downgrade guards for the Bluesky PDS,
  Confluence and Jira, the MediaWiki extensions refresh and the Matrix
  switch from the compose to the ansible flavor
- A named WireGuard hub for compose deployments with roaming spokes
- A Stalwart import of every Mailu mailbox with its Sieve script, mailbox
  mapping, catch-alls and aliases with external destinations

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 08:29:25 +02:00
evangelostsak c71f5bc196 Merge remote-tracking branch 'upstream/main' into agent/i8-release-article 2026-10-21 11:15:15 +02:00
evangelostsak 57a4d654db docs(agents): keep release social posts non-technical 2026-10-20 13:58:43 +02:00
evangelostsak b6ebc32dbb docs(agents): let release social posts be technical 2026-10-19 22:41:35 +02:00
evangelostsak 5c8b6318e6 docs(cheatsheet): mention social posts for i8-release-article 2026-10-19 20:02:50 +02:00
evangelostsak 989d53c7e6 docs(agents): add social posts to the release article procedure 2026-10-19 20:02:49 +02:00
kevinveenbirkenbachandClaude Opus 5.5 b055eece05 feat(ci): keep GitHub-hosted runner labels current through the updater
The workflows pin `runs-on: ubuntu-NN.NN`, so no job moves to a new Ubuntu
release behind our back, but nothing raised the pin either. A sixth job of
`🔄 Update versions` closes that: `utils/update/runner.py` reads the image
table of actions/runner-images, takes the newest x64 Ubuntu label whose
image carries no preview or beta badge, and raises every older bare
`runs-on: ubuntu-NN.NN` to it; arch-suffixed labels stay untouched. The job
opens the change as one PR over `.github/workflows`, so its CI run tests
the new image before it reaches main.

This commit carries the updater's first result: every job now runs on
ubuntu-26.04 (49 `runs-on`).

actionlint 1.7.12, the newest release, does not know `ubuntu-26.04` yet
(rhysd/actionlint#682, fix proposed in rhysd/actionlint#743), so
`.github/actionlint.yaml` declares the label until a release knows it.

act maps each `ubuntu-NN.NN` label the workflows use to the local platform
image, derived from `.github/workflows`, instead of a fixed list that did
not know ubuntu-26.04.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 16:56:52 +02:00
kevinveenbirkenbachandClaude Opus 5.5 52ad8549e0 fix(ci): pin GitHub-hosted runners to ubuntu-24.04
`ubuntu-latest` moved from ubuntu-24.04 to ubuntu-26.04 on its own
schedule, in the middle of run 39166850273, and every job that landed on
the new image met a different OS: sudo-rs instead of sudo, no ip_tables
loaded, and now the NFS probe-write of svc-storage-nfs-client failing on
26.04 swarm nodes. The same branch went red without a code change.

Every `runs-on` now names `ubuntu-24.04`. GitHub still rebuilds that image
weekly, so patches and tool updates keep arriving; only the release jump
becomes a deliberate change of the label. The CodeQL job drops its dead
swift/macos-latest branch, since no swift language is in its matrix. act
already maps ubuntu-24.04 to the local platform image.

A lint rejects any job whose `runs-on` contains a `*-latest` label.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 15:57:12 +02:00
evangelostsak 072336e0ed docs(cheatsheet): list i8-release-article 2026-10-19 15:45:16 +02:00
evangelostsak b750d361c8 docs(agents): add the release article procedure 2026-10-19 15:45:15 +02:00
kevinveenbirkenbach d0698daa5e Merge pull request #414 from pragepani/feature/web-app-wazuh/add-role
feat(web-app-wazuh): add Wazuh SIEM role with OIDC/LDAP RBAC
2026-10-19 14:35:24 +02:00
kevinveenbirkenbach 19914777c4 Merge remote-tracking branch 'origin/main' into fix/compose/primary-net-ip-range 2026-10-19 09:46:19 +02:00
kevinveenbirkenbachandClaude Opus 5.5 dd955a71a6 style(markdown): pin list markers to dash and convert every list
The 16.0.0 entry pkgmgr wrote on top of CHANGELOG.md uses "-" bullets
while every older entry uses "*". MD004's default "consistent" style takes
the marker of the first list in a file, so lint-markdown reported 400
MD004 findings in CHANGELOG.md and the pre-push gate refused the release
push.

MD004 is now pinned to "dash", the marker pkgmgr and the changelog skill
write, and make autoformat (markdownlint-cli2 --fix) converted the lists
of the 72 files that still used "*". Only list markers changed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 23:04:02 +02:00
kevinveenbirkenbachandClaude Opus 5.5 d2b33a3b2a fix(compose): keep dynamic addresses off the stack's static IPs
compose/cache.shared.override.yml attaches every worktree stack's
infinito service to the primary's network (infinito-nexus-core_default,
172.30.0.0/24) without an ipv4_address. The default network declared
no ip_range, so Docker IPAM handed out the lowest free address and the
worktree stacks took 172.30.0.2, .3, .8, .9 and, whenever the primary
container was down, .10, the primary's INFINITO_IP4. The primary's
`make compose-up` then failed with "Address already in use", and with
it `make quality-high` on main.

The default network now declares ip_range: ${INFINITO_IP_RANGE}, the
upper half of INFINITO_SUBNET. Every static address of the stack (.1,
.4 to .6, .10, .53) sits in the lower half, so a container without a
static address can no longer take one.

INFINITO_IP_RANGE is derived from the final INFINITO_SUBNET after
custom.env is applied, because a worktree pins its subnet there and
`make dotenv-force` regenerates without it in the environment. Existing
worktrees therefore get their own slot's range without a new pin.

A lint checks that every static IP in default.env and every
172.30.${slot}.N pin in scripts/system/worktree/up.sh lies below the
pool.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 21:44:16 +02:00
kevinveenbirkenbach da449f8894 Merge pull request #323 from evangelostsak/feature/svc-net-wireguard
feat(svc-net-wireguard): Dockerized WireGuard role + test-e2e-cli DinD e2e
2026-10-18 19:50:42 +02:00
kevinveenbirkenbach 5601592872 Merge pull request #989 from infinito-nexus/feature/fuzz/yaml-bootstrap-differential
feat(fuzz): fuzz the bootstrap YAML reader against PyYAML weekly
2026-10-18 13:29:43 +02:00
kevinveenbirkenbach 356ade4dd6 Merge remote-tracking branch 'origin/main' into fix/ci/affected-roles-skip-tests 2026-10-18 13:12:12 +02:00
kevinveenbirkenbachandClaude Opus 5.5 9a8cc70dbf fix(ci): stop a change under tests/ from deploying every role
scripts/meta/resolve/diff/affected_roles.sh emits __ALL__ as soon as
one changed path outside roles/<role>/ is not a .md or .rst file. A
role fix that also adds its unit test under tests/unit/python/roles/
therefore deployed the whole matrix: PR #982 changed
roles/web-app-zammad/ plus
tests/unit/python/roles/web-app-zammad/files/test_search_allocation_precheck.py,
and its "Detect affected roles" job logged "Resolver output: __ALL__".

Paths under tests/ now join the .md/.rst skip-list. No role deploy
reads the top-level tests/ tree, and those suites run in their own
jobs whatever the whitelist says. A diff of only skipped paths keeps
falling back to __ALL__, as before. The same resolver feeds
effective_whitelist.sh, so the narrowing applies to every diff-driven
run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-18 13:04:50 +02:00
evangelostsak bc4db9fb9f docs(ci): drop the INFINITO_SWARM_TRANSPORT_BENCH variable 2026-10-18 01:01:10 +02:00
kevinveenbirkenbachandClaude Opus 5.5 088c8be14f fix(ci): pull workspace images through the GHCR mirror like the deploy jobs
The workspace jobs pulled every image anonymously from Docker Hub and
two of them failed on its rate limit in run 39059128678 (#990): the
fedora swarm drill on busybox:1.38 on all three nodes, the centos
compose drill while building tor-smtp_custom. The regular deploy jobs
pull through the GHCR mirror, but the mirror was tied to being a real
GitHub runner: Profile.image_mirror_enabled() returned
runs_on_github(), and the swarm routine generated mirrors.yml only when
cli.meta.runtime reported github, which is act inside make
swarm-zombie.

The mirror is now its own capability, INFINITO_GHCR_MIRROR (next to
INFINITO_GHCR_MIRROR_PREFIX), written as a run fact like
INFINITO_CACHE_STACK: true on a real GitHub runner,
false everywhere else, and a non-empty exported value wins for the run.
Profile.image_mirror_enabled() reads the declaration and keeps
runs_on_github() as the fallback, and 02_provision_inventory.sh gates
on the same value instead of the runtime name. make swarm-zombie
forwards it into act through ACT_ENV, since act ignores the host env.

call-test-workspace.yml declares INFINITO_GHCR_MIRROR=true and passes
INFINITO_GHCR_MIRROR_PREFIX into the workspace container. Nothing else
of the workspace changes: is_ci, runs_on_github, the cache stack and
the docker root stay local-like. The step that loads the rescue paths
now removes the .env it generated on the runner, because on debian
rows load.sh sourced it inside the container and the run inherited
INFINITO_RUNNING_ON_GITHUB=true.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 22:40:13 +02:00
kevinveenbirkenbachandClaude Opus 5.5 a598b67d75 feat(fuzz): fuzz the bootstrap YAML reader against PyYAML weekly
OpenSSF Scorecard reports no fuzzer integration (code scanning alert
507, issue #853). tests/fuzz/_yaml_bootstrap.py is an atheris harness
that feeds arbitrary input to utils.yaml_bootstrap.load_block and fails
whenever the reader accepts a document that load_yaml_str parses
differently or rejects. That is the contract the module's docstring
states, and the existing property test only samples it. The leading
underscore keeps unittest discovery from importing it, because atheris
is only installed with the fuzz extra.

cron-security-fuzz.yml runs the harness for 15 minutes every Sunday and
on demand, on ubuntu-latest, and uploads crashing inputs as the
fuzz-crashes artifact. atheris 3.1.0 ships x86_64 manylinux wheels for
CPython 3.12 to 3.14 only, so it lives in its own `fuzz` extra and
stays out of every other install path. tests/fuzz/ is not part of
`make test`.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 18:46:26 +02:00
evangelostsak e62ed8c56f Merge remote-tracking branch 'upstream/main' into feature/svc-net-wireguard 2026-10-17 09:34:00 +02:00
evangelostsak 1b19fe7df3 docs(requirements): 039 test full meshes on the WireGuard role's own CI row
Compose app rows no longer spend deploy time on WireGuard. The full-mesh
test runs on svc-net-wireguard's own row, the role deploys where its group
puts it, and production keeps WireGuard for every role.
2026-10-16 21:26:16 +02:00
kevinveenbirkenbachandClaude Opus 5.5 d36e203171 fix(cache): render the applications carrier without the caller's application_id
`lookup('tls', ...)` aligns a cross-app domain to the consumer named by
`application_id` (utils/tls_common.py `align_domain_to_consumer`): a
clearnet-primary consumer gets the clearnet sibling of an onion-primary
target. The carrier key does not cover `application_id`, so a park that
renders inside a role hands that role's alignment to every later role
whose key matches.

The constructor and `tasks/utils/setup/role.yml` park at play scope,
where `application_id` is undefined. The re-park in
`roles/sys-token-store/tasks/write.yml` (67f6c8d7e8) and the nested-load
re-park render inside the caller: `svc-prx-openresty` at the preload
loader, `web-app-stalwart` or a provider role on the NFS host, the web
app itself under `sys-stk-front-base`. In a tor deploy that turned onion
targets into clearnet domains for onion-primary roles served from such a
park, and baked the caller's group into Nextcloud's sociallogin
`groupMapping`.

Drop `application_id` from the render's variables and from the
templar's for the duration of the render, so every park carries the
play-scope result the constructor parks have always carried. Rename the
nested re-park task so its log lines do not read as a role boundary.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 21:25:43 +02:00
kevinveenbirkenbachandClaude Opus 5.5 a58abd470c fix(cache): re-park the applications carrier after every nested app load
Job 116975298820 (Nextcloud#5, swarm, arch, btrfs, main 463df06202) hit
its budget (rc=124 after 20136 s). The app phase loads every service as a
nested `tasks/utils/load/app.yml` include under sys-service-loader, so
`tasks/utils/setup/role.yml` parks no carrier between `svc-virt-kata`
(L6073) and `update` (L38213). The only re-park in that stretch is the one
in `roles/sys-token-store/tasks/write.yml`, and Stalwart's user management
reaches it on the manager alone. After its last token write (L23574) the
manager carried the new key while both workers kept the old one and
rendered the full tree on every task: 85 non-wait tasks of 30 s or more, 63 min
from Keycloak (L25641) to the carry past `update` (L38237).

Park the carrier after every nested load on every host of the include.
A re-park whose key still matches serves the carried payload without
rendering.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 20:53:12 +02:00
Prageeth Panicker 5e39433ed1 Merge remote-tracking branch 'origin/main' into feature/web-app-wazuh/add-role 2026-10-16 11:40:30 +00:00
kevinveenbirkenbach 846a734b03 Merge branch 'fix/cache/carrier-token-stall' 2026-10-16 11:12:39 +02:00
kevinveenbirkenbachandClaude Opus 5.5 67f6c8d7e8 fix(cache): keep the applications carrier valid across token store writes
Since 778c18fb23 the carrier key holds the tokens file's mtime and size.
sys-token-store changed that stat on every inclusion (00_core.yml
touched the file) and on every persisted token, and nothing re-parked a
carrier afterwards. Every later task's fresh worker then rendered the
applications SPOT cold, 30 to 80 s each. On main fea6f31d9f (run
38812964308) seven heavy jobs logged 194 to 287 such tasks and ran out
of the 20400 s budget; the same jobs before 778c18fb23 logged 65 to 83,
all of them real waits.

- 00_core.yml touches the store with modification_time and access_time
  preserved, so it only creates a missing file. In swarm the controller
  sees the store over NFS with attribute caching, and the touch alone
  made the second pass go cold without any write.
- write.yml re-parks the carrier when the persist or the controller
  mirror changed the store. Both run once, so every host that ran the
  include gets the same verdict.
- tasks/utils/setup/role.yml re-parks after every role on every host,
  so hosts that did not run the writing role recover too. Where the
  key still matches this serves the carried payload; measured 0.1 s per
  role in a local compose deploy.
- The tokens file enters the key as the SHA-256 of its content,
  memoised per inode, mtime and size, so a touch no longer changes the
  key. A stat that still matches serves the memo (1.67 us against
  1.41 us for the old stat signature), and a stale stat keeps key and
  YAML cache on the same old content instead of pairing new content
  with an old key.
- applications_carrier opens the tokens file before it computes the
  key, so on the NFS-mounted controller the parked key reflects the
  revalidated attributes rather than a cached stat that changes a
  minute later.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 11:11:47 +02:00
evangelostsak 6cfe1f1f52 docs(requirements): list 038 under the archive 2026-10-16 08:46:23 +02:00
evangelostsak 0c42f53ca8 docs(requirements): archive 038, every criterion closed
The last two criteria closed on fork run 38836531620, a manual steer of
svc-db-redis#0 in compose with the vpn axis enforced. Its job log shows
INFINITO_COMPOSE_VPN=true reaching the step, svc-net-wireguard deployed beside
the app and skipped on the CI host, which holds no mesh, and the CLI test of
svc-net-wireguard writing two full meshes of two members each. The inner play
passed four handshake gates and four MTU probes, and the test printed all six
reachability assertions: I and II reach each other, II and III reach each
other, I and III do not.

With nothing left open, make requirements-archive moved its heading into the
README and deleted the file.
2026-10-16 08:46:23 +02:00
evangelostsak 20c42ab48b docs(requirements): 038 full-mesh WireGuard for Compose deployments
Compose hosts of one inventory join full meshes that each role opts into
through its networks.meshes, with no swarm manager and nothing hardcoded into
a role. The vpn axis decides per CI row, on a role's smallest variant only,
and a CLI test proves the shape on three throwaway hosts: I and II reach each
other, II and III reach each other, I and III do not.
2026-10-16 03:40:15 +02:00
evangelostsak 91de85a4d5 docs(requirements): list 037 under the archive 2026-10-16 01:43:33 +02:00
evangelostsak 86745f92ec docs(requirements): archive 037, every criterion closed
Ticked with evidence from the local lab and the fork's CI runs: both VPNs
including the backup host, swarm advertising on the mesh, the prologue and
both passes over the mesh, key rotation converging, the mesh-off arm, the
axis rotation, pin and title, the measured MTU, nothing naming a mesh, the
three-mesh example, the role installing its own tooling, the NFS mount over
the mesh, the controller reaching the hosts it deploys over, the gate, and
swarm control, overlay and NFS carried over the mesh.

Dropped: rotating over a live mesh connection, which the prologue avoids by
rotating before the transport moves; the role being inert in compose, which
the backup host now contradicts; the failing-mount half of the NFS
criterion; and the port-reachability criterion with its claim in the user
story.

With nothing left open, make requirements-archive moved its heading into the
README and deleted the file.
2026-10-16 01:43:33 +02:00
Prageeth Panicker 8e4ba0f8a9 Merge remote-tracking branch 'origin/main' into feature/web-app-wazuh/add-role 2026-10-15 21:58:47 +00:00
evangelostsak 1c5ba164f2 Merge remote-tracking branch 'upstream/main' into feature/svc-net-wireguard
No conflicts across 121 incoming commits. The one file both sides changed is
tasks/stages/01_constructor.yml: upstream parks an applications carrier for
the swarm bootstrap roles after the add_host tasks, and keys the carrier on
the tokens file as well. This branch's mesh bootstrap opens and drops its own
block-scoped carrier before that point, so both keep working as written.

Upstream also brings ruff 0.17.0, distro-derived env keys, a scoped act outer
teardown, the stalwart relay rule, the onion apex redirect and image and
version updates; ruff 0.17 reformats nothing on this branch.
2026-10-15 21:27:11 +02:00
kevinveenbirkenbach 91d2236803 Merge branch 'main' of github.com:infinito-nexus/core 2026-10-15 10:57:49 +02:00
kevinveenbirkenbach b637742f96 Merge remote-tracking branch 'origin/main' into fix/env/distro-derived-keys/794 2026-10-15 01:07:53 +02:00
evangelostsak 8386823b2a Merge remote-tracking branch 'upstream/main' into feature/svc-net-wireguard
No conflicts. The 14 incoming commits fix the n8n gateway probe trigger under
n8n 2, let stalwart address bans expire, keep the Docker apt key when its
refresh is refused, leave eol roles out of image discovery, stop the release
backfill below the oldest buildable tag, and provision the mermaid browser
only in install-lint. None of them touches the mesh, swarm, NFS, network or
workflow files this branch changes.
2026-10-15 00:38:14 +02:00
evangelostsak 6f4783d3ac docs(requirements): meshes as the roles' own network declarations
Checked: every role ships its mesh fields empty, one module reads them, and
the three-mesh layout deployed svc-dns-unbound end to end on the local lab
with the same members and addresses as before the move.
2026-10-14 15:03:41 +02:00
kevinveenbirkenbach efb816d93b Merge branch 'main' of github.com:infinito-nexus/core 2026-10-14 13:35:17 +02:00
evangelostsak eb90249d93 docs(requirements): add the multi-mesh and example criteria to 037
The multi-mesh spoke criterion is checked: the three-mesh example deployed
svc-dns-unbound end to end on the local lab with the NFS server up on beta and
gamma. The other two stay open until the CI dispatch has run.
2026-10-14 11:23:23 +02:00
Prageeth Panicker 06f0b42f12 Merge remote-tracking branch 'origin/main' into feature/web-app-wazuh/add-role 2026-10-14 09:00:39 +00:00
kevinveenbirkenbachandClaude Opus 5.5 8a29ba0bfd fix(images): leave eol roles out of image discovery
The scheduled mirror job has failed every day since 2026-09-25 on the same two
images: quay.io/minio/minio and quay.io/minio/mc answer `unauthorized` to
anonymous pulls ("2/197 failed", run 38352569503). Both belong to
web-app-minio, an eol role outside the lifecycle envelope that default.env
tests, so no CI deploy pulls them.

iter_role_images now skips every role that is_maintained() reports as
unmaintained, the check the version updaters already apply to the same list.
On the tree the discovery yields 187 images instead of 192; the five it drops
belong to the four eol roles web-app-confluence, web-app-jira, web-app-minio
and web-app-phpldapadmin. The mirror sync, resolver and wait read this list,
and their descriptions and mirror.md now say so.

The roles directory is resolved first: is_maintained reads a relative path as
a role name and would keep every role.

475ab9b386 on feature/store-i18n takes the same approach with a lifecycle
reader of its own; main already has is_maintained for it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-14 01:19:28 +02:00
kevinveenbirkenbachandClaude Opus 5.5 3fff830b9c feat(skills): add i8-cleanup on top of the portable cleanup skill
Routes disk and /tmp cleanup through the cleanup skill and adds the repository rules: compose-project attribution, the shared cache stack that is never a candidate, act and swarm keep rules, teardown targets with what each destroys, and the targets that must never run as a cleanup step. Listed in the agent cheatsheet.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 21:57:20 +02:00
kevinveenbirkenbachandClaude Opus 5.5 1079f48feb fix(env): derive the image and container names from the distro under test
A compose deploy job labelled centos or arch built its stack image from
pkgmgr-debian and ran it as infinito_nexus_debian (#794). distros.sh
exports INFINITO_DISTRO per iteration and sources load.sh again, but the
loader returned early because INFINITO_ENV_LOADED and the .env mtime were
unchanged. A full reload would not have helped either: the debian values
were already exported, so the restore step kept them as caller intent.

load.sh now records the distro it loaded for. Another INFINITO_DISTRO
defeats the early return and drops INFINITO_CONTAINER,
INFINITO_PARENT_IMAGE and INFINITO_IMAGE, the three keys the env handlers
derive from the distro. When the requested distro also differs from the
one .env was generated for, the loader sources a set that
`python -m cli.meta.env --output` generates for it in a private temp
directory and leaves .env untouched, so a local multi-distro run does not
switch the checkout's distro. A caller value set for the loaded distro
still wins.

Verified: tests/unit/python/scripts/meta/env/test_load.py and the new
distros.sh case pass. Against main's loader both fail with the symptom of
the issue: INFINITO_DISTRO=centos next to infinito_nexus_debian and
pkgmgr-debian:stable, and distros.sh handing debian, arch and centos the
same debian parent. shellcheck is clean.

Consequence: CI jobs labelled arch, ubuntu, fedora or centos now build
and deploy that distro, so a failure that shows up there was masked
before.

feature/store-i18n carries 3f973eb137, which resolves the parent image
for scripts/image/push.sh on its own, and 05e4dbafcb, which inserts the
INFINITO_INSTANCE slot check into the block this commit restructures. The
merge keeps the slot check ahead of the distro check.

Closes #794

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 21:30:48 +02:00