Skip to content

Commit 5ede2c4

Browse files
committed
chore: console log -> stdio
1 parent 38e8ccd commit 5ede2c4

24 files changed

Lines changed: 249 additions & 84 deletions

File tree

CLAUDE.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
## Node Architecture
1717

18-
- read `docs-internal/arch/overview.md` for the component map (NodeProcess, SandboxDriver, NodeDriver, NodeExecutionDriver, ModuleAccessFileSystem, Permissions)
18+
- read `docs-internal/arch/overview.md` for the component map (NodeRuntime, RuntimeDriver, NodeDriver, NodeExecutionDriver, ModuleAccessFileSystem, Permissions)
1919
- keep it up to date when adding, removing, or significantly changing components
2020

2121
## Specs Source of Truth
@@ -26,6 +26,7 @@
2626
- use `openspec/specs/README.md` for how to reference baseline capabilities in new change proposals
2727
- track development friction in `docs-internal/friction.md` (mark resolved items with fix notes)
2828
- OpenSpec proposals/design/tasks MUST explicitly list the concrete tests to add or update for the change
29+
- when a request is scoped as `opsx` (propose/plan/apply/archive), always use OpenSpec workflow end-to-end (`opsx propose` -> `opsx apply`) before implementation; do not apply code changes outside an active OpenSpec change
2930

3031
## Compatibility Project-Matrix Policy
3132

docs-internal/friction.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
3. **[resolved]** Default console capture buffered unbounded host memory.
1414
- Symptom: runtime execution accumulated console output in host-managed `stdout`/`stderr` arrays by default, enabling memory amplification under high-volume logs.
15-
- Fix: runtime now drops console output by default and exposes an explicit streaming hook (`onConsoleLog`) for host-controlled log handling.
15+
- Fix: runtime now drops console output by default and exposes an explicit streaming hook (`onStdio`) for host-controlled log handling.
1616
- Compatibility trade-off: `exec()`/`run()` no longer mirror Node stdout/stderr buffering by default; result payloads no longer expose `stdout`/`stderr` fields, so consumers that need logs must opt into hook-based streaming.
1717
- Migration note: switch any `result.stderr` checks to `result.errorMessage` for runtime error assertions.
1818
4. **[resolved]** Node module loading depended on allowlist projection setup and split filesystem paths.

docs/node-compatability.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Unsupported modules use: `"<module> is not supported in sandbox"`.
5858
- `console.log`/`warn`/`error` are supported and serialize arguments with circular-safe bounded formatting.
5959
- `exec()`/`run()` results do not expose buffered `stdout`/`stderr` fields.
6060
- By default, secure-exec drops console emissions instead of buffering runtime-managed output.
61-
- Consumers that need logs should use the explicit `onConsoleLog` hook to stream `stdout`/`stderr` events in emission order.
61+
- Consumers that need logs should use the explicit `onStdio` hook to stream `stdout`/`stderr` events in emission order.
6262

6363
## Node-Modules Overlay Behavior
6464

docs/quickstart.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ description: Get secure-exec running from TypeScript in a few minutes.
1111
</Step>
1212
<Step title="Execute code">
1313
```ts
14-
import { NodeProcess, createNodeDriver } from "secure-exec";
14+
import { NodeRuntime, createNodeDriver } from "secure-exec";
1515

16-
const proc = new NodeProcess({ driver: createNodeDriver({}) });
16+
const proc = new NodeRuntime({ driver: createNodeDriver({}) });
1717
const logs: string[] = [];
1818
const result = await proc.exec("console.log('hello from secure-exec')", {
19-
onConsoleLog: (event) => {
19+
onStdio: (event) => {
2020
logs.push(`[${event.channel}] ${event.message}`);
2121
},
2222
});

docs/security-model.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,5 @@ The bridge also enforces isolate-boundary payload limits so oversized base64 fil
8181
## Logging Contract
8282

8383
- Console output is **not buffered** into runtime-managed execution result fields by default (`exec()`/`run()` do not expose `stdout`/`stderr` result fields).
84-
- To consume logs, configure the optional `onConsoleLog` streaming hook and forward events to your own sink.
84+
- To consume logs, configure the optional `onStdio` streaming hook and forward events to your own sink.
8585
- This avoids implicit host-memory growth from untrusted high-volume logging.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: spec-driven
2+
created: 2026-03-02
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
## Context
2+
3+
The runtime refactor already split responsibilities to a thin runtime facade and driver-owned execution internals. However, the public names still used legacy `NodeProcess` and `SandboxDriver` terminology, which obscured the intended ownership model and conflicted with the architecture docs.
4+
5+
## Goals / Non-Goals
6+
7+
**Goals:**
8+
- Rename the runtime facade type from `NodeProcess` to `NodeRuntime`.
9+
- Rename the driver contract from `SandboxDriver` to `RuntimeDriver`.
10+
- Keep runtime behavior unchanged while updating symbols, imports, and docs.
11+
- Rename the dedicated driver type file to `runtime-driver.ts` and keep `types.ts` as the compatibility export surface.
12+
13+
**Non-Goals:**
14+
- Rework runtime execution semantics, permissions policy, or module-access behavior.
15+
- Restore browser runtime support.
16+
- Change low-level isolate/bridge orchestration.
17+
18+
## Decisions
19+
20+
1. Rename symbols directly instead of introducing aliases.
21+
- Rationale: avoid long-term dual API maintenance and ambiguity.
22+
- Alternative: export deprecated aliases (`NodeProcess`, `SandboxDriver`). Rejected for now to keep API surface explicit.
23+
24+
2. Keep `types.ts` as the import gateway for shared contracts.
25+
- Rationale: existing imports already point to `types.ts`; moving declarations to `runtime-driver.ts` with re-exports gives cleaner ownership with lower migration risk.
26+
- Alternative: force every consumer to import from `runtime-driver.ts`. Rejected as unnecessary churn.
27+
28+
3. Update OpenSpec baseline specs to new names.
29+
- Rationale: capability requirements must reflect the current external contract.
30+
- Alternative: keep old names in specs with translation notes. Rejected to prevent drift.
31+
32+
## Risks / Trade-offs
33+
34+
- [Breaking symbol rename] -> Mitigation: update all local call sites (src/tests/examples/docs/specs) in one pass and verify with typecheck/tests.
35+
- [Residual old references in docs/specs] -> Mitigation: run repository-wide symbol scans after rename and patch remaining hits.
36+
- [Behavior regression masked as rename] -> Mitigation: run targeted Node runtime and module-access suites after rename.
37+
38+
## Migration Plan
39+
40+
1. Rename `driver-types.ts` to `runtime-driver.ts` and rename `SandboxDriver` to `RuntimeDriver`.
41+
2. Rename `NodeProcess`/`NodeProcessOptions` to `NodeRuntime`/`NodeRuntimeOptions` in source and exports.
42+
3. Update tests/examples/docs/spec references.
43+
4. Validate with `tsc` and targeted vitest suites.
44+
45+
## Open Questions
46+
47+
- Do we want temporary compatibility aliases for one release window, or keep this as a hard break only?
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
## Why
2+
3+
The public naming around Node runtime orchestration and driver contracts was still mixed between generic and sandbox-specific terms. Aligning names to `NodeRuntime` and `RuntimeDriver` makes ownership clearer and matches the current architecture split (`NodeRuntime` facade over driver-owned execution internals).
4+
5+
## What Changes
6+
7+
- **BREAKING**: Rename `NodeProcess` to `NodeRuntime` and `NodeProcessOptions` to `NodeRuntimeOptions` in the `secure-exec` public API.
8+
- **BREAKING**: Rename `SandboxDriver` to `RuntimeDriver` in public and internal driver-facing type contracts.
9+
- Rename `packages/secure-exec/src/driver-types.ts` to `packages/secure-exec/src/runtime-driver.ts` and update re-exports from `types.ts`.
10+
- Update tests/examples/docs/spec references to the new names.
11+
12+
## Capabilities
13+
14+
### New Capabilities
15+
- None.
16+
17+
### Modified Capabilities
18+
- `node-runtime`: rename runtime facade and driver contract terms from `NodeProcess`/`SandboxDriver` to `NodeRuntime`/`RuntimeDriver`.
19+
- `node-permissions`: update permission scenarios to reference `NodeRuntime` construction semantics.
20+
21+
## Impact
22+
23+
- `packages/secure-exec/src/index.ts`
24+
- `packages/secure-exec/src/runtime-driver.ts`
25+
- `packages/secure-exec/src/types.ts`
26+
- `packages/secure-exec/src/node/driver.ts`
27+
- `packages/secure-exec/tests/*` (renamed helper/type usages)
28+
- `examples/hono/*`, `examples/just-bash/*`
29+
- `openspec/specs/node-runtime/spec.md`
30+
- `openspec/specs/node-permissions/spec.md`
31+
- `docs-internal/arch/overview.md`
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
## MODIFIED Requirements
2+
3+
### Requirement: allowAll permission helper
4+
The system SHALL export an `allowAll` constant of type `Permissions` where every domain checker (`fs`, `network`, `childProcess`, `env`) returns `{ allow: true }`.
5+
6+
#### Scenario: Runtime created with allowAll permits all operations
7+
- **WHEN** a `NodeRuntime` is created with `permissions: allowAll` and a filesystem adapter
8+
- **THEN** all filesystem operations SHALL succeed without `EACCES` errors
9+
10+
#### Scenario: allowAll is a valid Permissions object
11+
- **WHEN** `allowAll` is assigned to a variable of type `Permissions`
12+
- **THEN** it SHALL compile without type errors
13+
14+
### Requirement: Per-domain permission helpers
15+
The system SHALL export per-domain allow helpers: `allowAllFs`, `allowAllNetwork`, `allowAllChildProcess`, `allowAllEnv`. Each SHALL be a partial `Permissions` object containing only the corresponding domain checker returning `{ allow: true }`.
16+
17+
#### Scenario: Compose per-domain helpers for selective access
18+
- **WHEN** a `NodeRuntime` is created with `permissions: { ...allowAllFs, ...allowAllNetwork }` and both filesystem and network adapters
19+
- **THEN** filesystem and network operations SHALL succeed, while child-process and env operations SHALL throw `EACCES`
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
## MODIFIED Requirements
2+
3+
### Requirement: Unified Sandbox Execution Interface
4+
The project SHALL provide a stable Node sandbox execution interface, with `NodeRuntime` exposing an `exec` path for running untrusted code and returning structured execution results, and a `run` path that returns module exports. Browser runtime execution support SHALL be disabled for this change phase.
5+
6+
#### Scenario: Execute code in Node runtime
7+
- **WHEN** a caller creates `NodeRuntime` with a valid driver and invokes `exec`
8+
- **THEN** the sandbox MUST run the provided code in an isolated execution context and return structured output for the caller
9+
10+
#### Scenario: Browser runtime is disabled for this phase
11+
- **WHEN** a caller attempts to use browser sandbox runtime entrypoints during this change phase
12+
- **THEN** browser runtime execution MUST be unavailable under the runtime contract until a follow-up change restores support
13+
14+
#### Scenario: Run CJS module and retrieve exports
15+
- **WHEN** a caller invokes `run()` with CommonJS code that assigns to `module.exports`
16+
- **THEN** the result's `exports` field MUST contain the value of `module.exports`
17+
18+
#### Scenario: Run ESM module and retrieve namespace exports
19+
- **WHEN** a caller invokes `run()` with ESM code that uses `export` declarations
20+
- **THEN** the result's `exports` field MUST contain the module namespace object with all named exports and the `default` export (if declared)
21+
22+
#### Scenario: Run ESM module with only a default export
23+
- **WHEN** a caller invokes `run()` with ESM code containing `export default <value>`
24+
- **THEN** the result's `exports` field MUST be an object with a `default` property holding that value
25+
26+
#### Scenario: Run ESM module with named and default exports
27+
- **WHEN** a caller invokes `run()` with ESM code containing both `export default` and named `export` declarations
28+
- **THEN** the result's `exports` field MUST be an object containing both the `default` property and all named export properties
29+
30+
### Requirement: Driver-Based Capability Composition
31+
Runtime capabilities SHALL be composed through host-provided drivers so filesystem, network, and child-process behavior are controlled by configured adapters rather than hardcoded runtime behavior. `NodeRuntime` construction SHALL require a driver.
32+
33+
#### Scenario: Node process uses configured adapters
34+
- **WHEN** `NodeRuntime` is created with a driver that defines filesystem, network, and command-execution adapters
35+
- **THEN** sandboxed operations MUST route through those adapters for capability access
36+
37+
#### Scenario: Missing permissions deny capability access by default
38+
- **WHEN** a driver is configured without explicit permission allowance for a capability domain
39+
- **THEN** operations in that capability domain MUST be denied by default
40+
41+
#### Scenario: Omitted capability remains unavailable
42+
- **WHEN** a capability adapter is omitted from runtime configuration
43+
- **THEN** corresponding sandbox operations MUST be unavailable or denied by the runtime contract

0 commit comments

Comments
 (0)