@nebutra/agent-runtime 0.2.2 → 3.0.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 +33 -10
- package/dist/{chunk-KCNN4QUQ.js → chunk-5UGIUYJR.js} +4 -4
- package/dist/chunk-7ELA4SWE.js +73 -0
- package/dist/chunk-7ELA4SWE.js.map +1 -0
- package/dist/chunk-VXILZAXK.js +541 -0
- package/dist/chunk-VXILZAXK.js.map +1 -0
- package/dist/command-exec.d.ts +45 -0
- package/dist/command-exec.js +15 -0
- package/dist/command-exec.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +68 -12
- package/dist/index.js.map +1 -1
- package/dist/pulsar.js +2 -2
- package/dist/sandbox-DfcRttXt.d.ts +219 -0
- package/dist/sandbox.d.ts +2 -64
- package/dist/sandbox.js +25 -3
- package/package.json +8 -7
- package/dist/chunk-R5HOSQUW.js +0 -58
- package/dist/chunk-R5HOSQUW.js.map +0 -1
- /package/dist/{chunk-KCNN4QUQ.js.map → chunk-5UGIUYJR.js.map} +0 -0
package/dist/pulsar.js
CHANGED
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
Pulsar,
|
|
3
3
|
PulsarBuilder,
|
|
4
4
|
PulsarThread
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-5UGIUYJR.js";
|
|
6
6
|
import "./chunk-D4YAPLOW.js";
|
|
7
7
|
import "./chunk-37BBB2P2.js";
|
|
8
|
-
import "./chunk-4Y25ZTKI.js";
|
|
9
8
|
import "./chunk-6EGG2OZC.js";
|
|
10
9
|
import "./chunk-CGRCUKGT.js";
|
|
10
|
+
import "./chunk-4Y25ZTKI.js";
|
|
11
11
|
import "./chunk-424PT5DM.js";
|
|
12
12
|
export {
|
|
13
13
|
Pulsar,
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { CapabilityPolicy } from './policy.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Carina native transport: newline-delimited JSON-RPC 2.0 over a Unix socket
|
|
5
|
+
* (same wire as @carina/sdk and `carina-daemon -socket`).
|
|
6
|
+
*
|
|
7
|
+
* Node-only — not for edge runtimes without `node:net`.
|
|
8
|
+
*/
|
|
9
|
+
declare const defaultCarinaSocketPath: () => string;
|
|
10
|
+
/** Production co-deploy layout on the Sailor ECS api host. */
|
|
11
|
+
declare const CODEPLOY_CARINA_SOCKET_PATH = "/var/carina/run/daemon.sock";
|
|
12
|
+
declare const CODEPLOY_CARINA_WORKSPACE_ROOT = "/var/carina/ws";
|
|
13
|
+
declare const CODEPLOY_CARINA_STATE_DIR = "/var/carina/state";
|
|
14
|
+
declare const CODEPLOY_CARINA_BIN_DIR = "/var/carina/bin";
|
|
15
|
+
declare class CarinaNdjsonError extends Error {
|
|
16
|
+
readonly status: number;
|
|
17
|
+
readonly code?: string | undefined;
|
|
18
|
+
constructor(message: string, status: number, code?: string | undefined);
|
|
19
|
+
}
|
|
20
|
+
type NdjsonRpcClient = {
|
|
21
|
+
call: <T>(method: string, params: Record<string, unknown>) => Promise<T>;
|
|
22
|
+
close: () => void;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Create a reusable NDJSON JSON-RPC client for a Carina unix socket.
|
|
26
|
+
*/
|
|
27
|
+
declare function createCarinaNdjsonClient(socketPath: string, callTimeoutMs?: number): NdjsonRpcClient;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* External-sandbox delegation seam (PORT — capability #11).
|
|
31
|
+
*
|
|
32
|
+
* Governance decision (dual-track, ExternalSandbox posture): this multi-tenant
|
|
33
|
+
* web runtime NEVER executes untrusted code itself and introduces no isolation
|
|
34
|
+
* infrastructure. It only:
|
|
35
|
+
* 1. carries the capability policy (see ./policy),
|
|
36
|
+
* 2. delegates execution to an external isolator behind this interface
|
|
37
|
+
* (Track B = **Carina** upstream kernel),
|
|
38
|
+
* 3. records the outcome as a `command_execution` item (see ./model).
|
|
39
|
+
*
|
|
40
|
+
* The upstream OS enforcers (Seatbelt / Landlock / bubblewrap / Windows
|
|
41
|
+
* restricted token) are deliberately NOT ported — they are single-host and
|
|
42
|
+
* out of scope for a multi-tenant web product.
|
|
43
|
+
*
|
|
44
|
+
* @see docs/architecture/2026-08-03-carina-track-b-upstream.md
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
interface SandboxExecRequest {
|
|
48
|
+
/** Mandatory tenant scope — every delegated exec is tenant-bound. */
|
|
49
|
+
readonly tenantId: string;
|
|
50
|
+
readonly threadId: string;
|
|
51
|
+
readonly command: string;
|
|
52
|
+
/** The capabilities the external isolator must honor. */
|
|
53
|
+
readonly capabilityPolicy: CapabilityPolicy;
|
|
54
|
+
/** Optional inputs the executor should materialize before running. */
|
|
55
|
+
readonly inputs?: Readonly<Record<string, string>>;
|
|
56
|
+
}
|
|
57
|
+
interface SandboxExecResult {
|
|
58
|
+
readonly exitCode: number;
|
|
59
|
+
readonly aggregatedOutput: string;
|
|
60
|
+
/** Identifier of the isolator that actually ran the command. */
|
|
61
|
+
readonly executedOn: string;
|
|
62
|
+
/** Carina permission decision id when present (audit correlation). */
|
|
63
|
+
readonly decisionId?: string;
|
|
64
|
+
/** Host correlation id sent on the wire (JSON-RPC id or extension). */
|
|
65
|
+
readonly correlationId?: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The only thing Track A depends on for execution. Implemented by a decoupled
|
|
69
|
+
* isolator over Carina's public RPC catalog; never implemented in-process here.
|
|
70
|
+
*/
|
|
71
|
+
interface ExternalSandbox {
|
|
72
|
+
exec(request: SandboxExecRequest): Promise<SandboxExecResult>;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Fail-closed default. Wiring this in production requires a real
|
|
76
|
+
* {@link ExternalSandbox}; absent one, untrusted code never runs — by design.
|
|
77
|
+
*/
|
|
78
|
+
declare class NoExecutorConfiguredError extends Error {
|
|
79
|
+
constructor();
|
|
80
|
+
}
|
|
81
|
+
declare const REFUSING_SANDBOX: ExternalSandbox;
|
|
82
|
+
declare class SandboxDelegationError extends Error {
|
|
83
|
+
readonly status: number;
|
|
84
|
+
readonly code?: string | undefined;
|
|
85
|
+
constructor(message: string, status: number, code?: string | undefined);
|
|
86
|
+
}
|
|
87
|
+
declare class CarinaProtocolError extends Error {
|
|
88
|
+
constructor(message: string);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Generic HTTP POST of a Sailor-shaped body. Prefer {@link createCarinaSandbox}
|
|
92
|
+
* for production Track B — Carina owns the kernel and speaks JSON-RPC.
|
|
93
|
+
*/
|
|
94
|
+
declare function createHttpSandbox(baseUrl: string, fetchImpl?: typeof fetch, path?: string): ExternalSandbox;
|
|
95
|
+
/** Minimum `protocol_version` we accept from `gateway.hello` (Carina catalog). */
|
|
96
|
+
declare const CARINA_MIN_PROTOCOL_VERSION = 1;
|
|
97
|
+
type CarinaSandboxOptions = {
|
|
98
|
+
/**
|
|
99
|
+
* HTTP JSON-RPC base URL (optional if {@link socketPath} is set).
|
|
100
|
+
* Prefer unix socket co-deploy on the same host as the gateway.
|
|
101
|
+
*/
|
|
102
|
+
readonly baseUrl?: string;
|
|
103
|
+
/**
|
|
104
|
+
* Native Carina unix socket path (NDJSON JSON-RPC). Preferred for same-host
|
|
105
|
+
* co-deploy — full command.exec authority (TCP diagnostic is read-limited).
|
|
106
|
+
*/
|
|
107
|
+
readonly socketPath?: string;
|
|
108
|
+
/**
|
|
109
|
+
* Gateway token for HTTP transport only. Never a local owner unlock token.
|
|
110
|
+
*/
|
|
111
|
+
readonly token?: string;
|
|
112
|
+
readonly fetchImpl?: typeof fetch;
|
|
113
|
+
/**
|
|
114
|
+
* Path under baseUrl for JSON-RPC POST. Default `""` posts to baseUrl itself.
|
|
115
|
+
*/
|
|
116
|
+
readonly rpcPath?: string;
|
|
117
|
+
/** Fail closed if hello reports a lower protocol_version. Default {@link CARINA_MIN_PROTOCOL_VERSION}. */
|
|
118
|
+
readonly minProtocolVersion?: number;
|
|
119
|
+
/** Skip gateway.hello (tests only). Production should leave this false. */
|
|
120
|
+
readonly skipHello?: boolean;
|
|
121
|
+
/** Label when the wire body has no node id. */
|
|
122
|
+
readonly executedOn?: string;
|
|
123
|
+
/** Map Sailor thread → Carina `session_id`. Default: `threadId`. */
|
|
124
|
+
readonly resolveSessionId?: (request: SandboxExecRequest) => string;
|
|
125
|
+
/**
|
|
126
|
+
* Optional client metadata sent on hello (discovery only — not an auth grant).
|
|
127
|
+
*/
|
|
128
|
+
readonly clientId?: string;
|
|
129
|
+
/**
|
|
130
|
+
* When true, `command.exec` that returns `requires_approval` will call
|
|
131
|
+
* `governance.approval.resolve` (approve=true) once and retry. Default false
|
|
132
|
+
* (fail closed). Operators set via CARINA_AUTO_APPROVE=1 for unattended nodes.
|
|
133
|
+
*/
|
|
134
|
+
readonly autoApproveOnRequire?: boolean;
|
|
135
|
+
};
|
|
136
|
+
type CarinaEnsureSessionRequest = {
|
|
137
|
+
/** Sailor thread id — used as cache key and default correlation. */
|
|
138
|
+
readonly threadId: string;
|
|
139
|
+
/** Absolute workspace path on the Carina host (catalog-required). */
|
|
140
|
+
readonly workspaceRoot: string;
|
|
141
|
+
readonly tenantId?: string;
|
|
142
|
+
readonly profile?: string;
|
|
143
|
+
/** Carina session approval_mode when supported by the daemon. */
|
|
144
|
+
readonly approvalMode?: string;
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Track-B handle: {@link ExternalSandbox} plus host session lifecycle.
|
|
148
|
+
* `command.exec` requires a Carina session; call {@link CarinaSandbox.ensureSession}
|
|
149
|
+
* before the first exec for a thread (or let {@link registerCommandExecTool} do it).
|
|
150
|
+
*/
|
|
151
|
+
type CarinaApprovalResolveRequest = {
|
|
152
|
+
readonly decisionId: string;
|
|
153
|
+
readonly approve: boolean;
|
|
154
|
+
readonly approver?: string;
|
|
155
|
+
readonly scope?: "once" | "session" | "project";
|
|
156
|
+
};
|
|
157
|
+
interface CarinaSandbox extends ExternalSandbox {
|
|
158
|
+
/**
|
|
159
|
+
* Create (or reuse cached) Carina session for a Sailor thread.
|
|
160
|
+
* Maps `threadId` → Carina `session_id` for subsequent `command.exec`.
|
|
161
|
+
*/
|
|
162
|
+
ensureSession(request: CarinaEnsureSessionRequest): Promise<string>;
|
|
163
|
+
/** Peek cached Carina session id for a Sailor thread, if any. */
|
|
164
|
+
resolveMappedSessionId(threadId: string): string | undefined;
|
|
165
|
+
/**
|
|
166
|
+
* Host HITL: map product approve/deny → Carina `governance.approval.resolve`.
|
|
167
|
+
*/
|
|
168
|
+
resolveApproval(request: CarinaApprovalResolveRequest): Promise<unknown>;
|
|
169
|
+
/** Lightweight connectivity probe (`gateway.hello`). */
|
|
170
|
+
probe(): Promise<{
|
|
171
|
+
protocolVersion: number;
|
|
172
|
+
ok: true;
|
|
173
|
+
}>;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Track-B adapter: Sailor control plane → **Carina** public RPC catalog (v0.8.x).
|
|
177
|
+
*
|
|
178
|
+
* Mapping (Sailor → Carina, never the reverse ownership):
|
|
179
|
+
* - `threadId` → `command.exec` `session_id` (via ensureSession cache, else threadId)
|
|
180
|
+
* - `command` → `argv` via `/bin/sh -c` (kernel still gates the joined command string)
|
|
181
|
+
* - denied / requires_approval → {@link SandboxDelegationError} (fail closed)
|
|
182
|
+
* - allowed + CommandResult → {@link SandboxExecResult}
|
|
183
|
+
* - host lifecycle → `session.create` via {@link CarinaSandbox.ensureSession}
|
|
184
|
+
*
|
|
185
|
+
* Kernel protocol is maintained in `Nebutra/carina`. This file only maps.
|
|
186
|
+
*
|
|
187
|
+
* @see docs/architecture/2026-08-03-carina-track-b-upstream.md
|
|
188
|
+
*/
|
|
189
|
+
declare function createCarinaSandbox(options: CarinaSandboxOptions): CarinaSandbox;
|
|
190
|
+
/** Guard: reject the most dangerous posture unless explicitly opted in. */
|
|
191
|
+
declare function assertSafePosture(policy: CapabilityPolicy, allowDanger?: boolean): void;
|
|
192
|
+
/** Env bag for Carina host config. Compatible with `process.env`. */
|
|
193
|
+
type CarinaEnv = Readonly<Record<string, string | undefined>>;
|
|
194
|
+
/**
|
|
195
|
+
* Resolve workspace path for a tenant/thread.
|
|
196
|
+
* Order: CARINA_WORKSPACE_MAP[tenant] → TEMPLATE → CARINA_WORKSPACE_ROOT.
|
|
197
|
+
*/
|
|
198
|
+
declare function resolveCarinaWorkspaceRoot(tenantId: string, env?: CarinaEnv, threadId?: string): string | undefined;
|
|
199
|
+
/**
|
|
200
|
+
* Co-deploy is on unless explicitly disabled (`CARINA_CODEPLOY=0|false`).
|
|
201
|
+
* Same-host default: unix socket {@link CODEPLOY_CARINA_SOCKET_PATH}.
|
|
202
|
+
*/
|
|
203
|
+
declare function isCarinaCodeployEnabled(env?: CarinaEnv): boolean;
|
|
204
|
+
/**
|
|
205
|
+
* Resolve Track-B sandbox from environment.
|
|
206
|
+
*
|
|
207
|
+
* Priority:
|
|
208
|
+
* 1. `CARINA_JSONRPC_URL` → HTTP JSON-RPC
|
|
209
|
+
* 2. `CARINA_DAEMON_SOCK` → unix NDJSON
|
|
210
|
+
* 3. co-deploy default → {@link CODEPLOY_CARINA_SOCKET_PATH}
|
|
211
|
+
* 4. developer home socket → `~/.carina/daemon.sock` when co-deploy and no prod path intent
|
|
212
|
+
* 5. otherwise {@link REFUSING_SANDBOX}
|
|
213
|
+
*/
|
|
214
|
+
declare function resolveCarinaSandboxFromEnv(env?: CarinaEnv, overrides?: Partial<CarinaSandboxOptions>): ExternalSandbox;
|
|
215
|
+
/** Default workspace when co-deploy is enabled and no override is set. */
|
|
216
|
+
declare function resolveCarinaWorkspaceRootWithCodeploy(tenantId: string, env?: CarinaEnv, threadId?: string): string | undefined;
|
|
217
|
+
declare function isCarinaSandbox(sandbox: ExternalSandbox): sandbox is CarinaSandbox;
|
|
218
|
+
|
|
219
|
+
export { CARINA_MIN_PROTOCOL_VERSION as C, type ExternalSandbox as E, type NdjsonRpcClient as N, REFUSING_SANDBOX as R, SandboxDelegationError as S, CODEPLOY_CARINA_BIN_DIR as a, CODEPLOY_CARINA_SOCKET_PATH as b, CODEPLOY_CARINA_STATE_DIR as c, CODEPLOY_CARINA_WORKSPACE_ROOT as d, type CarinaApprovalResolveRequest as e, type CarinaEnsureSessionRequest as f, type CarinaEnv as g, CarinaNdjsonError as h, CarinaProtocolError as i, type CarinaSandbox as j, type CarinaSandboxOptions as k, NoExecutorConfiguredError as l, type SandboxExecRequest as m, type SandboxExecResult as n, assertSafePosture as o, createCarinaNdjsonClient as p, createCarinaSandbox as q, createHttpSandbox as r, defaultCarinaSocketPath as s, isCarinaCodeployEnabled as t, isCarinaSandbox as u, resolveCarinaSandboxFromEnv as v, resolveCarinaWorkspaceRoot as w, resolveCarinaWorkspaceRootWithCodeploy as x };
|
package/dist/sandbox.d.ts
CHANGED
|
@@ -1,65 +1,3 @@
|
|
|
1
|
-
import
|
|
1
|
+
import './policy.js';
|
|
2
|
+
export { C as CARINA_MIN_PROTOCOL_VERSION, b as CODEPLOY_CARINA_SOCKET_PATH, d as CODEPLOY_CARINA_WORKSPACE_ROOT, e as CarinaApprovalResolveRequest, f as CarinaEnsureSessionRequest, g as CarinaEnv, i as CarinaProtocolError, j as CarinaSandbox, k as CarinaSandboxOptions, E as ExternalSandbox, l as NoExecutorConfiguredError, R as REFUSING_SANDBOX, S as SandboxDelegationError, m as SandboxExecRequest, n as SandboxExecResult, o as assertSafePosture, q as createCarinaSandbox, r as createHttpSandbox, s as defaultCarinaSocketPath, t as isCarinaCodeployEnabled, u as isCarinaSandbox, v as resolveCarinaSandboxFromEnv, w as resolveCarinaWorkspaceRoot, x as resolveCarinaWorkspaceRootWithCodeploy } from './sandbox-DfcRttXt.js';
|
|
2
3
|
import 'zod';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* External-sandbox delegation seam (PORT — capability #11).
|
|
6
|
-
*
|
|
7
|
-
* Governance decision (dual-track, ExternalSandbox posture): this multi-tenant
|
|
8
|
-
* web runtime NEVER executes untrusted code itself and introduces no isolation
|
|
9
|
-
* infrastructure. It only:
|
|
10
|
-
* 1. carries the capability policy (see ./policy),
|
|
11
|
-
* 2. delegates execution to an external isolator behind this interface
|
|
12
|
-
* (a self-hosted kernel sidecar — Track B — or any other executor),
|
|
13
|
-
* 3. records the outcome as a `command_execution` item (see ./model).
|
|
14
|
-
*
|
|
15
|
-
* The upstream OS enforcers (Seatbelt / Landlock / bubblewrap / Windows
|
|
16
|
-
* restricted token) are deliberately NOT ported — they are single-host and
|
|
17
|
-
* out of scope for a multi-tenant web product.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
interface SandboxExecRequest {
|
|
21
|
-
/** Mandatory tenant scope — every delegated exec is tenant-bound. */
|
|
22
|
-
readonly tenantId: string;
|
|
23
|
-
readonly threadId: string;
|
|
24
|
-
readonly command: string;
|
|
25
|
-
/** The capabilities the external isolator must honor. */
|
|
26
|
-
readonly capabilityPolicy: CapabilityPolicy;
|
|
27
|
-
/** Optional inputs the executor should materialize before running. */
|
|
28
|
-
readonly inputs?: Readonly<Record<string, string>>;
|
|
29
|
-
}
|
|
30
|
-
interface SandboxExecResult {
|
|
31
|
-
readonly exitCode: number;
|
|
32
|
-
readonly aggregatedOutput: string;
|
|
33
|
-
/** Identifier of the isolator that actually ran the command. */
|
|
34
|
-
readonly executedOn: string;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* The only thing Track A depends on for execution. Implemented by a decoupled
|
|
38
|
-
* isolator over the ./protocol contract; never implemented in-process here.
|
|
39
|
-
*/
|
|
40
|
-
interface ExternalSandbox {
|
|
41
|
-
exec(request: SandboxExecRequest): Promise<SandboxExecResult>;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Fail-closed default. Wiring this in production requires a real
|
|
45
|
-
* {@link ExternalSandbox}; absent one, untrusted code never runs — by design.
|
|
46
|
-
*/
|
|
47
|
-
declare class NoExecutorConfiguredError extends Error {
|
|
48
|
-
constructor();
|
|
49
|
-
}
|
|
50
|
-
declare const REFUSING_SANDBOX: ExternalSandbox;
|
|
51
|
-
declare class SandboxDelegationError extends Error {
|
|
52
|
-
readonly status: number;
|
|
53
|
-
constructor(message: string, status: number);
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* The concrete Track-B coupling: delegate execution over HTTP to the decoupled
|
|
57
|
-
* Rust isolator (`backends/rust/sandbox`, `POST /api/v1/sandbox/exec`). The
|
|
58
|
-
* isolator is fail-closed; a non-2xx (e.g. 403 refusal) is surfaced as an
|
|
59
|
-
* error and never coerced into a fabricated result.
|
|
60
|
-
*/
|
|
61
|
-
declare function createHttpSandbox(baseUrl: string, fetchImpl?: typeof fetch): ExternalSandbox;
|
|
62
|
-
/** Guard: reject the most dangerous posture unless explicitly opted in. */
|
|
63
|
-
declare function assertSafePosture(policy: CapabilityPolicy, allowDanger?: boolean): void;
|
|
64
|
-
|
|
65
|
-
export { type ExternalSandbox, NoExecutorConfiguredError, REFUSING_SANDBOX, SandboxDelegationError, type SandboxExecRequest, type SandboxExecResult, assertSafePosture, createHttpSandbox };
|
package/dist/sandbox.js
CHANGED
|
@@ -1,16 +1,38 @@
|
|
|
1
1
|
import {
|
|
2
|
+
CARINA_MIN_PROTOCOL_VERSION,
|
|
3
|
+
CODEPLOY_CARINA_SOCKET_PATH,
|
|
4
|
+
CODEPLOY_CARINA_WORKSPACE_ROOT,
|
|
5
|
+
CarinaProtocolError,
|
|
2
6
|
NoExecutorConfiguredError,
|
|
3
7
|
REFUSING_SANDBOX,
|
|
4
8
|
SandboxDelegationError,
|
|
5
9
|
assertSafePosture,
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
createCarinaSandbox,
|
|
11
|
+
createHttpSandbox,
|
|
12
|
+
defaultCarinaSocketPath,
|
|
13
|
+
isCarinaCodeployEnabled,
|
|
14
|
+
isCarinaSandbox,
|
|
15
|
+
resolveCarinaSandboxFromEnv,
|
|
16
|
+
resolveCarinaWorkspaceRoot,
|
|
17
|
+
resolveCarinaWorkspaceRootWithCodeploy
|
|
18
|
+
} from "./chunk-VXILZAXK.js";
|
|
8
19
|
import "./chunk-424PT5DM.js";
|
|
9
20
|
export {
|
|
21
|
+
CARINA_MIN_PROTOCOL_VERSION,
|
|
22
|
+
CODEPLOY_CARINA_SOCKET_PATH,
|
|
23
|
+
CODEPLOY_CARINA_WORKSPACE_ROOT,
|
|
24
|
+
CarinaProtocolError,
|
|
10
25
|
NoExecutorConfiguredError,
|
|
11
26
|
REFUSING_SANDBOX,
|
|
12
27
|
SandboxDelegationError,
|
|
13
28
|
assertSafePosture,
|
|
14
|
-
|
|
29
|
+
createCarinaSandbox,
|
|
30
|
+
createHttpSandbox,
|
|
31
|
+
defaultCarinaSocketPath,
|
|
32
|
+
isCarinaCodeployEnabled,
|
|
33
|
+
isCarinaSandbox,
|
|
34
|
+
resolveCarinaSandboxFromEnv,
|
|
35
|
+
resolveCarinaWorkspaceRoot,
|
|
36
|
+
resolveCarinaWorkspaceRootWithCodeploy
|
|
15
37
|
};
|
|
16
38
|
//# sourceMappingURL=sandbox.js.map
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nebutra/agent-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"nebutra": {
|
|
8
|
+
"graph": "runtime",
|
|
8
9
|
"status": "wip",
|
|
9
10
|
"productionReady": false,
|
|
10
11
|
"requires": [
|
|
@@ -94,12 +95,12 @@
|
|
|
94
95
|
"dependencies": {
|
|
95
96
|
"p-limit": "^7.3.0",
|
|
96
97
|
"zod": "^4.3.6",
|
|
97
|
-
"@nebutra/agents": "
|
|
98
|
-
"@nebutra/ai-primitives": "0.1.
|
|
99
|
-
"@nebutra/
|
|
100
|
-
"@nebutra/
|
|
101
|
-
"@nebutra/
|
|
102
|
-
"@nebutra/
|
|
98
|
+
"@nebutra/agents": "3.0.0",
|
|
99
|
+
"@nebutra/ai-primitives": "0.1.3",
|
|
100
|
+
"@nebutra/capability-kit": "3.0.0",
|
|
101
|
+
"@nebutra/execution-policy": "3.0.0",
|
|
102
|
+
"@nebutra/graph-model": "3.0.0",
|
|
103
|
+
"@nebutra/mcp": "3.0.0"
|
|
103
104
|
},
|
|
104
105
|
"devDependencies": {
|
|
105
106
|
"@types/node": "^25.9.1",
|
package/dist/chunk-R5HOSQUW.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
// src/sandbox.ts
|
|
2
|
-
var NoExecutorConfiguredError = class extends Error {
|
|
3
|
-
constructor() {
|
|
4
|
-
super(
|
|
5
|
-
"No ExternalSandbox configured. This runtime never executes untrusted code in-process; delegate to a decoupled isolator (Track B)."
|
|
6
|
-
);
|
|
7
|
-
this.name = "NoExecutorConfiguredError";
|
|
8
|
-
}
|
|
9
|
-
};
|
|
10
|
-
var REFUSING_SANDBOX = {
|
|
11
|
-
async exec() {
|
|
12
|
-
throw new NoExecutorConfiguredError();
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
var SandboxDelegationError = class extends Error {
|
|
16
|
-
constructor(message, status) {
|
|
17
|
-
super(message);
|
|
18
|
-
this.status = status;
|
|
19
|
-
this.name = "SandboxDelegationError";
|
|
20
|
-
}
|
|
21
|
-
status;
|
|
22
|
-
};
|
|
23
|
-
function createHttpSandbox(baseUrl, fetchImpl = fetch) {
|
|
24
|
-
const endpoint = `${baseUrl.replace(/\/$/, "")}/api/v1/sandbox/exec`;
|
|
25
|
-
return {
|
|
26
|
-
async exec(request) {
|
|
27
|
-
const response = await fetchImpl(endpoint, {
|
|
28
|
-
method: "POST",
|
|
29
|
-
headers: { "content-type": "application/json" },
|
|
30
|
-
body: JSON.stringify(request)
|
|
31
|
-
});
|
|
32
|
-
if (!response.ok) {
|
|
33
|
-
const detail = await response.text().catch(() => "");
|
|
34
|
-
throw new SandboxDelegationError(
|
|
35
|
-
`Isolator refused execution (${response.status}): ${detail}`,
|
|
36
|
-
response.status
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
return await response.json();
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
function assertSafePosture(policy, allowDanger = false) {
|
|
44
|
-
if (policy.kind === "danger_full_access" && !allowDanger) {
|
|
45
|
-
throw new Error(
|
|
46
|
-
"danger_full_access capability policy refused: not permitted for multi-tenant delegation without explicit opt-in."
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export {
|
|
52
|
-
NoExecutorConfiguredError,
|
|
53
|
-
REFUSING_SANDBOX,
|
|
54
|
-
SandboxDelegationError,
|
|
55
|
-
createHttpSandbox,
|
|
56
|
-
assertSafePosture
|
|
57
|
-
};
|
|
58
|
-
//# sourceMappingURL=chunk-R5HOSQUW.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/sandbox.ts"],"sourcesContent":["/**\n * External-sandbox delegation seam (PORT — capability #11).\n *\n * Governance decision (dual-track, ExternalSandbox posture): this multi-tenant\n * web runtime NEVER executes untrusted code itself and introduces no isolation\n * infrastructure. It only:\n * 1. carries the capability policy (see ./policy),\n * 2. delegates execution to an external isolator behind this interface\n * (a self-hosted kernel sidecar — Track B — or any other executor),\n * 3. records the outcome as a `command_execution` item (see ./model).\n *\n * The upstream OS enforcers (Seatbelt / Landlock / bubblewrap / Windows\n * restricted token) are deliberately NOT ported — they are single-host and\n * out of scope for a multi-tenant web product.\n */\n\nimport type { CapabilityPolicy } from \"./policy\";\n\nexport interface SandboxExecRequest {\n /** Mandatory tenant scope — every delegated exec is tenant-bound. */\n readonly tenantId: string;\n readonly threadId: string;\n readonly command: string;\n /** The capabilities the external isolator must honor. */\n readonly capabilityPolicy: CapabilityPolicy;\n /** Optional inputs the executor should materialize before running. */\n readonly inputs?: Readonly<Record<string, string>>;\n}\n\nexport interface SandboxExecResult {\n readonly exitCode: number;\n readonly aggregatedOutput: string;\n /** Identifier of the isolator that actually ran the command. */\n readonly executedOn: string;\n}\n\n/**\n * The only thing Track A depends on for execution. Implemented by a decoupled\n * isolator over the ./protocol contract; never implemented in-process here.\n */\nexport interface ExternalSandbox {\n exec(request: SandboxExecRequest): Promise<SandboxExecResult>;\n}\n\n/**\n * Fail-closed default. Wiring this in production requires a real\n * {@link ExternalSandbox}; absent one, untrusted code never runs — by design.\n */\nexport class NoExecutorConfiguredError extends Error {\n constructor() {\n super(\n \"No ExternalSandbox configured. This runtime never executes untrusted \" +\n \"code in-process; delegate to a decoupled isolator (Track B).\",\n );\n this.name = \"NoExecutorConfiguredError\";\n }\n}\n\nexport const REFUSING_SANDBOX: ExternalSandbox = {\n async exec(): Promise<SandboxExecResult> {\n throw new NoExecutorConfiguredError();\n },\n};\n\nexport class SandboxDelegationError extends Error {\n constructor(\n message: string,\n readonly status: number,\n ) {\n super(message);\n this.name = \"SandboxDelegationError\";\n }\n}\n\n/**\n * The concrete Track-B coupling: delegate execution over HTTP to the decoupled\n * Rust isolator (`backends/rust/sandbox`, `POST /api/v1/sandbox/exec`). The\n * isolator is fail-closed; a non-2xx (e.g. 403 refusal) is surfaced as an\n * error and never coerced into a fabricated result.\n */\nexport function createHttpSandbox(\n baseUrl: string,\n fetchImpl: typeof fetch = fetch,\n): ExternalSandbox {\n const endpoint = `${baseUrl.replace(/\\/$/, \"\")}/api/v1/sandbox/exec`;\n return {\n async exec(request: SandboxExecRequest): Promise<SandboxExecResult> {\n const response = await fetchImpl(endpoint, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(request),\n });\n if (!response.ok) {\n const detail = await response.text().catch(() => \"\");\n throw new SandboxDelegationError(\n `Isolator refused execution (${response.status}): ${detail}`,\n response.status,\n );\n }\n return (await response.json()) as SandboxExecResult;\n },\n };\n}\n\n/** Guard: reject the most dangerous posture unless explicitly opted in. */\nexport function assertSafePosture(policy: CapabilityPolicy, allowDanger = false): void {\n if (policy.kind === \"danger_full_access\" && !allowDanger) {\n throw new Error(\n \"danger_full_access capability policy refused: not permitted for \" +\n \"multi-tenant delegation without explicit opt-in.\",\n );\n }\n}\n"],"mappings":";AAgDO,IAAM,4BAAN,cAAwC,MAAM;AAAA,EACnD,cAAc;AACZ;AAAA,MACE;AAAA,IAEF;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,mBAAoC;AAAA,EAC/C,MAAM,OAAmC;AACvC,UAAM,IAAI,0BAA0B;AAAA,EACtC;AACF;AAEO,IAAM,yBAAN,cAAqC,MAAM;AAAA,EAChD,YACE,SACS,QACT;AACA,UAAM,OAAO;AAFJ;AAGT,SAAK,OAAO;AAAA,EACd;AAAA,EAJW;AAKb;AAQO,SAAS,kBACd,SACA,YAA0B,OACT;AACjB,QAAM,WAAW,GAAG,QAAQ,QAAQ,OAAO,EAAE,CAAC;AAC9C,SAAO;AAAA,IACL,MAAM,KAAK,SAAyD;AAClE,YAAM,WAAW,MAAM,UAAU,UAAU;AAAA,QACzC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,MAC9B,CAAC;AACD,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,SAAS,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AACnD,cAAM,IAAI;AAAA,UACR,+BAA+B,SAAS,MAAM,MAAM,MAAM;AAAA,UAC1D,SAAS;AAAA,QACX;AAAA,MACF;AACA,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B;AAAA,EACF;AACF;AAGO,SAAS,kBAAkB,QAA0B,cAAc,OAAa;AACrF,MAAI,OAAO,SAAS,wBAAwB,CAAC,aAAa;AACxD,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACF;","names":[]}
|
|
File without changes
|