@tuent/sentinel 0.1.3 → 0.1.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/dist/Sentinel-4QKPFHTI.js +10 -0
- package/dist/{Sentinel-BVoMEF3F.d.ts → Sentinel-DT0IyGQi.d.ts} +112 -9
- package/dist/{chunk-PDWWRZXF.js → chunk-2IPSTUNH.js} +18 -7
- package/dist/chunk-B6S2PBS4.js +47 -0
- package/dist/{chunk-JTR2E7RD.js → chunk-FIEIGBYL.js} +222 -186
- package/dist/{chunk-G74MMDKA.js → chunk-HRI2Y326.js} +76 -21
- package/dist/{chunk-SSDIBY52.js → chunk-I2FVDDSG.js} +223 -90
- package/dist/{chunk-WLIDSTS4.js → chunk-KWZ7JKKO.js} +221 -27
- package/dist/{chunk-2TJ5Z53T.js → chunk-LTBVWF5H.js} +59 -20
- package/dist/cli.js +33 -35
- package/dist/gateway/index.d.ts +10 -1
- package/dist/gateway/index.js +4 -4
- package/dist/gatewayDaemon.js +5 -5
- package/dist/index.d.ts +2 -12
- package/dist/index.js +5 -5
- package/dist/logAdapter-WM43W3S7.js +7 -0
- package/dist/{mcpAdapter-R47GX2P3.js → mcpAdapter-WYAXUE7T.js} +2 -2
- package/dist/{policyLoader-KZL2U4M2.js → policyLoader-XX6BQXNB.js} +8 -4
- package/package.json +1 -1
- package/dist/Sentinel-5CQ6HKXS.js +0 -10
- package/dist/chunk-FMZWHT4M.js +0 -20
- package/dist/logAdapter-IB6ZDEV2.js +0 -7
package/dist/cli.js
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import"./chunk-TKAKHSZ3.js";import{AgentProfileManager as
|
|
3
|
-
`];for(const
|
|
4
|
-
`).map(
|
|
2
|
+
import"./chunk-TKAKHSZ3.js";import{AgentProfileManager as B,AlertManager as me,AuditTrail as b,BaselineBuilder as x,CorrelationDetector as he,DeviationDetector as _,FileStorageBackend as ye,ProfileStore as we,ReportGenerator as ve,Sentinel as E,SentinelRunner as $e,generateFleetReport as Ae}from"./chunk-I2FVDDSG.js";import{runInitClaudeCode as be}from"./chunk-LTBVWF5H.js";import{readReleaseToken as Ie}from"./chunk-LATQNIRW.js";import{deriveAgentId as Se}from"./chunk-B5QKJHSV.js";import"./chunk-B6S2PBS4.js";import"./chunk-FIEIGBYL.js";import{checkSaneNumber as P,loadPolicy as De,suggestKey as Te}from"./chunk-KWZ7JKKO.js";import{getOrCreateKeyPair as R}from"./chunk-NUXSUSYY.js";import{join as g}from"path";import{homedir as h}from"os";import{readFile as N,writeFile as C,access as G,mkdir as U}from"fs/promises";function ke(t){const o=new Date(t);if(isNaN(o.getTime()))return"unknown";const e=Date.now()-o.getTime();if(e<0)return"just now";const s=Math.floor(e/6e4);if(s<1)return"just now";if(s<60)return`${s} minute${s===1?"":"s"} ago`;const i=Math.floor(s/60);if(i<24)return`${i} hour${i===1?"":"s"} ago`;const a=Math.floor(i/24);if(a<14)return`${a} day${a===1?"":"s"} ago`;const d=Math.floor(a/7);if(a<60)return`${d} week${d===1?"":"s"} ago`;if(a>=365)return"over a year ago";const c=Math.floor(a/30);return`${c} month${c===1?"":"s"} ago`}function Ee(t,o){const n=new Date(o),e=isNaN(n.getTime())?1/0:Math.floor((Date.now()-n.getTime())/864e5);return t<.3||e>30?"declining":t>.7&&e<7?"rising":"stable"}function Ce(t){return t<.3?"inner":t<.65?"middle":"outer"}function J(t){if(t.length===0)return"No petals selected.";const o=new Map;for(const e of t)o.set(e.id,e.label);const n=[`Selected petals (${t.length}):
|
|
3
|
+
`];for(const e of t){const s=Ce(e.layer),i=e.isRichData?"":" [filler]";n.push(`- ${e.label}${i}`),n.push(` Category: ${e.category}`),n.push(` Layer zone: ${s} (${(e.layer*100).toFixed(0)}%)`),n.push(` Openness: ${(e.openness*100).toFixed(0)}%`),n.push(` Description: ${e.description}`),n.push(` Last active: ${e.lastActive}`);const a=ke(e.lastActive),d=e.weight!=null?Ee(e.weight,e.lastActive):"stable";if(n.push(` Temporal: Last active ${a} | Weight trend: ${d}`),e.source){const c={seed:"seed data",agent:"observed from activity",manual:"filesystem scan",diary:"personal diary entry",conversation:"created from conversation","agent-monitor":"monitored agent activity"};n.push(` Source: ${c[e.source]??e.source}`)}if(e.weight!=null&&n.push(` Weight: ${e.weight.toFixed(2)}`),e.connections.length>0){const c=e.connections.map(r=>o.get(r)??je(r));n.push(` Connections: ${c.join(", ")}`)}if(e.files&&e.files.length>0){const c=e.files.slice(0,10).map(r=>r.split("/").pop()??r);n.push(` Key files: ${c.join(", ")}`)}if(e.fileContents&&e.fileContents.length>0){n.push(" File contents:");for(const c of e.fileContents)n.push(` --- ${c.name} ---`),n.push(c.content.split(`
|
|
4
|
+
`).map(r=>` ${r}`).join(`
|
|
5
5
|
`))}n.push("")}return n.join(`
|
|
6
|
-
`)}function
|
|
6
|
+
`)}function je(t){return t.split("-").map(o=>o.charAt(0).toUpperCase()+o.slice(1)).join(" ")}function Me(t){const o=[Re(t.agentName,t.agentId,t.role),Ne(t.baseline),Fe(t.e),xe(t.findings),Pe()],n=Le(t.t);return n&&o.push(n),o.join(`
|
|
7
7
|
|
|
8
|
-
`)}function
|
|
9
|
-
`)}function
|
|
10
|
-
Not yet established. Insufficient data for baseline computation.`;const o=Object.entries(
|
|
11
|
-
`)}function
|
|
8
|
+
`)}function Re(t,o,n){const e=["=== Agent Identity ===",`Name: ${t}`,`ID: ${o}`];if(n){if(e.push(`Role: ${n.description}`),e.push(`Allowed actions: ${n.allowedActions.length>0?n.allowedActions.join(", "):"Not defined"}`),n.forbiddenTargetPatterns.length>0&&e.push(`Forbidden targets: ${n.forbiddenTargetPatterns.join(", ")}`),n.expectedSchedule){const s=[];n.expectedSchedule.activeHours&&s.push(`hours ${n.expectedSchedule.activeHours[0]}-${n.expectedSchedule.activeHours[1]}`),n.expectedSchedule.activeDays&&s.push(`days ${n.expectedSchedule.activeDays.join(", ")}`),s.length>0&&e.push(`Expected schedule: ${s.join("; ")}`)}}else e.push("No role definition \u2014 monitoring behavioral baseline only");return e.join(`
|
|
9
|
+
`)}function Ne(t){if(!t)return`=== Behavioral Baseline ===
|
|
10
|
+
Not yet established. Insufficient data for baseline computation.`;const o=Object.entries(t.actionDistribution).map(([e,s])=>`${e}: ${s}%`).join(", ");return["=== Behavioral Baseline ===",`Period: ${t.periodDays} days`,`Total sessions: ${t.totalSessions}`,`Total events: ${t.totalEvents}`,`Average events per session: ${t.averageEventsPerSession}`,`Average session duration: ${t.averageSessionDurationMinutes} minutes`,`Typical active hours: ${t.typicalActiveHours[0]}-${t.typicalActiveHours[1]}`,`Typical active days: ${t.typicalActiveDays.length>0?t.typicalActiveDays.join(", "):"N/A"}`,`Action distribution: ${o||"N/A"}`,`Normal weight range: ${t.normalWeightRange[0].toFixed(2)}-${t.normalWeightRange[1].toFixed(2)}`,`Top targets: ${t.topTargets.length>0?t.topTargets.slice(0,10).join(", "):"N/A"}`].join(`
|
|
11
|
+
`)}function Fe(t){const o=`=== Recent Activity (${t.length} sessions) ===`;return t.length===0?`${o}
|
|
12
12
|
No recent activity recorded.`:`${o}
|
|
13
|
-
${
|
|
14
|
-
No security findings detected. Agent behavior is within expected parameters.`;const n=[o];for(const
|
|
15
|
-
`)}function
|
|
16
|
-
`)}function
|
|
17
|
-
${
|
|
18
|
-
`)}function
|
|
19
|
-
`)}function
|
|
20
|
-
`)}function
|
|
21
|
-
`)}function
|
|
22
|
-
`)}async function
|
|
23
|
-
`),console.log(
|
|
24
|
-
`),console.log(
|
|
13
|
+
${J(t)}`}function xe(t){const o="=== Security Findings ===";if(t.length===0)return`${o}
|
|
14
|
+
No security findings detected. Agent behavior is within expected parameters.`;const n=[o];for(const e of t)n.push(`[${e.severity}] ${e.type}`),n.push(` Description: ${e.description}`),n.push(` Evidence: ${e.evidence.action} \u2192 ${e.evidence.target} at ${e.evidence.timestamp}`),e.evidence.baselineComparison&&n.push(` Baseline comparison: ${e.evidence.baselineComparison}`),n.push(` Recommendation: ${e.recommendation}`),n.push("");return n.join(`
|
|
15
|
+
`)}function Pe(){return["=== Analysis Request ===","Based on the data above, provide:","1. OVERALL HEALTH ASSESSMENT: Is this agent operating normally?","2. RISK SUMMARY: What is the overall risk level?","3. FINDING REVIEW: For each finding, confirm or adjust its severity with reasoning.","4. RECOMMENDATIONS: Specific actions the owner should take.","5. MONITORING GUIDANCE: What patterns to watch for going forward."].join(`
|
|
16
|
+
`)}function Le(t){return!t||t.length===0?null:`=== Owner Context ===
|
|
17
|
+
${J(t)}`}import{request as V}from"http";var u=process.argv.slice(2),p=v(u,"--agent"),Q=v(u,"--name"),qe=v(u,"--role"),Oe=u.includes("--create"),He=u.includes("--compute-baseline"),Ke=u.includes("--monitor"),We=u.includes("--init-config"),Be=u.includes("--init-policy"),_e=u.includes("init")&&u.includes("claude-code"),Ge=u.includes("--force"),z=v(u,"--from-policy"),Ue=u.includes("--report"),Je=u.includes("--report-all"),Ve=u.includes("--correlations"),Qe=u.includes("--verify-audit"),ze=u.includes("--enroll-manifest"),Ye=u.includes("--recompute-stats"),Xe=u.includes("--health"),Ze=u.includes("--restrict"),et=u.includes("--quarantine"),tt=u.includes("--release")||u[0]==="release",nt=u.includes("--status"),ot=u.includes("--start-task"),st=u.includes("--end-task"),at=u.includes("--intent-status"),it=u.includes("--intent-report"),Y=v(u,"--task-id"),X=v(u,"--description"),Z=v(u,"--relaxed-actions"),ee=v(u,"--phases"),te=v(u,"--reason"),L=v(u,"--quarantine"),q=v(u,"--quarantine-reason"),T=v(u,"--period"),ne=v(u,"--format"),S=new B;function v(t,o){const n=t.find(s=>s.startsWith(o+"="));if(!n)return;const e=n.indexOf("=");return n.slice(e+1)}async function k(t,o){try{const n=await N(g(t,o,"mode.json"),"utf-8"),e=JSON.parse(n);return e.mode==="restricted"||e.mode==="quarantined"||e.mode==="normal"?e:{mode:"normal"}}catch{return{mode:"normal"}}}function oe(t){const o=["Agent","Score","Status","Mode","C/H/M/L","Last Event","Baseline"],n=t.map(r=>[r.agentId,String(r.score),r.status,r.mode,r.findings,r.lastEvent,r.baseline?"\u2713":"\u2717"]),e=[o,...n],s=o.map((r,l)=>Math.max(...e.map(f=>f[l].length))),i=(r,l)=>r+" ".repeat(l-r.length),a=o.map((r,l)=>i(r,s[l])).join(" "),d=s.map(r=>"-".repeat(r)).join(" "),c=n.map(r=>r.map((l,f)=>i(l,s[f])).join(" "));return[a,d,...c].join(`
|
|
18
|
+
`)}function se(t){const o=["Agent ID","Mode","Reason","Changed"],n=t.map(r=>[r.agentId,r.mode.toUpperCase(),r.reason,r.changed]),e=[o,...n],s=o.map((r,l)=>Math.max(...e.map(f=>f[l].length))),i=(r,l)=>r+" ".repeat(l-r.length),a=o.map((r,l)=>i(r,s[l])).join(" "),d=s.map(r=>"-".repeat(r)).join(" "),c=n.map(r=>r.map((l,f)=>i(l,s[f])).join(" "));return[a,d,...c].join(`
|
|
19
|
+
`)}function ae(t){const o=["Agent ID","Sessions","Last Active","Role","Baseline","Mode","Status"],n=t.map(r=>[r.agentId,String(r.sessions),r.lastActive,r.roleDefined?"\u2713":"\u2717",r.baselineDefined?"\u2713":"\u2717",r.mode??"normal",r.status]),e=[o,...n],s=o.map((r,l)=>Math.max(...e.map(f=>f[l].length))),i=(r,l)=>r+" ".repeat(l-r.length),a=o.map((r,l)=>i(r,s[l])).join(" "),d=s.map(r=>"-".repeat(r)).join(" "),c=n.map(r=>r.map((l,f)=>i(l,s[f])).join(" "));return[a,d,...c].join(`
|
|
20
|
+
`)}function O(t,o){return t<10?"New":o.some(n=>n.severity==="HIGH"||n.severity==="CRITICAL")?"At Risk":o.some(n=>n.severity==="MEDIUM")?"Caution":"Healthy"}function H(t,o){const n=Date.now()-o*24*60*60*1e3;return t.filter(e=>new Date(e.lastActive).getTime()>=n)}function ie(t){return{id:t.id,label:t.label,category:t.category,description:t.description,layer:t.layer,lastActive:t.lastActive,openness:t.openness,connections:t.connections,isRichData:!0,source:t.source,core:t.core,sharable:t.sharable,weight:t.weight,files:t.files}}function K(t,o){const n=["Sentinel \u2014 Live Monitoring","\u2500".repeat(26)];for(const[e,s]of t){const i=(o.get(e)??"manual").toUpperCase(),a=s.getFindings(),d=a.filter(w=>w.severity==="HIGH"||w.severity==="CRITICAL").length,c=a.filter(w=>w.severity==="MEDIUM").length;let r=`${a.length} findings`;d>0?r=`${d} HIGH`:c>0&&(r=`${c} MEDIUM`);const l=O(s.sessionCount,a),f=e.padEnd(18),y=i.padEnd(5);n.push(`[${f}] ${y}| ${s.eventCount} events | ${s.sessionCount} sessions | ${r} | ${l}`)}return n.push(""),n.push("Press Ctrl+C to stop."),n.join(`
|
|
21
|
+
`)}function re(t){const o=["Monitoring stopped. Summary:"];for(const[n,e]of t){const s=e.getFindings();let i=`${s.length} findings`;if(s.length>0){const a={};for(const c of s)a[c.severity]=(a[c.severity]??0)+1;const d=Object.entries(a).map(([c,r])=>`${r} ${c}`);i=`${s.length} finding${s.length>1?"s":""} (${d.join(", ")})`}o.push(`- ${n}: ${e.eventCount} events, ${e.sessionCount} sessions, ${i}`)}return o.join(`
|
|
22
|
+
`)}async function rt(t,o){const n=g(h(),".dahlia","agents"),e=await k(n,t);if(e.mode==="quarantined"){console.log(`Agent ${t} is quarantined \u2014 cannot downgrade to restricted.`);return}const s=e.mode;await U(g(n,t),{recursive:!0}),await C(g(n,t,"mode.json"),JSON.stringify({mode:"restricted",reason:o,timestamp:new Date().toISOString(),previousMode:s}),"utf-8");const i=await R(g(n,t)),a=new b(t,{logDir:g(n,t)});await a.open(),a.setSigningKey(i.privateKey,i.publicKey),await a.logModeChange("restricted",o,s),await a.close(),console.log(`Agent ${t} RESTRICTED: ${o}`)}async function lt(t,o){const n=g(h(),".dahlia","agents"),s=(await k(n,t)).mode;await U(g(n,t),{recursive:!0}),await C(g(n,t,"mode.json"),JSON.stringify({mode:"quarantined",reason:o,timestamp:new Date().toISOString(),previousMode:s}),"utf-8");const i=await R(g(n,t)),a=new b(t,{logDir:g(n,t)});await a.open(),a.setSigningKey(i.privateKey,i.publicKey),await a.logModeChange("quarantined",o,s),await a.close(),console.log(`Agent ${t} QUARANTINED: ${o}`)}function ct(t,o=1500){return new Promise(n=>{const e=V({host:"127.0.0.1",port:t,path:"/api/sentinel/health",method:"GET"},s=>{s.resume(),n(s.statusCode===200)});e.on("error",()=>n(!1)),e.setTimeout(o,()=>{e.destroy(),n(!1)}),e.end()})}function dt(t,o,n){return new Promise((e,s)=>{const i=JSON.stringify({agentId:n,reason:"operator release (sentinel release)"}),a=V({host:"127.0.0.1",port:t,path:"/api/sentinel/release",method:"POST",headers:{"content-type":"application/json","content-length":Buffer.byteLength(i),"x-sentinel-token":o}},d=>{let c="";d.on("data",r=>c+=r),d.on("end",()=>{try{e({status:d.statusCode??0,body:JSON.parse(c)})}catch{e({status:d.statusCode??0,body:c})}})});a.on("error",s),a.setTimeout(3e3,()=>a.destroy(new Error("timeout"))),a.write(i),a.end()})}function le(t){const{id:o,selfDerived:n,previousMode:e,mode:s}=t;return n&&e==="normal"?`Agent ${o} was already normal \u2014 no change. If you are still locked out, your workspace id may differ (e.g. a symlinked root). Run: sentinel release --agent=<id>`:`[live] Agent ${o} RELEASED \u2014 was ${e}, now ${s}. Applied to the running daemon (no restart).`}async function gt(t){const o=g(h(),".dahlia","agents"),n=t===void 0,e=t??Se(process.cwd());n&&console.log(`Resolved agent-id from cwd: ${e}`);const s=Ie(h());if(s&&await ct(s.port))try{const r=await dt(s.port,s.token,e);if(r.status===200&&typeof r.body=="object"&&r.body.ok){console.log(le({id:e,selfDerived:n,previousMode:String(r.body.previousMode),mode:String(r.body.mode)}));return}const l=typeof r.body=="object"?JSON.stringify(r.body):r.body;console.error(`[live] daemon refused release (HTTP ${r.status}): ${l}`);return}catch(r){console.error(`[live] daemon release call failed: ${r.message}. Falling back to mode.json.`)}const i=await k(o,e);if(i.mode==="normal"){console.log(`Agent ${e} is already in normal mode.`);return}const a=i.mode;await C(g(o,e,"mode.json"),JSON.stringify({mode:"normal",reason:"manual release",timestamp:new Date().toISOString(),previousMode:a}),"utf-8");const d=await R(g(o,e)),c=new b(e,{logDir:g(o,e)});await c.open(),c.setSigningKey(d.privateKey,d.publicKey),await c.logModeChange("normal","manual release",a),await c.close(),console.log(`[fallback] Agent ${e} RELEASED (was ${a}) \u2014 no running daemon; mode.json written, applies on the daemon's next start.`)}async function ut(){const t=await S.listAgents();if(t.length===0){console.log("No monitored agents found.");return}const o=g(h(),".dahlia","agents"),n=[];for(const s of t){const i=await k(o,s);n.push({agentId:s,mode:i.mode,reason:i.reason??"-",changed:i.timestamp?i.timestamp.split("T")[0]:"-"})}console.log(`Agent Mode Status
|
|
23
|
+
`),console.log(se(n));const e=n.filter(s=>s.mode!=="normal");if(e.length>0){console.log("");for(const s of e){const i=s.mode==="quarantined"?"QUARANTINED":"RESTRICTED";console.log(`\u26A0 ${s.agentId}: ${i}`)}}}async function ft(){const t=await S.listAgents();if(t.length===0){console.log("No monitored agents found. Create one with --create --agent=ID --name=NAME");return}const o=[];for(const e of t)try{const a=(await S.loadAgentProfile(e)).build().filter(I=>I.source==="agent-monitor"),d=a.length,c=a.length>0?a.map(I=>I.lastActive).sort().reverse()[0].split("T")[0]:"never",l=await new x(e).loadBaseline(e),f=await S.loadRole(e),y=[];if(l){const I=H(a,7),F=new _(l,f);for(const $ of I){const D={label:$.label,category:$.category,lastActive:$.lastActive,description:$.description,weight:$.weight,source:$.source,files:$.files,connections:$.connections,eventCount:$.eventCount};y.push(...F.analyzeSession(D))}}const w=g(h(),".dahlia","agents"),M=await k(w,e);o.push({agentId:e,sessions:d,lastActive:c,roleDefined:f!==null,baselineDefined:l!==null,status:O(d,y),mode:M.mode})}catch(s){console.warn(`Error loading agent ${e}:`,s),o.push({agentId:e,sessions:0,lastActive:"error",roleDefined:!1,baselineDefined:!1,status:"Error",mode:"normal"})}const n=o.filter(e=>e.mode&&e.mode!=="normal");if(n.length>0){for(const e of n){const s=e.mode==="quarantined"?"QUARANTINED":"RESTRICTED";console.log(`\u26A0 ${e.agentId}: ${s}`)}console.log("")}console.log(`Sentinel Agent Overview
|
|
24
|
+
`),console.log(ae(o))}async function pt(t){const o=await S.loadAgentProfile(t),n=await S.loadRole(t),s=await new x(t).loadBaseline(t),a=o.build().filter(D=>D.source==="agent-monitor"),d=H(a,7),c=d.map(ie),r=[];if(s){const D=new _(s,n);for(const A of d){const pe={label:A.label,category:A.category,lastActive:A.lastActive,description:A.description,weight:A.weight,source:A.source,files:A.files,connections:A.connections};r.push(...D.analyzeSession(pe))}}const l=g(h(),".dahlia","profile.json"),f=new ye(l),y=new we({backend:f});let w=[];await y.load()&&(w=y.build().filter(A=>A.core===!0).map(ie));const I=Me({agentId:t,agentName:t,role:n,baseline:s,e:c,findings:r,t:w}),F=new Date().toISOString().split("T")[0],$=`Sentinel Agent Report \u2014 ${t} \u2014 ${d.length} recent sessions \u2014 generated ${F}
|
|
25
25
|
|
|
26
|
-
`;process.stdout.write($+I)}async function
|
|
27
|
-
`),console.log("Template config created at ~/.dahlia/sentinel.json \u2014 edit it with your agent details then run: npm run sentinel -- --monitor")}
|
|
28
|
-
\u26A0 [${
|
|
29
|
-
`+
|
|
30
|
-
`);for(const
|
|
31
|
-
`),console.log(
|
|
26
|
+
`;process.stdout.write($+I)}async function mt(t){const o=g(h(),".dahlia","agents"),n=new b(t,{logDir:g(o,t)});await n.open();const e=new x(t),s=await e.computeBaseline(n);await n.close(),await e.saveBaseline(s),console.log(`Baseline computed for agent: ${t}`),console.log(` Sessions: ${s.totalSessions}`),console.log(` Period: ${s.periodDays} days`),console.log(" Action distribution:");for(const[i,a]of Object.entries(s.actionDistribution))console.log(` ${i}: ${a}%`);console.log(` Saved to: ~/.dahlia/agents/${t}/baseline.json`)}async function ht(t,o,n){let e;if(n){let s;try{s=await N(n,"utf-8")}catch(i){console.error(`Failed to read role file "${n}":`,i);return}try{e=JSON.parse(s)}catch(i){console.error(`Invalid JSON in role file "${n}":`,i.message);return}}await S.createAgent(t,o,e),console.log(`Agent created: ${t} (${o})`),e&&console.log(` Role loaded from: ${n}`)}async function yt(){const t=g(h(),".dahlia","sentinel.json");try{await G(t),console.log(`Config already exists at ${t}`);return}catch{}await C(t,JSON.stringify({agents:[{agentId:"example-agent",name:"Example Agent",adapterType:"log",logPath:"/path/to/agent/activity.log",logFormat:"json-lines"}]},null,2)+`
|
|
27
|
+
`),console.log("Template config created at ~/.dahlia/sentinel.json \u2014 edit it with your agent details then run: npm run sentinel -- --monitor")}var wt=new Set(["log","webhook","mcp","manual"]),vt=new Set(["json-lines","csv"]),$t=new Set(["LOW","MEDIUM","HIGH","CRITICAL"]),ce=new Set(["informational","actionable"]),At=new Set(["console","webhook","file"]);function m(t){throw new Error(`sentinel.json validation error: ${t}`)}function j(t,o,n){for(const e of Object.keys(o))if(!n.includes(e)){const s=Te(e,n);m(`unknown key "${e}" in ${t}.`+(s?` Did you mean "${s}"?`:"")+` Valid keys: ${n.join(", ")}`)}}function de(t){(typeof t!="object"||t===null||Array.isArray(t))&&m("top level must be a JSON object");const o=t;o.baselineWindowDays!==void 0&&m("baselineWindowDays is not supported \u2014 it was never consumed; the baseline window is fixed at 30 days. Remove this field."),o.checkIntervalMs!==void 0&&m("checkIntervalMs is not supported \u2014 it was never consumed. Remove this field."),o.alertWebhook!==void 0&&m('alertWebhook is not supported \u2014 it was never consumed. Use alerts.channels with a webhook channel ({ "type": "webhook", "name": ..., "config": { "url": ... } }) instead.'),j("sentinel.json",o,["agents","alerts","baselineWindowDays","checkIntervalMs","alertWebhook"]),Array.isArray(o.agents)||m("agents must be an array");for(let n=0;n<o.agents.length;n++){const e=`agents[${n}]`,s=o.agents[n];if((typeof s!="object"||s===null)&&m(`${e} must be an object`),s.roleDefinitionPath!==void 0&&m(`${e}.roleDefinitionPath is not supported \u2014 it was never consumed; roles are loaded from the agent profile directory (~/.dahlia/agents/<id>/role.json). Remove this field.`),j(e,s,["agentId","name","adapterType","logPath","logFormat","fieldMapping","mcpLogDir","webhookPort","webhookApiKey","roleDefinitionPath","readExisting"]),(typeof s.agentId!="string"||s.agentId.length===0)&&m(`${e}.agentId is required and must be a non-empty string`),(typeof s.name!="string"||s.name.length===0)&&m(`${e}.name is required and must be a non-empty string`),(typeof s.adapterType!="string"||!wt.has(s.adapterType))&&m(`${e}.adapterType must be one of: log, webhook, mcp, manual`),s.logFormat!==void 0&&(typeof s.logFormat!="string"||!vt.has(s.logFormat))&&m(`${e}.logFormat must be one of: json-lines, csv`),s.webhookPort!==void 0){const i=P(s.webhookPort,{integer:!0,min:1,max:65535});i&&m(`${e}.webhookPort ${i}`)}s.readExisting!==void 0&&typeof s.readExisting!="boolean"&&m(`${e}.readExisting must be a boolean`)}if(o.alerts!==void 0){(typeof o.alerts!="object"||o.alerts===null)&&m("alerts must be an object");const n=o.alerts;if(j("alerts",n,["minSeverity","minKind","dedupeWindowMs","quietHoursEnabled","quietHours","channels"]),n.minSeverity!==void 0&&(typeof n.minSeverity!="string"||!$t.has(n.minSeverity))&&m("alerts.minSeverity must be one of: LOW, MEDIUM, HIGH, CRITICAL"),n.minKind!==void 0&&(typeof n.minKind!="string"||!ce.has(n.minKind))&&m("alerts.minKind must be one of: informational, actionable"),n.dedupeWindowMs!==void 0){const e=P(n.dedupeWindowMs,{min:0});e&&m(`alerts.dedupeWindowMs ${e}`)}if(n.quietHoursEnabled!==void 0&&typeof n.quietHoursEnabled!="boolean"&&m("alerts.quietHoursEnabled must be a boolean"),n.quietHours!==void 0){const e=n.quietHours,s=i=>P(i,{integer:!0,min:0,max:23});(!Array.isArray(e)||e.length!==2||s(e[0])||s(e[1]))&&m("alerts.quietHours must be [start, end] with integer values 0-23")}if(n.channels!==void 0){Array.isArray(n.channels)||m("alerts.channels must be an array");for(let e=0;e<n.channels.length;e++){const s=`alerts.channels[${e}]`,i=n.channels[e];(typeof i!="object"||i===null)&&m(`${s} must be an object`),j(s,i,["type","name","config","minKind"]),(typeof i.type!="string"||!At.has(i.type))&&m(`${s}.type must be one of: console, webhook, file`),i.minKind!==void 0&&(typeof i.minKind!="string"||!ce.has(i.minKind))&&m(`${s}.minKind must be one of: informational, actionable`),i.config!==void 0&&((typeof i.config!="object"||i.config===null)&&m(`${s}.config must be an object`),j(`${s}.config`,i.config,["url","headers","filePath"]))}}}return t}async function W(){const t=g(h(),".dahlia","sentinel.json");let o;try{o=await N(t,"utf-8")}catch(e){if(e.code==="ENOENT")return null;throw e}let n;try{n=JSON.parse(o)}catch(e){if(e instanceof SyntaxError)return console.error(`Invalid JSON in sentinel config: ${e.message}`),null;throw e}return de(n)}async function bt(t){const o=await W();if(!o){console.log("No sentinel config found. Create ~/.dahlia/sentinel.json or use --init-config to add agents. See docs for config format.");return}let n=o.agents;if(t&&(n=n.filter(l=>l.agentId===t),n.length===0)){console.log(`Agent "${t}" not found in sentinel.json`);return}const e=new Map,s=new Map,i=l=>l&&l.startsWith("~/")?h()+l.slice(1):l;let a;if(o.alerts){const l={...o.alerts.minSeverity&&{minSeverity:o.alerts.minSeverity},...o.alerts.dedupeWindowMs!==void 0&&{dedupeWindowMs:o.alerts.dedupeWindowMs},...o.alerts.quietHoursEnabled!==void 0&&{quietHoursEnabled:o.alerts.quietHoursEnabled},...o.alerts.quietHours&&{quietHours:o.alerts.quietHours},...o.alerts.minKind&&{minKind:o.alerts.minKind},...o.alerts.channels&&{channels:o.alerts.channels}};a=new me(l)}for(const l of n)try{const f=new $e(l.agentId,void 0,{type:l.adapterType,logPath:i(l.logPath),logFormat:l.logFormat,fieldMapping:l.fieldMapping,mcpLogDir:i(l.mcpLogDir),webhookPort:l.webhookPort,webhookApiKey:l.webhookApiKey,readExisting:l.readExisting});f.setAuditLogDir(g(h(),".dahlia","agents",l.agentId)),f.setFindingCallback(y=>{(y.severity==="HIGH"||y.severity==="CRITICAL")&&console.log(`
|
|
28
|
+
\u26A0 [${y.agentId}] ${y.severity}: ${y.description}`)}),a&&f.setAlertManager(a),await f.start(),e.set(l.agentId,f),s.set(l.agentId,l.adapterType)}catch(f){console.error(`Failed to start monitoring for agent ${l.agentId}:`,f)}console.log(K(e,s));const d=setInterval(()=>{console.clear(),console.log(K(e,s))},5e3),c=async()=>{clearInterval(d);for(const[l,f]of e)try{await f.stop()}catch(y){console.warn(`Error stopping runner ${l}:`,y)}console.log(`
|
|
29
|
+
`+re(e)),process.exit(0)},r=()=>{c().catch(l=>{console.error("Error during shutdown:",l),process.exit(1)})};process.on("SIGINT",r),process.on("SIGTERM",r)}async function It(t,o,n){const s=await new ve(t).generateReport({periodDays:o,format:n});process.stdout.write(s)}async function St(t,o){const n=await Ae({periodDays:t,format:o});process.stdout.write(n)}async function Dt(t=30){const o=await W();if(!o){console.log("No sentinel config found. Create ~/.dahlia/sentinel.json or use --init-config.");return}const n=g(h(),".dahlia","agents"),e=new Map;try{for(const a of o.agents){const d=new b(a.agentId,{logDir:g(n,a.agentId)});await d.open(),e.set(a.agentId,d)}const i=await new he().detect(e,t*24*60*60*1e3);if(i.length===0){console.log("No cross-agent correlations detected.");return}console.log(`Found ${i.length} cross-agent correlation(s):
|
|
30
|
+
`);for(const a of i)console.log(`[${a.severity}] ${a.rule}`),console.log(` Agent A: ${a.agentA.agentId} \u2014 ${a.agentA.action} on ${a.agentA.target}`),console.log(` Agent B: ${a.agentB.agentId} \u2014 ${a.agentB.action} on ${a.agentB.target}`),console.log(` Time delta: ${Math.round(a.timeDeltaMs/1e3)}s`),console.log(` Recommendation: ${a.recommendation}`),console.log("")}finally{for(const s of e.values())await s.close()}}async function Tt(t){const o=g(h(),".dahlia","agents"),n=g(o,t,"cumulative-stats.json");let e="(none)";try{e=JSON.parse(await N(n,"utf-8")).totalEntries}catch{}const i=await new b(t,{logDir:g(o,t)}).recomputeCumulativeStats();console.log(`Recomputed cumulative-stats for ${t}:`),console.log(` totalEntries: ${e} \u2192 ${i.totalEntries}`),console.log(` scope: ${i.countScope}`),console.log(" (Read-only over the signed trail; only cumulative-stats.json rewritten.)")}async function kt(t){const o=g(h(),".dahlia","agents"),n=g(o,t),e=await R(n),s=new b(t,{logDir:n});s.setSigningKey(e.privateKey,e.publicKey);const i=L&&q?[{file:L,reason:q}]:void 0,a=await s.enrollManifest(i?{quarantine:i}:void 0);console.log(`Manifest enrolled for ${t}: ${a.records} file record(s) signed + chained`+(a.quarantined?`, ${a.quarantined} quarantine record(s)`:"")+"."),i&&console.log(` Quarantined: ${L} \u2014 ${q}`),console.log(" (Read-only over audit entries; protects from enrollment forward.)")}async function Et(t){const o=g(h(),".dahlia","agents"),n=new b(t,{logDir:g(o,t)});await n.open();const e=await n.verify();if(e.valid?console.log(`Audit trail for ${t}: VALID (${e.totalEntries} entries verified)`):e.brokenAt!==void 0?console.log(`Audit trail for ${t}: BROKEN at entry ${e.brokenAt} (${e.totalEntries} entries checked)`):console.log(`Audit trail for ${t}: INVALID \u2014 file-level manifest integrity failure (${e.totalEntries} entries chain-verified)`),e.manifest){const i=e.manifest;console.log(` Manifest: ${i.recordCount} file record(s) \u2014 ${i.ok?"OK":`${i.issues.length} issue(s)`}`);for(const a of i.issues)console.log(` [${a.type}] ${a.detail}`);for(const a of i.quarantined)console.log(` [QUARANTINED] ${a.file} \u2014 ${a.reason} (retained on disk, excluded from verdict)`)}const s=await n.query({type:"finding",limit:1e4});if(s.length>0){let i=0,a=0,d=0;for(const r of s){const l=r.decision;l==="deny"?a++:l==="modify"?d++:i++}console.log(` Findings: ${s.length} total \u2014 ${i} allowed, ${a} denied, ${d} modified`);const c=s.slice(0,5);for(const r of c){const l=r,f=l.decision,y=l.modification,w=l.description,M=l._decisionDefaulted===!0;f==="modify"&&y?.type==="append_args"?console.log(` [modified] ${w} \u2014 appended args: [${y.args.join(", ")}]`):console.log(f==="deny"?` [denied] ${w}`:M?` [allowed (legacy)] ${w}`:` [allowed] ${w}`)}}await n.close()}async function Ct(){const t=g(h(),".dahlia","agents"),o=new E({agentsDir:t}),e=await new B(t).listAgents();if(e.length===0){console.log("No monitored agents found."),await o.stop();return}const s=[];for(const i of e){const a=await o.getHealthScore(i);s.push({agentId:i,score:a.score,status:a.status,mode:a.mode,findings:`${a.findings.critical}/${a.findings.high}/${a.findings.medium}/${a.findings.low}`,lastEvent:a.lastEvent?a.lastEvent.split("T")[0]:"-",baseline:a.baselineEstablished})}await o.stop(),console.log(`Agent Health Dashboard
|
|
31
|
+
`),console.log(oe(s))}var ge=`# Sentinel \u2014 Agent Security Policy
|
|
32
32
|
version: "1.0"
|
|
33
33
|
|
|
34
34
|
agent:
|
|
@@ -56,8 +56,6 @@ policy:
|
|
|
56
56
|
# schedule:
|
|
57
57
|
# hours: [9, 18]
|
|
58
58
|
# days: [Monday, Tuesday, Wednesday, Thursday, Friday]
|
|
59
|
-
# limits:
|
|
60
|
-
# maxEventsPerHour: 500
|
|
61
59
|
|
|
62
60
|
# enforcement:
|
|
63
61
|
# restrictAfter: 2
|
|
@@ -69,12 +67,12 @@ policy:
|
|
|
69
67
|
# minSeverity: MEDIUM
|
|
70
68
|
|
|
71
69
|
# repo:
|
|
72
|
-
#
|
|
70
|
+
# root: . # scan this directory for sensitive files
|
|
73
71
|
# mapPath: ~/.dahlia/repo-sensitivity.json
|
|
74
72
|
# overlayPath: ~/.dahlia/repo-sensitivity.review.json
|
|
75
|
-
`;async function
|
|
76
|
-
`),console.log(` Task ID: ${
|
|
77
|
-
`),console.log(` Intent starts: ${
|
|
78
|
-
Last ${d.length} misaligned action(s):`);for(const c of d){const
|
|
79
|
-
Recent drift findings: ${
|
|
80
|
-
Sentinel + Claude Code integration ready.`)}catch(n){console.error(`Init failed: ${n.message}`),process.exit(1)}}if(
|
|
73
|
+
`;async function ue(){const t=g(process.cwd(),".sentinel.yaml");try{await G(t),console.log(`.sentinel.yaml already exists in ${process.cwd()}`);return}catch{}await C(t,ge,"utf-8"),console.log("Created .sentinel.yaml \u2014 edit then run: npm run sentinel -- --from-policy .sentinel.yaml")}async function fe(t){const o=await De(t),n=await E.fromPolicy(t);console.log(`Loaded policy for agent ${o.agent.id}. Monitoring active.`);const e=async()=>{await n.stop(),console.log("Monitoring stopped."),process.exit(0)},s=()=>{e().catch(i=>{console.error("Error during shutdown:",i),process.exit(1)})};process.on("SIGINT",s),process.on("SIGTERM",s)}async function jt(t,o,n){const e=g(h(),".dahlia","agents"),s=new E({agentsDir:e});await s.addAgent(t,t);const i=Z?Z.split(","):void 0,a=ee?ee.split(",").map(c=>c.trim()):void 0,d=s.startTask(t,o,n,{relaxedActions:i,phases:a});if(!d){console.log(`Failed to start task for agent ${t}.`),await s.stop();return}console.log(`Task started for agent ${t}:`),console.log(` Task ID: ${d.taskId}`),console.log(` Description: ${d.description}`),console.log(` Keywords: ${d.keywords.join(", ")}`),d.relaxedActions?.length&&console.log(` Relaxed: ${d.relaxedActions.join(", ")}`),d.phases?.length&&console.log(` Phases: ${d.phases.join(", ")}`),console.log(` TTL: ${(d.ttlMs/6e4).toFixed(0)} minutes`),await s.stop()}async function Mt(t){const o=g(h(),".dahlia","agents"),n=new E({agentsDir:o});await n.addAgent(t,t);const e=n.endTask(t);e?(console.log(`Task ended for agent ${t}:`),console.log(` Task ID: ${e.taskId}`),console.log(` Description: ${e.description}`),console.log(` Status: ${e.status}`)):console.log(`No active task found for agent ${t}.`),await n.stop()}async function Rt(t){const o=g(h(),".dahlia","agents"),n=new E({agentsDir:o});await n.addAgent(t,t);const e=n.getActiveTask(t);if(!e){console.log(`No active task for agent ${t}.`),await n.stop();return}const s=Date.now()-new Date(e.startedAt).getTime(),i=e.ttlMs-s;console.log(`Active task for agent ${t}:
|
|
74
|
+
`),console.log(` Task ID: ${e.taskId}`),console.log(` Description: ${e.description}`),console.log(` Keywords: ${e.keywords.join(", ")}`),console.log(` Status: ${e.status}`),console.log(` Active for: ${(s/6e4).toFixed(1)} minutes`),console.log(` TTL remain: ${i>0?(i/6e4).toFixed(1)+" minutes":"EXPIRED"}`),e.relaxedActions?.length&&console.log(` Relaxed: ${e.relaxedActions.join(", ")}`),e.phases?.length&&console.log(` Phases: ${e.phases.join(", ")}`),e.acceptableActions.length>0&&console.log(` Acceptable: ${e.acceptableActions.map(a=>`${a.action}:${a.targetPattern}`).join(", ")}`),await n.stop()}async function Nt(t){const o=g(h(),".dahlia","agents"),n=new b(t,{logDir:g(o,t)});await n.open();const e=await n.getStats(),s=await n.query({type:"intent_check"}),a=(await n.query({type:"finding"})).filter(c=>c.findingType==="intent_drift");console.log(`Intent Alignment Report \u2014 ${t}
|
|
75
|
+
`),console.log(` Intent starts: ${e.intentStartCount}`),console.log(` Intent ends: ${e.intentEndCount}`),console.log(` Intent checks: ${e.intentCheckCount}`),console.log(` Drift findings: ${e.intentDriftCount}`),e.averageAlignmentScore!==null&&console.log(` Avg alignment: ${e.averageAlignmentScore.toFixed(2)}`);const d=s.filter(c=>c.aligned===!1).slice(0,5);if(d.length>0){console.log(`
|
|
76
|
+
Last ${d.length} misaligned action(s):`);for(const c of d){const r=typeof c.score=="number"?c.score.toFixed(2):"?",l=c.action??"?",f=c.primaryTarget??c.targets?.[0]??"?";console.log(` score: ${r} ${l} \u2192 ${f} (${c.timestamp.split("T")[0]})`)}}if(a.length>0){console.log(`
|
|
77
|
+
Recent drift findings: ${a.length}`);for(const c of a.slice(0,3)){const r=c.severity??"?",l=c.description??"";console.log(` [${r}] ${typeof l=="string"?l.slice(0,80):l}`)}}await n.close()}async function Ft(t,o){try{const n=await be({force:t,port:o});if(n.created.length>0){console.log("Created:");for(const e of n.created)console.log(` ${e}`)}if(n.skipped.length>0){console.log("Skipped (already exists \u2014 use --force to overwrite):");for(const e of n.skipped)console.log(` ${e}`)}if(n.merged.length>0){console.log("Merged:");for(const e of n.merged)console.log(` ${e}`)}if(n.errors.length>0){console.log("Errors:");for(const e of n.errors)console.log(` ${e}`)}n.errors.length===0&&console.log(`
|
|
78
|
+
Sentinel + Claude Code integration ready.`)}catch(n){console.error(`Init failed: ${n.message}`),process.exit(1)}}if(_e){const t=v(u,"--port");await Ft(Ge,t?parseInt(t,10):void 0)}else if(ot&&p&&Y&&X)await jt(p,Y,X);else if(st&&p)await Mt(p);else if(at&&p)await Rt(p);else if(it&&p)await Nt(p);else if(Be)await ue();else if(z)await fe(z);else if(ze&&p)await kt(p);else if(Ye&&p)await Tt(p);else if(Qe&&p)await Et(p);else if(Xe)await Ct();else if(Ze&&p)await rt(p,te??"No reason provided");else if(et&&p)await lt(p,te??"No reason provided");else if(tt)await gt(p);else if(nt)await ut();else if(We)await yt();else if(Ke)await bt(p);else if(Oe&&p&&Q)await ht(p,Q,qe);else if(He&&p)await mt(p);else if(Je){const t=T?parseInt(T,10):30;await St(t,ne==="json"?"json":"markdown")}else if(Ue&&p){const t=T?parseInt(T,10):30;await It(p,t,ne==="json"?"json":"markdown")}else if(Ve){const t=T?parseInt(T,10):30;await Dt(t)}else p?await pt(p):await ft();
|
package/dist/gateway/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { v as Sentinel, e as AgentRole, S as SecurityFinding } from '../Sentinel-
|
|
1
|
+
import { v as Sentinel, e as AgentRole, S as SecurityFinding } from '../Sentinel-DT0IyGQi.js';
|
|
2
2
|
import 'node:crypto';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -174,6 +174,15 @@ declare class SentinelGateway {
|
|
|
174
174
|
* when the isolation gate is ON.
|
|
175
175
|
*/
|
|
176
176
|
private resolveBPathRouting;
|
|
177
|
+
/**
|
|
178
|
+
* Forbidden-pattern list for ONE request: the gateway's construction-time
|
|
179
|
+
* list unioned with the request's merged-role patterns (operator-ceiling ∩
|
|
180
|
+
* workspace yaml). Without this, a workspace's custom forbid targets were
|
|
181
|
+
* enforced by the role validator inside wrap() but never reached the
|
|
182
|
+
* gateway's own bash-L1 / Grep layers, which checked only the static list.
|
|
183
|
+
* Normalization is idempotent (the chokepoint globstar-prepend).
|
|
184
|
+
*/
|
|
185
|
+
private patternsForRequest;
|
|
177
186
|
private handlePreToolUse;
|
|
178
187
|
private handlePostToolUse;
|
|
179
188
|
private handleSessionEnd;
|
package/dist/gateway/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SentinelGateway
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-HRI2Y326.js";
|
|
4
4
|
import "../chunk-B5QKJHSV.js";
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
5
|
+
import "../chunk-B6S2PBS4.js";
|
|
6
|
+
import "../chunk-FIEIGBYL.js";
|
|
7
|
+
import "../chunk-KWZ7JKKO.js";
|
|
8
8
|
export {
|
|
9
9
|
SentinelGateway
|
|
10
10
|
};
|
package/dist/gatewayDaemon.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runGatewayDaemon
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-HRI2Y326.js";
|
|
5
5
|
import {
|
|
6
6
|
computeBuildId,
|
|
7
7
|
runSessionStart
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-LTBVWF5H.js";
|
|
9
9
|
import "./chunk-LATQNIRW.js";
|
|
10
10
|
import "./chunk-B5QKJHSV.js";
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-B6S2PBS4.js";
|
|
12
|
+
import "./chunk-FIEIGBYL.js";
|
|
13
|
+
import "./chunk-KWZ7JKKO.js";
|
|
14
14
|
|
|
15
15
|
// src/gatewayDaemon.ts
|
|
16
16
|
import { fileURLToPath } from "url";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as AgentActivityEvent, S as SecurityFinding } from './Sentinel-
|
|
2
|
-
export { a as AcceptableAction, b as AdapterConfig, c as AgentBaseline, d as AgentMode, e as AgentRole, f as AlertChannel, g as AlertConfig, h as AllowResponse, i as AuditEntry, j as AuditQueryOptions, B as BlockResponse, C as CorrelationFinding, E as ExceptionApprovalContext, k as ExceptionApprovalFn, G as GuideResponse, H as HookCheckpoint, l as HookContext, m as HookHandler, n as HookRegistration, o as HookResponse, I as IntentAlignmentConfig, p as IntentAlignmentResult, M as ModifiableEventFields, q as MonitorOptions, O as OverlayDecisionType, R as RepoSensitivityMap, r as ReportOptions, s as RoleException, t as SecuritySeverity, u as SensitivityOverlay, v as Sentinel, w as SentinelConfig, T as TaskIntent } from './Sentinel-
|
|
1
|
+
import { A as AgentActivityEvent, S as SecurityFinding } from './Sentinel-DT0IyGQi.js';
|
|
2
|
+
export { a as AcceptableAction, b as AdapterConfig, c as AgentBaseline, d as AgentMode, e as AgentRole, f as AlertChannel, g as AlertConfig, h as AllowResponse, i as AuditEntry, j as AuditQueryOptions, B as BlockResponse, C as CorrelationFinding, E as ExceptionApprovalContext, k as ExceptionApprovalFn, G as GuideResponse, H as HookCheckpoint, l as HookContext, m as HookHandler, n as HookRegistration, o as HookResponse, I as IntentAlignmentConfig, p as IntentAlignmentResult, M as ModifiableEventFields, q as MonitorOptions, O as OverlayDecisionType, R as RepoSensitivityMap, r as ReportOptions, s as RoleException, t as SecuritySeverity, u as SensitivityOverlay, v as Sentinel, w as SentinelConfig, T as TaskIntent } from './Sentinel-DT0IyGQi.js';
|
|
3
3
|
import 'node:crypto';
|
|
4
4
|
|
|
5
5
|
interface SentinelPolicy {
|
|
@@ -35,17 +35,11 @@ interface SentinelPolicy {
|
|
|
35
35
|
hours: [number, number];
|
|
36
36
|
days?: string[];
|
|
37
37
|
};
|
|
38
|
-
limits?: {
|
|
39
|
-
maxEventsPerHour?: number;
|
|
40
|
-
maxSessionDuration?: number;
|
|
41
|
-
};
|
|
42
38
|
};
|
|
43
39
|
enforcement?: {
|
|
44
40
|
restrictAfter?: number;
|
|
45
41
|
quarantineAfter?: number;
|
|
46
42
|
approvalRequired?: boolean;
|
|
47
|
-
/** Minimum finding kind that triggers enforcement actions. Defaults to "actionable". */
|
|
48
|
-
minKind?: "informational" | "actionable";
|
|
49
43
|
/**
|
|
50
44
|
* List of finding types to promote from "informational" to "actionable".
|
|
51
45
|
* Cannot include LOCKED_ACTIONABLE_TYPES (they are already actionable).
|
|
@@ -121,10 +115,6 @@ declare function runInitClaudeCode(options: {
|
|
|
121
115
|
home?: string;
|
|
122
116
|
}): Promise<InitReport>;
|
|
123
117
|
|
|
124
|
-
/**
|
|
125
|
-
* Walks up from a given directory looking for .sentinel.yaml.
|
|
126
|
-
* Stops at $HOME (inclusive) or filesystem root.
|
|
127
|
-
*/
|
|
128
118
|
declare function discoverPolicy(startDir: string, home: string): string | null;
|
|
129
119
|
|
|
130
120
|
/**
|
package/dist/index.js
CHANGED
|
@@ -2,20 +2,20 @@ import "./chunk-TKAKHSZ3.js";
|
|
|
2
2
|
import {
|
|
3
3
|
Sentinel,
|
|
4
4
|
createCliApproval
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-I2FVDDSG.js";
|
|
6
6
|
import {
|
|
7
7
|
runInitClaudeCode,
|
|
8
8
|
runSessionStart
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-LTBVWF5H.js";
|
|
10
10
|
import "./chunk-LATQNIRW.js";
|
|
11
11
|
import {
|
|
12
12
|
discoverPolicy
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-B6S2PBS4.js";
|
|
14
|
+
import "./chunk-FIEIGBYL.js";
|
|
15
15
|
import {
|
|
16
16
|
loadPolicy,
|
|
17
17
|
loadPolicyFromString
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-KWZ7JKKO.js";
|
|
19
19
|
import "./chunk-NUXSUSYY.js";
|
|
20
20
|
export {
|
|
21
21
|
Sentinel,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
LogAdapter
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2IPSTUNH.js";
|
|
4
4
|
|
|
5
5
|
// src/adapters/mcpAdapter.ts
|
|
6
6
|
var ACTION_MAP = {
|
|
@@ -175,4 +175,4 @@ export {
|
|
|
175
175
|
McpAdapter,
|
|
176
176
|
mapToolToAction
|
|
177
177
|
};
|
|
178
|
-
//# sourceMappingURL=mcpAdapter-
|
|
178
|
+
//# sourceMappingURL=mcpAdapter-WYAXUE7T.js.map
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
LOCKED_ACTIONABLE_TYPES,
|
|
3
|
+
checkSaneNumber,
|
|
3
4
|
loadPolicy,
|
|
4
5
|
loadPolicyFromString,
|
|
5
6
|
policyToConfig,
|
|
6
|
-
policyToRole
|
|
7
|
-
|
|
7
|
+
policyToRole,
|
|
8
|
+
suggestKey
|
|
9
|
+
} from "./chunk-KWZ7JKKO.js";
|
|
8
10
|
export {
|
|
9
11
|
LOCKED_ACTIONABLE_TYPES,
|
|
12
|
+
checkSaneNumber,
|
|
10
13
|
loadPolicy,
|
|
11
14
|
loadPolicyFromString,
|
|
12
15
|
policyToConfig,
|
|
13
|
-
policyToRole
|
|
16
|
+
policyToRole,
|
|
17
|
+
suggestKey
|
|
14
18
|
};
|
|
15
|
-
//# sourceMappingURL=policyLoader-
|
|
19
|
+
//# sourceMappingURL=policyLoader-XX6BQXNB.js.map
|
package/package.json
CHANGED
package/dist/chunk-FMZWHT4M.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
// src/setup/policyDiscovery.ts
|
|
2
|
-
import { existsSync } from "fs";
|
|
3
|
-
import { resolve, join, dirname } from "path";
|
|
4
|
-
function discoverPolicy(startDir, home) {
|
|
5
|
-
let dir = resolve(startDir);
|
|
6
|
-
const homeAbs = resolve(home);
|
|
7
|
-
while (true) {
|
|
8
|
-
const candidate = join(dir, ".sentinel.yaml");
|
|
9
|
-
if (existsSync(candidate)) return candidate;
|
|
10
|
-
if (dir === homeAbs) return null;
|
|
11
|
-
const parent = dirname(dir);
|
|
12
|
-
if (parent === dir) return null;
|
|
13
|
-
dir = parent;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export {
|
|
18
|
-
discoverPolicy
|
|
19
|
-
};
|
|
20
|
-
//# sourceMappingURL=chunk-FMZWHT4M.js.map
|