Commit Graph
6 Commits
Author SHA1 Message Date
kevinveenbirkenbachandClaude Fable 5 194671d90f feat(readme): uniform description schema and clearer role titles
Rewrite all 254 role descriptions to a uniform noun-phrase schema
(function-first, no leading verb, no trailing period, <=120 chars) and
enforce it via the extended description lint. Rename 12 role README H1
titles for clarity (e.g. Backup Container to Local -> Backup Docker
Volumes, CSS Service -> Corporate Design, NGINX Legal -> Imprint) and
regenerate their Cosmos and Quick Setup sections. Overview table
regenerated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 01:11:48 +02:00
kevinveenbirkenbachandClaude Opus 4.7 951f6d36d2 chore(lint): unify autoformat/galaxy parallelism into one PARALLEL env var
* scripts/lint/autoformat.sh: rename AUTOFORMAT_PARALLEL to PARALLEL,
  declare it at file start with default `true`; still env-overridable.
  Reword the worker comment so the literal `# shellcheck` token no
  longer appears at start-of-line and trips SC1072/SC1073.
* scripts/lint/galaxy.sh: drop the GALAXY_FATAL / GALAXY_NAMESPACE /
  GALAXY_PARALLEL env vars (over-engineered for a single repo). Failure
  is always fatal. NAMESPACE is an internal constant. Add the same
  PARALLEL env var (default `true`, env-overridable); falsy demotes the
  xargs fan-out to one worker.
* docs/contributing/environment/variables.md: collapse the four
  AUTOFORMAT_*/GALAXY_* rows into one `PARALLEL` row covering both
  consumers.
* docs/contributing/tools/make.md: refer to `PARALLEL=0` everywhere;
  add the lint-galaxy parallelism note.

Plus working-tree drift across roles/, group_vars/, inventories/, and
tasks/ that accumulated from the make-test setup phase regenerating
generated artefacts during recent test runs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 00:59:24 +02:00
kevinveenbirkenbachandClaude Opus 4.7 79409ebf10 test(tooling): integrate markdownlint-cli2, ansible-lint, galaxy-importer + fix the resulting baseline
Tooling integration
* add .markdownlint-cli2.jsonc, .ansible-lint, .ansible-lint-ignore
  configs (permissive day-1: cosmetic rules disabled, semantic ones on)
* extend scripts/install/lint.sh with generic install_pip_pkg helper +
  ensure_ansible_lint / ensure_galaxy_importer / ensure_markdownlint_cli2
  ensure_* functions (pip / npm with sudo / --user / --break-system-packages
  fallbacks). install_ansible_tools now also pulls ansible-lint and
  galaxy-importer; new `markdown` install group.
* extend scripts/lint/ansible.sh to run ansible-lint after the existing
  syntax-check.
* add scripts/lint/markdown.sh and scripts/lint/galaxy.sh runners. The
  galaxy runner parallelizes via xargs (-P=$(nproc)), prints OK/FAIL per
  role, and treats `bare-name dependency` errors as success since our
  roles/ tree is not a Galaxy collection layout. All other Galaxy schema
  errors still fail.
* Makefile: new lint-markdown and lint-galaxy targets, both wired into
  `make lint`.
* CI: new workflows lint-markdown.yml and lint-galaxy.yml; lint-ansible.yml
  now installs ansible-core + ansible-lint; ci-orchestrator wires both
  new lint workflows into lint-gate.

Galaxy schema fixes
* shorten the canonical `galaxy_info.company` block from three lines to
  two ("Kevin Veen-Birkenbach\nhttps://www.veen.world", 45 chars) so it
  stays under Galaxy's hard 50-char limit. Updated everywhere: 229 role
  meta/main.yml plus _CANONICAL_COMPANY in
  tests/lint/repository/test_role_meta_main_galaxy_schema.py.
* shorten 19 over-long role descriptions to <=255 chars.
* add stub READMEs for sys-svc-compose-ca and sys-utils-service-loader.

Markdown baseline fixes
* markdownlint-cli2 --fix run repo-wide (formatting normalization
  across CHANGELOG, role READMEs, docs).
* manual MD041 fixes: prepend H1 in 15 files (CHANGELOG, LICENSE,
  TODO.md helpers, role README templates, etc.).
* MD025 / MD003 / MD001 / MD032 manual fixes for heading-style and
  list-spacing edge cases.
* role README content polish: "## Single Point of Truth (SPOT)" headings
  renamed to "## User data resolution" (D3 self-label rule).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 23:46:37 +02:00
kevinveenbirkenbachandClaude Opus 4.7 afdbd58540 chore(roles): normalize meta platforms + role README Credits, revert GenericLinux drift
* meta/main.yml: replace every prior platforms variant (Linux,
  GenericLinux, Any, Archlinux+rolling/all, distro-specific pins) with
  the canonical 5-distro list (ArchLinux, Debian, EL, Fedora, Ubuntu;
  versions: [all] each).
* lint: merge tests/lint/ansible/roles/test_meta_company_canonical.py
  into tests/lint/repository/test_role_meta_main_galaxy_schema.py and
  add a parallel canonical-platforms exact-value check; one file walk
  enforces both schema conformance and the two project canonical
  exact-values (company block-scalar + platforms 5-distro list).
* roles/<role>/README.md: strip emojis from H1/H2 headings (per
  readme_md.md role rule), normalize the Credits block to the canonical
  wording (Author/Authors/Author Information aliased; canonical block
  appended where absent).
* repo-wide: revert text-drift `GenericLinux` -> `Linux` in role
  description fields, README body prose, vars, j2 templates, and the
  Makefile (87 occurrences). The lint docstring keeps a single
  historical mention.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 22:15:39 +02:00
kevinveenbirkenbachandClaude Opus 4.7 01e0937240 fix(iam): make OpenCloud and OpenTalk Playwright OIDC scenarios pass and add OpenTalk recorder
Iterates the role-local Playwright specs from a structural skeleton into
fully green end-to-end scenarios that exercise the SSO handoff for both
the administrator and the biber LDAP persona, against the actual
deployed stack, and adds optional meeting recording for OpenTalk.

OpenCloud (web-app-opencloud)
- Add Keycloak's URL to connect-src and frame-src in the role CSP via
  lookup('tls', 'web-app-keycloak', 'url.base') so the SPA can hit the
  OIDC discovery and authorize endpoints from the browser
- Switch to read-only LDAP semantics: PROXY_AUTOPROVISION_ACCOUNTS=false,
  GRAPH_USERNAME_MATCH removed, GRAPH_ASSIGN_DEFAULT_USER_ROLE=true
- Set OC_LDAP_DISABLE_USER_MECHANISM=none so the user-lookup filter
  stops referencing the OpenCloud-only `openclouduserenabled` attribute
  that the central LDAP schema does not define
- Pin the image to opencloudeu/opencloud:4.0.6
- Spec primes localStorage forceAllowOldBrowser, bypasses the "browser
  not supported" splash, submits via Enter, asserts the Files-view banner

OpenTalk (web-app-opentalk)
- Provision a dedicated confidential Keycloak client `opentalk-controller`
  via kcadm so the controller can introspect access tokens; the shared
  realm client stays public for the browser PKCE flow. The service
  account is granted the realm-management view-users / query-users roles
  for the Keycloak admin Web API user-search backend
- Inject an nginx vhost extension via webserver_extra_configuration that
  routes /v1/, /signaling, and /livekit on open.talk.<DOMAIN> to the
  controller and LiveKit upstreams; the default route stays on the
  frontend
- Fix the frontend env vars to upstream names (OIDC_ISSUER, BASE_URL=""),
  pin the frontend image to v2.8.1
- Spec races between auto-redirect and explicit "Sign in" CTA, submits
  via Enter, asserts the post-login Home-link in the dashboard
- Add OpenTalk recorder (registry.opencode.de/opentalk/recorder v0.16.2)
  plus RabbitMQ broker (rabbitmq:4.2.4); wire the controller to publish
  recording jobs on the `opentalk_recorder` queue and the recorder to
  consume them; provision a dedicated confidential `opentalk-recorder`
  Keycloak client for the recorder service account
- Reference Keycloak and the cross-app domain through lookup('tls', ...)
  and lookup('domain', ...) in meta/server.yml instead of literal
  `auth.<DOMAIN>` / `open.cloud.<DOMAIN>` strings

Cross-cutting
- Rename canonical hostnames to the <vendor>.<category> pattern:
  - web-app-opentalk:    talk.<DOMAIN>  -> open.talk.<DOMAIN>
  - web-app-bigbluebutton: meet.<DOMAIN> -> bbb.talk.<DOMAIN>
- Restructure both READMEs to the per-role README contract; drop emojis
  from headings; strip em dashes / history phrases / self-SPOT
  declarations from IAM.md / LDAP.md / TODO.md
- Replace technical galaxy_info descriptions with user-facing copy so
  the dashboard cards read clearly

Validated end-to-end via the Role Loop (deploy-fresh-kept-apps then
deploy-reuse-kept-apps with SERVICES_DISABLED=matomo,email): all
seven OpenTalk containers + the OpenCloud container come up healthy,
scripts/tests/e2e/rerun-spec.sh web-app-opencloud and
scripts/tests/e2e/rerun-spec.sh web-app-opentalk both finish with
`2 passed`, and `make test` is green (1604 + 162 tests).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 17:05:10 +02:00
kevinveenbirkenbachandClaude Opus 4.7 84058f0cba feat(iam): add web-app-opencloud and web-app-opentalk with shared OIDC + LDAP
Implements requirement 015. Both new roles join the central Keycloak
realm and consume the central OpenLDAP through the same patterns as
web-app-nextcloud, so users can move between Files (OpenCloud) and
Video (OpenTalk) without separate accounts.

OpenCloud (web-app-opencloud)
- Single-binary deploy of opencloudeu/opencloud:4.0.6 at open.cloud.<DOMAIN>
- External Keycloak as IdP (OC_EXCLUDE_RUN_SERVICES=idp,
  PROXY_AUTOPROVISION_ACCOUNTS=true, PROXY_ROLE_ASSIGNMENT_DRIVER=oidc)
- Direct OpenLDAP user/group source via OC_LDAP_*
- Co-deployable with web-app-nextcloud (next.cloud.<DOMAIN> stays put)
- WEB_OPTION_OPENTALK_URL surfaces the OpenTalk meeting launcher into
  the Files UI when web-app-opentalk is in scope

OpenTalk (web-app-opentalk)
- Controller + LiveKit + web-frontend + dedicated Redis + dedicated MinIO
  (controller refuses to start without an S3 backend) at talk.<DOMAIN>
- Uses shared svc-db-postgres for relational data and shared
  web-svc-coturn for STUN/TURN (no dedicated TURN provisioning)
- Native Keycloak integration via controller.toml [oidc.*] +
  [user_search] backend = "keycloak_webapi"; LDAP is consumed
  transitively through Keycloak's federation
- Frontend env exposes SHARED_FOLDER_OPENCLOUD_URL when web-app-opencloud
  is in scope, wiring the in-meeting OpenCloud file picker
- Bucket bootstrap is idempotent: an Ansible task waits for MinIO and
  creates the configured bucket via mc

Cross-cutting
- Extends PORT_BANDS public.relay to 65535 so LiveKit's media UDP range
  (60000-60999) can coexist with web-svc-coturn (20000-39999),
  web-app-bigbluebutton (40000-49999), and web-app-nextcloud's onboard
  TURN (50000-59999)
- All credentials (OIDC client secrets, LDAP bind, TURN auth_secret,
  MinIO root, LiveKit API, OpenCloud JWT/transfer) are sourced via
  lookup('config', ..., 'credentials.*'); none are committed in plain text
- Each role ships IAM/LDAP docs mirroring web-app-nextcloud and
  role-local Playwright specs that cover the administrator AND biber
  personas through OIDC

Validated end-to-end via the Role Loop (deploy-fresh-purged-apps then
deploy-reuse-kept-apps with SERVICES_DISABLED=matomo,email): all five
OpenTalk containers + the OpenCloud container come up cleanly, the
controller successfully completes OIDC discovery against Keycloak, and
both canonical hostnames return HTTP 200 through the central reverse
proxy. Browser-validated assertions (admin role mapping, full SSO logout
propagation, OpenCloud<->OpenTalk cross-launch from a real LDAP user)
remain as TODOs in each role's TODO.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 09:10:58 +02:00