Commit Graph
274 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 4.7 031fb7568b test(lint): enforce single-source-of-truth for domain literals
Adds tests/lint/repository/test_domain_primary_spot.py which fails when a
file constructs a hostname via a literal `<sub>.{{ DOMAIN_PRIMARY }}` outside
the role's `meta/server.yml` (or `meta/variants.yml`) `domains.canonical` /
`domains.aliases` blocks. Every other reference MUST flow through the
project's lookup plugins so the canonical/aliases entries stay the SPOT.

Mechanics
- Regex matches `<word>.{{ DOMAIN_PRIMARY }}` patterns; wildcard fragments
  (`.{{ DOMAIN_PRIMARY }}`, `*.{{ DOMAIN_PRIMARY }}`) and bare
  `{{ DOMAIN_PRIMARY }}` references are intentionally NOT flagged
- meta/server.yml and meta/variants.yml: a state-machine line scanner
  exempts list items and dict entries inside `canonical:` / `aliases:`
  blocks (handles compact, expanded, list, and dict YAML styles)
- README.md is exempt; docs/ and files/ subtrees inside roles are skipped
- Per-line opt-out via `# noqa: domain-spot` (or `# nocheck: domain-spot`)
- File reads route through utils.cache.files.read_text and the helpers
  themselves are wrapped in lru_cache so repeated path lookups during
  the traversal pay the parse cost once

Repo cleanup
- 11 role meta/server.yml files now reference Keycloak, Collabora,
  OnlyOffice, Nextcloud, and their own canonical hostnames through
  `lookup('domain', '<role>')` (and `lookup('config', '<role>',
  'server.domains.canonical.<key>')` for the dict-canonical roles
  Matrix and Bluesky) instead of duplicating the SPOT
- `roles/web-app-mattermost/tasks/main.yml` keeps a single
  `# noqa: domain-spot` on the legacy domain cleanup task; the
  hardcoded historical hostname must persist there to remove stale
  on-disk nginx configs from the rename

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 17:34:34 +02:00
kevinveenbirkenbachandClaude Opus 4.7 b3de2a4d7c refactor(meta): land req-011 meta/info.yml + utils/cache cleanup
req-011 — descriptive role-level metadata
  * Move logo / homepage / video / display out of
    meta/main.yml.galaxy_info into a new project-owned
    roles/<role>/meta/info.yml (file-root convention, no `info:` wrapper).
  * 78 role meta/main.yml files migrated via ruamel round-trip
    (key-order / quoting / inline-comments preserved). Roles with none
    of the four fields are left untouched (no empty info.yml created).
  * web-app-dashboard/lookup_plugins/docker_cards.py reads logo +
    display from meta/info.yml; description / galaxy_tags continue to
    come from galaxy_info (Galaxy-spec fields).
  * docker_cards.py now routes ALL its file reads through the
    process-wide caches: load_yaml_any for vars/main.yml,
    meta/main.yml, meta/info.yml; read_text from utils.cache.files for
    README.md. The orphan `import yaml` is gone.

New utils/cache/files (renamed from tests/utils/fs)
  * The process-wide filesystem cache (read_text, iter_project_files,
    iter_project_files_with_content, _all_project_files) is not
    test-specific; it now lives under utils/cache/files.py next to the
    other process-wide caches. 34 consumer imports rewritten across
    tests/ and docs/. The empty tests/utils/ package is removed.
  * New unit suite tests/unit/utils/cache/test_files.py — 12 cases
    covering read_text, iter_project_files (skip-dirs, extensions,
    exclude_tests, exclude_dirs, walk-cache invariants), the combined
    iterator, non-UTF-8 silent skip, and _reset.

utils/cache redundancy cleanup
  * applications.py + users.py + cli/create/inventory/services_disabler.py
    drop their direct yaml.safe_load calls and their private
    _load_yaml_mapping/_load_yaml_variant_list copies; everything routes
    through utils.cache.yaml.load_yaml / load_yaml_any. The dead
    utils.cache.base._load_yaml_mapping is removed.
  * users.py:_load_store_users (tokens.yml read) likewise migrated.
  * _load_yaml_variant_list moves out of base.py to applications.py
    (its only consumer) and is renamed _load_variants_overrides — also
    routes through the cached loader now.
  * utils.cache.yaml._reset_cache_for_tests is renamed _reset (kept as
    alias) for parity with the per-domain reset helpers.
  * utils.cache.files grows a _reset() that clears its two LRU caches.
  * utils.cache.__init__._reset_cache_for_tests now orchestrates ALL
    six caches (applications, users, domains, base, yaml, files) so
    tests get clean state across cache layers — needed because
    applications/users now share the yaml cache and would otherwise
    serve stale parses across reset boundaries.
  * utils.cache.files imports PROJECT_ROOT from base instead of
    redefining it.
  * tests/unit/utils/cache/test_data.py + test_base.py: obsolete
    TestLoadYamlMapping / TestLoadYamlVariantList classes deleted
    (covered by test_yaml.py + test_variants.py).
  * README.md updated for the new module list (files, yaml) and the
    six-module orchestrator.

Galaxy schema lint
  * tests/lint/repository/test_role_meta_main_galaxy_schema.py: split
    galaxy_info field requirements into hard-required {author,
    description, license} and soft-recommended {min_ansible_version,
    platforms}. Soft-recommended -> emit a GitHub Actions ::warning::
    annotation via utils.annotations.message.warning (titled
    "meta/main.yml galaxy_info" with file= pointing at the offender),
    no test failure. Rationale: min_ansible_version + platforms are
    only enforced by Galaxy when *publishing*, which Infinito.Nexus
    does not do.
  * Galaxy lint goes green (was 226 offenders before req-011 +
    license_url/repository/documentation strip; was 62 before this
    relaxation; now 0 hard offenders, 62 soft warnings).
  * roles/svc-opt-keyboard-color/meta/main.yml: backfill `license`
    (only role missing the hard-required field).

New lint
  * tests/lint/repository/test_role_meta_info.py — enforces meta/info.yml
    file-root convention, the four-field allowlist (logo, homepage,
    video, display), and shape (logo.class string, homepage/video
    non-empty strings, display bool). Also fails if any
    meta/main.yml.galaxy_info still carries one of the four migrated
    fields.

Docs
  * docs/contributing/design/services/layout.md: new section
    "Descriptive Role-Level Metadata — meta/info.yml" with allowed-
    fields table, optionality rule, materialised path, and consumer
    note. File-Layout table grows the meta/info.yml row;
    meta/main.yml row gets the explicit "no logo/homepage/video/display"
    note. req-011 added to header and Related Pages.
  * utils/cache/README.md: files.py + yaml.py rows added; six-module
    reset orchestrator documented.

Validation
  * Unit:        1573 passed.
  * Lint:        55 passed.
  * Integration: 161 passed (1 skipped) via pre-commit hook.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 12:27:17 +02:00
kevinveenbirkenbachandClaude Opus 4.7 0ab817a839 refactor(roles): drop non-Galaxy license_url / repository / documentation from meta/main.yml
These three sub-keys lived under `galaxy_info:` purely as a workaround
because Galaxy silently ignores unknown keys (same pattern as the
`run_after` / `lifecycle` migration in req-010). The new lint
`tests/lint/repository/test_role_meta_main_galaxy_schema.py` rejects
them, and no consumer in `plugins/`, `utils/`, `cli/`, `filter_plugins/`
or `roles/` reads any of them, so the strip is safe.

Round-trip via ruamel.yaml so the remaining `galaxy_info:` block keeps
its key order, quoting style and inline comments.

224 files touched. Remaining lint offenders after this commit are still
present (`logo`, `homepage`, `video`, plus a handful of roles missing
required Galaxy fields like `min_ansible_version` / `platforms` /
`license`); those are a separate decision and not folded into this
change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 10:34:52 +02:00
kevinveenbirkenbachandClaude Opus 4.7 ed04dad5d5 refactor(meta): land req-008/009/010 role-meta layout/networks/ports/run_after migration
Single atomic landing for three back-to-back role-meta refactor requirements
(see docs/requirements/008-role-meta-layout.md, 009-per-role-networks-and-ports.md,
010-role-meta-runafter-lifecycle-migration.md).

req-008 — role meta layout
  * Move every role's metadata under meta/<topic>.yml with file-root
    convention (no wrapping key matching the basename):
      - schema/main.yml + config/main.yml.credentials → meta/schema.yml
      - users/main.yml                                → meta/users.yml
      - config/main.yml.server                        → meta/server.yml
      - config/main.yml.rbac                          → meta/rbac.yml
      - config/main.yml.compose.services + every other top-level key
        of config/main.yml inlined under <entity>.<key>
                                                      → meta/services.yml
      - config/main.yml.compose.volumes               → meta/volumes.yml
  * Drop the legacy schema/, users/, config/ directories from every role.
  * meta/schema.yml: support nested credential keys, optional `default:`
    field (Jinja literal, not rendered/validated/regenerated), implicit
    `algorithm: plain`.
  * Materialised paths drop the `compose.` prefix:
      compose.services.<e>.<…> → services.<e>.<…>
      compose.volumes.<k>      → volumes.<k>
      <former-top-level>.<…>   → services.<entity_name>.<former-top-level>.<…>
  * Update every Python consumer (utils/cache, utils/manager, utils/applications,
    plugins/lookup, plugins/filter, cli/*) plus every Jinja template, vars/*.yml
    and task file to the new paths.
  * No legacy fallback. Repository-wide grep for `compose.services.` /
    `compose.volumes.` / `schema/main.yml` / `users/main.yml` / `config/main.yml`
    is empty outside docs/requirements/ and tasks/utils/migrate_meta_layout.py.
  * Add tests/lint/repository/test_role_meta_layout.py guarding against the
    old paths returning, and an explicit lint guard that meta/variants.yml
    files do not carry a `compose:` wrapper.

req-009 — per-role networks/ports
  * Move group_vars/all/08_networks.yml.defaults_networks.local.<role>.{subnet,
    dns_resolver} into roles/<role>/meta/server.yml.networks.local.{subnet,
    dns_resolver}.
  * Delete group_vars/all/09_ports.yml entirely; ports now live on the
    service entity that exposes them at
    roles/<role>/meta/services.yml.<entity>.ports.{inter,local,public}.
  * Rename + int-cast every former top-level `services.<entity>.port`
    field to `services.<entity>.ports.inter` (single int).
  * Always-category-keyed maps for ports.local / ports.public; relay
    spans use {start, end} integers.
  * Add PORT_BANDS map to group_vars/all/08_networks.yml — single source
    of truth for the per-<scope>.<category> band ranges, consumed by both
    the new CLI helpers and the lint test.
  * New CLI helpers (cli meta ports suggest, cli meta networks suggest)
    walk the live role tree gap-first then increment-fallback, with
    deterministic output and non-zero exit on capacity overflow.
  * cli create role consumes both helpers when scaffolding a new role.
  * Lint extensions: bare-int port shape rejection, host-bound port
    collision check (single ints + relay span integers, inter excluded),
    band-membership check with documented allow-list for the legacy
    web-app-bigbluebutton.bigbluebutton.local.http: 48087 entry.

req-010 — run_after / lifecycle migration
  * Move galaxy_info.run_after and galaxy_info.lifecycle out of
    meta/main.yml into meta/services.yml.<primary_entity>.{run_after,
    lifecycle}; <primary_entity> is the value returned by
    get_entity_name(role_name).
  * For multi-entity roles whose primary entity has no compose service
    (web-app-bluesky → bluesky, web-app-matrix → matrix, desk/dev/drv/
    gen roles), create a dedicated metadata-only top-level entry under
    <primary_entity>.
  * Introduce utils/roles/meta_lookup.py with get_role_run_after /
    get_role_lifecycle that resolve <primary_entity> once and read from
    meta/services.yml; degrade gracefully when meta/services.yml is
    absent OR the field is absent; raise MetaServicesShapeError when the
    file exists but is malformed.
  * Update every consumer (utils/service_registry, utils/invokable,
    cli/meta/applications/resolution/run_after/__main__, cli/meta/roles/
    lifecycle_filter/__main__, cli/meta/applications/resolution/combined,
    cli/build/{tree,graph,role_include}, cli/deploy/development/{common,
    init,deps,deploy}, plugins/filter/canonical_domains_map, etc.) to
    use the helper.
  * Lint guards: no run_after/lifecycle in meta/main.yml; lifecycle
    values restricted to {planned,pre-alpha,alpha,beta,stable,deprecated};
    run_after/lifecycle never on a non-primary entity; empty run_after
    lists rejected.

Also folded into this change set
  * services_disabler now writes `services.<svc>.{enabled,shared}` into
    host_vars instead of the old `compose.services.<svc>.{...}` path; the
    discover/find pair walks meta/services.yml and only treats entries
    carrying enabled/shared/provides as provider declarations (so
    metadata-only entries from req-010 do not create spurious provider
    rows).
  * service_registry skips `run_after` deps whose target was filtered
    out via SERVICES_DISABLED instead of failing the whole load.
  * cli/mirror/resolver and cli/create/inventory/mirror_overrides emit/
    consume the new applications.<role>.services.<svc>.image shape
    (mirror.md updated to match).
  * utils/domains/list.build_applications_from_roles now reads
    meta/server.yml directly (it had been silently returning {} since
    config/main.yml stopped existing).
  * utils/roles/resource_validation.filter_roles_by_min_storage reads
    meta/services.yml.<entity>.min_storage instead of the legacy
    compose.services path.
  * web-app-bluesky pre-clones the social-app build context BEFORE
    sys-svc-compose so the build context is on disk by the time
    sys-stk-front-proxy/tasks/main.yml flushes the docker build handler.
  * 4 meta/variants.yml files (svc-ai-ollama, web-app-phpmyadmin,
    web-app-wordpress, web-app-keycloak) lose their `compose: services:`
    wrapper so deep-merge over meta/services.yml lands on the new
    file-root shape.

Validation
  * Unit tests:        1571 passed.
  * Lint tests:        50 passed.
  * Integration tests: 161 passed (1 skipped).
  * Full-cycle fresh-purged-apps deploy succeeded for the 8-app validation
    set: web-app-{nextcloud,wordpress,yourls,bigbluebutton,bluesky,gitea,
    discourse,mattermost}.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 09:58:26 +02:00
kevinveenbirkenbach 4e9d4b53db refactor(web-app-odoo): extract OIDC SQL to files/oidc/*.sql
Splits all 23 inline SQL bodies in `roles/web-app-odoo/tasks/03_oidc.yml`
into 17 standalone `.sql` files under `roles/web-app-odoo/files/oidc/`,
referenced from the tasks via `lookup('file', 'oidc/<name>.sql')`.

Why:
- Inline `query: >` heredocs hide SQL from grep, syntax highlighters,
  and SQL-aware tooling. Extracting them to dedicated files makes the
  queries trivially diffable + parseable + reviewable.
- The two tasks that previously interpolated Jinja straight into SQL
  (`'{{ ODOO_OIDC_AUTHORIZE_URL }}'` etc. for the Keycloak provider
  upsert) move to `named_args` with `%(name)s` placeholders, removing
  the SQL-injection surface those interpolations carried.

What also changes (kept tight to stay in scope):
- The five-line DB connection block (db / login_user / login_password /
  login_host / login_port) is deduplicated via a `module_defaults` block;
  the one task hitting the Keycloak DB instead of Odoo overrides them
  inline.
- Seven `INSERT INTO ir_config_parameter ... ON CONFLICT (key) DO UPDATE`
  tasks now share `upsert_ir_config_parameter.sql` (key + value via
  named_args). The two specialised template-user-id upserts (which need
  a subquery for the value) share
  `upsert_ir_config_parameter_template_user_id.sql`.

Net effect: tasks file shrinks from 389 to 192 lines, every SQL body
sits in its own annotated `.sql` file with a header comment describing
intent, and the deploy-time behaviour is unchanged (same statements,
same ordering, same idempotency guards, just better-organised).
2026-04-25 14:01:07 +02:00
kevinveenbirkenbachandClaude Opus 4.7 d97ed7a9e8 feat(deploy): per-role matrix-deploy variants with folder-per-round model
Introduces per-role `meta/variants.yml` for declaring multi-variant
deploys (e.g. WordPress Single-Site vs. Multisite) and reshapes the
development deploy CLI to materialise one inventory folder per variant
and iterate them with co-located sync+async passes.

Why:
- The previous single-inventory + Pass-1-then-Pass-2 split deployed each
  variant twice and ran the async pass against a host left in a
  different variant's state, masking real bugs.
- Inventory and runtime concerns were tangled: variant selection lived
  as a runtime extra-var and required cross-stage coordination.

How:
- `roles/<role>/meta/variants.yml` (file format docs at
  docs/contributing/artefact/files/role/variants.md): YAML list of
  deep-merge overrides on top of `config/main.yml`. Empty entry `{}` is
  variant 0 (= legacy payload). 6 roles get their dev overrides moved
  here from inventories/dev.yml; WordPress declares 2 variants.
- `utils/runtime_data.py` gains `_build_variants` / `get_variants` and
  drops the retired `_active_variants` runtime selector. Loader always
  returns variant 0 as the default; non-zero variants reach
  `get_merged_applications` as inventory-level `applications.<app>`
  overrides baked at init time.
- New `cli/deploy/development/inventory.py`: `DevInventorySpec`,
  `plan_dev_inventory_matrix` (pure planner shared between init and
  deploy), `build_dev_inventory_matrix` (materialises one folder per
  round at `<dir>-<R>`, or `<dir>` when single-variant). Single-folder
  paths preserve full backward compat.
- `cli/deploy/development/deploy.py`: matrix loop with per-round
  cleanup (only apps whose variant changed AND that are about to
  re-deploy), `--variant <idx>` (or `VARIANT=` env) to pin a single
  round, and `--full-cycle` (or `FULL_CYCLE=true`) which interleaves
  sync + async per round so the async re-deploy targets exactly the
  host state the matching sync deploy just produced.
- `cli/deploy/development/exec.py` gains repeatable `--env KEY=VAL` so
  bash callers can inject per-run context into in-container helpers
  without inlining heredocs.
- `scripts/meta/env/inventory.sh` exports `INVENTORY_VARS_FILE`
  (Python mirror in `cli.deploy.development.common.DEV_INVENTORY_VARS_FILE`;
  test_inventory_vars_file_spot.py locks them against drift).
- `make deploy-fresh-purged-apps` and `scripts/tests/deploy/ci/dedicated.sh`
  switch to a single init + single deploy `--full-cycle`. The
  `make deploy-reuse-*` bash scripts honour `VARIANT=` by suffixing
  `INVENTORY_DIR`/`INVENTORY_FILE`.
- The 5 `scripts/tests/deploy/local/deploy/*.sh` scripts now delegate
  their in-container heredocs to dedicated helpers in
  `scripts/tests/deploy/local/utils/`, removing the bash-in-bash
  quoting hell.

Tests:
- `tests/unit/utils/test_variants.py` (renamed from
  `test_application_variants.py`): loader edge cases, variant-zero
  default, retired-`_active_variants` guard.
- `tests/unit/cli/deploy/development/test_inventory.py` (new): planner,
  variant baking, builder, `filter_plan_to_variant`, `DevInventorySpec`.
- `tests/unit/cli/deploy/development/test_matrix_deploy.py` (new):
  per-round deploy filter, cleanup decisions, `--variant` pinning,
  `--full-cycle` per-round interleave.
- `tests/unit/cli/deploy/development/test_inventory_vars_file_spot.py`
  (new): drift guard for the bash <-> Python literal pair.
- `tests/unit/cli/deploy/development/test_exec.py` extended for `--env`.

Docs:
- `docs/contributing/artefact/files/role/variants.md` (new): file format.
- `docs/contributing/design/matrix-deploy.md` (new): runtime mechanism
  (folder layout, --variant, --full-cycle, cleanup logic).
- `docs/contributing/actions/deploy.md` (new): contributor dev-deploy
  flow (make targets, --variant pinning).
- `docs/administration/deploy.md` slimmed to admin-only (was mixed
  admin+dev), cross-links to the new contributor doc.
- `docs/agents/action/iteration/role.md` keeps only agent-iteration
  recipes; mechanism explanation moved out and linked.
- `docs/contributing/documentation.md` adds the "no self-SPOT
  declaration" rule; `applications.md` renamed its SoT header for
  consistency.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 13:47:48 +02:00
kevinveenbirkenbachandCopilot Autofix powered by AI 421f19acac Potential fix for code scanning alert no. 274: Empty except (#199)
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-04-25 09:38:27 +02:00
kevinveenbirkenbachandCopilot Autofix powered by AI 478f710d60 Potential fix for code scanning alert no. 272: Unused variable, import, function or class
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-04-25 09:38:27 +02:00
kevinveenbirkenbach b2914b7cd1 Merge branch 'main' into fix/users-applications.yml 2026-04-23 18:14:17 +02:00
Alejandro Roman 5d63017271 fix(Prometheus): add new apps and fix a dns conflicts 2026-04-23 12:03:16 +04:00
kevinveenbirkenbachandClaude Opus 4.7 447de6e5a6 fix(web-app-odoo): Odoo 19 OAuth auto-provisioning via sudo().create()
Fixes first-login flow for OIDC-provisioned users in Odoo 19. Upstream
auth_oauth._auth_oauth_signin delegates auto-provisioning through
auth_signup.signup() -> _create_user_from_template() which calls
template_user.copy() inside a savepoint. When that savepoint flushes,
ir_attachment._check_contents() walks env.user._get_group_ids(), and on
the unauthenticated OAuth callback env.user is an empty recordset, so
ensure_one() raises and the controller surfaces AccessDenied with no
traceback.

Overrides _auth_oauth_signin to bypass the template-copy path entirely
and create the user directly via sudo().create() with base.group_user,
then flushes pending recomputes under the sudo env before the
controller's cr.commit() runs.

Also makes the OIDC UID claim configurable via ODOO_OIDC_UID_FIELD
(default: preferred_username) so Odoo aligns with Mastodon, Pixelfed,
EspoCRM, and Taiga in the infinito.nexus stack instead of keying on
Keycloak's opaque sub UUID.

Playwright spec updated to tolerate Odoo 19's new .o_login_auth
container for the SSO provider list (older .o_auth_oauth_providers
selector still accepted).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-22 15:15:21 +02:00
kevinveenbirkenbachandClaude Opus 4.7 2dbb2aaa1a feat(email): introduce lookup('email') plugin, migrate all consumers
Moves the SYSTEM_EMAIL_* resolution logic out of group_vars/all/03_email.yml
into a dedicated Ansible lookup plugin, so every role template reads outgoing
mail settings via lookup('email') (global) or lookup('email', application_id)
(per-app). Per-app compose.services.email is merged on top of the resolved
defaults; SYSTEM_EMAIL_* variables remain usable as an inventory escape hatch.

Also splits the email docs: administrator-facing configuration stays under
docs/administration/configuration/, plugin contract and extension rules move
to docs/contributing/design/services/email.md. services.md is relocated to
services/base.md so the services/ subtree can host per-service design pages.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 22:47:40 +02:00
kevinveenbirkenbachandClaude Opus 4.7 8ce9179706 fix(lookups,web-app-peertube): finish users/applications migration and harden OIDC plugin install
- Resolve merge conflict in web-app-peertube/vars/main.yml; migrate
  remaining `applications |` and `users.*` references to
  `lookup('applications')` / `lookup('users', ...)` in web-app-odoo and
  web-app-decidim (compose, env, playwright, setup tasks).
- web-app-peertube: split OIDC tasks into oidc/{enable,disable}.yml,
  add install_mem_limit filter + PEERTUBE_MEM_LIMIT /
  PEERTUBE_OIDC_PLUGIN_INSTALL_MEM_LIMIT vars to raise the cgroup ceiling
  during the one-off `npm run plugin:install` exec (prevents OOM-SIGKILL
  that was surfacing as "Container is restarting"); add
  upsert-oidc-plugin.sql.j2 and diagnostics.sh.
- CI: test-deploy-{local,server,universal,workstation}.yml tweaks plus
  scripts/github/{dump_runner_state,enlarge_swap}.sh for constrained
  runners.
- cli/meta/applications/ressources: new CLI entry with unit tests.
- Misc config/docs updates across dashboard, mailu, mattermost, asset,
  cdn, file roles and contributing docs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 10:14:21 +02:00
kevinveenbirkenbachandClaude Opus 4.7 84ceb34249 fix(web-app-odoo): migrate direct users.* access to lookup('users', ...)
Replaces legacy `users.KEY.field` and `users['KEY'].field` references with
the runtime `lookup('users', 'KEY').field` pattern across vars, templates,
and tasks so the role aligns with the new users lookup plugin.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 02:44:12 +02:00
github-actions[bot] d2237ee380 update(images): update Docker image versions 2026-04-21 00:12:43 +00:00
evangelostsak 3050d2558c docs(TODO): format TODO list items as markdown links 2026-04-20 20:26:48 +02:00
evangelostsak d4c70a269f fix(auth_oauth_https): change license from Infinito.Nexus Community License to MIT 2026-04-20 20:26:48 +02:00
Evangelos Tsakoudisandkevinveenbirkenbach b4224cd72b Update roles/web-app-odoo/vars/main.yml
Co-authored-by: Kevin Veen-Birkenbach <kevin@veen.world>
2026-04-20 20:26:48 +02:00
Evangelos Tsakoudisandkevinveenbirkenbach c2daf84713 Update roles/web-app-odoo/files/addons/auth_oauth_https/__manifest__.py
Co-authored-by: Kevin Veen-Birkenbach <kevin@veen.world>
2026-04-20 20:26:48 +02:00
Evangelos Tsakoudisandkevinveenbirkenbach 6c52f5d224 Update roles/web-app-odoo/vars/main.yml
Co-authored-by: Kevin Veen-Birkenbach <kevin@veen.world>
2026-04-20 20:26:48 +02:00
evangelostsak 00f493457d docs(web-app-odoo): fix URL format to avoid external link check
Change access URL format from 'https://odoo.erp.<your-domain>/'
to 'odoo.erp.{DOMAIN}' to prevent CI external link checker from
parsing 'odoo.erp' as a real domain to validate.
2026-04-20 20:26:48 +02:00
evangelostsak 2efdacdc5e feat(web-app-odoo): add OIDC UID field to main.yml for user identification 2026-04-20 20:26:48 +02:00
evangelostsak 81753750c9 feat(web-app-odoo): add OIDC UID field to environment variables in compose template 2026-04-20 20:26:48 +02:00
evangelostsak 956119d8a6 feat(web-app-odoo): implement configurable OIDC UID field for OAuth authentication 2026-04-20 20:26:48 +02:00
evangelostsak 4dc1368f3a feat(web-app-odoo): update module name and summary to reflect configurable OIDC UID field 2026-04-20 20:26:47 +02:00
evangelostsak 394952afcd refactor(web-app-odoo): update TODO list with project links and remove low priority tasks 2026-04-20 20:26:47 +02:00
evangelostsak 453ce89343 fix(web-app-odoo): update Keycloak DB query to use administrator username instead of ID 2026-04-20 20:26:47 +02:00
evangelostsak 411c2ce864 feat(web-app-odoo): implement preferred_username support in OAuth authentication 2026-04-20 20:26:47 +02:00
evangelostsak 19ba134294 feat(web-app-odoo): add __init__.py to auth_oauth_https models for res_users import 2026-04-20 20:26:47 +02:00
evangelostsak ece5d6fd21 feat(web-app-odoo): update module name and description to include preferred_username support 2026-04-20 20:26:47 +02:00
evangelostsak bd2b2bd9f3 fix(web-app-odoo): import models in auth_oauth_https module 2026-04-20 20:26:47 +02:00
evangelostsak 74f3260d25 fix(web-app-odoo): clean up TODO list by removing completed high and medium priority tasks 2026-04-20 20:26:47 +02:00
evangelostsak 733b5453f4 feat(web-app-odoo): auto-create OAuth users with Internal User group
Addresses review feedback: biber and other LDAP users are now
auto-created on first SSO login via Keycloak OAuth signup rather
than hardcoded in Ansible.

OAuth template user mechanism:
- Sets website.auth_signup_uninvited=b2c to allow OAuth signup
- Creates _oauth_template user with Internal User group
- Sets base.template_portal_user_id (key param Odoo actually uses)
- Fallback grants Internal User to existing OAuth users

Adds biber Playwright test to verify OAuth auto-creation works.
2026-04-20 20:26:47 +02:00
evangelostsak 35cfcb834d fix(web-app-odoo): run admin setup before OIDC user linking
OIDC user linking failed because it ran before admin user was
renamed from 'admin' to configured username. Reorder tasks so
05_admin.yml runs before 03_oidc.yml.
2026-04-20 20:26:47 +02:00
evangelostsak 3a6202778f fix(main.yml): add container port definitions for Odoo service 2026-04-20 20:26:47 +02:00
evangelostsak 4dccf36e56 fix(playwright.env.j2): remove biber username and password variables 2026-04-20 20:26:47 +02:00
evangelostsak ae7920ecb2 fix(odoo.conf.j2): replace hardcoded ports with template variables for HTTP and longpolling 2026-04-20 20:26:47 +02:00
evangelostsak f6616bb40e fix(compose.yml.j2): update port mappings and volume definitions for Odoo service 2026-04-20 20:26:47 +02:00
evangelostsak c328cdca48 fix(main.yml): update task name and simplify Odoo addons directory creation 2026-04-20 20:26:47 +02:00
evangelostsak ce46ca21ab fix(oidc): remove biber user linking logic from Keycloak integration 2026-04-20 20:26:47 +02:00
evangelostsak 5f87759ab0 fix(meta): update author information in main.yml 2026-04-20 20:26:47 +02:00
evangelostsak efcb1a17d9 fix(playwright): remove unused Biber credentials from environment variable decoding 2026-04-20 20:26:47 +02:00
evangelostsak 36edf6a2b4 fix(config): update domain references to use 'odoo' prefix and enable Redis service 2026-04-20 20:26:47 +02:00
evangelostsak 90088defc7 docs(readme): update module configuration and authentication details in README 2026-04-20 20:26:47 +02:00
evangelostsak 3df98f9cc3 fix(todos): remove duplicate LDAP authentication test and reorder tasks in TODO list 2026-04-20 20:26:47 +02:00
evangelostsak ae00034976 fix(todos): adjust priority of custom addon development workflow in TODO list 2026-04-20 20:26:47 +02:00
evangelostsak 4bb5f5fce4 refactor(odoo): remove inline LDAP configuration variables from task file 2026-04-20 20:26:47 +02:00
evangelostsak 80324adc1b feat(odoo): add LDAP configuration for res_company_ldap table 2026-04-20 20:26:47 +02:00
evangelostsak 4a2b31085d fix(odoo): address Copilot review comments
- Remove unused BIBER env assertions from playwright.spec.js
- Pin pip package versions in Dockerfile for reproducible builds
- Use parameterized SQL queries in 04_ldap.yml to prevent injection
2026-04-20 20:26:47 +02:00
evangelostsak 2cd120b5ae feat(odoo): add Playwright environment configuration template 2026-04-20 20:26:47 +02:00