Commit 6cbb639
authored
feat(desktop): add per-provider TLS verification bypass (#355)
## Summary
- Adds an opt-in `tlsRejectUnauthorized` boolean on `ProviderEntry` so
users can connect to internal LLM gateways whose self-signed /
private-CA certificates Node 22's built-in fetch (undici) rejects —
`NODE_TLS_REJECT_UNAUTHORIZED` is intentionally ignored by undici, so a
runtime dispatcher swap is the only working bypass.
- Implements a ref-counted `withTlsBypass(enabled, fn)` helper in
`apps/desktop/src/main/tls-override.ts` that swaps the global undici
dispatcher for one with `rejectUnauthorized: false` around the wrapped
call, and restores the original in `finally`.
- Wires the bypass through every outbound HTTPS path: connection-test
(`test-active` / `test-provider` / `config:v1:test-endpoint`), models
discovery (`models:v1:list-for-provider`), and generation
(`codesign:v1:generate` + `codesign:v1:generate-title`).
- Surfaces the toggle in `AddCustomProviderModal` for non-built-in
providers only, gated behind a confirm prompt on first enable, and
renders a yellow "TLS verify off" badge on the affected provider row in
Settings.
- Built-in providers (anthropic, openai, openrouter, ollama)
force-ignore the flag at every call site so a tampered config cannot
weaken trusted endpoints.
Closes #229.
## Hard-constraints check (PRINCIPLES §5b)
- ✅ Compatibility — optional field, no schema version bump, existing
configs parse unchanged
- ✅ Upgradeability — flag is namespaced and per-entry; safe to extend
(e.g. per-CA pinning later)
- ✅ No bloat — `undici` was already a transitive dep via pi-ai; now
promoted to a direct dep so resolution is explicit. Helper is ~90 lines;
UI delta is a single checkbox + badge
- ✅ Elegance — single high-order wrapper, exception-safe via
`try/finally`, ref-count handles nested / concurrent acquires
## Design notes
Full design spec lives at
`docs/superpowers/specs/2026-05-23-tls-bypass-design.md` (gitignored per
project convention, local-only). The known concurrency window (parallel
non-bypass requests during a bypass interval inherit the loose
dispatcher) is documented in `tls-override.ts` and accepted as a
trade-off — eliminating it would require monkey-patching
`globalThis.fetch`, which touches every outbound call in the main
process and was deemed disproportionate. See spec §9 for rationale.
## Test plan
- [x] `pnpm typecheck` — clean across all 10 workspaces
- [x] `pnpm test` — 1354/1354 desktop, 228/228 shared, 208/208
providers, etc.
- [x] `pnpm lint` — only existing-on-main biome version-mismatch info;
no errors
- [x] New `apps/desktop/src/main/tls-override.test.ts` — 6 tests
covering: enabled=false noop, single acquire/release, nested acquire
(ref-count), throw-in-fn release, log emission, parallel acquire
- [x] Extended `apps/desktop/src/main/connection-ipc.test.ts` — 7 new
TLS bypass routing tests (built-in force-disable, non-built-in enable,
undefined/false → disable, payload flag enable, non-boolean reject)
- [x] Extended `packages/shared/src/config.test.ts` — schema
accepts/rejects/round-trips the new field
- [ ] Manual verification with an actual self-signed gateway is
recommended before merge (cannot be done in CI without spinning up a
fake CA)
## Known out-of-scope items
- `codesign:apply-comment` IPC also calls `runGenerate` against the
active provider; left unwrapped to stay in scope per spec. Recommend a
tiny follow-up to apply the same wrapper there for inline-comment edits
against bypass-enabled providers.1 parent 209263d commit 6cbb639
21 files changed
Lines changed: 941 additions & 220 deletions
File tree
- .changeset
- apps/desktop
- src
- main
- ipc
- onboarding
- preload
- renderer/src/components
- settings
- packages
- i18n/src/locales
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | | - | |
| 25 | + | |
| 26 | + | |
26 | 27 | | |
27 | 28 | | |
28 | 29 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
8 | 16 | | |
9 | 17 | | |
10 | 18 | | |
| |||
23 | 31 | | |
24 | 32 | | |
25 | 33 | | |
| 34 | + | |
26 | 35 | | |
27 | 36 | | |
28 | 37 | | |
| |||
1386 | 1395 | | |
1387 | 1396 | | |
1388 | 1397 | | |
| 1398 | + | |
| 1399 | + | |
| 1400 | + | |
| 1401 | + | |
| 1402 | + | |
| 1403 | + | |
| 1404 | + | |
| 1405 | + | |
| 1406 | + | |
| 1407 | + | |
| 1408 | + | |
| 1409 | + | |
| 1410 | + | |
| 1411 | + | |
| 1412 | + | |
| 1413 | + | |
| 1414 | + | |
| 1415 | + | |
| 1416 | + | |
| 1417 | + | |
| 1418 | + | |
| 1419 | + | |
| 1420 | + | |
| 1421 | + | |
| 1422 | + | |
| 1423 | + | |
| 1424 | + | |
| 1425 | + | |
| 1426 | + | |
| 1427 | + | |
| 1428 | + | |
| 1429 | + | |
| 1430 | + | |
| 1431 | + | |
| 1432 | + | |
| 1433 | + | |
| 1434 | + | |
| 1435 | + | |
| 1436 | + | |
| 1437 | + | |
| 1438 | + | |
| 1439 | + | |
| 1440 | + | |
| 1441 | + | |
| 1442 | + | |
| 1443 | + | |
| 1444 | + | |
| 1445 | + | |
| 1446 | + | |
| 1447 | + | |
| 1448 | + | |
| 1449 | + | |
| 1450 | + | |
| 1451 | + | |
| 1452 | + | |
| 1453 | + | |
| 1454 | + | |
| 1455 | + | |
| 1456 | + | |
| 1457 | + | |
| 1458 | + | |
| 1459 | + | |
| 1460 | + | |
| 1461 | + | |
| 1462 | + | |
| 1463 | + | |
| 1464 | + | |
| 1465 | + | |
| 1466 | + | |
| 1467 | + | |
| 1468 | + | |
| 1469 | + | |
| 1470 | + | |
| 1471 | + | |
| 1472 | + | |
| 1473 | + | |
| 1474 | + | |
| 1475 | + | |
| 1476 | + | |
| 1477 | + | |
| 1478 | + | |
| 1479 | + | |
| 1480 | + | |
| 1481 | + | |
| 1482 | + | |
| 1483 | + | |
| 1484 | + | |
| 1485 | + | |
| 1486 | + | |
| 1487 | + | |
| 1488 | + | |
| 1489 | + | |
| 1490 | + | |
| 1491 | + | |
| 1492 | + | |
| 1493 | + | |
| 1494 | + | |
| 1495 | + | |
| 1496 | + | |
| 1497 | + | |
| 1498 | + | |
| 1499 | + | |
| 1500 | + | |
| 1501 | + | |
| 1502 | + | |
| 1503 | + | |
| 1504 | + | |
| 1505 | + | |
| 1506 | + | |
| 1507 | + | |
| 1508 | + | |
| 1509 | + | |
| 1510 | + | |
| 1511 | + | |
| 1512 | + | |
| 1513 | + | |
| 1514 | + | |
| 1515 | + | |
| 1516 | + | |
| 1517 | + | |
| 1518 | + | |
| 1519 | + | |
| 1520 | + | |
| 1521 | + | |
| 1522 | + | |
| 1523 | + | |
| 1524 | + | |
| 1525 | + | |
| 1526 | + | |
| 1527 | + | |
| 1528 | + | |
| 1529 | + | |
| 1530 | + | |
| 1531 | + | |
| 1532 | + | |
| 1533 | + | |
| 1534 | + | |
| 1535 | + | |
| 1536 | + | |
| 1537 | + | |
| 1538 | + | |
| 1539 | + | |
| 1540 | + | |
| 1541 | + | |
| 1542 | + | |
| 1543 | + | |
| 1544 | + | |
| 1545 | + | |
| 1546 | + | |
| 1547 | + | |
| 1548 | + | |
| 1549 | + | |
| 1550 | + | |
0 commit comments