From 2662e36647ed96a547095b9875c647e3e3253801 Mon Sep 17 00:00:00 2001 From: eitsupi Date: Wed, 1 Jul 2026 00:43:53 +0000 Subject: [PATCH 1/2] docs(server): document Windows -A requirement for named pipes, add --tcp fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Windows named-pipe binding falls into Deno's check_has_all_permissions, which only -A (--allow-all) can satisfy — no scoped flag combination works. Unify start/dev tasks to -A (matching test/test:e2e) since deno.json tasks can't branch by OS, and document the same requirement plus a scoped --tcp workaround in the README quick-start instructions. --- README.md | 19 ++++++++++++++++++- server/deno.json | 28 +++++++++++++--------------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 1e46bff..6ee572b 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,11 @@ First [install Deno](https://docs.deno.com/runtime/getting_started/installation/ then run directly (dependencies are fetched automatically): ```bash -deno run https://raw.githubusercontent.com/grantmcdermott/jgd/refs/heads/main/server/main.ts +# macOS / Linux +deno run --allow-net --allow-read --allow-write --allow-env https://raw.githubusercontent.com/grantmcdermott/jgd/refs/heads/main/server/main.ts + +# Windows +deno run -A https://raw.githubusercontent.com/grantmcdermott/jgd/refs/heads/main/server/main.ts ``` Or, clone the repo and run locally: @@ -109,6 +113,19 @@ Or, clone the repo and run locally: cd server && deno task start && cd .. ``` +> [!NOTE] +> On **Windows**, R connections default to a named pipe, and Deno has no +> permission combination narrower than `-A` (`--allow-all`) that can satisfy +> binding one — that's why the Windows command above needs it (`deno task +> start` above already grants `-A` for the same reason). +> +> To keep permissions scoped on Windows instead, add `--tcp ` (e.g. +> `--tcp 8888`) to connect over localhost TCP rather than a named pipe: +> +> ```bash +> deno run --allow-net --allow-read --allow-write --allow-env https://raw.githubusercontent.com/grantmcdermott/jgd/refs/heads/main/server/main.ts --tcp 8888 +> ``` + Once the Deno server is running, open `http://127.0.0.1:/` in your browser (the URL is printed on startup). Then you start executing plotting commands from any R session. diff --git a/server/deno.json b/server/deno.json index 9e763af..272564c 100644 --- a/server/deno.json +++ b/server/deno.json @@ -8,24 +8,22 @@ "@astral/astral": "jsr:@astral/astral@^0.5" }, "tasks": { - // --allow-net is unrestricted (not scoped to 127.0.0.1): since Deno - // PR denoland/deno#34395, Deno.listen/connect({transport:"unix"}) also - // requires an --allow-net=unix: grant, in addition to - // --allow-read/--allow-write, to bind/connect the R unix socket. The - // socket path is randomly generated at runtime when --socket isn't - // passed explicitly, so it can't be allow-listed up front; unscoped - // --allow-net is the documented escape hatch for that case. - "start": "deno run --allow-net --allow-read --allow-write --allow-env main.ts", - "dev": "deno run --allow-net --allow-read --allow-write --allow-env --watch main.ts", - // -A is required here (not just --allow-net/read/write/env): on Windows, - // node:net's PipeWrap.bind/listen/connect (used for named pipes) routes + // -A (--allow-all) is required on Windows: R connections default to a + // named pipe there, and node:net's PipeWrap.bind/listen/connect routes // any non-drive-letter path like \\.\pipe\... through Deno's permission // checker's check_special_file, which demands every permission category // (read/write/net/env/sys/run/ffi/import) be fully granted -- i.e. -A - // itself, with no narrower combination accepted. These tasks exercise - // that code path directly (in-process pipe tests) or indirectly (via - // TestServer spawning main.ts), so they need -A on Windows; -A here for - // all platforms keeps the task portable without OS-specific branching. + // itself, with no narrower combination accepted. Separately, on + // Linux/macOS, Deno.listen({transport:"unix"}) requires an unscoped + // --allow-net (since denoland/deno#34395) because the R socket path is + // randomly generated at runtime and can't be allow-listed up front. + // -A satisfies both without OS-specific branching (deno.json tasks + // can't conditionally vary flags by platform). Passing --tcp to + // these tasks avoids named pipes/unix sockets entirely and only needs + // --allow-net --allow-read --allow-write --allow-env, if narrower + // permissions are preferred over -A. + "start": "deno run -A main.ts", + "dev": "deno run -A --watch main.ts", "test": "deno test -A --parallel --ignore=tests/e2e tests/", "test:e2e": "deno test -A tests/e2e/", "test:all": "deno task test && deno task test:e2e" From 1dcc342567c69e486df7b2b733563325e815bdaf Mon Sep 17 00:00:00 2001 From: eitsupi Date: Wed, 1 Jul 2026 00:46:36 +0000 Subject: [PATCH 2/2] docs(server): fix inaccurate --tcp scoping claim in deno.json comment start/dev hardcode -A, so passing --tcp through the task doesn't narrow permissions as the previous wording implied. Clarify that scoped --tcp usage requires invoking deno run directly, per the README. --- server/deno.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/server/deno.json b/server/deno.json index 272564c..c4af711 100644 --- a/server/deno.json +++ b/server/deno.json @@ -18,10 +18,11 @@ // --allow-net (since denoland/deno#34395) because the R socket path is // randomly generated at runtime and can't be allow-listed up front. // -A satisfies both without OS-specific branching (deno.json tasks - // can't conditionally vary flags by platform). Passing --tcp to - // these tasks avoids named pipes/unix sockets entirely and only needs - // --allow-net --allow-read --allow-write --allow-env, if narrower - // permissions are preferred over -A. + // can't conditionally vary flags by platform). -A is hardcoded into + // these tasks, so passing --tcp here does NOT narrow permissions + // (deno task start -- --tcp 8888 still runs with -A). To actually get + // scoped permissions with --tcp, invoke `deno run` directly instead of + // this task -- see the README's Deno-server quick-start section. "start": "deno run -A main.ts", "dev": "deno run -A --watch main.ts", "test": "deno test -A --parallel --ignore=tests/e2e tests/",