@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.
Files changed (75) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +130 -442
  3. package/assets/runtime-boundary.svg +36 -36
  4. package/dist/cli.js +141 -0
  5. package/dist/index.js +52 -0
  6. package/{release-exec/dist → dist}/wasm.lock.json +5 -4
  7. package/package.json +23 -54
  8. package/types.d.ts +2 -175
  9. package/.githooks/pre-commit +0 -2
  10. package/.githooks/pre-push +0 -2
  11. package/CHANGELOG.md +0 -75
  12. package/Release-README.md +0 -65
  13. package/WORKSPACE.md +0 -422
  14. package/_proof.mjs +0 -246
  15. package/bin/lbe.js +0 -12
  16. package/config/identity.config.json +0 -3
  17. package/config/policy.default.json +0 -24
  18. package/dist/cli/lbe.js +0 -4274
  19. package/dist/hooks/register.cjs +0 -505
  20. package/dist/state/appendCentral.cjs +0 -87
  21. package/dist/state/index.cjs +0 -101
  22. package/exec/cli.js +0 -472
  23. package/exec/index.js +0 -2
  24. package/index.js +0 -24
  25. package/lbe.audit.jsonl +0 -46
  26. package/release/README.md +0 -216
  27. package/release/TRUST.md +0 -90
  28. package/release/exec-README.md +0 -215
  29. package/release/exec-types.d.ts +0 -50
  30. package/release-exec/LICENSE +0 -1
  31. package/release-exec/README.md +0 -215
  32. package/release-exec/assets/lbe-gates.jpg +0 -0
  33. package/release-exec/assets/lbe-gates.png +0 -0
  34. package/release-exec/assets/runtime-boundary.svg +0 -36
  35. package/release-exec/assets/story-allow.jpg +0 -0
  36. package/release-exec/assets/story-allow.png +0 -0
  37. package/release-exec/assets/story-deny.jpg +0 -0
  38. package/release-exec/assets/story-deny.png +0 -0
  39. package/release-exec/dist/cli.js +0 -2841
  40. package/release-exec/dist/index.js +0 -1835
  41. package/release-exec/hooks/register.cjs +0 -473
  42. package/release-exec/package.json +0 -35
  43. package/release-exec/types.d.ts +0 -50
  44. package/runtime/engine.js +0 -322
  45. package/runtime/lbe_engine.wasm +0 -0
  46. package/src/cli/commands/auditVerify.js +0 -36
  47. package/src/cli/commands/dryrun.js +0 -175
  48. package/src/cli/commands/health.js +0 -153
  49. package/src/cli/commands/init.js +0 -306
  50. package/src/cli/commands/integrityCheck.js +0 -57
  51. package/src/cli/commands/logs.js +0 -53
  52. package/src/cli/commands/openState.js +0 -44
  53. package/src/cli/commands/policyAdd.js +0 -8
  54. package/src/cli/commands/policyMode.js +0 -7
  55. package/src/cli/commands/policySign.js +0 -72
  56. package/src/cli/commands/proof.js +0 -122
  57. package/src/cli/commands/run.js +0 -342
  58. package/src/cli/commands/status.js +0 -73
  59. package/src/cli/commands/verify.js +0 -144
  60. package/src/cli/main.js +0 -176
  61. package/src/cli/parseArgs.js +0 -114
  62. package/src/exec/localExecutor.js +0 -289
  63. package/src/hooks/register.cjs +0 -505
  64. package/src/state/appendCentral.cjs +0 -87
  65. package/src/state/fileIndex.js +0 -140
  66. package/src/state/index.cjs +0 -101
  67. package/src/state/index.js +0 -65
  68. package/src/state/intentRegistry.js +0 -83
  69. package/src/state/migration.js +0 -112
  70. package/src/state/proofRunner.js +0 -246
  71. package/src/state/stateRoot.js +0 -40
  72. package/src/state/targetRegistry.js +0 -108
  73. package/src/state/workspaceId.js +0 -40
  74. package/src/state/workspaceRegistry.js +0 -65
  75. /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
- # LetterBlack LBE
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, records local evidence, and
5
- returns an allow/deny outcome before the governed action runs.
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
- LBE is not an AI model, IDE, full OS sandbox, or cloud monitor. It does not
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 project policy material. `status` shows the local central state
22
- for the current workspace; `logs` reads its event history; `proof` shows the
23
- latest proof result; and `open-state` opens the central state folder.
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
- Proof combines an intent, optional target, file index, LBE events, and
33
- `proof/latest.json`. Use `lbe proof --public` for a redacted proof summary.
34
- Non-inspectable targets can produce `WEAK_PROOF` rather than a stronger claim.
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
- # Internal source workspace
45
-
46
- This workspace is not the public npm package. It contains readable source,
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
- ```bash
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
- ## Add what you need
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
- const sb = sandbox('./workspace', { state: 'workspace' });
217
- // writes to .lbe/ inside your project root
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
- ## Integration boundary
223
-
224
- LBE is embedded directly in the user's existing application through
225
- `execute(input)` or `createLBE().execute()`. It requires no companion service
226
- or separate runtime system. The calling code submits structured action requests
227
- and remains responsible for giving the SDK-governed path exclusive authority.
228
-
229
- The Model Context Protocol integration was removed because an MCP server only
230
- offers LBE as an optional tool; an agent host with native tools can act outside
231
- the governed execution boundary.
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
- ## Agent Safe Execution
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
- Choose the integration path that matches how your agent runs:
102
+ ![LBE gate sequence Request flows through Policy, Identity, and Scope gates before reaching Action. A rejected request is routed to denial before it reaches execution.](https://unpkg.com/@letterblack/lbe-exec/assets/lbe-gates.jpg)
241
103
 
242
- ### 1. Agents you own direct integration at the dispatch point
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
- Patched APIs: `fs.writeFile`, `fs.writeFileSync`, `fs.rm`, `fs.rmSync`, `fs.unlink`, `fs.unlinkSync`, `fs.rename`, `fs.renameSync`, `fs.promises.*` variants, `child_process.spawn`, `spawnSync`, `exec`, `execSync`.
268
-
269
- ### 3. Existing npm scripts — `lbe-exec npm`
270
-
271
- Inject the hook into any npm script via `NODE_OPTIONS`:
272
-
273
- ```bash
274
- npx lbe-exec npm run agent
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
- > **Note:** `NODE_OPTIONS`-based injection is less reliable than `run-node`. Some runtimes strip or override `NODE_OPTIONS`. Use `run-node` when the agent entry point is known.
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
- ### Init non-destructive script injection
128
+ ## When a request is approved
286
129
 
287
- ```bash
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
+ ![Happy path — agent proposes action, identity confirmed, policy approved, governed write executed, audit chain extended, result returned to app.](https://unpkg.com/@letterblack/lbe-exec/assets/story-allow.jpg)
292
131
 
293
- Input:
294
- ```json
295
- { "scripts": { "agent": "node ./src/agent.js" } }
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
- Output:
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
- ## Full governance
143
+ ## When a request is blocked
323
144
 
324
- For teams, compliance workflows, or named actors with distinct permission sets:
145
+ ![Deny path — policy rejection before a governed action, shell untouched, filesystem unchanged, audit entry written, final state clean.](https://unpkg.com/@letterblack/lbe-exec/assets/story-deny.jpg)
325
146
 
326
- ```js
327
- import { createLBE, generateKeyPair, createKeyStore } from '@letterblack/lbe-core';
328
-
329
- const { secretKey, publicKey } = generateKeyPair();
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
- Zero-config alternative auto-generates keys and policy for `rootDir`:
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
- ## How it works
156
+ ## What this covers
375
157
 
376
- ```
377
- Agent
378
- │ proposes intent
379
-
380
- Invariant Gate ── key present? policy signed? keyStore loaded?
381
-
382
-
383
- 7-Gate Validation
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
- ## Public SDK surface
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
- ## Internal source API (private package only)
427
-
428
- These helpers exist in `@letterblack/lbe-core` (this package) for
429
- repository development and testing. They are **not** exported from the public
430
- `@letterblack/lbe-core` package.
431
-
432
- ### `sandbox(root, opts?)` → `{ write, read, patch, lbe }`
433
-
434
- | Option | Default | Description |
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
- ## CLI
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
- | Command | Description |
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
- ## Security model
477
-
478
- - **Ed25519 signatures** every proposal is signed; the controller verifies before any gate runs
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.