fix(csp): allow loopback HTTP for the local AI provider; enable AI Assistant by default
Real end-to-end verification (Playwright-driven real Electron app on this Mac, against the actual local Ollama instance, not a mock) found the actual blocker: production's connect-src CSP (`'self' https: wss:`) rejects plain http:// entirely, so lib/ai/local-client.ts's loopback fetch to Ollama never even attempted the network in a production build - Electron or browser alike. This is almost certainly what looked like a browser-sandbox network issue in the earlier (non-Electron) QA pass tonight too. Fix is narrow, not a blanket http: relaxation: connect-src now additionally allows `http://127.0.0.1:*` and `http://localhost:*` specifically. Loopback has no network hop, so it doesn't reopen the mixed-content-style downgrade risk the existing https-only production policy guards against - unlike dev's blanket `http:` allowance, which stays dev-only. Confirmed fixed: rebuilt (build:standalone + build:electron), launched the real Electron app via Playwright's _electron, and got a genuine answer back from the real local Ollama - "Test connection" showed Reachable (the real success state, not the CORS-diagnostic fallback text), and asking "Reply with exactly the words: LOCAL AI WORKS" returned exactly that, with the correct "no local mail index in this session" banner alongside it (accurate for a fresh Electron session with nothing synced yet). Also flips FeatureGates.aiAssistantEnabled's default false->true: local now genuinely works and ships free/unmetered (see lib/ai/types.ts), so there is a real feature behind the tab, not an empty preview - matches tonight's explicit "I want AI visible" instruction. An admin can still turn it off. Verified: typecheck clean, lint clean (0 errors, pre-existing warnings only), translations pass (48/48), full production build succeeds.
This commit is contained in:
@@ -109,7 +109,22 @@ export async function proxy(request: NextRequest) {
|
||||
// https-served production app already gets unencrypted connections
|
||||
// blocked as mixed content by the browser itself, so allowing bare `ws:`
|
||||
// here would add no capability, only a false sense of one.
|
||||
const connectSrc = isDev ? `'self' http: https: ws: wss:` : `'self' https: wss:`;
|
||||
// `http://127.0.0.1:*`/`http://localhost:*` in production alongside
|
||||
// `https:`: the AI Assistant's `local` provider class (lib/ai/local-client.ts)
|
||||
// talks directly to a loopback Ollama-compatible runtime, over plain HTTP -
|
||||
// Ollama has no built-in TLS story, and there's no realistic MITM risk to
|
||||
// guard against on loopback (no network hop ever occurs). This is
|
||||
// deliberately NOT the same relaxation as blanket `http:` in dev: a
|
||||
// narrow, loopback-only allowance doesn't reopen the mixed-content-style
|
||||
// downgrade risk documented below for `wss:`. Confirmed as a real gap, not
|
||||
// theoretical: before this fix, a production build's own Electron shell
|
||||
// blocked `fetch('http://127.0.0.1:11434/...')` before any network
|
||||
// attempt happened at all (a CSP violation, connect-src as the violated
|
||||
// directive) - `local` was entirely inert in a production build,
|
||||
// Electron or browser alike.
|
||||
const connectSrc = isDev
|
||||
? `'self' http: https: ws: wss:`
|
||||
: `'self' https: wss: http://127.0.0.1:* http://localhost:*`;
|
||||
|
||||
const frameAncestors = isSandboxPath
|
||||
? `'self'`
|
||||
|
||||
Reference in New Issue
Block a user