Skip to content

feat(desktop): switch to embedded sqlite and electron packaging#125

Draft
rookedsysc wants to merge 137 commits intodevfrom
refactor/nextron
Draft

feat(desktop): switch to embedded sqlite and electron packaging#125
rookedsysc wants to merge 137 commits intodevfrom
refactor/nextron

Conversation

@rookedsysc
Copy link
Copy Markdown
Owner

@rookedsysc rookedsysc commented Mar 18, 2026

What does this PR do?

  • Migrates KanVibe from a Docker/PostgreSQL runtime to an embedded SQLite desktop runtime.
  • Adds Electron + Electron Builder packaging so the app can be distributed as a desktop build and prepared for DMG/Homebrew release flows.
  • Adds a Playwright login smoke test to verify the real button-click login flow end to end.
  • Adds a native runtime preflight so startup fails clearly on the wrong runtime and stale better-sqlite3 binaries are handled more safely.
  • Follows up on review feedback around session signing, packaged startup behavior, and CI/runtime hardening.

How is it implemented?

Embedded database runtime

  • Replace the PostgreSQL connection flow with better-sqlite3 + TypeORM.
  • Add runtime DB path resolution, bundled seed DB generation, and idempotent SQLite schema bootstrap logic.
  • Remove Docker-based startup requirements from the CLI flow.

Desktop packaging

  • Add Electron entrypoints and Electron Builder configuration.
  • Boot the existing Next.js custom server inside Electron and open it through a desktop window.
  • Add Linux headless hardening so desktop verification can run in CI-like environments without disabling the sandbox for all Linux users.
  • Add a Homebrew Cask template and document the DMG/Homebrew release path.

Verification and workflow updates

  • Add a Playwright login E2E that fills credentials, clicks the real login button, and asserts board access.
  • Pin local validation to Node 24 and align project docs/scripts with that runtime.
  • Ignore local automation state (.tooling, .omc, .codex/hooks) so verification artifacts do not pollute git status.
  • Add a startup preflight that validates the runtime before better-sqlite3 is first loaded.

Important Changes

Embedded SQLite migration

Runtime DB bootstrap and seed generation

  • Why: the app must run without Docker and carry its own local database.
  • Files: src/lib/database.ts, src/lib/databasePaths.ts, src/lib/sqliteSchema.ts, scripts/build-seed-db.ts, src/lib/typeorm-cli.config.ts

SQLite-compatible entity updates

  • Why: enum/json/uuid column definitions had to be made SQLite-safe while preserving current behavior.
  • Files: src/entities/KanbanTask.ts, src/entities/PaneLayoutConfig.ts

Desktop packaging support

Electron runtime bootstrap

  • Why: package the existing Next.js app as a desktop application without downgrading the current app structure.
  • Files: electron/main.js, electron/preload.js, electron-builder.yml, server.ts, package.json

Distribution and release templates

  • Why: make DMG and Homebrew release preparation part of the repository workflow.
  • Files: distribution/homebrew/kanvibe.rb.template, README.md, docs/README.ko.md, docs/README.zh.md, docs/nextron-bundled-db-homebrew-app.mdx

Review follow-up hardening

Session signing secret separation

  • Why: prevent the session cookie HMAC key from reusing the login password and keep generated secrets stable across restarts.
  • Files: src/lib/auth.ts, .env.example, src/lib/__tests__/auth.test.ts

Packaged runtime and CI safety

  • Why: avoid pnpm rebuild attempts inside packaged apps, keep Linux sandboxing enabled for desktop users, and isolate Playwright app data between concurrent runs.
  • Files: scripts/ensure-native-runtime.cjs, electron/main.js, playwright.config.ts

Packaging and cleanup reliability

  • Why: ensure packaged tsx alias resolution still finds tsconfig.json, remove dead request-cancellation state, and harden SQLite schema helpers against unsafe identifier interpolation.
  • Files: electron-builder.yml, src/components/AiSessionsDialog.tsx, src/lib/sqliteSchema.ts

Validation

  • node scripts/ensure-native-runtime.cjs under Node 24
  • node scripts/ensure-native-runtime.cjs under Node 25 to verify fast failure guidance
  • pnpm db:prepare
  • pnpm build
  • pnpm test:e2e:login
  • pnpm check
  • pnpm test
  • pnpm exec tsc --noEmit
  • pnpm exec vitest run src/lib/__tests__/auth.test.ts src/components/__tests__/AiSessionsDialog.test.tsx

Replace the Docker/PostgreSQL runtime with a bundled SQLite database,
add Electron Builder packaging, and document the DMG/Homebrew release flow.
Preserve hook-driven status updates and notification behavior while making
the app buildable as a desktop distribution.
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Mar 18, 2026

Greptile Summary

This PR is a significant architectural migration that replaces the Docker/PostgreSQL runtime with an embedded SQLite database and wraps the existing Next.js application in an Electron desktop shell for DMG/Homebrew distribution. The database layer swap is well-structured — entity columns are correctly migrated to SQLite-compatible types (simple-enum, simple-json, varchar(36)), the schema bootstrap is idempotent, and the seed-DB generation flow is clean. The Electron entrypoint correctly isolates the desktop server to 127.0.0.1 and uses a proper readiness poll before opening the window.

Key issues found (beyond those already in previous threads):

  • --no-sandbox is applied to all Linux users, not just CI/headless environments. This removes Chromium's primary renderer security sandbox for every Linux desktop user. It should be gated on process.env.CI or the absence of DISPLAY.
  • The Electron auto-rebuild path calls pnpm which is unavailable in a packaged app. If a native ABI mismatch is ever detected inside a distributed .app bundle, execFileSync("pnpm", …) will throw ENOENT, crashing startup with a confusing error instead of the intended human-readable guidance.
  • Playwright appDataDir is a hardcoded /tmp/ path, causing test-state collisions when CI runs jobs concurrently.
  • The E2E login test hardcodes credentials and Korean UI labels, making it brittle against environment-variable overrides and locale changes.
  • safeSessionsData null-guard in AiSessionsDialog.tsx is unreachablesessionsData is always initialised to a non-null object via createEmptySessionsResult.

Confidence Score: 3/5

  • Needs two targeted fixes before merging to avoid a security regression on Linux and a startup crash in the packaged Electron app.
  • The core migration (SQLite schema, entity changes, DB path resolution) is solid and the Electron bootstrap logic is well thought out. However the unconditional --no-sandbox on Linux is a real security regression for end-users, and the pnpm rebuild call inside a packaged app will crash instead of printing the intended guidance. These two P1 issues lower confidence meaningfully. The remaining issues (Playwright path, E2E credentials, dead null-check) are quality improvements that can be addressed in a follow-up if needed.
  • electron/main.js (sandbox flag) and scripts/ensure-native-runtime.cjs (packaged-app rebuild path) need attention before this is shipped to end-users.

Important Files Changed

Filename Overview
electron/main.js New Electron entrypoint: boots the internal server, waits for readiness, and opens BrowserWindow. The unconditional --no-sandbox flag on Linux removes Chromium's security sandbox for all end-users, not just CI environments.
scripts/ensure-native-runtime.cjs New preflight that validates the Node version and auto-rebuilds better-sqlite3 on ABI mismatch. The Electron rebuild path calls pnpm exec electron-builder install-app-deps which will fail with ENOENT in a packaged app where pnpm is not available.
src/lib/database.ts Replaces PostgreSQL DataSource with better-sqlite3 + TypeORM, removes migration imports, and adds WAL mode / foreign-key pragmas. Logic is sound; ensureRuntimeDatabaseFile and ensureSqliteDatabaseReady are called before DataSource initialisation.
src/lib/sqliteSchema.ts Idempotent SQLite bootstrap: creates tables, ensures additive columns, and exposes buildSeedDatabase. SQL template-literal injection concern was flagged in an earlier review thread; all current call sites use hardcoded literals so the immediate risk is low.
playwright.config.ts New Playwright config for the login E2E suite. Uses a hardcoded /tmp/kanvibe-playwright-appdata directory that will conflict between concurrent CI jobs.
tests/e2e/login.spec.js New E2E smoke test for the login flow. Hardcodes credentials and Korean UI labels, making it fragile if env vars differ or the default locale changes.
electron-builder.yml New Electron Builder configuration. tsconfig.json omission was flagged in a prior thread. asar: false is intentional to allow the custom Next.js server to read packaged files at runtime.
src/components/AiSessionsDialog.tsx Adds null-safe wrappers (createEmptySessionsResult, translateOptional) and refactors optional query/role args to avoid passing undefined as positional params. The safeSessionsData null guard is redundant since sessionsData is always initialised to a non-null object.

Sequence Diagram

sequenceDiagram
    participant U as User / OS
    participant E as electron/main.js
    participant B as boot.js
    participant P as ensure-native-runtime.cjs
    participant S as server.ts (Next.js)
    participant D as src/lib/database.ts
    participant DB as SQLite (.kanvibe/kanvibe.db)

    U->>E: Launch app
    E->>E: Set KANVIBE_DESKTOP, KANVIBE_APP_DATA_DIR,<br/>KANVIBE_SEED_DB_PATH, NODE_ENV
    E->>B: require(boot.js)
    B->>P: require(ensure-native-runtime.cjs)
    P->>P: Check Node major version
    P->>P: Try load better-sqlite3
    alt ABI mismatch
        P->>P: execFileSync pnpm rebuild / install-app-deps
        P->>P: Retry load better-sqlite3
    end
    B->>S: require(server.ts) via tsx
    S->>D: getDataSource() on first request
    D->>DB: ensureRuntimeDatabaseFile() — copy seed DB or create empty
    D->>DB: ensureSqliteDatabaseReady() — CREATE TABLE IF NOT EXISTS …
    D->>DB: DataSource.initialize()
    S-->>E: HTTP server listening on 127.0.0.1:PORT
    E->>E: waitForServer(http://127.0.0.1:PORT/ko/login)
    E->>U: BrowserWindow.loadURL(startUrl)
Loading

Last reviewed commit: "fix(native): add bet..."

Comment thread src/lib/auth.ts Outdated
Comment thread electron-builder.yml Outdated
Comment thread src/components/AiSessionsDialog.tsx Outdated
Add a real button-click login E2E flow with Playwright, pin the test
runtime to Node 24, and harden the local desktop/dev setup for headless
verification. Ignore local automation state so repo-only changes stay clean.
Comment thread src/lib/sqliteSchema.ts Outdated
Fail fast when local scripts run on the wrong Node major and auto-rebuild
better-sqlite3 before startup when the native ABI is stale. Document the
macOS recovery path so desktop and server launches recover consistently.
Comment thread electron/main.js
Comment thread scripts/ensure-native-runtime.cjs
Comment thread playwright.config.ts
Comment thread src/components/AiSessionsDialog.tsx
Separate the session signing secret from the login password, keep packaged Electron startup from trying local rebuild tools, and tighten Linux/test runtime defaults so desktop builds and CI runs stay predictable.
Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

rookedsysc and others added 2 commits March 22, 2026 14:48
Run the desktop dev entrypoint through a bootstrap script so missing installs and Electron ABI mismatches are handled before the app starts.
fix(desktop): automate native dependency recovery for desktop dev
Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

rookedsysc and others added 4 commits March 22, 2026 22:38
Open internal task detail links in separate Electron windows so desktop users can keep multiple tasks visible and searchable by branch and project title. Update the desktop title bar styling to use a white native chrome for a lighter app shell.
Handle Cmd/Ctrl+N at the Electron window level so desktop users can duplicate the current board or task view without relying on mouse interactions.
Keep drag-and-drop state updates pure so the board no longer triggers router updates while rendering. Add a regression test that verifies reorder persistence runs after the drag event completes.
feat(desktop): add multi-window support and board drag fixes
Copy link
Copy Markdown

@greptile-apps greptile-apps Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@rookedsysc rookedsysc marked this pull request as draft April 1, 2026 01:35
@rookedsysc rookedsysc self-assigned this Apr 1, 2026
rookedsysc and others added 11 commits April 1, 2026 23:03
Route Electron task notifications through the main process so desktop builds show OS-level alerts and restore the app window when users click them.
Keep the existing service worker flow for the web app and cover the desktop branch with targeted tests.
Document how the commit workflow can include AI author markers in commit footers and PR bodies only when the --aiauthor flag is provided.
fix(desktop): deliver native alerts and document --aiauthor option
Replace the localhost Next desktop shell with a Vite renderer and IPC-backed Electron services.
Keep lightweight hook endpoints for agent integrations while making dev and start launch the desktop app directly.
Memoize the desktop router so refresh handlers stay stable across renders.
Prevent the board auto-refresh hook from retriggering data fetches indefinitely.
Verify better-sqlite3 against the Electron runtime before launch and rebuild it from source when the ABI does not match.
Run the same recovery path during postinstall so desktop dependencies stay ready after install.
머지 충돌로 깨진 Electron 알림 경로와 렌더러 브리지를 함께 복구한다.
데스크톱 전용 동작과 테스트를 맞춰 PR 브랜치가 다시 검증 가능하도록 정리한다.
Avoid ambiguous task lookups when branch names or project names overlap.
Propagate project ids through generated AI hooks and update tests for the new payload.
fix: use project ids for hook-driven status updates
Add extra top padding to the board header in the mac desktop app so the logo and title do not collide with the traffic light buttons.
Handle session and parent identifiers directly from event payloads so only main OpenCode sessions change Kanvibe hook status.
Add coverage for session.deleted and the broader session shape handling in the generated plugin tests.
rookedsysc and others added 30 commits April 24, 2026 15:50
fix(opencode): refresh hook status diagnostics
Overwrite stale remote Claude and Gemini hook entries during reinstall,
replace existing Codex notify registrations instead of appending duplicates,
and log per-provider verification results after installation.

Reduce the OpenCode dialog to a short duplicate-plugin notice so detailed
verification stays in logs instead of the UI.

Co-Authored-By: Codex <noreply@openai.com>
fix(hooks): overwrite stale hook installs and simplify diagnostics
Use the concrete provider status unions for hook verification logging instead of casting through a generic index-signature object.
Guard OpenCode-only plugin URL fields so the installer compiles without weakening the type checks.

Co-Authored-By: OpenAI Codex <codex@openai.com>
fix(hooks): align verification status logging types
Remove the duplicate OpenCode plugin notice from the hooks status dialog.
Keep the regression test focused on verifying the dialog stays clean when duplicate plugins are detected.

Co-Authored-By: OpenAI Codex <codex@openai.com>
Delete the unused hooksOpenCodeDuplicatePluginsNotice translations and remove the last test reference to that key.

Co-Authored-By: OpenAI Codex <codex@openai.com>
fix(hooks): remove OpenCode duplicate plugin notice
맥 데스크톱에서 보드 헤더가 별도 타이틀바처럼 보이지 않도록 배경과 경계 스타일을 정리한다.
프로젝트 선택 검색 컨트롤이 traffic light 영역과 겹치지 않도록 상단 여백을 늘리고 회귀 테스트 기대값도 함께 갱신한다.

Co-Authored-By: OpenAI Codex <codex@openai.com>
새 태스크 저장 직후 보드 갱신을 먼저 보내고 hook 설치는 백그라운드로 넘깁니다.
설치 실패 이벤트와 상단 알럿을 추가해 재설치 필요 상태를 바로 안내합니다.
생성 경로와 알럿 동작 회귀 테스트 및 작업 계획 문서를 함께 정리합니다.

Co-Authored-By: OpenAI Codex <codex@openai.com>
perf(task): 새 태스크 hook 설치를 비동기로 전환
Replace the legacy notify-only Codex setup with the current hooks.json
lifecycle hook model and enable codex_hooks in config.toml.

Update remote installation, status verification, tests, and user-facing
documentation so KanVibe reflects the latest Codex hooks behavior.

Co-Authored-By: OpenAI Codex <codex@openai.com>
feat(codex): support current lifecycle hooks configuration
Hook API로 생성한 remote task에도 hooks를 자동 설치하도록 맞추고,
Hooks 상태 다이얼로그에서 도구별 설치를 병렬로 실행할 수 있게 조정한다.
또한 remote 환경에서는 SSH를 통해 gh로 PR URL을 조회하도록 보강하고 회귀 테스트를 추가한다.

Co-Authored-By: OpenAI Codex <codex@openai.com>
…e-pr-link

# Conflicts:
#	src/desktop/main/services/__tests__/kanbanService.test.ts
#	src/desktop/main/services/kanbanService.ts
fix(remote): resolve remote hook install and PR link regressions
원격 provider 하나가 SSH transport 오류로 실패해도 다른 세션 집계 결과를 유지합니다.
원격 Codex 회귀 테스트를 추가해 해당 실패를 source 비가용 상태로만 처리합니다.

Co-Authored-By: OpenAI Codex <codex@openai.com>
원격 task 상세에서 gh가 없으면 설치 여부를 dialog로 묻고,
설치가 완료되면 PR URL 조회를 다시 시도하도록 흐름을 보강합니다.
공식 gh 설치 경로와 프롬프트/조회 회귀 테스트도 함께 추가합니다.

Co-Authored-By: OpenAI Codex <codex@openai.com>
Stabilize remote task detail AI sessions and PR link recovery
Prefer the remote project repository path when resolving PR URLs so stale task worktree paths do not break SSH-based gh lookups.
Broadcast a board update after saving prUrl so remote task cards and detail screens can render the link without a manual reload.

Co-Authored-By: OpenAI Codex <codex@openai.com>
fix(pr): restore remote task PR link resolution
Keep desktop child windows independent from their opener so Cmd+W only closes the active window.
Reuse an existing Kanvibe window when the same internal route is already open, and cover the route-matching policy with focused regression tests.

Co-authored-by: Codex <noreply@openai.com>
fix(desktop): isolate multi-window closes and reuse existing routes
Defer remote root hook repair during project registration so SSH scans and worktree discovery are not blocked by hook setup failures.
Restore remote tmux pane bootstrapping, reuse SSH connections, and batch remote hook writes to reduce command latency.
Write generated AI hook files to the common git exclude for remote worktrees and treat hook server reachability as diagnostics instead of install failure.

Co-Authored-By: OpenAI Codex <codex@openai.com>
Fix remote worktree discovery and hook setup reliability
repair git exclude updates for linked worktrees and remote installs
await remote task hook installation while keeping local installs async
cache board and task detail data to reuse stale state on back and refresh

Co-Authored-By: OpenAI Codex <codex@openai.com>
fix(desktop): stabilize hook setup and route caching
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants