Commit Graph
14682 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 4.7 13626fdfd8 fix(web-app-bookwyrm): compile SCSS themes before collectstatic
BookWyrm ships its themes as `bookwyrm-light.scss` / `bookwyrm-dark.scss`
in `bookwyrm/static/css/themes/`, not pre-compiled CSS. The role startup
chain ran `collectstatic --noinput` directly, which hashes existing
files into the staticfiles manifest but does not compile SCSS. As a
result, the manifest never contained `css/themes/bookwyrm-light.css`,
and every request that resolved a `{% sass_src %}` tag for that theme
raised:

    ValueError: Missing staticfiles manifest entry for
                'css/themes/bookwyrm-light.css'

Django turned that into a 500 on the `/setup` landing page. Variant 0
hid the breakage because oauth2-proxy issues a 302 before the request
reaches BookWyrm; variant 1 (no SSO) exposed it and the baseline
Playwright check (`status < 500`) failed.

Insert `manage.py compile_themes` between `migrate` and `collectstatic`
so the theme CSS is on disk before the staticfiles manifest is built.

Validated in the live container before the repo change:
  compile_themes → "Compiled SASS/SCSS file: bookwyrm-light.scss" + dark
  collectstatic  → "2 static files copied"
  HUP gunicorn   → curl https://book.infinito.example/ = 200 (was 500)

`make compose-deploy mode=update apps=web-app-bookwyrm variant=1` then
ran Playwright green end-to-end (failed=0, 2 passed + 4 passed across
the two sync/async passes).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 12:51:28 +02:00
kevinveenbirkenbach 9699ab33b3 Release version 9.0.2 v9.0.2 2026-05-29 12:47:55 +02:00
kevinveenbirkenbach 85c1ed1a6e Merge branch 'main' into feature/web-app-zammad
# Conflicts:
#	CHANGELOG.md
#	packaging/arch/PKGBUILD
#	packaging/debian/changelog
#	packaging/fedora/infinito-nexus.spec
#	pyproject.toml
#	roles/sys-svc-compose/README.md
#	scripts/docker/entry.sh
#	scripts/github/update/image_versions.sh
#	scripts/github/update/repository_refs.sh
2026-05-29 11:18:28 +02:00
kevinveenbirkenbachandClaude Opus 4.7 c48386eeea chore(web-app-zammad): drop empty TODO.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 11:13:00 +02:00
kevinveenbirkenbachandClaude Opus 4.7 82491791e6 refactor(web-app-zammad): collapse helpdesk alias into single canonical zammad hostname
meta/server.yml: drop the helpdesk.<domain> canonical + zammad.helpdesk.<domain>
alias pair; the role now publishes only zammad.helpdesk.<domain> as its
canonical vhost.

Also removes the alias-domain Playwright spec that asserted the alias-to-canonical
rewrite — no alias remains to assert.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 11:08:41 +02:00
kevinveenbirkenbachandClaude Opus 4.7 345d33066a refactor(web-app-zammad): drop mail-to-ticket test, auto-link OIDC by email, trim role-wide comments
- Drop test-mail-to-ticket Playwright spec + its playwright.env keys; mail/SMTP
  integration is mostly testing Mailu, not Zammad, and required either a /28
  subnet resize or an email-lookup-plugin shared-mode branch to actually pass.
- Set auth_third_party_auto_link_at_inital_login=true in apply_oidc_settings.rb
  so the first OIDC sign-in of an LDAP-synced user links to the existing record
  by email instead of returning 422. Drops the conditional LDAP user_filter
  workaround and the LDAP_OIDC_COEXISTS env wiring that propped it up.
- Replace the RUBYOPT-loaded Telegram constant shim with a bind-mounted
  TelegramHelper stub that cuts the require 'telegram/bot' chain (the gem's
  Zeitwerk bypasses Kernel#require intercepts under bootsnap).
- Strip verbose docblocks across vars/tasks/templates/scripts/playwright; keep
  only WHY-non-obvious notes (upstream gem mismatches, security defaults, the
  intentional inital-typo).
- Fix broken Docker Compose CLI docs URL in sys-svc-compose/README.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 11:04:23 +02:00
kevinveenbirkenbachandClaude Opus 4.7 c1fb08e947 chore(web-app-bluesky): nest nocheck markers under acl
Move the three `# nocheck:` markers from top-level into the `acl:` block
they describe, and drop the verbose narrative comment above the ACL.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 10:37:22 +02:00
kevinveenbirkenbachandClaude Opus 4.7 f286ce54dd fix(update/open_pr): scope dedup to changed files
The previous tree-hash dedup compared whole-commit trees, so unrelated
drift on main (e.g. a manual edit to any roles/* file) caused the same
auto-update delta to appear "new" each daily cron and a fresh PR to open.

Now: fingerprint only the files that this run actually committed
(git diff --name-only HEAD~1 HEAD), both locally and on each candidate
open PR with the same UPDATE_BRANCH_PREFIX. If any open PR carries the
identical content for those files, skip push + PR creation entirely.

Branch name now carries the fingerprint's short hash so parallel PRs
of the same class can coexist (the close-superseded loop is dropped).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-29 10:37:21 +02:00
kevinveenbirkenbach 54835d6430 Merge pull request #283 from infinito-nexus/dependabot/github_actions/actions/cache-5
chore(deps): bump actions/cache from 4 to 5
2026-05-29 09:22:51 +02:00
kevinveenbirkenbach 4ca7f19415 Merge pull request #282 from infinito-nexus/dependabot/github_actions/actions/setup-node-6
chore(deps): bump actions/setup-node from 4 to 6
2026-05-29 09:22:02 +02:00
dependabot[bot] c4d3ac136e chore(deps): bump actions/cache from 4 to 5
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-29 01:48:27 +00:00
dependabot[bot] 3917241842 chore(deps): bump actions/setup-node from 4 to 6
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 6.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-29 01:48:23 +00:00
kevinveenbirkenbachandClaude Opus 4.7 c680be12ea fix(image/build): propagate INFINITO_VENV_DIR to docker build
scripts/image/build.sh drives 'make build' and the test-environment
matrix's dev-image build, but missed the new INFINITO_VENV_DIR build
arg. Dockerfile's ARG resolved to empty, ENV set INFINITO_VENV_DIR=""
in the image, and entry.sh's assert tripped on first --compile.

Adds the assert and the matching --build-arg, parallel to the
INFINITO_SRC_DIR plumbing already in this file and to the equivalent
plumbing in scripts/image/push.sh.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 22:33:15 +02:00
kevinveenbirkenbach ec5b775f11 Merge pull request #279 from infinito-nexus/update/docker-image-versions-20260528
update(images): update Docker image versions
2026-05-28 22:17:01 +02:00
kevinveenbirkenbach 6854838811 Update Friendica version to 2026.01 2026-05-28 22:16:10 +02:00
infinito-nexus-updater[bot] 3fdc5e5b4d update(images): update Docker image versions 2026-05-28 20:15:15 +00:00
kevinveenbirkenbach ba54a429e7 Merge pull request #280 from infinito-nexus/update/repository-refs-20260528
update(repos): bump git refs to latest semver tags
2026-05-28 22:14:56 +02:00
infinito-nexus-updater[bot] 369577ae31 update(repos): bump git refs to latest semver tags 2026-05-28 20:12:38 +00:00
kevinveenbirkenbachandClaude Opus 4.7 00c4246c3a refactor(env): introduce INFINITO_VENV_DIR SPOT, fix dev image build
Adds INFINITO_VENV_DIR=/opt/venvs/infinito to default.env (registered
in passthrough's STATIC_KEYS so make dotenv propagates it to .env) and
threads it through the build chain: compose.yml forwards it as a build
arg; scripts/image/push.sh asserts and --build-args it; the Dockerfile
declares the matching ARG/ENV and derives PYTHON/PIP/PATH from the
variable. scripts/meta/env/python.sh now prefers the value when set
before its fallback discovery so the SPOT is effective in env
resolution.

Fixes the dev image build regression where 'infinito --version' in
scripts/docker/entry.sh exited 127. Root cause: the Dockerfile RUN
SHELL uses bash -lc, which sources /etc/profile and resets PATH to
the Debian default, dropping ${INFINITO_VENV_DIR}/bin from it. The
fix invokes the script via its absolute path "${INFINITO_VENV_DIR}/bin/infinito"
so the post-install version check no longer depends on a PATH that
the login-shell init has just clobbered.

scripts/lint/wrapper.sh's existing PATH-reset note now references the
variable instead of the literal path. test-install-make.yml and
test-install-pkgmgr.yml read INFINITO_VENV_DIR from default.env up
front, pass it into their pkgmgr containers, and source the venv
activate script via the variable.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 22:12:19 +02:00
kevinveenbirkenbach b9a3a8762a Release version 9.0.1 v9.0.1 2026-05-28 21:19:49 +02:00
kevinveenbirkenbachandClaude Opus 4.7 3b048ce748 ci(workflows): add npm + ansible-galaxy caching where missing
lint-markdown and update gain cache: "npm" on setup-node so the
markdownlint-cli2 global install and the skills-updater node fetches
restore from ~/.npm. lint-ansible gains a dedicated actions/cache step
for ~/.ansible/collections keyed on the combined hash of
requirements.galaxy.yml and requirements.git.yml so the
ansible-galaxy collection install no longer re-downloads 50+MB of
collections on every run.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 21:06:34 +02:00
kevinveenbirkenbachandClaude Opus 4.7 a561aa76b5 ci(push): skip push CI when an open PR already covers the branch
push_ci_policy.sh now hard-fails on missing GH_TOKEN/GITHUB_REPOSITORY
and, for non-main branches, calls gh pr list to detect whether the
push is already covered by an open pull request. If so, emits
should_run=false (skip_reason=pr-ci-covers-this-push) so the push
workflow exits cleanly and the pull_request workflow handles the
actual CI run.

To absorb the bot's push -> gh-pr-create latency on update/* and
alert-autofix-* branches, the PR check retries up to 10x with 2s
sleeps before falling through to a real CI run. Human branches
(feature/**, hotfix/**, fix/**, chore/**) check once with no delay.

entry-push-latest.yml's run-policy step now forwards GH_TOKEN so the
gh call works against the repo.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 21:06:34 +02:00
kevinveenbirkenbachandClaude Opus 4.7 af628847bb fix(update/open_pr): delete head branch when closing superseded PRs
The previous gh pr close call left the bot's daily update branch
behind on the remote, so stale update/<prefix>-YYYYMMDD refs
accumulated indefinitely. --delete-branch removes the head ref on
close. Scope-safe because the loop only iterates branches matching
${UPDATE_BRANCH_PREFIX}-.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 21:06:34 +02:00
kevinveenbirkenbachandClaude Opus 4.7 915c7d4894 ci(workflows): enable pip cache and pin python 3.12 everywhere
Adds cache: pip + cache-dependency-path: pyproject.toml to every
setup-python step across .github/workflows/ and bumps the python-version
pin on every workflow that still declared 3.11 to 3.12 so the project's
declared >=3.11 range collapses to a single interpreter version in CI.

Cold runs hit pyproject.toml-keyed pip cache; subsequent runs skip the
full install pull and warm-restore in seconds. Highest impact on the
test-deploy-* and test-code-* matrices that ran make install fresh on
every PR.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 21:06:34 +02:00
kevinveenbirkenbachandClaude Opus 4.7 806a3e93db ci(pr-flow): gate env-matrix on cross-cutting diffs, dedup resolution
Adds a detect-affected-roles job to entry-pull-request-change.yml that
runs the affected-roles resolver upfront on host python (via make
install) and emits whitelist + roles_only. ci-orchestrator skips
test-development when roles_only=true; done job tolerates the skip.
entry-manual derives roles_only from its whitelist input.

affected_roles.sh now invokes the resolver host-side only (compose-exec
fallback removed; it was a no-op in every existing caller because
compose was never up there, always emitting __ALL__ fail-safe). The
PR-flow gate consolidates what test-deploy-* used to recompute per
job; downstream effective_whitelist.sh now consumes the pre-resolved
whitelist verbatim.

Test fixture switched from a fake docker binary to a fake PYTHON
binary and clears BASH_ENV so the bash-startup env loader does not
reset PYTHON.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 21:06:34 +02:00
kevinveenbirkenbachandClaude Opus 4.7 7e38fca6d7 docs: fix broken links to archived requirement files
Drops markdown links in 017/018 and role TODOs that pointed at the
016 and 019 requirement files archived in 027ba06ee. The text
references stay; only the now-broken link targets are removed so the
markdown-links lint passes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 21:06:34 +02:00
kevinveenbirkenbachandClaude Opus 4.7 ce078d1d78 docs(requirements): archive 7 completed requirements
Moves 008/009/010/011/016/019/020 to the archive list in
docs/requirements/README.md and removes the per-requirement files;
their acceptance criteria are considered closed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 21:06:33 +02:00
kevinveenbirkenbach 3d7bb7b983 Release version 9.0.0 v9.0.0 2026-05-28 18:37:57 +02:00
kevinveenbirkenbach 9e615e0bba Merge pull request #276 from kevinveenbirkenbach/feature/req-21-sso-flavor-migration
refactor(sso)\!: unify oauth2 + oidc into services.sso block (req 21)
2026-05-28 18:11:39 +02:00
kevinveenbirkenbach 84bd56e72c Merge branch 'main' into feature/req-21-sso-flavor-migration 2026-05-28 18:07:28 +02:00
kevinveenbirkenbach 21e878d7cd Release version 8.0.5 v8.0.5 2026-05-28 17:50:39 +02:00
kevinveenbirkenbachandClaude Opus 4.7 8e293bd921 fix(compose-deploy): stop persisting runtime routing knobs into .env
Root cause of step-08 deploy failures across all 4 test-development
distros in run 26572559126: `make compose-deploy mode=reinstall
apps=web-app-dashboard INFINITO_SERVICES_DISABLED=matomo` (step 07)
made make export the cmdline var into the recipe's shell env, which
reached `runner.py` → `make setup` → `make dotenv`. The dotenv
generator's `setdefault` then baked the runtime-only value into the
on-disk `.env`. Step 08 sourced that .env, filtered `web-app-matomo`
out of its primary apps, and exited with "All primary apps disabled".

Fix:

- Drop the 7 routing knobs (apps, mode, purge, bundles, disable,
  full_cycle, variant) from `passthrough.STATIC_KEYS` and from
  `default.env`. They are per-invocation; .env is the persistent SPOT
  and must not capture them.
- Switch every consumer from `os.environ["KEY"]` strict access to
  `os.environ.get("KEY", "")` so the missing-key path stops at "no
  filter" instead of a KeyError.
- Rename the env-var surface to match the make-alias surface 1:1
  (lowercase): INFINITO_APPS → apps, INFINITO_SERVICES_DISABLED →
  disable, INFINITO_BUNDLES → bundles, INFINITO_FULL_CYCLE →
  full_cycle, INFINITO_VARIANT → variant, INFINITO_DEPLOY_MODE → mode,
  INFINITO_PURGE_ENTITIES → purge. The make alias was the user-facing
  name in every doc; routing-knob env vars now use the same name so
  the cmdline form, the recipe env-prefix, and the consumer reads
  all line up.
- Collapse the Makefile `compose-deploy` recipe to just the two
  knobs whose alias differs from the env name (`type` →
  INFINITO_DEPLOY_TYPE, `debug` → INFINITO_DEBUG). GNU Make
  auto-exports cmdline variables into the recipe's shell env, so the
  identical-name `$(if $(apps),apps="$(apps)")` lines were pure
  noise.
- Drop `disable: ${disable}` from compose.yml. The dev CLI builds
  `extra_env` per `docker exec` call and forwards `disable` via
  `-e`, so the container env never needs the value frozen at
  compose-up time.
- Update the 3 actual leak call sites
  (07/08/09_deploy_*.sh) to the make-alias form
  (`disable=matomo`, `full_cycle=true`, `variant=1`).
- Add `SIM112` to ruff's ignore set: the lowercase env names are
  the deliberate make/env parity, not a typo.

Repro before fix: `INFINITO_SERVICES_DISABLED=matomo make dotenv`
wrote `INFINITO_SERVICES_DISABLED=matomo` to `.env`. After fix:
`disable=matomo make dotenv` leaves `.env` untouched.

Tests: `make test` and `make autoformat` green (2711 tests, 8 lint
sub-targets).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 17:47:03 +02:00
kevinveenbirkenbachandClaude Opus 4.7 13ef860025 docs(sys-svc-compose): drop dead Compose CLI reference link
`https://docs.docker.com/compose/cli-command/` returns 404; Docker
folded the CLI reference into the main Compose docs already linked
above. Removing the broken entry keeps the URL-reachability lint
happy without losing a unique destination.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 16:25:12 +02:00
kevinveenbirkenbachandClaude Opus 4.7 ad270fbbeb feat(cli): add --version / -V flag to infinito CLI
The Docker entry script's `[docker-infinito] Installed:` banner used
to call `pkgmgr version infinito`; after the pkgmgr removal that line
became `infinito --version || true`, which printed
`Error: command '--version' not found.` to stderr because the CLI's
argparse-style dispatcher treated `--version` as an unknown
subcommand.

Hook a real top-level flag into cli.core.app.parse_flags that prints
`infinito <version>` from importlib.metadata (single source of truth:
pyproject.toml's `version` field; falls back to `unknown` when the
package isn't pip-installed) and exits 0. entry.sh drops the
`|| true` since the call is now well-defined.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 16:24:06 +02:00
kevinveenbirkenbachandClaude Opus 4.7 3ffcc5e0ec feat(web-app-zammad): user-SPOT, LDAP source, Telegram boot shim, test fixes
User identity SPOT
- meta/users.yml gains zammad-api-bot (Basic-auth REST API bot) and
  zammad-wizard-bypass-admin (auto_wizard.json setup-bypass admin).
- vars/main.yml reads identity (login/email/firstname/lastname) via
  lookup('users', …); password stays in credentials/ to guarantee the
  shell-safe alphanumeric form needed for the Ansible→bash→docker-exec
  →Ruby ENV chain.
- auto_wizard.json.j2, apply_api_bot.rb, tasks/01_core.yml: consume the
  lookup-resolved identity.

Boot reliability
- templates/zz_telegram_constant_shim.rb.j2: pre-loaded via RUBYOPT;
  pre-declares the Telegram::Bot namespace and intercepts Kernel#require
  to refuse telegram/* loads, sidestepping the broken telegram-bot-ruby
  2.4.0 gem that crashes Zammad 6.5.0 boot. Telegram channel is inert.
- env.j2 sets RUBYOPT=-r/opt/zammad/zz_telegram_constant_shim.rb.
- tasks/01_core.yml stages the shim; compose.yml.j2 bind-mounts it into
  zammad-init/rails/websocket/scheduler/nginx.
- tasks/01_core.yml adds an explicit AutoWizard.setup post-init step
  (upstream zammad-init does NOT auto-process auto_wizard.json), which
  is what V2 (no-auth) and V3 (LDAP-only) need to skip the setup wizard.

LDAP source wire-up (TODO #1)
- files/scripts/apply_ldap_source.rb creates an LdapSource record
  pointing at svc-db-openldap (inetOrgPerson + groupOfNames mapping).
- tasks/01_core.yml runs it when services.ldap.enabled is true.

OIDC group→role mapping (TODO #3)
- templates/zz_oidc_group_role_mapping.rb.j2 patches Zammad's
  User.create_from_hash / update_from_hash to translate the RBAC
  group-path claim (e.g. /roles/web-app-zammad/administrator) into
  the matching Zammad role (Admin / Agent / Customer fallback).
- apply_oidc_settings.rb pins uid_field=preferred_username so OIDC
  matches the human-readable Keycloak username, NOT the sub UUID.
- compose.yml.j2 bind-mounts the initializer when OIDC is enabled.

Test coverage
- new test-login-via-ldap.js (driven only in LDAP-only V3).
- test-alias-domain.js accepts 2xx-direct OR 301-to-canonical
  (sys-svc-proxy renders aliases as 301 sources, not server-name
  aliases — server.yml updated to canonical=helpdesk + alias=
  zammad.helpdesk).
- test-mail-to-ticket.js: stage-level SMTP trace logging; reaches
  Mailu via host.docker.internal:465.
- test-ticket-reply-as-agent.js: scoped contenteditable lookup to
  .article-add to avoid hitting the ticket-title field.
- _shared.js: signInAsApiBot drives /api/v1/signin via the server-side
  APIRequestContext (shared cookie jar with the browser), unblocking
  the SPA-OIDC interlock.

SQL outsourcing
- templates/sql/grant_createdb.sql.j2: the CREATEDB grant now lives in
  a Jinja-templated .sql file; tasks/01_core.yml consumes it via
  lookup('template', …). Role name is rendered into the SQL by Jinja
  (NOT via database_query named_args), because psql parameter binding
  quotes string values as literals (`'zammad'`) which is invalid SQL
  for ALTER ROLE.

Misc
- meta/server.yml: canonical=helpdesk.<domain>, aliases=[zammad.helpdesk.<domain>]
  to match the 022 requirement (Decision #1).
- TODO.md drained — all seven items either landed or are explicitly
  documented as out-of-scope / brittle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 15:53:44 +02:00
kevinveenbirkenbachandClaude Opus 4.7 7ac77f0159 fix(sys-svc-compose): cap compose up handler at 30 min
Without a timeout, `docker compose up -d` blocks indefinitely on
`depends_on.condition: service_completed_successfully` when an upstream
container is stuck in a restart loop (observed: zammad-init crashing
at boot on the broken telegram-bot-ruby gem in Zammad 6.5.0; the play
hung 5+ hours before manual kill). Failing fast surfaces the broken
upstream and unblocks iteration.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 15:53:44 +02:00
kevinveenbirkenbachandClaude Opus 4.7 8ab37347b1 feat(test-e2e-playwright): add host.docker.internal:host-gateway to sidecar runs
Gives Playwright sidecars a stable name for the docker host so role specs
can reach services whose port is bound on the host (e.g. Mailu's SMTP
submission on 465/587 in the Zammad email-channel test) without
attaching to that service's docker network.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 15:53:44 +02:00
kevinveenbirkenbach 3748a01415 Merge remote-tracking branch 'origin/main' into feature/web-app-zammad 2026-05-28 15:53:44 +02:00
kevinveenbirkenbachandClaude Opus 4.7 1bbdbdb877 fix(update): load .env before invoking python updaters
`update.yml` jobs (Docker image versions, repository refs) shelled
straight into `python3 -m cli.contributing.update.{docker,repository}`
without sourcing the project dotenv. After eb4bcd23a removed the
`.get(..., default)` fallback in resolve_max_fetch_workers(),
KeyError: 'INFINITO_WORKER_FETCH' surfaced on every run.

Both wrapper scripts now `make dotenv` (idempotent) and `set -a; . .env;
set +a` before exec'ing the updater, restoring the SPOT env chain on
CI runners that don't go through compose.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 15:53:44 +02:00
kevinveenbirkenbach c28aaf0b2a Release version 8.0.2 2026-05-28 15:53:44 +02:00
kevinveenbirkenbachandClaude Opus 4.7 449612fa6b chore(pkgmgr): bump pin to v1.15.2
v1.15.2 ships the `alias: infinito` entry in pkgmgr's
src/pkgmgr/config/defaults.yaml so `pkgmgr install infinito`
(and `pkgmgr path/version infinito`) resolves again. Without
this bump, sys-cli, web-app-navigator and the test-install-pkgmgr
CI job stay broken on the upstream identifier-rename fallout.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 15:53:44 +02:00
kevinveenbirkenbachandClaude Opus 4.7 2883025c8e fix(docker): drop pkgmgr from dev container, install in-tree via make
`pkgmgr install infinito` started failing in CI after the floating
`pkgmgr-<distro>:stable` base image was rebuilt with kpmx 1.15.x, which
no longer registers the `infinito` identifier in its default config:

    Identifier 'infinito' did not match any repository in config.

The error string then flowed through `pkgmgr path infinito` in
entry.sh and was treated as the install directory, leading to
`make install` in a bogus cwd. This broke test-development,
test-install-pkgmgr, and build-ci-images for every distro.

The pkgmgr step in the dev Dockerfile is redundant — `make install`
runs `pip install -e .` which already produces the `infinito` CLI
shim via pyproject.toml's [project.scripts] entry. Drop the pkgmgr
calls, the rsync-into-INFINITO_PATH dance, and the `INFINITO_PATH`
variable; everything operates on `INFINITO_SRC_DIR` directly.

Production `pkgmgr install` paths (roles/sys-cli, roles/web-app-navigator,
.github/workflows/test-install-pkgmgr.yml) are intentionally untouched —
the test-install-pkgmgr job is what surfaces the upstream kpmx breakage.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 15:53:44 +02:00
kevinveenbirkenbach 67c485c888 Release version 8.0.1 2026-05-28 15:53:44 +02:00
kevinveenbirkenbachandClaude Opus 4.7 8b9d196266 feat(make): add make requirements-archive target
Installs kpmx and runs `pkgmgr archive docs/requirements` in one
shot. The requirements-completeness lint failure message now points
contributors at this target instead of asking them to invoke pkgmgr
directly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 15:53:44 +02:00
kevinveenbirkenbachandClaude Opus 4.7 af0daea94a refactor(test/requirements-completeness): inline discovery and unchecked counter
The lint test only used two tiny helpers from kpmx
(iter_archivable_files, count_unchecked_items). Inlining them is ~15
lines and lets us drop kpmx from dev dependencies entirely, so neither
host nor container has to install the package just for a lint that
walks docs/requirements/ and counts task-list markers. The
pkgmgr archive CLI remains the canonical archival tool; the failure
message still points there.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 15:53:44 +02:00
kevinveenbirkenbachandClaude Opus 4.7 fedef21d62 chore(deps-dev): add kpmx>=1.15.0 for the requirements archive lint
tests/lint/repository/documentation/test_requirements_completeness.py
imports pkgmgr.actions.archive after the v8.0.x archive-CLI move out
of cli/contributing/requirements/. The test container installs dev
dependencies via `pip install -e .[dev]`, so kpmx must be listed
there or the lint test fails with `ModuleNotFoundError: pkgmgr`
during collection.

Pinned to >=1.15.0 because the archive subcommand and the
pkgmgr.actions.archive package only ship in that release.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 15:53:44 +02:00
kevinveenbirkenbachandClaude Opus 4.7 8e9308c32a refactor(requirements): move archive CLI from cli/ to kpmx (pkgmgr)
The fully-checked-Markdown archive helper used to live under
cli/contributing/requirements/archive/ in this repo. It is a generic
spec-folder-management primitive (numbered NNN-topic.md files,
task-list completeness check, README ## Archive section append) and
now ships in pkgmgr.actions.archive so every kpmx-managed repository
can rely on the same convention.

Changes here:

* tests/lint/repository/documentation/test_requirements_completeness.py
  imports the archive primitives from pkgmgr.actions.archive instead
  of the vendored cli.contributing.requirements.archive, and points
  contributors at `pkgmgr archive docs/requirements` in the failure
  message.
* cli/contributing/requirements/README.md becomes a stub that
  redirects readers to the kpmx archive subcommand.
* The vendored cli/contributing/requirements/archive/ package and its
  unit tests under tests/unit/ are deleted.
* The pkgmgr role pin bumps to v1.15.0 to pick up the new archive
  subcommand on deployed hosts.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 15:53:44 +02:00
kevinveenbirkenbachandClaude Opus 4.7 35137a83a3 fix(playwright): satisfy eslint preserve-caught-error + no-useless-assignment
Five eslint errors blocking make lint-javascript:

* personas/guest.js, web-app-opencloud/playwright.spec.js,
  web-app-opentalk/playwright.spec.js — re-thrown wrapped errors now
  carry { cause: err } so the symptom keeps a link to the root cause.
* personas/utils/csp.js — drop let blockedHost = "" initial value;
  the catch arm returns early, so the empty string was never read.
* web-app-wordpress/_shared.js — drop let match = null initial value;
  both branches assign before the readers fire.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 15:53:44 +02:00
kevinveenbirkenbachandClaude Opus 4.7 3b79abb0e3 chore(pkgmgr): pin to v1.14.0 (was floating stable)
v1.14.0 ships:
* `pkgmgr release --retry` re-deploys an existing HEAD release without
  re-tagging or modifying any files (re-push tag + re-align latest +
  re-run publish), so a release whose post-tag push or PyPI upload
  failed mid-flight can be recovered without code churn.
* package_name now resolves from packaging/debian/control,
  packaging/arch/PKGBUILD, or RPM .spec instead of the repo folder
  basename, so renaming a repo no longer flips the distro-package
  identity. This is what unblocks the upcoming infinito-nexus-core
  Debian builds whose changelog/control mismatch caused
  `dpkg-source --before-build` to exit 2.

Explicit pin (vs the prior floating `stable`) gives reproducible
deploys across hosts and locks the new package_name resolver behaviour
to a known version.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 15:53:43 +02:00
kevinveenbirkenbach 91ad89b3f4 Release version 8.0.4 v8.0.4 2026-05-28 13:50:57 +02:00