feat: config & onboarding — each teammate connects their own Gitea (productionize Phase A) #51

Merged
christian merged 1 commits from feat/config-onboarding into main 2026-07-09 14:41:20 +00:00
Owner

Phase A of productionizing for team sharing. Replaces .env.local-only dev config with a real per-teammate connection flow — the foundation for handing this to your team.

Main

  • config-store.ts — token encrypted at rest via Electron safeStorage (OS keychain); config JSON in userData. Token lives only in main; the renderer receives everything but the token.
  • resolveConfig — saved config > .env.local (dev) > null; ignored under COMMITEA_E2E. pm-state repo defaults to ${repo}-pm-state. resetClients() re-reads on change, so saving config takes effect without a restart. gitea:status gains demo.
  • IPCconfig:get (no token), config:test (authed read validates token+repo), config:set (encrypt+save+reset), config:clear. Model bridge reads config.modelUrl and probes reachability — chat is 'configured' only if a model actually answers (localhost default is dev-only via app.isPackaged).

Renderer

  • ConnectScreen — real onboarding form (URL / owner / repo / PAT / optional model) → test → save. AppShell gates: demo → shell (fixtures/e2e); configured → shell (real); else → connect.
  • Settings Connection card is real (repo / url / model / sidecar) with Reconfigure + Disconnect.
  • Chat cleanly disables with a 'no model' state instead of the scripted canned reply.

Verified

main + desktop typecheck clean · 14 fixture e2e green (demo mode unchanged) · live onboarding e2e: a fresh app (isolated userData, no .env.local) → connect form → validated PAT → real board (24 done / 10 open). Screenshot in run.

Next (productionize)

  • Phase B — kill the remaining fixtures: Standup, Inbox, Gantt + Dependencies tabs, Issue-screen sidecar; hide dev-only rail entries (States/Primitives/First-run) in prod.
  • Phase C — package: electron-builder → an unsigned macOS .dmg you can share.

🤖 Generated with Claude Code

**Phase A of productionizing for team sharing.** Replaces `.env.local`-only dev config with a real per-teammate connection flow — the foundation for handing this to your team. ## Main - **`config-store.ts`** — token encrypted at rest via Electron **safeStorage** (OS keychain); config JSON in userData. Token lives only in main; the renderer receives everything *but* the token. - **resolveConfig** — saved config > `.env.local` (dev) > null; ignored under `COMMITEA_E2E`. pm-state repo defaults to `${repo}-pm-state`. **`resetClients()`** re-reads on change, so saving config takes effect **without a restart**. `gitea:status` gains `demo`. - **IPC** — `config:get` (no token), `config:test` (authed read validates token+repo), `config:set` (encrypt+save+reset), `config:clear`. Model bridge reads `config.modelUrl` and **probes reachability** — chat is 'configured' only if a model actually answers (localhost default is dev-only via `app.isPackaged`). ## Renderer - **ConnectScreen** — real onboarding form (URL / owner / repo / PAT / optional model) → test → save. **AppShell gates**: demo → shell (fixtures/e2e); configured → shell (real); else → connect. - **Settings Connection** card is real (repo / url / model / sidecar) with **Reconfigure + Disconnect**. - **Chat** cleanly disables with a *'no model'* state instead of the scripted canned reply. ## Verified main + desktop typecheck clean · 14 fixture e2e green (demo mode unchanged) · **live onboarding e2e**: a fresh app (isolated userData, no `.env.local`) → connect form → validated PAT → **real board** (24 done / 10 open). Screenshot in run. ## Next (productionize) - **Phase B** — kill the remaining fixtures: Standup, Inbox, Gantt + Dependencies tabs, Issue-screen sidecar; hide dev-only rail entries (States/Primitives/First-run) in prod. - **Phase C** — package: electron-builder → an unsigned macOS `.dmg` you can share. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
christian added 1 commit 2026-07-09 06:10:21 +00:00
The foundation for a shareable team build. Replaces the .env.local-only dev config
with a real, per-teammate connection flow.

main:
- config-store.ts: token encrypted at rest via Electron safeStorage (OS keychain),
  config JSON in userData. Token lives only in main; renderer gets everything but.
- resolveConfig: saved config > .env.local (dev) > null; ignored under COMMITEA_E2E.
  pm-state repo defaults to `${repo}-pm-state`. resetClients() re-reads on change so
  saving config takes effect without a restart. gitea:status gains `demo` (e2e).
- IPC: config:get (no token), config:test (authed read validates token+repo),
  config:set (encrypt+save+reset), config:clear. Model bridge reads config.modelUrl
  and probes reachability — chat is "configured" only if a model actually answers;
  localhost default is dev-only (app.isPackaged gate).

renderer:
- ConnectScreen: real onboarding form (URL/owner/repo/PAT/optional model) → test →
  save. AppShell gates on it: demo → shell (fixtures/e2e); configured → shell (real);
  else → connect. Settings Connection card is real (repo/url/model/sidecar) with
  Reconfigure + Disconnect. Chat cleanly disables with a "no model" state instead of
  the scripted canned reply.

Verified: main + desktop typecheck clean, 14 fixture e2e green (demo mode unchanged),
live onboarding e2e: fresh app → connect form → validated PAT → real board (24 done /
10 open). COMMITEA_NO_ENV_LOCAL + COMMITEA_USERDATA are test hooks for the onboarding path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
christian merged commit 62a521e7eb into main 2026-07-09 14:41:20 +00:00
Sign in to join this conversation.
No description provided.