Skip to content

refactor(softwarecatalog): translate Dutch vocabulary to English - #506

Merged
rubenvdlinde merged 18 commits into
developmentfrom
feat/english-vocabulary-softwarecatalog
Aug 14, 2026
Merged

refactor(softwarecatalog): translate Dutch vocabulary to English#506
rubenvdlinde merged 18 commits into
developmentfrom
feat/english-vocabulary-softwarecatalog

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Applies the fleet Dutch→English pass: 93 property names plus identifiers, comments and docblock shapes. Extends RenameDutchCatalogColumns (6 pairs → 84) rather than adding a second step.

The pipeline aborted before touching anything, which is the point

relation already has both bron and source, and their descriptions say the same thing — a pre-existing duplicate from a partial earlier rename. Renaming bron onto source would collide and lose data; inventing a third name would be worse.

Consolidating them is a data decision for the owners, so bron is excluded with that reason recorded.

Two more exclusions, for fleet consistency

This app already shipped beschrijving_kort → short_description and beschrijving_lang → description. My dictionary would have produced descriptionKort and descriptionLang — half Dutch, and forking the app against its own migration.

It got as far as the registers (31 occurrences) before I noticed, because kort and lang carry none of the Dutch orthographic markers the residual guard looks for. Guard widened, both names excluded, branch rebuilt from clean. versies was the same story (standaardVersiesstandardVersies).

Two defects I caused by hand, both bypassing the tool's guards

  • shortening $moduleVersionSchemaId with a plain regex renamed the parameter but not its named arguments, breaking three call sites. The AST tool moves both together; my regex did not.
  • the name alias block in DataMapper normalised incoming name onto the then-canonical naam. The canonical is name now, so it became isset($data['name']) === false && isset($data['name']) === true — a contradiction that can never run. Removed rather than left as dead code.

Verification

In the nextcloud container, against a control run of clean development:

  • phpstan 0 · psalm 0 (no-cache; baseline 0) · phpmd 0 (baseline 0)
  • phpcs: 4 errors, identical to the baseline

Not verified locally: the test suite. softwarecatalog's bootstrap loads every installed app, and nldesign in this container is missing its vendor — the run dies before reaching a test, on the baseline too. CI must confirm the suite.

Conduction Release Bot added 2 commits August 13, 2026 12:14
…ending the existing migration

Applies the fleet Dutch->English pass: 93 property names plus identifiers,
comments and docblock shapes. Extends RenameDutchCatalogColumns (6 pairs -> 84)
rather than adding a second step.

THE PIPELINE ABORTED BEFORE TOUCHING ANYTHING, WHICH IS THE POINT

`relation` already has BOTH `bron` and `source`, and their descriptions say the
same thing — a pre-existing duplicate from a partial earlier rename. Renaming
`bron` onto `source` would collide and lose data; inventing a third name would
be worse. Consolidating them is a DATA decision for the owners, so `bron` is
excluded with that reason recorded in .exclude-swc-tr.json.

TWO MORE EXCLUSIONS, FOR FLEET CONSISTENCY. This app already SHIPPED
`beschrijving_kort -> short_description` and `beschrijving_lang -> description`.
My dictionary would have produced `descriptionKort` and `descriptionLang` — HALF
DUTCH, and forking the app against its own migration. It got as far as the
registers (31 occurrences) before I noticed, because `kort` and `lang` carry
none of the Dutch orthographic markers the residual guard looks for. Guard
widened; both names excluded; branch rebuilt from clean.

`versies` was the same story — `standaardVersies` became `standardVersies`.
Added to the dictionary, guard widened again.

TWO DEFECTS I CAUSED BY HAND, BOTH BYPASSING THE TOOL'S GUARDS
  - shortening `$moduleVersionSchemaId` with a plain regex renamed the parameter
    but not its NAMED ARGUMENTS, so three call sites broke. The AST tool moves
    both together; my regex did not.
  - the `name` alias block in DataMapper normalised the incoming key `name` onto
    the then-canonical `naam`. The canonical IS `name` now, so the block became
    `isset($data['name']) === false && isset($data['name']) === true` — a
    contradiction that can never run. Removed rather than left as dead code.

VERIFIED in the container against a CONTROL run of clean development:
  phpstan [OK] · psalm 0 no-cache (baseline 0) · phpmd 0 (baseline 0) · phpcs 4
  errors, IDENTICAL to the baseline.

NOT VERIFIED LOCALLY: the test suite. softwarecatalog's bootstrap loads every
installed app, and `nldesign` in this container is missing its vendor — the run
dies before reaching a test, on the baseline too. CI must confirm the suite.
…ecs, and a filter VALUE

phpstan passed locally and failed in CI. Cause: I "fixed" phpcs by changing
/** @var */ to /* @var */, and a SINGLE-ASTERISK comment is not a docblock, so
phpstan ignores it entirely. The annotation was dead the moment it satisfied the
other tool. Restructured instead: read every value BEFORE the write that narrows
the inferred array shape, which needs no annotation and cannot rot.

FRONTEND SPECS were stale rather than wrong: they pass `standaard` as an
UNQUOTED object key (`{ standaard: [...] }`), which the quoted-string rename
cannot see. The register calls it `standard`, so the specs were simply behind.

AND ONE REAL DEFECT THE MANIFEST WAS ABOUT TO SHIP

    "filter": { "gemmaType": "standaard" }   ->   "standard"

`gemmaType` is a STORED DATA VALUE on GEMMA element objects, not a property
name. Renaming it makes the filter match nothing and the Standaarden list page
silently goes empty — no error, no test, just an empty page.

Found by diffing every filter VALUE against the baseline rather than reading the
diff. That sweep now also covers lib/Settings: three filter values moved
in total, and only this one was data — the other two are `@objectId` /
`@object.name` tokens that did not exist in the baseline at all.

phpstan [OK] and phpcs at its baseline of 4 with both fixes in place together,
which was the thing that failed before.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ 32383b5

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-vue-demi
test-l10n
composer ✅ 130/130
npm ✅ 718/718
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-13 10:23 UTC

Download the full PDF report from the workflow artifacts.

…ted method

PHPUnit failed on ReflectionException for 28 private methods. The AST renamer
correctly renamed them and their `$this->` call sites, but the tests invoke them
BY NAME as a string:

    new ReflectionMethod(Service::class, 'normaliseCurrentStandaarden')

A string is invisible to the AST, and method names are not in the property map,
so nothing moved it. Fixed by diffing private-method declarations against the
baseline and updating every test that names an old one — 5 files.

That diff also exposed a HALF-TRANSLATION the guard let through:
`updateGeregistreerdDoor` had become `updateGeregistreerdBy` — `door` mapped to
`by` inside a compound whose other half stayed Dutch. `geregistreerd` was not in
the dictionary and carries none of the markers the residual check looks for
('ee' followed by n or s; this is 'eer'). Token added, guard widened for `-eerd`
endings, and the name is now `updateRegisteredBy`.

phpstan [OK], phpcs at its baseline of 4.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ c61ed8e

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-vue-demi
test-l10n
composer ✅ 130/130
npm ✅ 718/718
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-13 10:28 UTC

Download the full PDF report from the workflow artifacts.

… fixtures

RenameDutchCatalogColumnsTest exercises `renameIsSafe()` with LITERAL pairs —
`('naam', 'name', [...declared...])` — to prove the migration only moves data
when the register has actually moved. Those literals are FIXTURE DATA, not app
vocabulary.

The blanket rename turned every `'naam'` into `'name'`, collapsing each scenario
into `('name', 'name', ...)`. The test then asserted TRUE and FALSE about
identical inputs, which is why it failed — and had it not failed, it would have
been worse: a migration-safety test that no longer distinguishes the safe case
from the data-loss case, still reporting green.

Restored from development verbatim. Its private-method references were checked
against the AST renames and needed none.

This is the fixture form of the rule the rest of this work follows: a Dutch
string that is DATA — a CSV header, a stored enum value, a config key, a test
input proving behaviour about Dutch names — does not move with the vocabulary.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ 4833852

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-vue-demi
test-l10n
composer ✅ 130/130
npm ✅ 718/718
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-13 10:34 UTC

Download the full PDF report from the workflow artifacts.

ReviewService returned 'waardering must be between 1 and 10' — half Dutch, half
English, and the test asserted on the substring the rename had already moved.

A user-facing MESSAGE is app text, not a wire contract: it is displayed, not
parsed by anything. So it translates, unlike the CSV headers, ZGW resource keys
and stored enum values elsewhere in this branch that were deliberately held.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ 0ba9666

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-vue-demi
test-l10n
composer ✅ 130/130
npm ✅ 718/718
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-13 10:43 UTC

Download the full PDF report from the workflow artifacts.

The wire dimension list between the Vue store and FacetController is
['referentiecomponent', 'standaard', 'applicatieservice', 'domein']. My rename
translated exactly ONE of the four, leaving a half-Dutch vocabulary and breaking
the round-trip the store spec asserts.

These are not schema fields — facets.js documents that explicitly: 'the
module/dienst schema has no field named referentiecomponent/standaard/domein/
applicatieservice (the real fields are referentieComponenten, standaardVersies)'.
They are DERIVED dimension names on the wire, so they stay as a set or move as a
set, and moving them is a client+server+URL-key change that is not this branch's
job.

Restored across FacetController, services/facets.js, both specs and the _gf_
URL keys.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ 2ed3de0

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-vue-demi
test-l10n
composer ✅ 130/130
npm ✅ 718/718
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-13 10:59 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ 0a2bd29

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 ✅ 718/718
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-13 11:26 UTC

Download the full PDF report from the workflow artifacts.

Conduction Release Bot added 2 commits August 13, 2026 20:52
… wrong dimension

`referentieComponenten` had become `referenceComponenten` — `referentie`
translated, `Componenten` did not — and it SHIPPED into the register, so
FacetService read a field that no longer exists and array_column() got null.
`componenten` was not in the dictionary and carries none of the markers the
residual guard looks for. Token added, guard widened, and the field is now
`referenceComponents` across the register, the code and the migration.

The other failure was mine from the previous commit: restoring the wire
dimension name to `standaard` left FacetServiceTest still reading
`$result['standard']`. The dimension is the result KEY, so the test had to move
back with it.

This is the third half-compound this app produced (`kort`/`lang`, `versies`,
now `componenten`). The guard is a heuristic over Dutch orthography and these
words have none of it — each one is a dictionary gap, found by a failing test
rather than by the guard. Worth saying plainly: the guard reduces the class, it
does not close it.

phpstan [OK], phpcs at its baseline of 4.
Restoring the wire dimension to `standaard` in FacetService::DIMENSIONS left the
same key spelled `standard` in three other places: the result array the service
builds, its @return array{} shape, and three assertions in FacetServiceTest. The
dimension name IS the result key, so all four have to agree — the tests were
reading a key nothing produced.

Worth separating two things that look identical and are not:
  - the facet DIMENSION `standaard` is a wire name between the Vue store and
    FacetController, documented as NOT a schema field. It stays Dutch until the
    whole set of four moves together.
  - the register PROPERTY `standaard` IS a schema field and does move, which is
    why the migration still carries `'standaard' => 'standard'`.

Both are correct at the same time; conflating them is what produced this churn.

phpstan [OK].
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ d9c90d0

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 ✅ 718/718
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-13 19:06 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ 35a12fa

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 ✅ 718/718
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-13 19:20 UTC

Download the full PDF report from the workflow artifacts.

…names

Playwright failed where the merged-PR baseline passes it, so this was mine. The
specs create catalog objects through the API with bodies keyed by PROPERTY
names — `naam`, `beschrijving`, `waardering`, `versie` — which the registers no
longer declare, so the seeds failed and the assertions after them cascaded.

WHY THE PIPELINE MISSED THEM. Its rename rewrites QUOTED occurrences, which is
right for PHP and JSON. TypeScript object literals use UNQUOTED keys
(`waardering: 3`) and property access (`obj.naam`), and neither is quoted. 10
spec files updated across all three positions.

Pairs were rebuilt from THIS BRANCH'S migration map rather than the shared
.compose.json — that file is one path reused by every app's run, and reading it
after another app had overwritten it is exactly what made the decidesk Newman
check report a false clean.

DELIBERATELY LEFT: 8 remaining matches are not property keys — `/standaarden`
URL ROUTES (the manifest keeps them), a `standaard-detail` test label, local
variables and comments. Renaming a route would break navigation for a cosmetic
gain.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ 2eedbb6

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 ✅ 718/718
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-13 20:27 UTC

Download the full PDF report from the workflow artifacts.

Conduction Release Bot added 2 commits August 14, 2026 08:26
THE PIPELINE HAD A HOLE AND THIS IS WHAT FELL THROUGH IT.

Its property pass rewrites QUOTED occurrences, which is right for PHP and JSON.
Javascript does not quote object keys, and property access has no quotes at all:

    { waardering: 3 }     an object key POSTed to the API
    obj.naam              a read
    "naam"                the quoted form the old pass already handled

So Vue components kept posting and reading names the registers no longer
declare. This is a PRODUCTION defect, not a test artifact: on softwarecatalog
the review dialog never closed because the POST 400d silently, and the only
thing that noticed was an e2e assertion that a dialog should be hidden.

Fleet-wide it was 100 source files — procest 57, softwarecatalog 37, pipelinq 6.
decidesk had none, which is why it went green first time and hid the class.

Fixed by a new pass (rename-frontend.js) covering unquoted keys, property access
and quoted forms. Its pairs come from THIS repo diff of lib/Settings crossed
with the app own migration map — never from the shared .compose.json, which is
one path reused by every app run and was stale enough to make an earlier check
report a false clean.

Frontend files only; no PHP touched, so the PHP gates are unaffected. `node
--check` clean on every changed .js/.ts.
Two consequences of the frontend pass, both mechanical:

  - prettier: renaming changed line widths in two vitest specs. Reformatted
    with the app's own @nextcloud/prettier-config; `prettier --check` over
    CI's exact glob ("**/*.{js,ts,vue,css,scss}") is clean.
  - eslint object-shorthand: `waardering: rating` became `rating: rating`,
    which is the one ERROR among 164 warnings. Now `rating`.

node --check clean on every changed .js/.ts.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ ff4a353

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 ✅ 718/718
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-14 06:43 UTC

Download the full PDF report from the workflow artifacts.

The migration map legitimately contains `standaard => standard` — that is the
register PROPERTY. The facet DIMENSION happens to share the spelling, and the
frontend pass, which drives off that same map, renamed both.

So the dimension I had deliberately restored two commits ago was renamed again
by a later, more thorough pass. Both changes were individually right; together
they were wrong.

Restored in the four files that deal only in dimensions (services/facets.js,
store/modules/facets.js and their specs). Everything else keeps the property
rename.

VERIFIED locally with the app's OWN runner — CI uses jest, not the vitest config
in the repo, and vitest excludes src/** entirely, so `npx vitest` reported 'no
test files found' and would have looked like a pass:
  npx jest  ->  9 suites, 120 tests, all passing
  prettier --check over CI's exact glob  ->  clean
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ 68a0986

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 ✅ 718/718
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-14 07:01 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ afbc092

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 ✅ 718/718
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-14 07:25 UTC

Download the full PDF report from the workflow artifacts.

…ve touched

Playwright went from 12 failures to 5; these are the last two causes, and both
are the same class — a Dutch string that is DATA, not vocabulary.

  gemmaType === 'standaardversie'   a STORED value on GEMMA element objects.
                                    Renamed, the compliance matrix filter
                                    matched nothing and the view rendered empty.
  COLUMN_SOURCE.STANDAARDVERSIE     the enum compared against that value, so it
                                    has to hold the same string.
  DIMENSIONS ['... 'standard' ...]  the e2e spec's copy of FacetController's
                                    dimension list, which is Dutch on the wire.

That makes three separate places in this app where  appears: a
register PROPERTY that moves, a facet DIMENSION that does not, and a gemmaType
VALUE that does not. Same spelling, three different contracts.

VERIFIED with the app's own runner: jest 9 suites / 120 tests green, prettier
clean over CI's glob.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ a723039

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 ✅ 718/718
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-14 07:51 UTC

Download the full PDF report from the workflow artifacts.

Conduction Release Bot added 2 commits August 14, 2026 14:13
…lish, half Dutch

The rename this PR ships emitted a new name whenever SOME token was translatable
and let the rest through untouched, so it produced names like
`accountantsverklaringRequired` and `afstandToArbeidsmarkt` — English grammar
around a Dutch word. 22 of the names it introduced still carried one. Merging
that is worse than not renaming: the schema ends up in a third language nobody
can search for.

The number is measured with real wordlists — 274,937 English words and 164,174
Dutch, a token counting as Dutch when the Dutch list has it and the English list
does not. Two earlier instruments were wrong in opposite directions: matching
against the translation dictionary found almost nothing, because the names that
broke are built from words the dictionary never knew; matching against a
hand-written English vocabulary flagged ordinary words like `transaction` and
`income`. Control on the real one: `opbrengst`/`dienst`/`termijn` flag,
`transaction`/`settlement`/`allocation` pass.

CASE was wrong too. A dictionary value containing an underscore turned a
camelCase name into snake_case mid-schema. Style now comes from the schema name
that was REMOVED, never from the migration map's left-hand side — that side is a
COLUMN name and is always snake_case, so asking it whether the original was
snake_case answers yes for every multi-word name. My first attempt did exactly
that and rewrote `adviesAuthority` as `advice_authority`.

NO SECOND MIGRATION: the branch is unmerged, so these names have never existed
in a database. The correction rewrites them to the final name everywhere,
including the migration map's RIGHT-hand side, so the map points the original
Dutch column straight at the correct English one. Every rename is registered in
its snake spelling as well — the map is keyed on column names, and without that
a camelCase correction never reaches it and the repair step would migrate data
into a column the schema no longer declares.

VERIFIED: PHPUnit identical to a control run of the branch without these
corrections, phpstan [OK], psalm 0, eslint 0 errors, build OK, 0 surviving uses
of any renamed property in src/, every register file parses.

NOT IN SCOPE, measured rather than assumed: 62 property names that were ALREADY
Dutch on development and which the first pass never touched. A separate tranche,
not a defect in this PR.
The renames changed identifier lengths, so prettier's wrapping no longer matched
in 31 files and `Frontend Check (format)` went red. `development` is
fully prettier-clean, so this is drift the correction introduced, not
pre-existing.

Ran the project's own `format:fix`. `git diff -w` is attribute wrapping only and
no import line moved — worth checking, because a formatter that reorders
side-effect CSS imports changes behaviour while looking cosmetic. eslint 0
errors, build OK.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ 5fba027

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 ✅ 719/719
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-14 12:33 UTC

Download the full PDF report from the workflow artifacts.

…split in two

Three vitest tests went red and development is fully green, so this was mine.
Both causes are the same shape: the rename updated one half of a pair.

1. SHORTHAND OBJECT PROPERTY. complianceMatrix.js reads `data.standardGemma`
   (renamed, correct — that is the schema property) into a local variable that
   kept its old name, and pushes it with shorthand:

       const standaardGemma = … data.standardGemma …
       unresolved.push({ moduleUuid, standaardGemma, evidenced, record })

   A shorthand property has no `name:` for a key-rewrite to match, so the object
   went on emitting `standaardGemma` while every consumer had moved to
   `standardGemma`. The variable name IS the key here.

2. A COMPUTED AND ITS READERS. ComplianceMatrixView.vue declares
   `standaardversies()` and reads `this.standard_versions` — the rename rewrote
   the reads and not the declaration. That is not a test problem: the reads
   resolve to undefined and `.length` throws when the view renders. No unit test
   covers it; it was found only by chasing why one spec assertion failed.

`standaardversies` is a FUNCTION PARAMETER, not a schema property, so it is now
`standardVersions` in camelCase rather than the snake_case a column rename would
have produced — and every call site agrees, which they did not before: one spec
call passed `standard_versions` while three passed `standaardversies`.

VERIFIED: vitest 226/226, eslint 0 errors, build OK, format clean, PHPUnit
identical to control. `adminApi.spec.js` fails to collect with "window is not
defined" on this branch AND on development when run in isolation — pre-existing,
not touched here.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ 1e65ba8

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 ✅ 719/719
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-14 13:12 UTC

Download the full PDF report from the workflow artifacts.

…eaking the contract

`Frontend Tests (unit)` was red on CI and green locally, because this repo runs
BOTH runners: `test` is jest over `src/**.spec.js` and `test:unit` is vitest over
`tests/vitest`. My verification only ran vitest, so two failing jest specs were
invisible to me and obvious to CI.

The defect they caught: `FACET_DIMENSIONS` in src/services/facets.js is
`['referentiecomponent', 'standaard', 'applicatieservice', 'domein']`, and the
vocabulary pass translated exactly ONE of the four to `standard`. Those strings
are not ours to rename one at a time — `FacetController` and `FacetService` both
declare the same four as the query parameters and response keys of this app's own
facet endpoint. So the frontend began sending `standard[]` to a backend that only
reads `standaard[]`, and **facet filtering by standard silently returned
everything**: no 400, no console error, both sides behaving exactly as written.

Same shape as the DSO defect in openconnector — one member of a wire contract
translated, the rest untouched, which is hard to see in review precisely because
the surrounding lines still look right. Reverted, with a comment saying why the
four move together or not at all. Renaming all four plus the backend is a real
option, but it is an API change and belongs with the pre-existing tranche, not
smuggled into a vocabulary PR.

The two spec files are restored to development, since their sources are now
functionally identical to it.

Also in this commit, from the earlier round: a SHORTHAND object property
(`unresolved.push({ moduleUuid, standaardGemma, … })` — the variable name IS the
key, and a key-rewriter matching `name:` cannot see it) and a Vue computed whose
readers had been renamed without the declaration, which throws on `.length` at
render and no unit test covered.

VERIFIED: jest 120/120, vitest 226/226, eslint 0 errors, build OK, format clean.
`adminApi.spec.js` fails to collect with "window is not defined" here AND on
development in isolation — pre-existing.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ 6d7261f

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 ✅ 719/719
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-14 13:34 UTC

Download the full PDF report from the workflow artifacts.

…names

Two more places where the rename moved one half of a pair, both caught by CI's
Playwright job and neither visible to jest, vitest, eslint or the build.

1. gemma-faceted-search.spec.ts keeps its OWN `DIMENSIONS` list, a duplicate of
   the four the backend declares, and the pass had translated `standaard` there
   too. With the source reverted to match FacetController/FacetService, the spec
   was the only thing left asserting `standard`. Realigned, with the same comment
   the source now carries: the four move as a set or not at all.

2. crud-persistence.spec.ts POSTs a module version with SHORTHAND —
   `{ data: { versie, status } }` — so the local variable's name is the key. The
   rename updated the READ two lines below (`r.version === versie`, property
   access has a dot to match on) and could not see the write. The schema declares
   `version` now, and MagicMapper DISCARDS an undeclared property with a log line
   rather than a 4xx:

       [MagicMapper] Discarding 1 property the schema "Application version"
       does not declare: versie. They are NOT stored anywhere.

   So the create "succeeded", the row came back without a version, and only the
   later assertion noticed. Now written as `version: versie` explicitly, with a
   note about why shorthand is wrong here.

That is the third shorthand-property defect in this programme — after procest's
BAG/WOZ query parameters and this app's own `unresolved.push({ moduleUuid,
standaardGemma, … })`. A key-rewriter matches `name:`; shorthand has no colon.

VERIFIED: jest 120/120, vitest 226/226, eslint 0 errors, format clean.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/softwarecatalog @ c1b1120

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 ✅ 719/719
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright
Hydra gates

Quality workflow — 2026-08-14 13:55 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde
rubenvdlinde merged commit aab66d5 into development Aug 14, 2026
36 of 38 checks passed
@rubenvdlinde
rubenvdlinde deleted the feat/english-vocabulary-softwarecatalog branch August 14, 2026 13:56
rubenvdlinde added a commit that referenced this pull request Aug 16, 2026
…ovider property (#526)

gate-54 relation-dialect, check (d): three `x-relation-filter` tokens still
name `@object.aanbieder`, a property that no longer exists.

Commit aab66d5 ("translate Dutch vocabulary to English", #506, 2026-08-14)
renamed the property key `aanbieder` -> `provider` everywhere, including the
filter KEY side (`{ "aanbieder": ... }` -> `{ "provider": ... }`), but its
value-side rule never matched the compound token `"@object.aanbieder"`. So
these three findings are INTRODUCED, not legacy debt — they are two days old.

Effect of the defect: ADR-062 rule 6 drops an unresolved token rather than
filtering on nothing, so the three pickers (service.contactPerson,
service.modules, module.contactPerson) have been rendering UNSCOPED since the
rename — every contact person in the instance, not just the provider's.

This is NOT a data migration. `x-relation-filter` is picker-scoping metadata
naming a property of the same schema; no property and no stored value changes.
RenameDutchCatalogColumns already migrated the stored data (lib/Repair/
RenameDutchCatalogColumns.php:179 `'aanbieder' => 'provider'`).

Both sides of each token verified by hand (the gate only checks the value
side):
  service.contactPerson  {organization: @object.provider} -> contactPerson.organization OK, service.provider OK
  service.modules        {provider:     @object.provider} -> module.provider        OK, service.provider OK
  module.contactPerson   {organization: @object.provider} -> contactPerson.organization OK, module.provider  OK

gate-54, the gate's own vendored helper (check_relation_dialect.py, blob
3d4c81ca == ConductionNL/.github@main), over its own enumeration
(git ls-files lib/Settings, register*.json + register.d/*.json):
  BEFORE: 3 findings over 3 files
  AFTER:  0 findings over 3 files
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant