Skip to content

Conversation

@Tim020
Copy link
Contributor

@Tim020 Tim020 commented Jan 24, 2026

No description provided.

dependabot bot and others added 12 commits January 13, 2026 00:01
Bumps [xkcdpass](https://github.com/redacted/XKCD-password-generator) from 1.20.0 to 1.30.0.
- [Commits](redacted/XKCD-password-generator@xkcdpass-1.20.0...xkcdpass-1.30.0)

---
updated-dependencies:
- dependency-name: xkcdpass
  dependency-version: 1.30.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [alembic](https://github.com/sqlalchemy/alembic) from 1.17.2 to 1.18.0.
- [Release notes](https://github.com/sqlalchemy/alembic/releases)
- [Changelog](https://github.com/sqlalchemy/alembic/blob/main/CHANGES)
- [Commits](https://github.com/sqlalchemy/alembic/commits)

---
updated-dependencies:
- dependency-name: alembic
  dependency-version: 1.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.14.11 to 0.14.13.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](astral-sh/ruff@0.14.11...0.14.13)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.14.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [alembic](https://github.com/sqlalchemy/alembic) from 1.18.0 to 1.18.1.
- [Release notes](https://github.com/sqlalchemy/alembic/releases)
- [Changelog](https://github.com/sqlalchemy/alembic/blob/main/CHANGES)
- [Commits](https://github.com/sqlalchemy/alembic/commits)

---
updated-dependencies:
- dependency-name: alembic
  dependency-version: 1.18.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Add implementation plan for Electron standalone frontend

- Detailed architecture documentation
- Implementation phases with timeline
- File inventory and directory structure
- Development workflows and build process
- Testing strategy and success criteria

Issue #839

* Implement Phase 1: Platform abstraction foundation for Electron frontend

Add platform abstraction layer to support both browser and Electron environments:
- Create platform detection module (platform/index.js) with runtime detection
- Add browser implementation (platform/browser.js) using window.location
- Add Electron implementation (platform/electron.js) with IPC placeholders
- Update utils.js, main.js, and store.js to use platform layer
- Configure ESLint to support top-level await (ES2022)

This foundation enables seamless operation in both web and Electron contexts
with 95% code sharing and minimal modifications to the existing Vue app.

Refs #839

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Implement Phase 2: Electron core setup with IPC communication

Add Electron main process, preload script, and connection management:
- Create electron/main.js with BrowserWindow and IPC handlers
- Create electron/preload.js exposing window.electronAPI via contextBridge
- Create ConnectionManager service using electron-store for persistence
- Add package.json with Electron 32.x and dependencies
- Configure dev mode (Vite dev server) and production mode (built files)

The Electron app now launches successfully and loads the Vue frontend.
IPC communication is established for connection management and storage.

Refs #839

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Implement Phase 3: Version checking and mDNS discovery services

Add server validation and discovery capabilities:
- Create VersionChecker service to validate server compatibility
  - Fetches /api/v1/settings endpoint
  - Requires exact version match between client and server
  - Handles connection errors with detailed error messages
- Create MDNSDiscovery service for local network server discovery
  - Uses bonjour-service to find _digiscript._tcp services
  - Optional version checking for discovered servers
  - 5 second discovery timeout
- Add IPC handlers in main.js:
  - version:check - Validate server compatibility
  - mdns:discover - Find servers on local network
  - mdns:discoverWithVersionCheck - Discovery with version validation
- Update preload.js to expose new methods to renderer

Server-side mDNS advertising will be implemented in future backend work.
The client-side discovery is ready to use when servers advertise.

Refs #839

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Implement Phase 4: Connection Selector UI

Add complete connection management interface for Electron app:
- Create ServerSelector.vue component with:
  - Saved connections list with Connect/Test/Delete actions
  - mDNS discovery with version compatibility checking
  - Manual server entry form with validation
  - Test connection functionality
  - Real-time version compatibility feedback
- Update router/index.js:
  - Add /electron/server-selector route (Electron-only)
  - Add navigation guard to redirect to selector if no active connection
  - Prevent non-Electron access to Electron-only routes
- Fix VersionChecker.js to use dynamic import for node-fetch (ES module)

The Electron app now has a complete connection workflow:
1. App launches → checks for active connection
2. No connection → redirects to ServerSelector
3. User selects/adds/discovers server
4. Version compatibility verified
5. Connection saved and activated
6. Redirects to home page

Refs #839

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Fix navigation guard for Electron server selector

Move Electron connection check after store initialization and skip all
settings fetching and auth checks when navigating to server selector.

This fixes the blank page issue where the app would try to fetch settings
from a non-existent server connection, causing the navigation to fail.

Refs #839

* Fix WebSocket initialization for Electron app

Make WebSocket initialization conditional:
- Check if running in Electron and if there's an active connection
- Skip WebSocket initialization if no server is configured
- Use window.location.href to reload page after connecting to server

This fixes the blank page issue where main.js would try to initialize
WebSocket before any server connection was configured, causing the app
to crash before the ServerSelector could load.

Connection flow:
1. App loads → checks for connection → skips WebSocket if none
2. Router redirects to ServerSelector
3. User adds/selects server
4. Page reloads with active connection
5. WebSocket initializes with correct server URL

Refs #839

* Skip App.vue initialization when no Electron connection

Add check in App.vue created hook to skip settings fetch and WebSocket
initialization when running in Electron without an active connection.

This fixes the error where App.vue would try to fetch settings before the
router guard could redirect to the ServerSelector, causing the app to show
the navbar but get stuck with a spinner.

Now App.vue checks for active connection first and skips all initialization
if none exists, allowing the router to properly redirect to ServerSelector.

Refs #839

* Set loaded=true when skipping initialization in Electron

Fix infinite spinner by setting loaded=true before returning early when
there's no active connection in Electron. Also add null check for SETTINGS
in template to prevent errors when SETTINGS hasn't been fetched.

The App.vue template shows a spinner when !loaded and only renders
router-view when loaded=true. Previously, when skipping initialization,
we never set loaded=true, causing the spinner to show forever.

Refs #839

* Add version to settings API endpoint

Add dynamic version reading from package metadata to settings.as_json():
- Use importlib.metadata.version() to read from pyproject.toml
- Fallback to '0.0.0' if package metadata unavailable
- Required for Electron client version compatibility checking

The /api/v1/settings endpoint now includes a 'version' field that the
Electron client uses to validate server compatibility before connecting.

Refs #839

* Hide navbar on ServerSelector page

Add v-if condition to hide navbar when on /electron/server-selector route.
The navbar (with About, Help, Login buttons) is now hidden on the server
selection screen, providing a cleaner first-run experience.

Refs #839

* Read version directly from pyproject.toml

Replace importlib.metadata.version() with direct reading from pyproject.toml
using tomllib (Python 3.11+ built-in). This avoids dependency on package
installation and ensures version is always available.

- Add _get_version() helper function
- Read from pyproject.toml using tomllib
- Fallback to '0.0.0' if file not found or parse error
- Log warning if version read fails

Fixes issue where version was returning '0.0.0' because server wasn't
installed as a package.

Refs #839

* Add CORS headers to support Electron app requests

Add CORS (Cross-Origin Resource Sharing) headers to BaseController:
- set_default_headers() adds CORS headers to all responses
- options() method handles CORS preflight requests
- Allow all origins (*) for Electron compatibility (file:// protocol)
- Allow standard HTTP methods and headers

This fixes CORS errors when the Electron app (running from file:// or
Vite dev server) makes requests to the backend API.

Refs #839

* Fix RBAC roles not loading on page reload in Electron

After connecting to a server via ServerSelector and reloading the page,
the router guard wasn't detecting that RBAC roles needed to be fetched.
The check only looked at whether the store was undefined, not whether
the store data was empty.

Now also checks if RBAC_ROLES getter is empty to trigger settings fetch,
ensuring all required state is loaded before navigation proceeds.

Fixes Vue warnings about IS_SHOW_EDITOR and other RBAC getters being
undefined during render.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Fix missing IS_SHOW_EDITOR getter in ConfigShow component

The ConfigShow component was referencing IS_SHOW_EDITOR in its template
(line 6: v-if="IS_SHOW_EDITOR") but not importing it in mapGetters.

This caused Vue development mode to display a warning:
"Property or method IS_SHOW_EDITOR is not defined on the instance"

In production builds, this was silently failing - the undefined value
evaluated to falsy, so the "Edit Show" button simply didn't render
instead of showing an error.

Added IS_SHOW_EDITOR to the mapGetters array to properly import the
getter and fix both the dev warning and ensure the button displays
correctly for users with edit permissions.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Configure Electron production build with shared frontend

Changes:
- Set base: './' in Vite config for relative paths (works with both
  web server and Electron file:// protocol)
- Updated Electron to load from ../server/static in development,
  process.resourcesPath/static when packaged
- Added server connection dropdown in navbar (Electron only)
- Added switchServer() method and clearActiveConnection IPC
- Configured Electron Forge to include server/static as extraResource
- Added build script: builds frontend then packages Electron app

Build workflow:
1. cd client && npm run build (outputs to ../server/static)
2. cd electron && npm run build (packages app with frontend included)

Both web and Electron use same built files - no duplication!

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Fix Electron routing by using hash mode for file:// protocol

When loading from file:// protocol (Electron production build),
Vue Router's history mode fails because it tries to navigate to
file paths that don't exist (e.g., file:///show-config).

Solution: Detect file:// protocol and use hash mode (#/show-config)
for Electron, while keeping history mode for web server.

This allows navigation to work correctly in packaged Electron apps
while maintaining clean URLs in the web version.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Fix file:// protocol navigation using window.location.reload()

The issue: After connecting to a server, using window.location.href = '/'
navigates to file:/// (filesystem root) instead of reloading the app.

Solution: Use window.location.reload() to reload the current page,
which works correctly with both file:// protocol and web servers.

Changes:
- ServerSelector.vue: Replace window.location.href = '/' with
  window.location.reload() after successful connection
- App.vue: Use router.push() + reload() for switchServer action

This ensures navigation works correctly in packaged Electron apps.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Fix Electron navigation and WebSocket cleanup issues

Issue 1: After connecting, window.location.reload() was reloading the
ServerSelector page instead of navigating to home. This caused a
redirect loop.

Issue 2: WebSocket connection stayed active when switching servers,
causing connection leaks.

Solutions:
1. Navigate to home using hash-based URL (baseUrl + '#/') instead of
   reload, which properly navigates in hash mode
2. Close WebSocket connection with this.$socket.close() before clearing
   active connection and navigating to ServerSelector

Now users can connect to a server and navigate properly, and switching
servers cleanly closes the old connection before reconnecting.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Fix WebSocket reinitialization after server connection

The issue: After connecting to a server, changing window.location.href
to a hash URL (e.g., baseUrl + '#/') only triggers client-side
navigation, not a full page reload. This means main.js never re-runs,
so the WebSocket is never reinitialized.

Solution: Set window.location.hash first (to specify target route),
then call window.location.reload() to force a full page reload.
This ensures main.js runs again and reinitializes the WebSocket.

Changes:
- ServerSelector: Set hash to '/' then reload after connecting
- App.vue switchServer: Set hash to '/electron/server-selector' then reload

Now the WebSocket properly reinitializes after switching/reconnecting.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Separate web and Electron builds to fix routing issues

Issue: Using base: './' for both web and Electron caused SPA routing
issues. On refresh of nested routes like /show-config/cast, relative
asset paths resolved incorrectly (e.g., ./assets/index.js became
/show-config/cast/assets/index.js), causing MIME type errors.

Solution: Separate build outputs with different base paths:
- Web build: base: '/' → ../server/static/ (absolute paths)
- Electron build: base: './' → ./dist-electron/ (relative paths)

Changes:
- vite.config.js: Conditional base and outDir based on BUILD_TARGET env
- Electron build script: Sets BUILD_TARGET=electron
- Electron main.js: Loads from ../client/dist-electron/
- Electron Forge: Packages dist-electron/ as extraResource
- .gitignore: Ignore dist-electron/

Build commands:
- Web: cd client && npm run build
- Electron: cd electron && npm run build (builds frontend + packages)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Implement mDNS service discovery for Electron app

Add mDNS/DNS-SD service advertising on the server and discovery on the
Electron client, allowing automatic server detection on the local network.

Server changes:
- Create MDNSAdvertiser class using AsyncZeroconf for async event loop
  compatibility
- Integrate mDNS into DigiScriptServer with toggleable setting
- Add mdns_advertising setting (enabled by default) with callback
- Support graceful start/stop when setting changes
- Deduplicate IP addresses from getaddrinfo()

Client changes:
- Fix bonjour-service import (use named export with constructor)
- MDNSDiscovery service already implemented, just needed import fix

Technical details:
- Use AsyncZeroconf instead of sync Zeroconf to avoid blocking Tornado's
  event loop
- Service type: _digiscript._tcp.local.
- Advertise on all non-loopback IPv4 addresses
- Async settings access pattern for proper lock handling

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Add ESLint and Prettier configuration to Electron project

Configure linting and formatting for the Electron project to match the
client project's code quality standards.

Changes:
- Add ESLint 9 with flat config (eslint.config.mjs)
- Add Prettier for code formatting (.prettierrc.json)
- Add lint and format npm scripts matching client project
- Install required dev dependencies:
  - eslint, @eslint/js
  - prettier, eslint-config-prettier, eslint-plugin-prettier
  - globals for environment definitions

Scripts added:
- npm run lint: Format and lint with auto-fix
- npm run ci-lint: Check formatting and linting (CI mode)
- npm run format: Auto-format all JavaScript and JSON files
- npm run format:check: Check formatting without changes

Configuration:
- ESLint: Node.js globals, ES2021 features, Prettier integration
- Prettier: Single quotes, 100 char width, ES5 trailing commas
- Automatically formatted existing code to match standards

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Create unit tests for platform abstraction layer

* Update GitHub actions

* Potential fix for code scanning alert no. 1145: Workflow does not contain permissions

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Add back basic navbar to server config page

* Server connection UX improvements

* Add secure health endpoint and restore settings authentication

Create dedicated /api/v1/health endpoint for version checking that
exposes only minimal, non-sensitive information (version and status).
Previously, the Electron client used /api/v1/settings which exposed
sensitive system data (database paths, log paths, debug mode, etc.)
to unauthenticated clients.

Backend changes:
- Add GET /api/v1/health endpoint (public, no auth required)
- Restore @api_authenticated decorator to GET /api/v1/settings
- Keep @allow_when_password_required for password reset workflow
- Export get_version() function from settings module
- Fix test infrastructure: add missing port parameter to DigiScriptTestCase

Frontend changes:
- Update Electron VersionChecker to use /api/v1/health endpoint
- Update ServerSelector UI enhancements (text alignment, time formatting)

Tests:
- Add comprehensive test suite for health endpoint (4 tests)
- Add authentication tests for settings endpoint (2 tests)
- All 315 backend tests passing
- All 83 frontend tests passing

Security impact:
- Before: 10+ sensitive fields exposed publicly via /api/v1/settings
- After: Only 2 non-sensitive fields exposed via /api/v1/health
- Settings endpoint now requires authentication (401 without token)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Restructure CI/CD workflows into modular build pipeline

Replace monolithic build.yml with three separate workflows for better
separation of concerns and parallel execution.

New workflow structure:
1. release.yml - Creates GitHub release with release notes
2. build-server.yml - Builds PyInstaller server executables
3. build-electron.yml - Builds Electron desktop installers

Benefits:
- Parallel execution: Server and Electron builds run simultaneously
- Better testing: Both workflows run on PRs to validate builds
- Cleaner separation: Each workflow has single responsibility
- Faster releases: No sequential dependency between builds

Workflow triggers:
- On tag push (v*): All three run, artifacts uploaded to release
- On PR (main/dev): Build workflows run for validation (no upload)

Release process:
1. Push tag (e.g., v0.24.0)
2. release.yml creates GitHub release
3. build-server.yml builds server, uploads to release
4. build-electron.yml builds Electron apps, uploads to release
5. All artifacts appear in single release

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Fix CI build failures and add security permissions

Build Fixes:
- Add author field to electron/package.json (required by Squirrel Windows)
- Add authors config to Squirrel maker
- Add bin config to deb/rpm makers (fixes executable name mismatch)
- Add maintainer/vendor fields to Linux makers for consistency
- Add author and description to client/package.json

Security Improvements (per GitHub Advanced Security):
- Add explicit permissions blocks to all new workflows
- Use contents: read as default for build jobs
- Use contents: write only for release upload jobs
- Follows principle of least privilege for GITHUB_TOKEN

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* Add GPL-3.0 license to Electron package.json

Required for RPM package builds which need a license identifier
in the spec file.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add Electron app documentation

- development.md: Add project structure, Electron build instructions,
  BUILD_TARGET explanation, and Electron linting command
- deployment.md: Add server executable downloads, Electron installation
  guide, server connection instructions, version compatibility notes,
  and CI/CD pipeline overview

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Remove outdated Phase 2 comment

IPC is already implemented via sendSync - comment was misleading.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* remove plan file

* Update npm packages across client and electron

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
- Upgrade electron from ^32.2.10 to ^40.0.0
- Upgrade electron-store from ^8.2.0 to ^11.0.2
- Upgrade globals from ^15.14.0 to ^17.1.0
- Remove node-fetch (using native fetch in Node 24)

ESM migration:
- Add "type": "module" to package.json
- Convert main.js and services to ES modules
- Rename preload.js to preload.cjs (sandboxed preload requires CommonJS)
- Update ESLint config to handle both .js (ESM) and .cjs (CommonJS)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Bumps [setuptools](https://github.com/pypa/setuptools) from 80.9.0 to 80.10.1.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](pypa/setuptools@v80.9.0...v80.10.1)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-version: 80.10.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.14.13 to 0.14.14.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](astral-sh/ruff@0.14.13...0.14.14)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.14.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@Tim020 Tim020 added the release Pull requests for creating a new release label Jan 24, 2026
@github-actions github-actions bot added github GitHub actions related issue or pull request client Pull requests changing front end code server Pull requests changing back end code xlarge-diff idea git labels Jan 24, 2026
@github-actions
Copy link

github-actions bot commented Jan 24, 2026

Client Test Results

83 tests   83 ✅  0s ⏱️
 3 suites   0 💤
 1 files     0 ❌

Results for commit 67ed187.

♻️ This comment has been updated with latest results.

@github-actions
Copy link

github-actions bot commented Jan 24, 2026

Python Test Results

  1 files    1 suites   35s ⏱️
313 tests 313 ✅ 0 💤 0 ❌
318 runs  318 ✅ 0 💤 0 ❌

Results for commit 67ed187.

♻️ This comment has been updated with latest results.

@Tim020 Tim020 marked this pull request as ready for review January 24, 2026 22:28
@Tim020 Tim020 enabled auto-merge January 24, 2026 22:30
@Tim020 Tim020 merged commit 3792aae into main Jan 24, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

client Pull requests changing front end code git github GitHub actions related issue or pull request idea release Pull requests for creating a new release server Pull requests changing back end code xlarge-diff

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants