Skip to content

Release: merge development into beta - #1318

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

Release: merge development into beta#1318
github-actions[bot] wants to merge 38 commits into
betafrom
development

Conversation

@github-actions

Copy link
Copy Markdown

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.

github-actions Bot and others added 2 commits August 31, 2026 10:25
The 2.0.8-beta.20260831102341 release bumped the version on beta. Without this,
development stays behind beta and the next development -> beta promotion
conflicts on the version file.

Version files resolve to development's side, which is the higher line,
so this never moves a version backwards.
Dependabot cannot propose composer updates for this app. Its updater fails
with:

  Your requirements could not be resolved to an installable set of packages.
    - edgedesign/phpqa[v1.27.0, ..., v1.27.2] require ext-xsl * ->
      it is missing from your system.

config.platform pins php 8.3 so composer resolves against a known PHP version,
but says nothing about extensions. edgedesign/phpqa requires ext-xsl and the
resolving environment does not have it, so the resolve fails before any bump
can be computed.

CI is unaffected, which is why this went unnoticed: composer install replays
the committed lock and never re-resolves, so the pipeline stays green while
dependabot -- which does re-resolve -- fails every time. The shared quality.yml
installs no xsl extension anywhere and never invokes phpqa.

Declaring ext-xsl beside the php pin makes resolution assume exactly what the
committed lockfile already assumes. Verified in a clean composer:2 container
without --ignore-platform-reqs: the same file fails without this line and
resolves (103 installs, lock written) with it.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
github-actions Bot and others added 6 commits August 31, 2026 11:00
The 2.0.8-beta.20260831105849 release bumped the version on beta. Without this,
development stays behind beta and the next development -> beta promotion
conflicts on the version file.

Version files resolve to development's side, which is the higher line,
so this never moves a version backwards.
The 2.0.8 release bumped the version on main. Without this,
development stays behind main and the next development -> main promotion
conflicts on the version file.

Version files resolve to development's side, which is the higher line,
so this never moves a version backwards.
….0.8

chore(release): sync main back into development
….0.8-beta.20260831105849

chore(release): sync beta back into development
….0.8-beta.20260831102341

chore(release): sync beta back into development
Levels this app with the fleet. 2.27.2 adds two fixes the earlier 2.27.0 pin does
not carry:

  * headerless is no longer chromeless — a flat KPI card in a borderless wrapper
    had no card, border or background at all;
  * a stat `variant` paints from the `-text` tokens rather than the fill tokens,
    which failed WCAG AA at 1.08:1 as a foreground colour. The KPI colour
    cleanup converted hardcoded values to `variant`, so this is what makes those
    conversions contrast-safe.

Lockfile only, and npm pruned nothing.
@github-actions

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 499f886

Check PHP Vue Security License Tests
lint ⏭️
phpcs ⏭️
phpmd ⏭️
psalm ⏭️
phpstan ⏭️
phpmetrics ⏭️
eslint ⏭️
stylelint ⏭️
build ⏭️
composer ⏭️ ⏭️
npm ⏭️ ⏭️
app:check-code ⏭️
info.xml ⏭️
REUSE ⏭️
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 11:25 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 2a246ce

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 12:36 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 5623f83

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 13:10 UTC

Download the full PDF report from the workflow artifacts.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ efa0ef1

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 14:37 UTC

Download the full PDF report from the workflow artifacts.

Dependabot cannot update these packages. Its npm updater fails with:

  npm error code EOVERRIDE
  npm error Override for <pkg> conflicts with direct dependency

The package is listed BOTH as a direct dependency and as a literal overrides
entry pinned to the same range. Dependabot bumps the direct dependency and
does not move the override, npm rejects the mismatched pair, and the update
is abandoned -- so these packages can never be updated, security advisories
included.

npm's self-reference is the idiom for exactly this: $<name> tells the
override to follow whatever the direct dependency resolves to, instead of a
range that has to be kept in lockstep by hand. This repo already uses it (see
the vue entry under @vue/test-utils).

Transitive consumers still get pinned to one version -- the direct
dependency's -- which is what the override was there to do. What changes is
that the pin tracks the dependency instead of duplicating it.

Verified in a clean container: bumping the direct dependency with the literal
override reproduces the EOVERRIDE above; with the self-reference the same
bump resolves.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 2500f3e

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 16:30 UTC

Download the full PDF report from the workflow artifacts.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 74f08bb

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-08-31 20:41 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 0826dea

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-01 04:01 UTC

Download the full PDF report from the workflow artifacts.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ f374485

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-01 21:58 UTC

Download the full PDF report from the workflow artifacts.

…match absent (#1365)

WOO-517 is the only failing test in the suite and it flaps: red on c402608,
green on a07067a, red again on 6012ff5, always alone and always with 111
others passing. The extraction request reported no error in any of them.

Extraction is queued work. extractFile() force-triggers it and returns as soon
as the request is accepted, so the marker becomes searchable some time later.
Ten seconds was enough on an idle runner and not on a loaded one, which turns
a timing race into the message 'the body-text match surfaces the owning
document when _content=true' — an assertion about the FEATURE, blamed for a
wait that had not finished.

The poll returns the moment a title appears, so a 30s ceiling costs nothing
when extraction is prompt. The test budget goes to 120s to cover it, since 60s
now has to hold a wait that can legitimately take half of it.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 336e448

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-01 22:37 UTC

Download the full PDF report from the workflow artifacts.

…one (#1369)

* fix(e2e): give text extraction a realistic poll before declaring the match absent

WOO-517 is the only failing test in the suite and it flaps: red on c402608,
green on a07067a, red again on 6012ff5, always alone and always with 111
others passing. The extraction request reported no error in any of them.

Extraction is queued work. extractFile() force-triggers it and returns as soon
as the request is accepted, so the marker becomes searchable some time later.
Ten seconds was enough on an idle runner and not on a loaded one, which turns
a timing race into the message 'the body-text match surfaces the owning
document when _content=true' — an assertion about the FEATURE, blamed for a
wait that had not finished.

The poll returns the moment a title appears, so a 30s ceiling costs nothing
when extraction is prompt. The test budget goes to 120s to cover it, since 60s
now has to hold a wait that can legitimately take half of it.

* fix(search): resolve a document that names its publication by slug alone

Content search has surfaced no body-text match since c402608. WOO-517 has
failed on every run since, and it is the only failing test in the suite.

assemblePublicSearchResults() drops a document row unless
resolveDocumentPublicationSummary() returns a publicly-visible publication.
That resolver had three paths and none of them matched the shape the fleet
actually writes:

  M1  reads $documentRow['publication']['id']
  M2  reads $documentRow['@self']['relations']['publication'] and
      ['publication.slug']
  fallback  asks the INVERSE question, a publication whose _relations contain
      this document, which a document→publication write never answers

A document is created with 'publication' => ['slug' => ..., 'title' => ...],
as a plain property, with no id and not inside _relations. So it resolved
through nothing, the row was discarded, and the caller saw an empty result set,
which is indistinguishable from 'nothing matched'.

M1b reads the carried publication.slug and routes it through the slug lookup
that already exists for the _relations form, reusing the same slug cache. On a
miss it falls through to M2 exactly as before, so a document whose slug names a
non-public publication is still dropped.

VERIFICATION IS CI, NOT LOCAL, AND THAT IS NOT A CHOICE. This suite cannot run
in a bare checkout: OCP and openregister are both absent, so all 27 tests error
before asserting. With both stubbed onto the autoloader the run is identical
with and without this change (27 tests, 39 assertions, 4 errors, 11 failures),
because the pre-existing slug-path tests fail there too. phpcs is clean.

---------

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 5e25712

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-02 00:09 UTC

Download the full PDF report from the workflow artifacts.

…1371)

NOT FOR MERGE. This isolates one variable.

WOO-517 passed at f156675 (09:50) and has failed on every run since
c402608 (15:58). Both sides of that boundary moved: opencatalogi took the
WOO-536 search rework via the beta sync, AND openregister went from
2.0.12-unstable.20260901050305 to 2.0.14-unstable.20260901212512, because
additional-apps clones it unpinned at 'development'.

So the bisect on opencatalogi's own SHAs could never have been conclusive.
6fc19be5 is the openregister release commit for the version the green run
actually enabled. Green here means the regression is openregister's; red means
it is opencatalogi's WOO-536 rework.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ e7773e0

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-02 02:02 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 325d241

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-02 03:51 UTC

Download the full PDF report from the workflow artifacts.

The previous pin used the commit SHA and every job died at setup with exit
128: the additional-apps clone resolves its ref with git clone --branch, which
takes a branch or a tag and not an arbitrary commit. Nothing ran, so the
experiment answered nothing and development was left failing at setup.

v2.0.12-unstable.20260901050305 is the tag for the version the last green run
enabled. Reverting as soon as this reports.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 8c1bb40

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-02 06:09 UTC

Download the full PDF report from the workflow artifacts.

The pin was a diagnostic and is removed as promised.

WITH openregister pinned to 2.0.12-unstable.20260901050305 — the version the
last green run enabled, confirmed in the run log — WOO-517 STILL FAILS:
1 failed / 111 passed, identical to the unpinned runs.

So the regression is NOT openregister's. It is opencatalogi's WOO-536 search
rework, somewhere in assemblePublicSearchResults() past the catalog-scope
guard. Recorded on #1368.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 7d09877

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-02 07:18 UTC

Download the full PDF report from the workflow artifacts.

…#1381)

The metadata-only assertion in WOO-517 is satisfied by an EMPTY list. It
passes identically whether the endpoint correctly withheld one document or
returned nothing because the anonymous caller can see no publications
whatsoever. That distinction is the whole question when the _content=true half
comes back empty, and the test could not tell them apart.

WOO-551 removed OR's _rbacAsPublic toggle. The replacement inherits
authorization at the schema level, so anonymous visibility now depends on read
rules being present on the register. Without them every publication is
invisible here, a document can never resolve its owning publication, and the
failure reads as 'the body-text match does not surface' — an assertion about
content search, blamed for an authorization gap.

The seeded publication carries a past publicationDate, which is exactly what
the register's read rules scope anonymous access to, so it must be visible.
This makes the test say which of the two it is.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 19be847

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-02 09:26 UTC

Download the full PDF report from the workflow artifacts.

…#1383)

The first control (#1381) proved anonymous callers see PUBLICATIONS: it passed
on the run that still failed WOO-517, which kills the WOO-551 RBAC hypothesis
I had been carrying.

It does not prove they see DOCUMENTS, and the document is what has to surface.
Searching its TITLE is a metadata match, so it must succeed with no
_content=true at all. If it does not, the document is invisible to this caller
and the body-text assertion can never pass however content search behaves —
reporting a content-search failure for a visibility one, which is the same
trap the first control closed one layer up.

Together the two controls bisect the remaining space: publication visible plus
document visible means the drop really is in the chunk-match path, and the
search narrows to FileMapper::findOwningObjectUuid() and the schema-slug gate
rather than anything about authorization.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 308c9e7

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-02 09:50 UTC

Download the full PDF report from the workflow artifacts.

…iled (#1385)

ROOT CAUSE, bisected by the two controls in #1381 and #1383 rather than
guessed. The anonymous caller CAN see the publication and CANNOT see the
document. Content search was never involved.

Since WOO-536, /api/search derives its scope from the catalog model:
resolveCatalogScope() unions the registers and schemas of every
listed+published catalog. It used to come from app config, whose keys were
publication_register / publication_schema / document_schema — the service's
own Stap 2 comment records the replacement. The document schema was in the old
scope by name and is in the new one only if a catalog lists it.

createCatalog() wired every fixture catalog to schemas: [SCHEMA_PUBLICATION].
No catalog in the suite listed the document schema, so documents were out of
scope, and a document out of scope is invisible to every query with or without
_content=true. That is the whole failure.

Two changes:

  - the fixture catalog now covers SCHEMA_DOCUMENT as well, because a catalog
    that surfaces publications but not their documents cannot answer for them;
  - this spec creates its own catalog instead of depending on another spec
    having created one, which was an ordering dependency it never declared.

This is why the openregister pin experiment came back red: nothing about
openregister was ever wrong.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 02873c6

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-02 10:16 UTC

Download the full PDF report from the workflow artifacts.

rubenvdlinde and others added 2 commits September 2, 2026 12:25
…pe (#1387)

Corrects my own #1385, which was wrong twice over: it did not fix WOO-517, and
it broke catalog-crud-persistence by widening a default that test asserts
round-trips exactly (2 failed / 110 passed, worse than the 1 / 111 before).

The real mechanism is one line up from where I was looking.
resolveCatalogScope() unions only catalogs that are listed AND published, and
isCatalogPubliclyAvailable() requires 'published' to be a non-empty string
parsing to a date <= now. createCatalog() set listed: true and no published
field at all, so EVERY catalog this fixture makes was dropped from that union
silently. Adding the document schema therefore changed nothing: the catalog
carrying it was never in scope to begin with.

Two changes:

  - the fixture default goes back to schemas: [SCHEMA_PUBLICATION], which is
    what catalog-crud-persistence asserts, and gains a past 'published' date so
    the catalogs it creates actually reach the scope union;
  - the content-search spec names both schemas through extra.schemas, since it
    is the one spec that needs documents in scope.

The document probe from #1383 stays the arbiter: it fails while the document is
invisible and passes when it is not, whatever the reason turns out to be.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
…dcast job (#1389)

* fix: wire the three orphaned pieces the flow-engine audit found

Three defined-but-never-called or never-registered pieces, each one a
silent hole:

- WooService::publishBatch() now evaluates the configured approval chain
  before publishing a WOO batch. getPublishApprovalChain() was defined
  and never called, so any admin-settings user could publish a legally
  reviewable batch with zero sign-off. The gate fails closed: no chain
  configured, approval store unreachable, and no completed approving
  sequence all refuse with a translated message naming what is missing
  (nl + en strings added). The evaluation only reads the recorded
  outcome from OpenRegister's task-sequence store; the chain itself
  stays an OR approval-workflow construct (ADR-022).

- RetentionService::applyDefaults() had no caller, leaving RET-004
  (retention defaults stamped at publication) unimplemented. The new
  applyDefaultsAtPublication() guards on the publication register and
  schema, resolves the catalog slug by register/schema membership, fills
  only empty retention fields, and saves nothing when nothing changed,
  so the follow-up update event terminates instead of looping. Both OR
  object event listeners call it on the unpublished-to-published
  transition, independent of the auto-publishing options.

- BackgroundJob\Broadcast is now registered in info.xml. DIR-007
  requires the 4-hourly directory broadcast and even carried the status
  'Bug (Not Registered in info.xml)'; the pending delegate-to-OR-webhooks
  change replaces how a broadcast is delivered, not whether a schedule
  exists, so registration is the truthful option. A manifest test keeps
  the registration from regressing.

Also fixed encountered pre-existing defects: the listeners caught
\Exception where a PHP Error would abort the OR save pipeline (now
\Throwable via an injected logger), and the SchemaMapper test stub
lacked findMultipleOptimized(), which fataled 5 SettingsService tests
in any bare checkout.

* refactor: settle the analyzer findings on the new gate code

phpcs flagged the no-chain refusal line at 183 characters; the message is
now the short form naming the missing setting, in the code and in all
four l10n files. PHPMD flagged applyDefaultsAtPublication() at
complexity 12, so the register/schema guard and the id carry-over moved
into their own helpers, and WooService slid back under the 1000-line
class ceiling by deduplicating the unverifiable-chain refusal.

* fix: parse info.xml as a string, since the server's entity loader breaks simplexml_load_file

The Nextcloud bootstrap installs a libxml external entity loader that
returns null, which makes simplexml_load_file() fail on any file once
the server tree is loaded, as it is on the CI runner. Read the bytes
and parse with simplexml_load_string instead.

Also list QualityService as @uses on StatsControllerTest so the rollup
test is no longer risky and its coverage is not discarded under
beStrictAboutCoverageMetadata.
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 0838e29

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-02 10:56 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ fac9d6a

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-02 11:11 UTC

Download the full PDF report from the workflow artifacts.

…or (#1391)

* fix(search): admit the document schema when content search is asked for

WOO-517 has been red on development since it was written: "a body-text-only
match surfaces via ?_content=true and is absent without it".

ROOT CAUSE. A catalog is wired at the publication register + PUBLICATION
schema, so the resolved scope is publication-only. OpenRegister applies that
same scope to every chunk owner its content arm resolves, and a body-text
chunk belongs to a DOCUMENT. Every document match was therefore discarded
inside OpenRegister and this assembler never saw a row.

Reproduced on the dev instance 2026-09-02 with a freshly seeded, publicly
visible publication + document + .txt, extraction confirmed, probing
OpenRegister's ContentSearchHandler:

  CHUNK file=596 ownerUuid='f9a02425-...'
  RESOLVED 'f9a02425-...' rbac=true mt=false
  SCOPECHECK objReg=31 objSchema=1114
             scope={"registers":[31],"schemas":[1113]} match=false

1113 is publication, 1114 is document. The owner resolved perfectly and was
then dropped for being the very thing the search was looking for. The
endpoint answered {"results":[],"total":1}, which is also why this looked
like a flaky poll rather than a scope bug: the count said something matched.

This is the silent drop resolveDocumentPublicationSummary()'s own docblock
warned about, one layer further out.

THE FIX. When `_content=true`, widen `_schemas` to the document schemas the
scope's registers carry. Scoped to that flag on purpose: without it the
schemas stay publication-only, so a document still MUST NOT surface on the
metadata-only path, which is the test's other arm.

Transitive visibility is untouched. The document rows this admits are still
gated by the existing check that drops any document whose linked publication
is not publicly visible.

Verified live, unauthenticated, all three arms:

  _content=true, public publication      -> total 1, rows 1 (the document)
  no _content                            -> total 0, rows 0
  _content=true, publication depublished -> total 0, rows 0

* test(search): cover the document-schema widening

The coverage guard was right: the widening shipped with no test at all.
Seven cases, driven through reflection because both methods are private
and the public entry point needs the whole OR container standing up.

The cases that matter are the ones that must NOT widen. Returning a
schema already in scope would duplicate a `_schemas` entry; widening on
a register that carries no document schema would reach past the catalog
boundary the caller's `unset()` of client-supplied `_schemas` exists to
hold. Unavailable mappers, an unreadable register and an unresolvable
slug each degrade to no widening, because the widening is an
enhancement to a search and never a precondition for one.

---------

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 1b65e79

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-02 12:13 UTC

Download the full PDF report from the workflow artifacts.

…ting umbrella re-scope (#1393)

* feat(retention): RET-004 defaults resolve through OR's shared decision-table evaluator

The One Engine audit flagged applyDefaults()'s category/_fallback lookup as
app-local rule evaluation. The stored retention_defaults shape is unchanged
(no migration); RetentionPolicyTable translates it into a FIRST-policy DMN
table (quoted-literal category cells, trailing '-' catch-all) and the match
runs through OCA\OpenRegister\Service\Dmn\DecisionTableEvaluator, resolved
with the same guarded container pattern as ObjectService. no_rule_matched and
an unavailable evaluator both degrade to 'no defaults', logged - the in-app
matcher is deleted, not kept as a fallback. CI stubs are signature copies of
the OR classes; the unit suite runs the real grammar when a sibling OR
checkout exists.

openspec change: retention-defaults-on-shared-decision-tables

* docs(openspec): re-scope the dcat-oai-pmh-harvesting umbrella into five shippable slices

The umbrella sat at 0/177 tasks and double-counted outbound DCAT, which had
already shipped as the live dcat-ap-harvest spec (DCAT-001..010). It becomes
a superseded redirect with a full scope-disposition table; the 177-task list
and 51-scenario delta spec are removed (git history keeps them). Successors:

- oai-pmh-endpoint: outbound OAI-PMH 2.0 per catalog, fully authored
  (proposal/design/tasks/delta spec) and ready to hand to an agent
- harvest-feed-intake: feed registration + inbound DCAT JSON-LD; scheduling
  moves onto the OR flow engine (TriggerScheduleNode with explicit runAs) -
  the app-local cron parser/scheduler/dispatcher tasks are cut
- harvest-conflict-policies: the four policies + manual review
- harvest-protocol-plugins: DCAT-RDF, OAI-PMH client, CKAN, schema.org
- harvest-observability: SHACL gate, per-feed dashboard, run logs

Also cut: RML mapping (JSON-path only) and oai_datacite. No code carried
@SPEC tags into the umbrella; the two openspec references (adr-001 row,
nora-architectuur-publishing) are repointed.

* test(retention): complete the strict-coverage roster for the policy-table extraction

CI runs beStrictAboutCoverageMetadata with a coverage driver, so executing
RetentionPolicyTable outside RetentionServiceTest's roster marked 5 tests
risky and voided their recorded coverage - the ratchet then read a 27% drop
that no behaviour change caused. Add the @uses entry and a dedicated
RetentionPolicyTableTest covering the translation grammar directly (rule
order, fallback-last, quote escaping, null output entries, unusable rows).

---------

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 7ef5dc6

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-02 12:56 UTC

Download the full PDF report from the workflow artifacts.

… inside (#1395)

its own card.

⚠️ THE CAUSE IS AN INSET, NOT A COMPONENT. A card widget renders `flush` and
then has its padding put BACK by the card-fit rule (`padding: 8px 14px`), so
the KPI sits inside the wrapper while the WRAPPER draws the border, radius
and background the user reads as "the card". The library's
`--clickable:hover` rule then drew a 2px border and a drop shadow on the KPI
itself, 8-14px in from the edge being hovered.

Measured live on dossiq, while genuinely hovered: the tile carried a 2px
rgb(0,103,158) border and its own shadow, inset 9px from the wrapper's top
and 15px from its left. A non-card-fit tile sits at 1px, so its border lands
on the wrapper's own edge and reads as one card. That inset is the whole
difference, which is why it looked app-specific and was not.

nextcloud-vue#932 moves the affordance to the wrapper. No layout change:
nothing moves, one card outlines. Verified in the browser with a real pointer
hover:

  before   inner 2px rgb(0,103,158) + shadow   wrapper grey, no shadow
  after    inner transparent, no shadow        wrapper rgb(0,103,158) + shadow

Every app with clickable stat, gauge or delta tiles had this. This bump is
one of the fleet sweep that clears it.

Dependency change only: package.json and the nextcloud-vue entry in
package-lock.json.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Author

Quality Report — ConductionNL/opencatalogi @ 9720f51

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
check-l10n
check-manifest
format
check-schema-l10n
check-l10n-js
composer ✅ 129/129
npm ✅ 881/881
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman
Playwright
Hydra gates

Quality workflow — 2026-09-02 19:06 UTC

Download the full PDF report from the workflow artifacts.

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