@@ -143,40 +143,38 @@ in-house ruleset) and keep the escalation machinery.
143143
144144## SDKs (Python · TypeScript)
145145
146- Drive sentry from your own code — author ACL policy, run the judge, submit events, stream typed
147- decisions, read metrics — instead of wiring stdin/stdout by hand. Both are dependency-free and mirror
148- the same model; each is contract-tested against the real binary (an SSRF event round-trips to a
149- ` block ` , and an SDK-authored ACL rule fires through the daemon's own parser).
146+ ** Native, in-process** SDKs — the Rust L1/L2/L3 judge embedded via PyO3 (Python) and napi-rs
147+ (TypeScript), the same model as [ ` @a3s-lab/code ` ] ( https://github.com/A3S-Lab/Code ) . Build the judge
148+ from one ACL config (the daemon's whole config in a single file — rules + L2/L3 backends + sinks) and
149+ evaluate observer events in-process; no daemon, no subprocess. Each is verified by judging real events
150+ through the embedded engine (a cloud-metadata SSRF → ` block ` /` DenyEgress ` ; an SDK-authored ACL rule
151+ firing at ` tier=Rules ` ).
150152
151- - ** Python** — [ ` sdk/python ` ] ( sdk/python ) (` pip install a3s-sentry ` ), async :
153+ - ** Python** — [ ` sdk/python ` ] ( sdk/python ) (` pip install a3s-sentry ` ):
152154
153155 ``` python
154- from a3s_sentry import Sentry, SentryConfig, Event, Policy, Rule, Verdict, Severity, Action
156+ from a3s_sentry import Sentry, egress, tool_exec
155157
156- Policy([Rule(" no-netcat" , " ToolExec" , r " (?i) \b ( ncat| netcat) \b " ,
157- Verdict.BLOCK , Severity.MEDIUM , " netcat" , Action.DENY_EXEC )]).write(" rules.acl" )
158-
159- async with Sentry(SentryConfig(policy = " rules.acl" , egress_deny = " egress.txt" )) as s:
160- await s.submit(Event.egress(1 , " 169.254.169.254" , 80 )) # cloud-metadata SSRF
161- async for audit in s.decisions():
162- print (audit.decision.verdict, audit.subject); break
158+ sentry = Sentry.create(" sentry.acl" ) # ACL file path or content
159+ d = sentry.evaluate(egress(1 , " 169.254.169.254" , 80 )) # cloud-metadata SSRF
160+ print (d.verdict, d.action.kind, d.action.target) # block DenyEgress 169.254.169.254
161+ d2, enforced = sentry.evaluate_and_enforce(tool_exec(2 , [" /usr/bin/ncat" , " h" , " 4444" ]))
163162 ```
164163
165- - ** TypeScript** — [ ` sdk/typescript ` ] ( sdk/typescript ) (` @a3s-lab/sentry ` ) , Node 18+ :
164+ - ** TypeScript** — [ ` sdk/typescript ` ] ( sdk/typescript ) (` @a3s-lab/sentry ` , Node ≥12) :
166165
167166 ``` ts
168- import { Sentry , Policy , Event } from " @a3s-lab/sentry" ;
169-
170- new Policy ([{ name: " no-netcat" , on: " ToolExec" , match: " (?i)\\ b(ncat|netcat)\\ b" ,
171- verdict: " block" , severity: " medium" , reason: " netcat" , action: " deny-exec" }])
172- .write (" rules.acl" );
167+ import { Sentry , egress } from " @a3s-lab/sentry" ;
173168
174- const s = new Sentry ({ policy: " rules.acl" , egressDeny: " egress.txt" });
175- await s .start ();
176- await s .submit (Event .egress (1 , " 169.254.169.254" , 80 ));
177- for await (const audit of s .decisions ()) { console .log (audit .decision .verdict , audit .subject ); break ; }
169+ const sentry = Sentry .create (" sentry.acl" );
170+ const d = sentry .evaluate (egress (1 , " 169.254.169.254" , 80 ));
171+ if (d ?.verdict === " block" ) console .log (d .reason , d .action ); // { kind: "DenyEgress", target: "…" }
178172 ```
179173
174+ The ` sentry.acl ` config — rules, optional ` llm {} ` (L2) / ` agent {} ` (L3) backends, and ` deny {} `
175+ sinks — is shown in each SDK's README. Event builders (` egress ` , ` toolExec ` , ` dns ` , ` fileAccess ` ,
176+ ` sslContent ` , ` securityAction ` ) construct the event JSON ` evaluate ` takes.
177+
180178## Speculative parallelism
181179
182180By default the tiers run serially (L2, then L3 only if L2 escalates). Set ` A3S_SENTRY_SPECULATE=high `
0 commit comments