Repository navigation
refactor(ztc): the publish routes get their own controller, two helpers leave ZtcController - #3922
Merged
Merged
Conversation
Decision 224. The case type delete check, drc-004 and drc-007 let a request through when their lookup failed. They now refuse with 503 check-not-completed, name the rule, and log the rule and the object. drc-003 gives the same answer instead of claiming a duplicate, and the controller's relation check before a document delete (drc-008a) follows. Two sites leave the catch-return-null list, ceiling 263 to 261.
… facades method-decomposition slice 8h. The engine couples to 18 classes against 13 and takes 14 constructor arguments. The design gives it one facade over what a case declares and one over what a move writes; the engine keeps the order of the checks.
Characterisation before the StatusTransitionService split (method-decomposition slice 8h), green on the single class: the order of the five refusals, the conflict check, the one save of a closing move with the version it read, the timer after the save, the record that cannot be written back, the free-form refusals and the shape of the available transitions. Seven mutations of the engine turn it red.
…fourteen collaborators method-decomposition slice 8h. StatusTransitionService coupled to 18 classes against 13 and took 14 constructor arguments. Transitions/CaseDeclarations reads what a case declares about its status and its moves, and Transitions/CaseMoveLedger holds what a move writes. The engine keeps the decision and the order of the checks, takes nine arguments and couples to 12 classes. Both suppressions are gone; phpmd.suppressWarnings 183 to 181. The public methods and their answers are unchanged. The characterisation test and the five existing engine tests are green with only their constructor call changed.
…ceiling 256 to 254
…26; phpmd.suppressWarnings 182 to 180
…ments The change what-a-status-declares was archived on 7 October. 206 @SPEC lines in 42 files still cited its path under openspec/changes/, which no longer exists. They now cite openspec/specs/status-transition-engine/spec.md (REQ-SDC-01 to 05) and openspec/specs/doorlooptijd-dashboard/spec.md (REQ-SDW-01), where the requirements live. Two lines that became a repeat of the line above them are removed.
… (Q-dossiq-L11-3) The store reads the ZGW rules share answered a failed read as nothing found: a uniqueness search that failed counted the identificatie as free, and a zaaktype, informatieobjecttype or besluittype that could not be read counted as absent. They now throw LookupNotCompleted, and ZgwBusinessRulesService refuses the request for it once, with the 503 check-not-completed answer of decision 224, logged at error with the rule and what was read. Not found, and a read OpenRegister refuses (NotAuthorizedException), still read as none. No store in the request, or an empty schema setting, still skips the lookup (the coordinator's ruling on the question). The lookups lost their logger, which only logged the swallowed failures. catch-return-null: three sites left, ceiling 254 to 251. REQ-ZBR-022.
…4 (Q-dossiq-L11-2) A ZGW delete answered 404 Not found on any failure: an unknown id, a store that was down and a refused permission read the same, and so did a delete that happened but whose notification failed. A show did the same, and an update answered 400. One place, StoreFailureAnswer behind ZgwService::storeFailureResponse(), now sorts a store failure for every resource: DoesNotExistException or no object is 404; OpenRegister's NotAuthorizedException or any failure with code 403 is 403 permission_denied; anything else is 503 store-not-reached, logged at error. ZgwService show, update and delete and the two BRC deletes answer through it. A delete that happened answers 204 even when its notification fails, and logs that at error. PATCH merges onto the object the update already read instead of reading it a second time. The cross-register writes of the Besluiten API stay best effort; a failure is now logged at error with the rule, the resource and the objects. REQ-ZBR-023.
The sync now logs a failed cross-register write at error with the rule, the resource and the objects (Q-dossiq-L11-2); its own test still read the old warning lines.
…rs leave ZtcController Method-decomposition slice 8i. ZtcController carried two class suppressions: 12 public methods against 10, and complexity 79 against 50. The three publish routes move to ZtcPublishController with handlePublish() and publishedCopy(); the URLs, verbs, rate limits and auth attributes are the same, only the route names change to ztcPublish#. The datumGeldigheid filter becomes Zgw/ValidityDateFilter and the ztc-010m name lookup Zgw/ZtcTypeNameResolver. Bodies are moved unchanged. Both suppressions go; phpmd.suppressWarnings 180 to 178 (stacked on 8h).
rubenvdlinde
requested review from
Rem-Dam,
SudoThijn,
WilcoLouwerse,
bbrands02,
remko48 and
rjzondervan
as code owners
October 14, 2026 21:17
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.
Method-decomposition slice 8i, by measured complexity. Stacked on #3921 (Q-dossiq-L11-2; it shares
.debt-baseline.jsonand the decomposition tasks with #3858): land after it.What moves
ZtcControllercarried two class suppressions: 12 public methods against 10, and complexity 79 against 50 (measured on development without the suppressions).ZtcPublishController, withhandlePublish()andpublishedCopy(). Same URLs, verbs, rate limits and auth attributes; only the route names change (ztc#publish*toztcPublish#publish*inappinfo/routes.php). It extendsZgwController, so the ZGW auth middleware still applies.Zgw/ValidityDateFilter: thedatumGeldigheidfilter of a Catalogi list.Zgw/ZtcTypeNameResolver: ztc-010m, an informatieobjecttype named by its omschrijving becomes its uuid.Bodies are moved unchanged. After: 9 public methods, complexity under 50, both suppressions gone.
phpmd.suppressWarnings180 to 178 on top of #3858.Tests
ZtcPublishControllerContractTest, 6 tests).ZgwRateLimitTestandZgwAuthMiddlewareTestlist the new controller, so its rate limits and its place under the middleware stay pinned.ValidityDateFilterTest(both bounds inclusive, open bounds, re-indexed) andZtcTypeNameResolverTest(name, then full text, outside the caller's access; and every case that leaves the body alone).Seen, not changed
The ZTC publish routes run no business rule: the CT-02b publish guard (
ZgwBusinessRulesService::guardCaseTypePublish, status types, a final status and a valid-from date) does not run on them, and they check no ZGW scope (the contract test documents the scope part). A zaaktype can therefore be published through/zaaktypen/{uuid}/publishwithout what the guard demands. Asked as Q-dossiq-L11-5; not a decomposition change.Verified (once, on the stack top 3bfc0b4, which holds #3858 and the four PRs above it)
Every
composer check:strictstage once, one at a time in the lane's check worktree (exit codes indq-l11-logs/r7/s31.rc):BooleanArgumentFlagfindings inlib/Service/Termijn/TermLetters.php(401, 425) that development carries since fix(letters): every date in a letter to the applicant reads the same way #3884/fix(portal): the Woo request form reads Dutch dates and names refused fields in Dutch #3895. Inherited.--no-coverage: 8,676 tests, exit 0 (7 skipped, 1 warning). A first run found 3 reds of this stack (BrcCrossRegisterSyncTeststill read the old warning lines), fixed in 28e4ad6, then the run above.ZgwBusinessRulesService, the throw infindBySchemaKey, the throw infieldPairExists, the not-found branch, the not-allowed branch and the null check inhandleDestroyeach turn their tests red.@covers/@usesof every touched test were checked by hand (each class a test can now execute is listed). CI is the check for that.src/manifest.json, which this stack does not touch; 23, 43, 51, 55, 104, 107). Gates 5, 13, 16, 25 and 46 pass.openspec validate guards-refuse-when-unsureandmethod-decomposition: valid.phpmd.suppressWarnings187 measured against 182) andeslint.inlineDisables15 against 14.No register change, so no
info.versionbump.