@letterblack/lbe-sdk 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -12
- package/README.md +83 -163
- package/config/policy.default.json +162 -0
- package/dist/cli.js +21 -64
- package/dist/index.js +12 -678
- package/dist/mcp-server.js +19 -29
- package/package.json +8 -18
- package/types.d.ts +26 -0
- package/CHANGELOG.md +0 -47
- package/COMMERCIAL_DISTRIBUTION.md +0 -29
- package/dist/engine.js +0 -78
- /package/{runtime → dist}/lbe_engine.wasm +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,66 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
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(`
|
|
2
|
+
import Gt from"fs";import xe from"path";import{fileURLToPath as gs}from"url";function Ge(e){if(e.length===0)return{command:"help",opts:{}};let t=e[0],r={};for(let s=1;s<e.length;s++)if(e[s].startsWith("--")){let o=e[s].substring(2);if(o.includes("=")){let[n,i]=o.split("=");r[n]=i}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 le(e="unknown"){console.log(`
|
|
54
3
|
\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
|
|
56
|
-
\u2551 Local-first execution governance SDK v${
|
|
4
|
+
\u2551 LetterBlack Sentinel \u2014 CLI Governance \u2551
|
|
5
|
+
\u2551 Local-first execution governance SDK v${e.padEnd(12)}\u2551
|
|
57
6
|
\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
7
|
|
|
59
8
|
USAGE:
|
|
60
9
|
lbe [command] [options]
|
|
61
10
|
|
|
62
11
|
COMMANDS:
|
|
63
|
-
init Initialize
|
|
12
|
+
init Initialize LetterBlack Sentinel environment
|
|
64
13
|
verify Verify a proposal (validate, don't execute)
|
|
65
14
|
dryrun Validate and simulate execution (no changes)
|
|
66
15
|
run Validate and execute a proposal
|
|
@@ -109,14 +58,22 @@ EXAMPLES:
|
|
|
109
58
|
lbe audit-verify --audit ./data/audit.log.jsonl
|
|
110
59
|
lbe verify --in proposal.json --pub-key-file ./keys/public.key
|
|
111
60
|
|
|
112
|
-
For more info, visit: https://github.com/Letterblack0306/LetterBlack-
|
|
113
|
-
`)}import
|
|
114
|
-
`).map(r=>r.trim()).filter(r=>r&&!r.startsWith("#")&&!r.startsWith("!")).map(r=>r.endsWith("/")?r+"**":r):[]}function
|
|
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
|
|
61
|
+
For more info, visit: https://github.com/Letterblack0306/LetterBlack-LBE-Core
|
|
62
|
+
`)}import x from"fs";import $ from"path";import kr from"readline";import be from"tweetnacl";import{canonicalize as We}from"json-canonicalize";function we(e){return Buffer.from(e,"base64")}function Ae(e){return Buffer.from(e).toString("base64")}function de({payloadObj:e,sigB64:t,pubKeyB64:r}){try{let s=Buffer.from(We(e),"utf8"),o=we(t),n=we(r),i=be.sign.detached.verify(new Uint8Array(s),new Uint8Array(o),new Uint8Array(n));return{valid:i,message:i?"Signature verified":"Signature verification failed"}}catch(s){return{valid:!1,message:`Signature verification error: ${s.message}`}}}function He(){let e=be.sign.keyPair();return{publicKey:Ae(e.publicKey),secretKey:Ae(e.secretKey)}}function ze({payloadObj:e,secretKeyB64:t}){try{let r=Buffer.from(We(e),"utf8"),s=we(t),o=be.sign.detached(new Uint8Array(r),new Uint8Array(s));return{signature:Ae(o),error:null}}catch(r){return{signature:null,error:`Signing failed: ${r.message}`}}}import Ze from"fs";import Zt from"path";import Xe from"fs";import zt from"path";var Xt=/^[A-Za-z0-9:_-]{3,128}$/;function Qt(e){return typeof e=="string"&&Xt.test(e)&&e!=="default"}function Q(e){let t=zt.resolve(e);if(!Xe.existsSync(t))return{ok:!1,reason:"KEY_STORE_MISSING",message:`Key store not found: ${t}`,store:null};try{let r=Xe.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 Qe({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(!Qt(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,i=o.expiresAt||o.validUntil;if(typeof n!="string"||typeof i!="string")return{ok:!1,reason:"KEY_LIFECYCLE_INVALID",message:`Key '${t}' must define lifecycle fields 'notBefore' and 'expiresAt'`,publicKey:null};let a=new Date(n),c=new Date(i);return Number.isNaN(a.getTime())||Number.isNaN(c.getTime())?{ok:!1,reason:"KEY_LIFECYCLE_INVALID",message:`Key '${t}' has invalid lifecycle timestamp(s)`,publicKey:null}:a>=c?{ok:!1,reason:"KEY_LIFECYCLE_INVALID",message:`Key '${t}' has notBefore >= expiresAt`,publicKey:null}:s<a?{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 ${i}`,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 ue({policyObj:e,secretKeyB64:t,keyId:r}){let s=ze({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 Z({policyObj:e,keyStore:t,policySigPath:r="./config/policy.sig.json",allowUnsigned:s=!1}){let o=Zt.resolve(r);if(!Ze.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(Ze.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 i=Qe({keyStore:t,keyId:n.keyId,requesterId:void 0});if(!i.ok)return{ok:!1,skipped:!1,reason:"POLICY_SIGNER_NOT_TRUSTED",message:i.message};let a=de({payloadObj:e,sigB64:n.sig,pubKeyB64:i.publicKey});return a.valid?{ok:!0,skipped:!1,reason:null,message:"Policy signature verified",keyId:n.keyId}:{ok:!1,skipped:!1,reason:"POLICY_SIGNATURE_INVALID",message:a.message}}import _e from"fs";import L 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"}],Ne=["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"]},rt=[".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:[]},et={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 T(e){return _e.existsSync(e)}function tt(e,t){return t.filter(r=>T(L.join(e,r))).map(r=>`${r}/**`)}function ur(e){let t=L.join(e,".gitignore");return T(t)?_e.readFileSync(t,"utf8").split(`
|
|
63
|
+
`).map(r=>r.trim()).filter(r=>r&&!r.startsWith("#")&&!r.startsWith("!")).map(r=>r.endsWith("/")?r+"**":r):[]}function B(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=L.join(e,s.file||s.dir);T(o)&&(t.add(s.type),r.push(s.type))}return r.length>0?r:["generic"]}function pr(e){return Ne.find(t=>e.includes(t))??"generic"}function mr(e){let t=cr.filter(s=>T(L.join(e,s))),r=lr.filter(s=>T(L.join(e,s)));try{let s=_e.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]=tt(e,n);r.secrets=rt.filter(o=>{let n=o.split("/")[0].replace(/\*.*/,"");return n.includes("*")||T(L.join(e,n))});let s=B(t.flatMap(o=>et[o]||et.generic).concat(or));if(r.config=B([...s.filter(o=>!o.includes("*")&&!o.endsWith("/**")&&T(L.join(e,o))),...s.filter(o=>o.endsWith("/**")&&T(L.join(e,o.replace("/**","")))),...tt(e,nr)]),r.lockfiles=B(t.flatMap(o=>sr[o]||[]).filter(o=>{let n=o.replace(/\*.*/,"").split("/")[0];return n.includes("*")||T(L.join(e,n))})),!t.some(o=>Ne.includes(o))){let o=mr(e);r.config=B([...r.config,...o.manifests]),r.lockfiles=B([...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 (${rt.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=>Ne.includes(c)),n=o.length===1?ir[o[0]]:"project configuration",i=r.config.slice(0,5).join(", "),a=r.config.length>5?" and related files":"";s.config=`Treat ${i}${a} 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=B([...e.source,...e.docs,...e.tests]),s=[...e.config],o=B([...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 st(e){let t=L.resolve(e||process.cwd()),r=fr(t),s=pr(r),o=yr(t,r),n=ur(t),i=gr(r,s,o),a=hr(o,n);return{projectTypes:r,primaryType:s,surfaces:o,semantics:i,enforcement:a}}function ot(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(`
|
|
64
|
+
`)}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 Er(e){return{...e,approval:[]}}function vr(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 y of["config","keys","data"])x.mkdirSync($.join(e,y),{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[y,S]of Object.entries(n)){let k=$.join(e,y);x.existsSync(k)||x.writeFileSync(k,S)}let i=$.join(e,"keys"),a=$.join(i,"public.key"),c=$.join(i,"secret.key"),l,u;if(x.existsSync(a)&&x.existsSync(c))l=x.readFileSync(a,"utf8").trim(),u=x.readFileSync(c,"utf8").trim();else{let y=He();l=y.publicKey,u=y.secretKey,x.writeFileSync(a,l),x.writeFileSync(c,u,{mode:384})}let f=$.join(e,"config/keys.json"),d=x.existsSync(f)?JSON.parse(x.readFileSync(f,"utf8")):{schemaVersion:"1",defaultKeyId:s,trustedKeys:{}};for(let y of[s,o])d.trustedKeys[y]||(d.trustedKeys[y]={publicKey:l,notBefore:t,expiresAt:r,validFrom:t,validUntil:r,deprecated:!1});d.defaultKeyId=s,x.writeFileSync(f,JSON.stringify(d,null,2));let p=$.join(e,"config/policy.default.json"),g;x.existsSync(p)?g=JSON.parse(x.readFileSync(p,"utf8")):(g={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"]}}}},x.writeFileSync(p,JSON.stringify(g,null,2)));let m=ue({policyObj:g,secretKeyB64:u,keyId:o});return m.ok&&x.writeFileSync($.join(e,"config/policy.sig.json"),JSON.stringify(m.envelope,null,2)),{defaultKeyId:s,secretKeyB64:u,publicKeyB64:l}}async function nt(e={}){let t=process.cwd(),r=e.yes||e.y||!process.stdin.isTTY,s=$.join(t,"lbe.workspace.json");console.log(`
|
|
116
65
|
Scanning workspace...
|
|
117
|
-
`);let{projectTypes:o,primaryType:n,semantics:
|
|
66
|
+
`);let{projectTypes:o,primaryType:n,semantics:i,enforcement:a}=st(t);console.log(ot(o,i,a)),console.log("");let c=a;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(a)),u==="r"&&(c=Er(a))}let l={lbe:!0,version:"0.4.0",state:"local",projectTypes:o,primaryType:n,semantics:i,enforcement:c};return x.writeFileSync(s,JSON.stringify(l,null,2)),console.log("\u2713 Wrote lbe.workspace.json"),vr(t),console.log(`\u2713 Keys and policy ready
|
|
118
67
|
`),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
|
-
`)
|
|
121
|
-
|
|
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)});
|
|
68
|
+
`),{success:!0,contract:l}}import Pe from"fs";import te from"path";import dt from"fs";import _r from"path";import w from"fs";import Oe from"path";import xr from"crypto";var wr={timeoutMs:5e3,pollMs:15,staleMs:3e4};function Ar(e){return e+".lock"}function it(e){try{let t=w.openSync(e,"wx");return w.writeSync(t,`pid:${process.pid}:${Date.now()}`),w.closeSync(t),!0}catch(t){if(t.code==="EEXIST"||t.code==="EPERM"||t.code==="EBUSY"||t.code==="EACCES")return!1;throw t}}function at(e,t){try{let r=w.statSync(e);if(Date.now()-r.mtimeMs>t)try{w.unlinkSync(e)}catch{}}catch{}}function br(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 ct(e,t,r){let s=typeof t=="function"?t:r,o=typeof t=="function"?{}:t||{},{timeoutMs:n,pollMs:i,staleMs:a}={...wr,...o},c=Oe.dirname(e);w.existsSync(c)||w.mkdirSync(c,{recursive:!0});let l=Ar(e),u=Date.now()+n,f=!1;for(;!f&&(f=it(l),!f);){if(Date.now()>=u){if(at(l,a),f=it(l),f)break;let p=new Error(`withFileLock: timeout acquiring ${l} after ${n}ms`);throw p.code="ELOCKTIMEOUT",p}at(l,a);let d=Math.floor(Math.random()*i);br(i+d)}try{return s()}finally{try{w.unlinkSync(l)}catch{}}}function A(e,t,r={}){let s=Oe.dirname(e);w.existsSync(s)||w.mkdirSync(s,{recursive:!0});let o=Oe.join(s,`.tmp-${Date.now()}-${xr.randomBytes(4).toString("hex")}`);try{w.writeFileSync(o,t,r),w.renameSync(o,e)}catch(n){try{w.existsSync(o)&&w.unlinkSync(o)}catch{}throw n}}function lt(e){try{if(!w.existsSync(e))return null;let t=w.readFileSync(e,"utf8");return JSON.parse(t)}catch(t){return console.error(`[atomicWrite] Failed to read JSON from ${e}:`,t.message),null}}function ut(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 Nr(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 ft(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 Or(e){if(!dt.existsSync(e))return{schemaVersion:"1",lastAccepted:null,updatedAt:null};try{let t=JSON.parse(dt.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 Cr(e,t){let r=JSON.stringify(t,null,2);A(e,r,{encoding:"utf8"})}function q({policyObj:e,statePath:t=_r.resolve("data/policy.state.json"),maxCreatedAtSkewSec:r=31536e3,nowSec:s=Math.floor(Date.now()/1e3),persist:o=!0}){let n=ut(e?.version);if(!n.ok)return{ok:!1,reason:n.reason,message:n.message,updated:!1};let i=ft(e?.createdAt);if(!i.ok)return{ok:!1,reason:i.reason,message:i.message,updated:!1};let a=Math.abs(s-i.epochSec),c=Number.isFinite(r)&&r>0?Math.floor(r):31536e3;if(a>c)return{ok:!1,reason:"POLICY_CREATED_AT_SKEW_EXCEEDED",message:`Policy createdAt skew ${a}s exceeds allowed ${c}s`,updated:!1};let l;try{l=Or(t)}catch(m){return{ok:!1,reason:"POLICY_STATE_CORRUPT",message:m.message,updated:!1}}let u=l.lastAccepted,f=null,d=null,p=0;if(u&&(f=ut(u.version),d=ft(u.createdAt),f.ok&&d.ok)){if(p=Nr(n,f),p<0)return{ok:!1,reason:"POLICY_VERSION_REGRESSION",message:`Policy version regression: current '${n.raw}' < last '${f.raw}'`,updated:!1};if(p===0&&i.epochSec<d.epochSec)return{ok:!1,reason:"POLICY_CREATED_AT_REGRESSION",message:`Policy createdAt regression: current '${e.createdAt}' < last '${u.createdAt}'`,updated:!1};if(p>0&&i.epochSec<d.epochSec)return{ok:!1,reason:"POLICY_CREATED_AT_REGRESSION",message:"Policy createdAt must be monotonic when version increases",updated:!1}}let g=!u||!f?.ok||!d?.ok||p>0||p===0&&i.epochSec>d.epochSec;if(o&&g){let m={schemaVersion:"1",lastAccepted:{version:e.version,createdAt:e.createdAt,environment:e.environment||null},updatedAt:new Date().toISOString()};Cr(t,m)}return{ok:!0,reason:null,message:"Policy version guard passed",updated:g}}import pt from"fs";import yt from"path";import{fileURLToPath as Rr}from"url";var Lr=yt.dirname(Rr(import.meta.url)),Ce=yt.join(Lr,"lbe_engine.wasm"),mt={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"}},Pr={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"}},Dr={1:"KEY_ID_INVALID",2:"KEY_NOT_TRUSTED",3:"KEY_DEPRECATED",4:"KEY_REQUESTER_MISMATCH",5:"KEY_LIFECYCLE_INVALID",6:"KEY_NOT_YET_VALID",7:"KEY_EXPIRED"},Tr={0:"schema",1:"timestamp",2:"key",3:"signature",4:"rate_limit",5:"nonce",6:"policy",255:"ok"},$r=["LOW","MEDIUM","HIGH","CRITICAL"],Fr={ECHO:0,READ_FILE:1,WRITE_FILE:2,PATCH_FILE:3,DELETE_FILE:4,RUN_SHELL:5},fe=null;function M(){if(fe)return fe;if(!pt.existsSync(Ce))throw new Error(`LBE engine missing: ${Ce}`);let e=pt.readFileSync(Ce);return fe=new WebAssembly.Instance(new WebAssembly.Module(e),{}),fe}function pe(){return new Uint8Array(M().exports.memory.buffer)}function gt(){return M().exports.lbe_in_ptr()}function ht(){return M().exports.lbe_out_ptr()}function jr(){return M().exports.lbe_buf_size()}function kt(e){let t=new TextEncoder().encode(e),r=pe(),s=gt();r.set(t,s),r[s+t.length]=0}function St(){let e=pe(),t=ht(),r=t;for(;e[r]!==0&&r-t<jr();)r++;return new TextDecoder().decode(e.slice(t,r))}function Kr(e){let t=pe(),r=gt(),s=new DataView(t.buffer,r);e.forEach((o,n)=>s.setUint32(n*4,o>>>0,!0))}function qr(){let e=pe(),t=ht(),r=new DataView(e.buffer,t);return{stage:r.getUint32(0,!0),code:r.getUint32(4,!0)}}function It(e){Kr([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,e.cmdTimestamp>>>0,e.nowSec>>>0,e.maxClockSkewSec>>>0,e.keyIdFormatValid?1:0,e.keyFound?1:0,e.keyNotDeprecated?1:0,e.keyRequesterMatches?1:0,e.keyNotBeforeOk?1:0,e.keyNotExpired?1:0,e.keyLifecycleFieldsPresent?1:0,e.signatureValid?1:0,e.rateLimitOk?1:0,e.rateLimitRetryAfterSec>>>0,e.nonceOk?1:0,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]),M().exports.lbe_validate_pipeline();let{stage:t,code:r}=qr();return{ok:t===255,stage:t,stageLabel:Tr[t]||"unknown",code:r,schemaError:t===0?Pr[r]?.error||"Schema invalid":null,keyReason:t===2?Dr[r]||"KEY_ERROR":null,policyResult:t===6?{...mt[r]||mt[1],code:r}:null,retryAfterSec:t===4?r:0,skewSec:t===1?r:0}}function Re({ttlSec:e,nowSec:t,newKey:r,existingEntries:s}){let o=[`${e}:${t}`,r,...s].join(`
|
|
69
|
+
`)+`
|
|
70
|
+
`;if(kt(o),M().exports.lbe_nonce_check()!==0)return{ok:!1,updatedEntriesText:null};let i=St();return{ok:!0,updatedEntriesText:i.startsWith(`OK
|
|
71
|
+
`)?i.slice(3):i}}function Et({windowSec:e,maxRequests:t,nowSec:r,requesterId:s,existingEntries:o}){let n=[`${e}:${t}:${r}`,s,...o].join(`
|
|
72
|
+
`)+`
|
|
73
|
+
`;kt(n);let i=M().exports.lbe_rate_check()!==0,a=St();if(i){let c=parseInt(a.match(/^EXCEEDED:(\d+)/)?.[1]??"1",10),l=a.replace(/^EXCEEDED:\d+\n/,"");return{ok:!1,retryAfterSec:c,updatedEntriesText:l}}return{ok:!0,retryAfterSec:0,updatedEntriesText:a.startsWith(`OK
|
|
74
|
+
`)?a.slice(3):a}}function vt(e,t=!1){let r=Fr[e]??0,s=M().exports.lbe_classify_risk(r,t?1:0);return $r[s]??"LOW"}import Le from"path";function Mr(e){let t=n=>e!=null&&Object.prototype.hasOwnProperty.call(e,n),r=n=>typeof n=="string",s=e?.payload,o=e?.signature;return{hasId:t("id"),idValid:r(e?.id)&&/^[A-Z_]+$/.test(e.id)&&e.id.length>=1&&e.id.length<=50,hasCommandId:t("commandId"),commandIdValid:r(e?.commandId)&&/^[a-f0-9-]+$/.test(e.commandId)&&e.commandId.length===36,hasRequesterId:t("requesterId"),requesterIdValid:r(e?.requesterId)&&e.requesterId.length>=3&&e.requesterId.length<=100,hasSessionId:t("sessionId"),sessionIdValid:r(e?.sessionId)&&e.sessionId.length>=3,hasTimestamp:t("timestamp"),timestampValid:typeof e?.timestamp=="number"&&e.timestamp>=1e9,hasNonce:t("nonce"),nonceValid:r(e?.nonce)&&e.nonce.length>=32&&e.nonce.length<=128,hasRequires:t("requires"),requiresValid:Array.isArray(e?.requires)&&e.requires.length>=1&&e.requires.every(r),hasPayload:t("payload")&&typeof s=="object"&&s!==null&&!Array.isArray(s),hasPayloadAdapter:s!=null&&Object.prototype.hasOwnProperty.call(s,"adapter"),payloadAdapterValid:r(s?.adapter),hasSignature:t("signature")&&typeof o=="object"&&o!==null&&!Array.isArray(o),hasSignatureAlg:o!=null&&Object.prototype.hasOwnProperty.call(o,"alg"),signatureAlgValid:o?.alg==="ed25519",hasSignatureKeyId:o!=null&&Object.prototype.hasOwnProperty.call(o,"keyId"),hasSignatureSig:o!=null&&Object.prototype.hasOwnProperty.call(o,"sig"),signatureSigValid:r(o?.sig)&&o.sig.length>=10,hasRisk:t("risk"),riskValid:["LOW","MEDIUM","HIGH","CRITICAL"].includes(e?.risk)}}function Vr(e,t){let r=!!(e&&e.default==="DENY"&&e.requesters&&typeof e.requesters=="object"),s=e?.requesters?.[t.requesterId],o=t.id?.toLowerCase()??"",n=!!s?.allowCommands?.some(p=>p.toLowerCase()===o),i=!!s?.allowAdapters?.includes(t.payload?.adapter),a=!!t.payload?.cwd,c=!1,l=!1,u=!1;if(a){let p=s?.filesystem?.roots??[];if(c=p.length>0,c){let g=Le.resolve(t.payload.cwd);l=p.some(y=>{let S=Le.resolve(y);return g===S||g.startsWith(S+Le.sep)}),u=(s?.filesystem?.denyPatterns??[]).some(y=>new RegExp("^"+y.replace(/\./g,"\\.").replace(/\*\*/g,".*").replace(/\*/g,"[^/]*")+"$").test(g))}}let f=!1,d=!0;if(t.id==="RUN_SHELL"){f=!0;let p=s?.exec?.allowCmds??[],g=s?.exec?.denyCmds??[],m=t.payload?.cmd;g.includes(m)?d=!1:d=p.length===0||p.includes(m)}return{policyConfigured:r,requesterConfigured:!!s,commandAllowed:n,adapterAllowed:i,filesystemRequired:a,filesystemRootsDefined:c,filesystemOk:l,pathDenied:u,shellRequired:f,shellCommandOk:d}}function Yr(e,t,r,s=new Date){if(!e||!t)return{keyIdFormatValid:!1,keyFound:!1,keyNotDeprecated:!1,keyRequesterMatches:!1,keyNotBeforeOk:!1,keyNotExpired:!1,keyLifecycleFieldsPresent:!1,publicKey:null};let n=/^[A-Za-z0-9:_-]{3,128}$/.test(t)&&t!=="default";if(!n)return{keyIdFormatValid:n,keyFound:!1,keyNotDeprecated:!1,keyRequesterMatches:!1,keyNotBeforeOk:!1,keyNotExpired:!1,keyLifecycleFieldsPresent:!1,publicKey:null};let i=e.trustedKeys?.[t],a=!!i;if(!a)return{keyIdFormatValid:n,keyFound:a,keyNotDeprecated:!1,keyRequesterMatches:!1,keyNotBeforeOk:!1,keyNotExpired:!1,keyLifecycleFieldsPresent:!1,publicKey:null};let c=!i.deprecated,l=!i.requesterId||i.requesterId===r,u=i.notBefore||i.validFrom,f=i.expiresAt||i.validUntil,d=typeof u=="string"&&typeof f=="string",p=!1,g=!1;if(d){let m=new Date(u),y=new Date(f);!isNaN(m.getTime())&&!isNaN(y.getTime())&&m<y&&(p=s>=m,g=s<y)}return{keyIdFormatValid:n,keyFound:a,keyNotDeprecated:c,keyRequesterMatches:l,keyNotBeforeOk:p,keyNotExpired:g,keyLifecycleFieldsPresent:d,publicKey:i.publicKey??null}}function xt(e){return(e?.entries??[]).map(t=>`${t.key}:${t.timestamp}`)}function wt(e){return e.split(`
|
|
75
|
+
`).filter(Boolean).map(t=>{let r=t.lastIndexOf(":");return{key:t.slice(0,r),timestamp:parseInt(t.slice(r+1),10)||0}})}function Jr(e){return(e?.entries??[]).map(t=>`${t.requesterId}:${t.timestamp}`)}function Br(e){return e.split(`
|
|
76
|
+
`).filter(Boolean).map(t=>{let r=t.lastIndexOf(":");return{requesterId:t.slice(0,r),timestamp:parseInt(t.slice(r+1),10)||0}})}function ee({commandObj:e,pubKeyB64:t,keyStore:r,nonceDb:s,policy:o,rateLimiter:n,policyStatePath:i}){let a={valid:!1,commandId:e?.commandId,checks:{},errors:[]},c=Math.floor(Date.now()/1e3),l=new Date,u=Number.isFinite(o?.security?.maxClockSkewSec)?o.security.maxClockSkewSec:600;if(i&&o?.version!==void 0)try{let h=q({policyObj:o,statePath:i});if(a.checks.policyVersion=h.ok,!h.ok)return a.errors.push({type:"POLICY_VERSION_INVALID",message:h.message}),a}catch{a.checks.policyVersion=!0}else a.checks.policyVersion=!0;let f=Mr(e),d=e?.signature?.keyId,p=Yr(r,d,e?.requesterId,l),g=!1,m=p.publicKey;if(!m&&t&&(m=t),m){let h={...e};delete h.signature,g=de({payloadObj:h,sigB64:e?.signature?.sig,pubKeyB64:m}).valid}let y=!0,S=0;if(g&&n&&typeof n.db<"u"){let h=o?.requesters?.[e.requesterId]?.rateLimit||{},_=o?.security?.defaultRateLimit||{},O=h.windowSec??_.windowSec??60,z=h.maxRequests??_.maxRequests??30,X=Et({windowSec:O,maxRequests:z,nowSec:c,requesterId:e.requesterId,existingEntries:Jr(n.db)});y=X.ok,S=X.retryAfterSec,X.ok&&(n.db.entries=Br(X.updatedEntriesText))}else if(g&&n&&typeof n.checkAndRecord=="function"){let h=o?.requesters?.[e.requesterId]?.rateLimit||{},_=o?.security?.defaultRateLimit||{},O=n.checkAndRecord({requesterId:e.requesterId,nowSec:c,windowSec:h.windowSec??_.windowSec??60,maxRequests:h.maxRequests??_.maxRequests??30});y=O.ok,S=O.retryAfterSec??0}let k=!0,D=`${e?.requesterId}|${e?.sessionId}|${e?.nonce}`,K=3600;if(g&&y&&s)if(typeof s.checkAndRecord=="function")if(s.db){let h=Re({ttlSec:K,nowSec:c,newKey:D,existingEntries:xt(s.db)});k=h.ok,h.ok&&(s.db.entries=wt(h.updatedEntriesText))}else k=s.checkAndRecord({requesterId:e.requesterId,sessionId:e.sessionId,nonce:e.nonce}).ok;else{let h=Re({ttlSec:K,nowSec:c,newKey:D,existingEntries:xt(s)});k=h.ok,h.ok&&(s.entries=wt(h.updatedEntriesText))}let Ue=Vr(o,e??{}),I=It({...f,cmdTimestamp:e?.timestamp??0,nowSec:c,maxClockSkewSec:u,...p,signatureValid:g,rateLimitOk:y,rateLimitRetryAfterSec:S,nonceOk:k,...Ue}),b=I.stage;if(a.checks.schema=b!==0,b>=1&&(a.checks.timestamp=b!==1),b>=2&&(a.checks.keyId=b!==2),b>=2&&(a.checks.signature=b!==2&&b!==3),b>=4&&(a.checks.rateLimit=b!==4),b>=5&&(a.checks.nonce=b!==5),(b>=6||I.ok)&&(a.checks.policy=b!==6),!I.ok){let h=I.stageLabel;if(h==="schema")a.errors.push({type:"SCHEMA_ERROR",message:I.schemaError||"Schema invalid"});else if(h==="timestamp")a.errors.push({type:"TIMESTAMP_SKEW_EXCEEDED",message:`Command timestamp skew ${I.skewSec}s exceeds allowed ${u}s`});else if(h==="key"){let _=I.keyReason||"KEY_ERROR",O={KEY_ID_INVALID:`Invalid keyId '${d}'`,KEY_NOT_TRUSTED:`Key '${d}' is not in trusted key store`,KEY_DEPRECATED:`Key '${d}' is deprecated`,KEY_REQUESTER_MISMATCH:`Key '${d}' is not authorized for requester '${e?.requesterId}'`,KEY_LIFECYCLE_INVALID:`Key '${d}' must define notBefore and expiresAt`,KEY_NOT_YET_VALID:`Key '${d}' is not yet valid`,KEY_EXPIRED:`Key '${d}' has expired`};a.errors.push({type:_,message:O[_]||_})}else h==="signature"?a.errors.push({type:"SIGNATURE_INVALID",message:m?"Signature verification failed":"No public key available"}):h==="rate_limit"?a.errors.push({type:"RATE_LIMIT_EXCEEDED",message:`Rate limit exceeded. Retry after ${I.retryAfterSec}s`}):h==="nonce"?a.errors.push({type:"REPLAY_NONCE",message:"Nonce has already been used"}):h==="policy"&&I.policyResult?a.errors.push({type:I.policyResult.reason,message:I.policyResult.message}):a.errors.push({type:"VALIDATION_FAILED",message:`Failed at stage: ${h}`});return a}return a.valid=!0,a.risk=vt(e.id,e.payload?.cmd==="rm"),a.message="Command validation successful",a}import me from"fs";import Ur from"path";var V=class{constructor(t,r=3600){this.dbPath=t,this.ttlSec=r,this.db={entries:[]}}async load(){if(!me.existsSync(this.dbPath)){this.db={entries:[]};return}try{let t=me.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=Ur.dirname(this.dbPath);me.existsSync(t)||me.mkdirSync(t,{recursive:!0}),A(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(i=>o-i.timestamp<=this.ttlSec);let n=`${t}|${r}|${s}`;return this.db.entries.some(i=>i.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}}};async function At(e){let{in:t}=e,r=e.config||e.policy,s=e["pub-key"],o=e["keys-store"]||te.resolve("config/keys.json"),n=e["policy-sig"]||te.resolve("config/policy.sig.json"),i=e["policy-state"]||te.resolve("data/policy.state.json"),a=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=te.resolve(t),k=Pe.readFileSync(S,"utf-8");c=JSON.parse(k)}catch(S){console.error(JSON.stringify({status:"error",error:"INVALID_PROPOSAL_FILE",message:S.message})),process.exit(5)}let l;try{let S=r||te.resolve("config/policy.default.json");Pe.existsSync(S)||(console.error(JSON.stringify({status:"error",error:"MISSING_POLICY",message:`Policy file not found: ${S}`})),process.exit(1));let k=Pe.readFileSync(S,"utf-8");l=JSON.parse(k)}catch(S){console.error(JSON.stringify({status:"error",error:"INVALID_POLICY",message:S.message})),process.exit(1)}let u=Q(o),f=u.ok?u.store:null,d=Z({policyObj:l,keyStore:f,policySigPath:n,allowUnsigned:a});d.ok||(console.error(JSON.stringify({status:"error",error:d.reason,message:d.message},null,2)),process.exit(8));let p=q({policyObj:l,statePath:i,maxCreatedAtSkewSec:l?.security?.maxPolicyCreatedAtSkewSec});p.ok||(console.error(JSON.stringify({status:"error",error:p.reason,message:p.message},null,2)),process.exit(8));let g=new V(te.resolve("data/nonce.db.json"));await g.load(),!f&&!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 m=ee({commandObj:c,pubKeyB64:s,keyStore:f,nonceDb:g,policy:l}),y={status:m.valid?"valid":"invalid",commandId:c.commandId||"N/A",checks:m.checks,errors:m.errors||[],risk:m.risk||"UNKNOWN"};console.log(JSON.stringify(y,null,2)),m.valid||(m.checks.schema===!1&&process.exit(5),m.checks.signature===!1&&process.exit(3),m.checks.nonce===!1&&process.exit(4),m.checks.timestamp===!1&&process.exit(6),m.checks.rateLimit===!1&&process.exit(7),m.checks.policy===!1&&process.exit(2),process.exit(9)),process.exit(0)}import $e from"fs";import oe from"path";async function bt(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 Gr}from"child_process";import De from"path";function Wr(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 _t(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 i=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(i.length>0&&!i.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(f=>{let d=De.resolve(f),p=De.resolve(s.cwd);return p===d||p.startsWith(d+De.sep)}))return{adapter:"shell",commandId:e.commandId,status:"blocked",error:`CWD '${s.cwd}' not authorized`,exitCode:2};let u=Wr(s.args);if(!u.ok)return{adapter:"shell",commandId:e.commandId,status:"blocked",error:u.error,exitCode:2};try{let f=Gr(s.cmd,u.args,{cwd:s.cwd,timeout:o,encoding:"utf8",maxBuffer:n,stdio:["pipe","pipe","pipe"],shell:!1});if(f.error)throw f.error;let d=`${f.stdout||""}${f.stderr||""}`,p=f.status??1;return p!==0?{adapter:"shell",commandId:e.commandId,command:s.cmd,status:"error",error:d.substring(0,n)||`Command exited with code ${p}`,exitCode:p,timestamp:new Date().toISOString()}:{adapter:"shell",commandId:e.commandId,command:s.cmd,status:"completed",output:d.substring(0,n),exitCode:0,timestamp:new Date().toISOString()}}catch(f){return{adapter:"shell",commandId:e.commandId,command:s.cmd,status:"error",error:f.message,exitCode:f.status||1,timestamp:new Date().toISOString()}}}import ie from"fs";import se from"path";import Y from"fs";import ye from"path";import Hr from"crypto";function ge(e,t){let r=t||ye.resolve("data/backups");Y.existsSync(r)||Y.mkdirSync(r,{recursive:!0});let s=ye.resolve(e),o=Y.existsSync(s),n=null,i=null;o&&(n=Y.readFileSync(s),i=Hr.createHash("sha256").update(n).digest("hex"));let a=ye.basename(s).replace(/[^a-zA-Z0-9._-]/g,"_"),c=`${Date.now()}-${i?i.slice(0,8):"new"}-${a}`,l=o?ye.join(r,c):null;return o&&n!==null&&A(l,n),{originalPath:s,backupPath:l,existed:o,hash:i,createdAt:new Date().toISOString()}}function U(e){if(!e)return{restored:!1,error:"No backup metadata"};let{originalPath:t,backupPath:r,existed:s}=e;if(!s)try{return Y.existsSync(t)&&Y.unlinkSync(t),{restored:!0,action:"deleted"}}catch(o){return{restored:!1,error:o.message}}if(!r||!Y.existsSync(r))return{restored:!1,error:"Backup file not found at: "+r};try{let o=Y.readFileSync(r);return A(t,o),{restored:!0,action:"restored"}}catch(o){return{restored:!1,error:o.message}}}var zr=10*1024*1024;function Xr(e,t){return e?se.isAbsolute(e)?se.resolve(e):se.resolve(t||process.cwd(),e):null}function Qr(e,t){let r=se.resolve(e);return t.some(s=>{let o=se.resolve(s);return r===o||r.startsWith(o+se.sep)})}function Zr(e,t){for(let r of t||[])if(new RegExp("^"+r.replace(/\./g,"\\.").replace(/\*\*/g,".*").replace(/\*/g,"[^/\\\\]*")+"$").test(e))return r;return null}function re(e,t,r,s=2){return{adapter:"file",commandId:e.commandId,status:"blocked",errorCode:t,error:r,exitCode:s}}function F(e,t,r,s=null,o=1){return{adapter:"file",commandId:e.commandId,status:"error",errorCode:t,error:r,backup:s?he(s):null,exitCode:o}}function he(e){return e?{path:e.backupPath,existed:e.existed,hash:e.hash,createdAt:e.createdAt}:null}async function Nt(e,t,r){let s=e.payload,o=s.action,n=s.cwd||process.cwd(),i=Xr(s.target,n);if(!o)return re(e,"FILE_NO_ACTION","payload.action is required");if(!i&&o!=="noop")return re(e,"FILE_NO_TARGET","payload.target is required");let a=r?.filesystem?.roots||[];if(a.length===0)return re(e,"FILE_NO_ROOTS","No filesystem roots defined for requester");if(!Qr(i,a))return re(e,"FILE_OUTSIDE_ROOT",`'${i}' is outside allowed roots`);let c=Zr(i,r?.filesystem?.denyPatterns);if(c)return re(e,"FILE_PATH_DENIED",`'${i}' matches deny pattern: ${c}`);switch(o){case"read":return es(e,i);case"write":return ts(e,i,s);case"patch":return rs(e,i,s);case"delete":return ss(e,i);default:return re(e,"FILE_UNKNOWN_ACTION",`Unknown action: '${o}'`)}}function es(e,t){if(!ie.existsSync(t))return F(e,"FILE_NOT_FOUND",`Not found: ${t}`);try{let r=ie.statSync(t);if(r.size>zr)return F(e,"FILE_TOO_LARGE","File exceeds 10 MB read limit");let s=ie.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 F(e,"FILE_READ_ERROR",r.message)}}function ts(e,t,r){let s=r.content;if(s==null)return F(e,"FILE_MISSING_CONTENT","payload.content is required for write");let o=Te(t);try{return A(t,s,{encoding:"utf8"}),{adapter:"file",action:"write",commandId:e.commandId,status:"completed",target:t,backup:he(o),output:`Wrote ${Buffer.byteLength(s,"utf8")} bytes to ${t}`,exitCode:0}}catch(n){return U(o),F(e,"FILE_WRITE_ERROR",n.message,o)}}function rs(e,t,r){let s=r.content;if(s==null)return F(e,"FILE_MISSING_CONTENT","payload.content is required for patch");let o=Te(t);try{return A(t,s,{encoding:"utf8"}),{adapter:"file",action:"patch",commandId:e.commandId,status:"completed",target:t,backup:he(o),output:`Patched ${t} (${Buffer.byteLength(s,"utf8")} bytes)`,exitCode:0}}catch(n){return U(o),F(e,"FILE_PATCH_ERROR",n.message,o)}}function ss(e,t){if(!ie.existsSync(t))return F(e,"FILE_NOT_FOUND",`Not found: ${t}`);let r=Te(t);try{return ie.unlinkSync(t),{adapter:"file",action:"delete",commandId:e.commandId,status:"completed",target:t,backup:he(r),output:`Deleted ${t}`,exitCode:0}}catch(s){return U(r),F(e,"FILE_DELETE_ERROR",s.message,r)}}function Te(e){try{return ge(e)}catch{return null}}async function Ot(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:i,issueType:a,description:c,severity:l,metadata:u}=e.payload||{};if(!a||!c)return{adapter:"observer",commandId:e.commandId,status:"error",error:"Observer payload must include issueType and description",exitCode:1};let f=["low","medium","high","critical"];return l&&!f.includes(l)?{adapter:"observer",commandId:e.commandId,status:"error",error:`Invalid severity '${l}'. Must be one of: ${f.join(", ")}`,exitCode:1}:{adapter:"observer",commandId:e.commandId,status:"recorded",timestamp:new Date().toISOString(),requesterId:e.requesterId,observation:{source:n||"unknown",context:i||"unknown",issueType:a,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 Ct={noop:bt,shell:_t,file:Nt,observer:Ot};function os(e){return Ct[e]}async function ke(e,t,r,s){let o=os(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 jo=Object.keys(Ct);async function Rt(e){let{in:t}=e,r=e.config||e.policy,s=e["pub-key"],o=e["keys-store"]||oe.resolve("config/keys.json"),n=e["policy-sig"]||oe.resolve("config/policy.sig.json"),i=e["policy-state"]||oe.resolve("data/policy.state.json"),a=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=oe.resolve(t),D=$e.readFileSync(k,"utf-8");c=JSON.parse(D)}catch(k){console.error(JSON.stringify({status:"error",error:"INVALID_PROPOSAL_FILE",message:k.message})),process.exit(5)}let l;try{let k=r||oe.resolve("config/policy.default.json");$e.existsSync(k)||(console.error(JSON.stringify({status:"error",error:"MISSING_POLICY",message:`Policy file not found: ${k}`})),process.exit(1));let D=$e.readFileSync(k,"utf-8");l=JSON.parse(D)}catch(k){console.error(JSON.stringify({status:"error",error:"INVALID_POLICY",message:k.message})),process.exit(1)}let u=Q(o),f=u.ok?u.store:null,d=Z({policyObj:l,keyStore:f,policySigPath:n,allowUnsigned:a});d.ok||(console.error(JSON.stringify({status:"error",error:d.reason,message:d.message},null,2)),process.exit(8));let p=q({policyObj:l,statePath:i,maxCreatedAtSkewSec:l?.security?.maxPolicyCreatedAtSkewSec});p.ok||(console.error(JSON.stringify({status:"error",error:p.reason,message:p.message},null,2)),process.exit(8));let g=new V(oe.resolve("data/nonce.db.json"));await g.load(),!f&&!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 m=ee({commandObj:c,pubKeyB64:s,keyStore:f,nonceDb:g,policy:l});if(!m.valid){let k={status:"invalid",commandId:c.commandId||"N/A",checks:m.checks,errors:m.errors||[],executionResult:null};console.log(JSON.stringify(k,null,2)),m.checks.schema===!1&&process.exit(5),m.checks.signature===!1&&process.exit(3),m.checks.nonce===!1&&process.exit(4),m.checks.timestamp===!1&&process.exit(6),m.checks.rateLimit===!1&&process.exit(7),m.checks.policy===!1&&process.exit(2),process.exit(9)}let y;try{let k=l.requesters?.[c.requesterId];y=await ke("noop",c,l,k)}catch(k){y={adapter:"noop",status:"error",error:k.message}}let S={status:"valid_simulated",commandId:c.commandId||"N/A",checks:m.checks,risk:m.risk||"UNKNOWN",executionResult:{adapter:y.adapter,status:y.status,output:y.output||y.error||"",exitCode:y.exitCode||0,note:"This is a simulation using noop adapter. No actual execution occurred."}};console.log(JSON.stringify(S,null,2)),process.exit(0)}import Ee from"fs";import R from"path";import ds from"crypto";import J from"fs";import Fe from"path";import ns from"crypto";function Lt(e){return ns.createHash("sha256").update(e).digest("hex")}function is(e){try{if(!J.existsSync(e))return"GENESIS";let t=J.readFileSync(e,"utf8").trim();if(!t)return"GENESIS";let r=t.split(`
|
|
77
|
+
`),s=r[r.length-1];try{return JSON.parse(s).hash||"GENESIS"}catch{return"GENESIS"}}catch{return"GENESIS"}}function je(e,t){let r=Fe.dirname(e);J.existsSync(r)||J.mkdirSync(r,{recursive:!0});let s;return ct(e,()=>{let o=is(e),n={...t,prevHash:o,timestamp:new Date().toISOString()};delete n.hash;let i=JSON.stringify(n),a=Lt(i),c=JSON.stringify({...n,hash:a}),l="";J.existsSync(e)&&(l=J.readFileSync(e,"utf8"));try{A(e,l+c+`
|
|
78
|
+
`,{encoding:"utf8"})}catch(u){throw new Error(`Audit log write failed: ${u.message}`)}s={success:!0,hash:a,prevHash:o,message:"Audit entry appended"}}),s}function Pt(e,t={}){let r=t.failFast!==!1,s=Number.isFinite(t.maxEntries)&&t.maxEntries>0?Math.floor(t.maxEntries):null,o={ok:!0,file:Fe.resolve(e),entries:0,valid:!0,firstInvalidIndex:null,reason:null,errors:[],message:"Audit log verified"};try{if(!J.existsSync(e))return o.message="Audit log file not found (treated as empty)",o;let n=J.readFileSync(e,"utf8").trim();if(!n)return o.message="Empty audit log",o;let i=n.split(`
|
|
79
|
+
`),a=s?i.slice(0,s):i;o.entries=a.length;let c="GENESIS";for(let l=0;l<a.length;l++){let u;try{u=JSON.parse(a[l])}catch{let g={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??=g.reason,o.errors.push(g),r)break;continue}if(u.prevHash!==c){let g={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??=g.reason,o.errors.push(g),r)break}let f={...u},d=f.hash;delete f.hash;let p=Lt(JSON.stringify(f));if(d!==p){let g={index:l,reason:"HASH_MISMATCH",message:`Expected hash '${p}', got '${d}'`};if(o.valid=!1,o.ok=!1,o.firstInvalidIndex??=l,o.reason??=g.reason,o.errors.push(g),r)break}c=d}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:Fe.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 Se from"fs";import as from"path";var Ie=class{constructor(t){this.dbPath=t,this.db={entries:[]}}async load(){try{if(!Se.existsSync(this.dbPath)){this.db={entries:[]};return}let t=Se.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=as.dirname(this.dbPath);Se.existsSync(t)||Se.mkdirSync(t,{recursive:!0}),A(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),i=Number.isFinite(s)&&s>0?s:60,a=Number.isFinite(o)&&o>0?o:30,c=n-i;this.db.entries=this.db.entries.filter(u=>u.timestamp>=c);let l=this.db.entries.filter(u=>u.requesterId===t);if(l.length>=a){let u=l.sort((d,p)=>d.timestamp-p.timestamp)[0],f=Math.max(1,i-(n-u.timestamp));return{ok:!1,reason:"RATE_LIMIT_EXCEEDED",message:`Rate limit exceeded for '${t}' (${a}/${i}s)`,retryAfterSec:f}}return this.db.entries.push({requesterId:t,timestamp:n}),{ok:!0,reason:null,message:"Rate limit check passed",retryAfterSec:0}}};import ls from"crypto";import cs from"path";var qe=class{constructor(t){this.dbPath=t||cs.resolve("data/checkpoints.db.json"),this.store={checkpoints:{},tokens:{}},this._load()}_load(){let t=lt(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);A(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}},Ke=null;function Dt(e){return Ke||(Ke=new qe(e)),Ke}var Ve=class{constructor(t){this.store=Dt(t),this._pendingResolvers=new Map}createToken(t,r={}){let s=ls.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}},Me=null;function Tt(e){return Me||(Me=new Ve(e)),Me}function Ye(e){return ds.createHash("sha256").update(JSON.stringify(e)).digest("hex")}async function $t(e){let{in:t}=e,r=e.config||e.policy,s=e["pub-key"],o=e["keys-store"]||R.resolve("config/keys.json"),n=e["policy-sig"]||R.resolve("config/policy.sig.json"),i=e["policy-state"]||R.resolve("data/policy.state.json"),a=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 E=R.resolve(t),C=Ee.readFileSync(E,"utf-8");c=JSON.parse(C)}catch(E){console.error(JSON.stringify({status:"error",error:"INVALID_PROPOSAL_FILE",message:E.message})),process.exit(5)}let l;try{let E=r||R.resolve("config/policy.default.json");Ee.existsSync(E)||(console.error(JSON.stringify({status:"error",error:"MISSING_POLICY",message:`Policy file not found: ${E}`})),process.exit(1));let C=Ee.readFileSync(E,"utf-8");l=JSON.parse(C)}catch(E){console.error(JSON.stringify({status:"error",error:"INVALID_POLICY",message:E.message})),process.exit(1)}let u=Q(o),f=u.ok?u.store:null,d=Z({policyObj:l,keyStore:f,policySigPath:n,allowUnsigned:a});d.ok||(console.error(JSON.stringify({status:"error",error:d.reason,message:d.message},null,2)),process.exit(8));let p=q({policyObj:l,statePath:i,maxCreatedAtSkewSec:l?.security?.maxPolicyCreatedAtSkewSec});p.ok||(console.error(JSON.stringify({status:"error",error:p.reason,message:p.message},null,2)),process.exit(8));let g=new V(R.resolve("data/nonce.db.json"));await g.load(),!f&&!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 m=new Ie(R.resolve("data/rate-limit.db.json"));await m.load();let y=ee({commandObj:c,pubKeyB64:s,keyStore:f,nonceDb:g,policy:l,rateLimiter:m});if(!y.valid){try{await g.save(),await m.save()}catch{}let E={status:"invalid",commandId:c.commandId||"N/A",checks:y.checks,errors:y.errors||[],executionResult:null};console.error(JSON.stringify(E,null,2));let C=R.resolve("data/audit.log.jsonl");try{je(C,{commandId:c.commandId||"N/A",status:"rejected",requesterId:c.requesterId||"unknown",payloadHash:Ye(c),reason:y.checks,timestamp:new Date().toISOString()})}catch(Ht){console.error(JSON.stringify({status:"error",error:"AUDIT_WRITE_FAILED",message:Ht.message})),process.exit(10)}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 S=y.risk||"LOW",k=c.payload.adapter||"shell",D=l.requesters?.[c.requesterId],K=D?.requireApproval;if(K===!0||Array.isArray(K)&&(K.includes(S)||K.includes("*")||["HIGH","CRITICAL"].includes(S)&&K.includes("HIGH+"))){let C=Tt().createToken(c.commandId,{requesterId:c.requesterId,adapter:k,risk:S});await g.save().catch(()=>{}),await m.save().catch(()=>{}),console.log(JSON.stringify({status:"approval_required",commandId:c.commandId||"N/A",risk:S,approvalToken:C,message:`${S} risk operation requires operator approval. Approve with: lbe approve --token ${C}`},null,2)),process.exit(11)}let I=null;if((e.backup===!0||k==="file")&&c.payload.target)try{I=ge(R.resolve(c.payload.target))}catch{}let h;try{h=await ke(k,c,l,D)}catch(E){h={adapter:k,status:"error",error:E.message,exitCode:1}}let _=h.status==="error"||h.exitCode!==0,O=null;if(_&&I&&e["rollback-on-failure"]!==!1)try{O=U(I)}catch(E){O={restored:!1,error:E.message}}let z=null;if(!_&&c.payload.target&&["write","patch"].includes(c.payload.action)){let C=Ee.existsSync(R.resolve(c.payload.target));z={ok:C,check:"target_exists",target:c.payload.target},!C&&I&&(O=U(I),h.status="error")}let X=R.resolve("data/audit.log.jsonl");try{je(X,{commandId:c.commandId||"N/A",status:O?.restored?"rolled_back":h.status||"completed",requesterId:c.requesterId||"unknown",payloadHash:Ye(c),executionHash:Ye(h),adapter:h.adapter,riskLevel:S,exitCode:h.exitCode||0,rolledBack:O?.restored||!1,timestamp:new Date().toISOString()})}catch(E){console.error(JSON.stringify({status:"error",error:"AUDIT_WRITE_FAILED",message:E.message})),process.exit(10)}await g.save(),await m.save();let Wt={status:_||z&&!z.ok?"failed":"executed",commandId:c.commandId||"N/A",risk:S,checks:y.checks,executionResult:{adapter:h.adapter,status:h.status||"completed",output:h.output||h.error||"",exitCode:h.exitCode||0},backup:I?{path:I.backupPath,existed:I.existed,hash:I.hash}:null,rollback:O,postValidation:z};console.log(JSON.stringify(Wt,null,2)),process.exit(h.exitCode||0)}import Ft from"path";function jt(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 Kt(e){let t=e.audit?Ft.resolve(e.audit):Ft.resolve("data/audit.log.jsonl"),r=jt(e["fail-fast"],!0),s=jt(e.json,!0),o=Number.isFinite(Number(e.max))?Number(e.max):void 0,n=Pt(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 Be from"path";import G from"fs";import P from"path";import us from"crypto";import{fileURLToPath as fs}from"url";var ae=P.dirname(fs(import.meta.url));function qt(e){try{let t=G.readFileSync(e);return us.createHash("sha256").update(t).digest("hex")}catch{return null}}function ps(e=P.join(ae,"../..")){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=P.join(e,s),n=qt(o);n&&(t[s]=n)}return t}function ms(e,t=P.join(ae,"../..")){let r={valid:!0,mismatches:[],missing:[],checkedFiles:0};for(let[s,o]of Object.entries(e)){let n=P.join(t,s);if(!G.existsSync(n)){r.valid=!1,r.missing.push(s);continue}let i=qt(n);r.checkedFiles++,i!==o&&(r.valid=!1,r.mismatches.push({file:s,expected:o,actual:i}))}return r}async function ne(e={}){let t=typeof e=="string"||e===null?{manifestPath:e}:e,r=t.rootDir||P.join(ae,"../.."),s=t.strict===!0,o=t.manifestPath||P.join(r,"config/integrity.manifest.json");if(!G.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=G.readFileSync(o,"utf8"),i=JSON.parse(n),a=ms(i,r);return{...a,skipped:!1,reason:a.valid?null:"INTEGRITY_CHECK_FAILED",message:a.valid?`Integrity check passed (${a.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 Mt({outputPath:e=P.join(ae,"../../config/integrity.manifest.json"),rootDir:t=P.join(ae,"../..")}={}){let r=ps(t),s=JSON.stringify(r,null,2),o=P.dirname(e);return G.existsSync(o)||G.mkdirSync(o,{recursive:!0}),G.writeFileSync(e,s),{outputPath:e,fileCount:Object.keys(r).length,manifest:r}}function Je(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 Vt(e){let t=Je(e.strict,!1)||Je(e["integrity-strict"],!1),r=e.manifest?Be.resolve(e.manifest):Be.resolve(e["integrity-manifest"]||"config/integrity.manifest.json"),s=Je(e.json,!0),o=await ne({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 Yt(e){let t=Be.resolve(e.out||e.output||e.manifest||"config/integrity.manifest.json"),r=Mt({outputPath:t});console.log(JSON.stringify({ok:!0,outputPath:r.outputPath,fileCount:r.fileCount},null,2)),process.exit(0)}import W from"fs";import ve from"path";async function Jt(e){let t=ve.resolve(e.config||e.policy||"config/policy.default.json"),r=ve.resolve(e["policy-sig"]||"config/policy.sig.json"),s=ve.resolve(e["secret-key-file"]||"keys/secret.key"),o=String(e["policy-key-id"]||"policy-signer-v1-2026Q1");W.existsSync(t)||(console.error(JSON.stringify({status:"error",error:"POLICY_FILE_MISSING",message:`Policy file not found: ${t}`},null,2)),process.exit(1)),W.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(W.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 i=W.readFileSync(s,"utf8").trim(),a=ue({policyObj:n,secretKeyB64:i,keyId:o});a.ok||(console.error(JSON.stringify({status:"error",error:a.reason||"POLICY_SIGN_FAILED",message:a.message},null,2)),process.exit(8));let c=ve.dirname(r);W.existsSync(c)||W.mkdirSync(c,{recursive:!0}),W.writeFileSync(r,JSON.stringify(a.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 v from"fs";import N from"path";function Bt(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 j(e,t,r,s){e[t]={ok:r,message:s}}function H(e){try{return v.accessSync(e,v.constants.R_OK),!0}catch{return!1}}function ys(e){let t=N.join(e,`.healthcheck-${Date.now()}`);try{return v.mkdirSync(e,{recursive:!0}),v.writeFileSync(t,"ok","utf8"),v.unlinkSync(t),{ok:!0,message:"Data directory writable"}}catch(r){return{ok:!1,message:`Data directory not writable: ${r.message}`}}}async function Ut(e){let t=Bt(e.json,!0),r=N.resolve(e.config||e.policy||"config/policy.default.json"),s=N.resolve(e["policy-sig"]||"config/policy.sig.json"),o=N.resolve(e["keys-store"]||"config/keys.json"),n=N.resolve(e["data-dir"]||"data"),i=N.resolve(e.audit||N.join(n,"audit.log.jsonl")),a=N.resolve(e["nonce-db"]||N.join(n,"nonce.db.json")),c=N.resolve(e["rate-db"]||N.join(n,"rate-limit.db.json")),l=N.resolve(e["policy-state"]||N.join(n,"policy.state.json")),u=Bt(e["integrity-strict"],!1),f=N.resolve(e["integrity-manifest"]||"config/integrity.manifest.json"),d={};j(d,"policy",v.existsSync(r)&&H(r),v.existsSync(r)?`Policy file readable: ${r}`:`Policy file missing: ${r}`),j(d,"policySignature",v.existsSync(s)&&H(s),v.existsSync(s)?`Policy signature readable: ${s}`:`Policy signature missing: ${s}`),j(d,"trustedKeys",v.existsSync(o)&&H(o),v.existsSync(o)?`Trusted keys readable: ${o}`:`Trusted keys missing: ${o}`),j(d,"auditLog",v.existsSync(i)&&H(i),v.existsSync(i)?`Audit log readable: ${i}`:`Audit log missing: ${i}`),j(d,"nonceDb",v.existsSync(a)&&H(a),v.existsSync(a)?`Nonce DB readable: ${a}`:`Nonce DB missing: ${a}`),j(d,"rateLimitDb",v.existsSync(c)&&H(c),v.existsSync(c)?`Rate-limit DB readable: ${c}`:`Rate-limit DB missing: ${c}`),j(d,"policyState",v.existsSync(l)&&H(l),v.existsSync(l)?`Policy state readable: ${l}`:`Policy state missing: ${l}`);let p=ys(n);if(j(d,"dataWritable",p.ok,p.message),u){let y=await ne({strict:!0,manifestPath:f});j(d,"integrity",y.valid,y.valid?y.message:`${y.reason}: ${y.message}`)}let g=Object.values(d).every(y=>y.ok===!0),m={ok:g,status:g?"healthy":"unhealthy",timestamp:new Date().toISOString(),checks:d};console.log(t?JSON.stringify(m,null,2):`${m.status.toUpperCase()}: ${Object.keys(d).length} checks`),process.exit(g?0:8)}function hs(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 ks=xe.dirname(gs(import.meta.url)),Ss=xe.join(ks,"../package.json"),ce=JSON.parse(Gt.readFileSync(Ss,"utf-8"));async function Is(){let e=process.argv.slice(2);e.includes("--version")&&(console.log(`LetterBlack Sentinel v${ce.version}`),process.exit(0)),(e.length===0||e.includes("--help")||e.includes("-h"))&&(le(ce.version),process.exit(0));let{command:t,opts:r}=Ge(e);r.version&&(console.log(`LetterBlack Sentinel v${ce.version}`),process.exit(0)),(r.help||!t||t==="help")&&(le(ce.version),process.exit(0));try{if(r["pub-key-file"])try{r["pub-key"]=Gt.readFileSync(xe.resolve(r["pub-key-file"]),"utf-8").trim()}catch(s){console.error(`Error reading public key file: ${s.message}`),process.exit(1)}if(["verify","dryrun","run"].includes(t)){let s=hs(r["integrity-strict"],!1),o=xe.resolve(r["integrity-manifest"]||"config/integrity.manifest.json"),n=await ne({strict:s,manifestPath:o});n.valid||(console.error(JSON.stringify({status:"error",error:n.reason||"INTEGRITY_CHECK_FAILED",message:n.message},null,2)),process.exit(8))}switch(t){case"init":await nt(r);break;case"verify":await At(r);break;case"dryrun":await Rt(r);break;case"run":await $t(r);break;case"audit-verify":await Kt(r);break;case"integrity-check":await Vt(r);break;case"integrity-generate":await Yt(r);break;case"policy-sign":await Jt(r);break;case"health":await Ut(r);break;default:console.error(`Unknown command: ${t}`),le(ce.version),process.exit(1)}}catch(s){console.error(JSON.stringify({status:"error",error:"INTERNAL_ERROR",message:s.message,stack:process.env.DEBUG?s.stack:void 0})),process.exit(9)}}Is().catch(e=>{console.error(JSON.stringify({status:"error",error:"FATAL_ERROR",message:e.message})),process.exit(9)});
|