mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
fix/dev-python/python-upper-bound
21
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c35f2409a4 |
fix(web-app-odoo): make the OAuth addon work on Odoo 20
Nobody could sign in to Odoo through Keycloak. Odoo sent an http redirect URI, and Keycloak refused it as "Invalid parameter: redirect_uri". The addon auth_oauth_https builds that URI from web.base.url. Two things kept it from doing so after the image moved to Odoo 20. Its manifest declared version 19.0.1.8.0, and Odoo marks a module whose version names another series as not installable. It only warns about that, so the install task stayed green and the addon was missing. The manifest now declares 1.8.0, which Odoo prefixes with its own series. Once installed, the addon read the parameter with get_param, which Odoo 20 replaced by typed getters. The call raised AttributeError, a broad except logged it and fell back to the URL of the request, which is http behind the proxy. The addon reads the parameter with get_str now and no longer catches the error. A deploy now fails when the addon is not installed afterwards. The check reads ir_module_module, because the output of "odoo -i" does not tell an installed module from a skipped one. The spec logged out by navigating to /web/session/logout. Odoo 20 accepts POST only on that route and answered 405, so both SSO tests failed after a successful login. The spec logs out through the user menu now. A host that runs the suite with several workers still failed it. Odoo computes the session token of an account from its OAuth access token, so every new sign-in ends the other sessions of that account, and the spec files share the administrator. The role caps its suite at one worker with PLAYWRIGHT_MAX_WORKERS, which the central config now honours, and the spec asserts the cap. Closes #822 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
|
|
70ad33bc13 |
fix(web-app-peertube): repair the SeaweedFS object-store e2e test for PeerTube v8.2.1
The test timed out: the publish-button locator no longer matched the v8.2.1 manage-video wizard, and the inline 78-byte MP4 stub was structurally invalid, so PeerTube rejected the upload as "Video file unreadable" and left the Save button disabled. - test-seaweedfs.js: target the v8.2.1 save control (.save-button > button), upload PeerTube's real video_short.mp4 fixture, and assert a version-tolerant saved marker. - add fixture roles/web-app-peertube/files/playwright/fixtures/video_short.mp4. - test-e2e-playwright: stage role-local files/playwright/fixtures/ next to the tests (the *.js glob ships neither binaries nor subdirectories), so specs load a fixture via path.join(__dirname, "fixtures", <name>). - docs: document the fixtures/ folder and the per-scenario test-*.js split in the playwright spec contract and the runner README. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
84bd56e72c | Merge branch 'main' into feature/req-21-sso-flavor-migration | ||
|
|
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>
|
||
|
|
4187237ed0 |
docs(req-21): rename stale oidc/oauth2 service-gate refs to sso
Three docs still referenced the pre-collapse service keys:
* docs/contributing/artefact/files/role/playwright.specs.js.md — biber
and administrator auth-chain diagrams listed
`skipUnlessServiceEnabled('oidc' | 'oauth2' | 'ldap')`; the unified gate
is `'sso' | 'ldap'`.
* docs/contributing/design/role/services/base.md — the `lookup('service',
...)` example block carried the now-invalid `'oidc'` key; replaced
with `'sso'`.
* docs/requirements/019-playwright-meta-services-parity.md — the
prometheus, matomo, and mailu rows still spelled
`safeSkipUnlessEnabled("oauth2"|"oidc")` and
`isServiceEnabled("oauth2")`; all rewritten to `"sso"`.
|
||
|
|
aacca6025d |
docs(playwright-specs): require dedicated LDAP scenario per persona, drop contradictory variant-pinning sentence
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
5196283f6c |
refactor(test-e2e-playwright): bake @playwright/test into a shared node_modules
Per-role Playwright runs no longer call `npm install` against registry.npmjs.org on every invocation. A new `01_setup.yml` runs once per host/version, populates `_shared/node_modules/` inside the Playwright container, and stamps the installed version in `.installed-version`. Each `02_run_one.yml` mounts that tree read-only at `/e2e/node_modules` and the container command becomes `npx --no-install playwright test`. This eliminates the npmjs.org TLS-handshake flake that took out the keycloak playwright in a recent variant-2 update, saves ~4 s per role, and gives version bumps a single rebuild point. Three retry layers cover transient registry failures: Ansible (3× with 5 s delay), npm fetch (5× with 10-60 s backoff), and image pull (3×). Stage-base / shared-dir / stamp / node_modules paths live as SPOT constants in `vars/main.yml` so call sites never reconstruct them. Renames `tasks/run_one.yml` → `tasks/02_run_one.yml` (and adds `01_setup.yml`) to make the include order visible by filename; updates cross-references in `AGENTS.md`, the two `docs/contributing/...` pages, `dump_disk_diagnostics.sh`, and the lint test. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
9a578952c3 |
feat(env): SPOT env-pipeline + INFINITO_* namespace
Replace 8 bash env modules with a single Python generator
(cli.meta.env) that materialises env/static.env + runtime context
into a gitignored .env. Each variable lives in its own handler
under utils/env/handlers/; defaults carry inline one-line `# ...`
comments.
Rename to the INFINITO_* schema:
- workflow inputs: APPS, SERVICES_DISABLED, CMD, DEBUG, WHITELIST,
BUNDLES, FULL_CYCLE, VARIANT, RUN_FLAGS, LIMIT_HOST, PARALLEL
- inventory: INVENTORY_DIR / INVENTORY_FILE / HOST_VARS_FILE,
PW_FILE -> INVENTORY_PASSWORD_FILE
- venv: VENV_BASE / VENV_FALLBACK / VENV_NAME
- new SPOT defaults: COMPILE_SILENCE, CONTAINER_NO_CA,
WAIT_HEALTH_TIMEOUT_S, PACKAGE_CACHE_FRONTEND_INIT_IMAGE,
promoted IMAGE_TAG from GHA-only to general passthrough
compose.yml hardening:
- inline \${VAR:-default} removed; strict \${VAR:?...} everywhere
- new integration lint blocks regressions
Tooling:
- scripts/install/all.sh owns the stamp-file install logic
(Makefile target delegates)
- scripts/meta/env/load.sh is the single shell entry point;
8 bash modules deleted
- new shell lint: no INFINITO_* defaults outside env/static.env
Tests:
- 93 new unit tests for utils/env/{builder,parser,runtime,writer}
- restructure tests/lint into repository/ (file-content rules) vs
filesystem/{shell,python,env}/ (filesystem-shape rules)
- drift + smoke integration tests against the generator
Docs:
- variables.md is now a pointer; per-variable docs live next to
the key in env/static.env / env/ci.env
- compose.yml.md drops the Default column
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
c2c532c8e6 |
refactor(playwright): centralize dashboard-tile mechanics in web-app-dashboard SPOT; move specs into files/playwright/ subdir
Architecture
============
- New SPOT helper `roles/web-app-dashboard/files/playwright/dashboard-card-flow.js` (`runDashboardCardScenario(page, context, target)`): per `roles_with_service('dashboard')` target, asserts tile visible → click loads in `#main iframe` (outer URL gets `?iframe=` + iframe src matches canonical_domain) → header "Tab" button pops the embed into a fresh browser tab.
- `web-app-dashboard/files/playwright/playwright.spec.js` parametrised loop calls the helper for every `DASHBOARD_TARGET_ROLES_JSON` entry — the single owner of dashboard-tile mechanics across the whole codebase.
Spec relocation
===============
- 71 `roles/<role>/files/playwright.spec.js` → `roles/<role>/files/playwright/playwright.spec.js` (`git mv`, history preserved). odoo + pixelfed show as D+A in `git status` because of substantial content rewrites; coverage retained.
- New SPOT constant `ROLE_FILE_PLAYWRIGHT_SPEC` in `utils/roles/mapping.py`, registered as optional on `ROLE_TYPE_APPLICATION` (disallowed elsewhere, mirrors `ROLE_FILE_META_VARIANTS` pattern).
- `roles/test-e2e-playwright/tasks/run_one.yml`: staging task replaced with `with_fileglob` over `files/playwright/*.js` — roles can ship companion helpers (like `dashboard-card-flow.js`) next to the spec without further wiring.
Spec migrations (no more dashboard-iframe path in app specs)
============================================================
13 specs rewritten so the persona/SSO journey starts at the app URL directly, never through the dashboard tile or iframe:
* fider, mailu, mattermost, nextcloud, odoo, taiga: iframe-wrap removed (no more `frameLocator("#main iframe")`)
* bigbluebutton, discourse, kix, matrix, openwebui, peertube: dashboard goto preamble removed
* pixelfed: ~270 LOC of iframe-aware helpers/login/logout collapsed to direct-URL flow
Title cleanup
=============
- 64 specs: `"<persona>: dashboard → app → universal logout"` / `"administrator: dashboard → prometheus → app → universal logout"` → `"<persona>: app → universal logout"`.
- 13 specs: `"<persona>: dashboard to <app> ..."` → `"<persona>: <app> ..."`.
Dead-code cleanup
=================
- `dashboardBaseUrl` consts + beforeEach assertions removed from 11 specs (no functional uses; personas helper handles env validation).
- `DASHBOARD_BASE_URL=` env-template lines removed from fider, mattermost, odoo, taiga, pixelfed, kix.
- `DASHBOARD_SERVICE_ENABLED=` env-template lines removed (pixelfed retained for the still-gated spec).
- Stale "loads inside the iframe" / "FrameLocator parameter" comments cleaned in fider, odoo, prometheus, nextcloud.
Tooling
=======
- 5 lint Python files + 1 integration test now use `from utils.roles.mapping import ROLE_FILE_PLAYWRIGHT_SPEC`.
- `eslint.config.js` glob pattern + `roles/test-e2e-playwright/meta/main.yml` description + `roles/test-e2e-playwright/README.md` updated to new path.
- 25 markdown/docstring references in `docs/`, `roles/**/README.md`, `roles/**/TODO.md`, persona-helper docstrings updated to new path.
- `docs/contributing/artefact/files/role/playwright.specs.js.md`: file-placement section now documents the `files/playwright/` convention + `ROLE_FILE_PLAYWRIGHT_SPEC` SPOT constant; dashboard SPOT delegation explicit at 3 places.
Net diff: 124 files, +1142/-1564 (−422 LOC).
Integration suite: 183/183 green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
4ac7a95ec6 |
refactor(tests): split overflowing folders into thematic subdirs
Reorganises four folders that exceeded the 12-item readability limit: - tests/lint/repository/ (27 -> 11): structure/, naming/, documentation/, python/, dependencies/, shell/, yaml/, network/, settings/ - tests/integration/ (25 -> 7): ansible/, infrastructure/, iam/, meta/ (24 sibling dirs grouped under 4 super-categories) - tests/integration/roles/ (13 -> 10): naming/, playwright/, dashboard/ - tests/unit/utils/ (15 -> 12): certs/ for 3 cert/TLS test files Renames 7 test files whose name duplicated the new folder name (e.g. test_no_direct_yaml_calls.py -> yaml/test_no_direct_calls.py, test_dashboard_integration_scope.py -> dashboard/test_integration_scope.py). Adjusts parents[N] in moved __init__.py files, fixes __file__-based path resolution in 8 tests, updates self-path whitelists, and uses absolute imports for PROJECT_ROOT re-exports (ruff TID252). Adds README.md to each new subfolder following the existing scope template. Updates all docs links (suppression.md, base.md, email.md, playwright spec/parity docs, 005-/019- requirements) to new paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
7018b3c991 |
refactor(playwright): share CSP header/meta/violation helpers
Nine role specs (bigbluebutton, dashboard, discourse, keycloak,
matomo, matrix, moodle, openwebui, wordpress) each carried inline
copies of the same six CSP helpers and the `EXPECTED_CSP_DIRECTIVES`
constant. The bodies were semantically identical; only message
wording, brace style, and one captured-field-set differed.
Changes
-------
- Extends `roles/test-e2e-playwright/files/personas/utils/csp.js`
(already home to `assertCspInjections`) with
`installCspViolationObserver`, `readCspViolations`,
`parseCspHeader`, `assertCspResponseHeader`,
`assertCspMetaParity`, `expectNoCspViolations`, and the
`EXPECTED_CSP_DIRECTIVES` constant. The helpers are re-exported
through `personas/utils/index.js` so specs that
`require("./personas")` get them via the existing aggregator.
- Strips the inline definitions from the nine role specs and amends
each spec's `require("./personas")` destructuring with whichever
helpers the body still references.
Drift handling
--------------
- moodle's reduced violation-record shape (only `violatedDirective`
+ `blockedURI`) is replaced by the canonical 5-field record.
Moodle's downstream consumer asserts `.toEqual([])` on the array
only, so the extra fields are diagnostic-only — no behaviour
change.
- dashboard's 2-arg `expectNoCspViolations(page, label)` call site
is updated to the canonical 3-arg form
`expectNoCspViolations(page, null, label)`. The shared helper
guards `if (diagnostics && Array.isArray(diagnostics.cspRelated))`
before checking the diagnostics arm, so passing `null` keeps the
exact pre-migration behaviour for that call site.
- bigbluebutton and matrix had subtly different failure-message text
in `assertCspResponseHeader` and `expectNoCspViolations`. The
canonical wording is more descriptive; passing tests are
unaffected, failing tests get clearer diagnostics.
Doc
---
`docs/contributing/artefact/files/role/playwright.specs.js.md` is
extended in two places: the invariants section names the full CSP
test surface and pins the "import from `./personas`, no inline copy"
rule, and the per-service catalogue's CSP / injectors row lists the
helpers by name.
Verification
------------
- 419 passed / 1 skipped / 0 failed across `tests/lint/`,
`tests/integration/roles/`, `tests/unit/plugins/lookup/`.
- `make lint-javascript`: 0 errors, 283 warnings (unchanged from
baseline).
- `markdownlint-cli2`: 0 errors on the touched doc.
- 0 inline definitions of any extracted helper / constant remain in
any role spec.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
122c82910b |
refactor(playwright): share decodeDotenvQuotedValue + normalizeBaseUrl
Both helpers were inlined verbatim in 71 of the role-local
`playwright.spec.js` files (52 with the compact form, 19 with the
verbose form, plus one parameter-name variant). All bodies were
semantically identical.
Changes
-------
- New `roles/test-e2e-playwright/files/personas/utils/dotenv.js` holds
the canonical pair (`decodeDotenvQuotedValue` and `normalizeBaseUrl`),
re-exported through `personas/utils/index.js` so specs that
`require("./personas")` get them via the existing aggregator.
- Every role spec drops its inline copies and pulls the helpers from
`./personas` instead. Specs that only reference one of the two
carry only that one in the destructuring (no unused-import noise).
Doc
---
`docs/contributing/artefact/files/role/playwright.specs.js.md` no
longer carries the "once a third spec needs them, MUST be promoted"
directive: the helpers live at the shared path and inline copies are
forbidden.
Verification
------------
- 419 passed / 1 skipped / 0 failed across `tests/lint/`,
`tests/integration/roles/`, `tests/unit/plugins/lookup/`.
- `make lint-javascript`: 0 errors, 283 warnings (unchanged from
baseline; no new unused-imports introduced).
- 0 inline `function decodeDotenvQuotedValue|normalizeBaseUrl`
definitions remain in any role spec.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
db2a2d9638 |
refactor(playwright): move cross-service tests to provider specs
Cross-service surface assertions for dashboard, prometheus and matomo
no longer run in every consumer role's persona. They are owned by the
provider's own spec, parameterised once over a `<NAME>_TARGET_ROLES_JSON`
manifest rendered into the provider's `templates/playwright.env.j2` via
the new `lookup('roles_with_service', '<svc>')` Ansible lookup.
Changes
-------
- New `plugins/lookup/roles_with_service.py` enumerates roles that
declare `services.<svc>.{enabled, shared}` truthy in the merged
applications config, returning `[{id, canonical_domain}, …]`.
- `roles/web-app-{dashboard,prometheus,matomo}/files/playwright.spec.js`
parse `<NAME>_TARGET_ROLES_JSON` and parameterise the per-consumer
assertion (dashboard tile reachability, prometheus `up=1`, matomo
SitesManager registration). The matomo spec gains an explicit
biber-denial test (request body validated against admin DOM markers
per the body-marker rule); the prometheus admin-reach test drops
the dashboard-iframe path in favour of direct goto.
- Persona helpers `roles/test-e2e-playwright/files/personas/{admin,
biber,guest}.js` enter at `${APP_BASE_URL}/` directly. The
`clickRoleTileFromDashboard` step and the `assertPrometheus*` /
`assertMatomo*` cross-service probes are gone; `utils/{dashboard,
prometheus,matomo}.js` are deleted. `utils/csp.js` switches to
literal `process.env.<KEY>` reads so the env-keys-used parity guard
recognises matomo's CSP injector consumption.
- 42 consumer-role `templates/playwright.env.j2` templates drop
`DASHBOARD_BASE_URL`, `DASHBOARD_SERVICE_ENABLED`, `PROMETHEUS_BASE_URL`,
`PROMETHEUS_SERVICE_ENABLED`. `MATOMO_BASE_URL` and
`MATOMO_SERVICE_ENABLED` stay because the per-role CSP injection
helper still gates on matomo's tracker host.
- `tests/integration/roles/test_playwright_env_services_match.py`
globally exempts `dashboard` and `prometheus` from the
services.yml-to-env parity rule.
- `tests/unit/plugins/lookup/test_roles_with_service.py` adds 14
unit tests for the lookup, including an explicit-contract test
that pins the over-inclusive behaviour on raw Jinja strings (the
lookup expects a templar-rendered payload).
- Docs: `docs/requirements/019-playwright-meta-services-parity.md`
rewords Rules 1, 3, 12 and adds Rule 13 describing the SPOT shift.
`docs/contributing/artefact/files/role/playwright.specs.js.md`
reflects the new persona shape and per-service catalogue, and is
cleaned per `docs/contributing/documentation.md` (no SPOT self-
labels, no req-references, em dashes replaced with complete
sentences, multi-clause lines split onto separate lines, broken
anchor `#two-personas-fixed-flow-` corrected).
Verification
------------
- 418 passed / 1 skipped / 0 failed across `tests/lint/`,
`tests/integration/roles/`, `tests/unit/plugins/lookup/`.
- `make lint-javascript`: 0 errors.
- `markdownlint-cli2`: 0 errors on all touched docs.
- `make autoformat`: clean (FURB171 single-item-set inequality fixed).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
672c61e37e |
test(playwright/personas): hard-fail on un-executable persona journeys
The persona-flow runners now fail loudly when biber / administrator cannot reach an authenticated surface on the role under test. The previous runtime auto-detection silently `test.skip(...)`'d, hiding real regressions (broken OIDC mapping, removed logout button, misconfigured oauth2-proxy, drifted UI selectors) behind a green deploy. Roles where the persona legitimately has no access (admin-only roles, auth-provider roles) MUST declare an explicit env opt-out `PERSONA_BIBER_BLOCKED=true` / `PERSONA_ADMINISTRATOR_BLOCKED=true` in `templates/playwright.env.j2` with a documented rationale; without the flag the helper fails the test with a diagnostic naming the last-seen URL. A new lint guard (`test_persona_strict_mode.py`) hard-fails any future `test.skip(...)` in the persona helpers that is not guarded by an allowed env opt-out / auth-less-collapse / service-gate condition, and any `status === 200` branch in the prometheus / matomo deny-check helpers that does not validate role-specific body markers. Req 019 Rule 11 (strict-skip contract) and Rule 12 (200-body validation) plus a matching "Strict failure on un-executable persona cases" section in `playwright.specs.js.md` document the contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
0b14ca4d09 |
test(lint): forbid stub bodies in persona/contract playwright tests
Adds a lint that rejects empty/tautological/TODO-marked persona and contract test bodies in roles/<role>/files/playwright.spec.js, plus the spec-contract doc updates (playwright.specs.js.md, req-017/018/019) and the integration-test parity-guard tweak that articulate it. Reason: previous batch updates produced "contract: <svc> gate is wired" stubs whose bodies only proved what the gate itself already proved; the lint catches both the title shape and the body shape so a rename is not enough. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
f6865c6464 |
docs(req-019): tighten persona contract + autonomous closure procedure
Two coupled doc changes that turn req 019 from "the matrix" into a self-contained, agent-runnable rollout plan. playwright.specs.js.md (the per-role spec contract): - Persona scenarios are MUST-include with `<persona>: <flow>` naming; additional scenarios MAY be added on top. - New invariants for browser-context isolation, post-login assertion hierarchy, admin authorisation hierarchy, and `ignoreHTTPSErrors`. - New trigger entries for CSP baseline, cross-role round-trip hosting, and variant-specific scenarios. - New sub-sections "Test-budget overrides" (when `test.setTimeout`) and "Cleanup and teardown" (try/finally, idempotent, bounded). - Env-contract spelled out the minimum-required env-var set and the promote-to-shared-helper rule for `decodeDotenvQuotedValue` / `normalizeBaseUrl`. - OIDC-over-LDAP preference: when both are enabled, the persona flow uses OIDC; the LDAP-bind path lives in a separate scenario exercised by the LDAP-only matrix variant. req 019: - Vision rephrased: the role's single spec file is the unit of coverage; (role, included-service) pair MUST be exercised by ≥1 gated step inside it. - Persona scenarios are mandatory tree-wide (Rule 3); web-svc-* and the listed auth-less web-app-* roles MAY collapse to a single baseline. - New "Closure procedure" section with: Required reading, Autonomy (no questions, no SERVICES_DISABLED, ignore unrelated failures), Closure vocabulary (flag-closure vs role-closure), Per-role flow (now incl. meta/variants.yml adjustment as step 5), Pattern transfer (post-deploy edits to all later roles, single deploy per role), Preserving existing tests (purely additive, rename-only-when-flow-matches), Iteration order (dependency-aware within tier; explicit auth-less list), Resumability (drift matrix IS the progress marker), Commits (single commit at end). - Per-service catalogue dropped as a duplicate; pointed at the page that owns it. - Stale test-path references updated to reflect the `tests/lint/ansible/roles/web-app/playwright/` move. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
256e027525 |
docs: drop stale requirement refs + reflow soft-wraps to one sentence per line
Removes 67 live references to docs/requirements/<NNN>-*.md files across
43 contributor docs, role READMEs, code comments, task files, and tests.
Requirement docs are initial-creation-only artefacts; live references
freeze a snapshot that rots once the per-feature SPOT (a contributor
doc, a code module, a lint test) takes over the live behaviour.
In the same pass, fixes documentation.md violations on the touched
files: drops em-dashes used as thought breaks, removes "SPOT for ..."
self-labels, strips historical phrasing ("the legacy", "previously",
"used to", "is no longer used", "matching the historical"), and
reflows soft-wrapped sentences so each sentence stays on one logical
line.
The `test_inventory_vars_file_spot.py` whitelist for the literal
inventory path drops the docs/requirements/003 entry and instead
skips docs/requirements/ entirely; future requirement docs that
mention the literal path are then ignored automatically.
Verified by tests/lint/repository/test_no_stale_requirement_refs.py
(green tree-wide).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
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>
|
||
|
|
f0f802faf0 |
docs(requirements): add 005/006/007 and tighten Playwright spec guide
Add three follow-up requirements that extend the work landed in 004: - 005 WordPress Multisite support + LDAP per-application OU refactor: introduces opt-in rbac.tenancy schema, migrates every rbac-carrying role onto the ou=<application_id>,ou=roles,... hierarchy, adds a central rbac_group_path lookup plugin as the only sanctioned way to compute OIDC group paths, mandates one-time LDAP rewrite plus a Keycloak logout-all to flush stale tokens, and specifies the WordPress mu-plugin contract for per-site roles and grant_super_admin semantics. - 006 Service-gated Playwright tests: per-service <NAME>_SERVICE_ENABLED env flags, shared helper at roles/test-e2e-playwright/files/ service-gating.js with hard-fail on unknown services, test.skip() with flag-named reason, explicit per-role refactor checkboxes for every existing spec, and a new MODE_CI variable (GitHub Actions + nektos/act + make-driven deploy) replacing the accidental DOCKER_IN_CONTAINER proxy at the test-e2e-playwright include site. - 007 WordPress -> Discourse post round-trip: Playwright scenario that publishes a WP post and asserts the corresponding Discourse topic exists, gated on DISCOURSE_SERVICE_ENABLED, with teardown that covers draft and partial states and an API key scoped for topic delete. Also update the role Playwright spec guide to carry the Option B service-gating rules (per-service boolean flags, helper-only reads, hard-fail on unknown services) so contributor and requirement SPOTs stay in sync. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|
|
2bea93edaa |
test(web-app-nextcloud): add biber OIDC login scenario + expose biber creds
- playwright.spec.js: add "biber logs into nextcloud via OIDC and logs out" scenario covering the non-administrator persona required by the MUSTs; parameterize loginToStandaloneNextcloud on username/password, add a logoutStandaloneNextcloud helper, and wrap biber's first login in a retry so the LDAP first-login-provisioning delay does not flake. - playwright.env.j2: expose BIBER_USERNAME and BIBER_PASSWORD so the spec can read biber credentials from the rendered env. - docs/contributing/.../playwright.specs.js.md: codify the MUST that existing scenarios may not be deleted while optimizing a spec. - roles/web-app-nextcloud/docs/LDAP.md: document the biber first-login caveat against fresh Nextcloud + LDAP deployments. Validated via scripts/tests/e2e/rerun-spec.sh web-app-nextcloud: 3 passed (talk admin settings, dashboard to nextcloud login, biber). |
||
|
|
da140094a1 |
docs(agents): split iteration loops and refactor Playwright SPOT
Split docs/agents/action/iteration.md into role.md, playwright.md, workflow.md, and a scope-focused README. Move Certificate Authority and Inspect rules into role.md. Rewrite playwright.md as a machine- oriented state machine with explicit preconditions, procedure, exit gates, and escape path. Extract Playwright spec content MUSTs into the new contrib SPOT docs/contributing/artefact/files/role/playwright.specs.js.md. Reduce the agent-side spec and env.j2 pages to procedure only. Align the framework SPOT and the test-e2e-playwright role README with the central templates/package.json.j2 + files/playwright.config.js model and images.playwright.version as single source of truth. Sweep em dashes and sentence-case role headings across all touched docs per documentation.md and readme_md.md rules. |