Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
443 commits
Select commit Hold shift + click to select a range
ed493df
docs(openspec): design.md for the 22 LOW-triaged specs (full schema c…
rubenvdlinde May 1, 2026
876df64
feat(widgets): add label widget (REQ-LBL-001..007)
rubenvdlinde May 2, 2026
a82b0df
feat(widgets): add label widget (REQ-LBL-001..007)
rubenvdlinde May 2, 2026
e1781fa
feat(widgets): add unified widget add/edit modal (REQ-WDG-010..014)
rubenvdlinde May 2, 2026
d80a97c
feat(widgets): add unified widget add/edit modal (REQ-WDG-010..014)
rubenvdlinde May 2, 2026
f0ae36b
feat(initial-state): add typed provide/inject contract (REQ-INIT-001.…
rubenvdlinde May 2, 2026
2213a30
feat(initial-state): add typed provide/inject contract (REQ-INIT-001.…
rubenvdlinde May 2, 2026
671115b
feat(widgets): add text-display widget (REQ-TXT-001..005)
rubenvdlinde May 2, 2026
171ace6
feat(widgets): add text-display widget (REQ-TXT-001..005)
rubenvdlinde May 2, 2026
fee8008
feat(grid): responsive breakpoints + GridStack v12 bump (REQ-GRID-007…
rubenvdlinde May 2, 2026
711519b
feat(grid): responsive breakpoints + GridStack v12 bump (REQ-GRID-007…
rubenvdlinde May 2, 2026
81ab386
feat(resources): add admin-only base64 resource upload pipeline (REQ-…
rubenvdlinde May 2, 2026
de061cd
feat(resources): add admin-only base64 resource upload pipeline (REQ-…
rubenvdlinde May 2, 2026
aa483e8
feat(dashboards): add dashboard icons (REQ-ICON-001..004)
rubenvdlinde May 2, 2026
8d3dcde
feat(dashboards): add dashboard icons (REQ-ICON-001..004)
rubenvdlinde May 2, 2026
d0d5f7c
feat(dashboard-icons): custom-icon upload pattern (REQ-ICON-005..009)
rubenvdlinde May 2, 2026
ef4c276
feat(dashboard-icons): custom-icon upload pattern (REQ-ICON-005..009)
rubenvdlinde May 2, 2026
651f41d
feat(dashboards): add group_shared scope + visible-to-user resolution
rubenvdlinde May 2, 2026
e00ed71
feat(dashboards): add group_shared scope + visible-to-user resolution
rubenvdlinde May 2, 2026
5759323
feat(dashboards): admin UI + tests for default group dashboard (REQ-D…
rubenvdlinde May 2, 2026
651ae3d
feat(dashboards): admin UI + tests for default group dashboard (REQ-D…
rubenvdlinde May 2, 2026
f400346
feat(admin): runtime-gate personal dashboard creation behind allow_us…
rubenvdlinde May 2, 2026
69e61eb
feat(admin): runtime-gate personal dashboard creation behind allow_us…
rubenvdlinde May 2, 2026
fedc6df
feat(dashboard-switcher): add slide-in sidebar (REQ-SWITCH-001..007)
rubenvdlinde May 2, 2026
b66d1e2
feat(dashboard-switcher): add slide-in sidebar (REQ-SWITCH-001..007)
rubenvdlinde May 2, 2026
07b90bc
feat(resources): add public serving + listing endpoints (REQ-RES-006.…
rubenvdlinde May 2, 2026
465f0a3
feat(resources): add public serving + listing endpoints (REQ-RES-006.…
rubenvdlinde May 2, 2026
4296112
feat(dashboards): active-dashboard resolver + persist preference (REQ…
rubenvdlinde May 2, 2026
eb65240
feat(dashboards): active-dashboard resolver + persist preference (REQ…
rubenvdlinde May 2, 2026
529c997
feat(admin): add group priority order setting + admin UI (REQ-ASET-01…
rubenvdlinde May 2, 2026
7cf8f0f
feat(admin): add group priority order setting + admin UI (REQ-ASET-01…
rubenvdlinde May 2, 2026
7c5e689
feat(resources): add SVG sanitiser + invalid_svg envelope (REQ-RES-00…
rubenvdlinde May 2, 2026
2880828
feat(resources): add SVG sanitiser + invalid_svg envelope (REQ-RES-00…
rubenvdlinde May 2, 2026
27265a4
feat(grid): collision-aware widget placement helper (REQ-GRID-006/014)
rubenvdlinde May 2, 2026
1100391
feat(grid): collision-aware widget placement helper (REQ-GRID-006/014)
rubenvdlinde May 2, 2026
0f2cbf2
feat(dashboards): fork-current-as-personal endpoint (REQ-DASH-020..022)
rubenvdlinde May 2, 2026
2bd6059
feat(dashboards): fork-current-as-personal endpoint (REQ-DASH-020..022)
rubenvdlinde May 2, 2026
7fafe2d
feat(routing): add primary-group resolver as single source of truth (…
rubenvdlinde May 2, 2026
b6e4a98
feat(routing): add primary-group resolver as single source of truth (…
rubenvdlinde May 2, 2026
230ca3e
feat(widgets): add image widget with object-fit + click-through (REQ-…
rubenvdlinde May 2, 2026
6bd713a
feat(widgets): add image widget with object-fit + click-through (REQ-…
rubenvdlinde May 2, 2026
0e00f51
feat(widgets): add right-click context menu (REQ-WDG-015..017)
rubenvdlinde May 2, 2026
8b941ea
feat(widgets): add right-click context menu (REQ-WDG-015..017)
rubenvdlinde May 2, 2026
9669721
feat(widgets): add nc-widget proxy renderer + bridge polling helper
rubenvdlinde May 2, 2026
6d01222
feat(widgets): add nc-widget proxy renderer + bridge polling helper
rubenvdlinde May 2, 2026
242677b
feat(widgets): add link-button widget with createFile endpoint (REQ-L…
rubenvdlinde May 2, 2026
310088a
feat(widgets): add link-button widget with createFile endpoint (REQ-L…
rubenvdlinde May 2, 2026
d799521
feat(runtime-shell): add page-level workspace orchestrator (REQ-SHELL…
rubenvdlinde May 2, 2026
e36c114
feat(runtime-shell): add page-level workspace orchestrator (REQ-SHELL…
rubenvdlinde May 2, 2026
cdb322c
merge: feature/dashboard-icons into openspec-merged
rubenvdlinde May 2, 2026
9c1594e
merge: feature/dashboard-icons into openspec-merged
rubenvdlinde May 2, 2026
f888671
merge: feature/resource-uploads into openspec-merged
rubenvdlinde May 2, 2026
b1eca29
merge: feature/resource-uploads into openspec-merged
rubenvdlinde May 2, 2026
7b33657
merge: feature/responsive-grid-breakpoints into openspec-merged
rubenvdlinde May 2, 2026
0c2fba7
merge: feature/responsive-grid-breakpoints into openspec-merged
rubenvdlinde May 2, 2026
8e464f0
merge: feature/widget-collision-placement into openspec-merged
rubenvdlinde May 2, 2026
cc6c27f
merge: feature/widget-collision-placement into openspec-merged
rubenvdlinde May 2, 2026
b7fe81d
merge: feature/text-display-widget into openspec-merged
rubenvdlinde May 2, 2026
31fa9f8
merge: feature/text-display-widget into openspec-merged
rubenvdlinde May 2, 2026
6cfd015
merge: feature/custom-icon-upload-pattern into openspec-merged
rubenvdlinde May 2, 2026
7e05149
merge: feature/custom-icon-upload-pattern into openspec-merged
rubenvdlinde May 2, 2026
f37e328
merge: feature/dashboard-switcher-sidebar into openspec-merged
rubenvdlinde May 2, 2026
4a71174
merge: feature/dashboard-switcher-sidebar into openspec-merged
rubenvdlinde May 2, 2026
f93d547
merge: feature/default-dashboard-flag into openspec-merged
rubenvdlinde May 2, 2026
891dc55
merge: feature/default-dashboard-flag into openspec-merged
rubenvdlinde May 2, 2026
8753903
merge: feature/active-dashboard-resolution into openspec-merged
rubenvdlinde May 2, 2026
7069d52
merge: feature/active-dashboard-resolution into openspec-merged
rubenvdlinde May 2, 2026
26fcc17
merge: feature/allow-personal-dashboards-flag into openspec-merged
rubenvdlinde May 2, 2026
bd6c2eb
merge: feature/allow-personal-dashboards-flag into openspec-merged
rubenvdlinde May 2, 2026
a17237d
merge: feature/group-priority-order into openspec-merged
rubenvdlinde May 2, 2026
9640e38
merge: feature/group-priority-order into openspec-merged
rubenvdlinde May 2, 2026
a574236
merge: feature/group-routing into openspec-merged
rubenvdlinde May 2, 2026
32b7032
merge: feature/group-routing into openspec-merged
rubenvdlinde May 2, 2026
00ece5d
test: harden vitest CSS noop for transitive @nextcloud/vue chunks
rubenvdlinde May 2, 2026
1e595bc
test: harden vitest CSS noop for transitive @nextcloud/vue chunks
rubenvdlinde May 2, 2026
c35ae49
merge: feature/fork-current-as-personal into openspec-merged
rubenvdlinde May 2, 2026
81a7418
merge: feature/fork-current-as-personal into openspec-merged
rubenvdlinde May 2, 2026
9b7f75e
merge: feature/image-widget into openspec-merged
rubenvdlinde May 2, 2026
c07b1e6
merge: feature/image-widget into openspec-merged
rubenvdlinde May 2, 2026
2790848
merge: feature/link-button-widget into openspec-merged
rubenvdlinde May 2, 2026
78fa06e
merge: feature/link-button-widget into openspec-merged
rubenvdlinde May 2, 2026
9b729c0
merge: feature/nc-dashboard-widget-proxy into openspec-merged
rubenvdlinde May 2, 2026
2943a3b
merge: feature/nc-dashboard-widget-proxy into openspec-merged
rubenvdlinde May 2, 2026
2811db8
fix(phpstan): suppress FileController status-code widening + relax se…
rubenvdlinde May 2, 2026
6a25811
fix(phpstan): suppress FileController status-code widening + relax se…
rubenvdlinde May 2, 2026
90e386a
chore: update SBOM
github-actions[bot] May 2, 2026
9a9461c
chore: update SBOM
github-actions[bot] May 2, 2026
78af2c9
merge: development into openspec-merged
rubenvdlinde May 2, 2026
326184f
merge: development into openspec-merged
rubenvdlinde May 2, 2026
7863796
fix(merge): align tests with new constructors + ESM stubs for Vitest
rubenvdlinde May 2, 2026
dd574c7
fix(merge): align tests with new constructors + ESM stubs for Vitest
rubenvdlinde May 2, 2026
6929567
Merge pull request #99 from ConductionNL/feature/openspec-merged
rubenvdlinde May 2, 2026
948efcc
Merge pull request #99 from ConductionNL/feature/openspec-merged
rubenvdlinde May 2, 2026
91e4f83
chore: openspec validate clean + npm audit fix + dashboard-sharing-fo…
rubenvdlinde May 2, 2026
b4f6233
chore: openspec validate clean + npm audit fix + dashboard-sharing-fo…
rubenvdlinde May 2, 2026
c2a122d
test(dashboard): add testGroupSharedConstants + permission constant a…
rubenvdlinde May 2, 2026
50fa57d
test(dashboard): add testGroupSharedConstants + permission constant a…
rubenvdlinde May 2, 2026
0c4ea0b
chore(test): wire up Playwright E2E runner for spec-derived suite
rubenvdlinde May 2, 2026
0b50c85
chore(test): wire up Playwright E2E runner for spec-derived suite
rubenvdlinde May 2, 2026
0958153
Merge pull request #100 from ConductionNL/chore/openspec-followups
rubenvdlinde May 2, 2026
430ad50
Merge pull request #100 from ConductionNL/chore/openspec-followups
rubenvdlinde May 2, 2026
b99d5fd
chore(deps): bump @nextcloud/axios from 2.5.2 to 2.6.0
rubenvdlinde May 2, 2026
58e8282
chore(deps): bump @nextcloud/axios from 2.5.2 to 2.6.0
rubenvdlinde May 2, 2026
a7ce164
chore(test): bump Playwright navigationTimeout 15s → 60s
rubenvdlinde May 2, 2026
21610f8
chore(test): bump Playwright navigationTimeout 15s → 60s
rubenvdlinde May 2, 2026
b4e3278
Merge pull request #101 from ConductionNL/chore/bump-nextcloud-axios-2.6
rubenvdlinde May 2, 2026
a754c3e
Merge pull request #101 from ConductionNL/chore/bump-nextcloud-axios-2.6
rubenvdlinde May 2, 2026
aff208c
Merge pull request #102 from ConductionNL/chore/playwright-nav-timeout
rubenvdlinde May 2, 2026
91af142
Merge pull request #102 from ConductionNL/chore/playwright-nav-timeout
rubenvdlinde May 2, 2026
aa4dadd
Merge remote-tracking branch 'origin/feature/wave2-derived-spec-propo…
rubenvdlinde May 2, 2026
77530e2
chore(openspec): remove 24 stale change folders duplicated by wave2 m…
rubenvdlinde May 2, 2026
fa102a8
feat(cascade-events): add DashboardDeletedEvent + 11 listener stubs
rubenvdlinde May 2, 2026
9ae6e1b
feat(admin-roles): add Dashboard Admin / Editor / Viewer role system
rubenvdlinde May 2, 2026
60a0dd8
feat(dashboards): add hierarchical dashboard tree with slug paths
rubenvdlinde May 2, 2026
01d9c2e
feat(dashboards): add publication-state workflow (draft/published/sch…
rubenvdlinde May 2, 2026
94ed962
feat(reactions): implement dashboard emoji reactions (REQ-RXN-001..009)
rubenvdlinde May 2, 2026
10bfa89
feat(comments): add dashboard-comments capability backed by IComments…
rubenvdlinde May 2, 2026
314d4f3
feat(dashboards): add per-dashboard version history with debounced sn…
rubenvdlinde May 2, 2026
f2790f9
feat(dashboards): add edit-time locking with 15-min TTL and 60s heart…
rubenvdlinde May 2, 2026
cd2b213
feat(feeds): add per-user RSS/Atom dashboard feeds
rubenvdlinde May 2, 2026
8ed4843
feat(dashboards): add per-language content variants (REQ-DASH-038..044)
rubenvdlinde May 2, 2026
7fa2f5e
feat(dashboards): add ZIP export/import for dashboards (REQ-EXIM-001.…
rubenvdlinde May 2, 2026
b5999ad
feat(dashboards): add metadata-fields capability with type-safe registry
rubenvdlinde May 2, 2026
c57bdc3
feat(analytics): add privacy-preserving dashboard view analytics
rubenvdlinde May 2, 2026
e2852b9
feat(import): add Confluence HTML export importer (REQ-CFLI-001..012)
rubenvdlinde May 2, 2026
31a9704
feat(activity): integrate MyDash events into Nextcloud Activity feed …
rubenvdlinde May 3, 2026
6c1f7fb
feat(cleanup): add orphaned-data scan and purge pipeline
rubenvdlinde May 3, 2026
6081884
feat(search): add Nextcloud unified search integration for MyDash
rubenvdlinde May 3, 2026
f6b818a
feat(jobs): add background job feed refresh with cache table
rubenvdlinde May 3, 2026
78da9ee
feat(widgets): add header banner widget (REQ-HDR-001..012)
rubenvdlinde May 3, 2026
dbd214f
feat(people): add People widget with paginated user directory (REQ-PP…
rubenvdlinde May 3, 2026
bc602f9
feat(files-widget): add inline Nextcloud Files browser widget (REQ-FL…
rubenvdlinde May 3, 2026
690d39c
feat(widgets): add Quicklinks widget (REQ-QLNK-001..011)
rubenvdlinde May 3, 2026
d083f56
feat(video): add Video widget with YouTube/Vimeo/PeerTube/Nextcloud F…
rubenvdlinde May 3, 2026
77576a4
feat(news): add RSS/Atom news widget with merged feed display (REQ-NE…
rubenvdlinde May 3, 2026
5c67051
feat(calendar): add calendar widget aggregating internal NC calendars…
rubenvdlinde May 3, 2026
a02003c
feat(image-widget): add Files picker as third image source (REQ-IMP-0…
rubenvdlinde May 3, 2026
18613af
feat(widgets): add links-widget multi-column link grid (REQ-LNKS-001.…
rubenvdlinde May 3, 2026
7c60c56
feat(link-button): add list-mode display for multiple links per widge…
rubenvdlinde May 3, 2026
dec8c46
feat(menu): add hierarchical menu widget with dropdown/megamenu/tree …
rubenvdlinde May 3, 2026
4126e99
feat(widgets): add markdown content mode to text-display widget (REQ-…
rubenvdlinde May 3, 2026
269de65
feat(text-widget): add visual table editor and renderer (REQ-TBLE-001…
rubenvdlinde May 3, 2026
9f7d580
feat(dashboards): add admin bulk operations endpoints (REQ-BULK-001..…
rubenvdlinde May 3, 2026
c763c51
feat(templates): add dashboard template gallery + save-as-template (R…
rubenvdlinde May 3, 2026
7e0d253
feat(navigation): add organisation-wide navigation editor (REQ-ONAV-0…
rubenvdlinde May 3, 2026
f65e8f6
feat(footer): add global + per-dashboard footer customization (REQ-FT…
rubenvdlinde May 3, 2026
2b73b82
feat(showcases): add bundled demo dashboard showcases (REQ-DEMO-001..…
rubenvdlinde May 3, 2026
c5870a2
feat(setup-wizard): add multi-step first-run admin wizard (REQ-WIZ-00…
rubenvdlinde May 3, 2026
81e005e
feat(cli): add shared mydash CLI suite with global flags (REQ-CLI-001…
rubenvdlinde May 3, 2026
e8a49b7
merge: feature/wave2-admin-roles into wave2-merged
rubenvdlinde May 3, 2026
5bca14e
merge: feature/wave2-dashboard-cascade-events into wave2-merged
rubenvdlinde May 3, 2026
d415ce0
merge: feature/wave2-comments into wave2-merged
rubenvdlinde May 3, 2026
dd8f3b8
merge: feature/wave2-reactions into wave2-merged
rubenvdlinde May 3, 2026
7b74fde
merge: feature/wave2-versioning into wave2-merged
rubenvdlinde May 3, 2026
ddf26d9
merge: feature/wave2-metadata-fields into wave2-merged
rubenvdlinde May 3, 2026
262952b
merge: feature/wave2-language-content into wave2-merged
rubenvdlinde May 3, 2026
2f9736c
merge: feature/wave2-view-analytics into wave2-merged
rubenvdlinde May 3, 2026
66d9f0c
merge: feature/wave2-rss-feeds into wave2-merged
rubenvdlinde May 3, 2026
df54755
merge: feature/wave2-locking into wave2-merged
rubenvdlinde May 3, 2026
bd5bc97
merge: feature/wave2-bgjob-feed-refresh into wave2-merged
rubenvdlinde May 3, 2026
3daed58
merge: feature/wave2-nc-search into wave2-merged
rubenvdlinde May 3, 2026
0251822
merge: feature/wave2-orphaned-cleanup into wave2-merged
rubenvdlinde May 3, 2026
507ef07
merge: feature/wave2-header-widget into wave2-merged
rubenvdlinde May 3, 2026
57f5fa9
merge: feature/wave2-divider-widget into wave2-merged
rubenvdlinde May 3, 2026
b64c56c
merge: feature/wave2-files-widget into wave2-merged
rubenvdlinde May 3, 2026
4553730
merge: feature/wave2-people-widget into wave2-merged
rubenvdlinde May 3, 2026
8ea26f7
merge: feature/wave2-quicklinks-widget into wave2-merged
rubenvdlinde May 3, 2026
dfa890f
merge: feature/wave2-news-widget into wave2-merged
rubenvdlinde May 3, 2026
1f863d2
merge: feature/wave2-video-widget into wave2-merged
rubenvdlinde May 3, 2026
f3c8c00
merge: feature/wave2-calendar-widget into wave2-merged
rubenvdlinde May 3, 2026
8566a87
merge: feature/wave2-links-widget into wave2-merged
rubenvdlinde May 3, 2026
8e690ad
merge: feature/wave2-menu-widget into wave2-merged
rubenvdlinde May 3, 2026
3921725
merge: feature/wave2-image-widget-media-picker into wave2-merged
rubenvdlinde May 3, 2026
c6f4c5d
merge: feature/wave2-link-button-widget-list-mode into wave2-merged
rubenvdlinde May 3, 2026
a8b2caa
merge: feature/wave2-text-widget-markdown into wave2-merged
rubenvdlinde May 3, 2026
711d189
merge: feature/wave2-text-widget-tables into wave2-merged
rubenvdlinde May 3, 2026
30a1147
merge: feature/wave2-footer-customization into wave2-merged
rubenvdlinde May 3, 2026
6f8154f
fix: resolve leftover merge markers from text-widget-tables merge
rubenvdlinde May 3, 2026
e4bae7a
merge: feature/wave2-navigation-editor-org into wave2-merged
rubenvdlinde May 3, 2026
46d134a
merge: feature/wave2-dashboard-templates into wave2-merged
rubenvdlinde May 3, 2026
3e762bb
chore: add .github/CODEOWNERS for auto-review-request (#103)
rubenvdlinde May 3, 2026
8fcf910
merge: feature/wave2-dashboard-bulk-operations into wave2-merged
rubenvdlinde May 3, 2026
479220a
merge: feature/wave2-demo-data-showcases into wave2-merged
rubenvdlinde May 3, 2026
7cfa16c
merge: feature/wave2-setup-wizard into wave2-merged
rubenvdlinde May 3, 2026
a9f498a
fix: align AdminController docblocks + extend stale unit-test mocks
rubenvdlinde May 3, 2026
b622a14
chore(openspec): remove IntraVox/voxcloud references in favour of neu…
rubenvdlinde May 3, 2026
9578d25
feat(openspec): mydash-adopt-or-abstractions — manifest + runtime-onl…
rubenvdlinde May 3, 2026
5a64832
merge: development into wave2-merged
rubenvdlinde May 3, 2026
c558f6e
feat(openspec): mydash-legacy-quality-cleanup tracking change (#106)
rubenvdlinde May 3, 2026
829cd16
Merge remote-tracking branch 'origin/development' into feature/wave2-…
rubenvdlinde May 3, 2026
6784e83
Merge pull request #104 from ConductionNL/feature/wave2-merged
rubenvdlinde May 3, 2026
fd34a8f
test(integration): add Newman/Postman suite covering 131 OCS routes
rubenvdlinde May 3, 2026
cb3e690
feat(spec): annotate 62 public lib/ methods with @spec tags
rubenvdlinde May 3, 2026
467ed70
Merge pull request #107 from ConductionNL/chore/phantom-commitments
rubenvdlinde May 3, 2026
abf48fa
feat(openspec): wave3 UX-overhaul proposal pack (6 changes)
rubenvdlinde May 3, 2026
9ff91c9
feat(container-widget): nested-grid container widget with depth=3 cap
rubenvdlinde May 3, 2026
a91c451
feat(widgets): unified add-widget flow with tile registry type
rubenvdlinde May 3, 2026
2e61815
feat(widgets): registry completeness CI guard (REQ-WDG-023)
rubenvdlinde May 3, 2026
aaf0df2
feat(nc-widget): replace picker <select> with icon-card grid
rubenvdlinde May 3, 2026
2f6315d
feat(switcher): persistent footer + dedicated Add Dashboard card
rubenvdlinde May 3, 2026
9ad1613
feat(runtime-shell): trim toolbar, standalone switcher, and gear menu…
rubenvdlinde May 3, 2026
a7315d6
merge: feature/wave3-runtime-shell-trim into wave3-merged
rubenvdlinde May 3, 2026
955df4d
merge: feature/wave3-dashboard-switcher-extensions into wave3-merged
rubenvdlinde May 3, 2026
607a505
merge: feature/wave3-widget-registry-completeness into wave3-merged
rubenvdlinde May 3, 2026
3b14b8a
merge: feature/wave3-nc-widget-picker-grid into wave3-merged
rubenvdlinde May 3, 2026
f159061
Merge pull request #108 from ConductionNL/feature/wave3-merged
rubenvdlinde May 3, 2026
f57c8c5
fix(migration): replace named args on Doctrine + rename too-long tran…
rubenvdlinde May 3, 2026
e3d5461
Merge pull request #109 from ConductionNL/chore/migration-bug-fixes
rubenvdlinde May 3, 2026
5f7b46b
fix(ux): hide title strip when sidebar closed, restore Conduction log…
rubenvdlinde May 4, 2026
5131081
fix(ux): wave3.2 — restore dashboard render width, drop dead context-…
rubenvdlinde May 4, 2026
9f4f7be
fix(ux): wave3.3 — restore dashboard switching, move per-dashboard me…
rubenvdlinde May 4, 2026
f5b4015
chore(workspace): drop dead duplicate DashboardSwitcherSidebar mount …
rubenvdlinde May 4, 2026
692c672
test(e2e): add wave3 runtime-shell coverage spec (gates deferred) (#115)
rubenvdlinde May 4, 2026
3b32c22
feat(sidebar): per-row cog menu — actions act on the row, not on whic…
rubenvdlinde May 4, 2026
d80cebb
feat(default-dashboard): explicit pin via per-row 'Set as default' co…
rubenvdlinde May 4, 2026
106c3b2
feat(default-dashboard): expose 'Default dashboard' toggle in Dashboa…
rubenvdlinde May 4, 2026
dba0db4
fix(sidebar): per-row cog flips Edit→Save on the active row when edit…
rubenvdlinde May 4, 2026
1a8f755
feat(role-based-content): role-feature-permissions implementation [#9…
rubenvdlinde May 4, 2026
fd61973
ci(phpunit): rename phpunit-unit.xml → phpunit.xml + flip enable-phpu…
rubenvdlinde May 4, 2026
fd0cdb5
ci(playwright): future-prep `ensureBundleBuilt()` helper (gate stays …
rubenvdlinde May 4, 2026
1d6bda5
docs: add widget extension guide for app developers (#124)
rubenvdlinde May 5, 2026
4d22acf
fix(api): six backend bugs uncovered by Newman gate + flip gate on (#…
rubenvdlinde May 5, 2026
62e7eba
feat(dashboard): seed default widget bundle on user-created dashboard…
rubenvdlinde May 5, 2026
24042c3
fix(dashboard): set tileType='preset' on seeded tiles + pin shape in …
rubenvdlinde May 5, 2026
bde52a8
feat(sidebar): mark the user's pinned default dashboard with a star
rubenvdlinde May 5, 2026
5689e99
feat(sidebar): fall back to group-default when no personal pin is set
rubenvdlinde May 5, 2026
695e338
feat(deep-link): bidirectional URL sync for dashboards
rubenvdlinde May 5, 2026
58a1ddf
ci: retrigger after branch rename
rubenvdlinde May 5, 2026
a32db60
ci: retrigger after branch rename
rubenvdlinde May 5, 2026
d86b9b3
ci: retrigger after branch rename
rubenvdlinde May 5, 2026
d6c712e
Merge pull request #129 from ConductionNL/feature/default-widgets-and…
rubenvdlinde May 5, 2026
d87fe2c
Merge pull request #130 from ConductionNL/feature/sidebar-default-star
rubenvdlinde May 5, 2026
88e3a39
Merge remote-tracking branch 'origin/development' into feature/dashbo…
rubenvdlinde May 5, 2026
f653d10
Merge pull request #131 from ConductionNL/feature/dashboard-deeplinking
rubenvdlinde May 5, 2026
588e24f
docs(tutorials): user + admin walkthroughs with durable screenshot ca…
rubenvdlinde May 6, 2026
e8b7a6e
docs: move docusaurus deploy domain from mydash.app to mydash.conduct…
rubenvdlinde May 6, 2026
3ad9d57
docs(tutorials): first capture-spec run — 16 screenshots + selector f…
rubenvdlinde May 6, 2026
e7e4e72
test(docs-capture): instrument 4 components with stable data-testid
rubenvdlinde May 6, 2026
682d161
test(docs-capture): instrument admin settings sections with data-testid
rubenvdlinde May 6, 2026
6fab8ea
test(docs-capture): instrument widget picker, wrapper, and style editor
rubenvdlinde May 6, 2026
b420f5c
docs(tutorials): validated capture run — 26 screenshots from instrume…
rubenvdlinde May 6, 2026
2f2d5a0
Merge pull request #132 from ConductionNL/feature/user-and-admin-docs
rubenvdlinde May 6, 2026
95483ef
feat(in-app-docs): point in-app Documentation links at mydash.conduct…
rubenvdlinde May 6, 2026
34e3316
Merge pull request #133 from ConductionNL/feature/in-app-docs-url-update
rubenvdlinde May 6, 2026
3ba37e3
fix(docs): move screenshots into static/ so they actually load on the…
rubenvdlinde May 6, 2026
85f9b47
Merge pull request #134 from ConductionNL/feature/fix-screenshot-paths
rubenvdlinde May 6, 2026
04c7918
docs: openspec specs + feature reference pages for the recent feature…
rubenvdlinde May 7, 2026
c9e7ef0
Merge pull request #136 from ConductionNL/feature/openspec-recent-fea…
rubenvdlinde May 7, 2026
28ccfe1
feat(docs): adopt @conduction/docusaurus-preset for the brand wrapper
rubenvdlinde May 7, 2026
2741476
Merge pull request #137 from ConductionNL/chore/adopt-conduction-preset
rubenvdlinde May 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
36 changes: 36 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# CODEOWNERS — auto-request reviewers based on path domain.
# Last-match-wins; broad rules first, specific overrides below.
# Created 2026-05-03 from the OR-abstraction audit follow-up.

# Default: every named codeowner reviews unmatched paths.
* @rubenvdlinde @rjzondervan @Rem-Dam @remko48 @WilcoLouwerse @bbrands02 @SudoThijn

# Backend (PHP) — services, controllers, mappers, db, migration, etc.
lib/ @bbrands02 @rjzondervan @WilcoLouwerse
appinfo/ @bbrands02 @rjzondervan @WilcoLouwerse
**/*.php @bbrands02 @rjzondervan @WilcoLouwerse
phpcs.xml @bbrands02 @rjzondervan @WilcoLouwerse
phpmd.xml @bbrands02 @rjzondervan @WilcoLouwerse
phpstan.neon @bbrands02 @rjzondervan @WilcoLouwerse
phpstan-baseline.neon @bbrands02 @rjzondervan @WilcoLouwerse
phpmd.baseline.xml @bbrands02 @rjzondervan @WilcoLouwerse
composer.json @bbrands02 @rjzondervan @WilcoLouwerse
composer.lock @bbrands02 @rjzondervan @WilcoLouwerse

# Frontend (Vue / TS / JS) — components, stores, pages, build config.
src/ @SudoThijn @remko48
**/*.vue @SudoThijn @remko48
**/*.ts @SudoThijn @remko48
**/*.js @SudoThijn @remko48
package.json @SudoThijn @remko48
package-lock.json @SudoThijn @remko48
jest.config.js @SudoThijn @remko48
playwright.config.ts @SudoThijn @remko48
webpack.config.js @SudoThijn @remko48
babel.config.js @SudoThijn @remko48

# Specs / docs / ADRs / openspec.
openspec/ @rubenvdlinde @Rem-Dam
docs/ @rubenvdlinde @Rem-Dam
**/*.md @rubenvdlinde @Rem-Dam
README.md @rubenvdlinde @Rem-Dam
18 changes: 18 additions & 0 deletions .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,21 @@ jobs:
enable-phpmetrics: true
enable-frontend: true
enable-eslint: true
# Hard gates:
# - PHPUnit — wired in wave3.10. 4-way matrix (PHP 8.3/8.4 ×
# NC stable31/stable32) all green.
# - Newman — wired alongside the postman collection drift
# sweep (PR #123 follow-up): six real backend bugs fixed
# (Templates SQL, Feeds 2× constraint, addWidget TypeError,
# Lock-on-nonexistent, share TypeError, addRule TypeError),
# postman fixture-id wiring repaired and assertion drift
# resolved. 196 assertions / 0 failures locally.
#
# Playwright remains disabled — the shared workflow's
# PHP-built-in-server lifetime is the blocker (cross-repo PR
# `ConductionNL/.github#37`). The `tests/e2e/global-setup.ts`
# `ensureBundleBuilt()` helper is in place so once the shared
# workflow lands, flipping the gate Just Works.
enable-phpunit: true
enable-newman: true
newman-environment-path: "tests/integration/local.env.json"
2 changes: 1 addition & 1 deletion .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ jobs:
deploy:
uses: ConductionNL/.github/.github/workflows/documentation.yml@main
with:
cname: mydash.app
cname: mydash.conduction.nl
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ Thumbs.db
/phpqa/
/quality-reports/

# Playwright e2e
/tests/e2e/.auth/
/test-results/
/playwright-report/
/playwright/.cache/

# PHP
/composer.phar

Expand All @@ -60,3 +66,8 @@ Thumbs.db
sbom.cdx.json
bom-php.cdx.json
bom-npm.cdx.json

# Research notes (local-only)
/docs/sendent-analysis.md
/sendent-workspace-main/
/2026.*_sendent-workspace-main.zip
74 changes: 63 additions & 11 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,69 @@ All notable changes to this project will be documented in this file.

### Added

- **Initial-state contract** (REQ-INIT-001..REQ-INIT-005). Workspace and admin
pages now route every initial-state key through the typed PHP service
`OCA\MyDash\Service\InitialStateBuilder` (with a `Page` enum and required-key
enforcement via `MissingInitialStateException`). The mirrored typed JS reader
`src/utils/loadInitialState.js` returns a default-filled object and warns when
`INITIAL_STATE_SCHEMA_VERSION` (currently `1`) drifts between server and
client. To add a key: update the spec Data Model (REQ-INIT-002), bump
`INITIAL_STATE_SCHEMA_VERSION` in both PHP and JS, and add the setter +
reader entry in the same commit. Direct calls to
`IInitialState::provideInitialState` from controllers / settings, and direct
`loadState('mydash', ...)` calls from `src/`, are forbidden by lint.
- **Per-user RSS / Atom dashboard feeds** (REQ-FEED-001..009): users can
now opt-in to a personal feed of their accessible dashboards via
`GET /api/feed/token`. New routes `POST /api/feed/token/regenerate`
(atomic rotate), `DELETE /api/feed/token` (idempotent soft-revoke),
and the public `GET /feed/{token}.xml` (no Nextcloud auth — gated
only by the opaque token). Tokens are 32 random bytes encoded
URL-safe base64 (~43 chars, 256-bit entropy, non-enumerable). Feed
output is RSS 2.0 by default; `Accept: application/atom+xml` (or the
`?format=atom` query fallback) switches to Atom 1.0. Visibility
reuses `DashboardService::getVisibleToUser()` so private dashboards
never leak to public feed consumers; item count is capped at the
admin-tunable `mydash.feed_item_cap` (default 50). New
`oc_mydash_feed_tokens` table with `UNIQUE(user_id)` enforces the
one-token-per-user rotation invariant.

### Changed

- **GridStack bumped from `^10.3.1` to `^12.2.1`** (resolved 12.6.0). Major
version bump bundled with the responsive-grid-breakpoints change. The
`GridStack.init` signature, the `change` event payload, the
`engine.nodes` accessor, the `removeWidget(el, removeDOM)` call, and the
`enable()`/`disable()` lifecycle methods used by `DashboardGrid.vue` are
unchanged across the v10 -> v12 jump, so no caller-side breakage was
observed during the bump. Downstream forks pinning a narrower
`gridstack` range will need to widen their dependency.

### Added

- **Responsive grid breakpoints** (REQ-GRID-007 / REQ-GRID-012 /
REQ-GRID-013): the GridStack instance now reflows proportionally at four
viewport widths instead of staying fixed-12-column on narrow screens.
Breakpoints `[{w:1400,c:12},{w:1100,c:8},{w:768,c:4},{w:480,c:1}]` with
the `moveScale` layout algorithm. Geometry constants (`CELL_HEIGHT = 60`,
`GRID_MARGIN = 8`, `BREAKPOINTS`) live in
`src/composables/useGridManager.js` as the single source of truth and
are mirrored to the CSS custom property `--mydash-cell-height` at
init time so `calc()` expressions stay in sync. Cell height moved from
the previously documented 80 px to 60 px to better support multi-row
info widgets; flip the `CELL_HEIGHT` constant in the composable (single
edit) if a denser/looser default is preferred.

- **Initial-state contract** (REQ-INIT-001..006): `lib/Service/InitialStateBuilder.php`
centralises the per-page initial-state payload pushed via Nextcloud's
`IInitialState` service. The matching JS reader at
`src/utils/loadInitialState.js` returns a typed default-filled object for
the workspace and admin pages. Both sides stamp / validate a
`_schemaVersion` constant; deploy skew between PHP and JS surfaces as a
console warning at runtime.

Adding, removing, or renaming a key requires four coordinated edits in
the same commit:
1. update the spec Data Model in
`openspec/specs/initial-state-contract/spec.md`,
2. bump `INITIAL_STATE_SCHEMA_VERSION` in
`lib/Service/InitialStateBuilder.php` AND
`src/utils/loadInitialState.js`,
3. add (or remove) the typed setter in the PHP builder and the matching
entry in the JS reader's `PAGE_KEYS` table,
4. update the controller(s) that call the builder.

CI guards (`composer lint:initial-state`, `npm run lint:initial-state`)
forbid direct `IInitialState::provideInitialState()` calls outside the
builder and direct `loadState('mydash', ...)` calls outside the reader.

## 0.1.0 - Initial Release

Expand Down
26 changes: 18 additions & 8 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,26 @@ npm start # Dev server at http://localhost:3000 with hot reload

Simply add or edit Markdown files in the `docs/` folder. The sidebar is auto-generated from the folder structure. Changes will appear on the product page after pushing to `development`.

## Security review checkboxes
## Adding a widget type

### Extending the SVG whitelist
The widget registry (`src/constants/widgetRegistry.js`) is the single source of truth for "addable" custom widget types (REQ-WDG-014). Because many widget capabilities ship in parallel branches that all touch the same object, the file is a heavy merge-conflict site -- a regression that silently drops a type would silently disappear from the Add Custom Widget picker without any test signal. To add a new widget type:

`lib/Service/SvgSanitiser.php` ships a deliberately conservative whitelist of 24 element types and 50 attribute types — see `ALLOWED_ELEMENTS` and `ALLOWED_ATTRIBUTES` (REQ-RES-010 / REQ-RES-011 in the `resource-uploads` capability).
- Update `src/constants/widgetRegistry.js` with the new entry (`renderer`, `form`, `defaultContent`, `displayName`, `icon`).
- Update `EXPECTED_TYPES` in `src/constants/__tests__/widgetRegistry.completeness.spec.js` (REQ-WDG-023) so the completeness guard stays in sync. The test will fail with a precise diff if you forget.
- Implement the renderer + form Vue components following the pattern of an existing widget (e.g. `LabelWidget.vue` + `LabelForm.vue`).
- Add i18n keys for the type's `displayName` and any user-facing form labels to all four `l10n/` files (`en.js`, `en.json`, `nl.js`, `nl.json`).
- Add the canonical capability spec under `openspec/specs/<widget-name>/spec.md` so the type's REQ-* identifiers, defaults, and acceptance scenarios are documented.

Adding any element or attribute to either constant is a **security review checkbox**, not an editorial change. Before merging an addition, confirm:
## Security review checklist

- the element / attribute carries no executable surface (no script, no event handler, no foreign content, no URL fetch outside the existing `href` filter);
- the addition is justified by a real upload that is currently being rejected, not a speculative future need;
- a corresponding unit test covers the new whitelist entry.
### Extending the SVG sanitiser whitelist

The sanitiser runs server-side BEFORE the size cap (REQ-RES-009), so an over-permissive whitelist becomes stored XSS the moment a sanitised-looking SVG is rendered back into a logged-in user's browser.
`lib/Service/SvgSanitiser.php` enforces a deliberately conservative whitelist of allowed SVG element and attribute names (REQ-RES-010 / REQ-RES-011 in `openspec/specs/resource-uploads/spec.md`). Every uploaded SVG is parsed via `DOMDocument` with `LIBXML_NONET | LIBXML_NOENT` and the resulting tree is filtered against `ALLOWED_ELEMENTS` and `ALLOWED_ATTRIBUTES`. Anything not on those lists is removed before persistence, and the persisted bytes (NOT the original) are what subsequently get served back to other users' browsers.

If you propose adding a new element name to `ALLOWED_ELEMENTS` or a new attribute to `ALLOWED_ATTRIBUTES`:

- A security review is required before merge (XSS surface change).
- Verify the new element / attribute cannot carry executable payloads in any browser SVG renderer (e.g. `<animate>` `attributeName` injection, `<set>` event triggering, etc.).
- Add a PHPUnit scenario covering the new surface, plus a negative scenario showing that a known-bad construct involving the new name is still rejected.
- Update REQ-RES-010 / REQ-RES-011 in the canonical spec to reflect the new whitelist size and add the element / attribute name explicitly.
- The sanitiser runs server-side BEFORE the size cap (REQ-RES-009), so an over-permissive whitelist becomes stored XSS the moment a sanitised-looking SVG is rendered back into a logged-in user's browser.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
<a href="https://github.com/ConductionNL/mydash/releases"><img src="https://img.shields.io/github/v/release/ConductionNL/mydash" alt="Latest release"></a>
<a href="https://github.com/ConductionNL/mydash/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-AGPL--3.0-blue" alt="License"></a>
<a href="https://github.com/ConductionNL/mydash/actions"><img src="https://img.shields.io/github/actions/workflow/status/ConductionNL/mydash/code-quality.yml?label=quality" alt="Code quality"></a>
<a href="https://mydash.app"><img src="https://img.shields.io/badge/docs-mydash.app-green" alt="Documentation"></a>
<a href="https://mydash.conduction.nl"><img src="https://img.shields.io/badge/docs-mydash.conduction.nl-green" alt="Documentation"></a>
</p>

---

MyDash supercharges the Nextcloud dashboard. Create multiple personalized workspaces with drag-and-drop widgets, custom shortcut tiles, and smart visibility rules — then let admins roll out templates to entire teams. It works with every existing Nextcloud dashboard widget out of the box, supporting both the v1 and v2 Dashboard APIs.

📚 **[Step-by-step tutorials](https://mydash.conduction.nl/docs/category/tutorials)** — user + admin walkthroughs with screenshots, kept in sync with the live UI via the [journeydoc](https://github.com/ConductionNL/hydra/blob/development/openspec/architecture/adr-030-journeydoc-pattern.md) capture spec.

## Screenshots

<table>
Expand Down
43 changes: 42 additions & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Ideaal voor organisaties die consistente, samengestelde dashboards willen voor h

Vrij en open source onder de EUPL-1.2-licentie.
]]></description>
<version>1.0.3-unstable.4</version>
<version>1.0.4-unstable.0</version>
<licence>EUPL-1.2</licence>
<author mail="info@conduction.nl" homepage="https://www.conduction.nl/">Conduction</author>
<namespace>MyDash</namespace>
Expand All @@ -71,11 +71,45 @@ Vrij en open source onder de EUPL-1.2-licentie.
<nextcloud min-version="28" max-version="34"/>
</dependencies>

<!-- Surface dashboards, widget content, and metadata in NC unified search. REQ-SRCH-001. -->
<types>
<search/>
</types>

<background-jobs>
<job>OCA\MyDash\BackgroundJob\OrphanedDataCleanupJob</job>
</background-jobs>

<settings>
<admin>OCA\MyDash\Settings\MyDashAdmin</admin>
<admin-section>OCA\MyDash\Settings\MyDashAdminSection</admin-section>
</settings>

<commands>
<!-- REQ-EXIM-010: dashboard export / import via `php occ`. -->
<command>OCA\MyDash\Command\ExportCommand</command>
<command>OCA\MyDash\Command\ImportCommand</command>
<!-- REQ-CFLI-011: Confluence HTML export importer via `php occ`. -->
<command>OCA\MyDash\Command\ImportConfluenceCommand</command>
<!-- REQ-CLI-001..011: shared `mydash:` CLI suite (cli-commands). -->
<command>OCA\MyDash\Command\DashboardListCommand</command>
<command>OCA\MyDash\Command\DashboardShowCommand</command>
<command>OCA\MyDash\Command\DashboardDeleteCommand</command>
<command>OCA\MyDash\Command\DashboardDebugShareCommand</command>
<command>OCA\MyDash\Command\UserRevokeFeedTokenCommand</command>
<command>OCA\MyDash\Command\I18nExportStringsCommand</command>
<command>OCA\MyDash\Command\I18nMigrateLanguageStructureCommand</command>
<command>OCA\MyDash\Command\I18nCopyNavigationCommand</command>
<!-- REQ-OCLN-001..009: orphaned-data cleanup CLI. -->
<command>OCA\MyDash\Command\CleanupScanCommand</command>
<command>OCA\MyDash\Command\CleanupPurgeCommand</command>
<!-- REQ-DEMO-009: bundled demo showcase install / list. -->
<command>OCA\MyDash\Command\DemoShowcasesInstallCommand</command>
<command>OCA\MyDash\Command\DemoShowcasesListCommand</command>
<!-- REQ-WIZ-010: setup wizard via `php occ mydash:setup`. -->
<command>OCA\MyDash\Command\SetupCommand</command>
</commands>

<navigations>
<navigation>
<name>MyDash</name>
Expand All @@ -84,4 +118,11 @@ Vrij en open source onder de EUPL-1.2-licentie.
<order>-5</order>
</navigation>
</navigations>

<activity>
<!-- REQ-ACT-001: register the MyDash Activity provider that
surfaces the 13-event catalogue defined in
OCA\MyDash\Activity\Extension. -->
<provider>OCA\MyDash\Activity\Extension</provider>
</activity>
</info>
Loading
Loading