@letterblack/lbe-core 1.3.3 → 1.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,506 +1,167 @@
1
- # LetterBlack LBE
2
-
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.
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
11
-
12
- ```bash
13
- npm install @letterblack/lbe-core
14
- npx lbe init
15
- npx lbe status
16
- npx lbe logs
17
- npx lbe proof --public
18
- npx lbe open-state
19
- ```
20
-
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.
31
-
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.
41
-
42
- ---
43
-
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.
1
+ # @letterblack/lbe-core
62
2
 
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.
3
+ LBE Core is **local execution control for AI agents**.
93
4
 
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.
5
+ It evaluates file and shell actions routed through its execution boundary, records local evidence, and returns an allow/deny/proof outcome before agent work is treated as complete.
102
6
 
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:
7
+ LBE is not an AI model, IDE, full OS sandbox, cloud monitor, or hosted control plane. It only controls actions that are routed through LBE.
118
8
 
119
9
  ```text
120
- src/core/
121
- src/adapters/
122
- src/cli/
123
- scripts/
124
- test/
125
- keys/
126
- data/
127
- node_modules/
128
- *.map
10
+ Agent wants to act
11
+
12
+ LBE validates workspace, policy, target, and evidence
13
+
14
+ allow / deny / weak proof / error
15
+
16
+ Host executes only if LBE approved
17
+
18
+ Audit and proof records are written locally
129
19
  ```
130
20
 
131
21
  ---
132
22
 
133
- ## Install
134
-
135
- Internal source workspace:
23
+ ## Install and start
136
24
 
137
25
  ```bash
138
- npm install @letterblack/lbe-core
139
- ```
140
-
141
- Public users install:
142
-
143
- ```bash
144
- npm install @letterblack/lbe-core
26
+ npm install @letterblack/lbe-core
27
+ npx lbe init
28
+ npx lbe status
29
+ npx lbe logs
30
+ npx lbe proof --public
31
+ npx lbe open-state
145
32
  ```
146
33
 
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.
34
+ Requires Node.js `>= 20.9.0`.
152
35
 
153
- ---
36
+ Command summary:
154
37
 
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
- ```
38
+ | Command | Purpose |
39
+ |---|---|
40
+ | `npx lbe init` | Initialize LBE state for the current workspace |
41
+ | `npx lbe status` | Show workspace policy, state, and proof status |
42
+ | `npx lbe logs` | Show recent local LBE audit events |
43
+ | `npx lbe open-state` | Open the central local state folder for this workspace |
44
+ | `npx lbe proof` | Show the latest private proof result |
45
+ | `npx lbe proof --json` | Print the latest proof as JSON |
46
+ | `npx lbe proof --public` | Print a redacted proof safe for public sharing |
47
+ | `npx lbe status --all` | List known local workspaces from the workspace registry |
167
48
 
168
49
  ---
169
50
 
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.
51
+ ## What LBE does
194
52
 
195
- ---
53
+ LBE gives agent builders a local execution boundary:
196
54
 
197
- ## Add what you need
55
+ - validates requested file and shell actions before execution
56
+ - keeps governed actions inside the intended workspace
57
+ - records local audit evidence
58
+ - tracks intent, target, file-index snapshots, and proof results
59
+ - supports private proof and public/redacted proof output
60
+ - preserves legacy `.lbe/events.jsonl` logs while using central local state
198
61
 
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
- ```
62
+ Most systems ask only:
204
63
 
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
64
+ ```text
65
+ Did the user approve this?
209
66
  ```
210
67
 
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.
68
+ LBE asks a stricter question:
213
69
 
214
- To keep state inside the project instead (for team sharing):
215
- ```js
216
- const sb = sandbox('./workspace', { state: 'workspace' });
217
- // writes to .lbe/ inside your project root
70
+ ```text
71
+ Is this exact action allowed to reach the filesystem or terminal, and can we prove what happened?
218
72
  ```
219
73
 
220
74
  ---
221
75
 
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).
233
-
234
- ---
235
-
236
- ## Agent Safe Execution
237
-
238
- LBE Agent Safe Execution intercepts Node.js file and shell actions before they mutate the workspace.
239
-
240
- Choose the integration path that matches how your agent runs:
76
+ ## Local state and proof
241
77
 
242
- ### 1. Agents you own direct integration at the dispatch point
78
+ LBE keeps state locally in a central per-user state folder. Each workspace has a stable workspace ID and its own event log.
243
79
 
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.
80
+ In v1.3, an existing `.lbe/events.jsonl` remains local fallback truth and is imported into central state once. The source file is preserved.
245
81
 
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
- ```
82
+ Proof combines:
255
83
 
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
- ```
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`
84
+ ```text
85
+ intent
86
+
87
+ target
88
+
89
+ file-index before action
90
+
91
+ LBE audit event
92
+
93
+ file-index after action
94
+
95
+ proof/latest.json
96
+ ```
97
+
98
+ Proof results:
99
+
100
+ | Result | Meaning |
101
+ |---|---|
102
+ | `PASS` | Evidence is complete and actual changes match declared intent |
103
+ | `FAIL` | Evidence violates intent, policy, or expected file changes |
104
+ | `WEAK_PROOF` | Target evidence was uncertain or required user confirmation |
270
105
 
271
- Inject the hook into any npm script via `NODE_OPTIONS`:
106
+ Use:
272
107
 
273
108
  ```bash
274
- npx lbe-exec npm run agent
109
+ npx lbe proof --public
275
110
  ```
276
111
 
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.
112
+ for a redacted proof summary. Public proof redacts private paths, raw internal IDs, full diffs, hashes, and sensitive failure details.
282
113
 
283
114
  ---
284
115
 
285
- ### Init — non-destructive script injection
286
-
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.
292
-
293
- Input:
294
- ```json
295
- { "scripts": { "agent": "node ./src/agent.js" } }
296
- ```
297
-
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
- ```
116
+ ## What ships
310
117
 
311
- ### Status and audit
118
+ The npm package ships the packaged runtime boundary, not the private source tree.
312
119
 
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
120
+ ```text
121
+ bin/lbe.js CLI shim
122
+ dist/cli/lbe.js Bundled CLI runtime
123
+ dist/hooks/register.cjs Hook preload runtime
124
+ dist/state/index.cjs Packaged CJS state resolver
125
+ dist/state/appendCentral.cjs Packaged central JSONL append helper
126
+ README.md
127
+ Release-README.md
128
+ CHANGELOG.md
129
+ LICENSE
130
+ package.json
316
131
  ```
317
132
 
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.
133
+ The npm package must not include private implementation folders such as `src/core/**`, tests, local `.lbe/**` state, AppData state, diagnostic helpers, private keys, or workspace-local proof artifacts.
319
134
 
320
135
  ---
321
136
 
322
- ## Full governance
323
-
324
- For teams, compliance workflows, or named actors with distinct permission sets:
325
-
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
- ```
363
-
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
- ```
137
+ ## Limits
371
138
 
372
- ---
139
+ LBE controls only actions routed through its execution boundary.
373
140
 
374
- ## How it works
141
+ It does not provide:
375
142
 
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
- ```
143
+ - kernel-level process isolation
144
+ - network-egress control
145
+ - multi-tenant separation
146
+ - hosted monitoring
147
+ - universal control over tools outside LBE's execution boundary
398
148
 
399
- The controller is the only authority. Adapters execute they do not decide.
149
+ Central writes are best-effort. Local logs remain local.
400
150
 
401
151
  ---
402
152
 
403
- ## Public SDK surface
404
-
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
- ```
153
+ ## Release status
423
154
 
424
- ---
155
+ Current aligned release:
425
156
 
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';
157
+ ```text
158
+ @letterblack/lbe-core@1.3.3
465
159
  ```
466
160
 
467
- ## CLI
468
-
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 |
473
-
474
- ---
475
-
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).
161
+ Earlier `1.3.0`, `1.3.1`, and `1.3.2` builds are superseded by `1.3.3`.
501
162
 
502
163
  ---
503
164
 
504
- ## License
165
+ ## One-sentence summary
505
166
 
506
- MIT LetterBlack 2026
167
+ LBE Core does not make the agent smarter. It makes the agent's execution path controlled, evidence-backed, and locally auditable.