feat(cases): the New case form answers what the case type already knows - #1710
Merged
Conversation
Six things a case handler was doing by hand, or being asked that they should never have been asked. The case type already carries `initialStatus`, `defaultAssignee` and its own title, so `case.caseType` now declares `x-openregister-prefill` mapping those onto the case's status, assignee and title. Only an EMPTY field is filled, so a title someone typed survives both the first choice of case type and every later one. `status` is prefilled without being offered as a field. Someone filing a case does not choose the status it starts in, but the case still has to be stored in it. `decisions` is hidden. They are linked decidiq objects, made and signed in decidiq and reached through the case detail page; a raw reference list on a create or edit form could only ever be wrong. Checked first that no widget, table or spec reads the property, because `visible: false` hides a property from all three surfaces and not just the form. The New case dialog is now wide and two-column, which halves the scrolling, and the two Title Case labels among the nine create fields read as sentence case: "Start date" and "Planned end date". Case schema 1.11.0 to 1.12.0. Needs nc-vue 2.32.0 for the prefill and the columns prop; the dependency bump follows once it publishes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A case description rendered as a single-line text input, which is the difference between a form someone can use and one they fight. `format: textarea` is what the field engine reads to widen it, and in the new two-column layout a textarea spans both columns, so the description gets the full width of the dialog rather than half of it. Checked the other two specs that mention a description first: one uses a placeholder on a different modal, the other sets the field through the API. Neither goes through this widget. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… schema OpenRegister classifies adding `format` to a property as a tightened constraint, so putting `format: textarea` on `case.description` made the register import a BREAKING schema change needing an explicit acknowledgement on every upgrade. Measured, not guessed: the API refused the update with `constraint_tightened` naming exactly that property. Paying that for a presentation hint is the wrong trade. Which widget a field renders as is a decision belonging to the surface, not to the data contract, and the manifest already carries `fieldOverrides` for exactly this. The description still gets its textarea, and still spans both columns, without the case schema claiming a constraint it does not mean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Verified against the published tarball rather than the version number: 2.32.0 ships dist/esm/utils/dynamicProperties.js carrying x-openregister-prefill, and manifest schema 2.29.0 with the `size` and `columns` keys the New case action declares. Exactly one dependency moves in the lockfile. Production build clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
rubenvdlinde
requested review from
Rem-Dam,
SudoThijn,
WilcoLouwerse,
bbrands02,
remko48 and
rjzondervan
as code owners
September 3, 2026 07:06
…eate form Keeping `parentCase` off the New case form is right: a case is not filed as somebody's sub-case, it becomes one later. But the case detail page's `case-core` widget carries an explicit `include` allowlist, and `parentCase` was not in it. So excluding it from the create form left it editable NOWHERE. This is the same trap as a `visible: false`, wearing different clothes: the property is fine, `visible` is true, and an allowlist somewhere else decides it never renders. Checking the create form told me nothing about it, which is why the check has to be "which surfaces show this" and not "is it hidden". REQ-FCF-007 now states the create/edit split, and an e2e test asserts BOTH halves: absent when filing, present on the case. The second half is the one that matters, because the first half passed all along. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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 | ✅ | ✅ 540/540 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ❌ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ deferred — runs on the promotion into beta/main, not on a pull request into development | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-09-03 07:10 UTC
Download the full PDF report from the workflow artifacts.
…ard load A hard load of `/apps/dossiq/cases/<id>` answers 200 and is rewritten client-side to the dashboard by the SPA catch-all, which case-flow-human-steps.spec.ts already documents. The parent case assertion would then have run against the dashboard and failed naming the field, sending a reader after the manifest instead of the URL. Uses the `/index.php` form the other specs use, and asserts the URL stayed on the case, so a future regression in the router base fails as a navigation problem rather than as a missing field. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
Quality Report — ConductionNL/dossiq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ⏭️ | ||||
| phpcs | ⏭️ | ||||
| phpmd | ⏭️ | ||||
| psalm | ⏭️ | ||||
| phpstan | ⏭️ | ||||
| phpmetrics | ⏭️ | ||||
| eslint | ⏭️ | ||||
| stylelint | ⏭️ | ||||
| build | ⏭️ | ||||
| check-l10n-js | ❌ | ||||
| composer | ⏭️ | ⏭️ | |||
| npm | ⏭️ | ⏭️ | |||
| app:check-code | ⏭️ | ||||
| info.xml | ⏭️ | ||||
| REUSE | ⏭️ | ||||
| PHPUnit | ❌ | ||||
| Newman | ❌ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-09-03 07:11 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 | ✅ | ✅ 540/540 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ deferred — runs on the promotion into beta/main, not on a pull request into development | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-09-03 07:15 UTC
Download the full PDF report from the workflow artifacts.
`Frontend Check (format)` runs prettier over the tree, and my added locator chains were over the print width. The Quality Report failure alongside it was not independent: its only failing step is "Gate — fail when any upstream job failed". Verified after reformatting that eslint is still clean AND that the file still collects 11 tests. Prettier and eslint both pass on a spec file that collects ZERO tests, so the listing is the check that matters here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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 | ✅ | ✅ 540/540 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ deferred — runs on the promotion into beta/main, not on a pull request into development | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-09-03 07:23 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.
Follow-up to #1653, from testing the real form on a running instance.
What was wrong
Six things a case handler was doing by hand, or being asked that they should never have been asked.
The case type already knows the answers. It carries
initialStatus,defaultAssigneeand its own title, and the form had no way to ask it.case.caseTypenow declaresx-openregister-prefillmapping those onto the case's status, assignee and title. Only an EMPTY field is filled, so a title someone typed survives both the first choice of case type and every later one.Status was being asked for. Someone filing a case does not choose the status it starts in, but the case still has to be stored in it. It is now prefilled without being offered as a field.
Decisions were on the form. They are linked decidiq objects, made and signed in decidiq and reached through the case detail page's Besluitvorming widget, so a raw reference list on a create or edit form could only ever be wrong. Now
visible: false.The dialog was a single narrow column of nine questions. Now wide and two-column, with the description spanning both.
Two labels were Title Case, which the house style bans: "Start Date" and "Planned End Date" now read as sentence case.
A case description was a single-line input. It is prose; it gets a textarea.
Two things worth a reviewer's attention
Hiding
decisionswas checked before it was done.visible: falsehides a property from the form, the widget AND the table, not just the form. I confirmed no widget, table, or spec readscase.decisions: the Besluitvorming widget istype: integrationand fetches from decidiq rather than rendering the property.The description textarea is declared in the manifest, not the schema.
format: textareaon the property made OpenRegister classify the register import as a BREAKING change (constraint_tightened), which the API refused outright. Measured, not guessed. Paying a breaking acknowledgement on every upgrade for a presentation hint is the wrong trade, so it moved tofieldOverrideswhere presentation belongs.Verification
size,columnsandfieldOverrideskeysgate-19 reports EMPTY SCOPE (exit 3) for this diff, exactly as it did for #1653: these
@e2eanchors point intoopenspec/changes/, and the gate only inspectsopenspec/specs/. I verified every anchor resolves to a real heading by slugifying the spec myself. It is not a gate pass and I am not claiming one.e2e is skipped on PRs into
developmentby design, so the push run after merge is the authoritative gate.🤖 Generated with Claude Code