Skip to content

train: land 8 ready PRs (15 Oct, g) - #3968

Open
rubenvdlinde wants to merge 36 commits into
developmentfrom
train/2026-10-15-g
Open

rubenvdlinde wants to merge 36 commits into
developmentfrom
train/2026-10-15-g

Conversation

@rubenvdlinde

@rubenvdlinde rubenvdlinde commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Merge train of 4 stacks (8 PRs), built from the real heads with git merge --no-ff (no squash, no cherry-pick). Landing this PR makes every included head an ancestor of development, so GitHub marks them merged.

Included heads (tip of each stack)

Excluded

Conflict notes

  • .procedure-code-baseline.json: measured with ConductionNL/.github main check_procedure_code.py . --ref HEAD --list: 170 counted, baseline 170 (development 182). R2 and R8 lower it, fix(quality): the blocking Hydra gate findings on development #3947 moves CaseNumberReader out of Service/Termijn.
  • lib/Settings/dossiq_register.json info.version: development 0.20.47, R8 0.20.45, R2 0.20.43, so the train is 0.20.48. php tools/schema-version-digests.php run once at the end.
  • appinfo/info.xml: development's version line kept (higher than R2's); R8's repair step CopyShippedPublicationCategories and R2's additions merged without duplicates.
  • Catch-return-null ceiling unchanged at 251 (ServiceCatchReturnsNullTest passes).
  • .debt-baseline.json: development's as base; psalm.inlineSuppressions tightened 251 to 249. Not raised.
  • l10n: merged key-wise by the merge driver, npm run l10n:build run.
  • openspec/changes/woo-review-triage spec: development's text kept, with R8's OutcomePublisher::publish() name.
  • TermijnNotificationServiceTest: @uses for CaseNumberReader follows fix(quality): the blocking Hydra gate findings on development #3947's move to OCA\Dossiq\Service.

Exit codes (head e024c87)

  • composer lint 0, check:refusal-grounds-snapshot 0, phpcs 0, phpmd (both rulesets, empty HOME) 0, psalm --threads=1 0, phpstan 0
  • phpunit --no-coverage 0 (8816 tests, 1 warning, 6 skipped)
  • vitest --maxWorkers=2 0; npm run lint 0; npm run format 0; check:schema-l10n 0; test:l10n 0; check:l10n-js 0; gate 119 0 (170 against 170)
  • node scripts/debt-ratchet.js exit 1: phpunit.skips is 6 against 5. This is a static count of markTestSkipped call sites and development itself counts 6 (CrossAppListenerRegistrarTest, AskPersonHeartbeatRecoveryTest, LeafIntegrationDeclarationsTest, RenameDutchColumnsTest, PrivateScopeVerdictDriftTest, StubApiDriftTest), so a sibling openregister checkout does not change it. Inherited, baseline not raised.
  • Not run: phpunit under a coverage driver (CI runs failOnRisky), Playwright, the full Hydra gate set. fix(quality): the blocking Hydra gate findings on development #3947 reports gate-22 and gate-53 failing on development because the gate package's manifest schema lags (startOn); that needs the .github branch chore/vendored-manifest-schema-2.96.0. gate-23 stays inherited.

_rbac

_rbac appears once in the combined diff, in a docblock of the signing listener saying nothing is written with _rbac: false. No _rbac: false write.

Rollout

  1. Install and enable filinq before this lands: without it a decision cannot be signed (503 signing_unavailable).
  2. Optional: occ config:app:set dossiq signing.level --value=QES (or AdES); unset means SES.
  3. A decision tried in the old LibreSign flow that answered "pending" was never signed; ask for its signature again.
  4. Signing conclusions are written as the background service account (decision 242); a usable service account must exist (CreateBackgroundServiceGroup), otherwise the conclusion is logged and not written.
  5. Upgrade runs CopyShippedPublicationCategories; the Woo decision type keeps infocat014.

…ed end is shown

Decision 221. Dossiq raises filinq's DocumentSigningRequestedEvent through
the generic Service/Signing/DocumentSigningRequester (level from
signing.level, SES by default) and hears SigningConcludedEvent in
SigningConcludedListener. onderteken answers 202 and the decision waits with
signing.state = requested; signed moves it to signed, declined, cancelled
and expired (filinq's expiry, 30 days by default) mark it not-concluded and
let it be asked again. Without filinq the answer is 503 and nothing is
written. The audit packet says no validation report is available.

Deleted after git grep found no other caller: SigningAdapterInterface, the
four LibreSign classes, MockSigningAdapter, the signing binding in
BeschikkingAdapterRegistrar and three test files. beschikking schema 1.2.0
(signing), l10n, digests, app version moved. Gate 119 baseline 185 -> 179.
BeschikkingService passed phpmd's class complexity ceiling (50) with the
conclusion in it. Service/Signing/SigningConclusionRecorder now records
filinq's outcome on the decision; SigningConcludedListener calls it.
…lt link

Characterisation of WooResultLink before it moves: the stored label, a
published state with a url writes exactly that url, withdrawn clears the link
even with a url present, every other state or a published one without a url
changes nothing, and scalar values are read as strings.
…r what it does

OCA\Dossiq\Woo\WooResultLink becomes
OCA\Dossiq\Service\Publication\PublicationResultLink. It projects any
publication state onto the case's resultLink; nothing in it is particular to
one procedure. The stored label, the case fields it reads
(wooPublicationStatus, wooPublicationUrl) and resultLink keep their spelling.
Gate 119 baseline 181 to 180.
Characterisation of WooCaseLedger before it moves: the one decision with a
summary is the case's decision, none or several are refused with their
reason, the state write carries the result link and is logged when it
fails, links become absolute only with a URL generator, a delivery without a
set writer is the send alone, and the withheld list reads the classification
and grounds field it is configured with.
…s named for what it does

OCA\Dossiq\Woo\WooCaseLedger becomes
OCA\Dossiq\Service\Publication\CasePublicationState, beside CatalogTransport
and the publication service's other collaborators. resolveWooDecision()
becomes resolveDecision(); its refusal reasons, the case fields it writes and
the decision field it reads keep their stored spelling. The withheld list's
Woo classification is still passed in here; it moves to the case type's
configuration with the publisher. Gate 119 baseline 180 to 179.
…ails quietly

Characterisation of WooDossierReturn before it moves, beside the six pins it
had: nothing is written without a publication id or without OpenRegister, a
refused write answers false and is logged, and the collection is looked up
under the two stored config keys.
…ollection through a class named for what it does

OCA\Dossiq\Woo\WooDossierReturn becomes
OCA\Dossiq\Service\Publication\SourceCollectionReturn, and its test moves
with it (the three spec citations follow). It appends any publication to the
collection a request was started from; the case field it reads
(wooRequest.collectionId) and the two config keys keep their stored spelling.
The decision notice it calls stays in the Woo namespace until the notice
templates move. Gate 119 baseline 179 to 178.
…d payload

Characterisation of WooPublicationService before it moves: the publication
kind and the three case states keep their spelling, availability answers
opencatalogi first and OpenRegister second, and the payload takes the case
title, the decision texts, the category and the period, with its fallbacks.
…d for what it does

OCA\Dossiq\Service\WooPublicationService becomes
OCA\Dossiq\Service\Publication\OutcomePublisher, beside the collaborators it
was already split into. WOOAssessmentController gets it injected under the
new name; its routes and URLs do not change. The publication kind
(woo-besluit), the three case states, the refusal reasons and every case and
decision field keep their stored spelling. Spec, task and inventory
citations follow; the register.d/82 note keeps the old name because the
fragment set is hashed and a prose edit would re-import it. Gate 119
baseline 178 to 177.
The information category a published decision is filed under was a lookup
table in code (WooCategoryMapper: a default and a map by decision type).
Per decision 182 and Q-R8-1 it is now configuration on the decision type
row: `publicationCategory` (code, label, uri), an additive property on the
decisionType schema (1.2.1 to 1.3.0). Service/Publication/PublicationCategory
reads it and falls back to infocat014, the category every decision went out
under before, so a legacy type name or a row without a category publishes
exactly as it did.

The Woo decision type (d001) carries infocat014 in register.d/81, where the
Woo case type is seeded until Q-R8-3 moves it into the woo-verzoek package
with the same uuids. Repair step CopyShippedPublicationCategories copies a
shipped category onto a stored row that has none, so an existing instance
keeps its mapping; a row with its own category is left alone.

WooCategoryMapper and its test go; the two spec scenarios now cite
PublicationCategory. Gate 119 baseline 177 to 176.
…on category

The decisionType schema gains publicationCategory and the Woo decision type
row carries it; OpenRegister skips an import whose version is not higher.
…at all

Decision 242: SigningConcludedListener records filinq's conclusion through
BackgroundServiceAccount::runAs(), never as the signed-in signer. With no
usable service account nothing is written (no _rbac false, no admin), the
decision still reads signing.state requested, and an error names the
decision and the signing request. Both paths tested.

ZgwDocumentService::storeRaw goes: git grep finds no caller in lib/, src/
or another app (its one caller was the deleted LibreSign assembler); its
storage tests use storeBase64.
…cation state at its new path

The rename rewrote the class name inside the old path, so the allowlist
pointed at a file that does not exist and LocalDecisionAuthoringTest failed.
The inventory row names the old file correctly too.
…urce-collection-return

# Conflicts:
#	openspec/changes/procedures-are-configuration-dossiq/inventory.md
…tion-category

# Conflicts:
#	openspec/changes/procedures-are-configuration-dossiq/inventory.md
`quality / Hydra Gates` is a required check and it fails on development, so
no release can go out. Three of the five findings this repo can answer:

gate-43 table-headers. The review batch table had four column headers and no
`scope=`, so a screen reader could not name the column a cell belongs to
(WCAG 2.2 AA SC 1.3.1).

gate-51 schema-property-titles. 26 properties of `caseType.relations[]` and
`caseType.sessions[]` carried no `title`, six no `description` either.
`fieldsFromSchema` labels a field `prop.title || key`, so a case type manager
read `attendanceGraceHours` where a label belonged. Every new string has an
`en` and an `nl` catalogue entry, so the field is not English inside a Dutch
form.

gate-119 procedure-code. `CaseNumberReader` moves from
`OCA\Dossiq\Service\Termijn` to `OCA\Dossiq\Service`. The class was already
generic, it answers a case's number for a case UUID; only the directory named
it after a procedure term, and that is what the gate counted. Decision 182:
procedures are configuration, code is generic and named by what it does. The
directory keeps its name, since renaming it is decision 184's separate
refactor.

gate-22 and gate-53 are not fixed here, because they cannot be. Both validate
against the schema vendored in ConductionNL/.github, which is at 2.89.0, and
`walkthrough.tours[].startOn` arrived in 2.94.0. The published
@conduction/nextcloud-vue ships 2.96.0, so this manifest is valid against the
library and refused by the gate. Branch
chore/vendored-manifest-schema-2.96.0 on ConductionNL/.github repairs it
where the copy lives.

Assisted-by: ClaudeCode:claude-opus-5
…lish instead of swallowing it

A catch that answered [] counted against the catch-return-null ceiling (257
against 256). A missing decision type row still reads as the fallback.
On a case whose type enables document review, a document nobody marked
counts as outstanding whatever verdict it carries. The assess dialog
records only the verdict, so after "1 document assessed." the document
stayed unmarked and the transition guard kept the next stage closed
(rehearsal, Woo request 2026-0013: summary relevance.unmarked 1 beside
verdicts.openbaar 1).

Saving a verdict now marks the documents it judged in scope where they
were still unmarked, as the assessor's marking. A marked document keeps
its marking and a refused verdict marks nothing.
… to match

This branch moves CaseNumberReader out of the Termijn directory for
gate-119, so the `@uses` annotation that arrived from #3942 still named
`Service\Termijn\CaseNumberReader`. PHPUnit rejects an annotation whose
target does not exist, which failed five TermijnNotificationServiceTest
cases. It now names `Service\CaseNumberReader`.

The branch also removes suppressions, so eslint.inlineDisables is 14
against a baseline of 15 and phpmd.suppressWarnings 182 against 185. A
ratchet exists to come down: both baselines follow the real count.
…nq' into train/2026-10-15-g

# Conflicts:
#	.procedure-code-baseline.json
#	appinfo/info.xml
…' into train/2026-10-15-g

# Conflicts:
#	.procedure-code-baseline.json
#	lib/Settings/dossiq_register.json
#	openspec/changes/woo-review-triage/specs/woo-review-triage/spec.md
…train/2026-10-15-g

# Conflicts:
#	.debt-baseline.json
#	tests/Unit/Service/TermijnNotificationServiceTest.php
@rubenvdlinde rubenvdlinde changed the title train: land 4 ready stacks (15 Oct, g) train: land 8 ready PRs (15 Oct, g) Oct 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/dossiq @ 937e098

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 ❌ 8813/8813 · 3 skipped (no test failed, the job failed for another reason — see its log)
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-15 19:31 UTC

Download the full PDF report from the workflow artifacts.

This branch has not been deployed

No deployments
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