@letterblack/lbe-core 1.3.3 → 1.3.4
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/LICENSE +1 -1
- package/README.md +130 -442
- package/assets/runtime-boundary.svg +36 -36
- package/dist/cli.js +141 -0
- package/dist/index.js +52 -0
- package/{release-exec/dist → dist}/wasm.lock.json +5 -4
- package/package.json +23 -54
- package/types.d.ts +2 -175
- package/.githooks/pre-commit +0 -2
- package/.githooks/pre-push +0 -2
- package/CHANGELOG.md +0 -75
- package/Release-README.md +0 -65
- package/WORKSPACE.md +0 -422
- package/_proof.mjs +0 -246
- package/bin/lbe.js +0 -12
- package/config/identity.config.json +0 -3
- package/config/policy.default.json +0 -24
- package/dist/cli/lbe.js +0 -4274
- package/dist/hooks/register.cjs +0 -505
- package/dist/state/appendCentral.cjs +0 -87
- package/dist/state/index.cjs +0 -101
- package/exec/cli.js +0 -472
- package/exec/index.js +0 -2
- package/index.js +0 -24
- package/lbe.audit.jsonl +0 -46
- package/release/README.md +0 -216
- package/release/TRUST.md +0 -90
- package/release/exec-README.md +0 -215
- package/release/exec-types.d.ts +0 -50
- package/release-exec/LICENSE +0 -1
- package/release-exec/README.md +0 -215
- package/release-exec/assets/lbe-gates.jpg +0 -0
- package/release-exec/assets/lbe-gates.png +0 -0
- package/release-exec/assets/runtime-boundary.svg +0 -36
- package/release-exec/assets/story-allow.jpg +0 -0
- package/release-exec/assets/story-allow.png +0 -0
- package/release-exec/assets/story-deny.jpg +0 -0
- package/release-exec/assets/story-deny.png +0 -0
- package/release-exec/dist/cli.js +0 -2841
- package/release-exec/dist/index.js +0 -1835
- package/release-exec/hooks/register.cjs +0 -473
- package/release-exec/package.json +0 -35
- package/release-exec/types.d.ts +0 -50
- package/runtime/engine.js +0 -322
- package/runtime/lbe_engine.wasm +0 -0
- package/src/cli/commands/auditVerify.js +0 -36
- package/src/cli/commands/dryrun.js +0 -175
- package/src/cli/commands/health.js +0 -153
- package/src/cli/commands/init.js +0 -306
- package/src/cli/commands/integrityCheck.js +0 -57
- package/src/cli/commands/logs.js +0 -53
- package/src/cli/commands/openState.js +0 -44
- package/src/cli/commands/policyAdd.js +0 -8
- package/src/cli/commands/policyMode.js +0 -7
- package/src/cli/commands/policySign.js +0 -72
- package/src/cli/commands/proof.js +0 -122
- package/src/cli/commands/run.js +0 -342
- package/src/cli/commands/status.js +0 -73
- package/src/cli/commands/verify.js +0 -144
- package/src/cli/main.js +0 -176
- package/src/cli/parseArgs.js +0 -114
- package/src/exec/localExecutor.js +0 -289
- package/src/hooks/register.cjs +0 -505
- package/src/state/appendCentral.cjs +0 -87
- package/src/state/fileIndex.js +0 -140
- package/src/state/index.cjs +0 -101
- package/src/state/index.js +0 -65
- package/src/state/intentRegistry.js +0 -83
- package/src/state/migration.js +0 -112
- package/src/state/proofRunner.js +0 -246
- package/src/state/stateRoot.js +0 -40
- package/src/state/targetRegistry.js +0 -108
- package/src/state/workspaceId.js +0 -40
- package/src/state/workspaceRegistry.js +0 -65
- /package/{release-exec/dist → dist}/lbe_engine.wasm +0 -0
package/LICENSE
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
SEE LICENSE IN LICENSE
|
|
1
|
+
SEE LICENSE IN LICENSE
|
package/README.md
CHANGED
|
@@ -1,506 +1,194 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @letterblack/lbe-core
|
|
2
2
|
|
|
3
3
|
LBE is local execution control for AI agents. It evaluates file and shell
|
|
4
|
-
actions routed through its execution boundary
|
|
5
|
-
|
|
4
|
+
actions routed through its execution boundary and records local evidence.
|
|
5
|
+
It is not an AI model, IDE, full OS sandbox, or cloud monitor.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
control direct actions outside its execution boundary.
|
|
9
|
-
|
|
10
|
-
## Install and start
|
|
7
|
+
## Setup and workspace initialization
|
|
11
8
|
|
|
12
9
|
```bash
|
|
13
10
|
npm install @letterblack/lbe-core
|
|
14
11
|
npx lbe init
|
|
15
12
|
npx lbe status
|
|
16
13
|
npx lbe logs
|
|
17
|
-
npx lbe proof --public
|
|
18
14
|
npx lbe open-state
|
|
15
|
+
npx lbe proof
|
|
16
|
+
npx lbe proof --public
|
|
19
17
|
```
|
|
20
18
|
|
|
21
|
-
`init` creates
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
## Local state and proof
|
|
26
|
-
|
|
27
|
-
LBE keeps state locally in a central per-user state folder. Each workspace has
|
|
28
|
-
a stable workspace ID and its own event log. In v1.3, an existing
|
|
29
|
-
`.lbe/events.jsonl` remains local fallback truth and is imported into central
|
|
30
|
-
state once; the source file is preserved.
|
|
19
|
+
`npx lbe init` creates the workspace policy and state material in the central
|
|
20
|
+
per-user folder keyed by workspace ID. `npx lbe status`, `logs`, and
|
|
21
|
+
`open-state` read that local state, while `proof` writes the proof record and
|
|
22
|
+
`--public` redacts sensitive proof details.
|
|
31
23
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
## Limits
|
|
37
|
-
|
|
38
|
-
Only actions routed through LBE are controlled. Central writes are best-effort,
|
|
39
|
-
logs remain local, and LBE does not provide process isolation or network
|
|
40
|
-
egress control.
|
|
24
|
+
In v1.3, `.lbe/events.jsonl` remains local fallback truth and is imported once
|
|
25
|
+
without changing the original file. Proof uses intent, target, file index, LBE
|
|
26
|
+
events, and `proof/latest.json`. Central writes are best-effort, logs remain
|
|
27
|
+
local, and non-inspectable targets may produce `WEAK_PROOF`.
|
|
41
28
|
|
|
42
29
|
---
|
|
43
30
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
tests, and release tooling. The public package is generated into
|
|
48
|
-
`release-public/` as `@letterblack/lbe-core`.
|
|
49
|
-
|
|
50
|
-
Every AI action passes through a local gate before it can execute.
|
|
51
|
-
|
|
52
|
-
**Local-first execution governance for AI agents.**
|
|
53
|
-
Deterministic execution. Workspace context. Audit. Rollback.
|
|
54
|
-
|
|
55
|
-
Everything runs on your machine. No cloud required.
|
|
56
|
-
|
|
57
|
-
**Distribution model:** this private package owns source truth. The public SDK
|
|
58
|
-
package ships only the generated public surface: bundled/minified `dist/`
|
|
59
|
-
entrypoints, `types.d.ts`, README, default policy template, and the WASM runtime.
|
|
60
|
-
LBE is SDK-only and local-only. It does not ship an MCP server, daemon, HTTP
|
|
61
|
-
API, hosted service, deployment infrastructure, or companion platform.
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
## Private/Public Release Contract
|
|
66
|
-
|
|
67
|
-
Do internal development here:
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
npm install
|
|
71
|
-
npm run lint
|
|
72
|
-
npm test
|
|
73
|
-
npm run pack:check
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
Build the public SDK package here:
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
npm run build:engine
|
|
80
|
-
npm run validate:all
|
|
81
|
-
npm run verify:public-sdk
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Before publishing, install the generated tarball in a clean temporary project
|
|
85
|
-
and exercise the supported CLI workflow (`lbe init`, `lbe status`, `lbe policy`,
|
|
86
|
-
and `lbe enforce`). Publish only from `release-public/` after that test passes.
|
|
87
|
-
|
|
88
|
-
### Public repository release
|
|
89
|
-
|
|
90
|
-
`../.github/workflows/release-public.yml` publishes only the generated
|
|
91
|
-
`release-public/` tree to `Letterblack0306/LetterBlack-Sentinel`; it never
|
|
92
|
-
pushes this private source repository, its history, or its internal files.
|
|
93
|
-
|
|
94
|
-
Set `PUBLIC_REPO_TOKEN` and `NPM_TOKEN` as Actions secrets in this repository.
|
|
95
|
-
The former needs Contents read/write permission to the public repository; the
|
|
96
|
-
latter needs npm publish permission for `@letterblack/lbe-core`. Push a matching
|
|
97
|
-
`v<package-version>` tag from current `main` to release automatically, or run
|
|
98
|
-
the workflow manually with the same tag value. The workflow verifies the
|
|
99
|
-
artifact and tests first, publishes npm, replaces the public repository working
|
|
100
|
-
tree with the release artifact, then creates its tag and GitHub release. It
|
|
101
|
-
blocks release unless the checked-out commit is the current `main` head.
|
|
102
|
-
|
|
103
|
-
## Source authority
|
|
104
|
-
|
|
105
|
-
Only `main` in the primary working tree is a source of truth. Do not develop,
|
|
106
|
-
commit, validate, or push from feature branches, detached HEADs, or linked Git
|
|
107
|
-
worktrees. Run `npm run hooks:install` after cloning; see
|
|
108
|
-
[`docs/governance/mainhead.md`](docs/governance/mainhead.md) for the blocker
|
|
109
|
-
rules.
|
|
110
|
-
|
|
111
|
-
Publish only from:
|
|
112
|
-
|
|
113
|
-
```text
|
|
114
|
-
release-public/
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
The generated public package must not contain:
|
|
118
|
-
|
|
119
|
-
```text
|
|
120
|
-
src/core/
|
|
121
|
-
src/adapters/
|
|
122
|
-
src/cli/
|
|
123
|
-
scripts/
|
|
124
|
-
test/
|
|
125
|
-
keys/
|
|
126
|
-
data/
|
|
127
|
-
node_modules/
|
|
128
|
-
*.map
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
## Install
|
|
134
|
-
|
|
135
|
-
Internal source workspace:
|
|
31
|
+
LBE puts a local policy gate between what an AI agent proposes and what the
|
|
32
|
+
system actually executes. Every action — file write, shell command, anything —
|
|
33
|
+
is validated locally before it runs. No cloud service. No daemon.
|
|
136
34
|
|
|
137
|
-
|
|
138
|
-
npm install @letterblack/lbe-core
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
Public users install:
|
|
35
|
+
> **Used in production:** LBE is the safety engine inside [Letterblack for After Effects](https://letterblack.net) — every AI-generated script and automation command passes through it before touching a live project.
|
|
142
36
|
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
143
41
|
```bash
|
|
144
42
|
npm install @letterblack/lbe-core
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
Requires Node.js ≥ 20.9.0.
|
|
148
|
-
|
|
149
|
-
The current preview uses the audited JavaScript governance engine. The commercial
|
|
150
|
-
runtime target is a compiled engine loaded locally through WASM, with the same
|
|
151
|
-
public SDK and CLI surface.
|
|
152
|
-
|
|
153
|
-
---
|
|
154
|
-
|
|
155
|
-
## After install
|
|
156
|
-
|
|
157
|
-
```bash
|
|
158
|
-
npx lbe execute --input input.json
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
`input.json` must contain a signed LBE execution request. You can also pipe the
|
|
162
|
-
same JSON request through stdin:
|
|
163
|
-
|
|
164
|
-
```bash
|
|
165
|
-
cat input.json | npx lbe execute
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
---
|
|
169
|
-
|
|
170
|
-
## Quick Start
|
|
171
|
-
|
|
172
|
-
```js
|
|
173
|
-
import crypto from 'node:crypto';
|
|
174
|
-
import { execute } from '@letterblack/lbe-core';
|
|
175
|
-
|
|
176
|
-
const buildRequest = (name, payload = {}) => ({
|
|
177
|
-
version: '1.0',
|
|
178
|
-
request_id: crypto.randomUUID(),
|
|
179
|
-
timestamp: Math.floor(Date.now() / 1000),
|
|
180
|
-
actor: { id: 'agent:local', role: 'agent' },
|
|
181
|
-
intent: { type: 'command', name, payload },
|
|
182
|
-
context: { workspace: process.cwd(), env: {}, history: [] },
|
|
183
|
-
constraints: { policy_mode: 'strict', timeout_ms: 5000 },
|
|
184
|
-
auth: { signature: 'provided-by-host', nonce: crypto.randomUUID() }
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
const output = execute(JSON.stringify(buildRequest('status')));
|
|
188
|
-
console.log(JSON.parse(output));
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
The public contract is `execute(input: string): string`. This repo still
|
|
192
|
-
contains the private source package and its internal SDK helpers below, but the
|
|
193
|
-
published surface is the generated `@letterblack/lbe-core` package.
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Requires Node.js ≥ 20.9.0.
|
|
194
46
|
|
|
195
47
|
---
|
|
196
48
|
|
|
197
|
-
##
|
|
198
|
-
|
|
199
|
-
**Audit — see exactly what changed and when:**
|
|
200
|
-
```js
|
|
201
|
-
const sb = sandbox('./workspace', { audit: true });
|
|
202
|
-
// appends to ~/.lbe/workspaces/<id>/audit.log.jsonl
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
**Rollback — undo failed writes automatically:**
|
|
206
|
-
```js
|
|
207
|
-
const sb = sandbox('./workspace', { audit: true, rollback: true });
|
|
208
|
-
// backs up before every write, restores on failure
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
**State stays local** — all runtime state (audit logs, nonce store, backups) goes to
|
|
212
|
-
`~/.lbe/workspaces/<workspace-id>/` by default. Never inside your project, never sent anywhere.
|
|
49
|
+
## Quick start
|
|
213
50
|
|
|
214
|
-
To keep state inside the project instead (for team sharing):
|
|
215
51
|
```js
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
52
|
+
import { execute } from '@letterblack/lbe-core';
|
|
53
|
+
|
|
54
|
+
const request = {
|
|
55
|
+
version: '1.0',
|
|
56
|
+
request_id: 'req-001',
|
|
57
|
+
timestamp: Math.floor(Date.now() / 1000),
|
|
58
|
+
actor: { id: 'agent:local', role: 'agent' },
|
|
59
|
+
intent: { type: 'command', name: 'write_file', payload: { target: 'out.txt' } },
|
|
60
|
+
context: { workspace: process.cwd(), env: {}, history: [] },
|
|
61
|
+
constraints: { policy_mode: 'strict', timeout_ms: 5000 },
|
|
62
|
+
auth: { signature: '<host-signed>', nonce: '<unique-per-request>' }
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const result = JSON.parse(execute(JSON.stringify(request)));
|
|
66
|
+
// Approved: { ok: true, decision: 'allow', ... }
|
|
67
|
+
// Blocked: { ok: false, decision: 'deny', error: { stage, message } }
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`execute(input: string): string` — accepts JSON, returns JSON. The runtime validates and returns a decision. The host acts on the decision.
|
|
71
|
+
|
|
72
|
+
### Request fields
|
|
73
|
+
|
|
74
|
+
| Field | Required | Description |
|
|
75
|
+
|---|---:|---|
|
|
76
|
+
| `version` | Yes | `"1.0"` |
|
|
77
|
+
| `request_id` | Yes | Caller-supplied unique identifier |
|
|
78
|
+
| `timestamp` | Yes | Unix timestamp in seconds |
|
|
79
|
+
| `actor` | Yes | `{ id, role }` — identity of the requesting agent |
|
|
80
|
+
| `intent` | Yes | `{ type, name, payload }` — what the agent wants to do |
|
|
81
|
+
| `context` | Yes | Workspace path and caller context |
|
|
82
|
+
| `constraints` | Yes | `policy_mode` and `timeout_ms` |
|
|
83
|
+
| `auth` | Yes | Host-supplied `signature` and `nonce` |
|
|
219
84
|
|
|
220
85
|
---
|
|
221
86
|
|
|
222
|
-
##
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
See [`docs/decisions/ADR-001-remove-mcp-execution-surface.md`](docs/decisions/ADR-001-remove-mcp-execution-surface.md).
|
|
87
|
+
## CLI reference
|
|
88
|
+
|
|
89
|
+
| Command | Purpose |
|
|
90
|
+
|---|---|
|
|
91
|
+
| `npx lbe init` | Initialize the workspace policy and state material |
|
|
92
|
+
| `npx lbe status` | Show the current workspace and proof status |
|
|
93
|
+
| `npx lbe logs` | Inspect local evidence and event logs |
|
|
94
|
+
| `npx lbe open-state` | Open the central local state folder |
|
|
95
|
+
| `npx lbe proof` | Write the current proof record |
|
|
96
|
+
| `npx lbe proof --public` | Write a redacted proof record for public surfaces |
|
|
233
97
|
|
|
234
98
|
---
|
|
235
99
|
|
|
236
|
-
##
|
|
237
|
-
|
|
238
|
-
LBE Agent Safe Execution intercepts Node.js file and shell actions before they mutate the workspace.
|
|
100
|
+
## How the gate pipeline works
|
|
239
101
|
|
|
240
|
-
|
|
102
|
+

|
|
241
103
|
|
|
242
|
-
|
|
104
|
+
Every request enters a 7-gate pipeline. A failure at any gate returns a structured denial — the remaining gates are not evaluated.
|
|
243
105
|
|
|
244
|
-
If you control the agent's dispatch loop, integrate `lbe-exec` at the point where actions are issued. No preload hook needed — LBE governs each action directly through the SDK.
|
|
245
|
-
|
|
246
|
-
```js
|
|
247
|
-
import { createLocalExecutor } from '@letterblack/lbe-exec';
|
|
248
|
-
|
|
249
|
-
const lbe = createLocalExecutor({ rootDir: process.cwd(), mode: 'enforce' });
|
|
250
|
-
|
|
251
|
-
await lbe.writeFile('src/output.ts', content);
|
|
252
|
-
await lbe.deleteFile('src/old.ts');
|
|
253
|
-
await lbe.runShell('npm', ['test']);
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
Every call passes through the full 7-gate pipeline: local policy, key lifecycle, signature, rate limit, nonce, and audit.
|
|
257
|
-
|
|
258
|
-
### 2. Node agents you launch — `run-node`
|
|
259
|
-
|
|
260
|
-
Use `run-node` to launch any Node.js agent under the preload hook. The hook patches `fs` and `child_process` before the agent's entry module runs — including actions taken by the agent's own npm dependencies.
|
|
261
|
-
|
|
262
|
-
```bash
|
|
263
|
-
npx lbe-exec run-node ./agent.js
|
|
264
|
-
npx lbe-exec run-node --mode enforce ./agent.js
|
|
265
106
|
```
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
107
|
+
[1] Schema required fields and structural validity
|
|
108
|
+
↓
|
|
109
|
+
[2] Timestamp permitted clock-skew window (±10 minutes)
|
|
110
|
+
↓
|
|
111
|
+
[3] Key lifecycle trusted key, active, not expired
|
|
112
|
+
↓
|
|
113
|
+
[4] Signature Ed25519 request authenticity
|
|
114
|
+
↓
|
|
115
|
+
[5] Rate limit per-requester sliding-window limit
|
|
116
|
+
↓
|
|
117
|
+
[6] Nonce single-use replay protection
|
|
118
|
+
↓
|
|
119
|
+
[7] Policy configured authorization (deny-wins)
|
|
120
|
+
↓
|
|
121
|
+
allow / deny / error — structured result returned to host
|
|
275
122
|
```
|
|
276
123
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
### 4. Opaque or external agents — sandbox mode (future)
|
|
280
|
-
|
|
281
|
-
For agents that run outside Node.js, inside containers, or as opaque binaries — sandbox mode is planned. Not available in this release.
|
|
124
|
+
The WASM runtime owns all gate decisions. Your host receives the decision and acts on it. Nothing executes inside the runtime.
|
|
282
125
|
|
|
283
126
|
---
|
|
284
127
|
|
|
285
|
-
|
|
128
|
+
## When a request is approved
|
|
286
129
|
|
|
287
|
-
|
|
288
|
-
npx lbe-exec init
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
Detects agent scripts in `package.json` and adds `:lbe` and `:lbe:enforce` variants alongside them. Originals are never overwritten.
|
|
130
|
+

|
|
292
131
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
132
|
+
1. The agent produces a signed action proposal.
|
|
133
|
+
2. Identity is confirmed against a locally held key — no network call required.
|
|
134
|
+
3. The project policy is evaluated. The action is approved.
|
|
135
|
+
4. The host executes the write or command inside the allowed workspace.
|
|
136
|
+
5. The audit chain is extended — every approved action appends a hash-linked entry to the local log, permanently verifiable, impossible to silently remove.
|
|
137
|
+
6. A structured result returns: whether it succeeded, which rules matched, and the audit entry identifier.
|
|
297
138
|
|
|
298
|
-
|
|
299
|
-
```json
|
|
300
|
-
{
|
|
301
|
-
"scripts": {
|
|
302
|
-
"agent": "node ./src/agent.js",
|
|
303
|
-
"agent:lbe": "lbe-exec run-node --mode observe ./src/agent.js",
|
|
304
|
-
"agent:lbe:enforce": "lbe-exec run-node --mode enforce ./src/agent.js",
|
|
305
|
-
"lbe:status": "lbe-exec status",
|
|
306
|
-
"lbe:audit": "lbe-exec audit"
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
### Status and audit
|
|
312
|
-
|
|
313
|
-
```bash
|
|
314
|
-
npx lbe-exec status # hook state, PID liveness, patched function table
|
|
315
|
-
npx lbe-exec audit # stream .lbe/events.jsonl as a formatted table
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
`status` reads `.lbe/runtime/hook-status.json` written by the hook at preload time and checks PID liveness in a separate process — no shared memory required.
|
|
139
|
+
The application stays in control. @letterblack/lbe-core decides whether the action was permitted and hands the answer back. It does not execute for you.
|
|
319
140
|
|
|
320
141
|
---
|
|
321
142
|
|
|
322
|
-
##
|
|
143
|
+
## When a request is blocked
|
|
323
144
|
|
|
324
|
-
|
|
145
|
+

|
|
325
146
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
const lbe = createLBE({
|
|
332
|
-
secretKey,
|
|
333
|
-
keyId: 'prod-key',
|
|
334
|
-
keyStore: createKeyStore({ publicKey, keyId: 'prod-key' }),
|
|
335
|
-
policy: {
|
|
336
|
-
version: 1,
|
|
337
|
-
default: 'DENY',
|
|
338
|
-
requesters: {
|
|
339
|
-
'agent:writer': {
|
|
340
|
-
allowCommands: ['write_file', 'read_file'],
|
|
341
|
-
allowAdapters: ['file'],
|
|
342
|
-
filesystem: {
|
|
343
|
-
roots: ['./output/'],
|
|
344
|
-
denyPatterns: ['*.key', '*.env']
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
const result = await lbe.execute({
|
|
352
|
-
actor: 'agent:writer',
|
|
353
|
-
intent: 'write_file',
|
|
354
|
-
target: './output/report.md',
|
|
355
|
-
content: '# Report\n',
|
|
356
|
-
transaction: { backup: true, rollbackOnFailure: true, audit: true }
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
console.log(result.ok); // true | false
|
|
360
|
-
console.log(result.stage); // 'executed' | 'validate' | 'invariant_gate' | ...
|
|
361
|
-
console.log(result.commandId); // matches audit log entry
|
|
362
|
-
```
|
|
147
|
+
1. The agent proposes an action that is outside the permitted policy.
|
|
148
|
+
2. The policy gate closes immediately. The WASM runtime stamps the request denied before any adapter is reached.
|
|
149
|
+
3. The shell is untouched. The filesystem is unchanged.
|
|
150
|
+
4. The denial is written to the immutable audit log — chain sealed, evidence preserved.
|
|
363
151
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
```js
|
|
367
|
-
const lbe = createLBE({ rootDir: process.cwd() });
|
|
368
|
-
await lbe.writeFile('data/output.txt', 'result\n');
|
|
369
|
-
const text = await lbe.readFile('data/output.txt');
|
|
370
|
-
```
|
|
152
|
+
No partial execution. No silent failures. Denial is a first-class outcome, not an error.
|
|
371
153
|
|
|
372
154
|
---
|
|
373
155
|
|
|
374
|
-
##
|
|
156
|
+
## What this covers
|
|
375
157
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
├── schema
|
|
385
|
-
├── key lifecycle
|
|
386
|
-
├── timestamp skew
|
|
387
|
-
├── signature
|
|
388
|
-
├── rate limit
|
|
389
|
-
├── nonce replay
|
|
390
|
-
└── policy (deny-by-default)
|
|
391
|
-
│
|
|
392
|
-
▼ all gates pass
|
|
393
|
-
Adapter ── file | shell | noop
|
|
394
|
-
│
|
|
395
|
-
▼
|
|
396
|
-
Audit Log ── SHA-256 hash-chained JSONL, append-only
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
The controller is the only authority. Adapters execute — they do not decide.
|
|
158
|
+
| Threat | Gate |
|
|
159
|
+
|---|---|
|
|
160
|
+
| Malformed or incomplete request | Schema |
|
|
161
|
+
| Stale or replayed request | Timestamp + Nonce |
|
|
162
|
+
| Tampered or expired key | Key lifecycle + Signature |
|
|
163
|
+
| Excessive requests from one actor | Rate limit |
|
|
164
|
+
| Action not permitted by project policy | Policy — deny-wins |
|
|
165
|
+
| Agent writing outside project root | Scope check in host after decision |
|
|
400
166
|
|
|
401
167
|
---
|
|
402
168
|
|
|
403
|
-
##
|
|
169
|
+
## What ships
|
|
404
170
|
|
|
405
|
-
The published package (`@letterblack/lbe-core`) exposes one function:
|
|
406
|
-
|
|
407
|
-
```ts
|
|
408
|
-
export function execute(input: string): string;
|
|
409
|
-
```
|
|
410
|
-
|
|
411
|
-
`input` is a JSON-serialized `LBEExecuteInput`. The return value is a
|
|
412
|
-
JSON-serialized `LBEExecuteOutput`. Full type definitions are in `types.d.ts`.
|
|
413
|
-
|
|
414
|
-
```ts
|
|
415
|
-
interface LBEExecuteOutput {
|
|
416
|
-
ok: boolean;
|
|
417
|
-
result: { type: 'allowed' | 'denied' | 'error'; action: string; data: Record<string, unknown> };
|
|
418
|
-
policy: { decision: 'allow' | 'deny' | 'escalate'; reason: string; rules: string[] };
|
|
419
|
-
trace: { id: string; steps: unknown[]; hash: string };
|
|
420
|
-
error: null | { code: string; message: string };
|
|
421
|
-
}
|
|
422
171
|
```
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|---|---|---|
|
|
436
|
-
| `audit` | `false` | Append to audit log on every operation |
|
|
437
|
-
| `rollback` | `false` | Back up before write; restore on failure |
|
|
438
|
-
| `state` | `'local'` | `'local'` → `~/.lbe/` · `'workspace'` → `.lbe/` inside project |
|
|
439
|
-
|
|
440
|
-
### `createLBE(options)` → `{ execute, writeFile, readFile, exportLogs }`
|
|
441
|
-
|
|
442
|
-
| Option | Type | Description |
|
|
443
|
-
|---|---|---|
|
|
444
|
-
| `rootDir` | `string` | Auto-configure keys, policy, and state for this directory |
|
|
445
|
-
| `secretKey` | `string` | Ed25519 secret key (base64) |
|
|
446
|
-
| `keyId` | `string` | Key identifier |
|
|
447
|
-
| `policy` | `object` | Inline policy object |
|
|
448
|
-
| `state` | `string` | `'local'` (default) · `'workspace'` · `{ adapter }` |
|
|
449
|
-
| `logLevel` | `string` | `DEBUG` · `INFO` · `WARN` · `ERROR` |
|
|
450
|
-
|
|
451
|
-
### Additional exports
|
|
452
|
-
|
|
453
|
-
```js
|
|
454
|
-
import { AVAILABLE_ADAPTERS } from '@letterblack/lbe-core/adapters';
|
|
455
|
-
// → ['noop', 'shell', 'file']
|
|
456
|
-
|
|
457
|
-
import {
|
|
458
|
-
validateCommand,
|
|
459
|
-
appendAudit,
|
|
460
|
-
createBackup, restoreBackup,
|
|
461
|
-
signEd25519, verifyEd25519, generateKeyPair,
|
|
462
|
-
createLogger, deepFreeze,
|
|
463
|
-
checkInvariants, assertInvariants, InvariantGateError
|
|
464
|
-
} from '@letterblack/lbe-core';
|
|
172
|
+
dist/index.js WebAssembly runtime loader and execute()
|
|
173
|
+
dist/cli.js Local CLI (npx lbe)
|
|
174
|
+
dist/lbe_engine.wasm Verified runtime binary
|
|
175
|
+
dist/wasm.lock.json Runtime integrity lock (SHA-256 of wasm binary)
|
|
176
|
+
assets/lbe-gates.jpg Gate sequence diagram
|
|
177
|
+
assets/story-allow.jpg Approved-request storyboard
|
|
178
|
+
assets/story-deny.jpg Blocked-request storyboard
|
|
179
|
+
assets/runtime-boundary.svg Runtime boundary diagram
|
|
180
|
+
assets/lbe-gates.png Gate sequence diagram (full resolution)
|
|
181
|
+
assets/story-allow.png Approved-request storyboard (full resolution)
|
|
182
|
+
assets/story-deny.png Blocked-request storyboard (full resolution)
|
|
183
|
+
types.d.ts TypeScript declarations
|
|
465
184
|
```
|
|
466
185
|
|
|
467
|
-
|
|
186
|
+
At load time the runtime verifies `lbe_engine.wasm` against `wasm.lock.json`. A missing, modified, or swapped binary fails before any request is processed.
|
|
468
187
|
|
|
469
|
-
|
|
470
|
-
|---|---|
|
|
471
|
-
| `npx lbe execute --input input.json` | Execute one JSON request through the public runtime |
|
|
472
|
-
| `cat input.json \| npx lbe execute` | Execute one JSON request from stdin |
|
|
188
|
+
Source code, controller implementation, adapters, tests, keys, and runtime state are not included.
|
|
473
189
|
|
|
474
190
|
---
|
|
475
191
|
|
|
476
|
-
##
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
- **Nonce replay protection** — each `commandId` is single-use; replays are hard-rejected
|
|
480
|
-
- **Rate limiting** — per-requester, configurable window
|
|
481
|
-
- **Timestamp skew guard** — rejects proposals outside ±10 minutes
|
|
482
|
-
- **Policy signature verification** — the policy file itself is signed; tampering fails the invariant gate
|
|
483
|
-
- **Immutable audit trail** — SHA-256 hash-chained JSONL; any deletion or edit is detectable
|
|
484
|
-
- **Atomic writes** — all state files use write-then-rename; no partial state
|
|
485
|
-
|
|
486
|
-
**What is never committed:**
|
|
487
|
-
`keys/secret.key` · `keys/*.key` · `config/keys.json` · `config/policy.sig.json` · `data/`
|
|
488
|
-
|
|
489
|
-
**Scope — what this hardens against:**
|
|
490
|
-
Accidental writes outside allowed roots. Replay attacks. Policy drift. Audit log tampering. Rollback on failure.
|
|
491
|
-
|
|
492
|
-
**Not in scope:**
|
|
493
|
-
Kernel-level process isolation. Network egress control. Multi-tenant workload separation.
|
|
494
|
-
This SDK does not sandbox the agent process — it governs the actions that agent routes through the SDK.
|
|
495
|
-
|
|
496
|
-
---
|
|
497
|
-
|
|
498
|
-
## Changelog
|
|
499
|
-
|
|
500
|
-
See [`CHANGELOG.md`](CHANGELOG.md).
|
|
501
|
-
|
|
502
|
-
---
|
|
503
|
-
|
|
504
|
-
## License
|
|
505
|
-
|
|
506
|
-
MIT — LetterBlack 2026
|
|
192
|
+
## Limits
|
|
193
|
+
|
|
194
|
+
This package validates requests routed through its runtime. It does not provide kernel-level process isolation, network-egress control, multi-tenant separation, or a hosted control plane.
|