feat: case management implementation enhancements (#205)#267
feat: case management implementation enhancements (#205)#267rubenvdlinde wants to merge 36 commits intodevelopmentfrom
Conversation
…ustom properties and documents panels (#205)
Three pre-existing test files used getMockBuilder(\stdClass::class) ->addMethods([...]) which, in PHPUnit 10, generates parameter-less stubs that reject named-argument calls from production code with 'Unknown named parameter'. This blocked the Hydra pipeline builder on every run. Fixes: - ZgwZrcRulesServiceTest: add ObjectServiceStub interface with real signatures for find(), buildSearchQuery(), searchObjectsPaginated(); convert the 5 failing tests to createMock(ObjectServiceStub::class); correct the volgnummer-fallback test data to use sequenceNumber (the field production code actually reads) instead of order; fix testHoofdzaakNotFoundReturnsDoesNotExist so zaaktype lookup returns valid data while hoofdzaak lookup returns null. - SeedDataServiceTest: add SeedObjectServiceStub interface with real signatures for getObjects() and saveObject(); replace both addMethods(\stdClass) uses with createMock(SeedObjectServiceStub::class). - GisProxyServiceTest: fix testKadasterUrlIsAllowed to use a URL that actually matches the 'kadaster.nl' substring the production code checks for, so the test exercises the intended branch instead of falling through to the container.get() path. Container verification: vendor/bin/phpunit in nextcloud container now reports 'OK (112 tests, 284 assertions)'.
…ydra (#258) App repos should carry ONLY repo-specific ADRs (in openspec/architecture/), not stale copies of hydra's org-wide ADRs. These copies had drifted — adr-004-frontend.md in this repo still said 'fetch() not axios' while hydra master says the opposite since commit e4cf8a2. That caused Hydra's code reviewer on decidesk#71 to flag a real ADR contradiction. Per user direction (2026-04-19): delete all per-repo copies of hydra's org-wide ADRs. Reviewer + builder containers already COPY the relevant ADRs from hydra into the image at build time — agents operating in the repo outside a container should read hydra master directly. openspec/architecture/ stays — that's where repo-specific ADRs (authored by Specter during research) should live.
* chore(quality): run phpcbf — 1147 auto-fixable phpcs violations resolved Before: 1540 errors across 47 lib/ files After: 393 errors across 45 lib/ files Remaining violations are non-auto-fixable (named-parameter rewrites, operator !/=== FALSE swaps, implicit truthy, inline-if rewrites) and need human or reviewer judgment. * fix(headers): @author email typo dev@conductio.nl → info@conduction.nl Literal string replacement in docblock @author tags. Template fix in nextcloud-app-template PR #19 prevents recurrence.
Introduces CustomSniffs\Sniffs\Commenting\SpecTagSniff which walks every top-level class and public method in lib/ and emits a PHPCS warning when the preceding docblock lacks an @SPEC tag linking back to an OpenSpec change (ADR-003 Backend rules). The rule is registered as warning (not error) in phpcs.xml so CI surfaces the gap without blocking merges while coverage is backfilled. Anonymous classes, magic methods, private/protected methods, and test files are skipped. PHPUnit coverage ships alongside the sniff in phpcs-custom-sniffs/tests/Commenting/.
…phpmd; REUSE.toml (#261) * chore(quality): phpcbf auto-fixes (1147 violations) * chore(quality): phpcs fixes for small files (named-params, inline-if, file-docs) * chore(quality): phpcs fixes in Controllers (StufController, AppointmentController, PublicAppointmentController) * chore(quality): phpcs fixes for all Controllers (named-params, inline-if, empty() explicit, doc-blocks) * chore(quality): phpcs fixes for AiService, AppointmentService, BerichtenboxService * chore(quality): phpcs fixes for appointment backends and mock adapter * chore(quality): phpcs fixes for small/mid services (DsoIntake, Tenant, Checklist, CaseSharing, Consultation, ZgwZrc) * chore(quality): phpcs fixes for Stuf/Milestone/Parafering/LegesCalculation services * chore(quality): phpcs fixes for remaining services — zero phpcs errors * fix(quality): add SettingsService::getObjectService() pass-through Adds a nullable pass-through to resolve OpenRegister's ObjectService from the DI container. Mirrors the lazy-resolve pattern already used for ConfigurationService — OpenRegister is an optional runtime dependency so the class can't be type-hinted directly in the constructor. Eliminates ~20 phpstan/psalm 'undefined method' errors across services that already had null-checked call sites (CaseEmailService, ConsultationService, DsoIntakeService, MilestoneService, TemplateLibraryService). * fix(quality): real phpstan bug fixes across controllers and services - CaseDefinitionController: use is_array() guard on getUploadedFile() return value (real NC impl returns array|null despite OCP stub). - AppointmentService::getBackend: drop redundant ?? on non-nullable getConfigValue() return; explicit empty-string fallback for backend type. - MilestoneService::getCaseProgress: delete dead else branch — early return above guarantees $definitions is non-empty. - TenantMiddleware: remove invalid '@throws Response' (not a Throwable). - StufController::soapResponse: add @phpstan-param narrowing to Http::STATUS_* union for DataDisplayResponse status code. * chore(quality): phpstan/psalm framework-drift suppressions with reasons Each ignore has an inline comment explaining why the rule is off-target: phpstan.neon: - IRequest::getContent() / setParameter(): exist in NC Request impl but missing from nextcloud/ocp interface stub. - IMessage::attachFile(): implemented in NC Mail\Message, not on OCP stub. - OC_Util::getVersionString: method_exists() guarded compat check. - 'Property never read, only written': DI-held services kept for future handlers and constructor signature stability. - 'Constant unused': documented defaults. - IRequest::getUploadedFile() strict-comparison: stub promises array but real impl returns array|null — keep the runtime guard. psalm.xml: - OC_Util UndefinedClass: version-compat. - DOMNode::getElementsByTagName UndefinedMethod: DOMNode narrows to DOMElement at runtime; psalm can't track the downcast. - UnusedParam in lib/Service: interface-contract params and planned-feature hooks kept for API stability. * chore(quality): phpmd baseline for pre-existing architectural findings Freezes 287 pre-existing PHPMD findings (159 ElseExpression, 93 MissingImport, 32 Avoid*, 3 Remove*) as architectural debt rather than fixing case-by-case. Future violations will fail the gate. Updates composer.json's 'phpmd' script to load the baseline file. * chore(licence): add REUSE.toml for repo-level REUSE compliance Declares SPDX copyright/licence for PHP (EUPL-1.2), JS/Vue/CSS (EUPL-1.2), and data/docs/locked-files (CC0-1.0) without touching individual source files (per ADR-014: PHP uses @author/@copyright/@license docblocks).
| * @package OCA\Procest\Service | ||
| * | ||
| * @author Conduction Development Team <dev@conductio.nl> | ||
| * @author Conduction Development Team <info@conduction.nl> |
There was a problem hiding this comment.
[unfixed: environment-permission-denied — container files owned by root, no sudo; escalated to Applier] CRITICAL: Server-Side Request Forgery (SSRF) — CWE-918 / OWASP A10:2021
The companion getCapabilities() method (line 158–198 of this file) forwards a caller-supplied URL to file_get_contents($capUrl) at line 192 without calling isUrlAllowed(), unlike the proxyRequest() method which correctly validates via allowlist at line 87. Any authenticated Nextcloud user can supply an arbitrary URL via GET /apps/procest/gis/capabilities?url=http://internal-host/... to make the server probe internal network hosts, cloud metadata endpoints (e.g., http://169.254.169.254/latest/meta-data/), or other sensitive services.
Remediation: Add the following at the top of getCapabilities() (before line 161):
if ($this->isUrlAllowed(url: $url) === false) {
throw new \RuntimeException('URL not in configured layer allowlist', 403);
}Also update GisProxyController::capabilities() to handle exception code 403 → return JSON 403 (matching the pattern in proxy()).
Closes #205
Summary
Integrated CustomPropertiesPanel and DocumentChecklist components into CaseDetail.vue to provide UI for managing case-specific properties and required documents. These components leverage the OpenRegister API to fetch property definitions and document types associated with case types.
Spec Reference
openspec/changes/case-management/design.mdChanges
src/views/cases/CaseDetail.vue— Added CustomPropertiesPanel and DocumentChecklist component imports, integrated into template with appropriate props and conditional renderingopenspec/changes/case-management/design.md— Status set to pr-createdTest Coverage
Components Implemented