App health
Live Code Quality status for every Conduction Nextcloud app, on each of the
three branches it ships through. Badges come straight from GitHub Actions and
update themselves — click one to open that branch's runs.
Nextcloud apps
Every app is checked by the same Code Quality workflow. Category is the
role an app plays in the fleet; Type is its domain.
| App | Category | Type | Latest release | main | beta | development |
|---|---|---|---|---|---|---|
| decidiq | Application | Decision-making | 2026-08-17 | |||
| filinq | Application | Documents | 2026-08-17 | |||
| larpinq | Application | LARP management | 2026-08-17 | |||
| opencatalogi | Application | Catalogue | 2026-08-10 | |||
| pipelinq | Application | CRM | 2026-08-18 | |||
| portaliq | Application | Client portal | 2026-08-17 | |||
| dossiq | Application | Case management | 2026-08-17 | |||
| learniq | Application | LMS / LVS | 2026-08-18 | |||
| shillinq | Application | Business admin | 2026-08-17 | |||
| stackiq | Application | Catalogue | 2026-08-17 | |||
| humaniq | Application | HR & payroll | 2026-08-12 | |||
| launchpad | Framework | Dashboards | 2026-08-08 | |||
| buildiq | Framework | Low-code builder | 2026-08-17 | |||
| thematiq | Framework | Design system | 2026-08-17 | |||
| keepiq | Platform | Secrets management | 2026-08-18 | |||
| hermiq | Platform | AI / agents | 2026-08-18 | |||
| integriq | Platform | Integration / ESB | 2026-08-18 | |||
| openregister | Platform | Object store | 2026-08-10 | |||
| versioniq | Tooling | App lifecycle | 2026-08-12 | |||
| nextcloud-app-template | Scaffold | Project template | 2026-04-13 |
Deprecated apps
Still in the repository and still building, but not being taken forward. They stay listed because a deprecated app that disappears from the dashboard becomes an app nobody is measuring. Red here is informational: check whether the work is wanted before greening a row in this table.
| App | Category | Type | Latest release | main | beta | development |
|---|---|---|---|---|---|---|
| planninq | Application | Project management | 2026-08-03 | |||
| zaakafhandelapp | Application | Case management | 2024-10-23 |
Renaming
Apps are being renamed onto a common suffix. Both names appear in the wild
during a rename — the repository, the appinfo/info.xml id, the OpenSpec
directory and the App Store listing do not all move on the same day — so this
table is the mapping of record.
⚠️ A rename is a data migration, not a find-and-replace. The app id appears
in appinfo/info.xml, route names, OpenRegister register slugs, app-config
keys, and any object already written under the old id. Renaming the repository
alone leaves live data pointing at a name nothing answers to.
Renaming an app is the procedure: the three phases, which stores the app id keys, the repair steps that carry data across, and the per-user preference that reverts silently if you forget it.
| Old name | New name | Status |
|---|---|---|
mydash | launchpad | done — the mydash repo is archived; treat any surviving reference as stale |
scholiq | Learniq | repo renamed — app id pending |
nldesign | Thematiq | repo renamed — app id pending |
hrmq | Humaniq | repo renamed — app id pending |
decidesk | Decidiq | repo renamed — app id pending |
larpingapp | Larpinq | repo renamed — app id pending |
openbuild | Buildiq | repo renamed — app id pending |
procest | Dossiq | repo renamed — app id pending |
docudesk | Filinq | repo renamed — app id pending |
doriath | Keepiq | repo renamed — app id pending |
softwarecatalog | Stackiq | repo renamed — app id pending |
openconnector | Integriq | repo renamed — app id pending |
app-versions | Versioniq | repo renamed — app id pending |
planix | Planninq | repo renamed — app id pending; repo is in deprecated in fleet-apps.json. Not Planiq: that name collides with Anaplan's trademarked PlanIQ™, so the -inq form was taken instead |
OpenAnonymiser | Anonymiq | repo renamed — app id pending |
financeq | Accountinq | planned |
purchaseq | Purchasinq | planned |
Unchanged by decision (2026-08-21): launchpad, pipelinq, shillinq (the
coin, never "Shellinq"), hermiq, portaliq, openregister, opencatalogi,
openwoo, nextcloud-vue, nextcloud-app-template, and the ExApp sidecars.
zaakafhandelapp and deskdesk are discontinued and get no new name.
Until a row reads done, the old name is the one that resolves — the badges
above and every gh command still use it.
Libraries
Not Nextcloud apps, but every app depends on them, so a regression here reaches the whole fleet.
| Repository | Package | Kind | Version | main | beta | development |
|---|---|---|---|---|---|---|
| nextcloud-vue | @conduction/nextcloud-vue | Vue component library | 2.4.0 | |||
| design-system | @conduction/docusaurus-preset | Docusaurus preset | 3.28.0 | no Code Quality workflow | ||
| docusaurus-plugin-portaliq | docusaurus-plugin-portaliq | Docusaurus plugin | — | no Code Quality workflow | ||
| coding-standard | conduction/coding-standard | PHP coding standard | — | no Code Quality workflow | ||
| .github | conduction/hydra-gates | Quality gate suite | — | no Code Quality workflow |
Only nextcloud-vue runs the shared Code Quality workflow. The other four
are checked by their own workflows or not at all — which is worth knowing
before treating a blank cell as healthy.
⚠️ @conduction/docusaurus-preset still declares a Codeberg repository URL
in its npm metadata. Codeberg is retired; the live source is
ConductionNL/design-system.
Lifecycle and support
Every app release is tied to a Nextcloud version — the one current at its launch — though a release may still support lower versions. That anchor is what the support window is measured from.
| Guarantee | Window |
|---|---|
| Bug fixes | 2 years |
| Security fixes (CVE) | 5 years |
When a release happens relative to Nextcloud
The fleet runs two-week phases, so a beta is always one phase ahead of its stable release.
| Category | Stable release | Beta available |
|---|---|---|
| Platform apps | the day Nextcloud releases | 2 weeks before the Nextcloud release |
| Application apps | the week after Nextcloud releases | 1 week before the Nextcloud release |
Platform apps go first on purpose: application apps are thin clients over
openregister and openconnector, so the layer underneath has to be on the new
Nextcloud version before the layer above can be.
Application releases are normally minor — a new Nextcloud version is not by itself a reason for a breaking change.
A five-year CVE window tied to a launch-time Nextcloud version means an app released today is still receiving security fixes long after that Nextcloud version leaves upstream support. Check the anchor version before assuming an old install is out of scope: the app's clock started at its launch, not at Nextcloud's end-of-life.
Friday automation
Every Friday at 08:00 Europe/Amsterdam, per app:
- Merge outstanding
developmentpull requests whose checks are fully green - Open
development → beta; when green, merge it - Release
Green means green. Not parity with a red base, not "only the usual failures" — a pull request merges unattended only when every check has a verdict and none of them failed. A pending check is not a pass, and an unreadable response is not a pass either; both mean skip and report.
Anything the routine skips is logged with its reason. A silent skip is indistinguishable from a merge that happened, and a routine you cannot audit is a routine you cannot trust to run while nobody is watching.
⚠️ The clock is UTC. GitHub cron has no time-zone support, so 08:00 Dutch is
06:00 UTC in summer and 07:00 UTC in winter. A fixed cron drifts an hour
twice a year; the schedule is set in UTC and the job checks local time before
acting, rather than pretending the drift does not exist.
Status: built, and blocked on one secret. This section described intent rather than behaviour for long enough that someone read the page and reasonably believed the fleet was being merged every Friday. It is now three workflows, each of which refuses loudly rather than reporting a routine that measured nothing:
| workflow | Friday (UTC) | what it does |
|---|---|---|
fleet-drift-sweep.yml | 06:00 | re-runs Code Quality on development for every app, and fails when any app is not green |
fleet-cve-release.yml | 06:30 | merges Dependabot security fixes, classified against GitHub's own alerts |
fleet-friday-merge.yml | 07:00 | merges development pull requests that are genuinely green |
⚠️ None of them can run until FLEET_DISPATCH_TOKEN exists. It is an
org-level secret needing contents: write, pull-requests: write and
security-events: read on every repo in fleet-apps.json; GITHUB_TOKEN is
repository-scoped and cannot reach another repo. All three assert it first and
exit 1 — verified by dispatching them, which failed at exactly that step with
everything downstream skipped.
Two things are deliberately not automated, and are gaps rather than oversights:
- Promotion past
development. Shipping a CVE by promotingdevelopment → beta → mainwould release the whole unreleased backlog — measured 2026-08-19, openregister'sdevelopmentis 3,238 commits ahead ofbetaand 5,454 ahead ofmain. One dependency bump would carry thousands of unreviewed functional commits through the protection this is allowed to cross only for CVEs. - Release. It waits on a dry run being read against real pull requests. An unattended release is not where you discover that a lockfile cherry-pick conflicts.
The merge routine would not have caught gate drift
Merging green pull requests is not the same as knowing the fleet is still compliant, and it is worth being explicit about why.
A green badge is a verdict about a moment, not a state. The gates are
consumed at @main, so a stricter gate reaches every app the instant it merges
— but a gate only produces a verdict when a workflow runs, and app workflows
run on push and pull_request only. An app nobody has touched keeps the green
badge it earned under the old gates. Tighten a gate on Friday and the fleet is
non-compliant and green at the same time, until somebody happens to push.
Measured 2026-08-19: of 21 swept apps, exactly one (pipelinq) had any scheduled run at all. The other twenty could only be re-measured by hand.
So a separate fleet drift sweep re-runs Code Quality on development for
every app, Fridays at 06:00 UTC — .github/workflows/fleet-drift-sweep.yml,
iterating fleet-apps.json.
⚠️ It cannot be a cron inside each app, and the reason is easy to get wrong.
GitHub runs a scheduled workflow from the repository's default branch and
gives you no way to choose a ref. The fleet's defaults are split — measured
2026-08-19, 11 apps default to development and 10 to main — so copying
pipelinq's cron everywhere would measure main on ten of them. main is
stale-red across much of the fleet, so those ten would go red for reasons that
have nothing to do with drift. workflow_dispatch does take a ref, which is
why the sweep is central and passes --ref development explicitly.
🔴 The badges above cannot see the sweep — read the sweep run instead
The sweep's first draft stopped at dispatching, on the reasoning that each app's own Quality Report decides and the badges above show the result. Measured 2026-08-19, that is false, and it matters: it would have rebuilt the same silent failure one layer down.
Every badge on this page carries &event=push:
…/code-quality.yml?branch=development&event=push&label=development
A sweep produces workflow_dispatch runs, so shields.io does not look at them
at all — the badge keeps showing the last push verdict. Positive control on
pipelinq/development, which proves the filter is live rather than inert:
| Query | Newest run it sees |
|---|---|
?branch=development&event=push | push — success |
?branch=development | pull_request — failure |
So an app could fail every gate in the Friday sweep and stay green on this page.
Dropping &event=push is not the fix. Unfiltered, the newest run on a
branch is frequently a pull_request run of a PR merge ref — a verdict about a
proposal, not about the branch, exactly as the control above shows.
Instead the sweep's collect job waits for every dispatched run and fails
when any app is not success, with a per-app table in its run summary. One red
run covers the whole fleet, and — unlike a badge — it cannot go green by having
measured nothing: cancelled, no run appeared and still running at deadline
are each reported as red, never folded into a pass.
A second badge column keyed on event=workflow_dispatch is the natural
follow-up (an app with no dispatch run renders a grey no status, not a false
red — verified against nextcloud-app-template, which has none). It is not
added yet: every app already carries unrelated manual dispatch runs —
openregister's newest is from 2026-08-11 and failed — so the column would open
showing week-old verdicts as though they were this Friday's. Add it once the
first sweep has given every app a dispatch run that means what the column
claims.
Status: the workflow exists; it needs a token. It requires an org-level
FLEET_DISPATCH_TOKEN with actions: write on every repo in fleet-apps.json
— GITHUB_TOKEN is repository-scoped and cannot dispatch elsewhere. The job
asserts the token first and fails loudly when it is absent, rather than
being refused 21 times and reporting a green sweep that measured nothing.
Monday automation — keeping the shared dependencies current
The Friday sweep re-measures the fleet. It does not move it. Two packages every app depends on drift on their own, and nothing carried them:
| measured 2026-08-20 | available | |
|---|---|---|
conduction/hydra-gates | 17 of 17 apps on v1.8.0 | v1.8.1 |
@conduction/nextcloud-vue | 14 of 17 below 2.7.0 (12 on 2.3.0) | 2.8.2 |
⚠️ Nothing there was pinned on purpose. Both are declared with caret ranges that already permitted the newer releases. What froze them is the lockfile, which nobody re-resolves unless they happen to be touching dependencies that day. Neither number was a decision; both were the absence of one.
The cost was not theoretical. hydra-gates v1.8.0 shipped an
ObjectServiceInterface without patchObject(), and because the package
used to claim OCA\OpenRegister\Contract\ in its composer autoload — a
longer psr-4 prefix than openregister's own — a stale copy in any app's
vendor directory defined that contract for the whole instance. Measured:
softwarecatalog's vendor was supplying openregister's interface.
✅ That mechanism is gone. The prefix was removed from the package (ConductionNL/.github#531); the contracts still ship, but a consumer now opts in from its own test bootstrap behind
interface_exists(), which is order-independent. Four apps needed the opt-in — buildiq, decidiq, filinq and stackiq. The others either ship their own contract stubs (dossiq, pipelinq, shillinq), own the real one (openregister), or never reference it.
Separately, nc-vue's AI-companion singleton landed in 2.7.0, so every app below it rendered a second companion hex beside hermiq's on every page. Both fixes had existed upstream for weeks.
So a fleet shared-dependency bump runs Mondays at 05:00 UTC —
.github/workflows/fleet-shared-dep-bump.yml, iterating the same
fleet-apps.json. Monday deliberately, and earlier in the week than the sweep,
so a bump that turns an app red has the week to be noticed rather than being
discovered by Friday's measurement.
It cannot be a cron inside each app, for the same reason the sweep cannot — see above.
It opens pull requests; it does not push, and it never force-pushes
A shared bump is not always safe, and CI is what knows. Taking hydra-gates
v1.8.1 added patchObject() to a published interface, which is a load-time
fatal for any concrete test double implementing it without the method —
Class … contains 1 abstract method and must therefore be declared abstract.
The suite dies before a single test runs. Two apps needed stub updates before
they could take the bump at all. A workflow that pushed straight to
development would have broken them silently.
🔴 And it must never force-push. The first draft reused one long-lived branch per app and force-pushed it weekly. That destroys work: the PR body invites a maintainer to fix a broken bump on that branch, and the next Monday run would have overwritten the fix without a trace. So:
- if a bump PR is already open for an app, the run skips that app entirely and says so — an app already being dealt with is not a candidate;
- when it does push, it pushes a new dated branch, never a reused one.
It touches composer.lock / package-lock.json only. composer.json and
package.json are never rewritten, so a bump cannot silently widen what an app
declares it accepts.
Status: the workflow exists; it needs a wider token. It reuses
FLEET_DISPATCH_TOKEN, but needs contents: write and pull-requests: write
on the app repos where the sweep only needed actions: write. It asserts the
token first and fails loudly when it is absent; if the grant is merely too
narrow it fails at the push step, and the run summary names that as the likely
cause rather than leaving a blank row.
Release schedule
App Store on Friday, social announcement the following Monday. After the first two slots the cadence is one app every two weeks.
| Date | App Store (Fri) | Social (Mon) | Apps |
|---|---|---|---|
| Week of 17 Aug | 2026-08-21 | 2026-08-24 | openregister, keepiq, nextcloud-vue |
| Week of 24 Aug | 2026-08-28 | 2026-08-31 | hermiq, buildiq |
| +2 weeks | 2026-09-11 | 2026-09-14 | pipelinq |
| +2 weeks | 2026-09-25 | 2026-09-28 | portaliq |
| +2 weeks | 2026-10-09 | 2026-10-12 | dossiq |
| +2 weeks | 2026-10-23 | 2026-10-26 | filinq |
| +2 weeks | 2026-11-06 | 2026-11-09 | thematiq |
Every date above is a Friday, verified. The Latest release column in the
tables is the last GitHub release, which is not the same thing as an App
Store publication — an app can have shipped a dev tag today and still be
weeks from its store slot.
Not on this page, and why
Solutions, not apps. OpenWoo and openanonymiser are products assembled
from several repositories rather than a single Nextcloud app, so there is no one
Code Quality badge that represents them. OpenWoo alone spans OpenWooApp
(archived), openwoo-app-website, openwoo-app-config and the woo-website-*
family. Badging one repo of a solution would report on a part while reading as
the whole.
Archived repositories are excluded.
How this list is built
Membership comes from two checks, not from a hand-maintained list: the app
appears in the public site's apps-catalog.js, and the repository carries
appinfo/info.xml on its default branch — the canonical marker of a Nextcloud
app.
That matters. A hand-maintained fleet list previously omitted seven live apps,
and one of them carried well over a thousand outstanding gate findings while
going entirely unmeasured, because nothing swept an app that wasn't on the list.
Building this page from the catalog immediately surfaced planix, a Nextcloud
app running Code Quality that the working fleet list did not include. It is
now listed under Deprecated apps — which is the point: it went unmeasured
for months precisely because no list carried it, and "deprecated" is a reason to
record an app, not to drop it.
This page is the list of record. If an app is not on it — active, deprecated, or excluded with a reason below — it is not being measured by anybody. Add the row before you need it.
Archived repositories are excluded.