@superhq/shuru 0.1.2 → 0.2.0

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
@@ -42,6 +42,10 @@ const sb = await Sandbox.start({
42
42
  allowNet: true,
43
43
  ports: ["8080:80"],
44
44
  mounts: { "./src": "/workspace" },
45
+ secrets: {
46
+ API_KEY: { from: "OPENAI_API_KEY", hosts: ["api.openai.com"] },
47
+ },
48
+ network: { allow: ["api.openai.com", "registry.npmjs.org"] },
45
49
  });
46
50
  ```
47
51
 
@@ -54,6 +58,8 @@ const sb = await Sandbox.start({
54
58
  | `allowNet` | `boolean` | Enable network access |
55
59
  | `ports` | `string[]` | Port forwards (`"host:guest"`) |
56
60
  | `mounts` | `Record<string, string>` | Directory mounts (`{ hostPath: guestPath }`) |
61
+ | `secrets` | `Record<string, SecretConfig>` | Secrets to inject via proxy (see below) |
62
+ | `network` | `NetworkConfig` | Network access policy (see below) |
57
63
  | `shuruBin` | `string` | Path to shuru binary (default: `"shuru"`) |
58
64
 
59
65
  ## API
@@ -82,6 +88,34 @@ Save the VM's disk state and stop the VM. To continue working, call `Sandbox.sta
82
88
 
83
89
  Stop the VM without saving. All changes are discarded.
84
90
 
91
+ ### Secrets
92
+
93
+ Secrets keep API keys on the host. The guest receives a random placeholder token; the proxy substitutes the real value only on HTTPS requests to the specified hosts.
94
+
95
+ ```ts
96
+ const sb = await Sandbox.start({
97
+ allowNet: true,
98
+ secrets: {
99
+ API_KEY: { from: "OPENAI_API_KEY", hosts: ["api.openai.com"] },
100
+ },
101
+ });
102
+ // Inside the VM, $API_KEY is a placeholder token.
103
+ // Requests to api.openai.com get the real key injected by the proxy.
104
+ ```
105
+
106
+ ### Network policy
107
+
108
+ Restrict which domains the guest can reach:
109
+
110
+ ```ts
111
+ const sb = await Sandbox.start({
112
+ allowNet: true,
113
+ network: { allow: ["api.openai.com", "*.npmjs.org"] },
114
+ });
115
+ ```
116
+
117
+ Omit `network.allow` to allow all domains.
118
+
85
119
  ## Requirements
86
120
 
87
121
  - macOS 14+ on Apple Silicon
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superhq/shuru",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
package/src/index.ts CHANGED
@@ -1,2 +1,7 @@
1
1
  export { Sandbox } from "./sandbox";
2
- export type { ExecResult, StartOptions } from "./types";
2
+ export type {
3
+ ExecResult,
4
+ NetworkConfig,
5
+ SecretConfig,
6
+ StartOptions,
7
+ } from "./types";
package/src/sandbox.ts CHANGED
@@ -76,6 +76,18 @@ export function buildArgs(bin: string, opts: StartOptions): string[] {
76
76
  if (opts.diskSize) args.push("--disk-size", String(opts.diskSize));
77
77
  if (opts.allowNet) args.push("--allow-net");
78
78
 
79
+ if (opts.secrets) {
80
+ for (const [name, secret] of Object.entries(opts.secrets)) {
81
+ args.push("--secret", `${name}=${secret.from}@${secret.hosts.join(",")}`);
82
+ }
83
+ }
84
+
85
+ if (opts.network?.allow) {
86
+ for (const host of opts.network.allow) {
87
+ args.push("--allow-host", host);
88
+ }
89
+ }
90
+
79
91
  if (opts.ports) {
80
92
  for (const p of opts.ports) {
81
93
  args.push("-p", p);
package/src/types.ts CHANGED
@@ -1,3 +1,15 @@
1
+ export interface SecretConfig {
2
+ /** Host environment variable containing the real value. */
3
+ from: string;
4
+ /** Domains where this secret may be sent (e.g. "api.openai.com"). */
5
+ hosts: string[];
6
+ }
7
+
8
+ export interface NetworkConfig {
9
+ /** Allowed domain patterns. Omit to allow all. */
10
+ allow?: string[];
11
+ }
12
+
1
13
  export interface StartOptions {
2
14
  from?: string;
3
15
  cpus?: number;
@@ -6,6 +18,8 @@ export interface StartOptions {
6
18
  allowNet?: boolean;
7
19
  ports?: string[];
8
20
  mounts?: Record<string, string>;
21
+ secrets?: Record<string, SecretConfig>;
22
+ network?: NetworkConfig;
9
23
  shuruBin?: string;
10
24
  }
11
25