fix(register): two dangling objectDescriptionField values detached the whole voorzieningen register — E2E has run 0 tests since 08-14 - #529
Conversation
…e whole voorzieningen register
The E2E (Playwright) job on `development` has not run a single test since
2026-08-14 19:29Z. It fails in the seed step, before Playwright starts, on
softwarecatalog's own honest gate:
softwarecatalog has no register/schema mapping for:
['organisatie_schema', 'contactpersoon_schema', 'module_schema', 'contract_schema']
That gate is correct and the register really is unusable. The chain, read
from the failing job's own Nextcloud log (run 31937311499):
1. `view` and `bioMeasure` declare `objectDescriptionField: "summary"` while
neither schema has a `summary` property. OpenRegister's
`SchemaMapper::validateConfigField()` throws for exactly this, and
`ImportHandler` logs
`Failed to import schema: The value for objectDescriptionField ('summary')
does not exist as a property in the schema.`
2. Both schemas are therefore absent from the import's `schemasMap`, so the
`voorzieningen` and `vng-gemma` registers are imported without them —
OpenRegister logs 18 `not found in schemasMap` warnings.
3. `SettingsService::configureVoorzieningen()` iterates the register's
schemas to build the app-config map. With the links gone it writes
`register` and nothing else, leaving every `*_schema` key empty.
4. `tests/e2e/ci-seed.sh` refuses to run Playwright against that. Correctly —
the alternative is ~20 spec failures blaming the fixtures.
Where the two values came from: commit 386771d (#513, "translate 12
pre-existing Dutch property names") renamed the `view` schema's `summary`
property KEY to `omschrijving` and left `objectDescriptionField` pointing at
the old key, and separately rewrote `bioMeasure`'s `objectDescriptionField`
VALUE from `omschrijving` to `summary` while its property key stayed
`omschrijving`. Two dangling references, opposite directions, one commit.
This points both at the property each schema actually declares. It does not
rename anything: a property rename here is a data migration and belongs with
the vocabulary programme, not with an E2E fix.
Evidence, same instrument both sides — OpenRegister's own three acceptance
forms applied to the shipped register file, 20 schemas / 38 configuration
fields measured:
before: 2 failures (view.objectDescriptionField, bioMeasure.objectDescriptionField)
after: 0 failures
The new test reproduces that measurement in PHPUnit and carries a positive
control asserting the check can fail, so a future rename cannot silently
detach the register again. Run in a php:8.3-cli container (the host is 8.2):
before fix: Tests: 4, Assertions: 21, Failures: 1 (naming both schemas)
after fix: OK (4 tests, 21 assertions)
phpcs --standard=phpcs.xml on the new file: exit 0, 1 file measured
The test also records the two `objectSummaryField` values that dangle today
(`element`, `relation`). OpenRegister does not validate that key, so they are
inert — asserted as a known set rather than zero, so adding a new one fails
while the existing debt stays visible.
First honest E2E tally in two days — and it caught a live production fatalThe seed fix works. Run 31940827485, job 95151081157:
The 47 decompose exactly, and 42 are one server-side fatalThe only 5xx URL in the entire run — 176 occurrences — is
Two failures were stacked, and the outer one hid the inner oneThe seed has been broken since 08-14, so the E2E job ran zero tests. When ADR-084 shipped a runtime fatal at 08:46 today, E2E could not see it — the column read "E2E red" identically before and after, while the meaning changed completely. A job that is red for reason A cannot report reason B. Unblocking a broken harness is what makes the next regression visible. Parity — this PR is not the cause of any of it
E2E should go green on this branch once the |
Quality Report — ConductionNL/softwarecatalog @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ❌ | ||||
| phpmd | ❌ | ||||
| psalm | ❌ | ||||
| phpstan | ❌ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-vue-demi | ✅ | ||||
| test-l10n | ✅ | ||||
| format | ✅ | ||||
| composer | ✅ | ✅ 130/130 | |||
| npm | ✅ | ✅ 704/704 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ❌ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-16 11:06 UTC
Download the full PDF report from the workflow artifacts.
The E2E job has run zero Playwright tests since 2026-08-14 19:29Z
Not "some specs fail".
0 passed / 0 failed / 0 skipped— the job dies inthe seed step, before Playwright is invoked, on softwarecatalog's own gate in
tests/e2e/ci-seed.sh:That gate is right, and it is the reason this was diagnosable at all. The
register genuinely is unusable.
The chain, read from the failing job's own Nextcloud log
Run 31937311499 (
0335cb20,push), step "Show Nextcloud log":Two schemas are rejected outright.
viewandbioMeasuredeclare"objectDescriptionField": "summary"whileneither declares a
summaryproperty. OpenRegister'sSchemaMapper::validateConfigField()throws on exactly that, andImportHandlerlogs at ERROR:The register is then imported with almost no schema links.
18 warnings, one per reference:
The 18 are every schema of
voorzieningenandvng-gemmaexceptmoduleVersionandsbomComponent— the only two declared after the lastfailing schema in file order. That is the fingerprint, and it is what
promotes "two bad schemas" into "the register is empty" (see the note to
OpenRegister at the bottom).
configureVoorzieningen()writes an empty map. It builds theapp-config from
$targetRegister['schemas']; with the links gone it writesregisterand nothing else:ci-seed.shrefuses to continue rather than hand Playwright ahalf-seeded instance. Correct call — the alternative is ~20 spec failures
blaming the fixtures.
Where the two values came from
Commit
386771dc(#513, "translate 12 pre-existing Dutch property names"),merged 2026-08-14 21:29 CEST:
viewsummary;objectDescriptionField: "summary"omschrijving; config value left at"summary"bioMeasureomschrijving;objectDescriptionField: "omschrijving""summary"Two dangling references, produced in opposite directions by the same commit —
a key rename that did not follow its reference, and a value rename that should
never have touched a reference at all.
Bisected against the runs adjacent to that merge, not last-green-vs-later-red:
voorzieningen configf4e57ebborganisatie_schema: "22", … all populated386771dc""""Corroborating detail from the same two logs: OpenRegister's schema count drops
37 → 35, and the two that vanish are exactly
viewandbioMaatregel.The change
Point each
objectDescriptionFieldat the property its schema actuallydeclares —
view→omschrijving(its description property, title"summary"),bioMeasure→omschrijving(restoring the pre-#513 value).Nothing is renamed here. #513's
summary → omschrijvingkey rename is abackwards translation applied to 43 sites across this file; undoing it is a
data migration and belongs with the vocabulary programme, not with an E2E fix.
Flagged on the fleet board.
Evidence — before/after, same instrument
OpenRegister's own three acceptance forms (Twig template / pipe fallback list /
plain name) applied to the shipped register file:
view.objectDescriptionField,bioMeasure.objectDescriptionFieldtests/Unit/Settings/RegisterConfigFieldResolutionTest.phpmakes that astanding check. Run in a throwaway
php:8.3-clicontainer (host is PHP 8.2):The test carries its own positive control (
testTheResolutionCheckCanFail)asserting each of the three failure shapes is detected and each of the three
accepted shapes is not, plus a measured-field floor so a broken traversal
cannot report a silent zero.
It also records the two
objectSummaryFieldvalues that dangle today(
element,relation). OpenRegister does not validate that key, so they areinert — asserted as a known set rather than as zero, so adding a new one fails
the build while the existing debt stays visible and counted.
What this PR does NOT claim
It does not claim the E2E suite passes. It claims the suite will run — the
seed gate is what has been blocking it. The specs' first real verdict in two
days arrives with this PR's own CI, and any failures it exposes are pre-existing
and get their own work.
Parity
Baseline for judging this PR: 31937311499 (
0335cb20,push,conclusion: failure) — 13 failing jobs.The 4 PHP Quality (phpcs/phpmd/psalm/phpstan) + 6 PHPUnit failures there are
the
refactor/adr-084-type-hint-the-contractregression (#519), owned by slotR1, and are present on
developmentwithout this branch. This PR contains nolib/PHP. Its owntests/bootstrap.phpcannot even load locally for the samereason (
Interface "OCA\OpenRegister\Contract\ObjectEntityInterface" not found),which is why the test above was run with
--bootstrap vendor/autoload.php.🔴 A note for OpenRegister — one bad schema detaches an entire register
ImportHandler::importFromJson()(two-pass schema import) does:The
catchlogs and continues but does not restore the map, so every schemaimported before the failing one is erased. That is why two rejected schemas
produced 18 missing register links rather than 2, and it will do the same to any
app whose configuration file has a single bad schema. Not fixed here —
OpenRegister is another slot's repo and mid-wave — but it is the amplifier, and
it is worth a three-line fix.