fix(setup): make the setup wizard, the sample-data step and the case-type menu reachable - #1401
Merged
rubenvdlinde merged 14 commits intoAug 28, 2026
Merged
Conversation
…type menu reachable
Four things this app declared, wired and shipped, which no user could reach.
1. THE ROW-ACTION MENU HAD 15 BLANK ROWS. `config.actions` carried entries
that CnRowActions cannot draw — a bare string ("edit") and a key-only
object ({"key": "edit"}) — which render as full-height, clickable, INERT
items above the real ones. Six pages were affected: CaseTypes, Partners,
WorkflowDefinitions, LhsMatrices, Parafeerroutes and WmsLayers. Neither
shape is how built-ins are enabled (the show*Action toggles do that, and
they default on), so all 15 were pure loss.
Also drops the six hand-rolled `view` actions and their
`showViewAction: false`. Each named a detail route that the built-in View
now resolves to by itself — verified route-by-route: all six resolve to
exactly the page they used to name.
2. THE CASE-TYPE INDEX OPENED AN EDIT MODAL over a record that has its own
detail page. That modal renders the schema's flat scalars only, so a case
type's statuses, results, roles and properties — separate related records
— were uneditable from the surface claiming to edit them. With
@conduction/nextcloud-vue's matching change, Edit now goes to
CaseTypeDetail, which grew its own Edit button.
3. THE SAMPLE-DATA STEP WAS UNREACHABLE. `/api/setup/status` answers
`completed: true` on a clean install (the required register step
auto-satisfies on app-enable) with `seed: {done: false}`. CnAppRoot read
`completed` as "nothing left to do" and never opened the wizard offering
the seed step — the app's only demo-data affordance. Fixed in the library;
the app side adds the first tests SetupController has ever had, including
one that reads the shipped manifest and fails if a declared step goes
unreported (an unreported step is invisible to the wizard however
unfinished it is).
4. A SEED RUN THAT CREATED NOTHING RECORDED ITSELF AS DONE.
`seedBezwaarBeroepData()` returns success with every counter at zero when
its payload is absent — which is its state, the case types having been
parked under `_caseTypes_disabled` in favour of a register.d fragment. So
one click reported "Seeded 0 case types, 0 status types, 0 role types (0
skipped)" as a success, marked the step complete, and the wizard never
offered it again. It now answers 422 and leaves the step outstanding.
Also:
- SURFACES THE DWANGSOM CALLBACK SIGNING SECRET. `status()` computed
`dwangsom_callback_secret_configured` for the
enforce-dwangsom-callback-signature spec and NOTHING in the frontend read
it — it was serialised and dropped on every request, so the incident it
exists to prevent was never being prevented. It is now also a reported
optional setup step, so the wizard asks for it; the legacy flag is kept for
API consumers and derived from the same value so the two cannot drift.
- THE WALKTHROUGH NOW SHOWS WHERE CASE TYPES AND FLOWS LIVE. Two view-only
stops, both `allowManualNext` with a route-match advance — they point at
the surfaces without requiring anyone to create a case type or a flow.
manifest.version 1.1.0 -> 1.2.0 so returning users get the new steps
(`sinceVersion` is compared against it).
- THE E2E NAV HELPER NOW DISMISSES THE SETUP WIZARD. It only started
appearing once the library learned to tell "reported not done" from "never
mentioned", so no spec in this suite had ever had to account for a
modal-mask that swallows every click on the app behind it.
KNOWN GAP, filed as ConductionNL/openregister#2935: a fresh install still has
zero demo CASES. dossiq declares 191 seed objects in its register config and
35 of them — 9 schemas, including all 10 demo cases — are never imported, with
no error and a success result. That is an OpenRegister import defect, measured
and reported separately.
Verified: 12 SetupController tests (5 fail against the pre-fix source);
2445 unit tests green; phpcs 0 errors (unchanged from the control), phpmd,
psalm and phpstan clean; Playwright e2e covers all four user-visible fixes.
…script tag
Two assertions that could not have passed, and whose failure looked like
missing code rather than a broken instrument.
- `meta[name=requesttoken]` does not exist on NC 34, so the CSRF header went
out empty and `/api/setup/status` answered 412 {"message":"CSRF check
failed"} — a refusal a caller checking only for a 2xx reads as data. The
token is on `OC.requestToken`, with head[data-requesttoken] as fallback.
- `/apps/dossiq/js/dossiq-main.js` answers 200 with the app's HTML shell, not
the bundle (the real path is /custom_apps/...). Resolving it from the page's
own <script src> instead of hardcoding it means the test reads the artefact
the browser actually loaded.
…way to author a CMMN plan Two findings, both measured rather than assumed. 1. THE APP HAS TWO SURFACES THAT CLAIM TO AUTHOR A CASE TYPE. The real one is in Admin Settings — AdminRoot -> CaseTypeAdmin -> CaseTypeList/CaseTypeDetail with eight tabs (Statuses, Results, Roles, Properties, Document types, Decision types, Sub-case types, Workflow). The in-app /settings/case-types pages are plain schema-driven pages over caseType's 32 scalar columns, with no composition at all — and until the accompanying fix, the index's row menu opened an edit MODAL over those scalars. The manifest's own note records how: page-topology-cleanup B1 correctly retired the in-app route that mounted AdminRoot through the in-app router (ADR-004), and the replacement rebuilt only the flat half. 2. NOTHING CAN AUTHOR A CMMN CASE PLAN. handlingModel accepts 'cmmn'; CaseModelEngine and CaseModelLoader implement it; the runtime routes exist; the caseModel schema is declared and tagged x-cmmn-equivalent: CasePlanModel. But zero files under src/ mention caseModel, the eight admin tabs do not include it, no manifest page binds to it, and routes.php has no CRUD for it. CaseModelLoader::getActiveModel() returns null when nothing is published, so choosing 'cmmn' today yields case types the engine has nothing to run — silently, null being a normal return. Includes the CMMN <-> ZGW ZTC mapping the fleet needs to keep straight: CMMN is the richer runtime model, ZGW the publication contract, so CMMN is the core and ZGW the projection — and a stage/milestone must be able to name the statusType it maps to, or the export gets maintained beside the model instead of derived from it.
rubenvdlinde
requested review from
Rem-Dam,
SudoThijn,
WilcoLouwerse,
bbrands02,
remko48 and
rjzondervan
as code owners
August 27, 2026 13:54
…tops added The l10n gate is doing exactly its job here: every string the wizard and the walkthrough put on screen is user-facing, and nine of them existed only as English literals in src/manifest.json. Dutch is written rather than copied — this app's audience reads it, and 'Zaaktypen' is the term the rest of nl.json already uses for case types (Flows stays 'Flows', which is also what the existing catalogue does). Also runs prettier over the new e2e spec, which the format gate caught.
…ugh already is
Making the wizard OPEN is the library fix; it also means its modal-mask
intercepts every click on the app behind it. Before that fix CnAppRoot could
not open the non-gating wizard at all, so no spec in this suite had ever had to
account for it — and navigation.spec.ts clicks sidebar links without dismissing
any overlay:
<div ... data-testid-modal="cn-wizard-dialog"> subtree intercepts pointer events
Seeding the dismissal marker into the persisted storageState fixes it for the
whole suite in one place, exactly as global-setup already does for the
walkthrough's cn-walkthrough-seen key. A range of setup.version values is
seeded rather than the current one, so a later bump does not silently re-arm
it. Dismissing it in the nav helper (the previous attempt) only covered specs
that route through navTo.
The spec that TESTS the wizard now clears those keys and reloads. Without that
it would assert against a wizard suppressed before it could open — a test that
cannot fail.
… translated label Two things the full suite surfaced. 1. l10n/*.json is the SOURCE; l10n/*.js is what the browser loads. Adding the nine strings to the JSON left en.js and nl.js stale, so they existed in the repo and reached no user — the same shape as the 2026-08-24 finding where nine apps shipped 8,137 translations no browser ever received. `check:l10n-js` catches it; this is `npm run l10n:build`. 2. The spec navigated with navTo(page, 'Case types'), which resolves a nav entry by its exact VISIBLE TEXT. On a Dutch-locale instance the sidebar reads 'Zaaktypen' and the helper fails by name — as pages.spec.ts did in this same run. A spec about case types should not also be asserting which language the instance happens to run in, so it resolves the entry by its /settings/case-types href instead, and fails by name if no link routes there at all.
…lves CnWalkthrough.resolveTarget() looks a nav-item target up as `[data-cn-route="<ref>"]`, and CnAppNav sets that attribute from `item.route`. The step was authored with the MENU id (FlowsMenu), which matches nothing, so it fell back to a centred anchorless coachmark instead of pointing at the entry. Easy to miss because every tour step in this fleet that works today targets an entry whose menu id happens to EQUAL its route (Cases, MyWork). FlowsMenu -> Flows is the first place they differ. Verified against the live DOM: [data-cn-route="Cases"] resolves, [data-cn-route="FlowsMenu"] does not.
Contributor
Quality Report — ConductionNL/dossiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ❌ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ⏭️ | ||||
| stylelint | ✅ | ||||
| build | ⏭️ | ||||
| check-manifest | ✅ | ||||
| check-vue3-compile | ✅ | ||||
| test-l10n | ❌ | ||||
| format | ❌ | ||||
| composer | ⏭️ | ✅ 106/106 | |||
| npm | ⏭️ | ✅ 552/552 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ❌ | ||||
| Newman | ❌ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-27 15:15 UTC
Download the full PDF report from the workflow artifacts.
gate-96 (manifest-copy-style) caught it: "Em-dashes and double-dashes are AI tells. Replace with a period, a comma, or a colon." The Flows stop's body ended "...read and edit them — nothing to build now."; it now ends with a full stop and a short sentence, which is what the rule asks for and reads no worse. The English string is the l10n KEY, so the catalogues are re-keyed in the same change and the browser .js rebuilt. Leaving the key behind would have made the string untranslated in every locale while the catalogue still claimed to cover it. The Dutch value drops its em-dash too, for the same reason the English one does. Verified per app with the script that app's own CI runs (test:l10n or check:l10n), plus check:l10n-js, plus schema validation of the manifest.
Contributor
Quality Report — ConductionNL/dossiq @
|
| 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 | ✅ | ||||
| composer | ✅ | ✅ 106/106 | |||
| npm | ✅ | ✅ 552/552 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-27 18:42 UTC
Download the full PDF report from the workflow artifacts.
Contributor
Quality Report — ConductionNL/dossiq @
|
| 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 | ✅ | ||||
| composer | ✅ | ✅ 106/106 | |||
| npm | ✅ | ✅ 552/552 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ❌ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-27 20:34 UTC
Download the full PDF report from the workflow artifacts.
The three walkthrough tests already here prove the steps are declared and
reach the built bundle. None of them proves a user ever sees one.
CnWalkthrough.armStep():
const el = this.resolveTarget(this.step)
if (!el) { if (this.step.optional) { this.wt.skip(); return } }
An optional step whose target is absent is skipped outright — no console
error, no stall, nothing on screen. `optional: true` is what stops these two
stops forcing authorship, so the friendly authoring choice is also the one
that fails silently.
The step counter cannot catch it either: skip() advances past the step and
the declared total stays 7, so `/ 7` reads the same whether both stops
render or neither does. That is a test that cannot fail.
So assert what resolveTarget() actually queries: [data-cn-route="<route>"].
Both stops target nav items in the SETTINGS section, and CnAppNav emitted
that attribute on its main/child/footer loops but not the settings one until
nextcloud-vue#811. That gap is how both steps could ship and reach nobody.
Red until package-lock.json pins a library containing #811, which is the
point of the test.
Contributor
Quality Report — ConductionNL/dossiq @
|
| 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 | ✅ | ||||
| composer | ✅ | ✅ 106/106 | |||
| npm | ✅ | ✅ 552/552 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-27 22:28 UTC
Download the full PDF report from the workflow artifacts.
gate-100 landed on .github main last night and is diff-scoped on
src/manifest.json, so this PR's walkthrough edit pulls the setup
declaration into scope. dossiq opened with `welcome`, which is what the
gate exists to stop: a welcome screen tells you what the app is, the
demo-data offer lets you SEE it, and seeing it is the only question a
first reader actually has.
WHAT MOVED. The step that loads the Bezwaar & Beroep sample data is
promoted from `seed` to `demo-data` and put first, with the greeting
folded into its copy rather than kept as a separate screen. ADR-111 is
explicit that the first step can still say hello.
THE ORDER CHANGE IS NOT FREE. `seed` used to run after `register-check`,
so it could assume the register and schemas existed. First, it cannot:
on a clean install they do not, and seeding into a register that is not
there yet touches zero rows — which the existing guard correctly refuses
to record as done, so the affordance would look broken rather than fail
loudly. runAction() now calls loadConfiguration() before seeding. It is
idempotent, so a repeat run costs nothing.
THE ACTION ID IS A PUBLIC SURFACE. `/api/setup/action/{actionId}` is a
POST route, not an internal label. A wizard someone left half-finished
keeps posting `seed`, so `seed` stays accepted as an alias; without it
the rename becomes a silent 400 that presents as "the button does
nothing". testTheOldSeedActionIdStillRunsTheStep pins that.
Verified locally against the schema CI actually uses: the app vendors
2.25.0 while hydra-gates vendors 2.26.0, and only the latter decides the
gate. gate-22 PASS (0 errors) under 2.26.0, gate-96 rc=0, gate-100 rc=0,
phpunit 13/13, phpcs rc=0, test:l10n and check:l10n-js clean.
…ndex-actions-and-setup-wizard
…h anchor The `see-case-types` and `see-flows` stops target nav items in the SETTINGS section. CnAppNav emitted `data-cn-route` on its main, child and footer loops but not the settings one, so both stops resolved nothing — and CnWalkthrough.armStep() SKIPS an optional step whose target is absent, silently. Both stops would have shipped and reached nobody. The caret range is not what decides this. `npm ci` installs from package-lock.json, so the fix only arrives when the LOCK moves. It was pinned at 2.20.0, which does not contain #811. 2.21.0 verified by unpacking the published tarball rather than trusting the version string: data-cn-route appears 4 times, one of them at line 277 inside the `v-for="item in settingsItems"` template at 262. This is what turns the anchor test added in cbd1207 from red to green.
Contributor
Quality Report — ConductionNL/dossiq @
|
| 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 | ✅ | ||||
| composer | ✅ | ✅ 106/106 | |||
| npm | ✅ | ✅ 552/552 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-28 06:25 UTC
Download the full PDF report from the workflow artifacts.
Two things this branch changed, both of which the suite still asserted the old way. 1. The setup step id moved from `seed` to `demo-data` (ADR-111 rule 4), so `status.steps.seed` is now undefined and `after.steps.seed.done` threw rather than failing with a readable message. Updated to `steps['demo-data']`, and the POST now targets the canonical action id. The `seed` alias stays covered by SetupControllerStatusTest. 2. Edit on an index row navigates to the case's detail page instead of opening a modal over the list (@conduction/nextcloud-vue 2.21.0). The dialog is one click further on, behind the detail page's Edit button. What each test checks is unchanged: the seeder still must not record a zero-row run as done, and the title edit still must persist.
dossiq#1408 landed the generated demo dataset while this branch was open. Both changed `setup.steps`, so they conflicted. Development's shape wins and my half is withdrawn, because #1408 solves it properly: - It adds `demo-data` as its OWN step with its own action (`install-demo-data`) and its own service, and keeps `seed` — the bezwaar/beroep seeder — as a separate step. My change had renamed `seed` to `demo-data` to satisfy gate-100, which would have collapsed two different datasets into one id. - So the seed→demo-data rename, its `seed` alias, and the loadConfiguration() call I added are all reverted. `seed` runs after `register-check` again, so it can assume the register exists. - `dwangsom-secret` is re-added on top: it is this branch's own step and was not in #1408. - `seed` is restored to the step list. The merge had silently dropped it, because my side deleted it (as a rename) and nothing conflicted on the deletion. The action-menu hunks also go development's way. My side REMOVED the label-less action entries; development instead gave them proper labels and a route to the detail page. Both close the invisible-row defect, and development's manifest now validates clean against schema 2.26.0 — 0 non-object actions, 0 missing labels — so the strip is no longer needed. Test fallout, both real: - SetupController gained a 4th constructor argument (DemoDataService), so the test builder had to supply it or every test died in the constructor. - The l10n catalogues came from development and lacked this branch's nine walkthrough and dwangsom strings; re-derived and translated. Verified: gate-22 PASS under CI's 2.26.0 schema, gate-96 rc=0, gate-100 rc=0, test:l10n and check:l10n-js rc=0, phpcs rc=0, phpunit 2469 tests / 10931 assertions / 0 failures.
Contributor
Quality Report — ConductionNL/dossiq @
|
| 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 | ✅ | ||||
| composer | ✅ | ✅ 106/106 | |||
| npm | ✅ | ✅ 552/552 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ✅ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-28 09:39 UTC
Download the full PDF report from the workflow artifacts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Companion to ConductionNL/nextcloud-vue#806. Four things this app declared, wired and shipped, which no user could reach — all found on a clean install of
localhost:8080/apps/dossiq.1. The row-action menu had 15 blank rows
config.actionscarried entriesCnRowActionscannot draw — a bare string ("edit") and a key-only object ({"key": "edit"}) — which render as full-height, clickable, inert items above the real ones. Six pages:CaseTypes,Partners,WorkflowDefinitions,LhsMatrices,Parafeerroutes,WmsLayers.Neither shape is how built-ins are enabled (the
show*Actiontoggles do that, and they default on), so all 15 were pure loss — the author got a blank row instead of the action they asked for, and the built-in they meant was already there.Also drops the six hand-rolled
viewactions and theirshowViewAction: false. Each named a detail route the built-in View now resolves to by itself — checked route by route, all six resolve to exactly the page they used to name.2. The case-type index opened an edit modal
…over a record that has its own detail page. That modal renders
caseType's flat scalars only, so a case type's statuses, results, roles and properties — separate related records — were uneditable from the surface claiming to edit them. With the library change, Edit now goes toCaseTypeDetail, which grew its own Edit button.3. The sample-data step was unreachable
/api/setup/statusanswerscompleted: trueon a clean install (the required register step auto-satisfies on app-enable) withseed: {done: false}.CnAppRootreadcompletedas "nothing left to do" and never opened the wizard offering the seed step — the app's only demo-data affordance. Fixed in the library.This side adds the first tests
SetupControllerhas ever had (12), including one that reads the shipped manifest and fails if a declared step goes unreported — an unreported step is invisible to the wizard however unfinished it is.4. A seed run that created nothing recorded itself as done
seedBezwaarBeroepData()returns success with every counter at zero when its payload is absent — which is its state, the case types having been parked under_caseTypes_disabledin favour of aregister.dfragment. So one click reported "Seeded 0 case types, 0 status types, 0 role types (0 skipped)" as a success, marked the step complete, and the wizard never offered it again. It now answers 422 and leaves the step outstanding.Also
The dwangsom callback signing secret is now asked for.
status()computeddwangsom_callback_secret_configuredfor theenforce-dwangsom-callback-signaturespec and nothing in the frontend read it — serialised and dropped on every request, so the incident it exists to prevent was never being prevented. It is now a reported optional setup step; the legacy flag stays for API consumers and is derived from the same value so the two cannot drift.The walkthrough shows where case types and flows live. Two view-only stops, both
allowManualNextwith aroute-matchadvance — they point at the surfaces without requiring anyone to create a case type or a flow.manifest.version1.1.0 → 1.2.0 so returning users get them (sinceVersionis compared against it).The e2e nav helper now dismisses the setup wizard. It only started appearing once the library learned to tell "reported not done" from "never mentioned", so no spec in this suite had ever had to account for a modal-mask that swallows every click on the app behind it.
Known gap — filed separately
A fresh install still has zero demo cases. dossiq declares 191 seed objects in its register config and 35 of them — 9 schemas, including all 10 demo
caseobjects — are never imported, with no error and a success result. That is an OpenRegister import defect: ConductionNL/openregister#2935.Also proposed (docs only)
openspec/changes/case-type-one-authoring-surface/records two measured findings behind the modal complaint:AdminRoot → CaseTypeAdmin → CaseTypeList/CaseTypeDetail, eight tabs). The in-app pages are a flat duplicate — a consequence ofpage-topology-cleanupB1 correctly retiring the in-app AdminRoot route per ADR-004, with the replacement rebuilding only the flat half.handlingModelacceptscmmn,CaseModelEngine/CaseModelLoaderimplement it, the runtime routes exist, thecaseModelschema is taggedx-cmmn-equivalent: CasePlanModel— but zero files undersrc/mentioncaseModel, no admin tab covers it, no manifest page binds to it, and there is no CRUD route.getActiveModel()returnsnullwhen nothing is published, so choosingcmmntoday yields case types the engine has nothing to run.It includes the CMMN ↔ ZGW ZTC mapping table, on the framing that CMMN is the core runtime model and ZGW the publication projection.
Verification
lint,phpcs(0 errors, warning count identical to the control),phpmd,psalmandphpstanall clean.Depends on
nextcloud-vue#806 (merged to
development) and its beta release. Items 1, 3, 4 and the walkthrough work on the currently-pinned 2.19.0; item 2's edit-routing needs the new library, so this merges together with the version bump.