Skip to content

Besluitvorming becomes an on-request case definition package (ADR-118, R1) - #3725

Merged
rubenvdlinde merged 27 commits into
developmentfrom
refactor/r1-package-besluitvorming
Oct 12, 2026
Merged

rubenvdlinde merged 27 commits into
developmentfrom
refactor/r1-package-besluitvorming

Conversation

@rubenvdlinde

@rubenvdlinde rubenvdlinde commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Status, 12 October

The second of a stack of three: #3669, #3725, #3768. They land together by #3768's head. See #3768 for the checks on the stack.

  • Holds Bezwaar and beroep become a case definition package (ADR-118, R1) #3669 and development with merge train 3 (train: land 18 ready PRs (12 Oct, c) #3809).
  • Development renamed the mandaat guard on the old mandaatbesluit template. That template stays deleted, and the package flow carries the new guard: delegatedAuthorityGuard with actField: mandaatCategorie.
  • The three case types' statuses name the roles the case flow moves by.
  • scripts/packages/package-to-newman.py now writes what the vth collection had by hand: for a package with a draft flow, each flow with its route and lifecycle and the flow a new case follows; a case type's list layout and default flow; each seed row.
  • Gate 119: .procedure-code-baseline.json is 198 on this head. .debt-baseline.json: psalm.inlineSuppressions 266 to 265. catch-return-null ceiling 261.

Where a line below disagrees with this section, this section is the current one.

What

The three deprecated besluitvorming bundles (college-besluit, raadsbesluit, mandaatbesluit) become the case definition package besluitvorming, marked install: on-request (hydra ADR-118, decision 190). This is refactor lane R1. It is stacked on #3669, which is stacked on #3654: merge those two first.

  • Package. lib/Settings/packages/besluitvorming/ holds 3 case types, 26 statuses, 15 roles, 17 property definitions, 8 document types, 9 result types and 3 published flows. Every id is fixed. scripts/packages/seed-to-package.py converted them once. The converter now also carries property definitions, document types and result types, resolves initialStatusName to initialStatus, reads one case type per file from several sources, and gives a case type without an id a UUIDv5 of its identifier. Regenerating bezwaar-beroep with the extended converter gives the same flows and case types as before.
  • Generic package API. GET /api/packages lists what is shipped. POST /api/packages/{id}/install installs one package, admin only: 200 when installed or current, 422 when refused (with the installer's reason), 500 when a write failed and was rolled back. It replaces POST /api/besluitvorming/templates/{slug}/activate, which no frontend called, and it works for every on-request package.
  • Live instances. SeedBesluitvormingTemplates ran on every install, so these case types exist under random ids on most instances. The installer adopts them by identifier (Case definition package installer: install procedures from lib/Settings/packages (C19) #3654, REQ-CT-51), so nothing is duplicated. The journey finds the case types by identifier for the same reason.
  • Deleted: BesluitvormingTemplateService, Besluitvorming/TemplateBundleSeeder, Besluitvorming/WorkflowReferenceResolver, SeedBesluitvormingTemplates (both repair blocks), BesluitvormingController and its route, the three bvw-*.json bundles, BesluitvormingTemplateServiceTest and BvwTemplateConformanceTest. The catch-return-null ceiling goes from 256 to 255.
  • Tests: a Newman collection tests/integration/packages/besluitvorming.postman_collection.json (37 reads, generated by the new scripts/packages/package-to-newman.py), a Playwright journey tests/e2e/packages/besluitvorming.spec.ts, and PackageControllerTest for the API. The category sweep now walks every package.
  • Spec: OpenSpec change besluitvorming-package (REQ-BVW-001 modified, REQ-CT-52 added).

Verified locally

  • PackageControllerTest (4), tests/Unit/Repair (399), tests/Unit/Architecture (99), WorkflowGuardConformanceTest (10), SeedPayloadSchemaConformanceTest, SeededCaseTypeCategoriesTest: all exit 0.
  • Every shipped package validates with the real PackageValidator.
  • phpcs, phpmd, phpstan and psalm on the changed lib files: exit 0.
  • COMPOSER_PROCESS_TIMEOUT=0 composer check:strict once, through the slot, on c619407 (r1-logs/bvw-strict.log): lint, refusal-grounds snapshot, phpcs (warnings only), phpmd, psalm and phpstan passed. The full PHPUnit suite ran 7,299 tests with 1 failure, and it was mine: ShippedActionVocabularyTest found no retired-type actions after the bundles moved, because it did not read flows stored as JSON strings. The sweep now reads inside them and covers the packages. That file exits 0 on e268fcc.
  • Not run locally: the Newman read-back and the Playwright journey. No instance has the installer, and the browser service is down. CI runs both. The PR stays draft until the journey is green (decision 185).

Assumptions

  • Flows ship published (lifecycleStatus: published), as bezwaar-beroep does. The old seeder left them unpublished, and cases only run on published flows.
  • New instances no longer get these case types on install. That is the meaning of on-request.

The bezwaar and beroep case types ship as lib/Settings/packages/bezwaar-beroep/
(install: on-request), written by the package installer. The setup action
`seed` installs it; installed or already current records setup_seed_done, a
refusal or failed write answers 422 with the installer's message.

Converted once, offline, by scripts/packages/seed-to-package.py: status names
resolved into fixed UUIDs, a `*` source status (honoured by no reader) expanded
into one transition per open status, flows published. The nine fields the
flows guard on are declared as property definitions, so every guarded
transition can be taken; the guard sweep and the payload sweep now walk every
package.

Deleted: SeedDataService, SeedSummary, SeedBezwaarBeroepData,
SeedBezwaarBeroepCommand (occ dossiq:bezwaar:seed), SeedBezwaarWorkflowDefinition,
bezwaar_seed_data.json and their unit tests. Newman collection and Playwright
journey added (decision 185).
…-bezwaar-beroep

# Conflicts:
#	tests/Unit/Architecture/catch-return-null.allowlist.json
…, R1)

The three deprecated bvw bundles ship as lib/Settings/packages/besluitvorming,
install on-request (decision 190), converted once with fixed ids and
published flows. A generic package API (GET /api/packages, POST
/api/packages/{id}/install) replaces the besluitvorming activate route and
serves every on-request package. Instances where the old seeder ran get
their case types adopted by identifier, not duplicated.

Deleted: BesluitvormingTemplateService, Besluitvorming/TemplateBundleSeeder,
Besluitvorming/WorkflowReferenceResolver, SeedBesluitvormingTemplates,
BesluitvormingController and route, the bvw-*.json bundles and their unit
tests. Newman collection and Playwright journey added; package-to-newman.py
writes a package's read-back collection.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/dossiq @ a775e2b

Check PHP Vue Security License Tests
lint ✅
phpcs ✅
phpmd ✅
psalm ✅
phpstan ✅
phpmetrics ✅
eslint ❌
stylelint ✅
build ✅
check-manifest ✅
check-vue3-compile ✅
test-l10n ✅
format ❌
check-schema-l10n ✅
check-l10n-js ✅
check-debt-ratchet ❌
check-types-e2e ✅
composer ✅ ✅ 109/109
npm ✅ ✅ 659/659
app:check-code ⏭️
info.xml ✅
REUSE ❌
lockfile sync ✅
PHPUnit 🚨 NO VERDICT — enabled but never ran
Newman ⏭️
Playwright ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development.
Hydra gates ⏭️

Quality workflow — 2026-10-11 08:10 UTC

Download the full PDF report from the workflow artifacts.

…ckage-bezwaar-beroep

# Conflicts:
#	appinfo/info.xml
#	lib/Repair/SeedBezwaarWorkflowDefinition.php
#	tests/Unit/Architecture/catch-return-null.allowlist.json
…ckage-besluitvorming

# Conflicts:
#	tests/Unit/Architecture/catch-return-null.allowlist.json
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/dossiq @ e56e8ea

Check PHP Vue Security License Tests
lint ✅
phpcs ✅
phpmd ✅
psalm ✅
phpstan ✅
phpmetrics ✅
eslint ❌
stylelint ✅
build ✅
check-manifest ✅
check-vue3-compile ✅
test-l10n ✅
format ❌
check-schema-l10n ✅
check-l10n-js ✅
check-debt-ratchet ❌
check-types-e2e ✅
composer ✅ ✅ 109/109
npm ✅ ✅ 659/659
app:check-code ⏭️
info.xml ✅
REUSE ❌
lockfile sync ✅
PHPUnit 🚨 NO VERDICT — enabled but never ran
Newman ⏭️
Playwright ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development.
Hydra gates ⏭️

Quality workflow — 2026-10-12 07:54 UTC

Download the full PDF report from the workflow artifacts.

…s as OpenRegister answers them

CI's packages job: OpenRegister answers the JSON text of a flow's
transitions as a list, and the collection parsed it as text. It takes
either now. The journey imports its type on its own line and is
formatted, which eslint and prettier asked for.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/dossiq @ cabe480

Check PHP Vue Security License Tests
lint ✅
phpcs ✅
phpmd ✅
psalm ✅
phpstan ✅
phpmetrics ✅
eslint ✅
stylelint ✅
build ✅
check-manifest ✅
check-vue3-compile ✅
test-l10n ✅
format ❌
check-schema-l10n ✅
check-l10n-js ✅
check-debt-ratchet ❌
check-types-e2e ✅
composer ✅ ✅ 109/109
npm ✅ ✅ 659/659
app:check-code ⏭️
info.xml ✅
REUSE ❌
lockfile sync ✅
PHPUnit 🚨 NO VERDICT — enabled but never ran
Newman ⏭️
Playwright ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development.
Hydra gates ⏭️

Quality workflow — 2026-10-12 08:22 UTC

Download the full PDF report from the workflow artifacts.

…ckage-bezwaar-beroep

Development now seeds the Bezwaar case type with the Woo case type
(register.d/84) and read the old bezwaar seed in a test. The seed stays
deleted. The package names Bezwaar's statuses by the uuids the register seeds,
so installing it completes the seeded case type; the test that read the parked
seed now checks that. catch-return-null ceiling 262 (development's 263 minus
the deleted SeedDataService site).
…ckage-besluitvorming

Development renamed the mandaat guard on the old mandaatbesluit template; the
template stays deleted and the package flow carries the new guard
(delegatedAuthorityGuard with actField mandaatCategorie). catch-return-null
ceiling 261.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/dossiq @ cacfa62

Check PHP Vue Security License Tests
lint ✅
phpcs ✅
phpmd ✅
psalm ✅
phpstan ✅
phpmetrics ✅
eslint ✅
stylelint ✅
build ✅
check-manifest ✅
check-vue3-compile ✅
test-l10n ✅
format ✅
check-schema-l10n ✅
check-l10n-js ✅
check-debt-ratchet ❌
check-types-e2e ✅
composer ✅ ✅ 109/109
npm ✅ ✅ 659/659
app:check-code ⏭️
info.xml ✅
REUSE ❌
lockfile sync ✅
PHPUnit 🚨 NO VERDICT — enabled but never ran
Newman ⏭️
Playwright ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development.
Hydra gates ⏭️

Quality workflow — 2026-10-12 10:39 UTC

Download the full PDF report from the workflow artifacts.

…ow moves by; the read-back reads the version record

The shipped case flow moves a case by status role (intake, in-progress, closed).
The Bezwaar and Beroep statuses had none, in the package and in the register
fragment that seeds Bezwaar, so the flow would stop at its first step on a case
of either type. Both now name the three.

On a clean instance the register seeds the Bezwaar case type before the package
installs, so the package finds it present and writes no ledger row for it. The
collection now reads the package's version record, and the ledger row of the
Beroep case type, which the package does write.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/dossiq @ d1f98e6

Check PHP Vue Security License Tests
lint ✅
phpcs ✅
phpmd ✅
psalm ✅
phpstan ✅
phpmetrics ✅
eslint ✅
stylelint ✅
build ✅
check-manifest ✅
check-vue3-compile ✅
test-l10n ✅
format ✅
check-schema-l10n ✅
check-l10n-js ✅
check-debt-ratchet ❌
check-types-e2e ✅
composer ✅ ✅ 109/109
npm ✅ ✅ 659/659
app:check-code ⏭️
info.xml ✅
REUSE ❌
lockfile sync ✅
PHPUnit 🚨 NO VERDICT — enabled but never ran
Newman ⏭️
Playwright ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it locally with npx playwright test, or from the Actions tab on a branch with no open pull request into development.
Hydra gates ⏭️

Quality workflow — 2026-10-12 14:04 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde
rubenvdlinde marked this pull request as ready for review October 12, 2026 14:08
@rubenvdlinde
rubenvdlinde merged commit 8aefff4 into development Oct 12, 2026
49 of 51 checks passed
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