Release: merge development into beta#2
Conversation
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
PHPUnit Tests
Integration Tests (Newman)
E2E Tests (Playwright)
Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (100 total)
npm dependencies (215 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
PHPUnit Tests
Integration Tests (Newman)
E2E Tests (Playwright)
Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (100 total)
npm dependencies (215 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 (100 total)
npm dependencies (215 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 (100 total)
npm dependencies (215 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 (100 total)
npm dependencies (215 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 (100 total)
npm dependencies (215 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 (100 total)
npm dependencies (416 total)
PHPUnit Tests
Code coverage: 0% (0 / 3 statements) Integration Tests (Newman)
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 (100 total)
npm dependencies (416 total)
PHPUnit Tests
Integration Tests (Newman)
E2E Tests (Playwright)
Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (100 total)
npm dependencies (416 total)
PHPUnit Tests
Code coverage: 0% (0 / 3 statements) Integration Tests (Newman)
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 (100 total)
npm dependencies (416 total)
PHPUnit Tests
Integration Tests (Newman)
E2E Tests (Playwright)
Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (100 total)
npm dependencies (416 total)
PHPUnit Tests
Code coverage: 0% (0 / 3 statements) Integration Tests (Newman)
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 (100 total)
npm dependencies (416 total)
PHPUnit Tests
Integration Tests (Newman)
E2E Tests (Playwright)
Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
npm dependencies (416 total)
PHPUnit Tests
Integration Tests (Newman)
E2E Tests (Playwright)
Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (100 total)
npm dependencies (416 total)
PHPUnit Tests
Code coverage: 0% (0 / 3 statements) Integration Tests (Newman)
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 (100 total)
npm dependencies (416 total)
PHPUnit Tests
Code coverage: 0% (0 / 3 statements) Integration Tests (Newman)
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 (100 total)
PHPUnit Tests
Integration Tests (Newman)
E2E Tests (Playwright)
Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (100 total)
npm dependencies (416 total)
PHPUnit Tests
Code coverage: 0% (0 / 3 statements) Integration Tests (Newman)
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 (100 total)
npm dependencies (416 total)
PHPUnit Tests
Code coverage: 0% (0 / 3 statements) Integration Tests (Newman)
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 (100 total)
npm dependencies (416 total)
PHPUnit Tests
Code coverage: 0% (0 / 3 statements) Integration Tests (Newman)
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
npm dependencies (416 total)
PHPUnit Tests
Integration Tests (Newman)
E2E Tests (Playwright)
Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (100 total)
npm dependencies (416 total)
PHPUnit Tests
Code coverage: 0% (0 / 3 statements) Integration Tests (Newman)
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
npm dependencies (416 total)
PHPUnit Tests
Integration Tests (Newman)
E2E Tests (Playwright)
Generated automatically by the Quality workflow.
|
Quality Report
Summary
PHP Quality
Vue Quality
Security
License Compliance
composer dependencies (100 total)
npm dependencies (416 total)
PHPUnit Tests
Code coverage: 0% (0 / 3 statements) Integration Tests (Newman)
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 (100 total)
npm dependencies (416 total)
PHPUnit Tests
Integration Tests (Newman)
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 (100 total)
npm dependencies (416 total)
PHPUnit Tests
Code coverage: 0% (0 / 3 statements) Integration Tests (Newman)
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 (100 total)
npm dependencies (416 total)
PHPUnit Tests
Code coverage: 0% (0 / 3 statements) Integration Tests (Newman)
E2E Tests (Playwright)Playwright E2E tests were not enabled for this run. Generated automatically by the Quality workflow.
|
Quality Report — ConductionNL/decidesk @
|
| Check | Result |
|---|---|
| PHP lint | ✅ |
| PHP phpcs | ✅ |
| PHP phpmd | ✅ |
| PHP psalm | ✅ |
| PHP phpstan | ✅ |
| PHP phpmetrics | ✅ |
| eslint | ✅ |
| stylelint | ✅ |
| Security (composer) | ✅ |
| Security (npm) | ✅ |
| License (composer) | ✅ 100/100 |
| License (npm) | ✅ 416/416 |
| PHPUnit | ✅ |
| Newman | ✅ |
| Playwright | ⏭️ |
Coverage: 0% (0/3 statements)
Quality workflow — 2026-04-13 18:03 UTC
Download the full PDF report from the workflow artifacts.
Quality Report — ConductionNL/decidesk @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 100/100 | |||
| npm | ✅ | ❌ | |||
| PHPUnit | ❌ | ||||
| Newman | ❌ | ||||
| Playwright | ❌ |
Quality workflow — 2026-04-13 18:11 UTC
Download the full PDF report from the workflow artifacts.
Annotates all 15 openspec specs with @e2e exclude or UI test coverage: Whole-spec excludes (backend/V1-not-built): mcp-tools — pure PHP DI/service layer, PHPUnit covered openregister-integration — data-layer contracts, no SPA form nextcloud-integration — OCP hooks (Calendar/Files/Talk/Activity), V1 process-configuration — no processTemplate pages in manifest, V1 meeting-efficiency — timer/cost/analytics UI not built, V1 resolution-minutes — generation/editing/approval not built, V1 voting-system — all scenarios require live in-progress state admin-settings — governing-body/member-import UI not built user-settings — notification/delegation/display prefs not built UI test files (tests/e2e/spec-coverage/): dashboard.spec.ts — KPI grid, app mount, NC widget meeting-management.spec.ts — list, add-dialog, live meeting mount decision-management.spec.ts — list, add-dialog, detail render agenda-management.spec.ts — list, add-dialog, live meeting agenda motion-amendment.spec.ts — list, add-dialog fields, detail render relation-tab-ui.spec.ts — agenda/motion/meeting/minutes details Gate-19 result: 150 scenarios, 58 covered, 92 excluded, 0 uncovered. Playwright: 30 passed, 1 skipped (no amendment seed data), 0 failed.
test(e2e): gate-19 spec-coverage — 0 uncovered scenarios
… fix PHPCS errors SettingsController was refactored to use #[AuthorizedAdminSetting] for admin enforcement (removing IGroupManager from the constructor), but SettingsControllerTest still passed a groupManager named arg that no longer exists, causing 7 setUp errors. Update the test to match the current constructor signature and remove tests for controller-level admin checks that are now handled by the framework attribute. Also fix 5 PHPCS errors: rewrite 3 inline ternary IFs in DecideskToolProvider as multi-line if/else blocks, auto-fix alignment in VotingBehaviourController, and remove a trailing blank line in WorkspaceService.
…lertest-and-phpcs fix: PHPUnit drift in SettingsControllerTest and 5 PHPCS errors
…#323) Resolves four CRITICALs: #296 C1 — Replace non-existent findObject/findObjects/getObject(register:,schema:,uuid:) calls throughout all service and controller files with the real OR API: find(id:,register:,schema:) + entity->jsonSerialize(), and setRegister/setSchema + findAll(['filters'=>...]) for collections. #297 C2 — Add missing `chair` field (string UUID) to Meeting schema in decidesk_register.json; bump Meeting schema version 0.3.0 → 0.4.0 and top-level register version 0.1.0 → 0.2.0. #298 C3 — Add missing `nextcloudUserId` field (string) to Participant schema in decidesk_register.json; bump Participant schema version 0.1.0 → 0.2.0. #299 C4 — MailReplyHandler now HMAC-signs _mail entries at ingestion time (hash_hmac/sha256 with per-round derived secret); verifyMailHmac() with hash_equals() guards ballot counting; email votes on isSecret rounds are rejected (reason: secret-ballot). Also: update test stubs and unit tests to match real OR API signatures; expand ternary jsonSerialize patterns to if/else blocks to satisfy PHPCS; update PHPMD baseline for pre-existing complexity violations.
…sk operations - DelegationController: pass caller UID to revoke/expire; service now verifies delegatedBy === caller (403 on mismatch) - WorkspaceController: pass caller UID to addMember/removeMember; service checks caller is owner or existing member - CommentController: pass caller UID to resolveThread; service checks author === caller; admins bypass via null - TaskController: pass caller UID to updateTaskStatus; service checks assignee/delegator === caller; admins bypass via null Fixes #304, #305, #310, #311
…agement participant - CommentController::create: ignore client-supplied author; always use session UID - EngagementController::capture: verify participant UUID matches caller's own participant record; NC admins bypass the check to allow chair-operated engagement panels Fixes #309
…loudUserId in chair check - AgendaController::requireChairOrAdmin: check nextcloudUserId field (PR #323) for chair/secretary role match, with fallback to legacy owner field - DecideskToolProvider::listOpenActionItems (scope=all): post-filter to action items linked to meetings the caller participates in; admins unfiltered - DecideskToolProvider::listRecentMeetings: post-filter to meetings the caller participates in via getCallerMeetingUuids helper; admins unfiltered Fixes #306, #307
…live, PHP8 attributes Closes #301, #308, #312, #319, #321, #322 - VotingService::checkQuorum() now fails closed (returns false) when no governance body is linked to the meeting instead of silently returning true and bypassing quorum enforcement entirely (#301). - openVotingRound() captures the checkQuorum() result and stores it as quorumMet on the VotingRound record rather than always hardcoding true (#312). - LiveMeetingController::recordLiveDecision() now requires chair or secretary role (parallel to AgendaController) instead of NC admin; adds requireChairOrAdmin() helper with nextcloudUserId field support and legacy owner fallback (#308). - MinutesController: all seven admin-only gates replaced with requireChairOrAdminForMinutes() which resolves the linked meeting UUID and checks participant roles; all @NoAdminRequired docblock annotations converted to #[NoAdminRequired] PHP 8 attributes (#308). - DecisionController, AnalyticsController: @NoAdminRequired docblocks converted to #[NoAdminRequired] PHP 8 attributes; AnalyticsController admin gate removed from getSummary/getCompletionRates so chairs can view meeting metrics (#308, #321). - DashboardController: @NoAdminRequired/@NoCSRFRequired docblocks on page() and catchAll() converted to PHP 8 attributes (#321). - InitializeSettings repair step pre-seeds voter_token_secret at install/upgrade time, eliminating the concurrent first-call race in VotingService::voterTokenSecret() (#319). - ActionItemExtractionService::saveExtracted() validates dueDate against ISO-8601 pattern before accepting, rejecting relative strtotime expressions such as "yesterday" or "next Monday" (#322).
…-SHA fallback) GitHub Actions OIDC publish is blocked so beta.108 never landed on npm. Switch to the dist-committed branch SHA (14572a47) that ships built dist/ directly. CnDataTable.effectiveColumns() now normalises string-array column shorthand so table views render real data instead of "—". Swap back to ^1.0.0-beta.108 once the Release workflow publishes to npm.
fix(deps): point @conduction/nextcloud-vue to pre-built beta.108 (CnDataTable table fix)
…, workflow default-deny, published-only ORI (#330) Closes #300 castVote now verifies caller's participant is a member of the meeting that owns the voting round before accepting the vote. Closes #302 saveShowOfHandsTally validates submitted counts against active participant count; rejects tallies that exceed meeting membership. Closes #303 getPublicState returns null (404) for secret rounds and for rounds whose lifecycle is not 'published', preventing anonymous projection display of draft or secret ballots. Closes #313 WorkflowService::isTransitionAllowed evaluates domain allow-flags (allowPause / allowAdjourn) before the chairOnlyTransitions list so domain restrictions cannot be short-circuited by a chair-only match. Closes #314 getDomainWorkflow falls back to RESTRICTED_WORKFLOW (quorum enforced, no pause, no adjourn) for unrecognized domains instead of the permissive 'operations' config. Closes #315 AgendaService::publishAgenda and reviseAgenda now read the full meeting object before saveObject to prevent partial updates from wiping required fields. Closes #316 OriController::index and ::show filter to lifecycle=='published' so anonymous ORI callers never see draft or unpublished objects. Closes #317 MotionService::transitionLifecycle rejects empty actorId to prevent unauthenticated DI-path callers from bypassing controller auth guards.
… auth to ORI publication (#331) Closes #318 VotingService::closeVotingRound no longer swallows lifecycle-transition and ORI-publication failures silently. State-machine violations (\InvalidArgumentException) are re-thrown so the controller returns an explicit error. Infrastructure errors are promoted from WARNING to ERROR level in logs. ORI publication errors are attached to the returned round payload as 'oriPublicationError' so callers can surface them. Closes #320 OriPublicationService::publish now reads 'ori_bearer_secret' from IAppConfig and includes it as an Authorization: Bearer header when set. The key is added to SettingsService::CONFIG_KEYS so it can be saved from the admin UI. When the key is not configured the Authorization header is omitted (intentional: ORI endpoints that require auth will return 401, exposing the gap rather than silently failing with 200).
Replace the deprecated customComponents prop with the v2 registry prop
on CnAppRoot (ADR-036). Each page component is wrapped as
{ kind: 'page', component } via src/registry.js.
feat(adr-036): migrate App.vue to v2 kind-tagged registry prop
…ent @self.relations.meeting participant filters (C3/H1/H2) (#335) The participant schema has no meeting relation; five sites were filtering by '@self.relations.meeting' which silently returned empty results, making all chair/secretary and participant membership checks fail-open. Introduces ParticipantResolver service with canonical meeting→governanceBody→participant path (mirrors VotingService.checkQuorum) and routes AgendaController, LiveMeetingController, MinutesController, VotingService (castVote preset and saveShowOfHandsTally), and DecideskToolProvider.requireParticipantOrAdmin through it.
- MotionCoauthorController: pass callerUid + callerIsAdmin to all mutators; catch InvalidArgumentException (403) and RuntimeException (404/409) appropriately - MotionCoauthorService: add checkMotionAccess() guard (checks @self.owner proposer match and coAuthors membership) + resolveParticipantUuid() helper using canonical OR-API (setRegister/setSchema/findAll/jsonSerialize) - EngagementController: replace non-existent findObjects() with canonical setRegister/setSchema/findAll; use named arg on internal call - WorkspaceService: add resolveParticipantUuid() helper; fix isMembershipManager() to resolve caller's NC UID to participant UUID before checking against members[] (which stores participant UUIDs, not NC UIDs) — closes H3 UID/UUID confusion
…ure (C2/C5/L1) (#337) - C2: remove MailReplyHandler from background-jobs in info.xml and stop scheduling it in Application::boot() — email-voting is disabled until the feature is fully audited; removes unused IJobList import - C5: restrict ORI email field to Organization-typed resources only; was previously included for all types (meetings, motions, bodies), leaking any email field present on those objects to the public API - L1: fix serializeOri() id resolution to prefer entity uuid field over @self.id (internal OR metadata); @self.id must not be surfaced publicly - Fix pre-existing PHPStan: Application.php DI registrations were missing participantResolver param for MinutesController/VotingService/ LiveMeetingController, groupManager for TaskController/CommentController/ MotionCoauthorController, container+groupManager for EngagementController, and had spurious groupManager on AnalyticsController
…atch, find() named args (M1-M4) (#338) - M1: DelegationController revoke/expire — add IGroupManager; pass null (skip ownership check) for admins, callerUid for non-admins, enabling admins to revoke/expire any delegation without ownership error - M2: OriController::show — lifecycle gate now uses null-check so schemas without a lifecycle/status field (votes, persons, etc.) pass through instead of returning 404 on every request - M3: OriPublicationService::publish — rethrow \Throwable after logging so the outer VotingService catch can attach oriPublicationError to the round data (previously swallowed all exceptions, making outer catch dead) - M4: Standardize find() to named-arg pattern in DelegationService, TaskService, MotionCoauthorService — remove setRegister/setSchema prefix - L2: already resolved by PR A (AgendaController requireChairOrAdmin no longer uses findAll with register/schema in filters[]) - L3: already present in MailReplyHandler::signMailEntry (@SPEC tag exists) - Fix Application.php DI: add groupManager to DelegationController wiring
…CVEs Fixes CVE-2026-48805, CVE-2026-48806, CVE-2026-48807, CVE-2026-48808, CVE-2026-46636 (all twig/twig sandbox bypass, reported 2026-05-27). twig/twig was a transitive dependency via edgedesign/phpqa (constraint ~1.38|~2.7|>=3); bumped from v3.26.0 to v3.27.0 via `composer update twig/twig --with-dependencies`. `composer audit` is now clean.
fix(security): bump twig/twig to v3.27.0 (5 sandbox-bypass CVEs)
…ts traversal C1 VotingService.php:636 — anonymisation used scalar votingRoundId filter; votes are linked via relations.voting-round, not a scalar field. Fixes silent GDPR anonymisation no-op that confirmed success while leaving all vote values intact. C2 VotingBehaviourService.php — getStats used scalar governanceBodyId/ participantId/votingRoundId filters; none exist on those schemas. Fixed with canonical traversal: body→motions (relations.governance-body)→rounds (relations.motion)→votes (relations.voting-round + relations.participant). Also adds proxiesReceived increment (via delegator relation scan). C3 DecideskToolProvider.php — getCallerMeetingUuids read @self.relations.meeting from participant records; participants have no meeting relation. Fixed: walk participant→governance-body relation, then query meetings by relations.governance-body. Non-admin MCP scoping now actually resolves. C4 AgendaService.php — 4 sites used @self.relations.meeting on agenda-item and participant queries. OR MagicSearchHandler strips @-prefixed flat keys; queries returned unscoped/empty results. Fixed: agenda-item queries use relations.meeting; participant query delegates to ParticipantResolver. Also injects ParticipantResolver dependency and guards non-existent CalendarEventService::updateMeetingEvent with method_exists. C5 DecideskToolProvider.php — getMeetingDetails used @self.relations.meeting on agendaItems/decisions/actionItems queries. Same OR filter bug. Fixed: switch to relations.meeting (no @self. prefix).
Update six unit test files to match updated constructor signatures (ParticipantResolver, IAppConfig injections) and corrected service logic (ObjectEntity mock types, requireChairOrAdminForMinutes flow, getCallerMeetingUuids admin bypass, isParticipant guard setup).
PHPCS: remove inline-IF ternaries in TaskController and CommentController (callerIsAdmin bypass paths) by extracting to explicit if/else blocks. PHPMD: - Remove unused \$lifecycleError assignment in VotingService::closeVotingRound - Eliminate BooleanArgumentFlag from MotionCoauthorService::addCoauthor, removeCoauthor, updateMotionText — replace \$callerIsAdmin bool with null-callerUid admin-bypass convention (null = skip access check) - Fix MissingImport in AgendaService, CommentService, DelegationService, MotionCoauthorService, WorkspaceService (use imported class names) - Rename short variables \$p/\$m in DecideskToolProvider::getCallerMeetingUuids - Rename LongVariable \$callerParticipantUuid in WorkspaceService - Remove ElseExpression in ActionItemExtractionService::saveExtracted - Baseline architectural violations (NPath/CC/LongClass) for DecideskToolProvider, VotingBehaviourService, VotingService, MinutesController, AgendaController PHPUnit: 176 tests pass (37 skipped), 0 errors. Stylelint: auto-fixed rule-empty-line-before in 9 tab components.
…ylelint fix: make composer check:strict pass on development
Removes 7 scaffold-only change dirs that contained only tooling metadata (.openspec.yaml, context-brief.md, hydra.json, README.md, builds/, pipeline-logs) with no authored proposal.md. Created by bulk-scaffolding steps that didn't follow through to author. Removed: - pluggable-integration-registry, integration-calendar, integration-analytics (only README.md + hydra.json) - p2-meeting-management-core-t2, p2-meeting-management-core-t3, p2-motion-and-voting-other-t2, p2-motion-and-voting-other-t3 (only .openspec.yaml + builds/ + context-brief.md, no proposal) Re-create individual changes via /opsx-new when ready to author.
Bugs fixed: - AgendaController publish/advanceBobPhase/processHamerstukken/reorder/revise: add explicit `getUser() === null → 401` as the FIRST statement in each method so unauthenticated requests return 401 before any service or CSRF middleware interaction can produce an incorrect 500 or 422. advanceBobPhase specifically now guards before the objectService->find() call that previously ran without authentication. - MotionController + VotingController: add missing #[NoAdminRequired] PHP 8 attribute to all action methods (only @NoAdminRequired docblock existed). Without the attribute, NC 28+ SecurityMiddleware treats the endpoint as admin-only and blocks non-admin authenticated users. Also fixes the requireChairOrSecretary() helper in both controllers to return 401 (not 403) when getUser() is null — unauthenticated is different from authenticated-but-unauthorised. Bug 4 (motion-voting routes): routes ARE registered in appinfo/routes.php and controller methods DO exist. The 405 responses Newman observed were caused by the missing #[NoAdminRequired] attribute; fixed above. Adds unit tests asserting: - every affected endpoint returns 401 (not 403/422/500) for null user - service methods are never called for unauthenticated requests - MotionController and VotingController action methods carry #[NoAdminRequired]
…rder fix: harden auth guards on agenda/motion/voting endpoints
…auth bypass) + H1 H4 sweep C-1: ActionItemAnalyticsService resolved ObjectService via wrong DI key 'OpenRegisterObjectService'; replace with canonical 'OCA\OpenRegister\Service\ObjectService' at all 3 call sites (getSummary, getCompletionRates, getMyItems). Silent Throwable catch returned plausible-looking zero dashboards, hiding the failure. Add integration test asserting non-empty response when at least one action-item exists. C-2: VotingBehaviourController::getStats compared participant UUID directly against NC UID ($participantId === $uid) — they are different namespaces and never match, so every non-admin always received 403 on their own stats. Fix: inject ObjectService, resolve participant by UUID, compare nextcloudUserId (with owner fallback) against the caller's NC UID. Unit tests updated to pass a UUID + mock the object lookup; add a new test asserting 403 when the participant object cannot be found. H-1: MinutesGenerationService::fetchRelatedObjects filtered by flat 'meeting' key; replace with 'relations.meeting' to match the OR relation filter convention (wave-3 swept AgendaService + DecideskToolProvider but missed this helper). H-4: MinutesController::submitForApproval called saveObject with schema: 'Minutes' (PascalCase); correct to lowercase 'minutes' matching the register schema slug.
Automated PR to sync development changes to beta for beta release.
Merging this PR will trigger the beta release workflow.