@letterblack/lbe-sdk 0.4.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,47 @@
1
+ # Changelog
2
+
3
+ ## v0.4.0
4
+
5
+ ### Engine
6
+
7
+ - Governance engine rewritten as a compiled WASM binary (`runtime/lbe_engine.wasm`).
8
+ - All validation pipeline decisions (schema, timestamp skew, key lifecycle,
9
+ signature, rate-limit, nonce deduplication, policy evaluation) now execute
10
+ inside the compiled runtime — no readable JS orchestration of these rules.
11
+ - Audit hash chaining (SHA-256 of `prevHash || entry`) computed in WASM.
12
+ - Risk classification and rollback decisions computed in WASM.
13
+ - JS layer reduced to: field extraction, Ed25519 verification, file IO, adapter
14
+ dispatch, and the public `createLBE` / `sandbox` API surface.
15
+ - `dist/engine.js` added as the WASM bridge module (internal; not a public export).
16
+
17
+ ### Package
18
+
19
+ - `dist/engine.js` added to published `files`.
20
+ - `"private": true` on source repo hard-blocks accidental source publish.
21
+ - Source repository URL removed from release package metadata.
22
+ - License aligned: `SEE LICENSE IN LICENSE` (commercial, not MIT).
23
+
24
+ ### API
25
+
26
+ - Public surface unchanged: `createLBE`, `sandbox`.
27
+
28
+ ---
29
+
30
+ ## v0.3.0 — SDK Distribution
31
+
32
+ ### Added
33
+
34
+ - `@letterblack/lbe-sdk` package identity.
35
+ - Bundled SDK entry points under `dist/`.
36
+ - `lbe` CLI entry point.
37
+ - `lbe-mcp` MCP server entry point.
38
+ - TypeScript declarations.
39
+ - Local SDK package artifact.
40
+ - Public package documentation and license terms.
41
+
42
+ ### Package Scope
43
+
44
+ - Ships SDK distribution artifacts only.
45
+ - Excludes source files, tests, demos, and build tooling.
46
+ - Supports local-first agent workspace workflows, file operations, command
47
+ workflows, audit, rollback, and MCP integration.
@@ -0,0 +1,29 @@
1
+ # LBE SDK Distribution
2
+
3
+ The LBE SDK is a local-first SDK for governed AI agent file and command
4
+ workflows.
5
+
6
+ This package is intended for developers and teams that need:
7
+
8
+ - Agent workspace setup
9
+ - Governed file reads, writes, and patches
10
+ - Governed command execution
11
+ - Audit and rollback support
12
+ - MCP integration through `lbe-mcp`
13
+ - Programmatic SDK integration through `sandbox()` and `createLBE()`
14
+
15
+ ## Package Contents
16
+
17
+ The npm package includes:
18
+
19
+ - Bundled JavaScript entry points in `dist/`
20
+ - Runtime artifact in `runtime/`
21
+ - TypeScript declarations
22
+ - README, changelog, and license terms
23
+
24
+ It does not include source files, tests, demos, or build tooling.
25
+
26
+ ## Licensing
27
+
28
+ Commercial usage is governed by the package LICENSE and any separate written
29
+ agreement with LetterBlack.
package/LICENSE ADDED
@@ -0,0 +1,12 @@
1
+ Copyright (c) LetterBlack.
2
+
3
+ All rights reserved.
4
+
5
+ This commercial SDK distribution is provided only under a separate written
6
+ license, subscription, evaluation agreement, or other authorization from
7
+ LetterBlack. You may not copy, modify, redistribute, sublicense, reverse
8
+ engineer, or use this package except as permitted by that agreement or by
9
+ applicable law.
10
+
11
+ If you received this package without an applicable license or authorization,
12
+ do not use or distribute it. Contact LetterBlack for licensing terms.
package/README.md ADDED
@@ -0,0 +1,190 @@
1
+ # @letterblack/lbe-sdk
2
+
3
+ Lockstep Boundary Engine SDK for local-first AI execution governance.
4
+
5
+ Sandboxed writes. Workspace context. Audit. Rollback. MCP access.
6
+
7
+ Everything runs on your machine. No hosted service is required.
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install @letterblack/lbe-sdk
13
+ ```
14
+
15
+ Requires Node.js 20.9.0 or newer.
16
+
17
+ ## Initialize
18
+
19
+ ```bash
20
+ npx lbe init
21
+ ```
22
+
23
+ Initializes local governance settings for the current workspace so agents can
24
+ operate inside explicit project boundaries.
25
+
26
+ Run once per workspace. Re-run when the workspace structure changes.
27
+
28
+ ## Quick Start
29
+
30
+ ```js
31
+ import { sandbox } from '@letterblack/lbe-sdk';
32
+
33
+ const sb = sandbox('./workspace');
34
+
35
+ await sb.write('output.txt', 'Hello\n');
36
+ const text = await sb.read('output.txt');
37
+ ```
38
+
39
+ `sandbox()` routes reads and writes through the workspace root you provide.
40
+ Use it as the boundary for all agent-facing file operations.
41
+
42
+ ## Audit and Rollback
43
+
44
+ ```js
45
+ import { sandbox } from '@letterblack/lbe-sdk';
46
+
47
+ const sb = sandbox('./workspace', {
48
+ audit: true,
49
+ rollback: true
50
+ });
51
+
52
+ await sb.write('output.txt', 'governed write\n');
53
+ ```
54
+
55
+ Audit records and rollback state are stored locally. Use workspace-scoped
56
+ state when your team shares governance artifacts:
57
+
58
+ ```js
59
+ const sb = sandbox('./workspace', { state: 'workspace' });
60
+ ```
61
+
62
+ ## MCP Server
63
+
64
+ Add LBE governance to any MCP-compatible AI host:
65
+
66
+ ```json
67
+ {
68
+ "mcpServers": {
69
+ "lbe": {
70
+ "command": "npx",
71
+ "args": ["lbe-mcp"]
72
+ }
73
+ }
74
+ }
75
+ ```
76
+
77
+ ### Agent Tools
78
+
79
+ | Tool | Purpose |
80
+ |---|---|
81
+ | `lbe_workspace_context` | Fetch local workspace constraints before planning actions |
82
+ | `lbe_write_file` | Governed write with backup and rollback support |
83
+ | `lbe_read_file` | Governed read |
84
+ | `lbe_patch_file` | Governed append/patch |
85
+ | `lbe_shell_command` | Governed command execution through the configured allowlist |
86
+ | `lbe_health` | Verify local SDK readiness |
87
+
88
+ ## Programmatic Use
89
+
90
+ Use `createLBE()` for full SDK integration:
91
+
92
+ ```js
93
+ import { createLBE } from '@letterblack/lbe-sdk';
94
+
95
+ const lbe = createLBE({
96
+ rootDir: process.cwd()
97
+ });
98
+
99
+ const result = await lbe.execute({
100
+ actor: 'agent:sdk',
101
+ intent: 'write_file',
102
+ target: './output/report.md',
103
+ content: '# Report\n'
104
+ });
105
+
106
+ console.log(result.ok);
107
+ console.log(result.stage);
108
+ ```
109
+
110
+ ## Public API
111
+
112
+ ### `sandbox(root, opts?)`
113
+
114
+ Creates a governed workspace helper.
115
+
116
+ | Option | Default | Description |
117
+ |---|---|---|
118
+ | `audit` | `false` | Record governed operations to the local audit log |
119
+ | `rollback` | `false` | Back up before writes; restore on failure |
120
+ | `state` | `'local'` | State storage: `'local'`, `'workspace'`, or adapter |
121
+
122
+ ### `createLBE(options)`
123
+
124
+ Creates a full SDK client for application integrations.
125
+
126
+ | Option | Description |
127
+ |---|---|
128
+ | `rootDir` | Workspace root — enables automatic local setup |
129
+ | `secretKey` | Ed25519 signing key (base64). Required for execution |
130
+ | `keyStore` | Trusted key registry object |
131
+ | `policy` | Inline policy object (overrides policy file) |
132
+ | `state` | State storage mode |
133
+ | `logLevel` | Runtime log level (`DEBUG`, `INFO`, `WARN`, `ERROR`) |
134
+
135
+ `createLBE()` returns an object with:
136
+
137
+ - `execute({ actor, intent, target, content, args, transaction })` — run a governed operation
138
+ - `writeFile(target, content)` — convenience governed write
139
+ - `readFile(target)` — convenience governed read
140
+ - `exportLogs()` — return the in-memory operation log
141
+
142
+ ## CLI
143
+
144
+ | Command | Description |
145
+ |---|---|
146
+ | `npx lbe init` | Initialize local workspace governance |
147
+ | `npx lbe health` | Verify local runtime readiness |
148
+ | `npx lbe verify --in proposal.json` | Validate an execution proposal |
149
+ | `npx lbe run --in proposal.json` | Validate and execute a proposal |
150
+ | `npx lbe audit-verify` | Verify local audit chain integrity |
151
+ | `npx lbe-mcp` | Start the LBE MCP server on stdio |
152
+
153
+ ## Runtime
154
+
155
+ The governance engine ships as a compiled WASM binary (`runtime/lbe_engine.wasm`).
156
+ Validation pipeline, policy decisions, nonce deduplication, rate-limit enforcement,
157
+ audit hash chaining, risk classification, and rollback logic all execute inside
158
+ the compiled runtime. The JS layer handles file IO, adapter dispatch, and the
159
+ public API surface only.
160
+
161
+ The engine loads once on first call and is cached for the process lifetime.
162
+ No network access is required. No data leaves the machine.
163
+
164
+ ## Security Notes
165
+
166
+ LBE governs agent actions routed through the SDK. It provides local policy
167
+ enforcement, auditability, and rollback support for governed operations.
168
+
169
+ LBE does not replace OS-level sandboxing, container isolation, network egress
170
+ controls, or multi-tenant workload isolation.
171
+
172
+ ### What LBE reduces the risk of
173
+
174
+ - Unauthorized workspace modification by agent workflows
175
+ - Policy bypass caused by agent behavior drift
176
+ - Accidental destructive operations (delete, overwrite)
177
+ - Loss of visibility into agent-driven changes
178
+
179
+ ### What LBE does not replace
180
+
181
+ - Operating-system security and user permissions
182
+ - Root or administrator access controls
183
+ - Malware protection
184
+ - Container or VM isolation
185
+ - Network security controls
186
+
187
+ ## License
188
+
189
+ See [LICENSE](./LICENSE). Commercial usage requires an applicable LetterBlack
190
+ license, subscription, evaluation agreement, or other written authorization.
package/dist/cli.js ADDED
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env node
2
+ const __lbePublicOutputFilter = (() => {
3
+ const command = process.argv[2];
4
+ if (command !== "init" && command !== "health") return null;
5
+ const originalLog = console.log.bind(console);
6
+ let healthStatus = null;
7
+ console.log = (...args) => {
8
+ if (command === "health") {
9
+ try {
10
+ const parsed = JSON.parse(String(args[0]));
11
+ if (parsed && typeof parsed.status === "string") healthStatus = parsed.status;
12
+ } catch {}
13
+ }
14
+ };
15
+ process.on("exit", (code) => {
16
+ if (command === "init" && code === 0) originalLog("LBE workspace initialized.");
17
+ if (command === "health") originalLog(`LBE SDK health: ${healthStatus || (code === 0 ? "healthy" : "unhealthy")}`);
18
+ });
19
+ return true;
20
+ })();if (process.argv.includes("--help") || process.argv.includes("-h") || process.argv.length <= 2) {
21
+ console.log(`LBE SDK
22
+
23
+ Usage:
24
+ lbe <command> [options]
25
+
26
+ Commands:
27
+ init Initialize local workspace governance
28
+ health Check local SDK readiness
29
+ verify Validate an execution proposal without applying changes
30
+ dryrun Simulate a proposal without applying changes
31
+ run Run a governed proposal
32
+ audit-verify Review local audit status
33
+ help Show help
34
+
35
+ Options:
36
+ --in Input proposal file
37
+ --config Configuration file
38
+ --json JSON output
39
+ --version Show version
40
+ --help Show help
41
+
42
+ Examples:
43
+ lbe init
44
+ lbe health
45
+ lbe verify --in proposal.json
46
+ lbe dryrun --in proposal.json
47
+ lbe run --in proposal.json
48
+ lbe audit-verify
49
+
50
+ Documentation:
51
+ https://github.com/Letterblack0306/LetterBlack-Sentinel`);
52
+ process.exit(0);
53
+ }import Jt from"fs";import he from"path";import{fileURLToPath as ns}from"url";import Ut from"fs";import Je from"path";import{fileURLToPath as Wt}from"url";var Gt=Je.dirname(Wt(import.meta.url)),Ht=Je.join(Gt,"../package.json"),zt=JSON.parse(Ut.readFileSync(Ht,"utf8")).version;function Ve(e){if(e.length===0)return{command:"help",opts:{}};let t=e[0].startsWith("-")?"help":e[0],r={},i=t==="help"&&e[0].startsWith("-")?0:1;for(let s=i;s<e.length;s++)if(e[s].startsWith("--")){let o=e[s].substring(2);if(o.includes("=")){let[n,a]=o.split("=");r[n]=a}else{let n=e[s+1];!n||n.startsWith("-")?r[o]=!0:(r[o]=n,s++)}}else if(e[s].startsWith("-")){let o=e[s].substring(1),n=e[s+1];!n||n.startsWith("-")?r[o]=!0:(r[o]=n,s++)}return{command:t,opts:r}}function Se(){console.log(`
54
+ \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
55
+ \u2551 Lockstep Boundary Engine SDK \u2551
56
+ \u2551 Local-first execution governance SDK v${zt.padEnd(12)}\u2551
57
+ \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
58
+
59
+ USAGE:
60
+ lbe [command] [options]
61
+
62
+ COMMANDS:
63
+ init Initialize LBE SDK environment
64
+ verify Verify a proposal (validate, don't execute)
65
+ dryrun Validate and simulate execution (no changes)
66
+ run Validate and execute a proposal
67
+ policy-sign Sign policy and write policy signature envelope
68
+ health Run deployment/runtime health checks
69
+ integrity-check Verify controller integrity manifest
70
+ integrity-generate Generate controller integrity manifest
71
+ audit-verify Verify audit log hash-chain integrity
72
+ help Show this help message
73
+
74
+ OPTIONS:
75
+ --in Input file (JSON proposal)
76
+ --config Policy config file (default: ./config/policy.default.json)
77
+ --policy Alias for --config
78
+ --policy-sig Policy signature file (default: ./config/policy.sig.json)
79
+ --policy-state Policy monotonic state file (default: ./data/policy.state.json)
80
+ --policy-unsigned-ok Allow unsigned policy (dev-only; default: false)
81
+ --policy-key-id Signer keyId for policy-sign (default: policy-signer-v1-2026Q1)
82
+ --secret-key-file Secret key for policy-sign (default: ./keys/secret.key)
83
+ --data-dir Data directory for health checks (default: ./data)
84
+ --nonce-db Nonce DB path for health checks
85
+ --rate-db Rate-limit DB path for health checks
86
+ --keys-store Trusted keys store (default: ./config/keys.json)
87
+ --pub-key Public key for verification (Ed25519 base64)
88
+ --pub-key-file Legacy single-key file path (fallback mode)
89
+ --integrity-strict Fail verify/dryrun/run if integrity check fails
90
+ --integrity-manifest Integrity manifest path (default: ./config/integrity.manifest.json)
91
+ --manifest Manifest path override for integrity-check
92
+ --out Output path for integrity-generate
93
+ --audit Audit log file (default: ./data/audit.log.jsonl)
94
+ --json JSON output (default: true)
95
+ --fail-fast Stop at first audit integrity error (default: true)
96
+ --max Max audit entries to process (optional)
97
+ --version Show version
98
+ --help Show this help message
99
+
100
+ EXAMPLES:
101
+ lbe init
102
+ lbe verify --in proposal.json --keys-store ./config/keys.json
103
+ lbe dryrun --in proposal.json --keys-store ./config/keys.json
104
+ lbe run --in proposal.json --keys-store ./config/keys.json
105
+ lbe policy-sign --config ./config/policy.default.json --policy-sig ./config/policy.sig.json
106
+ lbe health --json true
107
+ lbe integrity-generate --out ./config/integrity.manifest.json
108
+ lbe integrity-check --integrity-strict --manifest ./config/integrity.manifest.json
109
+ lbe audit-verify --audit ./data/audit.log.jsonl
110
+ lbe verify --in proposal.json --pub-key-file ./keys/public.key
111
+
112
+ For more info, visit: https://github.com/Letterblack0306/LetterBlack-Sentinel
113
+ `)}import v from"fs";import R from"path";import kr from"readline";import xe from"tweetnacl";import{canonicalize as Be}from"json-canonicalize";function Ie(e){return Buffer.from(e,"base64")}function ve(e){return Buffer.from(e).toString("base64")}function oe({payloadObj:e,sigB64:t,pubKeyB64:r}){try{let s=Buffer.from(Be(e),"utf8"),o=Ie(t),n=Ie(r),a=xe.sign.detached.verify(new Uint8Array(s),new Uint8Array(o),new Uint8Array(n));return{valid:a,message:a?"Signature verified":"Signature verification failed"}}catch(s){return{valid:!1,message:`Signature verification error: ${s.message}`}}}function Ye(){let e=xe.sign.keyPair();return{publicKey:ve(e.publicKey),secretKey:ve(e.secretKey)}}function Ue({payloadObj:e,secretKeyB64:t}){try{let r=Buffer.from(Be(e),"utf8"),s=Ie(t),o=xe.sign.detached(new Uint8Array(r),new Uint8Array(s));return{signature:ve(o),error:null}}catch(r){return{signature:null,error:`Signing failed: ${r.message}`}}}import Ge from"fs";import Zt from"path";import We from"fs";import Qt from"path";var Xt=/^[A-Za-z0-9:_-]{3,128}$/;function Ee(e){return typeof e=="string"&&Xt.test(e)&&e!=="default"}function W(e){let t=Qt.resolve(e);if(!We.existsSync(t))return{ok:!1,reason:"KEY_STORE_MISSING",message:`Key store not found: ${t}`,store:null};try{let r=We.readFileSync(t,"utf-8"),s=JSON.parse(r);return!s||typeof s!="object"||typeof s.trustedKeys!="object"?{ok:!1,reason:"KEY_STORE_INVALID",message:`Invalid key store format: ${t}`,store:null}:{ok:!0,reason:null,message:"Key store loaded",store:s}}catch(r){return{ok:!1,reason:"KEY_STORE_INVALID_JSON",message:`Unable to parse key store: ${r.message}`,store:null}}}function ne({keyStore:e,keyId:t,requesterId:r,now:s=new Date}){if(!e||typeof e!="object")return{ok:!1,reason:"KEY_STORE_UNAVAILABLE",message:"Trusted key store is not available",publicKey:null};if(!Ee(t))return{ok:!1,reason:"KEY_ID_INVALID",message:`Invalid keyId '${t}'. Use versioned key IDs like 'agent:gpt-v1-2026Q1'`,publicKey:null};let o=e.trustedKeys?.[t];if(!o)return{ok:!1,reason:"KEY_NOT_TRUSTED",message:`Key '${t}' is not in trusted key store`,publicKey:null};if(o.deprecated)return{ok:!1,reason:"KEY_DEPRECATED",message:`Key '${t}' is deprecated`,publicKey:null};if(o.requesterId&&o.requesterId!==r)return{ok:!1,reason:"KEY_REQUESTER_MISMATCH",message:`Key '${t}' is not authorized for requester '${r}'`,publicKey:null};let n=o.notBefore||o.validFrom,a=o.expiresAt||o.validUntil;if(typeof n!="string"||typeof a!="string")return{ok:!1,reason:"KEY_LIFECYCLE_INVALID",message:`Key '${t}' must define lifecycle fields 'notBefore' and 'expiresAt'`,publicKey:null};let i=new Date(n),c=new Date(a);return Number.isNaN(i.getTime())||Number.isNaN(c.getTime())?{ok:!1,reason:"KEY_LIFECYCLE_INVALID",message:`Key '${t}' has invalid lifecycle timestamp(s)`,publicKey:null}:i>=c?{ok:!1,reason:"KEY_LIFECYCLE_INVALID",message:`Key '${t}' has notBefore >= expiresAt`,publicKey:null}:s<i?{ok:!1,reason:"KEY_NOT_YET_VALID",message:`Key '${t}' not valid until ${n}`,publicKey:null}:s>c?{ok:!1,reason:"KEY_EXPIRED",message:`Key '${t}' expired on ${a}`,publicKey:null}:!o.publicKey||typeof o.publicKey!="string"?{ok:!1,reason:"KEY_CONFIG_INVALID",message:`Trusted key '${t}' is missing publicKey`,publicKey:null}:{ok:!0,reason:null,message:"Trusted key resolved",publicKey:o.publicKey}}function ie({policyObj:e,secretKeyB64:t,keyId:r}){let s=Ue({payloadObj:e,secretKeyB64:t});return s.error?{ok:!1,reason:"POLICY_SIGNATURE_CREATE_FAILED",message:s.error,envelope:null}:{ok:!0,reason:null,message:"Policy signature created",envelope:{alg:"ed25519",keyId:r,sig:s.signature,createdAt:Math.floor(Date.now()/1e3)}}}function G({policyObj:e,keyStore:t,policySigPath:r="./config/policy.sig.json",allowUnsigned:s=!1}){let o=Zt.resolve(r);if(!Ge.existsSync(o))return s?{ok:!0,skipped:!0,reason:"POLICY_SIGNATURE_SKIPPED",message:`Policy signature not found: ${o} (allowed by flag)`}:{ok:!1,skipped:!1,reason:"POLICY_SIGNATURE_MISSING",message:`Policy signature file not found: ${o}`};let n;try{n=JSON.parse(Ge.readFileSync(o,"utf-8"))}catch(c){return{ok:!1,skipped:!1,reason:"POLICY_SIGNATURE_INVALID",message:`Unable to parse policy signature file: ${c.message}`}}if(!n||n.alg!=="ed25519"||typeof n.keyId!="string"||typeof n.sig!="string")return{ok:!1,skipped:!1,reason:"POLICY_SIGNATURE_INVALID",message:"Policy signature envelope must include {alg, keyId, sig}"};if(!t)return{ok:!1,skipped:!1,reason:"POLICY_SIGNER_KEY_STORE_UNAVAILABLE",message:"Trusted key store is required for policy signature verification"};let a=ne({keyStore:t,keyId:n.keyId,requesterId:void 0});if(!a.ok)return{ok:!1,skipped:!1,reason:"POLICY_SIGNER_NOT_TRUSTED",message:a.message};let i=oe({payloadObj:e,sigB64:n.sig,pubKeyB64:a.publicKey});return i.valid?{ok:!0,skipped:!1,reason:null,message:"Policy signature verified",keyId:n.keyId}:{ok:!1,skipped:!1,reason:"POLICY_SIGNATURE_INVALID",message:i.message}}import we from"fs";import C from"path";var er=[{file:"package.json",type:"node"},{file:"pyproject.toml",type:"python"},{file:"requirements.txt",type:"python"},{file:"go.mod",type:"go"},{file:"Cargo.toml",type:"rust"},{file:"pom.xml",type:"java"},{file:"build.gradle",type:"java"},{file:"build.gradle.kts",type:"java"},{file:"Dockerfile",type:"docker"},{file:"docker-compose.yml",type:"docker"},{dir:".github/workflows",type:"ci"},{file:".gitlab-ci.yml",type:"ci"},{dir:".circleci",type:"ci"},{file:"Jenkinsfile",type:"ci"},{file:".travis.yml",type:"ci"}],Ae=["node","python","go","rust","java"],tr={source:["src","lib","app","pages","components","core","api","server","client","pkg","cmd"],generated:["dist","build",".next","out","coverage","target",".cache","__pycache__",".turbo"],tests:["test","tests","__tests__","spec","e2e"],docs:["docs","doc","documentation"]},Qe=[".env",".env.*","keys/**","secrets/**","*.key","*.pem","*.p12","*.pfx","*.crt"],rr=["node_modules/**",".git/**"],sr={node:["package-lock.json","yarn.lock","pnpm-lock.yaml"],python:["Pipfile.lock","poetry.lock"],go:["go.sum"],rust:["Cargo.lock"],java:["gradle/wrapper/**"],docker:[],ci:[],generic:[]},He={node:["package.json","tsconfig*.json","jest.config.*","vite.config.*","next.config.*","webpack.config.*",".eslintrc*",".eslint.config.*",".prettierrc*","babel.config.*"],python:["pyproject.toml","setup.py","setup.cfg","tox.ini","pytest.ini","mypy.ini",".flake8",".pylintrc","Pipfile"],go:["go.mod",".golangci.yml",".golangci.yaml"],rust:["Cargo.toml","rust-toolchain.toml","clippy.toml",".rustfmt.toml"],java:["pom.xml","build.gradle","build.gradle.kts","gradle.properties","settings.gradle","settings.gradle.kts"],docker:["Dockerfile","docker-compose.yml",".dockerignore"],ci:[".gitlab-ci.yml","Jenkinsfile",".travis.yml"],generic:["Makefile","CMakeLists.txt","meson.build"]},or=[".editorconfig",".nvmrc",".node-version",".python-version"],nr=["config",".github",".gitlab",".circleci",".vscode"],ir={node:"dependency and build config",python:"package and environment config",go:"module definition",rust:"crate manifest",java:"build definition",docker:"container config",ci:"pipeline definition",generic:"project config"},ar={node:"package manager",python:"dependency resolver",go:"module checksums",rust:"dependency resolver",java:"Gradle wrapper"},cr=["composer.json","Gemfile","mix.exs","pubspec.yaml","Package.swift","project.clj","build.sbt","stack.yaml","deno.json","deno.jsonc","Podfile"],lr=["composer.lock","Gemfile.lock","mix.lock","pubspec.lock","Package.resolved"],dr=[".csproj",".fsproj",".sln",".cabal"];function D(e){return we.existsSync(e)}function ze(e,t){return t.filter(r=>D(C.join(e,r))).map(r=>`${r}/**`)}function ur(e){let t=C.join(e,".gitignore");return D(t)?we.readFileSync(t,"utf8").split(`
114
+ `).map(r=>r.trim()).filter(r=>r&&!r.startsWith("#")&&!r.startsWith("!")).map(r=>r.endsWith("/")?r+"**":r):[]}function q(e){return e.filter((t,r,s)=>t&&s.indexOf(t)===r)}function fr(e){let t=new Set,r=[];for(let s of er){if(t.has(s.type))continue;let o=C.join(e,s.file||s.dir);D(o)&&(t.add(s.type),r.push(s.type))}return r.length>0?r:["generic"]}function pr(e){return Ae.find(t=>e.includes(t))??"generic"}function mr(e){let t=cr.filter(s=>D(C.join(e,s))),r=lr.filter(s=>D(C.join(e,s)));try{let s=we.readdirSync(e);for(let o of s)dr.some(n=>o.endsWith(n))&&t.push(o)}catch{}return{manifests:t,lockfiles:r}}function yr(e,t){let r={};for(let[o,n]of Object.entries(tr))r[o]=ze(e,n);r.secrets=Qe.filter(o=>{let n=o.split("/")[0].replace(/\*.*/,"");return n.includes("*")||D(C.join(e,n))});let s=q(t.flatMap(o=>He[o]||He.generic).concat(or));if(r.config=q([...s.filter(o=>!o.includes("*")&&!o.endsWith("/**")&&D(C.join(e,o))),...s.filter(o=>o.endsWith("/**")&&D(C.join(e,o.replace("/**","")))),...ze(e,nr)]),r.lockfiles=q(t.flatMap(o=>sr[o]||[]).filter(o=>{let n=o.replace(/\*.*/,"").split("/")[0];return n.includes("*")||D(C.join(e,n))})),!t.some(o=>Ae.includes(o))){let o=mr(e);r.config=q([...r.config,...o.manifests]),r.lockfiles=q([...r.lockfiles,...o.lockfiles])}return r}function gr(e,t,r){let s={};if(s.structure="Preserve the existing folder structure. Add new files within established directories. Do not create top-level directories, reorganize, or rename existing folders.",r.source.length>0&&(s.source=`Source code lives in ${r.source.join(", ")}. Make feature changes and bug fixes here only.`),s.secrets=`Never propose changes to credential or key files (${Qe.slice(0,4).join(", ")} \u2026). These are never task targets regardless of the instruction.`,r.generated.length>0&&(s.generated=`${r.generated.join(", ")} contain generated output. Modify the source files that produce them; never write to generated directories directly.`),r.config.length>0){let o=e.filter(c=>Ae.includes(c)),n=o.length===1?ir[o[0]]:"project configuration",a=r.config.slice(0,5).join(", "),i=r.config.length>5?" and related files":"";s.config=`Treat ${a}${i} as ${n} files. Do not modify them unless the task explicitly requires a configuration or dependency change.`}if(r.tests.length>0&&(s.tests=`Test files in ${r.tests.join(", ")} validate behavior. Update them only when the behavior they cover changes.`),r.lockfiles?.length>0){let o=ar[t]||"tooling",n=r.lockfiles.slice(0,3).join(", ");s.lockfiles=`${n} are generated by the ${o}. Never edit them directly.`}if(t==="generic"){let o=r.config.filter(n=>!n.endsWith("/**"));o.length>0?s.unknown=`This project uses an unrecognized toolchain. Treat ${o.slice(0,3).join(", ")} as dependency/manifest files. Do not modify them unless the task explicitly requires a dependency change.`:s.unknown="This project uses an unrecognized toolchain. Do not assume standard source layouts, dependency files, or build conventions apply. Confirm any structural assumption before acting."}return e.includes("docker")&&(s.docker="Dockerfile and docker-compose.yml define the container environment. Treat them as infrastructure config \u2014 only modify when the task explicitly involves container or environment changes."),e.includes("ci")&&(s.ci="CI config files (.github/**, .gitlab-ci.yml, etc.) define the build and deployment pipeline. Do not modify them unless the task explicitly involves CI/CD changes."),s}function hr(e,t){let r=q([...e.source,...e.docs,...e.tests]),s=[...e.config],o=q([...e.secrets,...e.generated,...e.lockfiles||[],...rr,...t.filter(n=>n.endsWith("/**")).slice(0,8)]);return{allow:r.length>0?r:["src/**"],approval:s.length>0?s:[],deny:o}}function Xe(e){let t=C.resolve(e||process.cwd()),r=fr(t),s=pr(r),o=yr(t,r),n=ur(t),a=gr(r,s,o),i=hr(o,n);return{projectTypes:r,primaryType:s,surfaces:o,semantics:a,enforcement:i}}function Ze(e,t,r){let s=[],o=Array.isArray(e)?e.join(" + "):e;s.push(`Detected: ${o}`),s.push(""),s.push("Agent semantics:");for(let[,n]of Object.entries(t))s.push(` - ${n}`);return s.push(""),s.push("Enforcement:"),r.allow.length&&s.push(` allow: ${r.allow.join(", ")}`),r.approval.length&&s.push(` approval: ${r.approval.join(", ")}`),r.deny.length&&s.push(` deny: ${r.deny.slice(0,6).join(", ")}${r.deny.length>6?" \u2026":""}`),s.join(`
115
+ `)}function Sr(e){return process.stdin.isTTY?new Promise(t=>{let r=kr.createInterface({input:process.stdin,output:process.stdout});r.question(e,s=>{r.close(),t(s.trim().toLowerCase())})}):Promise.resolve("y")}function Ir(e){return{...e,deny:[...new Set([...e.deny,...e.approval,"*.json","config/**"])],approval:[]}}function vr(e){return{...e,approval:[]}}function xr(e){let t=new Date().toISOString(),r=new Date(Date.now()+4320*60*60*1e3).toISOString(),s="agent:gpt-v1-2026Q1",o="policy-signer-v1-2026Q1";for(let d of["config","keys","data"])v.mkdirSync(R.join(e,d),{recursive:!0});let n={"data/nonce.db.json":JSON.stringify({entries:[]},null,2),"data/rate-limit.db.json":JSON.stringify({entries:[]},null,2),"data/policy.state.json":JSON.stringify({schemaVersion:"1",lastAccepted:null,updatedAt:null},null,2),"data/audit.log.jsonl":""};for(let[d,k]of Object.entries(n)){let g=R.join(e,d);v.existsSync(g)||v.writeFileSync(g,k)}let a=R.join(e,"keys"),i=R.join(a,"public.key"),c=R.join(a,"secret.key"),l,u;if(v.existsSync(i)&&v.existsSync(c))l=v.readFileSync(i,"utf8").trim(),u=v.readFileSync(c,"utf8").trim();else{let d=Ye();l=d.publicKey,u=d.secretKey,v.writeFileSync(i,l),v.writeFileSync(c,u,{mode:384})}let p=R.join(e,"config/keys.json"),f=v.existsSync(p)?JSON.parse(v.readFileSync(p,"utf8")):{schemaVersion:"1",defaultKeyId:s,trustedKeys:{}};for(let d of[s,o])f.trustedKeys[d]||(f.trustedKeys[d]={publicKey:l,notBefore:t,expiresAt:r,validFrom:t,validUntil:r,deprecated:!1});f.defaultKeyId=s,v.writeFileSync(p,JSON.stringify(f,null,2));let m=R.join(e,"config/policy.default.json"),h;v.existsSync(m)?h=JSON.parse(v.readFileSync(m,"utf8")):(h={default:"DENY",version:"1.0.0",createdAt:t,security:{maxClockSkewSec:600,maxPolicyCreatedAtSkewSec:31536e3,defaultRateLimit:{windowSec:60,maxRequests:30}},requesters:{"agent:gpt":{allowAdapters:["noop","shell"],allowCommands:["RUN_SHELL"],rateLimit:{windowSec:60,maxRequests:30},filesystem:{roots:[e],denyPatterns:["**/.git/**","**/secrets/**","**/*.key"]},exec:{allowCmds:["ls","node","python","echo"],denyCmds:["rm","chmod","chown","curl","wget","su","sudo"]}}}},v.writeFileSync(m,JSON.stringify(h,null,2)));let y=ie({policyObj:h,secretKeyB64:u,keyId:o});return y.ok&&v.writeFileSync(R.join(e,"config/policy.sig.json"),JSON.stringify(y.envelope,null,2)),{defaultKeyId:s,secretKeyB64:u,publicKeyB64:l}}async function et(e={}){let t=process.cwd(),r=e.yes||e.y||!process.stdin.isTTY,s=R.join(t,"lbe.workspace.json");console.log(`
116
+ Scanning workspace...
117
+ `);let{projectTypes:o,primaryType:n,semantics:a,enforcement:i}=Xe(t);console.log(Ze(o,a,i)),console.log("");let c=i;if(!r){let u=await Sr("Accept? [Y = accept / s = strict / r = relaxed / n = cancel] ");if(u==="n")return console.log("Cancelled."),{success:!1};u==="s"&&(c=Ir(i)),u==="r"&&(c=vr(i))}let l={lbe:!0,version:"0.4.0",state:"local",projectTypes:o,primaryType:n,semantics:a,enforcement:c};return v.writeFileSync(s,JSON.stringify(l,null,2)),console.log("\u2713 Wrote lbe.workspace.json"),xr(t),console.log(`\u2713 Keys and policy ready
118
+ `),console.log("Done. Agents that detect lbe.workspace.json will operate within these boundaries."),console.log(`Run npx lbe doctor at any time to review or update the contract.
119
+ `),{success:!0,contract:l}}import Oe from"fs";import z from"path";import tt from"fs";import ot from"path";import{fileURLToPath as Er}from"url";var wr=ot.dirname(Er(import.meta.url)),be=ot.join(wr,"../runtime/lbe_engine.wasm"),rt={0:{allowed:!0,reason:null,message:"Policy check passed"},1:{allowed:!1,reason:"POLICY_NOT_CONFIGURED",message:"No policy configured"},2:{allowed:!1,reason:"REQUESTER_NOT_ALLOWED",message:"Requester not in policy"},3:{allowed:!1,reason:"COMMAND_NOT_ALLOWED",message:"Command not allowed for requester"},4:{allowed:!1,reason:"ADAPTER_NOT_ALLOWED",message:"Adapter not allowed"},5:{allowed:!1,reason:"NO_FILESYSTEM_ROOTS_DEFINED",message:"No filesystem roots defined for requester"},6:{allowed:!1,reason:"CWD_OUTSIDE_ALLOWED_ROOT",message:"Path not under allowed roots"},7:{allowed:!1,reason:"PATH_DENIED_BY_PATTERN",message:"Path matches deny pattern"},8:{allowed:!1,reason:"SHELL_CMD_DENIED",message:"Shell command not allowed"}},st={0:{valid:!0,error:null},1:{valid:!1,error:"Missing required field: id"},2:{valid:!1,error:"Missing required field: commandId"},3:{valid:!1,error:"Missing required field: requesterId"},4:{valid:!1,error:"Missing required field: sessionId"},5:{valid:!1,error:"Missing required field: timestamp"},6:{valid:!1,error:"Missing required field: nonce"},7:{valid:!1,error:"Missing required field: requires"},8:{valid:!1,error:"Missing required field: payload"},9:{valid:!1,error:"Missing required field: signature"},10:{valid:!1,error:"Field 'id' is invalid"},11:{valid:!1,error:"Field 'commandId' is invalid"},12:{valid:!1,error:"Field 'requesterId' is invalid"},13:{valid:!1,error:"Field 'sessionId' is invalid"},14:{valid:!1,error:"Field 'timestamp' is invalid"},15:{valid:!1,error:"Field 'nonce' is invalid"},16:{valid:!1,error:"Field 'requires' is invalid"},17:{valid:!1,error:"payload.Missing required field: adapter"},18:{valid:!1,error:"payload.Field 'adapter' is invalid"},19:{valid:!1,error:"signature.Missing required field: alg"},20:{valid:!1,error:"signature.Missing required field: keyId"},21:{valid:!1,error:"signature.Missing required field: sig"},22:{valid:!1,error:"signature.Field 'alg' must be ed25519"},23:{valid:!1,error:"signature.Field 'sig' is invalid"},24:{valid:!1,error:"Field 'risk' is invalid"}},ae=null;function nt(){if(ae)return ae;if(!tt.existsSync(be))throw new Error(`LBE compiled engine missing: ${be}`);let e=tt.readFileSync(be),t=new WebAssembly.Module(e);return ae=new WebAssembly.Instance(t,{}),ae}function it(e){let r=nt().exports.lbe_policy_decision(e.policyConfigured?1:0,e.requesterConfigured?1:0,e.commandAllowed?1:0,e.adapterAllowed?1:0,e.filesystemRequired?1:0,e.filesystemRootsDefined?1:0,e.filesystemOk?1:0,e.pathDenied?1:0,e.shellRequired?1:0,e.shellCommandOk?1:0);return{...rt[r]||rt[1],code:r}}function at(e){let r=nt().exports.lbe_schema_decision(e.hasId?1:0,e.idValid?1:0,e.hasCommandId?1:0,e.commandIdValid?1:0,e.hasRequesterId?1:0,e.requesterIdValid?1:0,e.hasSessionId?1:0,e.sessionIdValid?1:0,e.hasTimestamp?1:0,e.timestampValid?1:0,e.hasNonce?1:0,e.nonceValid?1:0,e.hasRequires?1:0,e.requiresValid?1:0,e.hasPayload?1:0,e.hasPayloadAdapter?1:0,e.payloadAdapterValid?1:0,e.hasSignature?1:0,e.hasSignatureAlg?1:0,e.signatureAlgValid?1:0,e.hasSignatureKeyId?1:0,e.hasSignatureSig?1:0,e.signatureSigValid?1:0,e.hasRisk?1:0,e.riskValid?1:0);return{...st[r]||st[10],code:r}}var ct={type:"object",required:["id","commandId","requesterId","sessionId","timestamp","nonce","requires","payload","signature"],properties:{id:{type:"string",pattern:"^[A-Z_]+$",minLength:1,maxLength:50},commandId:{type:"string",pattern:"^[a-f0-9\\-]+$",minLength:36,maxLength:36},requesterId:{type:"string",minLength:3,maxLength:100},sessionId:{type:"string",minLength:3},timestamp:{type:"number",minimum:1e9},nonce:{type:"string",minLength:32,maxLength:128},requires:{type:"array",items:{type:"string"},minItems:1},risk:{type:"string",enum:["LOW","MEDIUM","HIGH","CRITICAL"]},payload:{type:"object",required:["adapter"],properties:{adapter:{type:"string"},cmd:{type:"string"},args:{type:"array"},cwd:{type:"string"}}},signature:{type:"object",required:["alg","keyId","sig"],properties:{alg:{type:"string",enum:["ed25519"]},keyId:{type:"string"},sig:{type:"string",minLength:10}}}}};function lt(e,t){let r=l=>e&&Object.prototype.hasOwnProperty.call(e,l),s=l=>typeof l=="string",o=(l,u)=>s(l)&&u.test(l),n=e?.payload,a=e?.signature,i=at({hasId:r("id"),idValid:o(e?.id,/^[A-Z_]+$/)&&e.id.length>=1&&e.id.length<=50,hasCommandId:r("commandId"),commandIdValid:o(e?.commandId,/^[a-f0-9-]+$/)&&e.commandId.length===36,hasRequesterId:r("requesterId"),requesterIdValid:s(e?.requesterId)&&e.requesterId.length>=3&&e.requesterId.length<=100,hasSessionId:r("sessionId"),sessionIdValid:s(e?.sessionId)&&e.sessionId.length>=3,hasTimestamp:r("timestamp"),timestampValid:typeof e?.timestamp=="number"&&e.timestamp>=1e9,hasNonce:r("nonce"),nonceValid:s(e?.nonce)&&e.nonce.length>=32&&e.nonce.length<=128,hasRequires:r("requires"),requiresValid:Array.isArray(e?.requires)&&e.requires.length>=1&&e.requires.every(s),hasPayload:r("payload")&&typeof n=="object"&&n!==null&&!Array.isArray(n),hasPayloadAdapter:n&&Object.prototype.hasOwnProperty.call(n,"adapter"),payloadAdapterValid:s(n?.adapter),hasSignature:r("signature")&&typeof a=="object"&&a!==null&&!Array.isArray(a),hasSignatureAlg:a&&Object.prototype.hasOwnProperty.call(a,"alg"),signatureAlgValid:a?.alg==="ed25519",hasSignatureKeyId:a&&Object.prototype.hasOwnProperty.call(a,"keyId"),hasSignatureSig:a&&Object.prototype.hasOwnProperty.call(a,"sig"),signatureSigValid:s(a?.sig)&&a.sig.length>=10,hasRisk:r("risk"),riskValid:["LOW","MEDIUM","HIGH","CRITICAL"].includes(e?.risk)}),c=i.valid?[]:[i.error];return{valid:c.length===0,errors:c}}import ce from"fs";import Or from"path";import x from"fs";import Ne from"path";import Ar from"crypto";var br={timeoutMs:5e3,pollMs:15,staleMs:3e4};function Nr(e){return e+".lock"}function dt(e){try{let t=x.openSync(e,"wx");return x.writeSync(t,`pid:${process.pid}:${Date.now()}`),x.closeSync(t),!0}catch(t){if(t.code==="EEXIST"||t.code==="EPERM"||t.code==="EBUSY"||t.code==="EACCES")return!1;throw t}}function ut(e,t){try{let r=x.statSync(e);if(Date.now()-r.mtimeMs>t)try{x.unlinkSync(e)}catch{}}catch{}}function _r(e){let t=Date.now()+e;for(;Date.now()<t;)try{Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,Math.max(1,t-Date.now()))}catch{}}function ft(e,t,r){let s=typeof t=="function"?t:r,o=typeof t=="function"?{}:t||{},{timeoutMs:n,pollMs:a,staleMs:i}={...br,...o},c=Ne.dirname(e);x.existsSync(c)||x.mkdirSync(c,{recursive:!0});let l=Nr(e),u=Date.now()+n,p=!1;for(;!p&&(p=dt(l),!p);){if(Date.now()>=u){if(ut(l,i),p=dt(l),p)break;let m=new Error(`withFileLock: timeout acquiring ${l} after ${n}ms`);throw m.code="ELOCKTIMEOUT",m}ut(l,i);let f=Math.floor(Math.random()*a);_r(a+f)}try{return s()}finally{try{x.unlinkSync(l)}catch{}}}function E(e,t,r={}){let s=Ne.dirname(e);x.existsSync(s)||x.mkdirSync(s,{recursive:!0});let o=Ne.join(s,`.tmp-${Date.now()}-${Ar.randomBytes(4).toString("hex")}`);try{x.writeFileSync(o,t,r),x.renameSync(o,e)}catch(n){try{x.existsSync(o)&&x.unlinkSync(o)}catch{}throw n}}function pt(e){try{if(!x.existsSync(e))return null;let t=x.readFileSync(e,"utf8");return JSON.parse(t)}catch(t){return console.error(`[atomicWrite] Failed to read JSON from ${e}:`,t.message),null}}var j=class{constructor(t,r=3600){this.dbPath=t,this.ttlSec=r,this.db={entries:[]}}async load(){if(!ce.existsSync(this.dbPath)){this.db={entries:[]};return}try{let t=ce.readFileSync(this.dbPath,"utf8");this.db=JSON.parse(t),this.prune()}catch(t){throw new Error(`Nonce DB at ${this.dbPath} is corrupt or unreadable: ${t.message}`)}}async save(){try{let t=Or.dirname(this.dbPath);ce.existsSync(t)||ce.mkdirSync(t,{recursive:!0}),E(this.dbPath,JSON.stringify(this.db,null,2),{encoding:"utf8"})}catch(t){throw new Error(`Failed to save nonce DB: ${t.message}`)}}checkAndRecord({requesterId:t,sessionId:r,nonce:s}){let o=Math.floor(Date.now()/1e3);this.db.entries=this.db.entries.filter(a=>o-a.timestamp<=this.ttlSec);let n=`${t}|${r}|${s}`;return this.db.entries.some(a=>a.key===n)?{ok:!1,reason:"REPLAY_NONCE",message:"Nonce has already been used"}:(this.db.entries.push({key:n,timestamp:o}),{ok:!0,reason:null,message:"Nonce accepted"})}prune(){let t=Math.floor(Date.now()/1e3),r=this.db.entries.length;this.db.entries=this.db.entries.filter(o=>t-o.timestamp<=this.ttlSec);let s=this.db.entries.length;return{prunedCount:r-s,remainingCount:s}}};function mt(e,{requesterId:t,sessionId:r,nonce:s,timestamp:o},n=3600){let a=Math.floor(Date.now()/1e3);e.entries=e.entries.filter(c=>a-c.timestamp<=n);let i=`${t}|${r}|${s}`;return e.entries.some(c=>c.key===i)?{ok:!1,reason:"REPLAY_NONCE",message:"Nonce has already been used"}:(e.entries.push({key:i,timestamp:o}),{ok:!0,reason:null,message:"Nonce accepted"})}import _e from"path";function Cr(e,t){if(!t||t.length===0)return!1;let r=_e.resolve(e);return t.some(s=>{let o=_e.resolve(s);return r===o||r.startsWith(o+_e.sep)})}function Lr(e,t){let r=t.replace(/\./g,"\\.").replace(/\*\*/g,".*").replace(/\*/g,"[^/]*");return new RegExp(`^${r}$`).test(e)}function yt(e,t){let r=!!(e&&!(e.default==="DENY"&&!e.requesters)),s=e?.requesters?.[t.requesterId],o=!!s,n=t.id.toLowerCase(),a=s?.allowCommands?.some(k=>k.toLowerCase()===n)||!1,i=s?.allowAdapters?.includes(t.payload?.adapter)||!1,c=!1,l=!1,u=!0,p=!1,f=null;if(t.payload?.cwd){c=!0;let k=s?.filesystem?.roots||[];l=k.length>0,u=l&&Cr(t.payload.cwd,k);let g=s?.filesystem?.denyPatterns||[];for(let w of g)if(Lr(t.payload.cwd,w)){p=!0,f=w;break}}let m=!1,h=!0,y=!1;if(t.id==="RUN_SHELL"){m=!0;let k=s?.exec?.allowCmds||[],g=s?.exec?.denyCmds||[],w=t.payload?.cmd;y=g.includes(w),h=!y&&(k.length===0||k.includes(w))}let d=it({policyConfigured:r,requesterConfigured:o,commandAllowed:a,adapterAllowed:i,filesystemRequired:c,filesystemRootsDefined:l,filesystemOk:u,pathDenied:p,shellRequired:m,shellCommandOk:h});if(d.allowed)return d;if(d.reason==="REQUESTER_NOT_ALLOWED")return{...d,message:`Requester '${t.requesterId}' not in policy`};if(d.reason==="COMMAND_NOT_ALLOWED")return{...d,message:`Command '${t.id}' not allowed for requester`};if(d.reason==="ADAPTER_NOT_ALLOWED")return{...d,message:`Adapter '${t.payload?.adapter}' not allowed`};if(d.reason==="CWD_OUTSIDE_ALLOWED_ROOT")return{...d,message:`Path '${t.payload.cwd}' not under allowed roots`};if(d.reason==="PATH_DENIED_BY_PATTERN")return{...d,message:`Path '${t.payload.cwd}' matches deny pattern: ${f}`};if(d.reason==="SHELL_CMD_DENIED"){let k=t.payload?.cmd;return{...d,reason:y?"SHELL_CMD_DENIED":"SHELL_CMD_NOT_ALLOWLISTED",message:y?`Shell command '${k}' is explicitly denied`:`Shell command '${k}' not in allowlist`}}return d}function gt(e){return e.payload?.cmd==="rm"?"CRITICAL":["delete","destroy","remove"].some(t=>e.id.toLowerCase().includes(t))?"HIGH":["write","create","update"].some(t=>e.id.toLowerCase().includes(t))?"MEDIUM":"LOW"}import ht from"fs";import Pr from"path";function kt(e){if(typeof e=="number"&&Number.isFinite(e))return{ok:!0,kind:"int",parts:[Math.floor(e)],raw:String(e)};if(typeof e!="string"||!e.trim())return{ok:!1,reason:"POLICY_VERSION_INVALID",message:"Policy version is required"};let t=e.trim();if(/^\d+$/.test(t))return{ok:!0,kind:"int",parts:[Number(t)],raw:t};let r=t.replace(/^v/i,"");if(/^\d+(\.\d+){0,2}$/.test(r)){let s=r.split(".").map(o=>Number(o));for(;s.length<3;)s.push(0);return{ok:!0,kind:"semver",parts:s,raw:t}}return{ok:!1,reason:"POLICY_VERSION_INVALID",message:`Unsupported policy version format '${e}' (use integer or semver)`}}function Dr(e,t){let r=Math.max(e.parts.length,t.parts.length);for(let s=0;s<r;s++){let o=e.parts[s]??0,n=t.parts[s]??0;if(o>n)return 1;if(o<n)return-1}return 0}function St(e){if(typeof e=="number"&&Number.isFinite(e))return{ok:!0,epochSec:e>1e12?Math.floor(e/1e3):Math.floor(e)};if(typeof e!="string"||!e.trim())return{ok:!1,reason:"POLICY_CREATED_AT_INVALID",message:"Policy createdAt is required"};let t=Date.parse(e);return Number.isNaN(t)?{ok:!1,reason:"POLICY_CREATED_AT_INVALID",message:`Invalid policy createdAt '${e}'`}:{ok:!0,epochSec:Math.floor(t/1e3)}}function Rr(e){if(!ht.existsSync(e))return{schemaVersion:"1",lastAccepted:null,updatedAt:null};try{let t=JSON.parse(ht.readFileSync(e,"utf8"));if(!t||typeof t!="object")throw new Error("Policy state file has invalid structure");return{schemaVersion:String(t.schemaVersion||"1"),lastAccepted:t.lastAccepted&&typeof t.lastAccepted=="object"?t.lastAccepted:null,updatedAt:t.updatedAt||null}}catch(t){throw new Error(`Policy state at ${e} is corrupt or unreadable: ${t.message}`)}}function Tr(e,t){let r=JSON.stringify(t,null,2);E(e,r,{encoding:"utf8"})}function F({policyObj:e,statePath:t=Pr.resolve("data/policy.state.json"),maxCreatedAtSkewSec:r=31536e3,nowSec:s=Math.floor(Date.now()/1e3),persist:o=!0}){let n=kt(e?.version);if(!n.ok)return{ok:!1,reason:n.reason,message:n.message,updated:!1};let a=St(e?.createdAt);if(!a.ok)return{ok:!1,reason:a.reason,message:a.message,updated:!1};let i=Math.abs(s-a.epochSec),c=Number.isFinite(r)&&r>0?Math.floor(r):31536e3;if(i>c)return{ok:!1,reason:"POLICY_CREATED_AT_SKEW_EXCEEDED",message:`Policy createdAt skew ${i}s exceeds allowed ${c}s`,updated:!1};let l;try{l=Rr(t)}catch(y){return{ok:!1,reason:"POLICY_STATE_CORRUPT",message:y.message,updated:!1}}let u=l.lastAccepted,p=null,f=null,m=0;if(u&&(p=kt(u.version),f=St(u.createdAt),p.ok&&f.ok)){if(m=Dr(n,p),m<0)return{ok:!1,reason:"POLICY_VERSION_REGRESSION",message:`Policy version regression: current '${n.raw}' < last '${p.raw}'`,updated:!1};if(m===0&&a.epochSec<f.epochSec)return{ok:!1,reason:"POLICY_CREATED_AT_REGRESSION",message:`Policy createdAt regression: current '${e.createdAt}' < last '${u.createdAt}'`,updated:!1};if(m>0&&a.epochSec<f.epochSec)return{ok:!1,reason:"POLICY_CREATED_AT_REGRESSION",message:"Policy createdAt must be monotonic when version increases",updated:!1}}let h=!u||!p?.ok||!f?.ok||m>0||m===0&&a.epochSec>f.epochSec;if(o&&h){let y={schemaVersion:"1",lastAccepted:{version:e.version,createdAt:e.createdAt,environment:e.environment||null},updatedAt:new Date().toISOString()};Tr(t,y)}return{ok:!0,reason:null,message:"Policy version guard passed",updated:h}}function H({commandObj:e,pubKeyB64:t,keyStore:r,nonceDb:s,policy:o,rateLimiter:n,policyStatePath:a}){let i={valid:!1,commandId:e?.commandId,checks:{},errors:[]},c=lt(e,ct);if(i.checks.schema=c.valid,!c.valid)return i.errors.push(...c.errors.map(g=>({type:"SCHEMA_ERROR",message:g}))),i;if(a&&o?.version!==void 0)try{let g=F({policyObj:o,statePath:a});if(i.checks.policyVersion=g.ok,!g.ok)return i.errors.push({type:"POLICY_VERSION_INVALID",message:g.message}),i}catch{i.checks.policyVersion=!0}else i.checks.policyVersion=!0;let l=e.signature?.keyId;if(i.checks.keyId=Ee(l),!i.checks.keyId)return i.errors.push({type:"KEY_ID_INVALID",message:`Invalid keyId '${l}'. Use versioned IDs like 'agent:gpt-v1-2026Q1'`}),i;let u=Math.floor(Date.now()/1e3),p=Number.isFinite(o?.security?.maxClockSkewSec)?o.security.maxClockSkewSec:600,f=Math.abs(u-e.timestamp);if(i.checks.timestamp=f<=p,!i.checks.timestamp)return i.errors.push({type:"TIMESTAMP_SKEW_EXCEEDED",message:`Command timestamp skew ${f}s exceeds allowed ${p}s`}),i;let m=null;if(r){let g=ne({keyStore:r,keyId:l,requesterId:e.requesterId});if(!g.ok)return i.checks.signature=!1,i.errors.push({type:g.reason,message:g.message}),i;m=g.publicKey}if(!m&&t&&(m=t),!m)return i.checks.signature=!1,i.errors.push({type:"SIGNATURE_KEY_UNAVAILABLE",message:"No public key available. Provide --pub-key/--pub-key-file or config/keys.json"}),i;let h={...e};delete h.signature;let y=oe({payloadObj:h,sigB64:e.signature.sig,pubKeyB64:m});if(i.checks.signature=y.valid,!y.valid)return i.errors.push({type:"SIGNATURE_INVALID",message:y.message}),i;if(n&&typeof n.checkAndRecord=="function"){let g=o?.requesters?.[e.requesterId]?.rateLimit||{},w=o?.security?.defaultRateLimit||{},N=n.checkAndRecord({requesterId:e.requesterId,nowSec:u,windowSec:g.windowSec??w.windowSec??60,maxRequests:g.maxRequests??w.maxRequests??30});if(i.checks.rateLimit=N.ok,!N.ok)return i.errors.push({type:N.reason,message:`${N.message}. Retry after ${N.retryAfterSec}s`}),i}let d;if(s&&typeof s.checkAndRecord=="function"?d=s.checkAndRecord({requesterId:e.requesterId,sessionId:e.sessionId,nonce:e.nonce}):d=mt(s,{requesterId:e.requesterId,sessionId:e.sessionId,nonce:e.nonce,timestamp:e.timestamp}),i.checks.nonce=d.ok,!d.ok)return i.errors.push({type:d.reason,message:d.message}),i;let k=yt(o,e);return i.checks.policy=k.allowed,i.risk=gt(e),k.allowed?(i.valid=!0,i.message="Command validation successful",i):(i.errors.push({type:k.reason,message:k.message}),i)}async function It(e){let{in:t}=e,r=e.config||e.policy,s=e["pub-key"],o=e["keys-store"]||z.resolve("config/keys.json"),n=e["policy-sig"]||z.resolve("config/policy.sig.json"),a=e["policy-state"]||z.resolve("data/policy.state.json"),i=e["policy-unsigned-ok"]===!0||String(e["policy-unsigned-ok"]).toLowerCase()==="true";t||(console.error("Error: --in <file> is required"),process.exit(1));let c;try{let k=z.resolve(t),g=Oe.readFileSync(k,"utf-8");c=JSON.parse(g)}catch(k){console.error(JSON.stringify({status:"error",error:"INVALID_PROPOSAL_FILE",message:k.message})),process.exit(5)}let l;try{let k=r||z.resolve("config/policy.default.json");Oe.existsSync(k)||(console.error(JSON.stringify({status:"error",error:"MISSING_POLICY",message:`Policy file not found: ${k}`})),process.exit(1));let g=Oe.readFileSync(k,"utf-8");l=JSON.parse(g)}catch(k){console.error(JSON.stringify({status:"error",error:"INVALID_POLICY",message:k.message})),process.exit(1)}let u=W(o),p=u.ok?u.store:null,f=G({policyObj:l,keyStore:p,policySigPath:n,allowUnsigned:i});f.ok||(console.error(JSON.stringify({status:"error",error:f.reason,message:f.message},null,2)),process.exit(8));let m=F({policyObj:l,statePath:a,maxCreatedAtSkewSec:l?.security?.maxPolicyCreatedAtSkewSec});m.ok||(console.error(JSON.stringify({status:"error",error:m.reason,message:m.message},null,2)),process.exit(8));let h=new j(z.resolve("data/nonce.db.json"));await h.load(),!p&&!s&&(console.error(JSON.stringify({status:"error",error:"MISSING_KEY_MATERIAL",message:`${u.message}. Provide --pub-key/--pub-key-file or create config/keys.json`})),process.exit(1));let y=H({commandObj:c,pubKeyB64:s,keyStore:p,nonceDb:h,policy:l}),d={status:y.valid?"valid":"invalid",commandId:c.commandId||"N/A",checks:y.checks,errors:y.errors||[],risk:y.risk||"UNKNOWN"};console.log(JSON.stringify(d,null,2)),y.valid||(y.checks.schema===!1&&process.exit(5),y.checks.signature===!1&&process.exit(3),y.checks.nonce===!1&&process.exit(4),y.checks.timestamp===!1&&process.exit(6),y.checks.rateLimit===!1&&process.exit(7),y.checks.policy===!1&&process.exit(2),process.exit(9)),process.exit(0)}import Pe from"fs";import Z from"path";async function vt(e){return{adapter:"noop",commandId:e.commandId||"unknown",command:e.id||"unknown",status:"completed",output:`[NOOP] Would execute: ${e.id||"unknown"} on adapter: ${e.payload?.adapter||"unknown"}`,exitCode:0,timestamp:new Date().toISOString()}}import{spawnSync as $r}from"child_process";import Ce from"path";function jr(e){if(e===void 0)return{ok:!0,args:[]};if(!Array.isArray(e))return{ok:!1,error:"payload.args must be an array"};let t=[];for(let r of e){if(typeof r!="string"&&typeof r!="number"&&typeof r!="boolean")return{ok:!1,error:"payload.args may only contain string, number, or boolean values"};t.push(String(r))}return{ok:!0,args:t}}async function xt(e,t,r){let s=e.payload,o=3e4,n=1024*1024;if(s.adapter!=="shell")return{adapter:"shell",commandId:e.commandId,status:"error",error:"Adapter mismatch",exitCode:1};let a=r?.exec?.allowCmds||[];if((r?.exec?.denyCmds||[]).includes(s.cmd))return{adapter:"shell",commandId:e.commandId,status:"blocked",error:`Command '${s.cmd}' is denied`,exitCode:2};if(a.length>0&&!a.includes(s.cmd))return{adapter:"shell",commandId:e.commandId,status:"blocked",error:`Command '${s.cmd}' not in allowlist`,exitCode:2};if(!(r?.filesystem?.roots||[]).some(p=>{let f=Ce.resolve(p),m=Ce.resolve(s.cwd);return m===f||m.startsWith(f+Ce.sep)}))return{adapter:"shell",commandId:e.commandId,status:"blocked",error:`CWD '${s.cwd}' not authorized`,exitCode:2};let u=jr(s.args);if(!u.ok)return{adapter:"shell",commandId:e.commandId,status:"blocked",error:u.error,exitCode:2};try{let p=$r(s.cmd,u.args,{cwd:s.cwd,timeout:o,encoding:"utf8",maxBuffer:n,stdio:["pipe","pipe","pipe"],shell:!1});if(p.error)throw p.error;let f=`${p.stdout||""}${p.stderr||""}`,m=p.status??1;return m!==0?{adapter:"shell",commandId:e.commandId,command:s.cmd,status:"error",error:f.substring(0,n)||`Command exited with code ${m}`,exitCode:m,timestamp:new Date().toISOString()}:{adapter:"shell",commandId:e.commandId,command:s.cmd,status:"completed",output:f.substring(0,n),exitCode:0,timestamp:new Date().toISOString()}}catch(p){return{adapter:"shell",commandId:e.commandId,command:s.cmd,status:"error",error:p.message,exitCode:p.status||1,timestamp:new Date().toISOString()}}}import te from"fs";import X from"path";import M from"fs";import le from"path";import Fr from"crypto";function de(e,t){let r=t||le.resolve("data/backups");M.existsSync(r)||M.mkdirSync(r,{recursive:!0});let s=le.resolve(e),o=M.existsSync(s),n=null,a=null;o&&(n=M.readFileSync(s),a=Fr.createHash("sha256").update(n).digest("hex"));let i=le.basename(s).replace(/[^a-zA-Z0-9._-]/g,"_"),c=`${Date.now()}-${a?a.slice(0,8):"new"}-${i}`,l=o?le.join(r,c):null;return o&&n!==null&&E(l,n),{originalPath:s,backupPath:l,existed:o,hash:a,createdAt:new Date().toISOString()}}function J(e){if(!e)return{restored:!1,error:"No backup metadata"};let{originalPath:t,backupPath:r,existed:s}=e;if(!s)try{return M.existsSync(t)&&M.unlinkSync(t),{restored:!0,action:"deleted"}}catch(o){return{restored:!1,error:o.message}}if(!r||!M.existsSync(r))return{restored:!1,error:"Backup file not found at: "+r};try{let o=M.readFileSync(r);return E(t,o),{restored:!0,action:"restored"}}catch(o){return{restored:!1,error:o.message}}}var Mr=10*1024*1024;function Kr(e,t){return e?X.isAbsolute(e)?X.resolve(e):X.resolve(t||process.cwd(),e):null}function qr(e,t){let r=X.resolve(e);return t.some(s=>{let o=X.resolve(s);return r===o||r.startsWith(o+X.sep)})}function Jr(e,t){for(let r of t||[])if(new RegExp("^"+r.replace(/\./g,"\\.").replace(/\*\*/g,".*").replace(/\*/g,"[^/\\\\]*")+"$").test(e))return r;return null}function Q(e,t,r,s=2){return{adapter:"file",commandId:e.commandId,status:"blocked",errorCode:t,error:r,exitCode:s}}function T(e,t,r,s=null,o=1){return{adapter:"file",commandId:e.commandId,status:"error",errorCode:t,error:r,backup:s?ue(s):null,exitCode:o}}function ue(e){return e?{path:e.backupPath,existed:e.existed,hash:e.hash,createdAt:e.createdAt}:null}async function Et(e,t,r){let s=e.payload,o=s.action,n=s.cwd||process.cwd(),a=Kr(s.target,n);if(!o)return Q(e,"FILE_NO_ACTION","payload.action is required");if(!a&&o!=="noop")return Q(e,"FILE_NO_TARGET","payload.target is required");let i=r?.filesystem?.roots||[];if(i.length===0)return Q(e,"FILE_NO_ROOTS","No filesystem roots defined for requester");if(!qr(a,i))return Q(e,"FILE_OUTSIDE_ROOT",`'${a}' is outside allowed roots`);let c=Jr(a,r?.filesystem?.denyPatterns);if(c)return Q(e,"FILE_PATH_DENIED",`'${a}' matches deny pattern: ${c}`);switch(o){case"read":return Vr(e,a);case"write":return Br(e,a,s);case"patch":return Yr(e,a,s);case"delete":return Ur(e,a);default:return Q(e,"FILE_UNKNOWN_ACTION",`Unknown action: '${o}'`)}}function Vr(e,t){if(!te.existsSync(t))return T(e,"FILE_NOT_FOUND",`Not found: ${t}`);try{let r=te.statSync(t);if(r.size>Mr)return T(e,"FILE_TOO_LARGE","File exceeds 10 MB read limit");let s=te.readFileSync(t,"utf8");return{adapter:"file",action:"read",commandId:e.commandId,status:"completed",target:t,output:s,bytesRead:r.size,exitCode:0}}catch(r){return T(e,"FILE_READ_ERROR",r.message)}}function Br(e,t,r){let s=r.content;if(s==null)return T(e,"FILE_MISSING_CONTENT","payload.content is required for write");let o=Le(t);try{return E(t,s,{encoding:"utf8"}),{adapter:"file",action:"write",commandId:e.commandId,status:"completed",target:t,backup:ue(o),output:`Wrote ${Buffer.byteLength(s,"utf8")} bytes to ${t}`,exitCode:0}}catch(n){return J(o),T(e,"FILE_WRITE_ERROR",n.message,o)}}function Yr(e,t,r){let s=r.content;if(s==null)return T(e,"FILE_MISSING_CONTENT","payload.content is required for patch");let o=Le(t);try{return E(t,s,{encoding:"utf8"}),{adapter:"file",action:"patch",commandId:e.commandId,status:"completed",target:t,backup:ue(o),output:`Patched ${t} (${Buffer.byteLength(s,"utf8")} bytes)`,exitCode:0}}catch(n){return J(o),T(e,"FILE_PATCH_ERROR",n.message,o)}}function Ur(e,t){if(!te.existsSync(t))return T(e,"FILE_NOT_FOUND",`Not found: ${t}`);let r=Le(t);try{return te.unlinkSync(t),{adapter:"file",action:"delete",commandId:e.commandId,status:"completed",target:t,backup:ue(r),output:`Deleted ${t}`,exitCode:0}}catch(s){return J(r),T(e,"FILE_DELETE_ERROR",s.message,r)}}function Le(e){try{return de(e)}catch{return null}}async function wt(e,t,r){let s=Date.now();try{let o=e.id||"";if(!o.toUpperCase().startsWith("OBSERVE"))return{adapter:"observer",commandId:e.commandId,status:"error",error:`Observer adapter only handles OBSERVE_* commands, got '${o}'`,exitCode:1};let{source:n,context:a,issueType:i,description:c,severity:l,metadata:u}=e.payload||{};if(!i||!c)return{adapter:"observer",commandId:e.commandId,status:"error",error:"Observer payload must include issueType and description",exitCode:1};let p=["low","medium","high","critical"];return l&&!p.includes(l)?{adapter:"observer",commandId:e.commandId,status:"error",error:`Invalid severity '${l}'. Must be one of: ${p.join(", ")}`,exitCode:1}:{adapter:"observer",commandId:e.commandId,status:"recorded",timestamp:new Date().toISOString(),requesterId:e.requesterId,observation:{source:n||"unknown",context:a||"unknown",issueType:i,description:c,severity:l||"info",metadata:u||{}},duration_ms:Date.now()-s,exitCode:0}}catch(o){return{adapter:"observer",commandId:e.commandId,status:"error",error:`Observer execution failed: ${o.message}`,exitCode:9}}}var At={noop:vt,shell:xt,file:Et,observer:wt};function Wr(e){return At[e]}async function fe(e,t,r,s){let o=Wr(e);if(!o)return{adapter:e,commandId:t.commandId,status:"error",error:`Adapter '${e}' not found`,exitCode:1};try{return await o(t,r,s)}catch(n){return{adapter:e,commandId:t.commandId,status:"error",error:`Adapter execution failed: ${n.message}`,exitCode:9}}}var Ko=Object.keys(At);async function bt(e){let{in:t}=e,r=e.config||e.policy,s=e["pub-key"],o=e["keys-store"]||Z.resolve("config/keys.json"),n=e["policy-sig"]||Z.resolve("config/policy.sig.json"),a=e["policy-state"]||Z.resolve("data/policy.state.json"),i=e["policy-unsigned-ok"]===!0||String(e["policy-unsigned-ok"]).toLowerCase()==="true";t||(console.error("Error: --in <file> is required"),process.exit(1));let c;try{let g=Z.resolve(t),w=Pe.readFileSync(g,"utf-8");c=JSON.parse(w)}catch(g){console.error(JSON.stringify({status:"error",error:"INVALID_PROPOSAL_FILE",message:g.message})),process.exit(5)}let l;try{let g=r||Z.resolve("config/policy.default.json");Pe.existsSync(g)||(console.error(JSON.stringify({status:"error",error:"MISSING_POLICY",message:`Policy file not found: ${g}`})),process.exit(1));let w=Pe.readFileSync(g,"utf-8");l=JSON.parse(w)}catch(g){console.error(JSON.stringify({status:"error",error:"INVALID_POLICY",message:g.message})),process.exit(1)}let u=W(o),p=u.ok?u.store:null,f=G({policyObj:l,keyStore:p,policySigPath:n,allowUnsigned:i});f.ok||(console.error(JSON.stringify({status:"error",error:f.reason,message:f.message},null,2)),process.exit(8));let m=F({policyObj:l,statePath:a,maxCreatedAtSkewSec:l?.security?.maxPolicyCreatedAtSkewSec});m.ok||(console.error(JSON.stringify({status:"error",error:m.reason,message:m.message},null,2)),process.exit(8));let h=new j(Z.resolve("data/nonce.db.json"));await h.load(),!p&&!s&&(console.error(JSON.stringify({status:"error",error:"MISSING_KEY_MATERIAL",message:`${u.message}. Provide --pub-key/--pub-key-file or create config/keys.json`})),process.exit(1));let y=H({commandObj:c,pubKeyB64:s,keyStore:p,nonceDb:h,policy:l});if(!y.valid){let g={status:"invalid",commandId:c.commandId||"N/A",checks:y.checks,errors:y.errors||[],executionResult:null};console.log(JSON.stringify(g,null,2)),y.checks.schema===!1&&process.exit(5),y.checks.signature===!1&&process.exit(3),y.checks.nonce===!1&&process.exit(4),y.checks.timestamp===!1&&process.exit(6),y.checks.rateLimit===!1&&process.exit(7),y.checks.policy===!1&&process.exit(2),process.exit(9)}let d;try{let g=l.requesters?.[c.requesterId];d=await fe("noop",c,l,g)}catch(g){d={adapter:"noop",status:"error",error:g.message}}let k={status:"valid_simulated",commandId:c.commandId||"N/A",checks:y.checks,risk:y.risk||"UNKNOWN",executionResult:{adapter:d.adapter,status:d.status,output:d.output||d.error||"",exitCode:d.exitCode||0,note:"This is a simulation using noop adapter. No actual execution occurred."}};console.log(JSON.stringify(k,null,2)),process.exit(0)}import ye from"fs";import O from"path";import Zr from"crypto";import K from"fs";import De from"path";import Gr from"crypto";function Nt(e){return Gr.createHash("sha256").update(e).digest("hex")}function Hr(e){try{if(!K.existsSync(e))return"GENESIS";let t=K.readFileSync(e,"utf8").trim();if(!t)return"GENESIS";let r=t.split(`
120
+ `),s=r[r.length-1];try{return JSON.parse(s).hash||"GENESIS"}catch{return"GENESIS"}}catch{return"GENESIS"}}function Re(e,t){let r=De.dirname(e);K.existsSync(r)||K.mkdirSync(r,{recursive:!0});let s;return ft(e,()=>{let o=Hr(e),n={...t,prevHash:o,timestamp:new Date().toISOString()};delete n.hash;let a=JSON.stringify(n),i=Nt(a),c=JSON.stringify({...n,hash:i}),l="";K.existsSync(e)&&(l=K.readFileSync(e,"utf8"));try{E(e,l+c+`
121
+ `,{encoding:"utf8"})}catch(u){throw new Error(`Audit log write failed: ${u.message}`)}s={success:!0,hash:i,prevHash:o,message:"Audit entry appended"}}),s}function _t(e,t={}){let r=t.failFast!==!1,s=Number.isFinite(t.maxEntries)&&t.maxEntries>0?Math.floor(t.maxEntries):null,o={ok:!0,file:De.resolve(e),entries:0,valid:!0,firstInvalidIndex:null,reason:null,errors:[],message:"Audit log verified"};try{if(!K.existsSync(e))return o.message="Audit log file not found (treated as empty)",o;let n=K.readFileSync(e,"utf8").trim();if(!n)return o.message="Empty audit log",o;let a=n.split(`
122
+ `),i=s?a.slice(0,s):a;o.entries=i.length;let c="GENESIS";for(let l=0;l<i.length;l++){let u;try{u=JSON.parse(i[l])}catch{let h={index:l,reason:"INVALID_JSON_LINE",message:`Line ${l} is not valid JSON`};if(o.valid=!1,o.ok=!1,o.firstInvalidIndex??=l,o.reason??=h.reason,o.errors.push(h),r)break;continue}if(u.prevHash!==c){let h={index:l,reason:"PREV_HASH_MISMATCH",message:`Expected prevHash '${c}', got '${u.prevHash}'`};if(o.valid=!1,o.ok=!1,o.firstInvalidIndex??=l,o.reason??=h.reason,o.errors.push(h),r)break}let p={...u},f=p.hash;delete p.hash;let m=Nt(JSON.stringify(p));if(f!==m){let h={index:l,reason:"HASH_MISMATCH",message:`Expected hash '${m}', got '${f}'`};if(o.valid=!1,o.ok=!1,o.firstInvalidIndex??=l,o.reason??=h.reason,o.errors.push(h),r)break}c=f}return o.message=o.valid?`Audit log verified: ${o.entries} entries`:`Audit log integrity failed at index ${o.firstInvalidIndex}`,o}catch(n){return{ok:!1,file:De.resolve(e),entries:0,valid:!1,firstInvalidIndex:null,reason:"AUDIT_VERIFY_ERROR",errors:[{index:null,reason:"AUDIT_VERIFY_ERROR",message:n.message}],message:`Integrity check failed: ${n.message}`}}}import pe from"fs";import zr from"path";var me=class{constructor(t){this.dbPath=t,this.db={entries:[]}}async load(){try{if(!pe.existsSync(this.dbPath)){this.db={entries:[]};return}let t=pe.readFileSync(this.dbPath,"utf8");this.db=JSON.parse(t),Array.isArray(this.db.entries)||(this.db={entries:[]})}catch{this.db={entries:[]}}}async save(){let t=zr.dirname(this.dbPath);pe.existsSync(t)||pe.mkdirSync(t,{recursive:!0}),E(this.dbPath,JSON.stringify(this.db,null,2),{encoding:"utf8"})}checkAndRecord({requesterId:t,nowSec:r,windowSec:s,maxRequests:o}){let n=Number.isFinite(r)?r:Math.floor(Date.now()/1e3),a=Number.isFinite(s)&&s>0?s:60,i=Number.isFinite(o)&&o>0?o:30,c=n-a;this.db.entries=this.db.entries.filter(u=>u.timestamp>=c);let l=this.db.entries.filter(u=>u.requesterId===t);if(l.length>=i){let u=l.sort((f,m)=>f.timestamp-m.timestamp)[0],p=Math.max(1,a-(n-u.timestamp));return{ok:!1,reason:"RATE_LIMIT_EXCEEDED",message:`Rate limit exceeded for '${t}' (${i}/${a}s)`,retryAfterSec:p}}return this.db.entries.push({requesterId:t,timestamp:n}),{ok:!0,reason:null,message:"Rate limit check passed",retryAfterSec:0}}};import Xr from"crypto";import Qr from"path";var $e=class{constructor(t){this.dbPath=t||Qr.resolve("data/checkpoints.db.json"),this.store={checkpoints:{},tokens:{}},this._load()}_load(){let t=pt(this.dbPath);t&&(this.store=t,this.store.checkpoints=this.store.checkpoints||{},this.store.tokens=this.store.tokens||{})}_save(){let t=JSON.stringify(this.store,null,2);E(this.dbPath,t,{encoding:"utf8"})}saveCheckpoint(t,r){this.store.checkpoints[t]={jobId:t,...r,updatedAt:Date.now()},this._save()}getCheckpoint(t){return this.store.checkpoints[t]||null}getAllCheckpoints(){return Object.values(this.store.checkpoints)}removeCheckpoint(t){return this.store.checkpoints[t]?(delete this.store.checkpoints[t],this._save(),!0):!1}saveToken(t,r){this.store.tokens[t]={tokenId:t,...r,createdAt:Date.now()},this._save()}getToken(t){return this.store.tokens[t]||null}getAllTokens(){return Object.values(this.store.tokens)}removeToken(t){return this.store.tokens[t]?(delete this.store.tokens[t],this._save(),!0):!1}},Te=null;function Ot(e){return Te||(Te=new $e(e)),Te}var Fe=class{constructor(t){this.store=Ot(t),this._pendingResolvers=new Map}createToken(t,r={}){let s=Xr.randomBytes(16).toString("hex"),o={jobId:t,context:r,status:"pending",expiresAt:Date.now()+1440*60*1e3};return this.store.saveToken(s,o),s}awaitApproval(t){let r=this.store.getToken(t);return r?r.status!=="pending"?Promise.reject(new Error(`Approval token ${t} is no longer pending (status: ${r.status})`)):Date.now()>r.expiresAt?(this.store.removeToken(t),Promise.reject(new Error(`Approval token ${t} expired`))):new Promise((s,o)=>{this._pendingResolvers.set(t,{resolve:s,reject:o})}):Promise.reject(new Error(`Approval token ${t} not found`))}approve(t,r={}){let s=this.store.getToken(t);if(!s)throw new Error("Token not found");if(s.status!=="pending")throw new Error("Token not pending");this.store.saveToken(t,{...s,status:"approved",approverData:r,resolvedAt:Date.now()});let o=this._pendingResolvers.get(t);return o&&(o.resolve({approved:!0,approverData:r}),this._pendingResolvers.delete(t)),!0}deny(t,r="Manually denied"){let s=this.store.getToken(t);if(!s)throw new Error("Token not found");if(s.status!=="pending")throw new Error("Token not pending");this.store.saveToken(t,{...s,status:"denied",reason:r,resolvedAt:Date.now()});let o=this._pendingResolvers.get(t);return o&&(o.reject(new Error(`Approval denied: ${r}`)),this._pendingResolvers.delete(t)),!0}},je=null;function Ct(e){return je||(je=new Fe(e)),je}function Me(e){return Zr.createHash("sha256").update(JSON.stringify(e)).digest("hex")}async function Lt(e){let{in:t}=e,r=e.config||e.policy,s=e["pub-key"],o=e["keys-store"]||O.resolve("config/keys.json"),n=e["policy-sig"]||O.resolve("config/policy.sig.json"),a=e["policy-state"]||O.resolve("data/policy.state.json"),i=e["policy-unsigned-ok"]===!0||String(e["policy-unsigned-ok"]).toLowerCase()==="true";t||(console.error("Error: --in <file> is required"),process.exit(1));let c;try{let S=O.resolve(t),_=ye.readFileSync(S,"utf-8");c=JSON.parse(_)}catch(S){console.error(JSON.stringify({status:"error",error:"INVALID_PROPOSAL_FILE",message:S.message})),process.exit(5)}let l;try{let S=r||O.resolve("config/policy.default.json");ye.existsSync(S)||(console.error(JSON.stringify({status:"error",error:"MISSING_POLICY",message:`Policy file not found: ${S}`})),process.exit(1));let _=ye.readFileSync(S,"utf-8");l=JSON.parse(_)}catch(S){console.error(JSON.stringify({status:"error",error:"INVALID_POLICY",message:S.message})),process.exit(1)}let u=W(o),p=u.ok?u.store:null,f=G({policyObj:l,keyStore:p,policySigPath:n,allowUnsigned:i});f.ok||(console.error(JSON.stringify({status:"error",error:f.reason,message:f.message},null,2)),process.exit(8));let m=F({policyObj:l,statePath:a,maxCreatedAtSkewSec:l?.security?.maxPolicyCreatedAtSkewSec});m.ok||(console.error(JSON.stringify({status:"error",error:m.reason,message:m.message},null,2)),process.exit(8));let h=new j(O.resolve("data/nonce.db.json"));await h.load(),!p&&!s&&(console.error(JSON.stringify({status:"error",error:"MISSING_KEY_MATERIAL",message:`${u.message}. Provide --pub-key/--pub-key-file or create config/keys.json`})),process.exit(1));let y=new me(O.resolve("data/rate-limit.db.json"));await y.load();let d=H({commandObj:c,pubKeyB64:s,keyStore:p,nonceDb:h,policy:l,rateLimiter:y});if(!d.valid){try{await h.save(),await y.save()}catch{}let S={status:"invalid",commandId:c.commandId||"N/A",checks:d.checks,errors:d.errors||[],executionResult:null};console.error(JSON.stringify(S,null,2));let _=O.resolve("data/audit.log.jsonl");try{Re(_,{commandId:c.commandId||"N/A",status:"rejected",requesterId:c.requesterId||"unknown",payloadHash:Me(c),reason:d.checks,timestamp:new Date().toISOString()})}catch(Yt){console.error(JSON.stringify({status:"error",error:"AUDIT_WRITE_FAILED",message:Yt.message})),process.exit(10)}d.checks.schema===!1&&process.exit(5),d.checks.signature===!1&&process.exit(3),d.checks.nonce===!1&&process.exit(4),d.checks.timestamp===!1&&process.exit(6),d.checks.rateLimit===!1&&process.exit(7),d.checks.policy===!1&&process.exit(2),process.exit(9)}let k=d.risk||"LOW",g=c.payload.adapter||"shell",w=l.requesters?.[c.requesterId],N=w?.requireApproval;if(N===!0||Array.isArray(N)&&(N.includes(k)||N.includes("*")||["HIGH","CRITICAL"].includes(k)&&N.includes("HIGH+"))){let _=Ct().createToken(c.commandId,{requesterId:c.requesterId,adapter:g,risk:k});await h.save().catch(()=>{}),await y.save().catch(()=>{}),console.log(JSON.stringify({status:"approval_required",commandId:c.commandId||"N/A",risk:k,approvalToken:_,message:`${k} risk operation requires operator approval. Approve with: lbe approve --token ${_}`},null,2)),process.exit(11)}let P=null;if((e.backup===!0||g==="file")&&c.payload.target)try{P=de(O.resolve(c.payload.target))}catch{}let A;try{A=await fe(g,c,l,w)}catch(S){A={adapter:g,status:"error",error:S.message,exitCode:1}}let ke=A.status==="error"||A.exitCode!==0,U=null;if(ke&&P&&e["rollback-on-failure"]!==!1)try{U=J(P)}catch(S){U={restored:!1,error:S.message}}let se=null;if(!ke&&c.payload.target&&["write","patch"].includes(c.payload.action)){let _=ye.existsSync(O.resolve(c.payload.target));se={ok:_,check:"target_exists",target:c.payload.target},!_&&P&&(U=J(P),A.status="error")}let Vt=O.resolve("data/audit.log.jsonl");try{Re(Vt,{commandId:c.commandId||"N/A",status:U?.restored?"rolled_back":A.status||"completed",requesterId:c.requesterId||"unknown",payloadHash:Me(c),executionHash:Me(A),adapter:A.adapter,riskLevel:k,exitCode:A.exitCode||0,rolledBack:U?.restored||!1,timestamp:new Date().toISOString()})}catch(S){console.error(JSON.stringify({status:"error",error:"AUDIT_WRITE_FAILED",message:S.message})),process.exit(10)}await h.save(),await y.save();let Bt={status:ke||se&&!se.ok?"failed":"executed",commandId:c.commandId||"N/A",risk:k,checks:d.checks,executionResult:{adapter:A.adapter,status:A.status||"completed",output:A.output||A.error||"",exitCode:A.exitCode||0},backup:P?{path:P.backupPath,existed:P.existed,hash:P.hash}:null,rollback:U,postValidation:se};console.log(JSON.stringify(Bt,null,2)),process.exit(A.exitCode||0)}import Pt from"path";function Dt(e,t){if(e===void 0)return t;if(e===!0||e===!1)return e;let r=String(e).trim().toLowerCase();return r==="true"||r==="1"||r==="yes"?!0:r==="false"||r==="0"||r==="no"?!1:t}async function Rt(e){let t=e.audit?Pt.resolve(e.audit):Pt.resolve("data/audit.log.jsonl"),r=Dt(e["fail-fast"],!0),s=Dt(e.json,!0),o=Number.isFinite(Number(e.max))?Number(e.max):void 0,n=_t(t,{failFast:r,maxEntries:o});s?console.log(JSON.stringify(n,null,2)):n.valid?(console.log(`OK: ${n.file}`),console.log(`Entries: ${n.entries}`)):(console.log(`FAIL: ${n.file}`),console.log(`First invalid index: ${n.firstInvalidIndex}`),console.log(`Reason: ${n.reason}`)),process.exit(n.valid?0:8)}import qe from"path";import V from"fs";import L from"path";import es from"crypto";import{fileURLToPath as ts}from"url";var re=L.dirname(ts(import.meta.url));function Tt(e){try{let t=V.readFileSync(e);return es.createHash("sha256").update(t).digest("hex")}catch{return null}}function rs(e=L.join(re,"../..")){let t={},r=["src/core/signature.js","src/core/validator.js","src/core/policyEngine.js","src/core/nonceStore.js","src/core/auditLog.js","src/core/schema.js","bin/lbe.js"];for(let s of r){let o=L.join(e,s),n=Tt(o);n&&(t[s]=n)}return t}function ss(e,t=L.join(re,"../..")){let r={valid:!0,mismatches:[],missing:[],checkedFiles:0};for(let[s,o]of Object.entries(e)){let n=L.join(t,s);if(!V.existsSync(n)){r.valid=!1,r.missing.push(s);continue}let a=Tt(n);r.checkedFiles++,a!==o&&(r.valid=!1,r.mismatches.push({file:s,expected:o,actual:a}))}return r}async function ee(e={}){let t=typeof e=="string"||e===null?{manifestPath:e}:e,r=t.rootDir||L.join(re,"../.."),s=t.strict===!0,o=t.manifestPath||L.join(r,"config/integrity.manifest.json");if(!V.existsSync(o))return s?{valid:!1,skipped:!1,reason:"INTEGRITY_MANIFEST_MISSING",message:`Integrity manifest not found: ${o}`,checkedFiles:0,mismatches:[],missing:[]}:{valid:!0,skipped:!0,reason:null,message:"Integrity manifest not found - check skipped",checkedFiles:0,mismatches:[],missing:[]};try{let n=V.readFileSync(o,"utf8"),a=JSON.parse(n),i=ss(a,r);return{...i,skipped:!1,reason:i.valid?null:"INTEGRITY_CHECK_FAILED",message:i.valid?`Integrity check passed (${i.checkedFiles} files verified)`:"Runtime integrity check failed - system may be tampered"}}catch(n){return{valid:!1,skipped:!1,reason:"INTEGRITY_CHECK_ERROR",message:`Integrity check error: ${n.message}`,checkedFiles:0,mismatches:[],missing:[]}}}function $t({outputPath:e=L.join(re,"../../config/integrity.manifest.json"),rootDir:t=L.join(re,"../..")}={}){let r=rs(t),s=JSON.stringify(r,null,2),o=L.dirname(e);return V.existsSync(o)||V.mkdirSync(o,{recursive:!0}),V.writeFileSync(e,s),{outputPath:e,fileCount:Object.keys(r).length,manifest:r}}function Ke(e,t=!1){if(e===void 0)return t;if(e===!0||e===!1)return e;let r=String(e).trim().toLowerCase();return r==="true"||r==="1"||r==="yes"?!0:r==="false"||r==="0"||r==="no"?!1:t}async function jt(e){let t=Ke(e.strict,!1)||Ke(e["integrity-strict"],!1),r=e.manifest?qe.resolve(e.manifest):qe.resolve(e["integrity-manifest"]||"config/integrity.manifest.json"),s=Ke(e.json,!0),o=await ee({manifestPath:r,strict:t});console.log(s?JSON.stringify({ok:o.valid,valid:o.valid,skipped:o.skipped===!0,strict:t,manifestPath:r,checkedFiles:o.checkedFiles,mismatches:o.mismatches||[],missing:o.missing||[],reason:o.reason||null,message:o.message},null,2):o.message),process.exit(o.valid?0:8)}async function Ft(e){let t=qe.resolve(e.out||e.output||e.manifest||"config/integrity.manifest.json"),r=$t({outputPath:t});console.log(JSON.stringify({ok:!0,outputPath:r.outputPath,fileCount:r.fileCount},null,2)),process.exit(0)}import B from"fs";import ge from"path";async function Mt(e){let t=ge.resolve(e.config||e.policy||"config/policy.default.json"),r=ge.resolve(e["policy-sig"]||"config/policy.sig.json"),s=ge.resolve(e["secret-key-file"]||"keys/secret.key"),o=String(e["policy-key-id"]||"policy-signer-v1-2026Q1");B.existsSync(t)||(console.error(JSON.stringify({status:"error",error:"POLICY_FILE_MISSING",message:`Policy file not found: ${t}`},null,2)),process.exit(1)),B.existsSync(s)||(console.error(JSON.stringify({status:"error",error:"SECRET_KEY_MISSING",message:`Secret key file not found: ${s}`},null,2)),process.exit(1));let n=JSON.parse(B.readFileSync(t,"utf8"));(typeof n.version>"u"||typeof n.createdAt>"u")&&(console.error(JSON.stringify({status:"error",error:"POLICY_VERSION_METADATA_MISSING",message:"Policy must include version and createdAt before signing"},null,2)),process.exit(8));let a=B.readFileSync(s,"utf8").trim(),i=ie({policyObj:n,secretKeyB64:a,keyId:o});i.ok||(console.error(JSON.stringify({status:"error",error:i.reason||"POLICY_SIGN_FAILED",message:i.message},null,2)),process.exit(8));let c=ge.dirname(r);B.existsSync(c)||B.mkdirSync(c,{recursive:!0}),B.writeFileSync(r,JSON.stringify(i.envelope,null,2)),console.log(JSON.stringify({status:"ok",message:"Policy signature written",policy:t,policySig:r,keyId:o},null,2)),process.exit(0)}import I from"fs";import b from"path";function Kt(e,t){if(e===void 0)return t;if(e===!0||e===!1)return e;let r=String(e).trim().toLowerCase();return r==="true"||r==="1"||r==="yes"?!0:r==="false"||r==="0"||r==="no"?!1:t}function $(e,t,r,s){e[t]={ok:r,message:s}}function Y(e){try{return I.accessSync(e,I.constants.R_OK),!0}catch{return!1}}function os(e){let t=b.join(e,`.healthcheck-${Date.now()}`);try{return I.mkdirSync(e,{recursive:!0}),I.writeFileSync(t,"ok","utf8"),I.unlinkSync(t),{ok:!0,message:"Data directory writable"}}catch(r){return{ok:!1,message:`Data directory not writable: ${r.message}`}}}async function qt(e){let t=Kt(e.json,!0),r=b.resolve(e.config||e.policy||"config/policy.default.json"),s=b.resolve(e["policy-sig"]||"config/policy.sig.json"),o=b.resolve(e["keys-store"]||"config/keys.json"),n=b.resolve(e["data-dir"]||"data"),a=b.resolve(e.audit||b.join(n,"audit.log.jsonl")),i=b.resolve(e["nonce-db"]||b.join(n,"nonce.db.json")),c=b.resolve(e["rate-db"]||b.join(n,"rate-limit.db.json")),l=b.resolve(e["policy-state"]||b.join(n,"policy.state.json")),u=Kt(e["integrity-strict"],!1),p=b.resolve(e["integrity-manifest"]||"config/integrity.manifest.json"),f={};$(f,"policy",I.existsSync(r)&&Y(r),I.existsSync(r)?`Policy file readable: ${r}`:`Policy file missing: ${r}`),$(f,"policySignature",I.existsSync(s)&&Y(s),I.existsSync(s)?`Policy signature readable: ${s}`:`Policy signature missing: ${s}`),$(f,"trustedKeys",I.existsSync(o)&&Y(o),I.existsSync(o)?`Trusted keys readable: ${o}`:`Trusted keys missing: ${o}`),$(f,"auditLog",I.existsSync(a)&&Y(a),I.existsSync(a)?`Audit log readable: ${a}`:`Audit log missing: ${a}`),$(f,"nonceDb",I.existsSync(i)&&Y(i),I.existsSync(i)?`Nonce DB readable: ${i}`:`Nonce DB missing: ${i}`),$(f,"rateLimitDb",I.existsSync(c)&&Y(c),I.existsSync(c)?`Rate-limit DB readable: ${c}`:`Rate-limit DB missing: ${c}`),$(f,"policyState",I.existsSync(l)&&Y(l),I.existsSync(l)?`Policy state readable: ${l}`:`Policy state missing: ${l}`);let m=os(n);if($(f,"dataWritable",m.ok,m.message),u){let d=await ee({strict:!0,manifestPath:p});$(f,"integrity",d.valid,d.valid?d.message:`${d.reason}: ${d.message}`)}let h=Object.values(f).every(d=>d.ok===!0),y={ok:h,status:h?"healthy":"unhealthy",timestamp:new Date().toISOString(),checks:f};console.log(t?JSON.stringify(y,null,2):`${y.status.toUpperCase()}: ${Object.keys(f).length} checks`),process.exit(h?0:8)}function is(e,t=!1){if(e===void 0)return t;if(e===!0||e===!1)return e;let r=String(e).trim().toLowerCase();return r==="true"||r==="1"||r==="yes"?!0:r==="false"||r==="0"||r==="no"?!1:t}var as=he.dirname(ns(import.meta.url)),cs=he.join(as,"../package.json"),ls=JSON.parse(Jt.readFileSync(cs,"utf-8"));async function ds(){let{command:e,opts:t}=Ve(process.argv.slice(2));t.version&&(console.log(`LBE SDK v${ls.version}`),process.exit(0)),(t.help||!e)&&(Se(),process.exit(0));try{if(t["pub-key-file"])try{t["pub-key"]=Jt.readFileSync(he.resolve(t["pub-key-file"]),"utf-8").trim()}catch(r){console.error(`Error reading public key file: ${r.message}`),process.exit(1)}if(["verify","dryrun","run"].includes(e)){let r=is(t["integrity-strict"],!1),s=he.resolve(t["integrity-manifest"]||"config/integrity.manifest.json"),o=await ee({strict:r,manifestPath:s});o.valid||(console.error(JSON.stringify({status:"error",error:o.reason||"INTEGRITY_CHECK_FAILED",message:o.message},null,2)),process.exit(8))}switch(e){case"init":await et(t);break;case"verify":await It(t);break;case"dryrun":await bt(t);break;case"run":await Lt(t);break;case"audit-verify":await Rt(t);break;case"integrity-check":await jt(t);break;case"integrity-generate":await Ft(t);break;case"policy-sign":await Mt(t);break;case"health":await qt(t);break;default:console.error(`Unknown command: ${e}`),Se(),process.exit(1)}}catch(r){console.error(JSON.stringify({status:"error",error:"INTERNAL_ERROR",message:r.message,stack:process.env.DEBUG?r.stack:void 0})),process.exit(9)}}ds().catch(e=>{console.error(JSON.stringify({status:"error",error:"FATAL_ERROR",message:e.message})),process.exit(9)});