Skip to content

Commit cf05221

Browse files
docs: fix Desktop IDE setup notes (CORS + discoverability)
Align AGENTS.md, SELF_HOST_GUIDE, and root README with desktop/README.md: keep loopback CORS wildcards when setting a public origin, link Desktop install, and document Node 22 / tunnel prerequisites. Match SecurityConfig @value fallback to application.properties port wildcards. Co-authored-by: Venkat SF <venkatesh.sakamuri@stayflexi.com>
1 parent 6e74e3e commit cf05221

6 files changed

Lines changed: 55 additions & 17 deletions

File tree

AGENTS.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,14 @@ or an in-process SSH local forward (`ssh2`, no `ssh` binary needed).
127127
| `desktop/src/main/windows/workspace.js` | Frameless shell: native chrome + embedded DeepSQL view |
128128
| `desktop/src/renderer/shared/theme.css` | Mirrors `src/index.css` tokens — keep in step |
129129

130-
No backend change was needed: `docker/nginx/default.conf` already serves the SPA,
131-
`/api` and `/agent-api` from one origin, which is what makes the thin-client
132-
model work without CORS or cookie special-casing.
130+
`docker/nginx/default.conf` already serves the SPA, `/api`, and `/agent-api` from
131+
one origin, so cookies and SSE behave like a normal browser. **CORS is the one
132+
backend setting the thin client still needs:** an SSH tunnel uses origin
133+
`http://127.0.0.1:<sticky-port>`, so `CORS_ALLOWED_ORIGINS` on the VM must keep
134+
the loopback port wildcards (`http://127.0.0.1:*,http://localhost:*`) alongside
135+
any public hostname. Overriding that env var *replaces* the built-in list — a
136+
public-origin-only value breaks Desktop tunnel login with a confusing 403.
137+
Setup and diagnosis: [`desktop/README.md`](desktop/README.md#cors-on-the-vm-the-403-nobody-can-read).
133138

134139
## Performance & Safety Guardrails
135140

@@ -308,10 +313,15 @@ only covers cloud-specific, non-obvious caveats.
308313
`deepsql agent --connection <uuid> "…"`. Interactive: `deepsql` / `deepsql agent`.
309314
The CLI is a thin client over `POST /api/agent/chat` (not a local agent runtime);
310315
backend + agent API (:8787) + provisioner must already be up.
311-
- **Spring CORS must allow both loopback hosts.** Set
312-
`CORS_ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:3000` in `.env`. Opening
313-
the UI as `http://127.0.0.1:3000` while only `localhost` is allowlisted yields **403**
314-
on `POST /api/agent/session` (and other cookie-auth APIs).
316+
- **Spring CORS must allow loopback (and Desktop tunnel ports).** Prefer
317+
`CORS_ALLOWED_ORIGINS=http://localhost:3000,http://127.0.0.1:*,http://localhost:*`
318+
in `.env` (match `.env.example`). Fixed `:3000` alone is enough for Vite on that
319+
port; the `*` port wildcards are required for DeepSQL Desktop’s SSH tunnel, which
320+
binds a sticky random local port. Opening the UI as `http://127.0.0.1:…` while
321+
only `localhost` (or only a public hostname) is allowlisted yields **403** on
322+
`POST /api/agent/session` (and other cookie-auth APIs). Electron GUI itself is
323+
out of scope for headless Cloud Agents — use Vite + these CORS patterns here;
324+
see [`desktop/README.md`](desktop/README.md) when developing the client.
315325
- **Before running backend tests that boot the Spring context** (e.g. `ApiSmokeTest`), stop
316326
the running backend first — both use `ddl-auto=update` on the same `dba_agent` DB and can
317327
deadlock on an `ALTER TABLE`. Test env vars are documented in `CLAUDE.md` (Testing).

CLAUDE.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ project** — `cd desktop && npm install`, not part of the root `package.json`.
129129

130130
```bash
131131
cd desktop
132-
npm start # run npm run dev # run with DevTools
132+
npm start # run
133+
npm run dev # run with DevTools
133134
npm test # drift guard for the DevTools kill switch
134135
npm run dist:mac # dmg + zip (arm64 + x64), also :win / :linux
135136
npm run smoke -- --url https://deepsql.example.com # headless connection check

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,22 @@ your schema — all from one shared brain.
241241
- **Postgres and MySQL, in your infra.** One dialect registry, read-only execution, and SSH
242242
tunnelling to reach databases behind a bastion.
243243

244+
### DeepSQL Desktop (optional)
245+
246+
A thin Electron client for a self-hosted VM — direct TLS or an in-process SSH tunnel —
247+
without bundling a second copy of the web UI. Separate npm project:
248+
249+
```bash
250+
cd desktop
251+
npm install
252+
npm start
253+
```
254+
255+
Requires **Node 22+**. Forward the tunnel to the **frontend container (port 3000)**, not a
256+
host reverse proxy on `:80`. Keep loopback CORS wildcards on the VM
257+
(`http://127.0.0.1:*,http://localhost:*`) or tunnel login fails with a confusing 403 — see
258+
[`desktop/README.md`](desktop/README.md).
259+
244260
---
245261

246262
## Operating the stack

backend/src/main/java/com/dbaagent/config/SecurityConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public class SecurityConfig {
5252
* only {@code application*.properties} — could not see it, and it ships to every reader
5353
* of the public repository. {@code CorsAllowlistSafetyTest} now scans this file too.
5454
*/
55-
@Value("${cors.allowed.origins:http://localhost:3000,http://localhost:3001,http://localhost:3002,http://127.0.0.1:3000,http://127.0.0.1:3001,http://127.0.0.1:3002}")
55+
@Value("${cors.allowed.origins:http://localhost:3000,http://localhost:3001,http://localhost:3002,http://127.0.0.1:3000,http://127.0.0.1:3001,http://127.0.0.1:3002,http://127.0.0.1:*,http://localhost:*}")
5656
private String corsAllowedOrigins;
5757

5858
@Bean

desktop/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ launch needs **right-click → Open** (or `xattr -dr com.apple.quarantine
5757

5858
### From source
5959

60+
**Requires Node.js 22+** (matches the Desktop release CI). GUI needs a display; on
61+
headless Linux use `xvfb-run` for the packaged app or the selftests.
62+
6063
```bash
6164
cd desktop
6265
npm install
@@ -336,6 +339,7 @@ scripts/
336339
generate-icons.js SVG → build/icon.png via Electron
337340
smoke.js headless connection check
338341
tunnel-selftest.js end-to-end SSH tunnel test
342+
settings-selftest.js proves an edited setting reaches the live connection
339343
```
340344

341345
The renderers are plain HTML/CSS/JS with no build step: they are chrome around

docs/root/SELF_HOST_GUIDE.md

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -426,17 +426,22 @@ serve from.
426426
| `DEEPSQL_BACKEND_PORT` | 8080 | [`docker-compose.yml:94`](../../docker-compose.yml) |
427427
| `DEEPSQL_POSTGRES_PORT` | 5432 (published as `127.0.0.1:…` only) | [`docker-compose.yml`](../../docker-compose.yml) |
428428
| `DEEPSQL_VALKEY_PORT` | 6379 (published as `127.0.0.1:…` only) | [`docker-compose.yml`](../../docker-compose.yml) |
429-
| `CORS_ALLOWED_ORIGINS` | `http://localhost:3000` | `application.properties:87`[`SecurityConfig.java`](../../backend/src/main/java/com/dbaagent/config/SecurityConfig.java) |
429+
| `CORS_ALLOWED_ORIGINS` | loopback hosts + port wildcards (see `.env.example`) | `application.properties`[`SecurityConfig.java`](../../backend/src/main/java/com/dbaagent/config/SecurityConfig.java) |
430430

431431
```env
432432
DEEPSQL_FRONTEND_PORT=13000
433-
CORS_ALLOWED_ORIGINS=http://localhost:13000
433+
# Port wildcards keep DeepSQL Desktop SSH-tunnel origins working (sticky local port).
434+
CORS_ALLOWED_ORIGINS=http://localhost:13000,http://127.0.0.1:*,http://localhost:*
434435
```
435436

436-
Behind a reverse proxy, `CORS_ALLOWED_ORIGINS` must list the **public** origin
437-
(`https://deepsql.your-company.example`), not the container port. Consider binding
438-
postgres and valkey to `127.0.0.1` on a public host, or dropping their `ports:` entries
439-
entirely — nothing outside the Compose network needs them.
437+
`CORS_ALLOWED_ORIGINS` **replaces** the built-in allowlist rather than extending it.
438+
Behind a reverse proxy, list the **public** origin
439+
(`https://deepsql.your-company.example`) **and** keep
440+
`http://127.0.0.1:*,http://localhost:*` if anyone will use [DeepSQL Desktop](../../desktop/README.md)
441+
(SSH tunnel → `http://127.0.0.1:<port>`). A public-origin-only value makes tunnel
442+
login fail with `403 Invalid CORS request` while GETs still look healthy. Consider
443+
binding postgres and valkey to `127.0.0.1` on a public host, or dropping their
444+
`ports:` entries entirely — nothing outside the Compose network needs them.
440445

441446
### Optional integrations
442447

@@ -482,7 +487,8 @@ Once TLS is in place, three settings must follow or authentication behaves oddly
482487

483488
```env
484489
SECURITY_COOKIE_SECURE=true
485-
CORS_ALLOWED_ORIGINS=https://deepsql.your-company.example
490+
# Public origin for browsers + loopback wildcards for DeepSQL Desktop tunnels.
491+
CORS_ALLOWED_ORIGINS=https://deepsql.your-company.example,http://127.0.0.1:*,http://localhost:*
486492
APP_BASE_URL=https://deepsql.your-company.example
487493
APP_PUBLIC_URL=https://deepsql.your-company.example
488494
```
@@ -803,7 +809,7 @@ Agent-specific (in addition to the core stack):
803809
- [ ] `ENCRYPTION_KEY` backed up somewhere other than where the database dumps live
804810
- [ ] TLS terminated in front of the frontend, with `SECURITY_COOKIE_SECURE=true`
805811
- [ ] `APP_BASE_URL` and `APP_PUBLIC_URL` set to the public URL, and the startup log line checked
806-
- [ ] `CORS_ALLOWED_ORIGINS` set to the public origin only
812+
- [ ] `CORS_ALLOWED_ORIGINS` includes the public origin **and** `http://127.0.0.1:*,http://localhost:*` (Desktop tunnel / local loopback)
807813
- [ ] `EMBEDDING_FAIL_OPEN=false` (the `prod` default) so retrieval failures surface
808814
- [ ] Postgres and valkey not published to a public interface
809815
- [ ] `.env` never committed — it is gitignored, keep it that way
@@ -816,6 +822,7 @@ Agent-specific (in addition to the core stack):
816822

817823
- [`README.md`](../../README.md) — overview, quick start, LLM configuration, development
818824
- [`.env.example`](../../.env.example) — inline documentation for every shipped variable
825+
- [`desktop/README.md`](../../desktop/README.md) — DeepSQL Desktop (Electron) install, SSH tunnel, and CORS requirements
819826
- [`mcp/README.md`](../../mcp/README.md) — the `deepsql` CLI and MCP server, including client configuration for Claude Desktop and Codex
820827
- [`docs/root/MCP_PHASE1.md`](./MCP_PHASE1.md) — MCP tools and environment variables
821828
- [`docs/LOGGING-GUIDE.md`](../LOGGING-GUIDE.md) — log format

0 commit comments

Comments
 (0)