This repository was archived by the owner on May 29, 2026. It is now read-only.
Release: merge development into beta#176
Open
github-actions[bot] wants to merge 103 commits into
Open
Conversation
- Merge openspec/README.md: keep Planix goal section, add artifact progression diagram, workflow steps, and full commands table - Add openspec/ROADMAP.md for feature tracking - Add openspec/architecture/README.md with ADR format guide - Add openspec/specs/README.md with feature spec format and lifecycle
…gn references Made-with: Cursor
Made-with: Cursor
…uestions - Resolve all 6 open research questions in ARCHITECTURE.md: CalDAV one-way export (V1), 1-level sub-tasks, configurable Procest bridge (Procest UI decides), per-task-only time tracking, GitHub sync via OpenConnector (V1), soft WIP limits - Update ADR-003 (Procest bridge) and ADR-004 (time tracking scope) - Create 8 OpenSpec changes with full artifacts (proposal, design, specs, tasks): register-schemas, projects, tasks, kanban-board, time-tracking, dashboard-my-work, admin-user-settings, procest-integration - Update all 7 feature specs to in-progress status with change links - Add conduction schema symlink (openspec/schemas/conduction) - Sync app description in info.xml and README.md with app-config.json goal
Replace example schema with 5 production schemas (task, project, column, timeEntry, label), add seed data (5 labels, 3 projects, 12 columns, 5 tasks, 3 time entries), register deep links for all schemas, and bump register version to 0.2.0.
…x data model Replace placeholder example schema with 5 production schemas (task, project, column, timeEntry, label) and 28 seed data objects. Fix repair step registration (info.xml), loadConfiguration() argument passing, and register definition fields required by ImportHandler. All quality checks pass (PHPCS, Psalm, PHPStan).
Implement register-schemas — 5 schemas with seed data for Planix data model
…, and l10n Add ProjectList, ProjectBoard, and ProjectBacklog views with supporting store, router entries, and MainMenu navigation. Include l10n strings, webpack config, and openspec plan/test-plan artifacts for the projects change and all related MVP changes.
Adds full project management surface to Planix — list, create, settings sidebar, member management, archive, and delete. All 47 tasks complete, verified by automated functional tests (all 11 TC pass). Key fixes applied during implementation: - webpack publicPath overridden to /apps-extra/planix/js/ (chunk 404s) - settings sidebar PATCH now includes members to prevent data loss on save - NcChip imported via component path (not available in @nextcloud/vue main index v8.16.0) - publicWrite/publicRead enabled on planix register via repair step migration
Add project management UI — list, create, settings, member management, archive and delete
…acking, settings, and procest integration Update README with restructured feature list, add six new feature docs with standards references, and include project screenshots.
Add bug tasks discovered by automated test agents to three changes: - admin-user-settings: health/metrics 500s, admin settings 404, label a11y - dashboard-my-work: KPI card a11y roles, missing alt text - tasks: status enum validation, PATCH support for partial updates
…Register init (#8) Merged by Hydra pipeline (admin override — PHPUnit CI failures are environment bootstrap issues, not code issues). All code review and security checks passed after 3 fix iterations.
Add 6 openspec change proposals (admin-settings-mvp archive, dashboard-my-work, kanban-mvp, label-crud, projects-crud, status-api) and 5 test scenarios for backend settings, frontend admin root, and default columns editor.
Contributor
Author
Quality Report — ConductionNL/planix @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 100/100 | |||
| npm | ❌ | ✅ 215/215 | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-04-14 05:30 UTC
Download the full PDF report from the workflow artifacts.
Contributor
Author
Quality Report — ConductionNL/planix @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 100/100 | |||
| npm | ❌ | ✅ 215/215 | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-04-14 08:41 UTC
Download the full PDF report from the workflow artifacts.
Contributor
Author
Quality Report — ConductionNL/planix @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 100/100 | |||
| npm | ❌ | ✅ 215/215 | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-04-14 09:21 UTC
Download the full PDF report from the workflow artifacts.
Contributor
Author
Quality Report — ConductionNL/planix @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 100/100 | |||
| npm | ❌ | ✅ 215/215 | |||
| PHPUnit | ⏭️ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Quality workflow — 2026-04-14 09:48 UTC
Download the full PDF report from the workflow artifacts.
…omplete-translations # Conflicts: # test-results/README.md # test-results/accessibility-results.md # test-results/api-results.md # test-results/performance-results.md # test-results/security-results.md # test-results/ux-results.md
- Add eslint-plugin-import-x and node-polyfill-webpack-plugin overrides/pins so the lockfile resolves without --legacy-peer-deps (lint-check ran 'npm ci' which failed on pre-existing peer-dependency conflicts). - Regenerate package-lock.json under strict peer resolution. - Declare the ADR-008 @SPEC JSDoc tag in eslint.config.js so the spec-coverage annotations stop tripping jsdoc/check-tag-names. - Add missing @param JSDoc lines and fix stylelint rule-empty-line-before errors in Settings.vue surfaced by the development merge.
…lations chore: kanban app icons, remove stale test-results, coverage report
Contributor
Author
Quality Report — ConductionNL/planix @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 100/100 | |||
| npm | ✅ | ✅ 426/426 | |||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/3 statements)
Quality workflow — 2026-05-26 05:25 UTC
Download the full PDF report from the workflow artifacts.
Contributor
Author
Quality Report — ConductionNL/planix @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| composer | ✅ | ✅ 100/100 | |||
| npm | ✅ | ✅ 426/426 | |||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ⏭️ |
Coverage: 0% (0/3 statements)
Quality workflow — 2026-05-26 06:10 UTC
Download the full PDF report from the workflow artifacts.
) Gate-5 route-auth: create HealthController and MetricsController for the /api/health and /api/metrics routes that were registered in routes.php but had no backing controller files, leaving those routes unreachable. Gate-7 no-admin-idor: add IUserSession 401 guard to SettingsController::index() so that the @NoAdminRequired READ endpoint explicitly returns 401 for unauthenticated callers rather than relying on implicit middleware. All 18 hydra gates green; phpstan no errors; php -l clean. Refs #250
All 16 scenarios in openspec/specs/register-schemas/spec.md are pure backend: PHP file content inspection, OpenRegister API validation (HTTP 400 responses), install-time repair steps, and version-skip logic. None have a browser UI surface, so the spec is excluded from gate-19 e2e-coverage enforcement with an explicit reason. Gate-19 result: uncovered=0, excluded=16, coverage_pct=null (no UI scenarios).
test(e2e): gate-19 e2e-coverage — 0 uncovered (register-schemas whole-spec excluded)
…alignment fix(phpcs): correct equals sign alignment in HealthController
…ross-tenant IDOR (#276) Fixes #257 (IDOR: any authenticated user could read/write all projects/tasks), #258 (missing owner field blocked creator-based RBAC), and #259 (migration docblock claimed publicWrite:true contradicting the membership-access spec). Changes: - planix_register.json: add `authorization` blocks to project, task, column, and timeEntry schemas enforcing member-based row-level read/write filtering; project delete restricted to owner or admin; timeEntry write restricted to the logging user. Add explicit `publicRead: false` and `publicWrite: false` to the register block. Add `owner` field to project schema for creator RBAC. Bump register version 0.2.0 -> 0.2.1, info version -> 0.2.3. - Version20260403000000.php: correct misleading docblock that claimed publicWrite:true — the intent is and has always been publicWrite:false. - tests/unit/Settings/PlanixRegisterSchemaTest.php: 7 new tests that mechanically assert the security properties introduced above, acting as regression guards so the IDOR cannot silently reopen.
- #260 ProjectLeaveDialog.mounted() no longer calls leaveProject as a probe; it inspects the already-fetched members array via fetchProject so Cancel can never inadvertently mutate state. - #261/#262 Split removeMember into a pure write action and a new getMemberTaskCount read action. confirmRemoveMember now queries the count first and only removes when count is zero, eliminating the remove-then-re-add race and the silent data-loss if the re-add fails. - #264 ProjectDeleteDialog now checks project.owner === currentUid || isAdmin before enabling the delete button. The canDelete guard is also enforced in confirm() as a server-side safety net. owner is now set on createProject so newly created projects are always gated correctly.
…eation policy (#278) - #263 deleteProject cascade error messages now explicitly tell the user some data may remain and to retry, rather than silently halting. - #265 allow_project_creation is now read by ProjectList: 'admins' policy hides the New project button and creation dialog from non-admin users. Added a UI control in Settings.vue so admins can configure the policy. - #266 SettingsService.setAdminSettings validates default_columns as a non-empty JSON array of non-empty strings before persisting; malformed values are rejected with a logger warning instead of being stored verbatim. New validateDefaultColumns() method is public and testable. - #267 DeepLinkRegistrationListener URL templates switched from hash-mode (#/tasks/{uuid}) to history-mode paths (/apps/planix/projects/{uuid}) matching the router configuration. All five hardcoded 'planix' strings replaced with Application::APP_ID.
…, error handling (#279) - #268 Remove the dead re-export of useObjectStore from store.js; the local modules/object.js is used only for boot-time configuration and no longer shadows the @conduction/nextcloud-vue store that projects.js actually imports. - #269 Dashboard KPI widgets now show real counts from the projects store (active/archived/total projects) instead of hardcoded placeholder values. Added a recent-projects list and a 'Go to projects' quick-action button. - #270/#271 MainMenu.openLink now passes 'noopener,noreferrer' to window.open. Documentation link updated from conduction.nl (marketing site) to planix.conduction.nl (app-specific docs site). - #272 Align version strings: info.xml bumped 0.2.1 → 0.2.3; register block version bumped 0.2.1 → 0.2.3 to match info.version and prevent OR from treating an already-imported register as stale. - #273/#267 DeepLinkRegistrationListener: all five hardcoded 'planix' literals replaced with Application::APP_ID. URL templates switched from hash-mode (#/path) to history-mode (/apps/planix/path) to match the Vue Router configuration. - #274 loadConfiguration validates x-openregister.app matches APP_ID before calling importFromApp, preventing accidental cross-app imports. - #275 MemberSearch.searchUsers now throws on non-2xx responses and surfaces all errors to the user via showError instead of silently logging to the console.
…add cross-project guards (C1 + H1) (#282) C1: project.update now requires owner match instead of member match. Any member could previously update owner/members fields, allowing a non-owner to evict the project owner. Now only the owner (or admin) may update a project. H1: task.create and column.create add parent-project membership predicate, preventing cross-project injection by an authenticated user who is not a member of the target project. timeEntry.create adds user:$userId match to prevent impersonation — a user may only log time as themselves. Bumps all affected schema versions (0.1.1 → 0.1.2) and register/ info.xml version (0.2.3 → 0.2.4).
…ion policy (C2 + H2) (#283) C2: InitializeSettings::run uses force:false (not force:true) so the repair step respects already-configured OR schema IDs and does not overwrite operator customisations on every install/upgrade. This was regressed on development when the retrofit spec added force:true; main was already correct. H2: allow_project_creation is now enforced server-side: - SettingsService::canCurrentUserCreateProject() reads the policy config key and returns false for non-admins when the policy is 'admins'. - ProjectController::checkCreatePolicy() exposes GET /api/projects/check-create-policy returning 200/403; requires @NoAdminRequired (authenticated user call). - ProjectCreationDialog::submit() calls the policy gate before delegating to OR, so a user who bypasses the client-side canCreateProject guard still receives a 403 from the server.
…ontroller, dashboard KPI (M1+M2+M3+L1+L2+L3) - M1: last-member leave guard in removeMember() + ProjectLeaveDialog disabled state - M2: owner field preserved in saveDetails() PUT payload - M3: task deep-link stub reads ?task= query param on ProjectBoard mount - L1: remove @NoAdminRequired from SettingsController admin write endpoints - L2: AbortController in MemberSearch cancels in-flight OCS requests - L3: remove hardcoded-0 open-tasks KPI tile from Dashboard, 4→3 column grid
CVE-2026-48808 — sandbox property allowlist bypass via column filter CVE-2026-48805 — sandbox state regression in deprecated internal wrappers CVE-2026-46636 — sandbox filter/tag/function allowlist bypass on re-render CVE-2026-48806 — sandbox __toString() bypass via dynamic mapping keys CVE-2026-48807 — sandbox __toString() bypass via Traversable in join/replace/in twig/twig was a transitive dependency (via edgedesign/phpqa); updated lock file from v3.26.0 to v3.27.0. No composer.json change required.
fix(deps): bump twig/twig to 3.27.0 (5 sandbox CVEs)
…ers, C3 leave endpoint C1: ProjectController::create() enforces allow_project_creation policy server-side. C2: addMember/removeMember use PATCH to prevent owner field null-wipe. C3: ProjectController::leaveProject() with _rbac: false enables non-owner leave.
Removes 2 scaffold-only change dirs with no authored proposal.md: - issue-180/ (only applier.json) - p2-meeting-management/ (only builds/) Created by bulk-scaffolding steps that didn't follow through to author. Re-create via /opsx-new when ready.
Non-owner members were getting a 403 when trying to leave a project
because the dialog called removeMember (PATCH on the OR object, subject
to owner-only RBAC). Replace with leaveProject which POSTs to
/api/projects/{id}/leave with server-side _rbac:false handling.
SettingsService:220 — add named parameter `raw:` to internal call of validateDefaultColumns() to satisfy the NamedParameters PHPCS sniff. ProjectController::create() — delegate the allow_project_creation policy check to checkCreatePolicy() instead of duplicating it inline. This removes the duplicated guard, gives checkCreatePolicy() a PHP caller so gate-6 orphan-auth passes, and consolidates the 403 path in one place. composer check:strict: exit 0. All 19 Hydra gates GREEN.
fix: pass composer check:strict — named-arg PHPCS + orphan-auth gate-6
…Project owner-wipe, test alignment
C1 (schema layer): tighten project.create rule from ["authenticated"] to
["admin"] in planix_register.json. The C1 proxy endpoint (ProjectController::create)
already owns enforcement server-side, so direct OR POSTs without admin
rights are now rejected at the schema layer as well, closing the bypass.
H1 (archiveProject owner-wipe): archiveProject() called updateProject(id,
{ status: 'archived' }) which triggered OR PUT semantics — filling every
missing schema property (including `owner`) with null. Switch to patchProject()
so only `status` is sent, matching the C2 fix already applied to addMember
and removeMember.
Test: PlanixRegisterSchemaTest::testProjectAuthorizationEnforcesMembershipForReadAndUpdate
was asserting a members-based update rule that no longer exists (wave-3
changed update to owner-match). Split into two tests: one for read-membership,
one for update-owner, both aligned with current security intent.
Bump appinfo/info.xml to 0.2.6 (immutable cache-bust).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automated PR to sync development changes to beta for beta release.
Merging this PR will trigger the beta release workflow.