Skip to content

fix(migration): resolve the body slug via @self metadata, not a body field - #913

Merged
rubenvdlinde merged 1 commit into
developmentfrom
fix/resolve-body-slug-via-self-metadata
Aug 26, 2026
Merged

fix(migration): resolve the body slug via @self metadata, not a body field#913
rubenvdlinde merged 1 commit into
developmentfrom
fix/resolve-body-slug-via-self-metadata

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

The bug

MigrateLegacyTemplatesToDecisionTemplate resolved a governance body by filtering ['slug' => …]. A seeded slug: key is an import-time identifier that OpenRegister keeps as @self metadata — it is not a stored property, so that filter matches nothing.

The failure is silent: the migration finds no row, skips the template, and reports success.

Measured, not reasoned

On a live instance:

  • ['slug' => …] returned 0 rows
  • scanning all 60 governance bodies found no object carrying slug as a field at all
  • ['@self' => ['slug' => …]] returned exactly 1

Fix

Filter on ['@self' => ['slug' => $slug]].

This is the known defect class — a fake validates the query you wrote: a mocked result set would have confirmed the original filter happily, because the fixture puts slug wherever the test author expected it. Only a live query distinguishes the two.

Note

This commit predates the ADR-110 nav work and was sitting unpushed locally; pushing so it lands rather than being lost.

… resolved

#886 added a slug→UUID resolver for `urgencyPolicy.ratifyingBody` and I reported
it as fixing the last two template migrations. IT DID NOT. Re-running the step
on a live instance after the merge, both failures were still there:

  Failed to migrate process-template 8d3460b3-…: Property
    'urgencyPolicy.ratifyingBody' should match format 'uuid' but
    'gemeenteraad-amsterdam' does not.

The resolver filtered `['slug' => $slug]`. A seeded `slug:` key is an
IMPORT-TIME IDENTIFIER that OpenRegister keeps in `@self` metadata — it is not a
stored object property. Measured on the live instance:

  filters ['slug' => 'gemeenteraad-amsterdam']            -> 0 rows
  scan of all 60 governance bodies for a `slug` FIELD     -> none carry one
  filters ['@self' => ['slug' => 'gemeenteraad-amsterdam']] -> 1 row

So the lookup returned null every time, and my deliberate "leave the slug as is
rather than blank it" fallback then re-emitted the original error — which is why
the symptom was unchanged and looked like the fix simply had not deployed.

⚠️ WHY I SHIPPED IT ANYWAY. The 16 unit tests pass either way: the fake answers
whatever shape the query asks for, so a filter naming a field that does not
exist matches the fixture just as well as the right one. I verified
`anonymousFailures=0` — the IDENTITY half — and took the format half on trust
because the tests were green. A fake cannot tell you that you are querying a
field the real store does not have.

Live-verified after the change: the step now completes with NO failures of
either kind. All 14 legacy templates migrate.

16 tests green, phpcs 0 errors.
@rubenvdlinde
rubenvdlinde merged commit 6763389 into development Aug 26, 2026
169 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/decidiq @ d015f17

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-manifest
check-nav-ceiling
test-l10n
format
check-l10n-js
check-schema-l10n
composer ✅ 104/104
npm ✅ 555/555
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-26 23:34 UTC

Download the full PDF report from the workflow artifacts.

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.

2 participants