Skip to content

Release: merge development into beta - #758

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

Release: merge development into beta#758
github-actions[bot] wants to merge 47 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.

rubenvdlinde and others added 30 commits August 27, 2026 09:26
)

* fix(l10n): regenerate all 38 browser catalogues, and add the check

Every locale catalogue was stale: l10n/<locale>.json is read server-side by PHP
`$l->t()`, while the browser only ever sees `OC.L10N.register(...)` from
l10n/<locale>.js, and a raw .json is not served from an app directory at all.
A key added to the JSON and forgotten in the JS renders in English for every
browser with nothing reporting it.

Ported keepiq's generator, which reads the app id from appinfo/info.xml rather
than hard-coding it — a catalogue registered under a stale id is silently
ignored by `t()`, which matters in a fleet that renames apps.

Backfilled first, then generated. This app had only 4 keys living solely in
.js, but the same step run blind cost opencatalogi 21,662 translations and
integriq 5,240, so the order is now fixed rather than judged per app.

Verified with the assertion that matters: comparing every rebuilt .js against
its pre-change version, keys DROPPED = 0. Not "no locale has fewer keys than
its json" — that comparison is blind to this failure, which is how dossiq
silently lost 631 real translations before I went back and re-checked.

nl.js carries 691 keys, de.js 278. check:l10n-js exits 0 after the build.

* fix(l10n): translate the 59 untranslated manifest strings

The catalogue fix in the previous commit made the browser able to READ Dutch.
This gives it Dutch to read.

59 strings: the getting-started tour, the nav, and the organisation, contract,
module and compliance surfaces. Domain terms as this catalogue's users have
them: leverancier, moduleversie, compliance-claim, onderbouwend bewijs,
audittrail.

GEMMA stays GEMMA, and the two catalogue descriptions keep the Dutch word the
domain actually uses: "Blader door de dienstencatalogus, gefilterd op
GEMMA-architectuurdimensie." The English original wrote "the service (dienst)
catalogue" precisely because dienst is the term of record.

Compliance stays Compliance. It is the word on the page in Dutch
organisations, and "naleving" would read as a translation of a label nobody
calls that.

Built on the same branch rather than a fresh one, because the generator these
translations need is in this PR and not yet on development.

Verified: 0 manifest strings left without Dutch, keys DROPPED = 0, nl.js
registers under "stackiq" with 750 keys and resolves "Organisations" ->
"Organisaties", check:l10n-js PASS.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…760)

This app already has the generator and the `check:l10n-js` script; it just
never ran them in CI. That is the whole difference between an app that stays
translated and one that quietly stops.

Adding a key to l10n/<locale>.json and forgetting the .js is invisible without
this check: the server renders Dutch, the browser renders English, and every
other check passes. `l10n/<locale>.json` is read server-side by PHP; the
browser only ever sees `OC.L10N.register(...)` from `l10n/<locale>.js`, loaded
as a script tag.

Measured across the fleet today: the apps running this check had zero drift,
while the four without it had accumulated 142, 329, 257 and 1,090 unreachable
entries between them. Same code, same generator. The check was the difference.

It also caught a translation PR that merged green having changed nothing a
browser loads, which is how the whole thing started.

Appended to the existing frontend-checks list rather than replacing it, so
every check this repo already runs still runs.

Verified before pushing: the workflow YAML still parses, and
`node scripts/build-l10n-js.js --check` exits 0 on this tree, so the new leg is
green on arrival rather than red for someone else to clean up.
* fix(deps): development cannot npm install

* fix(deps): rebase the lock on development's, not a from-scratch resolve

The previous commit deleted package-lock.json before installing. That
turns a five-package pin into a full re-resolution: on pipelinq it moved
172 package versions, added 64 and removed 132, when five were intended.

One of those unintended moves broke boot. dexie went 4.4.4 -> 4.4.5, and
@conduction/nextcloud-vue's published dist BUNDLES its own dexie copy, so
the app loaded two and Dexie throws at module load:

  pageerror: Two different versions of Dexie loaded in the same app:
             4.4.5 and 4.4.4

The E2E boot gate caught it -- "the bundle loaded but rendered nothing" --
while build, lint, stylelint and unit tests were all green. A passing
build says nothing about whether the app mounts.

Starting from development's lock and letting npm move only what the
manifest forces cuts the change to 85/17/46 and leaves dexie alone.

Control: development's own E2E run is 309 passed / 1 failed with no
dexie pageerror and no boot-gate failure, so the breakage was mine.

---------

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Untracked:
  build.log
  changed.tsv
  inst.log
  lint.log
  stylelint.log
  t2.log
  test_unit.log
#764)

The App Store keys everything on the app id, so renaming <id> to stackiq made
it a brand new store entry starting from nothing. The release workflow
derives its version baseline from the git tags and info.xml of THIS repo,
neither of which knows anything about what shipped as softwarecatalog -- so the
version line restarts below it. filinq was about to publish 0.0.40 while
docudesk sits at 0.1.0-beta.3 on the store.

The store has no version ordering rule (_check_permission validates
existence and ownership only), so that uploads with a 200 and is then
never offered to anyone already on the higher version.

previous-app-id folds the old entry's published versions into the
baseline, so the renamed app picks the line up instead of restarting it.
* feat(demo): generated demo data for every schema (ADR-111 rules 1-2)

This app declares schemas and shipped no demo data, so it opened on an empty
list: the person evaluating it had to author objects by hand against a schema
they did not know yet. Fleet-wide, 562 of 598 schemas were in that state.

🔴 GENERATED, NOT WRITTEN. Every value is derived from the schema that will
validate it — `enum` picks from the enum, `pattern` is satisfied, `format`
drives the shape, `minimum`/`maxLength` are honoured, `required` is always
populated. Hand-written demo data is wrong in a way nobody sees until the demo
(a status outside its own enum, a required field omitted) and it fails at
import, in front of whoever asked for the demo.

Produced and validated by the single file gate-99 also runs:
`vendor/conduction/hydra-gates/scripts/lib/generate_mock_register.py`.
`--keep` preserves curated objects and tops up only what is short.

🔴 IT DOES NOT INSTALL ITSELF (ADR-111 rule 3). `x-openregister.type: mock` is
imported ON DEMAND — sample data appearing on a production instance because
somebody upgraded is a data-integrity incident, not a convenience:

    occ openregister:descriptors:list --app=<app> --import=<register>

The setup-wizard step offering this on first run (ADR-111 rule 4, gate-100)
follows once OpenRegister's shared installer lands — deliberately not
twenty-one copies of the same logic.

Verified: `--check` re-validates every object against its own schema with
jsonschema and reports zero findings.

* fix(demo-data): attribute the descriptor to the app id, not the directory

`x-openregister.app` is what the descriptor inventory resolves a register to
an app by, and the generator was writing the CHECKOUT DIRECTORY name into it —
naming an app that does not exist. A cross-app id is a runtime lookup: it
finds nobody rather than erroring. The file is renamed to match and the
directory-named one removed, so exactly one mock descriptor remains.

---------

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
#777)

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
…779)

The skip-discipline gate now runs here (hydra-gates 1.10.0, #777) and
reports three V3 findings — exclusions with no reason recorded:

    1  workflows/crud-persistence.spec.ts
    1  workflows/org-export-workflow.spec.ts
    1  workflows/organisatie-crud.spec.ts

All three DO have a reason. None of them are where a machine can see it:

  - crud-persistence  : a twelve-line comment above the test
  - org-export        : in the test title, in parentheses
  - organisatie-crud  : in the test title, in parentheses

The gate reads report.json, and `test.fixme(title, fn)` records no
description there. A title is not an annotation, and a comment is
invisible to every tool.

So each reason moves into `test.fixme(true, '<reason>')` and the titles
lose the parenthetical, which is what a title should look like anyway.

Nothing about what runs changes: the same three tests are still excluded,
for the same documented reasons. They are simply attributable now, which
is the whole point of turning the gate on.

Verified: npm ci rc=0, npm run lint rc=0 (0 errors), prettier clean, and
`playwright test --list` compiles all 14 tests across the three files.

Part of ConductionNL/.github#609.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
* refactor(manifest): the flow pages are an index and a flow

`flows` and `flow-detail` are deprecated aliases. `flows` predates named index
sources: a flow lives in OpenRegister's native flow table rather than a
register/schema pair, so an object-backed index had nothing to bind to and the
list needed a page type of its own. `config.entitySource` closes that, so the
list is an ordinary `index` and only the EDITOR still needs its own type, now
named `flow`.

Behaviour is unchanged - both aliases resolve to the same components. The list
page's `_note` is updated in the same commit: it asserted the old rationale
(that an index "cannot address" a flow), which this change disproves.

`config.app` is untouched and is load-bearing: the editor stamps it on a flow
created there and the index filters on it.

Requires @conduction/nextcloud-vue 2.21, where a named source's columns and
create button are actually read.

* fix(deps): nextcloud-vue 2.20.1, whose manifest schema knows the flow page type

check:manifest failed on this PR with

    [validate-manifest] schema.version: 2.25.0
    Ajv validation: FAIL
      - /pages/N/type must be equal to one of the allowed values (keyword=enum)

This PR declares a `type: "flow"` page. That type entered the manifest
schema at 2.26.0, which ships in @conduction/nextcloud-vue 2.20.1
(published today 20:33). The app locked 2.19.0, which carries schema
2.25.0 and has no `flow` in its enum.

Both files move. A caret alone changes nothing — package-lock.json is
what npm ci installs, and it pinned 2.19.0.

Verified by diffing this manifest's page types against each schema enum:
against 2.26.0 nothing is rejected; against 2.25.0 exactly the new type
is, which is the failure above.

* chore(deps): bump @conduction/nextcloud-vue to ^2.21.0

The flow pages need 2.21.0: earlier releases DECLARE a named index source's
columns, create button and row actions without reading them, so the migrated
page renders a columnless table with no working create action.

The lock is the part that matters. CI installs with `npm ci`, which honours
package-lock.json and ignores how permissive the caret is — bumping the range
alone would change nothing about what actually installs.

* test(e2e): Edit lands on the detail page for a schema that has one

nextcloud-vue 2.21 brings #806: a record whose schema has a same-schema DETAIL
page is edited there, not in a modal launched from the table — the modal renders
only the schema's flat scalars and cannot express a record whose related rows
live elsewhere. CnPageRenderer sets `editOpensDetail` from
`detailPageByRegisterSchema`.

Both edit blocks in this spec waited on a dialog that no longer opens from the
index. They now go through one helper that BRANCHES: dialog if it opens
directly, otherwise follow the navigation and click the detail page's header
Edit. Which route applies is a property of the schema, not of the test, so
branching is the accurate shape rather than a relaxed one — the helper still
returns a real, visible edit dialog and every assertion after it is unchanged.

---------

Co-authored-by: Ruben van der Linde <juan.claude@conduction.nl>
Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
… to build one (#765)

* feat(walkthrough): show where flows are edited, without asking anyone to build one

This app ships a Flows page and its getting-started tour never mentions it, so
the automation surface is reachable only by someone who already knows it is
there. Measured across the fleet: 19 apps declare a walkthrough, 12 ship a
flows page, and exactly one tour mentioned flows at all.

The stop is deliberately view-only. `allowManualNext` with a `route-match`
advance and `optional: true` means it points at the surface and lets the user
walk past it — nothing here gates the tour on having built a flow, which is the
difference between showing someone where something lives and making them do it
before they may continue.

`manifest.version` gets a minor bump because that is what `sinceVersion` is
compared against: a returning user whose recorded seen-version equals the old
manifest version would otherwise never be shown the new step.

* chore(l10n): translate the three strings the Flows walkthrough stop adds

Every string the tour puts on screen is user-facing. Dutch is written rather
than machine-produced; "Flows" stays "Flows", which is what the existing
catalogue already does for the term.

Worth noting for whoever picks this up: this app's `tests/l10n/check-l10n.js`
does NOT scan `src/manifest.json`, so it reported OK for these keys before they
existed in any catalogue. The gate passed because it did not look, not because
the strings were covered — every menu label, page title, setup step and tour
line in the manifest is currently outside its scope. Only dossiq's copy of the
checker reads the manifest.

* chore(l10n): rebuild the browser catalogues so the new strings actually ship

`l10n/*.json` is the source; `l10n/*.js` is what the browser loads. Adding the
three tour strings to the JSON left the built catalogues stale, so the strings
existed in the repo and reached no user — the exact shape of the 2026-08-24
finding where nine apps shipped 8,137 translations no browser ever received.

`npm run check:l10n-js` catches it (`Stale browser catalogue: l10n/en.js,
l10n/nl.js`), which is why the gate exists. This is `npm run l10n:build` and
nothing else.

* fix(walkthrough): target the flows entry by ROUTE, which is what resolves

CnWalkthrough.resolveTarget() looks a nav-item target up as
`[data-cn-route="<ref>"]`, and CnAppNav sets that attribute from `item.route`.
The step was authored with the MENU id (FlowsMenu), which matches nothing, so
it fell back to a centred anchorless coachmark instead of pointing at the entry.

Easy to miss because every tour step in this fleet that works today targets an
entry whose menu id happens to EQUAL its route (Cases, MyWork). FlowsMenu ->
Flows is the first place they differ.

Verified against the live DOM: [data-cn-route="Cases"] resolves,
[data-cn-route="FlowsMenu"] does not.

* fix(copy): no em-dash in the tour copy, per voice.md section 8

gate-96 (manifest-copy-style) caught it: "Em-dashes and double-dashes are AI
tells. Replace with a period, a comma, or a colon." The Flows stop's body ended
"...read and edit them — nothing to build now."; it now ends with a full stop
and a short sentence, which is what the rule asks for and reads no worse.

The English string is the l10n KEY, so the catalogues are re-keyed in the same
change and the browser .js rebuilt. Leaving the key behind would have made the
string untranslated in every locale while the catalogue still claimed to cover
it. The Dutch value drops its em-dash too, for the same reason the English one
does.

Verified per app with the script that app's own CI runs (test:l10n or
check:l10n), plus check:l10n-js, plus schema validation of the manifest.

* build(deps): take @conduction/nextcloud-vue 2.21.0 so the Flows stop anchors

The `see-flows` stop added by this PR targets a nav item in the SETTINGS
section. CnAppNav emitted `data-cn-route` on its main, child and footer
loops but not the settings one, so the stop resolved nothing — and
CnWalkthrough.armStep() SKIPS an optional step whose target is absent,
with no console error and nothing on screen:

    const el = this.resolveTarget(this.step)
    if (!el) { if (this.step.optional) { this.wt.skip(); return } }

`optional: true` is exactly what keeps the stop from forcing anyone to
build a flow, so the friendly authoring choice is also the one that fails
silently. Without this bump the step ships and reaches nobody.

The caret range does not decide this: `npm ci` installs from
package-lock.json, and that was pinned at 2.19.0, which predates the fix
(nextcloud-vue#811). 2.21.0 was verified by unpacking the published
tarball — data-cn-route appears 4 times, one inside the
`v-for="item in settingsItems"` template.

* test(e2e): Edit opens the detail page, so the dialog is one click further

@conduction/nextcloud-vue 2.21.0 makes the index row's Edit action navigate
to the record's detail page instead of opening a modal over the list. That
is the intended fleet rule: a record with its own detail page is edited
there, where its nested collections are reachable, rather than through a
dialog that shows only the schema's flat scalars.

These two tests asserted the old shape and so failed with "element(s) not
found" on `getByRole('dialog')` — the dialog was never going to appear,
because the click now routes. The edit form still exists; it is reached
from the detail page's Edit button (`cn-detail-page-edit`, gated on
canEditRecord).

Everything the tests actually check — the title field, the absence of a
scheduledDate format alert, the save round-trip — is unchanged.

* test(e2e): return to the index before asserting the edit landed in the list

Follow-up to the detail-page edit route. The first of these two tests
passed once the extra click was added; this one still failed, for a
different reason.

It edits the record and then asserts the new job title is rendered as a
row in the Table view. That assertion assumed the edit happened in a modal
OVER the list, so the list was still on screen when it ran. It is not: the
row's Edit action routes to the record's detail page, the save happens
there, and the page never goes back on its own.

Without the return trip the assertion runs against the detail page and
fails as "row not found" — which reads like the save not persisting rather
than the test standing on the wrong page.

---------

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Co-authored-by: Ruben van der Linde <juan.claude@conduction.nl>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Adds `stackiq-compose.yaml` and a setup page describing it.

The compose brings up Postgres and Nextcloud, installs openregister (required),
thematiq and integriq (optional) and stackiq from release tarballs, and enables
them in dependency order. Nothing is bind-mounted: Nextcloud installs an app by
deleting its directory and extracting an archive over it, so pointing that at a
checkout deletes the working tree — measured on a development machine on
2026-08-27, where an app-store update fired on a container restart and removed
every top-level file including .git.

Release tarballs rather than a clone for a second reason: a tarball is a
complete app carrying vendor/ and the built js/, and an app with no vendor/
does not fail loudly — it warns once and keeps loading, so it looks installed
while every service needing a dependency is absent.

The openregister dependency is not declared in appinfo/info.xml — no app in the
fleet declares an <app> dependency — so the compose encodes what the manifest
does not.

Verified: docker compose config parses and interpolates; the same generated
file was booted end to end for portaliq, which produced 17 registers, 86
schemas and 13 magic tables for its own register, with the portal content API
returning a real site rather than an empty shell.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
#785)

* feat(setup): a wizard that offers the demo data this app already ships

This app ships lib/Settings/*_mock_register.json - a dataset generated from its
own schemas, conformant by construction, validated by the generator's --check -
and had no way for an operator to reach it. There was no setup wizard at all.

welcome -> demo-data -> done. Nothing app-specific is invented: the only action
is the demo-data import the descriptor already supports. A wizard that asked
questions the app does not act on would be worse than none, which is why there
are no configuration steps here yet.

completed is TRUE and the demo-data step is optional, so setup never gates the
app. skip-demo-data records its outcome just as installing does: since
nextcloud-vue 2.21 an OUTSTANDING OPTIONAL step opens the wizard over every
page (nextcloud-vue#806), so a step that can never be marked done is a dialog
that never closes - the defect buildiq was failing 37 E2E specs on.

Verified: manifest validates against schema 2.26.0, gate-100 PASS, routes.php
and both PHP files parse. The template was checked on launchpad against phpcs,
phpstan, psalm and phpmd - all clean.

* fix(setup): declare the endpoints' auth, and translate the wizard's strings

Two gate findings on the previous push.

gate-5 route-auth — status() and runAction() carried no auth attribute. The
docblock said 'admin-only by Nextcloud's default for an un-attributed method',
which is true and is not a declaration: the gate exists because a missing
attribute silently makes an endpoint unreachable, and a comment cannot be
checked by middleware. Both now carry
#[AuthorizedAdminSetting(Application::APP_ID)], placed DIRECTLY above the
declaration - gate-5 walks upward from the method and a long docblock between
attribute and declaration costs the attribute its visibility, which the gate
documents as a false FAIL it had to repair.

gate-102 manifest-l10n-coverage — the wizard's title and body strings had no
l10n/nl.json key, so a Dutch user would read them in English. Added, and the
browser catalogue rebuilt where the app ships one: nl.json alone is not enough,
because the browser reads nl.js.

The catalogue edit is insertions only, proven against the same change applied
structurally - an earlier attempt on another app re-serialised the whole file
(410 lines) before being reverted.

* fix(setup): authorize against the admin settings class, and test what it guards

`AuthorizedAdminSetting` takes a `class-string<IDelegatedSettings>`, not an
app id, so `Application::APP_ID` — a plain string — was rejected by phpstan.
The apps where this shipped green (larpinq, shillinq) already pass their admin
settings class; match them.

gate-47 and the coverage ratchet were both right to fail this. The change adds
an admin-authorized endpoint pair and ~364 lines of PHP with nothing behind
them. Two assertions are worth naming:

- a FAILED install must leave the step UNDECIDED. Recording the decision in
  the catch block would close the step for an operator who asked for demo data
  and received none.
- the object count comes from the FILE, not the importer's reply, so the
  number reported is the number ASKED FOR.

Both verified by mutation on openregister: reversing each behaviour fails
exactly the test that claims to guard it. The e2e spec issues both calls from
inside the logged-in admin page, which is the only place that middleware can
be observed admitting a real session.

---------

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

The ADR-111 setup step is OPTIONAL, and CnAppRoot opens the non-gating wizard
as a full modal mask while any optional non-info step is reported not-done —
in every fresh browser context, so once per spec. Merging the setup wizard
therefore turned this app's whole E2E suite red without touching a single
spec: the call log reads "locator resolved to <button ...> - attempting click
action" with <ol class="cn-wizard-dialog__progress"> named as the interceptor.
The element was found; the click never landed.

SKIPPED rather than installed, because recording the DECISION is what closes
the wizard. Installing would push the app's demo dataset into every list the
suite asserts on, which changes what the other specs measure.
`demo-data-setup-step.spec.ts` exercises the install deliberately, in
isolation.

Uses the workflow's own exported credentials rather than this script's
internals, and is tolerant of a non-200: an app whose wizard has no demo-data
step answers 400, and that is not a seeding failure.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
2.22.1 carries the theme app-id fix (nextcloud-vue#840). CnAppRoot calls
useScopedTheme() with no slug, so this app resolved theme tokens, the
token-set catalogue and the contrast check through a hardcoded 'nldesign'
app id. thematiq is renaming to 'thematiq', and every path in that
composable degrades to default styling by design — so once a renamed build
is installed this app would render unthemed with nothing in any log.

The LOCK is what moves here. A caret range alone changes nothing, because
npm ci installs what package-lock.json pins.

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

@conduction/nextcloud-vue 2.22.x made the product walkthrough actually open.
A `placement: "center"` welcome step used to be parked in `_pendingAutoTour`
and never shown; the library now correctly starts it on any route. Its
`cn-walkthrough__dim--full` layer is a `role="dialog" aria-modal="true"`
overlay, so every spec that clicks behind it times out, and
`getByRole('dialog').first()` resolves to the dim layer rather than the
modal under test.

The marker is per USER, not per test, so leaving it unseeded also makes the
suite order-dependent: whichever spec runs first wears the tour.

Seeds the same marker dossiq's global-setup already seeds, with a sentinel
above any real app version so the tour composes to an empty step set.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Two independent faults, either of which alone stops the docs site updating.

TRIGGER. This listened on a branch called `documentation`. Nobody has pushed
to one since 2026-05-25, so every docs change merged to `development` passed
review and published nothing.

SECRETS. A reusable workflow receives no secrets by default. With none mapped,
the callee's publish step finds CF_API_TOKEN empty and skips itself on its own
guard, and the run finishes GREEN having changed nothing. Fixing only the
trigger would have produced exactly that.

The worker name is now pinned. Deriving it is the documented way to get a green
run that reaches nobody: wrangler creates the derived worker and publishes
there while the custom domains keep routing to the real one.

Where the app was renamed, `canonical-host` turns the retired hostname from a
second live copy of every page into a 301 to the same path on the current one.

Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
Bumps [stylelint-config-html](https://github.com/ota-meshi/stylelint-config-html) from 1.1.0 to 2.0.0.
- [Release notes](https://github.com/ota-meshi/stylelint-config-html/releases)
- [Changelog](https://github.com/ota-meshi/stylelint-config-html/blob/main/CHANGELOG.md)
- [Commits](ota-meshi/stylelint-config-html@v1.1.0...v2.0.0)

---
updated-dependencies:
- dependency-name: stylelint-config-html
  dependency-version: 2.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [webpack](https://github.com/webpack/webpack) from 5.109.2 to 5.110.1.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Changelog](https://github.com/webpack/webpack/blob/main/CHANGELOG.md)
- [Commits](webpack/webpack@v5.109.2...v5.110.1)

---
updated-dependencies:
- dependency-name: webpack
  dependency-version: 5.110.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) from 3.2.7 to 4.1.11.
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.11/packages/coverage-v8)

---
updated-dependencies:
- dependency-name: "@vitest/coverage-v8"
  dependency-version: 4.1.11
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 20.19.43 to 26.4.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 26.4.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
)

Bumps [node-polyfill-webpack-plugin](https://github.com/Richienb/node-polyfill-webpack-plugin) from 4.0.0 to 4.1.0.
- [Release notes](https://github.com/Richienb/node-polyfill-webpack-plugin/releases)
- [Commits](Richienb/node-polyfill-webpack-plugin@v4.0.0...v4.1.0)

---
updated-dependencies:
- dependency-name: node-polyfill-webpack-plugin
  dependency-version: 4.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [nextcloud/ocp](https://github.com/nextcloud-deps/ocp) from 34.0.2 to 34.0.3.
- [Commits](nextcloud-deps/ocp@v34.0.2...v34.0.3)

---
updated-dependencies:
- dependency-name: nextcloud/ocp
  dependency-version: 34.0.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
dependabot Bot and others added 17 commits August 30, 2026 09:59
Bumps [vue-draggable-plus](https://github.com/Alfred-Skyblue/vue-draggable-plus) from 0.2.7 to 0.6.1.
- [Release notes](https://github.com/Alfred-Skyblue/vue-draggable-plus/releases)
- [Commits](https://github.com/Alfred-Skyblue/vue-draggable-plus/commits/0.6.1)

---
updated-dependencies:
- dependency-name: vue-draggable-plus
  dependency-version: 0.6.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.9.3 to 7.0.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Commits](microsoft/TypeScript@v5.9.3...v7.0.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 7.0.2
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…811)

Bumps [squizlabs/php_codesniffer](https://github.com/PHPCSStandards/PHP_CodeSniffer) from 3.13.6 to 4.0.4.
- [Release notes](https://github.com/PHPCSStandards/PHP_CodeSniffer/releases)
- [Changelog](https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/4.x/CHANGELOG-3.x.md)
- [Commits](PHPCSStandards/PHP_CodeSniffer@3.13.6...4.0.4)

---
updated-dependencies:
- dependency-name: squizlabs/php_codesniffer
  dependency-version: 4.0.4
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…810)

Bumps [phpcsstandards/phpcsextra](https://github.com/PHPCSStandards/PHPCSExtra) from 1.5.0 to 1.5.1.
- [Release notes](https://github.com/PHPCSStandards/PHPCSExtra/releases)
- [Changelog](https://github.com/PHPCSStandards/PHPCSExtra/blob/develop/CHANGELOG.md)
- [Commits](PHPCSStandards/PHPCSExtra@1.5.0...1.5.1)

---
updated-dependencies:
- dependency-name: phpcsstandards/phpcsextra
  dependency-version: 1.5.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [postcss-html](https://github.com/ota-meshi/postcss-html) from 1.8.1 to 2.0.0.
- [Release notes](https://github.com/ota-meshi/postcss-html/releases)
- [Commits](ota-meshi/postcss-html@v1.8.1...v2.0.0)

---
updated-dependencies:
- dependency-name: postcss-html
  dependency-version: 2.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…807)

Bumps [caniuse-lite](https://github.com/browserslist/caniuse-lite) from 1.0.30001806 to 1.0.30001810.
- [Commits](browserslist/caniuse-lite@1.0.30001806...1.0.30001810)

---
updated-dependencies:
- dependency-name: caniuse-lite
  dependency-version: 1.0.30001810
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan-phar-composer-source) from 2.2.8 to 2.2.9.
- [Commits](https://github.com/phpstan/phpstan-phar-composer-source/commits)

---
updated-dependencies:
- dependency-name: phpstan/phpstan
  dependency-version: 2.2.9
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [adbario/php-dot-notation](https://github.com/adbario/php-dot-notation) from 3.3.0 to 3.5.0.
- [Release notes](https://github.com/adbario/php-dot-notation/releases)
- [Commits](adbario/php-dot-notation@3.3.0...3.5.0)

---
updated-dependencies:
- dependency-name: adbario/php-dot-notation
  dependency-version: 3.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 7.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v4...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [phpmetrics/phpmetrics](https://github.com/phpmetrics/PhpMetrics) from 2.9.1 to 2.11.0.
- [Release notes](https://github.com/phpmetrics/PhpMetrics/releases)
- [Changelog](https://github.com/phpmetrics/PhpMetrics/blob/master/CHANGELOG.md)
- [Commits](phpmetrics/PhpMetrics@v2.9.1...v2.11.0)

---
updated-dependencies:
- dependency-name: phpmetrics/phpmetrics
  dependency-version: 2.11.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [twig/twig](https://github.com/twigphp/Twig) from 3.27.0 to 3.28.0.
- [Release notes](https://github.com/twigphp/Twig/releases)
- [Changelog](https://github.com/twigphp/Twig/blob/3.x/CHANGELOG)
- [Commits](twigphp/Twig@v3.27.0...v3.28.0)

---
updated-dependencies:
- dependency-name: twig/twig
  dependency-version: 3.28.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* feat(nav): a Flows surface in this app, on the shared page types

ADR-110 Decision 4. A flow is app-specific — it operates on this app's objects —
so the authoring surface belongs here rather than behind a deep link to another
app's list. The ENGINE stays single (ADR-065): these pages are a scoped view
onto OpenRegister's one native flow store, not a per-app store.

Two manifest pages and one settings entry, no component files: `type: "flows"`
and `type: "flow-detail"` are shipped page types in @conduction/nextcloud-vue
2.19.0, scoped by `config.app`.

Note the layout of the diff: entries are appended textually rather than by
reserialising the manifest. A `json.dump` round-trip rewrote pipelinq's file as
a 3,950-line diff for a 20-line addition — correct output, unreviewable change.

* build(deps): @conduction/nextcloud-vue 2.19.0 for the flows page types

Required by the manifest change: `type: "flows"` / `type: "flow-detail"` are
rejected by the compiled validator in earlier versions, and CI installs with
`npm ci` — so the LOCK is what decides, not the `^2.x` range. Several of these
locks were pinned many minors back, which is why some lockfile diffs are large:
npm restructures the nested tree (mostly @esbuild platform binaries under
@nextcloud/vue) to satisfy 2.19.0's peers. No direct dependency other than
@conduction/nextcloud-vue changes.

* fix(icons): register Sitemap, or the Flows entry renders with no icon

An icon name a manifest uses but src/icons.js does not register renders as
NOTHING — not a fallback (ADR-077 rule 3). The Flows menu entry this PR adds
uses `Sitemap`, and this app never registered it, so the entry would have
shipped with an empty icon slot.

Caught by gate-60 icon-vocabulary. I had checked `Sitemap` was registered in
dossiq and carried the assumption to the fleet; each app keeps its own icons.js,
and six of the twelve did not have it. The six failing gate runs were exactly
those six apps.

Both halves are required: the import alone is dead code, the registry entry
alone does not resolve.

* feat(flows): give the flow-detail canvas its sidebar

The manifest _note claimed the controls rendered in the NC app sidebar,
but the sidebarComponent field it described did not exist. Every
#/flows/:id -- and #/flows/new, the same route with the literal id -- drew
a bare canvas: savable and runnable, but with no way to name, describe,
trigger or step-edit the flow, because those controls all live in
CnFlowSidebar. Mirrors pipelinq#1490. ADR-110 Decision 4.
beta held 13 commit(s) development did not. Version files were
resolved to development's side so the version never moves backwards --
the same rule release.yml applies to its own post-release sync.

Recording the ancestry is the payload: without it the merge base never
moves and the next development -> beta promotion conflicts on the version
file exactly as before.
…260830084142

chore(sync): carry beta back into development
…2608300839

chore(sync): record beta's ancestry on development
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor Author

Quality Report — ConductionNL/stackiq @ 5497eab

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-30 09:04 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