Skip to content

Release: merge development into beta - #3726

Open
github-actions[bot] wants to merge 883 commits into
betafrom
development
Open

github-actions[bot] wants to merge 883 commits into
betafrom
development

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Automated PR to sync development changes to beta for beta release.

Merging this PR will trigger the beta release workflow.

Reminder: Add a major, minor, or patch label to this PR to control the version bump. Default is patch.

A batch and a triage rule are private to the people the case type names.
Two checks read them under the caller's own access and so saw a slice:
a document could go into a second open batch, and applying the rules as a
colleague of the assignee applied none and answered zero. Both now read
every record of the case; listings stay under the caller's access.
The embedded table held 16 interventions that differ from the 16 shipped
grid cells on every position. Decision 213: the grid cells are right. The
embedded table now holds the grid's interventions, and
LhsLookupAnswersTheGridTest reads the shipped files and asks all 16
positions from each source (stored table, register cells, embedded table),
with a control that reports exactly one changed cell.

Reapplies #3774, which train 3 reverted (c9cfb5d).
…ADR-118)

No class in lib/ injected KvkHandelsregisterAdapterInterface. The four client
classes, the registrar and the contract fixture go. The KvK card stays Not
available and says dossiq ships no KvK client.
A form can now offer the named OpenRegister record templates of its schema.
RecordTemplateReader reads one template as the signed-in caller, and
RecordTemplateSelect lists them from /apps/openregister/api/record-templates.
Both are generic: any schema, any case type.

The search plan of a request is the first form that uses them. Until the plan
is recorded the dialog offers the templates of the request configuration. A
template fills whose files, the systems and the terms, never the period. The
recorded configuration names the template in copiedFrom, and a plan that names
a template the caller may not use is refused.

woo-request-corpus-collection task 5.2.
Both sides added a method and a test at the same place: both kept. The
predicate is renamed isAdmittedReader().
… openregister development

openregister#4583 and #4592 landed in openregister train #4595, and dossiq#3761
in train 3. The tick for 5.2 records what was read on openregister development:
the review annotation is kept and validated, the 403 decision-owned answer, and
the two events dossiq listens to. 2.2 is ticked because ReviewBatches now calls
the reconcile. The Newman collection the tasks name does not exist yet.
Characterisation for termijnbewaking-op-engine-timers 4.2, part 3, green
on the code as it stands: the share of the statutory term that is gone
(CaseTermsService::progressFor) and how long a request for more
information has been open (AanvullingsverzoekService::daysOpen). The
other five term calculations in this part were already pinned.
caseSearchDeclarations.spec.js asks every case property for an input control
or a place on its silent list. Both fields are looked up by exact match.
A reviewerAccess.records entry carries assigneeMay and reviewersMay, each
read (the default) or update. CaseRecordReaders::grantsFor() answers
core's permission bits per reader, and ObjectReadGrants::reconcile() makes
the record's user grants equal them: a grant with other permissions than
its reader is due is revoked and granted again. Delete and share are never
granted (REQ-CRA-010).

Configured for the Woo case type: the assignee may update a review batch
and a triage rule. Register 0.20.39, Woo case type object 1.4.5.
termijnbewaking-op-engine-timers 4.2, part 3 of 4 (REQ-TOT-007). Term
consumed and days left (CaseTermsService), days of a pause used, days in
a phase, the calendar overrun of a first response and the days a request
has been open are counted through DayCount. No count changes.

DeadlineExtensionService and TermijnTimerService stay on the allowlist:
both sit at the PHPMD coupling limit and own their day math. Allowlist
19 to 14.
CaseRecordReaders::grantsFor() tripped the ratchet against a second
permission evaluator. It decides nothing about who may read: it answers
what dossiq asks OpenRegister to grant. Renamed to toGrant().
documentReview carries the private block. The Woo case type lists it:
the assignee reads and updates every review of the case, a batch
reviewer the reviews of their own batch, supervisors all of them.

Every rule that reads reviews now reads the whole case
(DocumentRelevance::forCase, REQ-CRA-011), so what is outstanding, which
pages are unseen and what a rule may mark do not depend on who asks, and
a marking never makes a second review for a document. The relevance
route, the pages-seen route (ReviewWrites) and the triage apply
reconcile the case when they create a review. A reconcile that cannot
run after a write is logged and answered as failed.

Register 0.20.40, documentReview 1.0.3, Woo case type object 1.4.6.
An administrator runs POST /api/cases/reviewer-access/reconcile once
after the upgrade.
src/settings.js, the admin entry, never imported
@conduction/nextcloud-vue/css/index.css (src/main.js does), so
/settings/admin/dossiq drew every library component unstyled.
…-once

fix(portal): a Woo request sent twice with the same submission key makes one case, and the dossier is linked after the answer
rubenvdlinde and others added 26 commits October 15, 2026 09:36
…ever scroll (#3937)

DqWerkbord draws the columns side by side in a grid, a few cards each and a
dashed "Toon 12 meer". The board was one row of every status, 16,116px wide,
with a scroller per column and cards wider than their column.

- Columns sit in a grid of at least 240px each and wrap to the next row.
- A column draws three cards; the rest stay in its list behind Show N more,
  so drops, selection and the keyboard move still see every case.
- No column scrolls on its own; the window scrolls the page.
- Card headers wrap instead of running past the card.
- The drag-to-pan helper went with the strip it panned.
…k from

The closing move's resultTypeId input now carries a label (Result /
Resultaat) and options, one per result type the engine already put on the
offered move (the case type's own and its parents'), labelled by name. The
stages widget's transition dialog renders that as a picker instead of a bare
required text field asking for a UUID.

Needs openregister to publish input label/options and nextcloud-vue to render
options; on older releases the keys are dropped or ignored and the dialog
shows the text field as before.
…result

fix(lifecycle): a closing stage offers the case type's results to pick from
#3940)

ICache types its parameters from Nextcloud 35 on and leaves them untyped
in 32 to 34. InMemoryMemcache named `string` on get, set, hasKey, remove
and clear, which PHP refuses on 32 to 34: an implementation may widen a
parameter type, never narrow it. Loading the class was a fatal error, so
every PHPUnit cell on development stopped before it ran a single test.

The five parameters lose their type, which satisfies both shapes. ncad is
typed identically in every supported version and keeps its types. The
twelve missing docblocks phpcs reported on this file are filled in, since
the file was open anyway.
…g team

A case filed while its case type had no handling block was written without
assignedGroup and kept none after the case type gained one. A repair step
fills it from handling.defaultGroup on open cases that have none.

Assisted-by: ClaudeCode:claude-opus-5-5
…mat gate (#3943)

`npm run format` (prettier --check) is red on development: three vitest specs
carry the same over-long `toMatch` assertion on one line. Prettier wraps each
into a multi-line call with a trailing comma. No behaviour changes.

Assisted-by: ClaudeCode:claude-opus-5
…an read the case type

2.84.0 ships schema 2.96.0 with `@context.<name>.<field>` and the detail
page's `visibilityContext` (nextcloud-vue#1602), which the case panels on
this branch use. Re-vendors tests/schemas to 2.96.0, and turns the
captions tripwire in structureProfile.spec.js round: the library now keeps
a caption through the relocation step unless the relocations emptied it.
…type

feat(case-detail): the family plan and the projects panel show only on the case types they belong to
…ters (#3946)

* refactor(termijn): a letter's language is an object, not a flag on every date

phpmd flagged TermLetters::dayOf() and ::shownDay() for taking a boolean
flag argument. The flag was the letter's language, threaded through every
date and defaulting to Dutch, so each call site decided the language again
and two of them decided it by leaving the argument out.

LetterDays holds the language once and prints days in it. A caller names
the language through a factory (forLocale, or dutch for the letters whose
wording exists in Dutch only), so no boolean crosses a call site.
termStartLines takes the locale the class already passes around instead of
its own boolean. Wording and dates are unchanged.

* refactor(termijn): the letter's language is a constructor argument, not a static factory

The ruleset that flags the boolean flag also flags StaticAccess, and it
exempts FleetAppId alone, so LetterDays::forLocale() traded one phpmd
finding for another. A caller now names the language as the locale it
already holds: `new LetterDays(language: $locale)`, or `'nl'` for the two
letters whose wording exists in Dutch only.
)

* test(ci): the coverage metadata names the classes these tests run

phpunit.xml sets beStrictAboutCoverageMetadata and failOnRisky, so a test
that executes a class its docblock does not name is risky, and a risky
test fails the run. 49 tests across 15 files did that. They were invisible
until #3940, because the PHPUnit cells fataled before running anything.

Each class comes from the run's own report, so the list is exact rather
than guessed. Six classes account for all of it, ReadableDay for 23.
Annotations only: no test and no production code changes.

* test(ci): the Woo intake test names the job and queue it runs
…e shipped snapshot (#3944)

testTheCheckNamesAGroundThatDiffers overwrote the tracked
lib/Settings/woo-refusal-grounds.snapshot.json and restored it in a finally, so
it needed write access to a file the app ships.

That failed wherever phpunit runs as a user other than the checkout's owner. In
the dossiq dev container, which runs as www-data against a host-owned bind
mount, file_put_contents() was refused, the check script read an untampered
snapshot, exited 0, and the suite reported only "Failed asserting that 0 is
identical to 1". That reads as snapshot drift and sends a reader to audit a
snapshot that is correct. It also risked the shipped file: a finally does not
survive SIGKILL, and filinq and opencatalogi vendor that snapshot as their
redaction fallback.

The tool resolves its paths from its own location, so the test now copies the
three files it reads into a temporary directory and tampers there. Both
assertions are unchanged. A control run of the untampered copy asserts exit 0
first, so a copy that cannot be read cannot read as drift, and the shipped
snapshot is asserted byte-identical afterwards.

Assisted-by: ClaudeCode:claude-opus-5
…case-type-team

fix(repair): open cases without a team take their case type's handling team
# Conflicts:
#	tests/Unit/BackgroundJob/AcknowledgementDispatchJobServiceAccountTest.php
#	tests/Unit/Controller/PortalWooRequestSubmissionKeyTest.php
#	tests/Unit/Controller/WOOAssessmentControllerExtensionNoticeTest.php
#	tests/Unit/Service/AcknowledgementDutyTest.php
#	tests/Unit/Service/Intake/SystemCaseStoreTest.php
#	tests/Unit/Service/Termijn/TermLettersTest.php
#	tests/Unit/Service/TermijnNotificationServiceTest.php
#	tests/Unit/Settings/WorkflowGuardConformanceTest.php
#	tests/Unit/Woo/PortalFiledCaseOpensLikeAStaffCaseTest.php
#	tests/Unit/Woo/WooRequestIntakeReceiveTest.php
#	tests/Unit/Woo/WooRequestIntakeTest.php
#	tests/Unit/Woo/WooWritesMatchTheRealSchemasTest.php
…ng two advisories (#3948)

`quality / Security (composer)` is red on development. `composer audit`
reports two advisories, both in packages-dev:

- symfony/http-foundation v6.4.43, CVE-2026-108082: ReDoS in
  HeaderUtils::split(), reachable through the Cache-Control request
  header. Patched from 6.4.46.
- symfony/yaml v6.4.40, CVE-2026-109413: unbounded recursion in the
  YAML inline lexer lets a single document crash the process. Patched
  from 6.4.45. It arrives through consolidation/robo (symfony/yaml ^6).

Both move to v6.4.48, the newest 6.x, so nothing crosses a major
boundary. composer.json is unchanged: the `^6.4.41` constraint on
http-foundation already allowed a patched release, and yaml is a
transitive requirement, so the lock alone was behind. The lock's
content-hash is unchanged and only these two packages move.

Assisted-by: ClaudeCode:claude-opus-5
…ed here

A newer version left every row the instance already held as it was, so an
untouched row never received a corrected value. After the write and the
ledger record, each held row now goes through the shipped-set ledger: an
untouched row takes the new version and is stamped with it, a row edited
here is kept and logged by id. The outcome reports refreshed and kept.

Assisted-by: ClaudeCode:claude-opus-5-5
Seven suppressions landed on development without the baseline moving with
them, so `npm run check:debt-ratchet` fails: eslint.inlineDisables 15 against
14, phpmd.suppressWarnings 187 against 182, psalm.inlineSuppressions 254
against 253.

Three of the seven hide nothing and are removed. The inline
`@psalm-suppress UnusedClass` on LinkCollectionToCaseJob duplicates psalm.xml's
blanket handler for that issue class. PHPMD does not apply StaticAccess inside
a trait, so the annotation on TranslatesRefusals changed no finding; its reason
moves to a comment at the `\OCP\Server::get()` call. PHPMD treats
DocumentAssessmentGuard::evaluate()'s $userId as interface-mandated when lib is
scanned whole, which is why its three sibling guards carry no such annotation.

Four are deliberate and stay, each already reasoned at its site: the title prop
nine dashboard widgets declare for the host to draw, GuardRegistry's one
parameter per guard kind, and WooPublicationService's coupling and parameter
count over five optional collaborators. The baseline rises by exactly those
four. psalm.inlineSuppressions returns to 253 and is not raised.

Assisted-by: ClaudeCode:claude-opus-5
…without raising it (#3952)

* fix(letters): a letter's dates take its language, not a boolean flag

dayOf() and shownDay() took `bool $english=false`, which phpmd reports as
BooleanArgumentFlag twice (TermLetters.php:414 and :438, from #3884). Both
now take the letter's locale, with no default, so every caller names the
language it writes in; termStartLines() takes the locale the same way.

* test(ci): the dossier link test names the job and queue it runs

testWithAJobListTheDossierIsLinkedAfterTheCaseIsAnswered executes
LinkCollectionToCaseJob and CollectionLinkQueue; under pcov with
--fail-on-risky it is risky without them. The other 49 risky tests are
covered by #3942.

* fix(quality): the debt ratchet holds at its baseline without raising it

eslint.inlineDisables 15 -> 14: FirstTodayWidget declared an unused title
prop under an eslint-disable so the host's title would not fall through
onto the banner. inheritAttrs: false does that without the prop.

phpmd.suppressWarnings 187 -> 182, every one removed suppressed nothing
(checked by removing it and re-running phpmd):
- TranslatesRefusals StaticAccess: phpmd does not flag a chained
  \OCP\Server::get()->get() call (control file confirms).
- DocumentAssessmentGuard UnusedFormalParameter: the signature comes from
  GuardEvaluatorInterface, which phpmd honours on a whole-lib run.
- AcController::validateAutorisatieScopes CyclomaticComplexity and
  NPathComplexity, LoadDefaultZgwMappings::getDefaultMappings
  ExcessiveMethodLength: the methods are under the thresholds.

psalm.inlineSuppressions 254 -> 253: UnusedClass on LinkCollectionToCaseJob,
which CollectionLinkQueue references.

* test(ci): the letter tests name LetterDays, which #3946 put between them and ReadableDay

Under pcov with --fail-on-risky, 20 tests in 8 files executed
Service\Support\LetterDays (and LetterDaysTest ReadableDay) without
naming it.
# Conflicts:
#	.debt-baseline.json
#	tests/Unit/Service/Termijn/TermLettersTest.php
…hes-untouched-rows

fix(packages): a newer package version refreshes the rows nobody edited here
train: land 23 ready PRs (15 Oct, f)

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