Skip to content
This repository was archived by the owner on May 29, 2026. It is now read-only.

fix(procest): repair OR-API drift + dangling seed references#417

Closed
rubenvdlinde wants to merge 0 commit into
developmentfrom
feature/procest-production-fixes
Closed

fix(procest): repair OR-API drift + dangling seed references#417
rubenvdlinde wants to merge 0 commit into
developmentfrom
feature/procest-production-fixes

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

Found during the local NC upgrade-and-audit pass — two production blockers:

1. Dangling seed references (config import fails on every install/upgrade)

Three parafeeractie seed objects in procest_register.json referenced voorstel-collegeadvies-0042 / voorstel-collegeadvies-0055, which have no matching voorstel seed object. OR validates parafeeractie.voorstel as a uuid-format relation and rejected the slug strings → Failed to import configuration for app procest: Property 'voorstel' should match format 'uuid'. The three orphaned objects are removed (42 → 39 objects).

2. Removed OR API: ObjectService::getObjects()findAll()

OCA\OpenRegister\Service\ObjectService::getObjects() no longer exists. Migrated all 9 call sites to findAll(['filters' => ['register' => ..., 'schema' => ..., ...]]) which returns a flat array. This fixes the Could not seed bezwaar/beroep data: Call to undefined method ObjectService::getObjects() repair warning (via SeedDataService::findByFilter).

TenantService::getTenantByGroupId() still has one getObjects() call but that path short-circuits before reaching it (the tenant_schema config key is never set) and PR #411 removes the method entirely — left as-is to avoid a merge conflict.

Out of scope (follow-ups)

  • The broken procest-main.js bundle ("Unexpected identifier 'Case'" JS syntax error — needs a rebuild)
  • 25 additionalProperties validation errors in src/manifest.json page actions against canonical schema v1.4.0 (the schema's action def is additionalProperties:false and lacks handler/route — needs an action-shape design decision)

Test plan

  • occ upgrade on a fresh NC dev env no longer emits the procest config-import warning
  • Quality gate (phpcs/psalm/phpstan) green

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/procest @ bf3fcea

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 100/100
npm ✅ 419/419
PHPUnit ⏭️
Newman ⏭️
Playwright

Spec coverage: 5% (21 tests / 456 specs)


Quality workflow — 2026-05-12 05:00 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/procest @ b6942cc

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 100/100
npm ✅ 419/419
PHPUnit ⏭️
Newman ⏭️
Playwright

Quality workflow — 2026-05-12 05:16 UTC

Download the full PDF report from the workflow artifacts.

@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/procest @ aebea2a

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
composer ✅ 100/100
npm ✅ 419/419
PHPUnit ⏭️
Newman ⏭️
Playwright

Spec coverage: 5% (21 tests / 456 specs)


Quality workflow — 2026-05-12 05:30 UTC

Download the full PDF report from the workflow artifacts.

rubenvdlinde added a commit that referenced this pull request May 12, 2026
Continues the procest quality cleanup (after the phpcs commits):

**stylelint** — added the missing peer deps of `@nextcloud/stylelint-config`
(which the config `extends`): `stylelint-config-recommended-scss@^13.1.0`,
`stylelint-config-recommended-vue@^1.6.1`, `postcss-html@^1.8.1` (matches
decidesk's set). `npm run stylelint` now runs and reports **0 errors** — the
"Vue Quality (stylelint)" gate was failing purely on the missing-config-module
error, not on actual style violations.

**eslint** — `npm run lint -- --fix` auto-fixed 5; the remaining 9 errors
fixed by hand:
  - `bezwaar.js` — removed unused `settingsStore` var + its now-unused import
  - `MyWork.vue` — `<template v-else-if="!loading">` → `v-if` (the v-else-if
    duplicated the preceding `<ParafeerInbox v-if="!loading">` condition →
    the grouped sections could never render; `vue/no-dupe-v-else-if`)
  - `DurationPicker.vue` — dropped unused `formatDuration` import
  - `CaseTransferDialog.vue` / `CreateShareDialog.vue` — moved `<template
    #actions>` out of the wrapping `<div>` to be a direct child of `<NcDialog>`
    (named slots must be owned by the component, not a nested div;
    `vue/valid-v-slot`)
  - `EmailComposer.vue` — `{{ '{{' + v + '}}' }}` → `{{ '{' + '{' + v + '}'
    + '}' }}` (a literal `}}` inside a `{{ }}` interpolation made Vue's
    template parser see the interpolation close early → "Unterminated string
    constant"; splitting the braces avoids it, renders identically)
  - `WorkflowCanvas.vue` — `v-model:nodes`/`v-model:edges` (Vue-3 named
    v-model) → `:nodes.sync`/`:edges.sync` (Vue-2 equivalent). This file is
    dormant anyway (see below).
`npm run lint` now exits 0 (errors=0; 14 warnings remain — `@nextcloud/no-deprecations`
on `OC.currentUser` etc. — tolerated).

**build** — `customComponents.js` no longer imports `VisualWorkflowEditor`
(→ `WorkflowCanvas` → `@vue-flow/{core,controls,background}` v1.x, which are
Vue-3-only and were breaking `npm run build` with 272 errors). The workflow
component files stay in `src/components/workflow/` but dormant; re-wire when
@vue-flow is replaced with a Vue-2-compatible flow lib. (Same fix as #417.)
`npm run build` now compiles with 0 errors; `procest-main.js` parses clean.

Together with the phpcs commits on this branch, procest's phpcs / eslint /
stylelint / build CI checks are all green. Still red: Playwright E2E and the
PHPUnit/Newman jobs (the latter fail on the OR-side `oc_openregister_objects`
fresh-install issue — openregister#1492 — not a procest problem).
Comment thread src/manifest.json Outdated
{
"type": "data"
}
],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[BLOCKER] Admin-only pages now accessible without page-level permission guard

Four pages that previously had "permission": "admin" at the page level have had that guard dropped during the reformatting pass:

  • /settings/wms-layers (WmsLayers index)
  • /settings/wms-layers/:id (Kaartlaag detail)
  • /settings/lhs-matrices (Handhavingsstrategie index)
  • /settings/lhs-matrices/:id (LHS Matrix detail)

The corresponding menu items still carry "permission": "admin" so non-admins won't see the links in the sidebar — but the manifest page objects themselves no longer enforce access. Any user who knows or guesses the URL can navigate directly to these admin-only pages, bypassing the menu-level guard. This is a privilege-escalation path that opens WMS layer management (external tile server credentials) and LHS enforcement-strategy matrices to all authenticated users.

Fix: restore "permission": "admin" as a top-level sibling of "route" on each of the four affected page objects, exactly as it appeared before this PR.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[BLOCKER] hasRow() called on flat findAll() array — shape mismatch may cause unchecked re-seeding

$existing is now the flat array returned by findAll() (a list of entity objects). The old getObjects() returned a paginated wrapper ['objects' => [...], 'total' => N]. The call $this->hasRow($existing) on line 61 is unchanged in this PR.

If hasRow() internally checks $existing['objects'] or treats a non-empty paginated wrapper as truthy, it will now receive an unexpected shape and silently return false even when an active LHS matrix already exists — causing the repair step to overwrite live matrix data on every run of php occ maintenance:repair.

The diff does not show the body of hasRow(). Before merging, verify that hasRow() correctly handles a flat PHP array. If it does not, inline the check as count($existing) > 0 or update hasRow() accordingly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CONCERN] PHP + operator silently discards caller-supplied register/schema overrides

The filter array is constructed as ['register' => $registerId, 'schema' => $schemaId] + $filters. PHP's + operator keeps left-hand keys on collision, so any register or schema key in $filters is silently discarded. The same pattern appears in LhsRecommendationService.php line 175.

This is likely intentional (callers should not override register/schema), but it creates a silent footgun: a caller passing those keys will see no error and get unexpected query results. At minimum, add a brief comment explaining the merge order is deliberate.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CONCERN] Incomplete OR-API migration: TenantService::getTenantByGroupId() still uses getObjects()

The PR description acknowledges that TenantService::getTenantByGroupId() still calls the removed getObjects() API and claims it is safe because execution short-circuits before reaching it. This is a fragile assumption: any refactor of the short-circuit condition or the caller chain could cause a fatal runtime error in production.

Since this PR is scoped to repair OR-API drift, leaving a known broken call site in-tree is an incomplete fix. Add a // TODO(#411): migrate getObjects() — safe only while <condition> holds comment directly on the call site so the next contributor can see the risk, and make sure PR #411 is linked as a blocking follow-up.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CONCERN] Seed deletion not verified for reverse references to deleted parafeeractie slugs

Three parafeeractie seed objects are removed because they contain dangling voorstel references. However, the PR does not confirm that no other remaining seed objects reference the deleted slugs themselves (parafeeractie-stap1-advies-2026-0042, parafeeractie-stap2-parafering-2026-0042, parafeeractie-stap2-geretourneerd-2026-0055).

If any surviving seed object references these slugs (e.g. a workflow step, a status record, or a voorstel body field), the deletion creates new dangling references in the opposite direction. Run grep -r 'parafeeractie-stap1-advies-2026-0042\|parafeeractie-stap2-parafering-2026-0042\|parafeeractie-stap2-geretourneerd-2026-0055' lib/Settings/ before merging.

Comment thread src/manifest.json Outdated
},
{
"id": "cases-by-type",
"type": "custom",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CONCERN] Manifest version not bumped despite schema-breaking structural changes

The manifest is described as 'conformed to canonical app-manifest schema v1.4.0', yet "version": "1.0.0" is unchanged. Actions arrays were changed from shorthand strings to full objects — a structural change. If the manifest version field is consumed by the loader or CI, leaving it at 1.0.0 is misleading. Consider bumping it to match the target schema version or the app's own semantic version for this release.

Comment thread src/manifest.json Outdated
},
{
"id": "cases-by-type",
"type": "custom",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CONCERN] 25 additionalProperties schema validation errors left unresolved

The PR description explicitly acknowledges 25 additionalProperties validation errors remain after the schema migration. The manifest declares a $schema URL but does not fully validate against it. Any schema-validation CI gate will continue to fail. These errors should be enumerated in a follow-up issue with an acceptance deadline, not left as open-ended known debt in the PR description.

Comment thread src/manifest.json Outdated
},
{
"id": "cases-by-type",
"type": "custom",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CONCERN] PR has merge conflicts with base branch development — must rebase before merge

The PR is currently marked CONFLICTING with development. The permission-guard omissions for WmsLayers and LhsMatrices pages may have been introduced accidentally during conflict resolution rather than being deliberate decisions. The author must rebase (not merge) against the current tip of development, resolve all conflicts, and re-request review. Approving a conflicting PR risks missing additional regressions introduced during the conflict resolution.

Comment thread src/customComponents.js

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[CONCERN] VisualWorkflowEditor commented out without a tracking issue

VisualWorkflowEditor is unwired because @vue-flow/core v1.x requires Vue 3 and procest runs on Vue 2.7. The comment is informative but there is no linked GitHub issue to track resolution. Without a tracked issue, this can silently rot and the src/components/workflow/ files will confuse contributors.

Fix: open a tracking issue (e.g. 'Replace @vue-flow with Vue-2-compatible library or migrate to Vue 3'), reference the issue number in the comment, and optionally add a // @deprecated tag to the workflow component files.

@WilcoLouwerse WilcoLouwerse left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

🔴 Blockers (2)

🟡 Concerns (7)

🟢 Minor (1)

  • Inconsistent (int) casting of register/schema across findAll() call sites (lib/BackgroundJob/AppointmentReminderJob.php:14)
    BackgroundJob files cast register and schema config values to (int) before passing them to findAll(). SeedLhsMatrix.php and LhsRecommendationService.php pass them as-is. If OR's findAll() API performs strict type comparison on filter values, mixed string/int inputs could produce silent empty results. Standardise the cast pattern across all call sites.

Reviewed by WilcoLouwerse via automated batch review.

@rubenvdlinde

Copy link
Copy Markdown
Contributor Author

Auto-closed in error by a force-push bug in the quality-cleanup harness. Reopened as #491 with the same branch and content.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants