Release: merge development into beta - #90
Conversation
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (94 total)
npm dependencies (248 total)
PHPUnit TestsPHPUnit tests were not enabled for this run. Integration Tests (Newman)Newman integration tests were not enabled for this run. Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (94 total)
npm dependencies (248 total)
PHPUnit TestsPHPUnit tests were not enabled for this run. Integration Tests (Newman)Newman integration tests were not enabled for this run. Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (94 total)
npm dependencies (248 total)
PHPUnit TestsPHPUnit tests were not enabled for this run. Integration Tests (Newman)Newman integration tests were not enabled for this run. Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (94 total)
npm dependencies (248 total)
PHPUnit TestsPHPUnit tests were not enabled for this run. Integration Tests (Newman)Newman integration tests were not enabled for this run. Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (94 total)
npm dependencies (248 total)
PHPUnit TestsPHPUnit tests were not enabled for this run. Integration Tests (Newman)Newman integration tests were not enabled for this run. Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (94 total)
npm dependencies (248 total)
PHPUnit TestsPHPUnit tests were not enabled for this run. Integration Tests (Newman)Newman integration tests were not enabled for this run. Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (94 total)
npm dependencies (248 total)
PHPUnit TestsPHPUnit tests were not enabled for this run. Integration Tests (Newman)Newman integration tests were not enabled for this run. Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (94 total)
npm dependencies (248 total)
PHPUnit TestsPHPUnit tests were not enabled for this run. Integration Tests (Newman)Newman integration tests were not enabled for this run. E2E Tests (Playwright)Playwright E2E tests were not enabled for this run. Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (94 total)
npm dependencies (248 total)
PHPUnit TestsPHPUnit tests were not enabled for this run. Integration Tests (Newman)Newman integration tests were not enabled for this run. E2E Tests (Playwright)Playwright E2E tests were not enabled for this run. Generated automatically by the Quality workflow.
|
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ❌ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ✅ | ✅ 248/248 | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-05-03 15:17 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ❌ | ||||
| stylelint | ❌ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ❌ | ❌ | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-05-03 17:46 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ❌ | ||||
| stylelint | ❌ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ❌ | ❌ | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-05-03 18:04 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ❌ | ||||
| stylelint | ❌ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ❌ | ❌ | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-05-07 20:52 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ❌ | ||||
| stylelint | ❌ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ❌ | ❌ | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-05-07 21:24 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ❌ | ||||
| stylelint | ❌ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ❌ | ❌ | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-05-12 21:23 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ❌ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ❌ | ||||
| stylelint | ❌ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ❌ | ❌ | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-05-12 21:55 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ❌ | ||||
| stylelint | ❌ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ❌ | ❌ | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-05-12 22:33 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ❌ | ||||
| stylelint | ❌ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ❌ | ❌ | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-05-12 22:41 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ❌ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ✅ | ✅ 375/375 | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-05-12 23:27 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ❌ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ✅ | ✅ 375/375 | |||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/10 statements)
Quality workflow — 2026-05-13 04:40 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ✅ | ✅ 376/376 | |||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/10 statements)
Quality workflow — 2026-05-13 04:47 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ✅ | ✅ 376/376 | |||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/10 statements)
Quality workflow — 2026-05-13 05:46 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ✅ | ✅ 376/376 | |||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/10 statements)
Quality workflow — 2026-05-13 07:50 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ✅ | ✅ 376/376 | |||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/10 statements)
Quality workflow — 2026-05-13 09:13 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ✅ | ✅ 376/376 | |||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/10 statements)
Quality workflow — 2026-05-18 18:19 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ✅ | ✅ 376/376 | |||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/10 statements)
Quality workflow — 2026-05-18 18:56 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ✅ | ✅ 376/376 | |||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/10 statements)
Quality workflow — 2026-05-18 19:15 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ✅ | ✅ 376/376 | |||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/10 statements)
Quality workflow — 2026-05-18 20:46 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ✅ | ✅ 376/376 | |||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/10 statements)
Quality workflow — 2026-05-18 21:00 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/larpingapp @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 94/94 | |||
| npm | ✅ | ✅ 376/376 | |||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/10 statements)
Quality workflow — 2026-05-18 21:17 UTC
Download the full PDF report from the workflow artifacts.
…r-and-relation-refs
…endpoints
hydra gate-25 at package 651e5c5, full tree:
[gate-25] contract-coverage: FAIL - 2 new public endpoint(s) missing a contract test
preferences#getPreference - new public endpoint (url=/api/preferences/{key})
preferences#setPreference - new public endpoint (url=/api/preferences/{key})
Both are consumed by shared @conduction/nextcloud-vue widgets across apps
(CnSupportDialog's 'seen' flag is the current caller), so their wire contract
is not private to this app and had no test at all.
Ten tests covering every branch of both endpoints, asserting the ITEM rather
than the container - the exact status code AND the exact body, plus the exact
IConfig call the controller must make:
- anonymous read/write -> 401 {message: 'Not logged in'}, and IConfig is
never touched (expects(never)), so a regression that read config before
checking the session is caught rather than merely returning the right code
- a key that sanitises to nothing -> 400 {message: 'Invalid key'}, IConfig
untouched
- a stored value -> 200 {value: <stored>} read from pref_<key> for THIS uid
- an unset key -> {value: null}, not '' - the widgets distinguish 'never set'
from 'set to empty'
- a write stores under pref_<key> and echoes the value
- an EMPTY value deletes rather than storing '', or the next read could not
tell cleared from empty
- key sanitisation asserted on the value actually handed to IConfig
('../USER_lang!' -> 'pref_userlang'), on both the read and the write path.
That is a security boundary, not formatting: the pref_ namespace is what
stops a caller addressing arbitrary IConfig user values of this app.
Can-fail verified by mutating the clear-semantics branch
(if ($value === '') -> a literal that never matches):
1) ...PreferencesControllerContractTest::testSetPreferenceWithAnEmptyValueDeletesTheKey
FAILURES! Tests: 10, Assertions: 23, Failures: 1.
restored, git diff lib/ empty, and the full unit suite is OK (195 tests, 639
assertions).
gate-25 goes FAIL - 2 -> PASS on the same tree with the same package.
…rt it creates nothing
`Integration Tests (Newman)` has been red on development and on every open PR.
One assertion of 48:
1. AssertionError anonymous OR write rejected 401
expected response to have status code 401 but got 403
inside "1. Character (OR object CRUD, ADR-022) / Create character AUTHZ:
anonymous write returns 401"
The 401 was the wrong model, not a regression. OpenRegister's
`ObjectsController::create()` is `#[PublicPage]` on purpose — it is what public
forms post through, which is why it also carries `#[AnonRateLimit]`. Nextcloud's
auth middleware therefore lets an anonymous request reach the controller, and
the refusal comes from OpenRegister's own RBAC afterwards. That is an
authorization failure on a request that was allowed to be anonymous: 403
Forbidden. 401 would mean "authenticate and try again", which this endpoint is
not saying.
Measured directly against a running instance rather than inferred from the CI
log:
STATUS=403
{"error":"User 'Anonymous' does not have permission to 'create' objects
in schema 'Character'"}
The security property the case exists for is unchanged and still strict — the
write is denied. What changed is that the test no longer asserts only a status
code. The status is the weaker half; a denial that nonetheless created a
character would have satisfied any status assertion while being the exact bug
this case is here to catch. So it now also asserts the response carries no
object id and no `@self.id`, and that the code is >= 400.
Verified on the same instance that the denial body carries neither key.
…sts-ed6daf19 test(preferences): wire-contract tests for the two public preference endpoints (gate-25)
The note explaining why `ownerRef` carries no $ref was placed INSIDE
`character.properties`, as a sibling of `ownerRef`. That declares a schema
property named `_note` whose value is a string, where JSON Schema requires a
schema object — and it is the only `_note` at properties level in any register
file in this repo, so there was no precedent making it safe.
OpenRegister walks that map in `Schema::getSchemaObject()`:
foreach ($this->properties ?? [] as $propertyName => $property) {
if (($property['properties'] ?? null) !== null) { ... }
...
foreach ($property as $key => $value) { ... }
`$property['properties'] ?? null` is harmless on a string (isset() on a
non-numeric string offset is false, so it yields null), but the later
`foreach ($property as ...)` is not. Reproduced on php:8.3 with the exact
shape:
Warning: foreach() argument must be of type array|object, string given
Not fatal, but it emits that warning wherever the character schema object is
built, and it puts a non-property into a property map.
Moved to schema level, a sibling of `version` and `properties`, which is what
it actually annotates — the schema's deliberate exception, not a field of it.
Text unchanged; the diff is the one line moving.
Verified after the move: `validate-register` PASS, `validate-json-strict` PASS,
gate-51 schema-property-titles PASS, gate-46 PASS, and gate-54 still reports
exactly the one documented `ownerRef` finding — the note's placement was never
what suppressed anything.
…d6daf19 test(newman): an anonymous OR write is denied 403, not 401 — and assert it creates nothing
…r-and-relation-refs
…e29-hidden-findings
…ation-prose-ed6daf19
…n-refs fix(specs): resolve the dangling @SPEC anchor and give attendance/portal relations a canonical $ref
…e29-hidden-findings
…ation-prose-ed6daf19
…ndings fix(gates): close two findings the full-tree run reported as PASS
…ation-prose-ed6daf19
…d6daf19 fix(security): the sentence saying @NoCSRFRequired was removed IS the annotation — CSRF was never enforced on either settings write
Hard pin to the vue3 dist-tag head (2.2.0-vue3.7), up from 2.2.0-vue3.3. Verified: - lockfile control run first with the pin unchanged: 0-line diff, so the 8-line lock change below is attributable to this bump alone - installed version read off disk after npm ci: exactly one copy, 2.2.0-vue3.7, peer vue ^3.5.0 - build: exit 0, 2 warnings before and after (unchanged) - unit tests: 5 files / 40 tests passed before and after - bundle: 63,847,011 -> 63,876,361 bytes (+29,350, +0.05%) No caret: ^2.2.0 does not match a prerelease, and the latest/beta dist-tags are the retired Vue 2 lineage.
chore(deps): pin @conduction/nextcloud-vue to 2.2.0-vue3.7
Follow-up to #303, which pinned 2.2.0-vue3.7. The vue3 dist-tag moved twice more while the fleet wave was running (vue3.7 -> vue3.8 -> vue3.9), because every merge to nc-vue's feat/vue-3 cuts a publish. The fleet converges on 2.2.0-vue3.9. Verified on npm 10.8.2, the version CI runs: - control (pin unchanged): 0-line diff - npm ci: exit 0 - installed off disk: one copy, 2.2.0-vue3.9, peer vue ^3.5.0 - build: exit 0, 2 warnings at 2.2.0-vue3.7 and at 2.2.0-vue3.9 - vitest: 5 files / 40 passed at both versions - bundle: 63,876,359 -> 63,887,521 bytes (+11,162, +0.02%) 2.2.0-vue3.9 is not pre-verified against our apps the way 2.2.0-vue3.7 was, so the run above is the verification. No regression.
chore(deps): pin @conduction/nextcloud-vue to 2.2.0-vue3.9
`workflow_dispatch` was absent, and this repo and one other were the only two of the sixteen fleet apps where that was true — checked by reading .github/workflows/code-quality.yml on `development` in all sixteen. The consequence was not inconvenience. Every fleet-wide gate sweep in the current quality programme is a workflow_dispatch fan-out, so this repo was not failing those sweeps and was not passing them: it was absent from the results table entirely, which in a table of fourteen verdicts is indistinguishable from a repo that was never a problem. A dispatch is also strictly more informative than a re-run of CI here. The shared quality workflow scopes workflow_dispatch to the FULL repository, because there is no pull-request target branch and no previous pushed tip to diff against, so ADR-020 diff-scoping has nothing to scope to. A push run on `development` typically covers one commit's files; this is the only way to ask what the state of the whole app is without opening a pull request. Expect the first dispatch to be redder than a PR — that is the honest answer, not a regression. MEASURED, not assumed: dispatch does NOT require the trigger on the default branch. nldesign's default branch is `main`, its `main` carries no workflow_dispatch, and its dispatch run 31393755672 on `development` fired regardless. Landing this on `development` is therefore sufficient.
…disproven, see below) (#306) * fix(gates): close gate-46 and gate-54 at full scope Two findings that a full-scope `workflow_dispatch` reports and a diff-scoped PR never showed. Both are real; neither is closed by relaxing a check. gate-46 spec-anchor-existence (1 -> 0) ------------------------------------- `tests/validate-manifest.js` carried a @SPEC tag pointing into an OpenRegister CHANGE directory. Three things were wrong with it at once: it is a change dir rather than a canonical spec; the path has never existed in THIS repository, so it could not resolve here however the gate was written; and OpenRegister itself archived that change on 2026-05-27 as superseded, so it no longer resolves there either. The requirement it names is real — REQ-OR-MAN-007, canonically at openspec/specs/openregister-app-manifest/spec.md in ConductionNL/openregister — and it has exactly one home, which is not larpingapp. Copying it into larpingapp/openspec/specs/ purely to make a tag resolve would manufacture a second copy of an existing spec, so the pointer is kept as prose naming the owning repo and is no longer asserted as a machine-checkable claim about this tree. The surrounding comment also described OpenRegister's wiring verbatim ("OpenRegister is the foundation app and ships no manifest yet") — larpingapp does ship a manifest and reaches this validator through the check:specs aggregate, so that is corrected too. gate-54 relation-dialect (1 -> 0) --------------------------------- `character.ownerRef` is genuinely a relation to `player` and now declares `$ref: "player"` per ADR-062 rule 7, together with `visible: false` and `readOnly: true`. The second half is why the first is finally safe. ef7346c removed this exact $ref because adding it alone broke the character create dialog — ocName already declares `$ref: "player"`, and a second player-targeted relation made `character create dialog exposes a player (ocName) selector` fail on `input[placeholder*="player" i]`, twice. That measurement stands for that arm. It does not carry to this one: nc-vue's `fieldsFromSchema()` drops `visible: false` / `readOnly: true` properties as its FIRST filter, before any $ref is read or any selector resolved, so a hidden property cannot contribute a second selector to the dialog. The visibility is correct on its own merits and is not a gate dodge. ownerRef is the portal-subject scoping key, stamped server-side by PortalObjectWriter and projected out of the player view; it was never meant to be typed by a user. Its direct sibling `ownerUid` has carried `visible: false` + `readOnly: true` in larpingapp_register.json all along, so this aligns the two. Evidence, full-scope `hydra-gates --full` against the whole tree: before gate-46 FAIL 1 · gate-54 FAIL 1 · gate-19 FAIL 50 (3 gates red) after gate-46 PASS · gate-54 PASS · gate-19 FAIL 50 (1 gate red) gate-16 spec-coverage stays PASS across both, so nothing was traded for it. gate-46 was additionally shown to be live rather than merely quiet: an intermediate revision of this commit quoted the dangling target verbatim inside the comment explaining it, and the gate — which reads the file as text — went straight back to FAIL 1 on that prose. Removing the literal returned it to PASS. A planted true positive, if an unintentional one. gate-19 (50 e2e-coverage findings) is untouched here and stays red on purpose; it needs real Playwright tests, not an annotation pass. * revert(gate-54): the ownerRef $ref breaks the dialog with `visible:false` too My hypothesis was wrong and the e2e says so. Reverting the gate-54 half of 2bd48f3; the gate-46 half is unaffected and stays. WHAT I CLAIMED. Adding `$ref: "player"` to `character.ownerRef` alone broke the character create dialog (ef7346c, measured twice on #289). I argued that adding it TOGETHER WITH `visible: false` + `readOnly: true` would be safe, because nc-vue's `fieldsFromSchema()` drops non-visible/readOnly properties as its FIRST filter — before any $ref is read or any selector resolved — so a hidden property could not contribute a second player selector. WHAT HAPPENED. Run 31428015957, Playwright: ✘ tests/e2e/spec-coverage/detail-forms-admin.spec.ts:570 'character create dialog exposes a player (ocName) selector' expect(locator).toBeVisible() — element(s) not found 1 failed / 170 passed (12.4m) The same test, the same locator, the same 1/170 shape as the arm this was supposed to avoid. Every other job on the PR passed. WHAT THAT ACTUALLY TELLS US — and it is worth more than the fix would have been. The claim about `fieldsFromSchema()` is TRUE; the conclusion drawn from it is not. Whatever resolves the player selector does not go through the visibility filter at all, so the collision between `ocName` and `ownerRef` is at SCHEMA level rather than form-field level, and hiding the property cannot reach it. That rules out an entire family of remediations rather than just this one. The `_note` on the property now records BOTH measured arms, names the run for each, and says explicitly not to try a third variant of the same idea — the next real attempt is upstream, keying relation resolution by PROPERTY rather than by target schema slug so two properties may point at `player` at once. gate-54 therefore returns to FAIL 1 on purpose. Verified locally at full scope: with the $ref gate-54 PASS without it gate-54 FAIL 1 so the gate is live in both directions; it is the remediation that is blocked, not the finding that is false. --------- Co-authored-by: Conduction Release Bot <release-bot@conduction.nl>
…blocked it (#307) The last non-coverage finding. Two previous arms added this exact $ref and both were reverted because one Playwright test went red. That test was wrong, and this commit shows it rather than asserting it. WHAT THE TEST ACTUALLY CHECKED test('character create dialog exposes a player (ocName) selector') expect(dialog.locator('input[placeholder*="player" i]')).toBeVisible() CnFormDialog passes `:placeholder="field.description"` ONLY on its text/email/ url and number branches. The NcSelect branch that renders a `$ref` relation is given `:input-id` and `:input-label` and NO placeholder. So that locator could never match a relation picker at all. The single element it did match in the Add Character dialog was `ownerRef`'s PLAIN TEXT BOX, whose description reads "UUID reference to the player object". The assertion was therefore the exact inverse of its own name: green precisely while ocName was NOT a selector, red the moment a $ref made it one. gate-54's remediation and this test were mutually exclusive by construction, which is why both previous arms failed with the identical 1-failed/170-passed shape — not because of anything they had in common with each other, but because both remove the text box the assertion was really reading. It slid onto ownerRef with no red window, so nothing flagged it: 987c9ee test written; ocName is a plain string, no $ref, no selector — the assertion passed BECAUSE there was no selector f33fc0b ownerRef added, plain text, description mentioning "the player object" — a second matching input f434f76 ocName gains `$ref: "player"`, becomes a select and LOSES its placeholder; the suite stayed green only because ownerRef had arrived two days earlier and inherited the match THE UPSTREAM FIX THAT WAS PROPOSED IS A NO-OP The previous note concluded the collision was "at SCHEMA level" and asked for nc-vue to key relation resolution by PROPERTY rather than by target schema slug. nc-vue already does: the async option state, the search handler and the enum cache are each keyed `field.key`; `referenceLabels` is keyed by UUID (shared by design, and harmless — identical labels). Nothing in the library is keyed by `field.reference.schema`. Two properties may already point at `player` at once. The proposed change would have implemented behaviour that already exists. WHAT THIS COMMIT DOES - `character.ownerRef` declares `$ref: "player"` with `visible: false` + `readOnly: true`. The visibility is correct on its own merits, not a gate dodge: ownerRef is stamped server-side by PortalObjectWriter and projected out of the player view, and its sibling `ownerUid` has carried both flags all along. - The assertion now targets `#cn-form-ocName` — the id CnFormDialog gives every select — so the test finally checks the selector its name promises, and fails if that picker stops rendering. This is a correction, not a tightening, and not a weakening: the old assertion could not fail for the reason it claimed. - The `_note` records the corrected diagnosis and withdraws the prohibition. BOTH DIRECTIONS PROVEN, canonical helper from ConductionNL/.github@main (78d882a — the ref CI resolves), against all 7 register files: before gate-54 FAIL 1 character.ownerRef — relation-shaped property lacks canonical $ref after gate-54 PASS 0 planted TP ($ref removed) gate-54 FAIL 1, naming character.ownerRef again reverted gate-54 PASS 0 gate-19 (50 e2e-coverage findings) is untouched and stays red on purpose; it needs real Playwright tests, not an annotation pass.
… feature + close the game-mechanics gate-19 cluster (50 → 42) (#311) * fix(listeners): two defensive guards that silently disabled their own feature Both of LarpingApp's OpenRegister listeners were registered, reached, and inert — each stopped by a guard on its first line. 1. CharacterRequirementListener (larpingapp#308) `isCharacterSchema()` probed `method_exists($entity, 'getSchema')`. `OCA\OpenRegister\Db\ObjectEntity` declares only `getObject()`; every other accessor is resolved by `OCP\AppFramework\Db\Entity::__call()`. Measured live (NC 34, openregister 0.2.17-unstable.36): method_exists($entity, 'getSchema') -> false (magic) is_callable([$entity, 'getSchema']) -> true $entity->getSchema() -> "17" method_exists($entity, 'getObject') -> true (declared — control) So the method returned false for EVERY character write, `handle()` returned early, and no veto was ever raised. Black-box on a single-owner rig, before -> after, one line changed: POST a character carrying a skill whose requiredSkills[] is unmet HTTP 201, persisted -> HTTP 422, itemised requirements PUT adding that skill to a clean character HTTP 200, persisted -> HTTP 422 POST a character with no unmet requirement (control) HTTP 201 -> HTTP 201 larpingapp#308 attributed this to OpenRegister never dispatching the vetoable pre-write event. It does dispatch it: `ObjectCreatingEvent` carries 7 listeners on this instance and CharacterRequirementListener is first in the chain. The issue's grep landed on `SaveObjects.php` (plural, the bulk path) rather than `SaveObject.php` (singular, the REST path). 2. DeepLinkRegistrationListener The guard probed `method_exists($event, 'registerDeepLink')`. `DeepLinkRegistrationEvent` has never declared such a method — the API is `register($appId, $registerSlug, $schemaSlug, $urlTemplate, ...)`. The guard was false on every dispatch, so zero deep links were registered; dropping the guard without renaming the call would have fatalled with "Call to undefined method". The guard was the only thing hiding a broken call. Verified live: 0 registrations -> 8. Also corrects two map keys. `item` and `event` collide instance-globally, so LarpingApp's schemas are `larping_item` / `larping_event`; the bare spellings matched no schema on any instance. Why the unit suites were green over both ---------------------------------------- Each suite's hand-written fake was shaped to what the caller CALLS rather than to what the collaborator IS: - `FakeObjectEntity` DECLARED `getSchema()`, so `method_exists()` answered true in the suite and false in production. It now mirrors the real class: `getObject()` declared, `getSchema()` via `__call()`. - The deep-link fakes declared a three-argument `registerDeepLink()` — an API that existed nowhere but in that file. They now mirror the real `register()` signature exactly. Negative control, expectation computed first: with the faithful fake and the `isCharacterSchema()` fix reverted, exactly the three rejection-asserting tests go red (`testRejectsCreateWithUnmetPrerequisite`, `testOverrideRejectedFromNonGm`, `testEmptyReasonOverrideRejected`). Restored: 201 tests, 683 assertions, `composer check:strict` ALL PASSED. Also fixes the app's only two pre-existing Psalm findings (`UndefinedMethod` on `getNewObject()`/`getOldObject()` in `extractEntities()`), present on the pristine tree before this change. * test(game-mechanics): close the 8-scenario gate-19 cluster with real numeric assertions gate-19 unscoped (CI's `--full` invocation): **50 -> 42**, with all eight `game-mechanics::` findings gone and nothing else moved. Expectation computed before the run. Every assertion is a number derived in advance from seeded data and compared against what the real `CharacterService` computes from rows really persisted through OpenRegister's object REST API. Nothing asserts merely that a write was accepted — that shape is why the previous attempt at the `skill-requirement-enforcement` cluster was correctly abandoned. Driven through the genuine production path — `calculateCharacter()` / `calculateAllCharacters()` with their own `loadAllEntities()`/findAll loader, no reflection injection, no stubbed collections: initializeAbilityScores -> applyEntityEffects (skills, items, conditions, events) -> applyEffects -> calculateEffect -> applyModifierToAbility NEGATIVE CONTROLS — three engine mutations, each prediction written before the run, each matched exactly -------------------------------------------------------------------------- | plant (source, not test) | predicted | observed | |-----------------------------------------------------|-----------|----------| | A `applyModifierToAbility` positive branch SUBTRACTS | 6 F / 2 P | 6 F / 2 P | | C the non-cumulative dedup rule can never match | 1 F / 7 P | 1 F / 7 P | | E `initializeAbilityScores` seeds value 0, not base | 7 F / 1 P | 7 F / 1 P | Plant A leaves `ability serialises` green (it carries no effects) and `condition applies a negative modifier` green (the `negative` branch is untouched) — both are covered by plant E. Plant E leaves `cumulative and non-cumulative` green because both its abilities are deliberately seeded at base 0, so it is base-independent by construction; plant C is what covers it. Every one of the eight fails under at least one mutation. All plants reverted; 8/8 green afterwards. HARNESS ------- - `computeStatsLive()` returns the WHOLE derived `stats` block. The scenarios are about the SHAPE of the derivation — an untouched ability keeping an empty audit, four carriers composing onto one ability in order, a non-cumulative effect applying exactly once — and none of that can be asserted one ability at a time. - `computeRosterLive()` drives `calculateAllCharacters()`, the batch entry point the roster-independence scenario is actually about. - `NC_CONTAINER` makes the docker path target a named rig. Previously, on a developer box, `findServerRoot()` walked up to the SHARED dev container's server root and ran the derivation against ITS database while the HTTP fixtures were written to an isolated rig — the two halves of every assertion talking to different instances, failing with `base: null`, which reads exactly like broken arithmetic. Unset, behaviour is unchanged, CI included. Isolation: `initializeAbilityScores()` walks EVERY ability in the register, so every assertion is keyed on the UUID of an ability seeded under this run's own `RUN_ID` prefix, never on the size of the stats block. * fix(deps): close CVE-2026-65954 — phpcsstandards/phpcsutils 1.2.2 -> 1.2.3 `quality / Security (composer)` has been red on `development` since at least run 31461764863 (2026-08-11 05:28Z), on a pre-existing advisory this branch did not introduce — proof: `git diff origin/development -- composer.json composer.lock` was EMPTY when the cell first went red on this PR. Advisory PKSA-kh6k-gs3g-dgr6 / CVE-2026-65954 Arbitrary code execution, PHPCSStandards/PHPCSUtils affected >=1.0.0-alpha1,<1.2.3 — installed 1.2.2 Bumped narrowly (no `--with-dependencies`, so nothing else in the tree moves): `composer audit` -> "No security vulnerability advisories found", `composer check:strict` -> ALL CHECKS PASSED, 201 tests / 683 assertions.⚠️ Note for anyone running the suite locally: `composer.json` sets `config.platform.php = 8.3` and `require.php = ^8.3`, so a plain `composer install` on a PHP 8.2 box regenerates `vendor/composer/platform_check.php` and every PHPUnit run then dies with exit 255 before collecting a single test — a failure that names the platform, not the change. Use `composer install --ignore-platform-reqs` there. CI runs 8.3/8.4 and is unaffected. * docs(spec-anchors): repoint 78 dangling @SPEC anchors to their canonical specs (larpingapp#309) `opsx-archive` moved 32 changes under `openspec/changes/archive/` and left every annotation behind. Measured by a resolver over every tracked `.php/.ts/.js/.vue`, with a positive control built in (it refuses to report unless anchors resolve): | | before | after | |----------------------|--------|-------| | RESOLVING `@spec` | 38 | **116** | | RESOLVING `@e2e` | 114 | 122 | | DANGLING total | 374 | **296** | | DANGLING `@spec` | 351 | **273** | This commit takes only the MECHANICAL subset: anchors of the shape `openspec/changes/<change>/specs/<Y>/spec.md` repointed to `openspec/specs/<Y>/spec.md`, and only where that canonical target was verified to exist first. 78 anchors, 21 sites, 19 files, 11 distinct path pairs.⚠️ TWO THINGS DELIBERATELY NOT DONE ----------------------------------- **1. The 22 `@e2e` anchors of the same shape are left dangling on purpose.** All 22 live in `tests/e2e/spec-coverage/spa-ui.spec.ts` and all point at the five `*-leaf` specs — features that are UNBUILT (open issues #184–#188, #302). larpingapp#301 already establishes that retargeting their inert tags manufactures a false green: a resolving `@e2e` is scored as coverage by gate-19 whether or not the test exercises the scenario. Repointing them would drop the gate-19 number without a single new assertion existing. They stay dangling until the leaves are built. The split is clean — every one of the 78 moved here is `@spec`, and no file mixes the two for the same path. **2. The 273 remaining dangling `@spec` anchors are NOT mechanically fixable.** 255 of them (235 + 15 + 5) target a `tasks.md#task-N` inside a retrofit change directory — the wrong KIND of artifact as well as a dead path, since `@spec` must target canonical `openspec/specs/`. Each needs a per-tag judgement about which requirement it describes, so they are left for a change that can make that judgement rather than guessed at in bulk. Verified unchanged by this commit, on the same tree: gate-19 **42** (no `@e2e` anchor moved), gate-16 `# count=0`, `composer check:strict` ALL PASSED, 201 tests / 683 assertions.
The PHP Quality (psalm) cell reported success while Psalm was disabled in the caller workflow, because the shared workflow still creates a job under that name for a disabled tool. The reason it was disabled was a broken stub path in psalm.xml pointing at an OCP.bak directory that only one developer's container-symlinked vendor tree ever had. Path corrected, cell enabled. This PR's own run shows Psalm reaching a clean result with 93.05 percent of the codebase inferred, matching the local measurement exactly. Also unguards the composer psalm and phpstan scripts so a missing binary fails loudly instead of greening the cell. Note the correction posted in the comments: the 142-byte artifact I originally cited is not evidence of anything.
* chore: adopt nextcloud/coding-standard, .editorconfig and NC 34 Configuration only. The reformat is the next commit on purpose, so .git-blame-ignore-revs can name a revision containing nothing but whitespace. - .php-cs-fixer.dist.php + conduction/coding-standard, which extends nextcloud/coding-standard and can only ADD to it — enforced by that package's invariant test, not by review. - cs:check / cs:fix now run php-cs-fixer. They were aliases for phpcs/phpcbf, so the documented Nextcloud command reformatted code AWAY from Nextcloud's standard. - nextcloud/coding-standard dropped as a direct dependency. It arrives transitively at a version conduction/coding-standard has tested against; declared directly it was a dead dependency with no config and no invocation. - phpcs.xml is now a stub over the shared semantics-only ruleset, and the local phpcs-custom-sniffs/ copy is gone. The fleet was carrying six divergent versions of NamedParametersSniff.php — a custom RULE, not a setting. - .editorconfig, verbatim from nextcloud/server. No fleet app had one, so an editor configured by someone's previous Nextcloud work defaulted to tabs, which the old ruleset then rejected. - nextcloud/ocp -> ^34.0 and PHPUnit -> stable34. This app declared support for NC 34 while being analysed against 31, so a symbol REMOVED in 32/33/34 was invisible to the type checker. That is why the NC 34 removal of \OC::$server needed a hand-written PHPCS sniff. - the stylelint glob is quoted, so stylelint expands it rather than the shell. Unquoted, src/**/ matches exactly one directory level and nested components are silently unlinted. gate-65 (coding-standard-adoption) enforces all of the above from ConductionNL/.github@main. This app failed it; with this commit it passes. * style: reformat with nextcloud/coding-standard — whitespace only Applied by php-cs-fixer with conduction/coding-standard. Tabs, same-line braces, (int)$x, single-space concatenation, ordered imports — Nextcloud's dialect, which this app now passes unchanged. 57 file(s), no behaviour change. Isolated from the configuration change so .git-blame-ignore-revs can name a revision that touches nothing but formatting. Reviewing it line by line is not a useful activity; the previous commit is the review. * chore: ignore the reformat commit in git blame 6a673f0 touches 57 files and changes no behaviour. Without this, every line it reflowed attributes to it and the real author is one --skip away. GitHub honours the file automatically; locally it needs `git config blame.ignoreRevsFile .git-blame-ignore-revs` once. * fix: regenerate composer.lock for the new constraints The previous commit changed composer.json without touching the lock, so `composer install` refused with exit 4 and EVERY PHP job failed: Required (in require-dev) package "conduction/coding-standard" is not present in the lock file. Required (in require-dev) package "conduction/hydra-gates" is not present in the lock file. Required (in require-dev) package "nextcloud/ocp" is in the lock file as "v31.0.9" but that does not satisfy your constraint "^34.0". Nothing was wrong with the reformat or the ruleset — the jobs never got as far as running a tool. Measured on larpingapp#313 before this fix: phpcs, psalm, phpstan and both PHPUnit legs red, all of them at `composer install`. Hydra Gates passed in the same run, because it does not install composer dependencies. Now locked at conduction/coding-standard v1.0.0, conduction/hydra-gates v1.7.0, nextcloud/ocp v34.0.2 — the last of which is the point of the exercise: this app declares support for NC 34 and is now analysed against it. * fix(appinfo): order info.xml elements per the App Store xs:sequence The App Store's info.xsd declares <info> and its children as xs:sequence, so element ORDER is significant. This file was rejected by `xmllint --noout --schema info.xsd appinfo/info.xml`. Nextcloud's lint-info-xml workflow validates against exactly that schema, and ConductionNL/.github#383 adds the same check to the shared pipeline. Elements were moved into the schema's order. <version> and the <nextcloud> min/max-version declaration are unchanged. Top-level blocks are now repair-steps, settings, navigations; <php> and the <database> entries precede <nextcloud>; and inside <repair-steps>, <post-migration> precedes <install> (the schema's order is pre-migration, post-migration, live-migration, install, uninstall - it does not reflect execution order, which Nextcloud selects by event). Ordering alone was not sufficient here. The <dependencies><app> entry is not an ordering problem: the App Store schema has no <app> child under <dependencies> at any position, so it can never validate. It was also inert - OC\App\DependencyAnalyzer::analyze() handles only architecture, php, database, command, lib, os and the server version, and never looks at "app" - so it enforced nothing at install time. The dependency is now recorded as a comment in the same place. The <groups>larpers</groups> block was likewise not an ordering problem: the schema has no <groups> element, and Nextcloud never read one - OC_App's app listing sets $info['groups'] unconditionally from the app's 'enabled' appconfig value, overwriting whatever info.xml parsed. So the block restricted nothing. The requirement and the supported mechanism (app-level group restriction via occ or the Apps admin page) are documented in the comment that already stood above it. Verified: `xmllint --noout --schema info.xsd appinfo/info.xml` reports "validates" (libxml2 2.12.10). The pre-change file failed the same command.
….prettierrc (#314) The phpcs migration (#313) pointed phpcs.xml at vendor/conduction/hydra-gates/quality-config/phpcs.xml and left the other root configs behind. This does the same for PHPMD. - phpmd.xml becomes the stub from quality-config/stubs/phpmd.xml. - phpmd-unusedparams.xml is deleted; the second leg of the `phpmd` composer script now points at the central copy. Both legs are kept, as is the worst-exit-code behaviour. - .prettierrc is deleted. Nothing depends on prettier (no package.json dep, no script, no workflow reference), so it is inert in CI — but it is live in editors, where it tells Prettier to format .ts with 2-space indent and double quotes, both of which @nextcloud/eslint-config then flags. Verified rather than assumed. Both legs were run in php:8.3-cli before and after, and the EFFECTIVE ruleset was dumped rule-by-rule (class, name, priority, every property) so a stub that quietly narrowed scope could not read as a clean pass: effective ruleset : 43 rules before, the same 43 after, byte-identical composer phpmd : identical output, exit 0 both times PHPStan is deliberately NOT in this commit. quality-config/phpstan-base.neon declares its paths relative, and PHPStan resolves those against the config file that declares them, so from vendor/ it looks for vendor/conduction/hydra-gates/quality-config/lib. Adopting the stub aborts the run outright. Fixed in ConductionNL/.github#387; this app follows once that is released.
#315) appinfo/info.xml declares <nextcloud min-version="32" max-version="34"/>, but nextcloud-test-refs was '["stable34"]' — so the declared floor and the middle major were advertised to the App Store with no job touching either. This is the coding-standard migration's own defect: its rollout REPLACED the ref list instead of extending it. The programme opened by reporting that nothing was tested on NC 34 and, in fixing that, made 32 and 33 the untested end. Same drift, other direction. stable34 stays first because newman, playwright and journeydoc-capture all read fromJSON(inputs.nextcloud-test-refs)[0] as their single server. Verified green on all three refs against nextcloud/ocp ^34 on portaliq (run 31599055849, six PHPUnit legs: 32/33/34 x PHP 8.3/8.4).
phpstan.neon now includes the shared base shipped in conduction/hydra-gates (quality-config/phpstan-base.neon) and keeps only what is genuinely local to this app: its own baseline include and the two ignores naming symbols no other fleet app has. Requires hydra-gates v1.7.1 — v1.7.0's base declared bare relative paths, which PHPStan resolves against the file that declares them, so the run aborted before analysing anything. composer.lock is updated accordingly; no other package moved. Verified with phpstan dump-parameters before and after: level, paths, excludePaths, bootstrapFiles and scanDirectories resolve byte-identically, 28 files analysed on both sides, no findings on either.
Moves the pin from 2.2.0-vue3.9 to the current vue3 dist-tag. The lockfile was regenerated with npm 10.8.2 to match the npm version CI runs (engines: npm ^10.0.0); npm ci was verified from a clean node_modules. Verified locally: npm ci, build, 5 vitest files / 40 tests via 'npm run test:unit' (this repo has no plain 'test' script), eslint, stylelint — all pass. Co-authored-by: Ruben van der Linde <juan.claude@conduction.nl>
…318) Lock-only. composer.json is untouched: the ^1.0 constraint is correct and stays floating. v1.7.3 removes two conditional paths from the shared phpstan-base.neon (%cwd%/vendor-bin and %cwd%/lib/Resources/template). A conditional path in a shared base has no spelling that is safe on both PHPStan majors: plain is validated and ABORTS on PHPStan 2.x, the '(?)' marker is parsed as a NEON entity after a %...% expansion and crashes 2.x, and quoting it stops 1.x from stripping the marker so the exclusion silently matches nothing. This app is on PHPStan 1.12.x, so it is not broken today, but it carries the landmine until it moves to PHPStan 2. It has neither vendor-bin nor lib/Resources/template, so no phpstan.neon change is needed.
Automated PR to sync development changes to beta for beta release.
Merging this PR will trigger the beta release workflow.