Files
Marco0300 d33940e37f
CI / compose (push) Successful in 9m4s
clarify desktop release status
2026-09-03 14:41:06 +02:00

156 lines
13 KiB
Markdown

# Windows desktop client
## Status and architecture
The desktop deliverable is a thin Electron shell that loads the unchanged `apps/web` bundle. In development it can load the bundled UI or a validated `--web-url=https://...`; in packaged builds the web assets are copied into `resources/web`. The shell provides first-run connection settings, safe backend URL persistence, reconnect/reload, external-link handling, and session/cache clearing without exposing secrets to renderer code.
Build the Windows installer/portable executable on a Windows-capable build host after installing dependencies:
```bash
npm install
npm run test
npm run verify
npm run build:win
```
Until one is selected and signed, do not describe an unsigned artifact as released. The source check is Chromium- and Windows-independent and is runnable from the repository root:
```powershell
node apps\desktop\scripts\smoke-desktop.mjs
```
The check is Chromium- and Windows-independent, verifies that all referenced web assets exist, confirms the desktop manifest covers local HTML assets, rejects a second UI copy, and compares the desktop route list with the web smoke harness. It is also runnable on Linux/macOS:
```bash
node apps/desktop/scripts/smoke-desktop.mjs
```
## Remote backend connection
The desktop client is a remote API client, not a local database or API server. Configure the web runtime object before packaging or at deployment time:
```js
window.__PROSPECT_CONFIG__ = Object.freeze({
apiBase: 'https://api.example.com',
assetVersion: 'phase-15'
});
```
- `apiBase` is the approved API origin; trailing `/` is accepted by the client and removed when building paths. An empty value uses the same origin, then the legacy `window.API_BASE`/`localStorage.prospect_api_base` fallback used by the web client.
- `assetVersion` is a cache-busting release label and is not a secret.
- Do not place API tokens, passwords, provider credentials, private keys, or session values in `config.js`, the manifest, the executable, logs, or installer metadata.
- The shell should provide network availability diagnostics and a retry path, but must not silently switch to another API origin.
- The API must be reachable over HTTPS in production. Local HTTP is suitable only for development (`http://127.0.0.1:8000` API and `http://127.0.0.1:8080` web server).
## Authentication and session behavior
The desktop uses the same login and session contract as web:
1. `POST /api/v1/auth/login` receives the email/password form over the configured origin.
2. Requests include `credentials: 'include'`; the API sets a server-side session cookie.
3. Startup calls `GET /api/v1/auth/me`. A `401` shows the login screen; it does not expose cached workspace data.
4. `401` from a protected request clears the dashboard and asks the user to sign in again. `403` remains an authorization/workspace denial.
5. Log out calls `POST /api/v1/auth/logout`, invalidates the server session, resets the form, and returns to login.
The shell must use the host's cookie jar/WebView profile, preserve cookies only for the configured origin, and provide a user-visible sign-out/clear-session operation. Never copy cookies into local storage, command-line arguments, crash reports, telemetry, or custom headers. A desktop session remains a bearer credential: lock the workstation, use OS account protection, and sign out on shared machines. Multi-factor authentication, password reset, and session administration are backend responsibilities; the current pilot does not claim those capabilities.
## Supported configuration
Supported desktop runtime configuration is intentionally limited to the two keys in the manifest: `apiBase` and `assetVersion`. Backend deployment configuration remains environment-only and is not desktop configuration:
- `APP_ENV`, `LOG_LEVEL`, `CORS_ORIGINS`, `API_PORT`, `WEB_PORT`, and `DATA_DIR` are deployment settings.
- Production requires `SESSION_SECRET` of at least 32 characters, supplied through a secret manager/protected environment.
- `BOOTSTRAP_ADMIN_EMAIL` and `BOOTSTRAP_ADMIN_PASSWORD` are one-time provisioning inputs; remove and rotate them after bootstrap.
- `AUTOMATED_OUTREACH_ENABLED` is rejected when enabled; the enforced default is `false`.
The desktop must not offer controls that imply it can override tenant authorization, source approval, rate limits, suppression, score/eligibility, AI policy, outreach, or backend safety settings. Those are server-enforced contracts.
## Security model
- The backend is the authority for authentication, authorization, tenant (`organization_id`) isolation, validation, audit records, suppression, pipeline transitions, job actions, and all safety gates.
- The desktop is an untrusted presentation client. Treat all responses, local files, clipboard content, and rendered prospect text as untrusted; preserve the web client's escaping and avoid adding privileged native bridges.
- The shell should expose only navigation and storage APIs required to render the web bundle. Disable arbitrary navigation, popups, downloads, file/system protocol access, script injection, and unrestricted native IPC unless separately reviewed.
- Do not grant the web content filesystem, process, registry, shell, camera, microphone, or credential-manager access by default. CSV preview is browser-local and is not an import or upload authority unless the server workflow explicitly confirms it.
- Keep the no-send boundary: no SMTP probing, provider calls, campaign creation, autonomous follow-up, or direct fetching of arbitrary target URLs from the desktop. A high score, AI suggestion, extracted contact, or approval does not authorize outreach.
- Production traffic must use HTTPS with certificate validation. Do not add a “trust all certificates” switch. Pinning, if considered, needs an operational rotation plan and is not currently required by this source contract.
## Windows build and release prerequisites
## Electron development and Windows packaging
Install Node.js 20+ and npm on Windows, then run these exact commands from PowerShell:
```powershell
cd <clone>\apps\desktop
npm install
npm run verify
```
Start the API in another PowerShell window, then start Electron in development mode:
```powershell
cd <clone>\apps\api
python app\main.py --host 127.0.0.1 --port 8000 --db $env:TEMP\prospects.db
# second window
cd <clone>\apps\desktop
npm run dev
```
`npm run dev` supplies the public runtime backend URL `http://127.0.0.1:8000`. For another environment, use `$env:PROSPECT_API_BASE="https://api.example.com"; npm start` (or the Connection settings menu). URLs are validated and credential/query/fragment-bearing values are rejected.
Build both x64 Windows artifacts only on Windows:
```powershell
cd <clone>\apps\desktop
npm install
npm run verify
npm run build:win
```
The NSIS installer and portable executable are written to `apps\desktop\release\`. This Linux checkout has not built, and does not claim to have built, an `.exe`.
## Auto-update policy
Auto-update is intentionally disabled until release signing, certificate custody, artifact publication, update-channel authorization, and rollback procedures are configured. There is no updater integration or publish provider in this package; do not add `electron-updater` or an update channel as part of a local build.
## API/CORS requirements
The renderer uses the existing web UI and sends credentialed requests to the configured API. Configure the API's `CORS_ORIGINS` for the exact origin emitted by the selected Electron loading strategy, with `Access-Control-Allow-Credentials: true`; never use `*` with credentials. Preserve server-side session, tenant authorization, CSRF, suppression, and outreach-disabled controls. CORS is not an authorization boundary. Verify preflight and authenticated login against staging before distribution.
A native desktop build packages `apps/web` unchanged via electron-builder `extraResources`; it does not modify backend files or create a second UI implementation.
A native release is blocked until the shell is selected and its toolchain is pinned. The release builder must provide:
- Supported Windows 10/11 x64 baseline, a clean build VM, and a documented x64/arm64 decision.
- Pinned Node.js LTS and package-lock (if the selected shell uses Node), plus the selected shell's exact SDK/toolchain and WebView2 runtime policy.
- Reproducible web asset build, manifest/version update, route/asset smoke check, JSON parse, JavaScript syntax check, and a clean `git diff --check`.
- Clean-room install/run test with the real signed artifact, login/session expiry/logout checks, offline/API-unavailable behavior, HTTPS certificate failure behavior, and DPI/scaling/high-contrast/basic keyboard navigation checks.
- Release notes containing API compatibility, minimum Windows version, architecture, config origin, known limitations, and rollback/revocation instructions.
- Artifact hashes and the exact source commit recorded beside the installer/MSIX/portable artifact. Retain the previous known-good artifact for rollback.
The API and web deployment still require their existing Docker/Compose, TLS, secret, backup, monitoring, and operational prerequisites. Building a Windows client does not deploy or upgrade the remote backend.
## Code signing and distribution
Every distributed `.exe`, `.msi`, MSIX package, and updater must be Authenticode-signed with an organization-controlled code-signing certificate. Prefer an EV/managed key or a hardware-backed/CI signing service; never commit a private key or export it into a developer workspace. Verify the signature and timestamp on a clean Windows host (for example with `Get-AuthenticodeSignature`) before publication. Sign each embedded executable and installer payload as required by the selected packaging technology, publish SHA-256 checksums, and retain signing/audit records. Unsigned developer builds must be clearly labeled and must never use the production API origin by default.
Certificate rotation, revocation, compromised-builder response, SmartScreen reputation, update-channel authorization, and artifact rollback require an owner and runbook before release. Signing proves publisher integrity; it does not make the client trusted with tenant data or make a backend response authoritative.
## Firewall and CORS
The desktop makes outbound HTTPS connections to the configured API; it does not listen for inbound connections and should not require an inbound Windows Firewall rule. If a chosen shell starts a local callback/update server, bind it to loopback, use an ephemeral port, authenticate the callback, and document the narrowly scoped firewall exception. Never open the API or a development server to `0.0.0.0` for desktop distribution.
For a remote API origin, configure `CORS_ORIGINS` to the exact desktop origin emitted by the selected shell/runtime and keep `Access-Control-Allow-Credentials: true`. Do not use `*` with credentialed requests. The API currently returns the configured `CORS_ORIGINS` value and allows `Content-Type`; verify the selected WebView's origin and preflight behavior in a staging environment. If the shell loads `file://` or a custom `app://` origin, do not guess a CORS value: choose a reviewed HTTPS/custom-origin strategy or package the UI behind the same approved origin, because cookie and CORS behavior differs by WebView host.
CORS is not authentication or tenant isolation. The backend must continue to enforce sessions and organization scope even when a request appears to come from the desktop.
## Limitations and support boundary
- The native Electron Windows shell and packaging configuration are checked in, but no signed Windows installer or portable `.exe` is included in this source checkout.
- The desktop has the web client's pilot limitations: SQLite/in-process jobs are not durable or horizontally scalable; SSE, live external discovery, production DNS/availability, production egress isolation, and production outreach delivery are not implemented.
- The current password fallback is development-grade; production still requires Argon2id, MFA, CSRF protection, rate limiting, durable audit/retention, and tested backup/restore procedures.
- Network loss, API version skew, expired sessions, proxy policy, certificate interception, sleep/resume, and WebView runtime updates can affect the client. The desktop cannot repair backend data or bypass a blocked safety gate.
- Local UI assets may be cached by the selected shell; bump `assetVersion` and require a restart/refresh after a UI release. There is no service-worker migration or offline write queue.
- CSV remains preview-only, and no desktop feature changes the no-send default. See `apps/web/README.md`, `apps/api/README.md`, `docs/SECURITY.md`, and `docs/RELEASE_CHECKLIST.md` for the authoritative web/API safety and operations contracts.