67 Commits

Author SHA1 Message Date
alexei.dolgolyov 2c9c36605d fix: consolidate migrations and fix Prisma ESM compatibility
Release / docker (push) Successful in 1m2s
Release / release (push) Successful in 4s
Lint & Test / lint-and-check (push) Failing after 5m11s
Lint & Test / test (push) Has been skipped
- Replace 3 partial migrations with single init migration from schema
- Fixes missing backupEnabled, integrationType, and other columns
- Move @prisma/client to dependencies for adapter-node externalization
- Add ssr.external to prevent Vite bundling Prisma (fixes __dirname error)
v0.0.1
2026-04-10 21:23:00 +03:00
alexei.dolgolyov 1f7e040049 fix: resolve Prisma __dirname ESM error in production Docker build
Lint & Test / lint-and-check (push) Failing after 5m5s
Release / docker (push) Successful in 1m23s
Release / release (push) Successful in 4s
Lint & Test / test (push) Has been skipped
Move @prisma/client and prisma to dependencies so adapter-node
externalizes them instead of bundling. Add ssr.external config
for Vite to prevent inlining Prisma's CJS engine loader.
2026-04-10 21:17:39 +03:00
alexei.dolgolyov 85b4576991 fix: remove deprecated --skip-generate flag from Prisma db push
Release / release (push) Successful in 4s
Lint & Test / lint-and-check (push) Failing after 5m1s
Lint & Test / test (push) Has been skipped
Release / docker (push) Successful in 1m0s
2026-04-10 20:31:24 +03:00
alexei.dolgolyov 32b874f4a3 fix(ci): use jq instead of python3, handle existing releases via PATCH
Release / docker (push) Successful in 32s
Release / release (push) Successful in 6s
Lint & Test / lint-and-check (push) Failing after 5m3s
Lint & Test / test (push) Has been skipped
2026-04-10 20:23:17 +03:00
alexei.dolgolyov bf907c7858 fix(ci): add OCI labels to associate Docker image with Gitea repo
Release / docker (push) Successful in 4s
Release / release (push) Failing after 4s
Lint & Test / lint-and-check (push) Has been cancelled
Lint & Test / test (push) Has been cancelled
2026-04-10 20:19:27 +03:00
alexei.dolgolyov 402a0b34c1 fix: use COPY --chown instead of recursive chown in Dockerfile
Release / docker (push) Successful in 55s
Release / release (push) Successful in 4s
Lint & Test / test (push) Has been cancelled
Lint & Test / lint-and-check (push) Has started running
Avoids slow chown -R over node_modules (thousands of files).
2026-04-10 20:15:24 +03:00
alexei.dolgolyov 0ebf6bd652 fix(ci): remove redundant test gate from release workflow
Lint & Test / lint-and-check (push) Failing after 5m14s
Lint & Test / test (push) Has been skipped
Release / release (push) Has been cancelled
Release / docker (push) Has been cancelled
Code is already validated by test.yml on push to master.
The release workflow now goes straight to docker build + release.
2026-04-10 20:04:03 +03:00
alexei.dolgolyov 124a7679b3 chore: release v0.0.1
Lint & Test / lint-and-check (push) Failing after 5m19s
Lint & Test / test (push) Has been skipped
Release / test (push) Failing after 5m14s
Release / docker (push) Has been skipped
Release / release (push) Has been skipped
- Rename CI workflow to test.yml (lint & test only)
- Add release.yml (Docker push + Gitea release on v* tag)
- Add README.md and RELEASE_NOTES.md
- Bump version to 0.0.1
2026-04-10 19:39:27 +03:00
alexei.dolgolyov 76ce85c9bb fix: polish empty states and status page layout
CI / lint-and-check (push) Failing after 5m4s
CI / test (push) Has been skipped
CI / docker-build (push) Has been skipped
- Boards: improved empty state with create button for admins
- Status: 2-column grid layout, colored left border by status, better empty state
2026-04-10 19:06:53 +03:00
alexei.dolgolyov aedc91e321 perf: batch-load app status history server-side to eliminate N+1 requests
- Load all app sparkline history in a single server query
- Pass preloadedHistory to AppCard to skip client-side fetch
- Polish empty state with icon, hint text, and add button
2026-04-10 19:06:43 +03:00
alexei.dolgolyov b5166d9768 refactor: header user menu with bits-ui dropdown, collapsible sidebar boards
- Replace manual click-outside menu with DropdownMenu from bits-ui
- Add collapsible boards section in sidebar with chevron toggle
- Add max-height scroll for boards list
2026-04-10 19:06:29 +03:00
alexei.dolgolyov 44e1849821 fix: resolve all linter errors and a11y warnings
CI / test (push) Has been cancelled
CI / docker-build (push) Has been cancelled
CI / lint-and-check (push) Has been cancelled
- Fix TS errors: editMode property order, implicit any, string|undefined
- Add $state() to bind:this element refs (IconGrid, EntityPicker, etc.)
- Fix a11y: labels, aria-labels, roles, tabindex on dialogs
- Remove unused imports (tick, svelte-i18n)
- Make AutocompleteInput/TagsInput accept optional string values
2026-04-10 19:05:25 +03:00
alexei.dolgolyov f96cbbca56 chore(i18n): add locale keys for widget resize, delete user, multi-picker 2026-04-10 19:05:11 +03:00
alexei.dolgolyov 5af670fa3c feat: multi-entity picker for status widget app selection
- Create MultiEntityPicker component with search, checkboxes, keyboard nav
- Replace plain checkbox list in status widget config with MultiEntityPicker
- Render app icons properly by type (lucide, simple, url, emoji)
2026-04-10 19:05:03 +03:00
alexei.dolgolyov f559c93e19 feat: widget column span resizing with visual size picker
- Add per-widget colSpan stored in config JSON (no DB migration)
- Replace hardcoded full-width types with configurable span
- Add visual size picker popover in edit mode overlay
- Merge widget config updates for temp widgets in Board changeset
2026-04-10 19:04:54 +03:00
alexei.dolgolyov 65783e35d2 feat: user deletion confirmation modal
Replace inline confirm/delete pattern with ConfirmDialog modal
2026-04-10 19:04:43 +03:00
alexei.dolgolyov 1e3a04f4de perf: optimize cold start by lazy-loading icons and parallelizing DB queries
- Replace barrel `import * as icons` in DynamicIcon with dynamic per-icon imports
- Eagerly connect Prisma client at startup to avoid first-request latency
- Parallelize 4 sequential DB queries in layout server load with Promise.all
2026-04-10 19:04:35 +03:00
alexei.dolgolyov 7beca05eec feat: inline dashboard editing mode with WYSIWYG experience 2026-04-03 00:33:34 +03:00
alexei.dolgolyov 17c8407c07 feat(widget-config): visual app selector grid with search and icons
Replace plain select dropdown with a searchable 2-column grid showing
app icons for the app widget type in the inline config panel.
2026-04-03 00:32:45 +03:00
alexei.dolgolyov c5f5f84c79 feat(app-form): icon picker, tag/category autocomplete, typography
- Replace AppIconPicker text input with visual IconPickerButton for
  lucide icons (grid with search)
- Add AutocompleteInput component for category field with existing
  category suggestions
- Add TagsInput component for tags field with tag pills, autocomplete
  from existing tags, and keyboard navigation
- Add GET /api/apps/suggestions endpoint returning all categories/tags
- Add getAllTags() to appService (merges Tag model + comma-separated)
- Install @tailwindcss/typography plugin to fix prose rendering
  (headings, lists, blockquotes now render in Note/Markdown widgets)
- Fix note widget validator test for new html format
2026-04-03 00:24:08 +03:00
alexei.dolgolyov a6b09aae9c feat(inline-edit): add WYSIWYG inline dashboard editing mode
Replace the disconnected board edit page with inline editing directly
on the board view. Toggle with Ctrl+E or the Edit button. Features:

- Edit mode store with changeset accumulation and batch save
- Floating toolbar (save, discard, add section, board settings, exit)
- Widget hover overlays with edit/delete/drag controls
- Type-specific widget config panels for all 14 widget types
- Section inline editing (title, icon picker, delete)
- "+" buttons for adding widgets and sections inline
- Section-level drag-and-drop reordering via svelte-dnd-action
- Batch save API endpoint (single Prisma transaction)
- Board properties side panel with live theme/wallpaper preview
- Modal widget type picker with search filtering
- Icon picker component with visual grid and search
- Confirmation dialog modal for all destructive actions
- HTML format support for Note widget (in addition to markdown/text)
- Full i18n support (en + ru) for all new UI strings
- Legacy edit page banner linking to new inline mode
2026-04-03 00:01:29 +03:00
alexei.dolgolyov d8f89c65dc Cleanup plans
CI / lint-and-check (push) Failing after 5m3s
CI / test (push) Has been skipped
CI / docker-build (push) Has been skipped
2026-04-02 23:20:08 +03:00
alexei.dolgolyov f6599430e5 Merge branch 'feature/database-backup' 2026-04-02 23:16:24 +03:00
alexei.dolgolyov b0439e39c4 feat(backup): replace JSON import/export with SQLite database backup system
Replace the JSON-based import/export with a proper backup system that copies
the SQLite database file directly. Supports manual on-demand backups, periodic
scheduled backups via node-cron, configurable retention, file download, and
full database restore.

- Add backupService with VACUUM INTO for safe DB copies
- Add backupScheduler following healthcheckScheduler pattern
- Add 6 admin API endpoints (create, list, download, restore, delete, schedule)
- Add BackupPanel UI with backup table, confirmation dialogs, schedule config
- Add backup fields to SystemSettings schema
- Remove old ImportExportPanel, exportService, importService, and related code
2026-04-02 23:16:18 +03:00
alexei.dolgolyov d479726fe3 feat: add app edit page with pre-populated form
CI / lint-and-check (push) Failing after 5m3s
CI / test (push) Has been skipped
CI / docker-build (push) Has been skipped
Add /apps/[id]/edit route that loads existing app data into the form,
allowing users to update app properties. Adds edit pencil button to
AppCard (visible on hover) and i18n keys for both EN and RU.
2026-03-25 22:42:20 +03:00
alexei.dolgolyov 44bbf7b410 fix(service-integrations): resolve type errors and test failures
- Fix CreateAppInput nullable types for integration fields
- Add type casts in IntegrationWidget renderer dispatching
- Guard decryptAppIntegration against missing fields in test mocks
2026-03-25 22:19:56 +03:00
alexei.dolgolyov 55e220bc07 feat(service-integrations): phases 9-10 — media integrations + Planka
- Emby: now playing, library stats, recently added, active streams
- Immich: library stats, recent uploads with formatted storage
- Deluge: active torrents with progress, transfer speed, disk space gauge
- MeTube: download queue progress (no auth required)
- Planka: my cards, overdue cards with red badges, board summary
- All 11 integrations registered in registry
2026-03-25 22:16:27 +03:00
alexei.dolgolyov d73fb9c680 feat(service-integrations): phases 3-8 — six service integrations
- NUT/UPS: TCP protocol client, battery/load gauges, runtime card, power alert banner
- Pi-hole: DNS stats summary, top blocked domains, query log, gravity status
- Portainer: Container summary/list, stack status via Docker API
- Gitea: Recent commits, open PRs, releases across repos
- Nginx Proxy Manager: Proxy hosts, SSL certificate expiry alerts, upstream status
- Authentik: User stats, login events feed, brute force detection alerts
- All integrations registered in registry with auto-discovery
2026-03-25 22:12:31 +03:00
alexei.dolgolyov 50e8519220 feat(service-integrations): phase 2 — integration widget & app form UI
- Add 6 renderer components: StatCard, Gauge, List, Progress, AlertBanner, Chart
- Add IntegrationWidget container with auto-refresh, loading, error states
- Add IntegrationAlertOverlay for layout-level critical alerts
- Add IntegrationConfigFields for dynamic form generation from Zod schemas
- Register integration type in WidgetRenderer
- Extend WidgetCreationForm with integration app/endpoint pickers
- Extend AppForm with integration config section and test connection button
- Add /api/integrations/alerts endpoint
2026-03-25 22:07:51 +03:00
alexei.dolgolyov 114dee57a8 feat(service-integrations): phase 1 — integration architecture foundation
- Add Integration interfaces, registry, cache, encryption, and base helpers
- Add integrationType, integrationConfig, integrationEnabled to App model
- Add integration widget type to constants and validators
- Add integration fields to AppRecord, CreateAppInput, UpdateAppInput
- Update appService with encryption/decryption for integration config
- Add API routes: list integrations, test connection, fetch endpoint data
2026-03-25 22:02:34 +03:00
alexei.dolgolyov c62ca79adb fix: delay search dialog close so link navigation fires first 2026-03-25 21:26:16 +03:00
alexei.dolgolyov bcde710cab fix: search store now parses API envelope response correctly
The search API returns { success, data: [...] } but the store was
looking for data.apps and data.boards (which don't exist). Fixed to
read from data.data[] and also added url/icon fields to search API
response so app results are clickable and show icons.
2026-03-25 21:12:17 +03:00
alexei.dolgolyov 92eeeadec0 perf: batch-load app history to eliminate N+1 fetches on board load
Previously each AppWidget fetched /api/apps/{id}/history individually
on mount, causing N sequential HTTP requests. Now the board page
server load fetches all app histories in a single Prisma query via
getBatchStatusHistory() and passes them to AppWidget via Svelte
context. AppWidget uses the pre-loaded data immediately with a
fallback fetch for non-board contexts.
2026-03-25 15:36:06 +03:00
alexei.dolgolyov 6eb6bba289 feat: Phases 4-7 — Full Feature Expansion (26 features)
8 new widget types, 6 visual enhancements, 8 functional features,
4 quality-of-life improvements. 212 files, 15k+ lines added.
Build, lint, type check, and 222 tests all pass.
2026-03-25 14:58:25 +03:00
alexei.dolgolyov 4326d95bf3 fix: use SVG icon for favicon and PWA manifest 2026-03-25 14:58:25 +03:00
alexei.dolgolyov d90507ad82 fix: add SSRF protection to URL preview endpoint
Block requests to private/reserved IP ranges (10.x, 172.16-31.x,
192.168.x, 127.x, 169.254.x, localhost, ::1) and non-http(s)
schemes in the /api/apps/preview endpoint to prevent server-side
request forgery.
2026-03-25 14:37:17 +03:00
alexei.dolgolyov 819283fa62 fix: use HLS.js for fullscreen camera stream
Fullscreen HLS video now initializes HLS.js via bind:this + $effect
instead of raw <video src>, which only works in Safari. Non-Safari
browsers now correctly play HLS streams in fullscreen mode.
2026-03-25 14:35:07 +03:00
alexei.dolgolyov 215c8fdd46 fix: enforce API token scope on requests
- Add apiTokenScope to App.Locals type definition
- Store token scope in event.locals during API token auth
- Block write operations (POST/PATCH/PUT/DELETE) for read-scoped tokens
- Block admin paths for non-admin-scoped tokens
- Returns 403 with descriptive error message
2026-03-25 14:32:48 +03:00
alexei.dolgolyov 014de026eb fix: address final review blockers
- Add /api/onboarding and /status to PUBLIC_PATHS in hooks.server.ts
  so onboarding wizard and status page work for unauthenticated users
- Add isOnboardingNeeded() guard to POST /api/onboarding to reject
  calls after onboarding is complete (security hardening)
- Add data-app-widget attribute to all AppWidget card variants to
  enable j/k keyboard navigation
2026-03-25 14:29:11 +03:00
alexei.dolgolyov 1c0a7cb850 feat: Phases 4-7 — Full Feature Expansion (26 features)
Phase 4 — New Widget Types:
- Clock/Weather, System Stats, RSS/Feed, Calendar, Markdown,
  Metric/Counter, Link Group, Camera/Stream widgets
- Backend services with caching for each data source
- Full creation form with dynamic config fields per type

Phase 5 — Visual & Styling Enhancements:
- Glassmorphism card style (solid/glass/outline)
- Board-level themes with per-board hue/saturation
- Animated SVG status rings replacing static dots
- Card size options (compact/medium/large)
- Custom CSS injection (admin + per-board, sanitized)
- Wallpaper backgrounds with blur/overlay/parallax

Phase 6 — Functional Features:
- Favorites bar with drag-and-drop reordering
- Recent apps tracking with privacy toggle
- Uptime dashboard page (/status, guest-accessible)
- Notifications system (Discord/Slack/Telegram/HTTP webhooks)
- App tags with filtering in board view
- Multi-URL app cards with expandable sub-links
- Personal API tokens with scoped permissions
- Audit log with retention and admin viewer

Phase 7 — Quality of Life:
- Onboarding wizard (5-step first-launch setup)
- App URL health preview with favicon/title detection
- Board templates (4 built-in + custom import/export)
- Keyboard shortcut overlay (j/k nav, 1-9 boards, ? help)

212 files changed, 15641 insertions, 980 deletions.
Build, lint, type check, and 222 tests all pass.
2026-03-25 14:18:10 +03:00
alexei.dolgolyov 8d7847889e feat: add IconGrid, EntityPicker controls and enhance search panel
CI / lint-and-check (push) Failing after 4m56s
CI / test (push) Has been skipped
CI / docker-build (push) Has been skipped
Port icon grid and entity picker patterns from wled-screen-controller.
IconGrid replaces plain <select> elements with visual icon grids for
known item sets (widget type, icon type, healthcheck method, permission
level). EntityPicker replaces search dropdowns with a command-palette
style overlay with keyboard navigation and filtering.

Enhance SearchDialog with keyboard navigation (arrow keys, Enter,
Escape), grouped results with section headers, active highlight,
and a footer with shortcut hints.
2026-03-25 11:58:21 +03:00
alexei.dolgolyov 54a30ca4ca feat: Phase 3 — Advanced Features
CI / lint-and-check (push) Failing after 4m58s
CI / test (push) Has been skipped
CI / docker-build (push) Has been skipped
- Import/Export: JSON export/import with conflict resolution (skip/overwrite)
- Ping history sparklines: 24h bar charts on app widgets with uptime %
- User theme overrides: per-user preferences (hue, saturation, mode, bg, locale)
- PWA: service worker, manifest, offline page, install prompt
- Auto-discovery: Docker socket + Traefik API scanning with approval UI
- Quick-add bookmarklet: popup-based add from any page
- Multi-tab sync: BroadcastChannel for theme + data changes
- Security: execFile for Docker commands, Zod on all API inputs, import limits
- 222 tests across 20 test files, all passing
2026-03-25 01:32:43 +03:00
alexei.dolgolyov 395ed821b7 fix: address all final review findings for Phase 3
- CRITICAL: Fix command injection in discoveryService (execFile instead
  of exec, path validation regex)
- CRITICAL: Add Zod validation on discover API endpoint
- HIGH: Add Zod validation on discover/approve endpoint
- HIGH: Add array length limits to import schema (1000/100/100)
- HIGH: Fix theme broadcast echo loop (setTimeout vs queueMicrotask)
- MEDIUM: Singleton BroadcastChannel instead of create-per-send
- MEDIUM: Exclude sensitive APIs from service worker cache
- MEDIUM: Fix TypeScript cast errors in exportService tests
2026-03-25 01:28:24 +03:00
alexei.dolgolyov 7d8a8fb0fc feat(phase3): phase 7 - integration & polish
Fix all build/type/lint errors, write 46 new tests (222 total across
20 files), regenerate Prisma client, update seed with user preferences.
Fix SvelteSet usage, add {#each} keys, clean unused imports.
2026-03-25 01:12:11 +03:00
alexei.dolgolyov dd6958b4d6 feat(phase3): PWA, auto-discovery, bookmarklet, multi-tab sync
- PWA: manifest, service worker (cache-first static, network-first API),
  offline page, install prompt banner
- Auto-discovery: Docker socket + Traefik API scanning, approval UI
- Quick-add bookmarklet: popup-based add page, favicon auto-detect
- Multi-tab sync: BroadcastChannel for theme + data changes
- i18n translations for all new strings (EN/RU)
2026-03-25 00:59:19 +03:00
alexei.dolgolyov c6a7de895d feat(phase3): import/export, sparklines, user theme overrides
- JSON import/export with conflict resolution (skip/overwrite) + admin UI
- Ping history sparklines on AppWidget and AppCard (24h, 288 points)
- Hourly cleanup job for old AppStatus records
- User theme preferences (hue, saturation, mode, background, locale)
- Settings page with ThemeCustomizer (sliders, toggles, live preview)
- Prisma migration for user preference fields
- i18n translations for all new strings (EN/RU)
2026-03-25 00:51:01 +03:00
alexei.dolgolyov d155b3ce4a chore: add plan files for Phase 3 advanced features 2026-03-25 00:16:41 +03:00
alexei.dolgolyov 345f17f25a feat: Phase 2 — Enhanced Features
CI / lint-and-check (push) Failing after 4m57s
CI / test (push) Has been skipped
CI / docker-build (push) Has been skipped
- OAuth/Authentik integration (OIDC/PKCE, auto-provision, admin config)
- Drag-and-drop reordering (sections + widgets, cross-section moves)
- Localization EN/RU (224 translation keys, language switcher)
- 4 new widget types: Bookmark, Note (markdown), Embed (iframe), Status
- Per-board access control UI (permissions editor, share dialog)
- Security: DOMPurify for markdown, iframe sandbox hardening, OAuth state
- 176 tests passing, all build/lint/type checks clean
2026-03-25 00:08:09 +03:00
alexei.dolgolyov cba160ecb8 fix: address all code review findings
- Extract shared permission logic into boardPermissions.ts utility
- Fix DnD drag revert: add dirty flag to prevent  overwrite
- Wrap OAuth group sync in Prisma transaction (N+1 fix)
- Add empty widgetIds validation in widget reorder API
- Add invalidateAll() after guest toggle PATCH
- Replace console.error with user-visible error banners
- Extract WidgetCreationForm component (DraggableSection was 448 lines)
- Remove unused boardId prop from DraggableSection
- Always include OAuth state parameter + validate in callback
- Clean up copyLink timer on component destroy
- Add type-specific widget config validation in addWidget action
2026-03-25 00:03:32 +03:00
alexei.dolgolyov 5a6002be76 fix: address security findings from final review
- Replace regex HTML sanitization with DOMPurify in NoteWidget (XSS fix)
- Remove allow-same-origin from default iframe sandbox in EmbedWidget
- Add URL scheme validation for embed URLs (http/https only)
- Install isomorphic-dompurify dependency
2026-03-24 23:50:37 +03:00