ask-sandbox-providers 0.1.2 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc353cb8a3cc934284dea7ddbe8b57631404a3a88ab99fe577343c519fc23c57
4
- data.tar.gz: 53319ce423b19e3a6c85d30f09a4caf526d2ce6c9a3c6198cfea24a8f1eb3c96
3
+ metadata.gz: bb95b1b00d2c4ed3bb7e3e9a98f77d9035b8c3cc5e990b47870e3edec87f4ea8
4
+ data.tar.gz: 64781ff4c3f4e8020d759cdef227a05b9f4a21f0b36a6bbb6776aca8849310f5
5
5
  SHA512:
6
- metadata.gz: 9aca24be7433a28b77993c1f42631345c492c52231e3f11c5a0308a69e692dfaacdc67e1059bf5f4a5fb74ea330e9a583e9a12893f10c66c4be6ebd505818fda
7
- data.tar.gz: 3e66b07e821f458ab19592aac2246cca303a3a26e5fa7e4244b419e64bb3b45270a5d9f8b960a3cbc6be57f8edf4037ab7c3bbfb9cbc0187f4e4e7bb5df6c9c1
6
+ metadata.gz: a14deb3e21c8ae4f73b65fd20d5f5eb6176ea871f6184fc18ecf826285ea1c150fa2f22fdf3a03d33e4602f817c7401f1e2da976a1b0fee6e451d880a39e5278
7
+ data.tar.gz: 3a1480416aa824fc853bdb6da60d278cad5699c6e8571d3d0bcd2bd5626f07a24b3664f884f7c7ac9166eaede264bfb954b2a8e1839a93bd9a566d819e9de9aa
data/README.md CHANGED
@@ -2,14 +2,7 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/ask-sandbox-providers.svg)](https://badge.fury.io/rb/ask-sandbox-providers)
4
4
 
5
- Sandbox providers for the ask-rb ecosystem. Isolated code execution via four backends:
6
-
7
- | Provider | Isolation | Speed | Requirement |
8
- |---|---|---|---|
9
- | `Local` | Process + rlimits (CPU, memory, processes, file size) | Instant | None (stdlib) |
10
- | `Docker` | Full container (read-only rootfs, no network, no capabilities) | ~1s | Docker daemon |
11
- | `Daytona` | Remote container via Daytona API | ~2-5s | `daytona` gem, API key |
12
- | `Cloudflare` | Cloudflare Workers sandbox via proxy Worker | ~1-3s | Proxy Worker URL |
5
+ Sandbox providers for the ask-rb ecosystem: isolated code execution with a single interface and four backends. The default Local provider needs nothing; Docker, Daytona, and Cloudflare add stronger or remote isolation.
13
6
 
14
7
  ## Installation
15
8
 
@@ -22,106 +15,42 @@ gem "ask-sandbox-providers"
22
15
  ```ruby
23
16
  require "ask-sandbox-providers"
24
17
 
25
- # Default: Local (subprocess + rlimits on macOS/Linux)
26
- result = Ask::Sandbox.provider.call(["ruby", "-e", "puts 1+1"])
27
- puts result.stdout # => "1\n"
28
- puts result.exit_code # => 0
29
- puts result.timed_out # => false
18
+ result = Ask::Sandbox.provider.call(["ruby", "-e", "puts 1 + 1"])
19
+ result.stdout # => "1\n"
20
+ result.exit_code # => 0
21
+ result.success? # => true
30
22
  ```
31
23
 
32
- ### Configure a different provider
33
-
34
- ```ruby
35
- # Docker (requires Docker daemon)
36
- Ask::Sandbox.provider = Ask::Sandbox::Docker.new(
37
- image: "ruby:3.4-alpine",
38
- memory: "256m",
39
- network: false
40
- )
41
-
42
- # Daytona (requires `daytona` gem + API key)
43
- Ask::Sandbox.provider = Ask::Sandbox::Daytona.new(
44
- api_key: Ask::Auth.lookup("DAYTONA_API_KEY"),
45
- server_url: "https://api.daytona.io"
46
- )
47
-
48
- # Cloudflare (requires a deployed proxy Worker)
49
- Ask::Sandbox.provider = Ask::Sandbox::Cloudflare.new(
50
- worker_url: "https://sandbox-proxy.my-worker.workers.dev",
51
- auth_token: ENV["CLOUDFLARE_SANDBOX_TOKEN"]
52
- )
53
- ```
24
+ Commands can be an Array (executed directly, no shell) or a String (executed via `bash -c`). All providers accept `call(command, timeout: 30, workdir: nil, env: {}, stdin: nil)`.
54
25
 
55
- ### String vs Array commands
26
+ ## Choosing a provider
56
27
 
57
28
  ```ruby
58
- # String executed via shell (bash -c)
59
- Ask::Sandbox.provider.call("ls -la | head -5")
29
+ Ask::Sandbox.provider = :docker # symbol shortcuts: :local, :docker, :daytona, :cloudflare
60
30
 
61
- # Array executed directly, no shell (safer for untrusted input)
62
- Ask::Sandbox.provider.call(["ruby", "-e", "puts ENV['HOME']"])
31
+ Ask::Sandbox.provider = Ask::Sandbox::Docker.new(image: "ruby:3.4-alpine", memory: "256m", network: false)
63
32
  ```
64
33
 
65
- ### Return value
66
-
67
- All providers return an `Ask::Sandbox::Result`:
68
-
69
- ```ruby
70
- Result = Data.define(:stdout, :stderr, :exit_code, :timed_out)
71
- ```
72
-
73
- ## Provider Details
74
-
75
- ### Local
76
-
77
- The default provider. Runs commands in a temp directory with:
34
+ | Provider | Isolation | Requirement |
35
+ |---|---|---|
36
+ | `Ask::Sandbox::Local` (default) | Subprocess with rlimits (CPU, memory, processes, file size), temp directory, sanitized environment | None, stdlib only |
37
+ | `Ask::Sandbox::Docker` | Container with read-only rootfs, no capabilities, no network | Docker daemon |
38
+ | `Ask::Sandbox::Daytona` | Remote sandbox via the Daytona API | `daytona` gem, API key |
39
+ | `Ask::Sandbox::Cloudflare` | Cloudflare Workers sandbox via a proxy Worker | Deployed proxy Worker URL |
78
40
 
79
- - **Process group isolation** all child processes are killed on timeout
80
- - **`Process.setrlimit`** — CPU (10s), address space (2GB), processes (50), file size (10MB), FDs (200)
81
- - **Temp directory** — execution sandbox is auto-cleaned
82
- - **Environment sanitization** — Bundler/Ruby env vars stripped
41
+ Daytona resolves its API key from `Ask::Auth.lookup("DAYTONA_API_KEY")` or `ENV["DAYTONA_API_KEY"]` when `api_key:` is not given. Cloudflare falls back to the `CLOUDFLARE_SANDBOX_WORKER_URL` and `CLOUDFLARE_SANDBOX_AUTH_TOKEN` env vars.
83
42
 
84
- Available on every platform where Ruby runs (macOS, Linux). Zero external dependencies.
43
+ ## Result
85
44
 
86
- ### Docker
45
+ Every provider returns `Ask::Sandbox::Result`, a `Data` object with `stdout`, `stderr`, `exit_code`, and `timed_out` fields, plus `#success?` (true when `exit_code == 0`).
87
46
 
88
- Runs commands in a Docker container with security hardening:
47
+ ## Full documentation
89
48
 
90
- - `--read-only` read-only root filesystem
91
- - `--cap-drop ALL` — no Linux capabilities
92
- - `--security-opt no-new-privileges` — no privilege escalation
93
- - `--network none` — no network egress (configurable)
94
- - `--memory`, `--cpus`, `--pids-limit` — resource limits
95
- - `--rm` — auto-cleanup on exit
96
-
97
- ### Daytona
98
-
99
- Runs commands in a Daytona sandbox via the official `daytona` gem. Daytona provides secure, elastic sandboxes with full isolation, dedicated kernel, filesystem, and network stack. See [daytona.io/docs](https://www.daytona.io/docs).
100
-
101
- ### Cloudflare
102
-
103
- Runs commands in a Cloudflare Workers sandbox. Requires deploying a proxy Worker that wraps `@cloudflare/sandbox`. See the [Cloudflare Sandbox SDK docs](https://developers.cloudflare.com/sandbox/) for setup.
104
-
105
- ## Migration from Direct Open3 Usage
106
-
107
- If you're upgrading from `ask-tools-shell` v0.1.0 where `Code` and `Bash` tools called
108
- `Open3.popen3` directly — no action needed. The default `Ask::Sandbox::Local` provider
109
- behaves identically. To enable stronger isolation, switch the provider:
110
-
111
- ```ruby
112
- # Before: direct Open3 (implicit Local)
113
- Ask::Tools::Code.new.call(code: "puts 1")
114
-
115
- # After: configure Docker for stronger isolation
116
- Ask::Sandbox.provider = Ask::Sandbox::Docker.new
117
- # The Code tool now runs code inside a Docker container automatically
118
- ```
49
+ The full ask-rb documentation lives at https://ask-rb.github.io/ask-docs. [ask-sandbox-providers in depth](https://ask-rb.github.io/ask-docs/core/sandbox) covers each provider and the hardening details. API reference: https://ask-rb.github.io/ask-docs/reference/api.
119
50
 
120
51
  ## Development
121
52
 
122
- ```bash
123
- git clone https://github.com/ask-rb/ask-sandbox-providers.git
124
- cd ask-sandbox-providers
53
+ ```
125
54
  bundle install
126
55
  bundle exec rake test
127
56
  ```
@@ -17,7 +17,11 @@ module Ask
17
17
 
18
18
  RLIMITS = {
19
19
  rlimit_cpu: [10, 30],
20
- rlimit_nproc: [200, 200],
20
+ # nproc limits the *user's* total process count, not the sandbox's.
21
+ # 200 is easily exceeded on a busy dev machine, which makes every
22
+ # fork in the sandboxed command fail with EAGAIN. 1024 still guards
23
+ # against fork bombs without breaking normal use.
24
+ rlimit_nproc: [1024, 1024],
21
25
  rlimit_fsize: [10_485_760, 10_485_760],
22
26
  rlimit_nofile: [200, 200],
23
27
  rlimit_as: [2_147_483_648, 2_147_483_648]
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ask
4
4
  module Sandbox
5
- VERSION = "0.1.2"
5
+ VERSION = "0.1.3"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ask-sandbox-providers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kaka Ruto