@clipboard-health/clearance 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # @clipboard-health/clearance
2
2
 
3
- HTTP/HTTPS clearance for deny-by-default sandboxes.
3
+ A local HTTP/HTTPS forward proxy that gates network egress against a
4
+ hostname allowlist. Built for deny-by-default sandboxes — coding agents,
5
+ CI workers, isolated build steps — where you want one choke point the
6
+ sandbox can permit, with every other route to the network closed.
4
7
 
5
8
  The proxy ships with **zero compiled-in opinions** about which hosts to allow.
6
9
  Bring your own list — either inline via env or by pointing at one or more
@@ -100,8 +103,9 @@ kill "$(cat "${XDG_CACHE_HOME:-$HOME/.cache}/clearance/clearance.pid")"
100
103
 
101
104
  ## Safehouse integration (macOS)
102
105
 
103
- Safehouse uses macOS sandbox profiles, so this section is for macOS hosts
104
- only. Safehouse allows network access by default for agent compatibility.
106
+ [Safehouse](https://agent-safehouse.dev/) uses macOS sandbox profiles, so
107
+ this section is for macOS hosts only. Safehouse allows network access by
108
+ default for agent compatibility.
105
109
  To force a wrapped agent through this proxy, run the proxy outside
106
110
  Safehouse, then append a Safehouse profile that denies direct remote
107
111
  egress while leaving `localhost` open for `http://127.0.0.1:19999`.
@@ -217,3 +221,14 @@ safehouse --env="$HOME/.config/agent-safehouse/clearance.env" \
217
221
  --append-profile="$HOME/.config/agent-safehouse/clearance-only.sb" \
218
222
  -- curl -I https://example.com
219
223
  ```
224
+
225
+ ## Hacking on clearance
226
+
227
+ For developers working on the package itself, the source lives in [`ClipboardHealth/core-utils`](https://github.com/ClipboardHealth/core-utils). After `npm install` in the repo, the bin scripts dispatch through a `runCli` helper that detects no compiled JS and re-execs node with `--conditions @clipboard-health/source`, so the proxy runs straight from TypeScript source — no build step:
228
+
229
+ ```bash
230
+ cd ~/dev/c/core-utils
231
+ CLEARANCE_ALLOW_HOSTS=api.example.com node ./packages/clearance/bin/run.js
232
+ ```
233
+
234
+ Requires Node ≥ 24.3 (native `.ts` type stripping enabled by default).
package/bin/ensure.js CHANGED
@@ -1,3 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import "../src/ensureCli.js";
3
+ import { dirname } from "node:path";
4
+
5
+ import { runCli } from "./runCli.js";
6
+
7
+ await runCli(dirname(import.meta.dirname), "ensureCli");
package/bin/run.js CHANGED
@@ -1,3 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import "../src/cli.js";
3
+ import { dirname } from "node:path";
4
+
5
+ import { runCli } from "./runCli.js";
6
+
7
+ await runCli(dirname(import.meta.dirname), "cli");
package/bin/runCli.js ADDED
@@ -0,0 +1,42 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import { constants as osConstants } from "node:os";
4
+ import { join } from "node:path";
5
+ import { pathToFileURL } from "node:url";
6
+
7
+ /**
8
+ * Load a side-effecting entrypoint by basename. In published/built mode, dynamically
9
+ * imports the compiled `${name}.js` in-process. In source/dev mode (no compiled output
10
+ * present), spawns a child node that loads the `.ts` source with
11
+ * `--conditions @clipboard-health/source` so cross-package bare imports of
12
+ * `@clipboard-health/*` workspace deps also resolve to source.
13
+ *
14
+ * @param {string} packageRoot
15
+ * @param {string} name
16
+ */
17
+ export async function runCli(packageRoot, name) {
18
+ const compiledPath = join(packageRoot, "src", `${name}.js`);
19
+ if (existsSync(compiledPath)) {
20
+ await import(pathToFileURL(compiledPath).href);
21
+ return;
22
+ }
23
+
24
+ const sourcePath = join(packageRoot, "src", `${name}.ts`);
25
+ const result = spawnSync(
26
+ process.execPath,
27
+ ["--conditions", "@clipboard-health/source", sourcePath, ...process.argv.slice(2)],
28
+ { stdio: "inherit" },
29
+ );
30
+
31
+ if (result.error !== undefined) {
32
+ throw result.error;
33
+ }
34
+
35
+ if (result.signal !== null) {
36
+ const signalNumber = osConstants.signals[result.signal];
37
+ process.exitCode = signalNumber === undefined ? 1 : 128 + signalNumber;
38
+ return;
39
+ }
40
+
41
+ process.exitCode = result.status ?? 1;
42
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clipboard-health/clearance",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Localhost HTTP/HTTPS egress proxy with hostname allow-listing, plus a macOS Safehouse integration for sandboxed agent processes.",
5
5
  "keywords": [
6
6
  "agent",
@@ -24,6 +24,15 @@
24
24
  "type": "module",
25
25
  "main": "./src/index.js",
26
26
  "typings": "./src/index.d.ts",
27
+ "exports": {
28
+ "./package.json": "./package.json",
29
+ ".": {
30
+ "@clipboard-health/source": "./src/index.ts",
31
+ "types": "./src/index.d.ts",
32
+ "import": "./src/index.js",
33
+ "default": "./src/index.js"
34
+ }
35
+ },
27
36
  "publishConfig": {
28
37
  "access": "public"
29
38
  },
package/src/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { LookupAddress } from "node:dns";
2
2
  import * as http from "node:http";
3
- export { resolveAllowlist, type ResolveAllowlistInput } from "./allowlist.js";
4
- export { type ClearanceCheckInput, type ClearanceListenerCheck, type ClearanceSpawner, ensureClearance, type EnsureClearanceInput, type EnsureClearanceResult, isClearanceListening, spawnClearance, type SpawnClearanceInput, } from "./launcher.js";
3
+ export { resolveAllowlist, type ResolveAllowlistInput } from "./allowlist.ts";
4
+ export { type ClearanceCheckInput, type ClearanceListenerCheck, type ClearanceSpawner, ensureClearance, type EnsureClearanceInput, type EnsureClearanceResult, isClearanceListening, spawnClearance, type SpawnClearanceInput, } from "./launcher.ts";
5
5
  export declare const CLEARANCE_PACKAGE_NAME = "@clipboard-health/clearance";
6
6
  export interface ClearanceConfig {
7
7
  allowedHosts: readonly string[];