@letterblack/lbe-exec 1.2.10 → 1.2.11
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 +96 -139
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,133 +1,19 @@
|
|
|
1
1
|
# @letterblack/lbe-exec
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
LBE puts a local policy gate between what an AI agent proposes and what the system actually executes. Every action — file write, shell command, anything — is validated locally before it runs. No cloud service. No daemon.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
> Use `@letterblack/lbe-sdk` if you only need validation decisions inside your own tool.
|
|
5
|
+
`lbe-exec` is the full in-process controller. It handles signing, execution, and auditing for you — your agent code just calls `lbe.writeFile()` or `lbe.runShell()`.
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
through a local validation gate before it can execute. One package, any agent,
|
|
10
|
-
zero cloud dependency, no daemon required.
|
|
7
|
+
> **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.
|
|
11
8
|
|
|
12
9
|
---
|
|
13
10
|
|
|
14
|
-
##
|
|
11
|
+
## Which package do you need?
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
and they will, the moment they are given a reason to. The host is the only
|
|
18
|
-
thing standing between a plausible-looking request and irreversible damage.
|
|
19
|
-
|
|
20
|
-
That is not enough.
|
|
21
|
-
|
|
22
|
-
`@letterblack/lbe-exec` puts a deterministic local gate between what the agent
|
|
23
|
-
proposes and what the system actually executes — fully in-process, no cloud
|
|
24
|
-
dependency, no daemon required.
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## How every request travels
|
|
29
|
-
|
|
30
|
-

|
|
31
|
-
|
|
32
|
-
Every request the agent produces enters a 7-gate pipeline. A failure at any
|
|
33
|
-
gate returns a structured denial — the remaining gates are not evaluated.
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
-
[1] Schema required fields and structural validity
|
|
37
|
-
↓
|
|
38
|
-
[2] Timestamp permitted clock-skew window (±10 minutes)
|
|
39
|
-
↓
|
|
40
|
-
[3] Key lifecycle trusted key, active, not expired
|
|
41
|
-
↓
|
|
42
|
-
[4] Signature Ed25519 request authenticity (signed locally, no network)
|
|
43
|
-
↓
|
|
44
|
-
[5] Rate limit per-requester sliding-window limit
|
|
45
|
-
↓
|
|
46
|
-
[6] Nonce single-use replay protection
|
|
47
|
-
↓
|
|
48
|
-
[7] Policy configured authorization (deny-wins)
|
|
49
|
-
↓
|
|
50
|
-
allow / deny / error — structured result returned to host
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
The executor signs every request with a host-held key before validation.
|
|
54
|
-
No key material leaves the process.
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
|
|
58
|
-
## When a request is approved
|
|
59
|
-
|
|
60
|
-

|
|
61
|
-
|
|
62
|
-
When a request clears every gate:
|
|
63
|
-
|
|
64
|
-
1. The agent calls a convenience method — `lbe.writeFile()`, `lbe.runShell()`, etc.
|
|
65
|
-
2. The executor constructs and signs the request locally with a host-held Ed25519 key.
|
|
66
|
-
3. All seven gates pass. The project policy approves the action.
|
|
67
|
-
4. The write or command executes inside the configured project root.
|
|
68
|
-
5. The audit chain is extended — every approved action appends a hash-linked
|
|
69
|
-
entry to `.lbe/audit.jsonl`, permanently verifiable, impossible to silently remove.
|
|
70
|
-
6. A structured result returns: whether it succeeded, which rules matched, and
|
|
71
|
-
the audit entry identifier.
|
|
72
|
-
|
|
73
|
-
The application stays in control. The executor decides whether the action was
|
|
74
|
-
permitted and hands the answer back.
|
|
75
|
-
|
|
76
|
-
---
|
|
77
|
-
|
|
78
|
-
## When a request is blocked
|
|
79
|
-
|
|
80
|
-

|
|
81
|
-
|
|
82
|
-
When a request fails any gate:
|
|
83
|
-
|
|
84
|
-
1. The agent attempts an action — whether by mistake, misconfiguration,
|
|
85
|
-
or a deliberate bypass attempt.
|
|
86
|
-
2. The policy gate closes immediately. The request is denied before any adapter
|
|
87
|
-
is reached.
|
|
88
|
-
3. The shell is untouched. The filesystem is unchanged. Nothing that should not
|
|
89
|
-
have happened, happened.
|
|
90
|
-
4. The denial is written to the immutable audit log — chain sealed, evidence
|
|
91
|
-
preserved.
|
|
92
|
-
5. The final state is clean, verifiable, and consistent.
|
|
93
|
-
|
|
94
|
-
No partial execution. No silent failures. Denial is a first-class outcome, not
|
|
95
|
-
an error.
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
|
|
99
|
-
## Policy — who writes the rules
|
|
100
|
-
|
|
101
|
-
Only the host application writes policy. Agents may propose a rule — the
|
|
102
|
-
proposal is returned as a plain object for the host to review. Until the host
|
|
103
|
-
explicitly accepts and writes it, the proposal has no effect on any gate.
|
|
104
|
-
|
|
105
|
-
This separation is intentional. An agent that can write its own policy rules
|
|
106
|
-
is an agent that can grant itself permission.
|
|
107
|
-
|
|
108
|
-
---
|
|
109
|
-
|
|
110
|
-
## What this covers
|
|
111
|
-
|
|
112
|
-
| Threat | Gate |
|
|
13
|
+
| I want… | Package |
|
|
113
14
|
|---|---|
|
|
114
|
-
|
|
|
115
|
-
|
|
|
116
|
-
| Tampered or expired key | Identity — key lifecycle |
|
|
117
|
-
| Excessive requests | Identity — rate limit |
|
|
118
|
-
| Action not permitted by project policy | Policy — deny-wins evaluation |
|
|
119
|
-
| Unauthorized shell command | Scope — explicit command allowlist |
|
|
120
|
-
| Injected payload (eval, exec, __proto__) | Content scan before pipeline |
|
|
121
|
-
|
|
122
|
-
---
|
|
123
|
-
|
|
124
|
-
## Observer mode — start here
|
|
125
|
-
|
|
126
|
-
Not ready to block? Start in observer mode. Every request is fully validated
|
|
127
|
-
and logged exactly as it would be in enforcement — but nothing is blocked.
|
|
128
|
-
|
|
129
|
-
Watch what the agent is doing before you decide what to deny. Your rules take
|
|
130
|
-
effect the moment you switch to enforcement.
|
|
15
|
+
| LBE to handle file writes and shell commands for me (full controller) | `@letterblack/lbe-exec` ← you are here |
|
|
16
|
+
| Just the allow/deny decision — I'll execute it myself | `@letterblack/lbe-sdk` |
|
|
131
17
|
|
|
132
18
|
---
|
|
133
19
|
|
|
@@ -138,39 +24,36 @@ npm install @letterblack/lbe-exec
|
|
|
138
24
|
npx lbe-exec init
|
|
139
25
|
```
|
|
140
26
|
|
|
141
|
-
`npx lbe-exec init`
|
|
142
|
-
mode, generates `CLAUDE.md` and `.github/copilot-instructions.md` so every AI
|
|
143
|
-
agent automatically discovers and follows governance, and creates
|
|
144
|
-
`.lbe/AGENT_CONTRACT.md` as a machine-readable contract.
|
|
27
|
+
`npx lbe-exec init` creates `lbe.policy.json` in observer mode, generates `CLAUDE.md` and `.github/copilot-instructions.md` so AI agents automatically discover and follow governance, and writes `.lbe/AGENT_CONTRACT.md` as a machine-readable contract.
|
|
145
28
|
|
|
146
29
|
Requires Node.js ≥ 20.9.0.
|
|
147
30
|
|
|
148
31
|
---
|
|
149
32
|
|
|
150
|
-
##
|
|
33
|
+
## Quick start
|
|
151
34
|
|
|
152
35
|
```js
|
|
153
36
|
import { createLocalExecutor } from '@letterblack/lbe-exec';
|
|
154
37
|
|
|
155
38
|
const lbe = createLocalExecutor({ rootDir: process.cwd() });
|
|
156
39
|
|
|
157
|
-
// Every call routes through the full 7-gate pipeline
|
|
40
|
+
// Every call routes through the full 7-gate pipeline automatically
|
|
158
41
|
await lbe.writeFile('output/report.md', content);
|
|
159
42
|
await lbe.readFile('src/config.json');
|
|
160
43
|
await lbe.patchFile('src/index.js', patch);
|
|
161
44
|
await lbe.deleteFile('tmp/scratch.txt');
|
|
162
45
|
await lbe.runShell('node', ['scripts/build.js']);
|
|
163
46
|
|
|
164
|
-
// Result shape
|
|
165
|
-
const result = await lbe.writeFile('output/result.md', data);
|
|
47
|
+
// Result shape — same for every method
|
|
166
48
|
// { ok: true, decision: 'allow', executed: true, auditId: '...' }
|
|
167
49
|
// { ok: false, decision: 'deny', executed: false, error: { code, message } }
|
|
168
50
|
```
|
|
169
51
|
|
|
170
|
-
No knowledge of the pipeline, request format, or policy internals required.
|
|
171
|
-
|
|
52
|
+
No knowledge of the pipeline, request format, or policy internals required. All signing, validation, and auditing happens automatically.
|
|
53
|
+
|
|
54
|
+
---
|
|
172
55
|
|
|
173
|
-
|
|
56
|
+
## Options
|
|
174
57
|
|
|
175
58
|
```js
|
|
176
59
|
const lbe = createLocalExecutor({
|
|
@@ -184,7 +67,11 @@ const lbe = createLocalExecutor({
|
|
|
184
67
|
});
|
|
185
68
|
```
|
|
186
69
|
|
|
187
|
-
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Policy management
|
|
73
|
+
|
|
74
|
+
Only the host application writes policy. Agents may propose a rule — the proposal is returned as a plain object for the host to review. Until the host explicitly accepts and writes it, the proposal has no effect.
|
|
188
75
|
|
|
189
76
|
```js
|
|
190
77
|
// Propose a rule — returns an object for the host to review, writes nothing
|
|
@@ -207,16 +94,20 @@ lbe.audit.verify();
|
|
|
207
94
|
|
|
208
95
|
---
|
|
209
96
|
|
|
210
|
-
##
|
|
97
|
+
## Observer mode — start here
|
|
98
|
+
|
|
99
|
+
Not ready to block? Start in observer mode. Every request is fully validated and logged exactly as it would be in enforcement — but nothing is blocked. Watch what the agent is doing before you decide what to deny.
|
|
211
100
|
|
|
212
101
|
```bash
|
|
213
102
|
npx lbe-exec init # create lbe.policy.json in observer mode
|
|
214
|
-
npx lbe-exec status # show mode, rule count, and audit entry count
|
|
215
103
|
npx lbe-exec enforce # switch to blocking
|
|
216
104
|
npx lbe-exec observe # switch back to advisory
|
|
217
|
-
npx lbe-exec policy # list active rules
|
|
218
105
|
```
|
|
219
106
|
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## CLI reference
|
|
110
|
+
|
|
220
111
|
| Command | Purpose |
|
|
221
112
|
|---|---|
|
|
222
113
|
| `npx lbe-exec init` | Bootstrap governance — policy, keys, agent files |
|
|
@@ -228,6 +119,74 @@ npx lbe-exec policy # list active rules
|
|
|
228
119
|
|
|
229
120
|
---
|
|
230
121
|
|
|
122
|
+
## How the gate pipeline works
|
|
123
|
+
|
|
124
|
+

|
|
125
|
+
|
|
126
|
+
Every request enters a 7-gate pipeline. A failure at any gate returns a structured denial — the remaining gates are not evaluated.
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
[1] Schema required fields and structural validity
|
|
130
|
+
↓
|
|
131
|
+
[2] Timestamp permitted clock-skew window (±10 minutes)
|
|
132
|
+
↓
|
|
133
|
+
[3] Key lifecycle trusted key, active, not expired
|
|
134
|
+
↓
|
|
135
|
+
[4] Signature Ed25519 request authenticity (signed locally, no network)
|
|
136
|
+
↓
|
|
137
|
+
[5] Rate limit per-requester sliding-window limit
|
|
138
|
+
↓
|
|
139
|
+
[6] Nonce single-use replay protection
|
|
140
|
+
↓
|
|
141
|
+
[7] Policy configured authorization (deny-wins)
|
|
142
|
+
↓
|
|
143
|
+
allow / deny / error — structured result returned to host
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
The executor signs every request with a host-held key before validation. No key material leaves the process.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## When a request is approved
|
|
151
|
+
|
|
152
|
+

|
|
153
|
+
|
|
154
|
+
1. The agent calls a convenience method — `lbe.writeFile()`, `lbe.runShell()`, etc.
|
|
155
|
+
2. The executor constructs and signs the request locally with a host-held Ed25519 key.
|
|
156
|
+
3. All seven gates pass. The project policy approves the action.
|
|
157
|
+
4. The write or command executes inside the configured project root.
|
|
158
|
+
5. The audit chain is extended — every approved action appends a hash-linked entry to `.lbe/audit.jsonl`, permanently verifiable, impossible to silently remove.
|
|
159
|
+
6. A structured result returns: whether it succeeded, which rules matched, and the audit entry identifier.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## When a request is blocked
|
|
164
|
+
|
|
165
|
+

|
|
166
|
+
|
|
167
|
+
1. The agent attempts an action — whether by mistake, misconfiguration, or a deliberate bypass attempt.
|
|
168
|
+
2. The policy gate closes immediately. The request is denied before any adapter is reached.
|
|
169
|
+
3. The shell is untouched. The filesystem is unchanged.
|
|
170
|
+
4. The denial is written to the immutable audit log — chain sealed, evidence preserved.
|
|
171
|
+
|
|
172
|
+
No partial execution. No silent failures. Denial is a first-class outcome, not an error.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## What this covers
|
|
177
|
+
|
|
178
|
+
| Threat | Gate |
|
|
179
|
+
|---|---|
|
|
180
|
+
| Agent writes outside the project root | Scope — sandbox path check |
|
|
181
|
+
| Replayed or stale request | Identity — nonce and timestamp |
|
|
182
|
+
| Tampered or expired key | Identity — key lifecycle |
|
|
183
|
+
| Excessive requests | Identity — rate limit |
|
|
184
|
+
| Action not permitted by project policy | Policy — deny-wins evaluation |
|
|
185
|
+
| Unauthorized shell command | Scope — explicit command allowlist |
|
|
186
|
+
| Injected payload (eval, exec, __proto__) | Content scan before pipeline |
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
231
190
|
## What ships
|
|
232
191
|
|
|
233
192
|
```
|
|
@@ -251,8 +210,6 @@ Source code, tests, keys, and runtime state are not included.
|
|
|
251
210
|
|
|
252
211
|
## Limits
|
|
253
212
|
|
|
254
|
-
This package governs actions routed through its executor. It does not provide
|
|
255
|
-
kernel-level process isolation, network-egress control, multi-tenant separation,
|
|
256
|
-
or a hosted control plane.
|
|
213
|
+
This package governs actions routed through its executor. It does not provide kernel-level process isolation, network-egress control, multi-tenant separation, or a hosted control plane.
|
|
257
214
|
|
|
258
215
|
For the raw WASM runtime without a controller, see `@letterblack/lbe-sdk`.
|