Commit Graph
32 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Opus 5 791eee7c9f refactor(mcp)!: prove the endpoint contract with a CLI test, not a deploy probe
The contract check ran as an Ansible task in the middle of every provider deploy, and the two client checks ran the same way. A test that is part of the deploy cannot be run without deploying, cannot be re-run on its own, and reports its verdict as a deploy failure. Twenty-seven task files lose 491 lines to this.

It is now what it always was. Each provider ships files/test/test.sh, templates/test.env.j2 and meta/tests.yml, and test-e2e-cli stages one shared harness beside it: run.sh drives contract.sh in a throwaway container on the provider's own network, then isolation.sh for adapter-fronted providers. The read probe each provider offers moved from the calling task into meta/mcp.yml next to the allowlist it must satisfy, and the schema now rejects a read probe naming a tool outside that allowlist.

The bearer the test presents is the one a client resolves through mcp.credential, via the new mcp_client_bearer lookup over resolve_credential, which moved to utils.roles.applications.mcp so it is the same function mcp_servers renders every client connection with. The probe presented whatever the calling role passed, which for the fifteen adapter-fronted providers is a different secret than any client holds.

Sidecar isolation is read from the engine rather than measured inside the container, so it no longer needs a delegation to the node holding the task: attachment is compared by network name, which drops the gwbridge special case, and a swarm worker says it cannot measure instead of skipping silently.

Retrying is bounded by wall clock against MCP_DEADLINE_SECONDS, which scales through the same lookup('timeout') as the harness budget it has to stay under. A flag that is neither true nor false aborts rather than reading as off.

mcp-provider-probe becomes mcp-provider-cli-test: an enabled provider must ship the test rather than include the task. mcp-probe-bearer becomes mcp-adapter-bearer, tying ADAPTER_BEARER to the declared credential key now that no probe include carries it. A new integration test renders the shared env template for every provider through Ansible's own templar, so a later change to it breaks visibly instead of poisoning twenty deploys quietly.

Hermes and OpenClaw keep their client-side proof as CLI tests of their own.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-01 20:46:26 +02:00
kevinveenbirkenbach 85af82b956 fix(gitlab): drop the licence tier MCP never required
The upstream survey recorded GitLab MCP as Premium and Ultimate only,
and c76de1a2d4 carried that into the probe's failure message, which sent
the operator to 'blocker: licence'. This role deploys the -ce images, so
under that reading it could never have served MCP at all.

The source says otherwise. lib/api/mcp/base.rb sits in the CE tree, not
under ee/, and at the pinned v19.3.1 its mcp_denial_reason returns
:instance_setting_disabled unless CurrentSettings.mcp_server_enabled? -
no licence check on that path - while application_setting.rb:836
declares that setting default: true. A stock CE instance serves it.

minimum_version moves to 19.0 rather than the 18.3 that first shipped the
route: at 18.3 the endpoint sits behind the per-user mcp_server feature
flag, and 19.0.0 is where CE defines feature_available? as an
unconditional true.

The assertion that commit added stays, because it is the right one - it
measures the tool inventory instead of trusting a declaration. Only its
explanation changes, to the two causes that actually produce an empty
list.
2026-08-29 11:01:48 +02:00
kevinveenbirkenbachandClaude Opus 5 9967c806bd fix(roles): follow the python scripts to their new folder
Twelve callers load their scripts with the relative form
lookup('file', 'name.py'), which resolves against the role's files/
directory. dfe7a7fdd moved those scripts into files/python/ without
updating them, so the MCP provisioning and probes of baserow, checkmk,
flowise, gitlab, homeassistant, jellyfin, n8n, openwebui and pretix, plus
n8n's AI gateway task, all resolved a path that no longer exists.

This is the second time the same relocation left callers behind. After
2aec4326a fixed the php paths, the claim that no stale references remained
came from grepping the worktree, which already carried the corrected paths;
HEAD still held the old ones. The check has to run against the commit.

Verified against HEAD this time: the eleven remaining stale relative lookups
are exactly the files in this bundle, and no other loading form (copy src,
script) carries a stale path.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-28 12:51:10 +02:00
kevinveenbirkenbachandClaude Opus 5 7162b7bf4c Merge fork/feature/svc-net-tor into feature/ai-agent-employees
834 commits from the Tor onion-service branch against 299 of ours, from merge
base 7b646bdece: 127 conflicted files, 3506 files changed.

The two sides are largely orthogonal. Theirs adds svc-net-tor and a `tor` service
across the role tree, plus two sweeping refactors: shipped scripts sorted by
language (files/ruby/, files/python/, files/shell/, scripts/lint/*.sh) and the
unit suite moved under tests/unit/python/. Ours is requirement 036, the native AI
gateway, plus the MCP role work. Most conflicts were both sides appending to the
same service map, resolved as unions.

Resolutions that were not unions:

Credentials moved namespace. Theirs renamed meta/schema.yml to meta/secrets.yml
and re-addressed credentials as secrets.credentials.<name>. Git carried our
litellm_api_key blocks through the rename, but every consumer we added still read
'credentials.<name>', which no longer resolves. All 45 call sites are migrated.

plugins/filter/container_volumes.py is deleted by theirs and relocated to
plugins/lookup/container_volumes.py, where it carries the same tmpfs defect our
f85996b43 had just fixed: a hard-coded {"size": ...} that silently drops a per
mount `mode`. The fix is re-applied in the relocated file, as that commit's merge
note anticipated.

compose.yml keeps only INFINITO_PLAYWRIGHT_REPORTS_BASE_DIR. Theirs also forwards
INFINITO_PLAYWRIGHT_STAGE_BASE_DIR; that line is deliberately dropped, per the
analysis recorded in 45804e9ad -- STAGE has a drift-proof role-vars fallback,
while forwarding it promotes a setdefault-pinnable .env value above that SPOT.

tasks/stages/01_constructor.yml takes their include, ./tasks/utils/setup/group.yml,
because their refactor removed tasks/groups/*-roles.yml, leaving our include
target nonexistent. Our task name is kept, since svc-virt is in the loop.

Makefile swarm-zombie is a union: their validate plus teardown, then our
lab_subnet cleanup, which their side dropped while leaving lab_subnet.sh as the
only orphaned reference in the file.

01_bootstrap.sh keeps our deterministic --ip pinning, which distinguishes an
already-attached node from a real failure, over their `|| true`.

Their language-sorted layout orphaned references our side still held: zammad's
two scripts/apply/*.rb, jenkins' java-with-ca-trust.sh, and the notify topics
their handlers renamed to hyphenated form. All corrected.

roles/sys-svc-compose/files/shell/swarm/stack_ready.sh gains our latched-update
block: paused, rollback_paused, rollback_started and rollback_completed exit 2
rather than polling a state that cannot resolve without another deploy.

config_from_run is unioned to (title, logged, jobs); the production caller in
trigger/__main__.py now passes jobs, without which our suite suppression would
have been inert.

READMEs are regenerated rather than hand-merged: 15 LiteLLM rows and 91 Tor rows
now derive from the merged metadata, which is itself evidence the meta merge is
coherent.

Verified: 5161 unit tests pass. The single failure, test_query.py TestSortSpec,
also fails on fork/feature/svc-net-tor at b51d2f9919, measured in a baseline
worktree -- so this merge introduces no new unit-test failure. Two modules are
excluded from that run because `baudolo`, a dependency their branch introduces,
is not installed on this host.
Not verified: no deploy has run against the merged tree, and make quality has not
been run end to end here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 16:32:30 +02:00
kevinveenbirkenbachandClaude Opus 5 a46348b6cf refactor(handlers): bind notify to a listen topic, not to a name
A handler name was doing two jobs at once: the line an operator reads in the
play output, and the identifier a `notify:` binds to. The two pull in opposite
directions -- the log wants "restart the SSH service, with diagnostics", the
binding wants a token that survives quoting, YAML flow style and a shell
round-trip -- and a name that changes for readability silently changes which
handler runs.

Every handler that a notify reached by name now carries a `listen:` with that
exact wording, so the binding is explicit before anything is renamed. The
topics themselves become identifiers: `compose up` reads `compose-up`,
`Restart NFS ganesha` reads `restart-nfs-ganesha`, 22 of them across both
sides of every notify. Where the topic is assembled at runtime, both branches
moved together: the conditional in sys-service carries two literals, and the
LDAP renderer interpolates `import-{{ folder }}-ldif-files`, which is what
makes those handlers reachable at all.

Freed from the binding, the names take the emoji prefix every other task line
already has.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16 03:38:42 +02:00
kevinveenbirkenbachandClaude Opus 5 2389b6e38b fix(gitlab): discover the OIDC issuer over the scheme it actually uses
GitLab could not log anyone in through Keycloak on an onion deployment. The sign-in page carried the omniauth flash: Could not authenticate you from OpenIDConnect because Ssl connect returned=1 errno=0 peeraddr=172.30.0.10:443 state=error: tlsv1 unrecognized name (ssl alert number 112), and gitlab-webservice logged OpenIDConnect::Discovery::DiscoveryFailed eleven times.

The openid_connect gem rebuilds the well-known URL and never reads the scheme of the issuer. Its config resource also drops the port when it is 80 or 443, so http://auth.onion loses port 80 and URI::HTTPS.build puts 443 back. The hidden service publishes port 80 only, so 443 reaches the SNI-less default listener, which answers ssl_reject_handshake - alert 112, exactly the string in the flash.

An initializer sets SWD.url_builder and WebFinger.url_builder to URI::HTTP when the issuer is plaintext. These are the same two lines web-app-decidim already ships for the identical bug, and this repo has one such fix per role for zammad, mastodon, decidim and peertube; gitlab was the gap. The mount copies the smtp_settings.rb initializer pattern onto webservice and sidekiq.

The scheme test lives in the ruby file rather than in the render and mount conditions, which both gate on services.sso.enabled alone. Two separately spelled conditions could drift once an inventory sets OIDC_OVERRIDE.URL, and would then either render a file that is never mounted or mount one that was never rendered.

Boot safety: omniauth_openid_connect and openid_connect are default-group Gemfile entries without require: false, so Bundler.require loads them before the initializers run, and openid_connect requires swd and webfinger itself. Both writers are public and assign an ivar. GitLab never assigns url_builder anywhere.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-14 13:37:57 +02:00
kevinveenbirkenbachandClaude Opus 5 28475455db feat(mcp): give every provider its own service account from the registry
Nine roles reached their MCP surface as the deployment administrator or with
an account password kept beside the account in credentials. A Moodle site
admin bypasses every capability check, a Nextcloud app password is not
scopable, a Gitea token reads every private repository, and a GitLab token on
root reads every private project. Each role now declares its own principal in
meta/users.yml and provisions it, so the exposed surface is what the service
role permits. jellyfin, zammad and snipe-it kept their account but took its
password from a credential named token; they read the registry too.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 15:44:12 +02:00
kevinveenbirkenbach 838b64a6bf feat(gitlab): proxy MCP through adapter 2026-08-12 02:02:40 +02:00
kevinveenbirkenbach 77896fba12 refactor(mcp): expose every role's MCP work at tasks/utils/mcp.yml
The reconciler addresses a client with tasks_from: utils/mcp.yml, which
only works when every role offers its MCP work at the same path. The
files were named per role, and on the two agents the work sat inline in
the entry point, where nothing but a full role run could reach it.

The filter docstring pointed at the pre-rename path and now names the
file that exists.
2026-08-09 23:57:43 +02:00
kevinveenbirkenbachandClaude Opus 5 a423bde6cc refactor(mcp): unify client entrypoints and read provider tokens through one lookup
Every MCP role keeps its task tree under tasks/utils/ without numeric
prefixes, so a caller can reach any of them through include_role
tasks_from. utils/roles/mapping.py holds that path as the single source.

Ansible resolves a relative include against the including file's own
directory when that file was reached by path, but against tasks/ when it
was reached through tasks_from. The same file therefore loaded from its
own role and failed from a caller using tasks_from. Every nested include
now names {{ role_path }}/tasks/utils/..., which holds under both bases,
and a lint walks each tasks_from entrypoint transitively to keep it so.
The exec-gating lint learns the same form, otherwise it loses the include
chain and reports inherited IS_STACK_HOST gates as missing.

The expression resolving a provider's stored token appeared eighteen
times. plugins/lookup/mcp_credential.py replaces it, and mcp_probe_owner
disappears from eight roles: it was only ever a step towards the bearer
and no probe read it.

The Hermes and OpenClaw probes stop aborting the play while it is still
running. Roles deploy in dependency order, so a client probing during its
own role can run before a provider exists at all, and failing there
prevents that provider from ever deploying. The verdict moves to the
reconciliation pass, gated on MCP_RECONCILE_STRICT, which the reconciler
sets and group_vars declares so the readers need no default.

The sys-svc-mcp-reconcile role is added here; wiring it into a stage is a
separate change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 21:06:31 +02:00
kevinveenbirkenbach 3e8a4c6cb3 feat(mcp): prove the contract and pin token ownership on the native servers
The eight roles whose MCP server is built into the application now end their MCP
step with the shared contract probe. It builds URL and Authorization header from
the role's own declaration, calls initialize and tools/list, invokes one
deterministic read tool per role, and compares the served surface against the
declared allowlist. It cannot be a Playwright test: the check needs the real
provider credential and a Playwright run would capture it in its trace.

Eleven sites wrote the MCP token into the store under the administrator's
identity while their metadata declared an owner of their own. The schema lint
forbids administrator as a credential owner, so declaration and storage
disagreed, and the probe would have looked for the bearer under the declared
owner and found nothing. They now read the declared owner.
2026-08-06 20:40:01 +02:00
kevinveenbirkenbachandClaude Opus 5 c76de1a2d4 test(gitlab): probe the MCP tool inventory, not just the handshake
The probe asserted an HTTP 200 on initialize and treated that as a working MCP
surface. It only proves the path exists and the token is accepted. This role
deploys the CE images while GitLab serves MCP through Duo, which is Premium and
Ultimate only, so an endpoint that answers but advertises nothing was
indistinguishable from a working one.

The probe now completes the handshake and calls tools/list, reading an SSE frame
when the response is one, and reports the count. A separate assertion fails the
deploy on zero tools and names the licence as the reason, which would put this
role behind 'blocker: licence' like web-app-openproject.

The assertion uses two substring checks rather than regex_search: backslash
escaping inside YAML scalars is a trap this repository has been bitten by.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 22:11:12 +02:00
kevinveenbirkenbach 255ee13f60 Merge branch 'feature/swarm-nfs' into feature/ai-agent-employees 2026-08-03 04:21:37 +02:00
kevinveenbirkenbachandClaude Opus 5 9e42610c02 feat(gitlab): mint the MCP token through the CNG rails entrypoint
Provision a personal access token carrying the mcp scope through the
rails runner. The role deploys the cloud-native images, which ship no
omnibus gitlab-rails wrapper, so the invocation names the rails binary
under /srv/gitlab/bin.

Attach clients through the role's overlay, keyed on the MCP service
flags, so a client container reaches the endpoint without publishing it.

Record what upstream does not enforce: the mcp scope grants read and
create, GitLab offers no server-side read-only mode, and the only filter
is a per-request header this deployment does not send. The tool policy in
meta/services.yml is therefore declarative, and every call carries the
blast radius of the root account. The endpoint additionally requires
Premium or Ultimate, so a Community deployment cannot reach it at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 22:11:39 +02:00
kevinveenbirkenbachandClaude Opus 5 673e994aa7 feat(lint): pin type and resolver on every container inspect
An untyped inspect searches every docker object kind, and a role's overlay network carries the same entity name as its main container, so the call can resolve the network and report a missing State key instead of naming the container. That is how the openresty assert died on every swarm job of run 30709070050.

Extend container-exec-resolver to cover inspect, stripping raw markers and quoted spans first so the flag walker survives Go template format strings. Add container-inspect-type, scoped to roles/ because the collision follows the entity naming convention and the outer act namespace carries no role networks. Sweep 40 call sites; suppress the delegate_to-resolved CIDs and the compose co-location probes with a stated reason.

Move the five container rules into tests/lint/ansible/shell/container/ and drop the container_ prefix from their filenames. Register both markers in the suppression docs, where the resolver marker was missing entirely.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-01 20:51:56 +02:00
kevinveenbirkenbachandClaude Opus 4.8 4039313266 refactor(tasks): enforce and apply a single task-file numbering scheme
Add tests/lint/repository/test_task_file_numbering.py: numbered task
files use exactly two leading digits, a numbered *_core.yml must be
00_core.yml, per directory the numbers are unique/consecutive and start
at 01 (00 with a core file), numbered includes appear in ascending
order, and shared helpers live in tasks/utils/ instead of the numbered
chain.

Apply it across every role: rename NN_core.yml to 00_core.yml with a
consecutive down-shift of the siblings, move letter-suffix children into
a subdirectory named after their parent task, relocate helpers included
from more than one place into tasks/utils/, and update every reference
(include_tasks, path_absolute, .ansible-lint-ignore, requirement docs).
Legacy narration comments in the touched files are deleted; the upstream
xwiki.properties reference block opts out via nocheck. The unused
MAILU_IP6_PUBLIC var (only ever named in now-removed comments) is dropped.

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

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

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 20:00:03 +02:00
kevinveenbirkenbachandClaude Fable 5 cb174cb9c3 chore(gitlab): drop explanatory comments
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 02:37:28 +02:00
kevinveenbirkenbachandClaude Fable 5 4ac854efbd fix(gitlab): survive container restarts and silence hlth-volumes
CNG's set-config copies the rendered configs into CONFIG_DIRECTORY on
every container start; the first cp creates the destination with the
source mode, so 0440/0400/0444 sources left the copy owner-unwritable
and the next start's truncating cp died with EACCES (permanent
crash-loop after any restart, including the deploy's own recreate).
Grant owner-write to exactly the files set-config copies; files bind-
mounted read-only at their final destination stay tight.

Mount the CNG images' declared VOLUME paths (/var/log*, /var/opt/gitlab)
as named node-local volumes so containers stop spawning anonymous
volumes that fail the hlth-volumes check.

Verified live: HTTP 200, all services healthy across recreate,
hlth-volumes Result=success.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 02:37:27 +02:00
kevinveenbirkenbachandClaude Opus 4.8 0bf1e8ef8c refactor(gitlab): replace Omnibus with the Cloud Native GitLab composition
Deploy GitLab from the official CNG CE images as six services: webservice (puma) and sidekiq scale to the topology default, workhorse is the sole HTTP entry, gitaly and a one-shot migrations job are pinned singletons, shell runs gitlab-sshd. The Omnibus container, its Dockerfile and the GITLAB_OMNIBUS_* config groups are removed. All rails/workhorse/shell/gitaly configs and shared secrets are pre-rendered by Ansible and mounted read-only; eleven credentials land in meta/schema.yml including an rsa_pem_2048 OIDC signing key (new value_generator algorithm). Postgres, redis and S3 object storage ride the existing lookups; OIDC, SMTP, the public SSH port and the root password are preserved. compose_volumes gains a per-volume nfs:false opt-out so the gitaly repositories volume stays node-local in swarm (upstream forbids git repositories on NFS); nfs_prep skips volumes without driver_opts accordingly. The Nextcloud gitlab integration execs the CNG rails runner. ruby_single_line dies with its only consumer; ruby_dq keeps test coverage. Ports (8181/8080/2222/8075/3808/9122) and service names resolve from single SPOT declarations in meta/services.yml via vars constants; the version pin sits on the webservice image pair so the updater can bump it. Live-validated in compose up to all six services healthy and migrations completed; fresh-install-only semantics for existing Omnibus data are documented.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 02:37:27 +02:00
kevinveenbirkenbachandClaude Opus 4.8 cddb0dc59b feat(lint): require emoji-prefixed task/step/job names + convert existing
Add tests/lint/repository/test_name_emoji_and_length.py: every Ansible task
name and GitHub Actions workflow/job/step name must start with an emoji (first
char not 0-9/A-Za-z) and be <= 80 chars.

- emit emoji names at the source: cli/build/include generator now writes
  "🔧 setup <app>" / "🚿 flush handlers after <app>" so generated
  tasks/groups/*-roles.yml satisfy the convention too
- convert existing task/step/job/workflow names to emoji-prefixed, choosing a
  task-fitting icon per action (📦 install, ✅ ensure, 🔍 probe, 🥾 bootstrap,
  🚀 deploy, 🧩 service-module load, ⬇️ checkout, 📂 include-routines, ...)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 22:45:06 +02:00
kevinveenbirkenbachandClaude Opus 4.8 3bfeba1243 fix(roles): set the run-once flag as the first 01_core task for shared providers
test_service_core_first_task_run_once requires tasks/01_core.yml to set the
run_once flag (include_tasks: utils/once/flag.yml) as its very first task so the
guard is in place before the role body runs and the variant-aware loader cannot
recurse. Move the flag include from the end to the top in the shared-provider
roles that had it last (bigbluebutton, flowise, gitlab, matrix, mattermost,
moodle, openproject, openwebui, peertube, suitecrm, xwiki).

Also give the template-only providers svc-db-redis and svc-db-memcached the
run-once guard (main.yml includes 01_core.yml when run_once_<role> is undefined;
01_core.yml sets the flag) so they satisfy the shared-provider run_once guard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 06:03:17 +02:00
kevinveenbirkenbachandClaude Opus 4.8 fc5ad87dc5 feat(roles): make referenced partner services proper shared providers
Declare the 14 services that consuming roles reference but no role provided
(bigbluebutton, xwiki, openproject, gitlab, mattermost, matrix, zammad,
openwebui, flowise, peertube, moodle, suitecrm, redis, memcached) as shared
providers: set enabled/shared/bond on each entity so the service registry
registers them and the dangling references resolve.

Add test_shared_service_provider.py (lint): fail when a referenced shared
service has no provider and its name matches a role's entity/provider that does
not register it (suppressable via '# nocheck: shared-provider').

Guard the 9 web-app shared services with the run-once 01_core.yml pattern
(main.yml includes 01_core.yml only when run_once_<role> is undefined; the core
flags itself via utils/once/flag.yml) so they deploy once when pulled in by
multiple consumers. svc-db-redis/memcached are template-only (no runtime tasks).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 06:03:17 +02:00
kevinveenbirkenbach 989c0c0fa2 refactor(stacks): merge stateful/stateless backend+full stacks into sys-stk-backend/sys-stk-full
- Replace sys-stk-back-stateful + sys-stk-back-stateless with unified sys-stk-backend role
- Replace sys-stk-full-stateful + sys-stk-full-stateless with unified sys-stk-full role
- Add reusable task helpers: _load_service.yml (optional deps) and 01_database.yml (DB bootstrap)
- Switch optional dependency loading (OpenLDAP, Ollama) to service_load_enabled (enabled && shared) + run_once guard
- Remove legacy OLLAMA_LOCAL_ENABLED flag; rely on docker.services.ollama.enabled/shared config
- Update all affected app/service roles and web-app template to use new stack role names

https://chatgpt.com/share/69685fb2-cb1c-800f-a9e8-2f5f765a1a53
2026-01-15 04:31:54 +01:00
kevinveenbirkenbach e6803e5614 refactor(ansible): normalize include_role syntax and unify host config paths via path_join
- Remove stray spaces after include_role: across many roles to ensure clean YAML and
  consistent linting/formatting.
- Listmonk:
  - Introduce LISTMONK_CONFIG_HOST = [ docker_compose.directories.config, 'config.toml' ] | path_join
  - Use that var in the template task (dest) and the docker-compose volume mount
- Matrix:
  - Build MATRIX_SYNAPSE_CONFIG_PATH_HOST, MATRIX_SYNAPSE_LOG_PATH_HOST, and
    MATRIX_ELEMENT_CONFIG_PATH_HOST via path_join
- Mobilizon:
  - Build mobilizon_host_conf_exs_file via path_join
  - Keep get_app_conf strictness unchanged (defaults to True in our filter), so behavior
    remains strict even though the explicit third arg was dropped
- Simpleicons:
  - Build server.js and package.json host paths via path_join
- Numerous web-app roles (Confluence, Discourse, EspoCRM, Friendica, Funkwhale, Gitea,
  GitLab, Jenkins, Joomla, Listmonk, Mailu, Mastodon, Matomo, Matrix, MediaWiki,
  Mobilizon, Moodle, Nextcloud, OpenProject, Peertube, Pixelfed, Pretix, Roulette Wheel,
  Snipe-IT, Syncope, Taiga, WordPress, XWiki, Yourls) and web-svc roles (coturn,
  libretranslate, simpleicons) updated for consistent include_role formatting

Why:
- path_join avoids double slashes and missing separators across different config roots
- Consistent include_role: formatting improves readability and prevents linter noise

Ref:
- Conversation: https://chatgpt.com/share/68d14711-727c-800f-b454-7dc4c3c1f4cb
2025-09-22 14:55:25 +02:00
kevinveenbirkenbach 6ea8301364 Refactor: migrate cmp/* and srv/* roles into sys-stk/* and sys-svc/* namespaces
- Removed obsolete 'cmp' category, introduced 'stk' category (fa-bars-staggered icon).
- Renamed roles:
  * cmp-db-docker → sys-stk-back-stateful
  * cmp-docker-oauth2 → sys-stk-back-stateless
  * srv-domain-provision → sys-stk-front
  * cmp-db-docker-proxy → sys-stk-full-stateful
  * cmp-docker-proxy → sys-stk-full-stateless
  * cmp-rdbms → sys-svc-rdbms
- Updated all include_role references, vars, templates and README.md files.
- Adjusted run_once comments and variable paths accordingly.
- Updated all web-app roles to use new sys-stk/* and sys-svc/* roles.

Conversation: https://chatgpt.com/share/68b0ba66-09f8-800f-86fc-76c47009d431
2025-08-28 22:23:09 +02:00
kevinveenbirkenbach 022800425d THE HUGE REFACTORING CALENDER WEEK 33; Optimized Matrix and during this updated variables, and implemented better reset and cleanup mode handling, also solved some initial setup bugs 2025-08-15 15:15:48 +02:00
kevinveenbirkenbach 7a38241485 Made code more modular and refactored to cmp roles 2025-07-09 20:15:32 +02:00
kevinveenbirkenbach c9c73cbdb2 Decoupeld database, docker and proxy 2025-07-09 14:21:30 +02:00
kevinveenbirkenbach 575df76ec3 Shortened service- to svc- 2025-07-09 05:00:41 +02:00
kevinveenbirkenbach 66198ca1ec Shortened webserver to srv-web- 2025-07-09 04:27:58 +02:00
kevinveenbirkenbach 563d5fd528 Huge role refactoring/cleanup. Other commits will propably follow. Because some bugs will exist. Still important for longrun and also for auto docs/help/slideshow generation 2025-07-08 23:43:13 +02:00