ffp-sql-sandbox 0.1.0 → 0.1.1

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/INTEGRATION.md CHANGED
@@ -1,37 +1,37 @@
1
- # Integrating ffp-sql-sandbox with ChuTingzj/ai-bi
1
+ # Integrating ffp-sql-sandbox
2
2
 
3
- This repository does **not** wire the library into [ChuTingzj/ai-bi](https://github.com/ChuTingzj/ai-bi). Keep that as a follow-up PR in ai-bi after this package is a real dependency, tests are green, and there are no P0s.
3
+ This repository ships **library primitives only**. It does not embed a product UI, Nest module, or connection catalog. Wire `validateSql` / `executeSql` in the host application after this package is a real dependency, tests are green, and there are no P0s.
4
4
 
5
5
  ## Adapter shape
6
6
 
7
- Keep NestJS, `CryptoService`, and `DataSource` inside ai-bi. Do not leak those types into this library.
7
+ Keep framework DI, secret decryption, and ORM / data-source types in the host app. Do not leak those types into this library.
8
8
 
9
- Suggested adapter (ai-bi `SandboxService`):
9
+ Suggested host adapter:
10
10
 
11
- 1. Decrypt `dataSource.password` with the existing `CryptoService`.
11
+ 1. Decrypt the database password with the host app’s secret store.
12
12
  2. Call `validateSql` / `executeSql` from `ffp-sql-sandbox`.
13
- 3. Map `{ ok: true, data }` → the current `SandboxResult` / `QueryResult` shape (`success` / `columns`+`rows`).
13
+ 3. Map `{ ok: true, data }` → the host app’s query-result shape (`success` / `columns`+`rows`).
14
14
  4. Map `{ ok: false, code, error }` → `{ success: false, error }`.
15
15
 
16
- ## Host rewrite stays in ai-bi
16
+ ## Host rewrite stays in the caller
17
17
 
18
18
  `resolveSandboxDbHost` is **not** a public export of this package (on purpose).
19
19
 
20
- ai-bi may keep its private loopback → `host.docker.internal` helper for its own tests and Docker-on-Linux setups. If the adapter rewrites the host *before* calling `executeSql`, put the rewritten name on `hostAllowlist` as well.
20
+ The host app may keep a private loopback → `host.docker.internal` helper for its own tests and Docker-on-Linux setups. If the adapter rewrites the host *before* calling `executeSql`, put the rewritten name on `hostAllowlist` as well.
21
21
 
22
22
  Alternatively, pass the original host (`localhost`, `db.internal`, …) in `connection.host`, allowlist **that** name, and let this library apply a private rewrite after the allowlist check. Either way, user-controlled hosts must not bypass `hostAllowlist`.
23
23
 
24
- ## What not to copy from the old sandbox
24
+ ## What not to copy from a naive Docker sandbox
25
25
 
26
- | Old ai-bi behavior | v1 library |
26
+ | Naive sandbox | v1 library |
27
27
  | --- | --- |
28
- | `DB_PASS` / password in container `Env` | Forbidden. Password goes to tmpfs `/run/secrets/db_password`. |
28
+ | Password in container `Env` (`DB_PASS`, `PGPASSWORD`, …) | Forbidden. Password goes to tmpfs `/run/secrets/db_password`. |
29
29
  | `Cmd: [sql]` | SQL on stdin JSON. |
30
- | Floating `SANDBOX_IMAGE=ai-bi-sandbox:latest` | Default image digest-pinned; custom `image` is untrusted. |
30
+ | Floating image tag (`:latest`) | Default image digest-pinned; custom `image` is untrusted. |
31
31
  | Configurable validator prefixes/patterns | Not exposed. `validateSql(sql)` only. |
32
32
  | Wait for container + `logs()` then parse/truncate | Streaming attach; `maxRows` / `maxBytes` applied as data arrives. |
33
33
  | Regex as the security proof | Documented as fail-fast only. Proof is RO role + limits + allowlist. |
34
34
 
35
35
  ## Image
36
36
 
37
- Build `sandbox/Dockerfile` from this repo (or pull the published digest) and configure ai-bi to use `DEFAULT_SANDBOX_IMAGE` or an explicit digest-pinned ref. Do not default to `:latest`.
37
+ Build `sandbox/Dockerfile` from this repo (or pull the published digest) and configure the host app to use `DEFAULT_SANDBOX_IMAGE` or an explicit digest-pinned ref. Do not default to `:latest`.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Read-only SQL sandbox primitives for Node.js: fail-fast `validateSql` plus one-shot Docker `executeSql` with hard resource, row, byte, timeout, and host-allowlist limits.
4
4
 
5
- This is the v1 library extracted from the sandbox ideas in [ChuTingzj/ai-bi](https://github.com/ChuTingzj/ai-bi) (`validateSql` + dockerode one-shot container) and redesigned around a stricter security model. It is **not** wired into ai-bi in this repository see [INTEGRATION.md](./INTEGRATION.md).
5
+ This is an FFP Tech Lab library: first-principles, read-only SQL sandbox primitives (`validateSql` plus a one-shot Docker runner) with a strict security model. It is a standalone package — host-app wiring lives in the caller; see [INTEGRATION.md](./INTEGRATION.md).
6
6
 
7
7
  ## Install
8
8
 
@@ -12,12 +12,19 @@ pnpm add ffp-sql-sandbox
12
12
 
13
13
  Docker is a **hard dependency** of `executeSql`. If the engine cannot be pinged, the call fails with `DOCKER_UNAVAILABLE` rather than falling back to in-process SQL.
14
14
 
15
- Build the runner image from `sandbox/Dockerfile` (digest-pinned `FROM`) and either publish it at the default ref below or pass `image` (untrusted override).
15
+ The default runner is published on GHCR and digest-pinned in `DEFAULT_SANDBOX_IMAGE`. Pull it (or build `sandbox/Dockerfile` locally and pass `image`, which is an untrusted override):
16
16
 
17
17
  ```bash
18
+ docker pull ghcr.io/ffp-tech-lab/ffp-sql-sandbox-runner@sha256:13cc50f33c2d00a9ae464f3742c49a18a6b2750fdc39c23d68022476c79171a9
19
+ # tags :v1 and :0.1.0 point at the same image
20
+ docker pull ghcr.io/ffp-tech-lab/ffp-sql-sandbox-runner:v1
21
+
22
+ # local build (untrusted override — pin and review if you use this)
18
23
  docker build -t ghcr.io/ffp-tech-lab/ffp-sql-sandbox-runner:v1 ./sandbox
19
24
  ```
20
25
 
26
+ If anonymous `docker pull` returns unauthorized, the GHCR package is still private — see [GHCR package visibility](#ghcr-package-visibility).
27
+
21
28
  ## Public API
22
29
 
23
30
  ```ts
@@ -51,7 +58,7 @@ executeSql(input: {
51
58
 
52
59
  `validateSql` is fail-fast only. There are no `allowPrefixes` / `forbidPatterns` options.
53
60
 
54
- `resolveSandboxDbHost` is **not** exported. Loopback rewrite for container DNS, if needed, stays private (and, for ai-bi, in the adapter — see INTEGRATION.md).
61
+ `resolveSandboxDbHost` is **not** exported. Loopback rewrite for container DNS, if needed, stays private (and in the host adapter — see INTEGRATION.md).
55
62
 
56
63
  ## Non-goals
57
64
 
@@ -83,7 +90,17 @@ Passwords are written to a **tmpfs** file at `/run/secrets/db_password` inside t
83
90
 
84
91
  The Dockerfile `FROM` line is also digest-pinned (`node:22-bookworm-slim@sha256:83f487e0a63425e5b4d146fb5e5be574bcbe1b7b843d3ebafdd95eaf7767a7e5`).
85
92
 
86
- Until GHCR publish, `DEFAULT_SANDBOX_IMAGE` is a **content digest** of the v1 runner files, not a registry-pullable image. `executeSql` without `image` will return `IMAGE_UNAVAILABLE` if that digest is not present locally. Build `sandbox/Dockerfile` and pass `image` (untrusted override), or `docker load` / retag the digest-pinned image. After the first registry push, replace the constant with `docker buildx imagetools inspect` output.
93
+ `DEFAULT_SANDBOX_IMAGE` is a **GHCR-pullable** digest of `ghcr.io/ffp-tech-lab/ffp-sql-sandbox-runner` (also tagged `:v1` and `:0.1.0`). `executeSql` without `image` uses that pin and returns `IMAGE_UNAVAILABLE` only if Docker cannot pull or find it (offline daemon, missing credentials while the package is private, etc.). Rebuilds of `sandbox/Dockerfile` are published by `.github/workflows/publish-runner.yml`; after a runner change, update this pin from the workflow job summary or `docker buildx imagetools inspect`.
94
+
95
+ ### GHCR package visibility
96
+
97
+ New organization packages on `ghcr.io` default to **private**. Anonymous `docker pull` of `ghcr.io/ffp-tech-lab/ffp-sql-sandbox-runner` needs the package to be **public** (this cannot be undone):
98
+
99
+ 1. Open the package: [github.com/orgs/FFP-Tech-Lab/packages](https://github.com/orgs/FFP-Tech-Lab/packages) (or the package page linked from this repository’s **Packages** sidebar).
100
+ 2. **Package settings** → **Danger Zone** → **Change visibility** → **Public**.
101
+ 3. Org owners can allow public package *creation* under **Organization settings → Packages → Package creation**.
102
+
103
+ `.github/workflows/ghcr-visibility.yml` attempts the same change via the GitHub API after publish. If that job warns, use the UI steps above.
87
104
 
88
105
  ## Default limits
89
106
 
@@ -127,7 +144,7 @@ Until GHCR publish, `DEFAULT_SANDBOX_IMAGE` is a **content digest** of the v1 ru
127
144
  | `TIMEOUT` | `executeSql` |
128
145
  | `INVALID_LIMITS` | `executeSql` |
129
146
  | `IMAGE_UNPINNED` | `executeSql` (default image missing digest) |
130
- | `IMAGE_UNAVAILABLE` | `executeSql` (image missing locally / not pullable; default digest is unpublished until GHCR) |
147
+ | `IMAGE_UNAVAILABLE` | `executeSql` (image missing locally / not pullable from GHCR) |
131
148
  | `UNSUPPORTED_DIALECT` | `executeSql` |
132
149
  | `EXECUTION_FAILED` | `executeSql` |
133
150
 
@@ -139,6 +156,35 @@ pnpm typecheck
139
156
  pnpm build
140
157
  ```
141
158
 
159
+ ## Release
160
+
161
+ Library (npm) and runner image (GHCR) are published by **separate** workflows. Do not mix them in one job.
162
+
163
+ ### npm (`ffp-sql-sandbox`)
164
+
165
+ Workflow: [`.github/workflows/publish-npm.yml`](./.github/workflows/publish-npm.yml).
166
+
167
+ **Triggers (conventional):** push of a version tag `v*` (for example `v0.1.1`). Also `workflow_dispatch`, and when a GitHub Release is published (so a Release created from that tag still publishes if the tag-push job was skipped). If `package.json`’s version is already on the registry, the job **skips** instead of force-republishing.
168
+
169
+ 1. Bump `version` in `package.json` (keep it in sync with the git tag; `0.1.1` is the current pin of the GHCR runner digest).
170
+ 2. Add repo secret **`NPM_TOKEN`**: **Settings → Secrets and variables → Actions → New repository secret**. Use an npm [granular access token](https://docs.npmjs.com/creating-and-viewing-access-tokens) with permission to **publish** `ffp-sql-sandbox` and **bypass 2FA**. The workflow maps it to `NODE_AUTH_TOKEN` / `.npmrc`; do not commit a token.
171
+ 3. Merge the version bump to `main`, then either:
172
+ - **Usual path:** `git tag v0.1.1 && git push origin v0.1.1`
173
+ - **Actions tab:** run **Publish npm** (`workflow_dispatch`) on the intended ref
174
+ - **GitHub Release:** publish a release for tag `vX.Y.Z`
175
+ 4. The job runs `pnpm install`, `pnpm test`, `pnpm build`, then `pnpm publish --access public`. A tag that does not match `package.json` version fails.
176
+
177
+ `ffp-sql-sandbox@0.1.1` is not on the registry until this workflow succeeds with `NPM_TOKEN` set.
178
+
179
+ ### GHCR runner image
180
+
181
+ Workflow: [`.github/workflows/publish-runner.yml`](./.github/workflows/publish-runner.yml) (image only; not npm).
182
+
183
+ - Push to `main` that touches `sandbox/**` or that workflow file, or run **Publish runner image** (`workflow_dispatch`).
184
+ - Pushes `ghcr.io/ffp-tech-lab/ffp-sql-sandbox-runner:v1` and `:0.1.0`, and prints the digest in the job summary.
185
+ - After a runner change, update `DEFAULT_SANDBOX_IMAGE` to that `sha256:…` pin.
186
+ - Anonymous `docker pull` needs the package **public** — see [GHCR package visibility](#ghcr-package-visibility).
187
+
142
188
  ## License
143
189
 
144
- MIT. The GitHub repository may stay private until the org publishes it; that does not change the source license.
190
+ MIT.
@@ -185,7 +185,7 @@ function isImageUnavailableError(err) {
185
185
  }
186
186
  function imageUnavailableMessage(request) {
187
187
  if (request.usingDefaultImage) {
188
- return `Default sandbox image is not pullable (${request.image}). Until GHCR publish, build sandbox/Dockerfile locally and pass image: '<tag-or-id>' (untrusted override), or docker load/tag the digest-pinned image.`;
188
+ return `Default sandbox image is not pullable (${request.image}). Pull ghcr.io/ffp-tech-lab/ffp-sql-sandbox-runner@sha256:<digest> (or :v1), or build sandbox/Dockerfile locally and pass image: '<tag-or-id>' (untrusted override). If docker pull is unauthorized, the GHCR package may still be private.`;
189
189
  }
190
190
  return `Sandbox image not found: ${request.image}. Build or pull it before calling executeSql.`;
191
191
  }
@@ -1 +1 @@
1
- {"version":3,"file":"docker-executor.js","sourceRoot":"","sources":["../src/docker-executor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"docker-executor.js","sourceRoot":"","sources":["../src/docker-executor.ts"],"names":[],"mappings":"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"}
package/dist/image.d.ts CHANGED
@@ -1,16 +1,11 @@
1
1
  /**
2
2
  * Default runner image. Digest-pinned in code; do not use a floating tag.
3
3
  *
4
- * This pin is the v1 identity of `sandbox/Dockerfile`. It is **not** a
5
- * GHCR-pullable digest until the runner is published. `executeSql` without
6
- * `image` returns `IMAGE_UNAVAILABLE` if Docker cannot find it. After the
7
- * first GHCR publish, replace this with `docker buildx imagetools inspect`.
8
- * Custom `image` overrides are untrusted.
9
- *
10
- * Content identity (sha256 of the runner files at this freeze):
11
- * sandbox/Dockerfile + execute.js + stream-limit.js + session-setup.js +
12
- * secrets.js + events.js + package.json.
4
+ * Published to GHCR as `ghcr.io/ffp-tech-lab/ffp-sql-sandbox-runner`
5
+ * (`:v1`, `:0.1.0`, and this digest). `executeSql` without `image` returns
6
+ * `IMAGE_UNAVAILABLE` if Docker cannot pull or find it. Custom `image`
7
+ * overrides are untrusted.
13
8
  */
14
- export declare const DEFAULT_SANDBOX_IMAGE = "ghcr.io/ffp-tech-lab/ffp-sql-sandbox-runner@sha256:861dd5eb53f5c3eb468b73b6068385f0688910fc10ba68610d20bb3de9f78952";
9
+ export declare const DEFAULT_SANDBOX_IMAGE = "ghcr.io/ffp-tech-lab/ffp-sql-sandbox-runner@sha256:13cc50f33c2d00a9ae464f3742c49a18a6b2750fdc39c23d68022476c79171a9";
15
10
  export declare function isDigestPinnedImage(image: string): boolean;
16
11
  //# sourceMappingURL=image.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,qBAAqB,wHACqF,CAAC;AAExH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE1D"}
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,wHACqF,CAAC;AAExH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE1D"}
package/dist/image.js CHANGED
@@ -2,17 +2,12 @@ const DIGEST_PINNED = /^.+@sha256:[a-f0-9]{64}$/i;
2
2
  /**
3
3
  * Default runner image. Digest-pinned in code; do not use a floating tag.
4
4
  *
5
- * This pin is the v1 identity of `sandbox/Dockerfile`. It is **not** a
6
- * GHCR-pullable digest until the runner is published. `executeSql` without
7
- * `image` returns `IMAGE_UNAVAILABLE` if Docker cannot find it. After the
8
- * first GHCR publish, replace this with `docker buildx imagetools inspect`.
9
- * Custom `image` overrides are untrusted.
10
- *
11
- * Content identity (sha256 of the runner files at this freeze):
12
- * sandbox/Dockerfile + execute.js + stream-limit.js + session-setup.js +
13
- * secrets.js + events.js + package.json.
5
+ * Published to GHCR as `ghcr.io/ffp-tech-lab/ffp-sql-sandbox-runner`
6
+ * (`:v1`, `:0.1.0`, and this digest). `executeSql` without `image` returns
7
+ * `IMAGE_UNAVAILABLE` if Docker cannot pull or find it. Custom `image`
8
+ * overrides are untrusted.
14
9
  */
15
- export const DEFAULT_SANDBOX_IMAGE = 'ghcr.io/ffp-tech-lab/ffp-sql-sandbox-runner@sha256:861dd5eb53f5c3eb468b73b6068385f0688910fc10ba68610d20bb3de9f78952';
10
+ export const DEFAULT_SANDBOX_IMAGE = 'ghcr.io/ffp-tech-lab/ffp-sql-sandbox-runner@sha256:13cc50f33c2d00a9ae464f3742c49a18a6b2750fdc39c23d68022476c79171a9';
16
11
  export function isDigestPinnedImage(image) {
17
12
  return DIGEST_PINNED.test(image.trim());
18
13
  }
package/dist/image.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"image.js","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AAAA,MAAM,aAAa,GAAG,2BAA2B,CAAC;AAElD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAChC,qHAAqH,CAAC;AAExH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,OAAO,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;AAC1C,CAAC"}
1
+ {"version":3,"file":"image.js","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AAAA,MAAM,aAAa,GAAG,2BAA2B,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAChC,qHAAqH,CAAC;AAExH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,OAAO,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;AAC1C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ffp-sql-sandbox",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Read-only SQL sandbox primitives: fail-fast validateSql + Docker executeSql with hard limits",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -22,16 +22,13 @@
22
22
  "engines": {
23
23
  "node": ">=20"
24
24
  },
25
- "packageManager": "pnpm@10.33.3",
26
25
  "repository": {
27
26
  "type": "git",
28
27
  "url": "git+https://github.com/FFP-Tech-Lab/ffp-sql-sandbox.git"
29
28
  },
30
- "scripts": {
31
- "build": "tsc -p tsconfig.build.json",
32
- "typecheck": "tsc -p tsconfig.json --noEmit",
33
- "test": "tsx --test test/**/*.test.ts",
34
- "prepack": "pnpm build"
29
+ "publishConfig": {
30
+ "access": "public",
31
+ "registry": "https://registry.npmjs.org/"
35
32
  },
36
33
  "dependencies": {
37
34
  "dockerode": "^4.0.7"
@@ -41,5 +38,10 @@
41
38
  "@types/node": "^22.18.0",
42
39
  "tsx": "^4.20.5",
43
40
  "typescript": "^5.9.2"
41
+ },
42
+ "scripts": {
43
+ "build": "tsc -p tsconfig.build.json",
44
+ "typecheck": "tsc -p tsconfig.json --noEmit",
45
+ "test": "tsx --test test/**/*.test.ts"
44
46
  }
45
- }
47
+ }