guardledger 0.1.0__tar.gz
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.
- guardledger-0.1.0/.claude/launch.json +11 -0
- guardledger-0.1.0/.env.example +14 -0
- guardledger-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +20 -0
- guardledger-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +13 -0
- guardledger-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +10 -0
- guardledger-0.1.0/.github/workflows/ci.yml +24 -0
- guardledger-0.1.0/.github/workflows/release.yml +25 -0
- guardledger-0.1.0/.gitignore +32 -0
- guardledger-0.1.0/ARCHITECTURE.md +148 -0
- guardledger-0.1.0/CHANGELOG.md +40 -0
- guardledger-0.1.0/COMPLIANCE.md +90 -0
- guardledger-0.1.0/CONTRIBUTING.md +30 -0
- guardledger-0.1.0/DECISIONS.md +85 -0
- guardledger-0.1.0/DEMO.md +90 -0
- guardledger-0.1.0/INTEGRATIONS.md +85 -0
- guardledger-0.1.0/LAUNCH.md +112 -0
- guardledger-0.1.0/LICENSE +173 -0
- guardledger-0.1.0/Makefile +22 -0
- guardledger-0.1.0/PKG-INFO +180 -0
- guardledger-0.1.0/PRD.md +97 -0
- guardledger-0.1.0/PUBLISHING.md +46 -0
- guardledger-0.1.0/README.md +149 -0
- guardledger-0.1.0/RESEARCH.md +282 -0
- guardledger-0.1.0/ROADMAP.md +62 -0
- guardledger-0.1.0/SECURITY.md +60 -0
- guardledger-0.1.0/examples/benchmark.py +48 -0
- guardledger-0.1.0/examples/generic_agent.py +140 -0
- guardledger-0.1.0/examples/trading_agent.py +138 -0
- guardledger-0.1.0/launch/outreach.md +42 -0
- guardledger-0.1.0/launch/reddit.md +29 -0
- guardledger-0.1.0/launch/show-hn.md +34 -0
- guardledger-0.1.0/launch/x-thread.md +37 -0
- guardledger-0.1.0/policies/example.yaml +41 -0
- guardledger-0.1.0/policies/starter.yaml +38 -0
- guardledger-0.1.0/pyproject.toml +56 -0
- guardledger-0.1.0/site/index.html +120 -0
- guardledger-0.1.0/src/sentinel/__init__.py +53 -0
- guardledger-0.1.0/src/sentinel/api.py +126 -0
- guardledger-0.1.0/src/sentinel/approvals.py +122 -0
- guardledger-0.1.0/src/sentinel/audit.py +171 -0
- guardledger-0.1.0/src/sentinel/cli.py +166 -0
- guardledger-0.1.0/src/sentinel/compliance.py +77 -0
- guardledger-0.1.0/src/sentinel/config.py +46 -0
- guardledger-0.1.0/src/sentinel/dashboard/index.html +197 -0
- guardledger-0.1.0/src/sentinel/db.py +19 -0
- guardledger-0.1.0/src/sentinel/detector.py +97 -0
- guardledger-0.1.0/src/sentinel/frameworks.py +239 -0
- guardledger-0.1.0/src/sentinel/killswitch.py +58 -0
- guardledger-0.1.0/src/sentinel/mcp_proxy.py +61 -0
- guardledger-0.1.0/src/sentinel/mcp_server.py +79 -0
- guardledger-0.1.0/src/sentinel/models.py +88 -0
- guardledger-0.1.0/src/sentinel/otel.py +80 -0
- guardledger-0.1.0/src/sentinel/policy.py +128 -0
- guardledger-0.1.0/src/sentinel/py.typed +0 -0
- guardledger-0.1.0/src/sentinel/ratelimit.py +46 -0
- guardledger-0.1.0/src/sentinel/redaction.py +46 -0
- guardledger-0.1.0/src/sentinel/sentinel.py +191 -0
- guardledger-0.1.0/tests/test_api.py +111 -0
- guardledger-0.1.0/tests/test_approvals.py +74 -0
- guardledger-0.1.0/tests/test_audit.py +82 -0
- guardledger-0.1.0/tests/test_compliance.py +25 -0
- guardledger-0.1.0/tests/test_db.py +19 -0
- guardledger-0.1.0/tests/test_detector.py +71 -0
- guardledger-0.1.0/tests/test_frameworks.py +49 -0
- guardledger-0.1.0/tests/test_killswitch.py +28 -0
- guardledger-0.1.0/tests/test_mcp_proxy.py +119 -0
- guardledger-0.1.0/tests/test_mcp_server.py +62 -0
- guardledger-0.1.0/tests/test_otel.py +49 -0
- guardledger-0.1.0/tests/test_policy.py +109 -0
- guardledger-0.1.0/tests/test_ratelimit.py +41 -0
- guardledger-0.1.0/tests/test_sentinel.py +245 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Sentinel configuration (copy to .env; .env is git-ignored)
|
|
2
|
+
|
|
3
|
+
# Where the tamper-evident audit log lives (SQLite).
|
|
4
|
+
SENTINEL_DB_PATH=./data/sentinel.db
|
|
5
|
+
|
|
6
|
+
# Active policy file (YAML).
|
|
7
|
+
SENTINEL_POLICY_PATH=./policies/starter.yaml
|
|
8
|
+
|
|
9
|
+
# Minimal control API / dashboard.
|
|
10
|
+
SENTINEL_API_HOST=127.0.0.1
|
|
11
|
+
SENTINEL_API_PORT=8787
|
|
12
|
+
|
|
13
|
+
# Comma-separated arg keys whose values are redacted before they ever hit the audit log.
|
|
14
|
+
SENTINEL_REDACT_KEYS=api_key,apikey,token,password,passwd,secret,authorization,access_token,private_key
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Something isn't working as documented
|
|
4
|
+
labels: bug
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**What happened**
|
|
8
|
+
|
|
9
|
+
**What you expected**
|
|
10
|
+
|
|
11
|
+
**Steps to reproduce**
|
|
12
|
+
1.
|
|
13
|
+
2.
|
|
14
|
+
|
|
15
|
+
**Environment**
|
|
16
|
+
- Sentinel version / commit:
|
|
17
|
+
- Python version:
|
|
18
|
+
- OS:
|
|
19
|
+
|
|
20
|
+
**Logs / output** (do NOT paste live secrets or customer data)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest an idea or improvement
|
|
4
|
+
labels: enhancement
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**The problem / use case** (what are you trying to do?)
|
|
8
|
+
|
|
9
|
+
**Proposed solution**
|
|
10
|
+
|
|
11
|
+
**Alternatives you considered**
|
|
12
|
+
|
|
13
|
+
**Which framework / agent are you using?** (LangChain, OpenAI Agents, CrewAI, MCP, plain Python, …)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
## What this changes
|
|
2
|
+
|
|
3
|
+
## Why
|
|
4
|
+
|
|
5
|
+
## Checklist
|
|
6
|
+
- [ ] `pytest` is green
|
|
7
|
+
- [ ] `ruff check src tests` is clean
|
|
8
|
+
- [ ] Added/updated tests (security-critical code — policy, audit, kill switch — is tests-first)
|
|
9
|
+
- [ ] Docs updated if behavior changed
|
|
10
|
+
- [ ] No secrets committed; the audit log stays append-only / tamper-evident
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
strategy:
|
|
11
|
+
fail-fast: false
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: ${{ matrix.python-version }}
|
|
19
|
+
- name: Install
|
|
20
|
+
run: pip install -e ".[dev]"
|
|
21
|
+
- name: Lint
|
|
22
|
+
run: ruff check src tests
|
|
23
|
+
- name: Test
|
|
24
|
+
run: pytest
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# Publishes to PyPI when a version tag (v*) is pushed, using PyPI Trusted Publishing
|
|
4
|
+
# (OIDC — no API token stored in the repo). See PUBLISHING.md for the one-time setup.
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
tags: ["v*"]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
publish:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
environment: pypi
|
|
13
|
+
permissions:
|
|
14
|
+
id-token: write # required for Trusted Publishing
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.12"
|
|
20
|
+
- name: Build
|
|
21
|
+
run: |
|
|
22
|
+
pip install build
|
|
23
|
+
python -m build
|
|
24
|
+
- name: Publish to PyPI
|
|
25
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Secrets
|
|
2
|
+
.env
|
|
3
|
+
.env.*
|
|
4
|
+
!.env.example
|
|
5
|
+
|
|
6
|
+
# Dependencies
|
|
7
|
+
node_modules/
|
|
8
|
+
__pycache__/
|
|
9
|
+
.venv/
|
|
10
|
+
venv/
|
|
11
|
+
*.egg-info/
|
|
12
|
+
|
|
13
|
+
# Build / artifacts
|
|
14
|
+
dist/
|
|
15
|
+
build/
|
|
16
|
+
*.log
|
|
17
|
+
.wrangler/
|
|
18
|
+
|
|
19
|
+
# Local audit/data stores (do not commit runtime data)
|
|
20
|
+
*.db
|
|
21
|
+
*.db-wal
|
|
22
|
+
*.db-shm
|
|
23
|
+
*.sqlite
|
|
24
|
+
*.sqlite-wal
|
|
25
|
+
*.sqlite-shm
|
|
26
|
+
*.sqlite3
|
|
27
|
+
data/
|
|
28
|
+
|
|
29
|
+
# OS / editor
|
|
30
|
+
.DS_Store
|
|
31
|
+
.idea/
|
|
32
|
+
.vscode/
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# ARCHITECTURE.md — Sentinel MVP
|
|
2
|
+
|
|
3
|
+
> v0.1 · Phase 2. Stack ו-interception אושרו 2026-06-13. כולל threat model.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. עקרונות מנחים
|
|
8
|
+
|
|
9
|
+
1. **Default-deny** — פעולה שלא הותרה במפורש נחסמת.
|
|
10
|
+
2. **Fail-closed** — אם שכבת ההכרעה עצמה נכשלת (שגיאה ב-policy/audit), הפעולה **נחסמת**, לא רצה. אבטחה > זמינות.
|
|
11
|
+
3. **Append-only + tamper-evident** — ה-audit לא נמחק ולא משתנה; כל שינוי מתגלה ב-`verify`.
|
|
12
|
+
4. **Interceptor מופשט** — הליבה (policy/audit/kill/detect) לא יודעת איך יורטה הפעולה. SDK wrapper היום, MCP-proxy מחר — אותה ליבה.
|
|
13
|
+
5. **Sentinel הוא נקודת כשל high-value** — מתייחסים לקוד שלנו עצמו כמשטח תקיפה (סעיף 6).
|
|
14
|
+
|
|
15
|
+
## 2. Stack (אושר)
|
|
16
|
+
|
|
17
|
+
| רכיב | בחירה | נימוק |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| שפה | **Python 3.11+** | העולם של MeiroX + ecosystem הסוכנים; מסלול מהיר |
|
|
20
|
+
| Interception | **SDK wrapper** (decorator/wrap) מאחורי `Interceptor` interface | מכסה את ה-tools הישירים של MeiroX, framework-agnostic, דטרמיניסטי ל-tests-first; MCP-proxy נכנס כ-adapter בלי שכתוב |
|
|
21
|
+
| Audit store | **SQLite** + hash-chain | embeddable, tamper-evident פשוט, משדרג ל-Postgres |
|
|
22
|
+
| Policy | **YAML** (`yaml.safe_load`) | declarative, קריא ללקוח, ניתן לעריכה ב-dashboard |
|
|
23
|
+
| API/Dashboard | **FastAPI** + עמוד HTML מינימלי | קל, async, OpenAPI חינם |
|
|
24
|
+
| בדיקות | **pytest** | tests-first על הליבה הקריטית |
|
|
25
|
+
|
|
26
|
+
## 3. דיאגרמת רכיבים + data flow
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
agent (למשל trading_agent)
|
|
30
|
+
│ tool_call(name, args)
|
|
31
|
+
▼
|
|
32
|
+
┌─────────────────────────────────────────────────────────┐
|
|
33
|
+
│ Interceptor (SDK wrapper) → sentinel.check(ToolCall) │
|
|
34
|
+
└───────────────────────────────┬─────────────────────────┘
|
|
35
|
+
▼
|
|
36
|
+
┌──────────────────────────────────────────┐
|
|
37
|
+
│ 1. KillSwitch.active? → block(reason=kill)│ (fail-closed)
|
|
38
|
+
│ 2. Detector.inspect() → flags[] │ (מסמן, לא חוסם)
|
|
39
|
+
│ 3. Policy.evaluate() → allow/block/ │ (default-deny)
|
|
40
|
+
│ require_approval │
|
|
41
|
+
│ 4. combine → Decision │
|
|
42
|
+
└───────────────┬────────────────────────────┘
|
|
43
|
+
allow ───────┤────── block / require_approval
|
|
44
|
+
│ │
|
|
45
|
+
execute tool_fn │ (לא מבוצע)
|
|
46
|
+
(try/except) │
|
|
47
|
+
│ │
|
|
48
|
+
▼ ▼
|
|
49
|
+
┌──────────────────────────────────────────┐
|
|
50
|
+
│ AuditLog.append(record) (hash-chained, │
|
|
51
|
+
│ redacted, compliance-mapped) │
|
|
52
|
+
└───────────────┬────────────────────────────┘
|
|
53
|
+
▼
|
|
54
|
+
┌──────────────────────────────────────────┐
|
|
55
|
+
│ FastAPI: /actions /audit/verify /export │
|
|
56
|
+
│ /policy /kill /status + dashboard│
|
|
57
|
+
└────────────────────────────────────────────┘
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**רצף לקריאה מותרת:** check → allow → execute → append record (status=`executed`/`error`).
|
|
61
|
+
**רצף לקריאה חסומה:** check → block → append record (status=`blocked`/`killed`/`pending_approval`), ה-tool **לא** מבוצע.
|
|
62
|
+
|
|
63
|
+
## 4. מודל הנתונים — רשומת Audit (לב המוצר)
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
AuditRecord
|
|
67
|
+
seq int # מונוטוני
|
|
68
|
+
ts float/iso # זמן
|
|
69
|
+
agent_id str
|
|
70
|
+
session_id str
|
|
71
|
+
tool str
|
|
72
|
+
args dict # אחרי redaction
|
|
73
|
+
decision enum # allow | block | require_approval
|
|
74
|
+
policy_rule str|null # id הכלל שהתאים (או null=default-deny)
|
|
75
|
+
reason str
|
|
76
|
+
flags [str] # מה-Detector
|
|
77
|
+
status enum # executed | blocked | error | pending_approval | killed
|
|
78
|
+
error str|null
|
|
79
|
+
compliance {eu_ai_act_art12: bool, owasp_agentic: [str]}
|
|
80
|
+
prev_hash str(64)
|
|
81
|
+
hash str(64) # sha256( prev_hash + canonical_json(payload) )
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Hash-chain:** רשומת genesis עם `prev_hash="0"*64`. כל רשומה: `hash = sha256(prev_hash + canonical_json(הכל חוץ מ-hash))`. `verify()` מחשב מחדש את כל השרשרת ובודק (א) כל hash תואם, (ב) כל `prev_hash` תואם ל-hash הקודם. כל עריכה/מחיקה/שינוי-סדר באמצע → מתגלה. (truncation של הזנב — מיטיגציה ב-`ROADMAP.md`: anchoring חיצוני תקופתי.)
|
|
85
|
+
|
|
86
|
+
> הערה: רשומה אחת לכל tool call, נכתבת אחרי ניסיון הביצוע (עטוף ב-try/except, כך ששגיאת tool עדיין נרשמת). הפער היחיד: process kill באמצע ביצוע. מיטיגציה (roadmap): two-phase logging (intent לפני, outcome אחרי).
|
|
87
|
+
|
|
88
|
+
## 5. מודל ה-Policy (YAML)
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
version: 1
|
|
92
|
+
default: deny # default-deny
|
|
93
|
+
rules:
|
|
94
|
+
- id: allow-reads
|
|
95
|
+
match: { tool: ["get_*", "read_*"] } # glob
|
|
96
|
+
action: allow
|
|
97
|
+
- id: cap-order
|
|
98
|
+
match:
|
|
99
|
+
tool: place_order
|
|
100
|
+
args: { amount: { gt: 500 } } # comparators: gt/gte/lt/lte/eq/in/contains
|
|
101
|
+
action: require_approval
|
|
102
|
+
- id: rate-limit-orders
|
|
103
|
+
match: { tool: place_order }
|
|
104
|
+
rate_limit: { max: 5, per_seconds: 60 } # מעל הסף → block
|
|
105
|
+
action: allow
|
|
106
|
+
- id: forbid-deletes
|
|
107
|
+
match: { tool: "delete_*" }
|
|
108
|
+
action: block
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
הכרעה: **first-match-wins** (לפי סדר), אחרת `default`. תמיכה: glob על שם tool, comparators על args, rate_limit (sliding window in-memory ל-MVP), ו-`on_flag: block` אופציונלי להסלמה על flag מה-Detector.
|
|
112
|
+
|
|
113
|
+
## 6. Threat Model (Sentinel עצמו כמשטח תקיפה)
|
|
114
|
+
|
|
115
|
+
| # | איום | מיטיגציה ב-MVP | סטטוס/roadmap |
|
|
116
|
+
|---|---|---|---|
|
|
117
|
+
| T1 | **Bypass** — קריאה ל-tool לא-עטוף | helper `wrap_all` + תיעוד; default-deny על מה שמוכר | מגבלת SDK-mode; proxy/egress עתידי הופך bypass לבלתי-אפשרי |
|
|
118
|
+
| T2 | **Audit tampering** — עריכת ה-DB | hash-chain → `verify` מגלה כל edit/reorder/delete | anchoring חיצוני נגד truncation (roadmap) |
|
|
119
|
+
| T3 | **Log-as-exfil / log injection** | redaction לפני כתיבה; args כ-data בלבד; canonical JSON | — |
|
|
120
|
+
| T4 | **Policy evasion** — args שמתחמקים מ-match | **default-deny** + טסטים על matchers | — |
|
|
121
|
+
| T5 | **Kill switch failure** | נבדק בכל קריאה, **persisted** (שורד restart), **fail-closed** אם לא נקרא | — |
|
|
122
|
+
| T6 | **Sentinel כ-vector** — ReDoS/YAML | `yaml.safe_load`, regexes חסומים | — |
|
|
123
|
+
| T7 | **Secrets handling** | redaction; אין סודות בלוג; `.env` (לא מקומיט) | — |
|
|
124
|
+
| T8 | **Fail-open** — שגיאה בליבה → tool רץ? | **fail-closed**: כל חריגה ב-check → block (נבדק בטסט) | — |
|
|
125
|
+
|
|
126
|
+
## 7. מבנה הפרויקט
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
sentinel/
|
|
130
|
+
src/sentinel/
|
|
131
|
+
models.py # ToolCall, Decision, AuditRecord
|
|
132
|
+
redaction.py # redaction של סודות
|
|
133
|
+
policy.py # טעינה + הכרעת YAML (default-deny, glob, comparators, rate-limit)
|
|
134
|
+
audit.py # AuditLog: SQLite, hash-chain, verify, export
|
|
135
|
+
killswitch.py # KillSwitch persisted (fail-closed)
|
|
136
|
+
detector.py # heuristics v1 (lethal-trifecta, off-baseline, injection sigs)
|
|
137
|
+
compliance.py # מיפוי Art.12 / OWASP Agentic
|
|
138
|
+
sentinel.py # הליבה: check() + wrap() (Interceptor)
|
|
139
|
+
api.py # FastAPI + dashboard
|
|
140
|
+
config.py
|
|
141
|
+
policies/example.yaml
|
|
142
|
+
examples/trading_agent.py # סוכן דמו (beachhead פיננסי)
|
|
143
|
+
tests/ # tests-first על policy/audit/kill
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## 8. למה זה לא נועל אותנו
|
|
147
|
+
|
|
148
|
+
`Interceptor` הוא interface. SDK wrapper הוא מימוש אחד; הליבה (`check()`) מקבלת `ToolCall` ולא יודעת מאיפה הגיע. MCP-proxy עתידי = adapter שבונה `ToolCall` מתעבורת MCP וקורא לאותו `check()`. אפס שכתוב של policy/audit/kill.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 (unreleased)
|
|
4
|
+
|
|
5
|
+
MVP of the audit/flight-recorder wedge, plus first hardening pass.
|
|
6
|
+
|
|
7
|
+
### Core
|
|
8
|
+
- Declarative, default-deny **policy engine** (YAML): glob + arg comparators + rate limits.
|
|
9
|
+
- Append-only, hash-chained **audit trail** (SQLite) with `verify` (tamper-evident) and a compliance `export`.
|
|
10
|
+
- **Two-phase logging**: intent (pre-exec) + outcome (post-exec) records linked by `action_id`.
|
|
11
|
+
- Persisted **kill switch** (global / per-agent) and `fail-closed` enforcement.
|
|
12
|
+
- **Detector** heuristics: full lethal-trifecta (untrusted-content tracking), off-baseline, injection signatures, dangerous-arg (cmd/SQL/path/URL), PII-in-arg.
|
|
13
|
+
- Secret **redaction** at write time; compliance mapping (EU AI Act Art. 12, OWASP Agentic).
|
|
14
|
+
- **Monitor mode** (observe-only): logs the would-be verdict, never blocks — but the kill switch still enforces. The trust bridge before flipping to enforcement.
|
|
15
|
+
|
|
16
|
+
### Interception
|
|
17
|
+
- **SDK wrapper** (`@sentinel.guard`) — the default interceptor.
|
|
18
|
+
- **MCP proxy** (`MCPProxy`) — second interceptor over the same `enforce()` path; no bypass.
|
|
19
|
+
- **Sentinel-guarded MCP server** (`SentinelMCPServer`) — expose tools over real MCP with enforcement built in (optional `mcp` extra).
|
|
20
|
+
- **Upstream MCP proxy** (`AsyncMCPProxy`) — man-in-the-middle over a live `mcp.ClientSession` (async `aenforce`).
|
|
21
|
+
- **Framework-agnostic by default**: generic `policies/starter.yaml` + a generic demo (`sentinel demo`); `Sentinel.wrap_all()` guards a whole toolset; INTEGRATIONS.md covers plain functions / LangChain / OpenAI Agents / CrewAI / MCP. (Trading is now just a vertical example.)
|
|
22
|
+
|
|
23
|
+
### Control plane
|
|
24
|
+
- FastAPI **dashboard** + API: live feed, integrity verify, policy editor, kill switch, approvals.
|
|
25
|
+
- **API auth** via `SENTINEL_API_TOKEN` on mutating endpoints; `sentinel serve` auto-generates one.
|
|
26
|
+
- **Read-endpoint protection** (`SENTINEL_API_PROTECT_READS`) — gate the sensitive audit reads behind the token too.
|
|
27
|
+
- **Human-in-the-loop approvals**: `require_approval` parks a call; operator approves; next identical call runs once.
|
|
28
|
+
- Persistent **rate limiter** (survives restart / shared across processes).
|
|
29
|
+
|
|
30
|
+
### Tooling
|
|
31
|
+
- CLI: `serve | verify | export [--format json|otel] | kill | unkill | approvals | approve | demo`.
|
|
32
|
+
- **Retention**: approval TTL + `sentinel gc` purges stale approvals / rate-limit state (audit log untouched).
|
|
33
|
+
- **Multi-framework compliance mapping** (`sentinel compliance`): EU AI Act, GDPR, NIST AI RMF, ISO 42001, Colorado AI Act, SEC/FINRA — honest full/partial/none coverage (COMPLIANCE.md).
|
|
34
|
+
- **EU AI Act Art.12 report** (`export --format art12`); OpenTelemetry GenAI export (JSON spans + real SDK emission).
|
|
35
|
+
- **PyPI release automation** (Trusted Publishing) — see PUBLISHING.md.
|
|
36
|
+
- Optional extras: `pip install "sentinel[mcp,otel]"`. Clean wheel/sdist build.
|
|
37
|
+
- Pre-launch security: dashboard HTML-escaping (anti-XSS), disclaimers (alpha / not legal advice), concurrency-safe audit append.
|
|
38
|
+
- CI (GitHub Actions, py3.11–3.13) with a ruff lint gate. Concurrency-safe SQLite (WAL + busy_timeout). Apache-2.0.
|
|
39
|
+
|
|
40
|
+
78 tests passing.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# COMPLIANCE.md — how Sentinel maps to existing AI / data law
|
|
2
|
+
|
|
3
|
+
> ⚠️ **Indicative engineering mapping — not legal advice or a conformity assessment.**
|
|
4
|
+
> Coverage describes what Sentinel *provides*, not whether *you* are compliant. Verify
|
|
5
|
+
> against the current legal texts. `sentinel compliance` is the machine-readable source
|
|
6
|
+
> of truth; this file mirrors it.
|
|
7
|
+
>
|
|
8
|
+
> Legend: **full** = Sentinel provides the control · **partial** = Sentinel provides
|
|
9
|
+
> evidence/infrastructure, you do the rest · **none** = out of scope (listed honestly).
|
|
10
|
+
|
|
11
|
+
## Coverage at a glance
|
|
12
|
+
|
|
13
|
+
| Framework | Jurisdiction | full | partial | none |
|
|
14
|
+
|---|---|:--:|:--:|:--:|
|
|
15
|
+
| EU AI Act (2024/1689) | EU | 1 | 4 | 2 |
|
|
16
|
+
| GDPR (2016/679) | EU/EEA | 0 | 4 | 1 |
|
|
17
|
+
| NIST AI RMF 1.0 | US (voluntary) | 0 | 3 | 1 |
|
|
18
|
+
| ISO/IEC 42001:2023 | International | 0 | 3 | 1 |
|
|
19
|
+
| Colorado AI Act (SB 24-205) | US — Colorado | 0 | 3 | 1 |
|
|
20
|
+
| SEC 17a-4 / FINRA 4511 | US — securities | 0 | 3 | 0 |
|
|
21
|
+
|
|
22
|
+
Sentinel is an **evidence + control-plane** layer: it makes the *logging, oversight,
|
|
23
|
+
and audit* obligations satisfiable. It does **not** do risk classification, conformity
|
|
24
|
+
assessment, DPIAs, user-facing disclosure, or your organisational processes.
|
|
25
|
+
|
|
26
|
+
## EU AI Act (Regulation 2024/1689)
|
|
27
|
+
|
|
28
|
+
| Article | Requirement (paraphrased) | Coverage | How |
|
|
29
|
+
|---|---|---|---|
|
|
30
|
+
| Art. 12 | Automatic event logs over the system lifetime | **full** | Append-only hash-chained audit; `export --format art12` |
|
|
31
|
+
| Art. 14 | Human oversight / stop button | partial | Kill switch + approvals; you design the oversight process |
|
|
32
|
+
| Art. 19 / 26(6) | Retain logs (deployers ≥ 6 months) | partial | Durable + tamper-evident; you set retention/backup |
|
|
33
|
+
| Art. 26 | Deployer monitoring, logs, oversight | partial | Action feed + audit + kill/approvals |
|
|
34
|
+
| Art. 72 | Post-market monitoring | partial | Audit + detector flags are the raw data |
|
|
35
|
+
| Art. 50 | Transparency to users / content marking | none | Sentinel governs actions, not disclosure |
|
|
36
|
+
| Art. 9 / Annex IV | Risk-management system & technical docs | none | Organisational process |
|
|
37
|
+
|
|
38
|
+
## GDPR (2016/679)
|
|
39
|
+
|
|
40
|
+
| Article | Requirement | Coverage | How |
|
|
41
|
+
|---|---|---|---|
|
|
42
|
+
| Art. 5(1)(c) | Data minimisation | partial | Secret/PII redaction before logging; PII detector |
|
|
43
|
+
| Art. 22 | Human intervention in automated decisions | partial | Approvals + kill provide the checkpoint |
|
|
44
|
+
| Art. 30 | Records of processing | partial | Per-action audit trail |
|
|
45
|
+
| Art. 32 | Security of processing | partial | Token-gated plane + tamper-evident logs |
|
|
46
|
+
| Art. 17 | Right to erasure | none | Audit is append-only — keep PII out (redaction); erase in source systems |
|
|
47
|
+
|
|
48
|
+
## NIST AI RMF 1.0 (+ GenAI profile)
|
|
49
|
+
|
|
50
|
+
| Function | Coverage | How |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| GOVERN | partial | Default-deny policy + immutable audit |
|
|
53
|
+
| MAP | none | Analytical/process activity |
|
|
54
|
+
| MEASURE | partial | Detector flags + action feed = continuous monitoring |
|
|
55
|
+
| MANAGE | partial | Kill switch + forensic audit for response/recovery |
|
|
56
|
+
|
|
57
|
+
## ISO/IEC 42001:2023
|
|
58
|
+
|
|
59
|
+
| Control theme | Coverage | How |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| Operational controls & monitoring | partial | Runtime enforcement + live monitoring + audit |
|
|
62
|
+
| Event logging & records | partial | Tamper-evident audit; auditor export |
|
|
63
|
+
| Incident management | partial | Detector + kill + audit |
|
|
64
|
+
| Management-system processes (Cl. 4-10) | none | Organisational AIMS |
|
|
65
|
+
|
|
66
|
+
## Colorado AI Act (SB 24-205, eff. 2026-06-30)
|
|
67
|
+
|
|
68
|
+
| Obligation | Coverage | How |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| Risk-management program | partial | Policy + audit are core evidence |
|
|
71
|
+
| Recordkeeping | partial | Per-action audit trail |
|
|
72
|
+
| AG notice of algorithmic discrimination (≤90 days) | partial | Detector + audit help detect/evidence; notice is yours |
|
|
73
|
+
| Consumer notice / right to contest | none | User-facing process |
|
|
74
|
+
|
|
75
|
+
## SEC Rule 17a-4 / FINRA Rule 4511 (broker-dealer recordkeeping — for trading agents)
|
|
76
|
+
|
|
77
|
+
| Obligation | Coverage | How |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| Non-rewriteable records / audit-trail alternative | partial | Hash-chained tamper-evident audit; true WORM needs object-lock storage (roadmap) |
|
|
80
|
+
| Retention periods | partial | Durable store; configure long-term archival |
|
|
81
|
+
| Supervision of automated trading | partial | Action feed + kill + approvals |
|
|
82
|
+
|
|
83
|
+
## Generate live, evidence-backed reports
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
sentinel compliance --all # coverage summary (all frameworks)
|
|
87
|
+
sentinel compliance --framework eu_ai_act # full mapping + your audit evidence
|
|
88
|
+
sentinel export --format art12 # EU AI Act Art. 12 record-keeping report
|
|
89
|
+
```
|
|
90
|
+
Set `SENTINEL_SYSTEM_NAME` and `SENTINEL_PROVIDER` to stamp reports with your system identity.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Contributing to Sentinel
|
|
2
|
+
|
|
3
|
+
Thanks for looking! Sentinel is an early (alpha) open-source project — issues, ideas, and
|
|
4
|
+
PRs are all welcome.
|
|
5
|
+
|
|
6
|
+
## Dev setup
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
make install # venv + editable install with dev extras
|
|
10
|
+
make test # pytest
|
|
11
|
+
make lint # ruff
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Ground rules
|
|
15
|
+
|
|
16
|
+
- **Tests-first on security-critical code** (policy engine, audit integrity, kill switch).
|
|
17
|
+
Add a test with (or before) the change.
|
|
18
|
+
- Keep `ruff check src tests` clean and `pytest` green — CI enforces both (3.11–3.13).
|
|
19
|
+
- The audit log is **append-only and tamper-evident** — never add anything that mutates
|
|
20
|
+
past records or breaks the hash chain.
|
|
21
|
+
- Be honest in docs: compliance mappings are *indicative engineering aids, not legal advice*.
|
|
22
|
+
|
|
23
|
+
## Security issues
|
|
24
|
+
|
|
25
|
+
Report privately — see [SECURITY.md](SECURITY.md). Do not open a public issue for an
|
|
26
|
+
unfixed vulnerability.
|
|
27
|
+
|
|
28
|
+
## License
|
|
29
|
+
|
|
30
|
+
By contributing, you agree your contributions are licensed under Apache-2.0.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# DECISIONS.md — יומן החלטות Sentinel
|
|
2
|
+
|
|
3
|
+
פורמט: תאריך · החלטה · נימוק · סטטוס.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 2026-06-13 · Phase 0 — מתודולוגיית המחקר
|
|
8
|
+
**החלטה:** מחקר תחרותי דרך 4 זרמים מקבילים (runtime security / identity+payments / standards+OSS / market+regulation), כל אחד מחזיר digest ממוקד עם מקורות אמיתיים בלבד.
|
|
9
|
+
**נימוק:** כיסוי רחב במהירות + הפרדה בין איסוף-מודיעין (delegated) לבין הסינתזה האסטרטגית ודירוג ה-wedge (נשאר אצלי).
|
|
10
|
+
**סטטוס:** ✅ הושלם → `RESEARCH.md`.
|
|
11
|
+
|
|
12
|
+
## 2026-06-13 · ממצא מרכזי — ה-wedge המקורי תפוס
|
|
13
|
+
**החלטה:** לא להיכנס דרך "Runtime Control Plane / AI firewall" גנרי כ-positioning ראשי.
|
|
14
|
+
**נימוק:** 9 רכישות ב-12 חודשים, OSS חינמי (NeMo/Guardrails AI), bundling בענן, ו-CodeIntegrity (seed) בונה מוצר כמעט-זהה. תחרות מול חינם + מאות מיליוני $.
|
|
15
|
+
**סטטוס:** ✅ הוכרע במחקר.
|
|
16
|
+
|
|
17
|
+
## 2026-06-13 · בחירת wedge — **מאושר** ✅
|
|
18
|
+
**החלטה:** wedge = **"compliance-grade flight recorder + kill switch"** — interception שמפיק audit trail חתום וממופה-רגולציה. **מוצר אופקי**, beachhead ראשון = סוכנים פיננסיים/מסחר אוטונומיים (MeiroX-style), ואז התרחבות.
|
|
19
|
+
**נימוק:** השכבה הכי פחות צפופה, מגובה ב-deadline רגולטורי (EU AI Act Art. 12 — 2.8.2026), בת-ביצוע לבנאי יחיד, וזורעת את ה-Trust Graph דרך הדאטה. ראה `RESEARCH.md` §8.
|
|
20
|
+
**סטטוס:** ✅ **אושר ע"י Itamar (2026-06-13).** עוברים ל-PRD.
|
|
21
|
+
|
|
22
|
+
## 2026-06-13 · Phase 1 — PRD
|
|
23
|
+
**החלטה:** הפרדה חדה: PRD מגדיר *מה* (תרחישים, scope, DoD); *איך* מיירטים (proxy/SDK/middleware) נדחה במכוון ל-ARCHITECTURE (נקודת החלטה נפרדת).
|
|
24
|
+
**נימוק:** מנגנון ה-interception הוא ההחלטה הארכיטקטונית הכי קשה-להפוך — לא לקבע אותה ב-PRD לפני שמציגים trade-offs.
|
|
25
|
+
**סטטוס:** ✅ `PRD.md` נכתב.
|
|
26
|
+
|
|
27
|
+
## 2026-06-13 · Phase 2 — Stack ו-Interception — **מאושר** ✅
|
|
28
|
+
**החלטה:** Python 3.11+ · interception = **SDK wrapper** מאחורי `Interceptor` interface (MCP-proxy כ-adapter עתידי) · audit = **SQLite + hash-chain** · policy = **YAML** · API = **FastAPI** + dashboard מינימלי · בדיקות = **pytest**.
|
|
29
|
+
**נימוק:** ה-beachhead (סוכנים פיננסיים/MeiroX) משתמש ב-tools של קריאות ישירות, לא MCP — SDK wrapper מכסה אותם, framework-agnostic, ודטרמיניסטי ל-tests-first. עקרונות: default-deny, fail-closed, append-only. ראה `ARCHITECTURE.md`.
|
|
30
|
+
**סטטוס:** ✅ אושר ע"י Itamar. עוברים לבנייה (Phase 3).
|
|
31
|
+
|
|
32
|
+
## עקרונות אבטחה שנקבעו (מחייבים את כל הקוד)
|
|
33
|
+
- **Fail-closed:** חריגה בליבת ההכרעה → block, לא execute.
|
|
34
|
+
- **Default-deny:** אין כלל מתאים → block.
|
|
35
|
+
- **Tests-first** על policy / kill switch / audit-integrity (קוד קריטי).
|
|
36
|
+
- **Sentinel עצמו = משטח תקיפה** — threat model ב-`ARCHITECTURE.md` §6.
|
|
37
|
+
|
|
38
|
+
## 2026-06-13 · Phase 3 — שינוי כפוי: HTTP layer
|
|
39
|
+
**החלטה:** נבדק ש-FastAPI+uvicorn+pydantic מותקנים נקי על Python 3.14.3 → נשארנו עם FastAPI כמתוכנן (לא נפלנו ל-stdlib).
|
|
40
|
+
**נימוק:** הסיכון היה wheels חסרים ל-3.14; אומת בפועל לפני התחייבות.
|
|
41
|
+
**סטטוס:** ✅
|
|
42
|
+
|
|
43
|
+
## 2026-06-13 · Phase 4 — בדיקות, demo, אבטחה — הושלם
|
|
44
|
+
**החלטה:** 32 טסטים עוברים; E2E demo (5 תרחישים) עובד; tamper detection אומת חי; compliance export עובד; self-security check נקי (`SECURITY.md`).
|
|
45
|
+
**הערה כנה:** ה-dashboard אומת פונקציונלית (טסטים + curl חי), אבל ה-preview-MCP לא הצליח להריץ אותו כי ה-sandbox חוסם גישה ל-.venv — מגבלת סביבה, לא באג. רץ תקין תחת `sentinel serve`.
|
|
46
|
+
**סטטוס:** ✅ MVP הושלם.
|
|
47
|
+
|
|
48
|
+
## 2026-06-13 · Post-MVP — הכל חוץ מחיבור MeiroX (לבקשת Itamar)
|
|
49
|
+
**החלטה:** Itamar בחר לבצע את כל ההמשך **חוץ** מחיבור הבוט האמיתי — "רק בנינו את זה, אני לא סומך על זה ב-100%". החלטה נכונה: לא לשים שכבת בקרה לא-בדוקה לפני כסף אמיתי. תואם [[feedback_account_anxiety]].
|
|
50
|
+
**בוצע ב-3 workstreams:**
|
|
51
|
+
- **A (הקשחה):** auth לדאשבורד (Bearer token, `SENTINEL_API_TOKEN`), rate-limit מתמשך (SQLite), two-phase logging (intent+outcome, action_id), approval flow (HITL — park→approve→run-once).
|
|
52
|
+
- **B (MCP-proxy):** `MCPProxy` מעל `Sentinel.enforce` משותף (refactor) — אין נתיב bypass.
|
|
53
|
+
- **C (OSS):** Apache-2.0, OTel GenAI export (`gen_ai.*`), CI (3.11–3.13), classifiers, CHANGELOG.
|
|
54
|
+
**סטטוס:** ✅ 51 טסטים עוברים. חיבור MeiroX נדחה במכוון עד שיש אמון מוכח.
|
|
55
|
+
|
|
56
|
+
## 2026-06-13 · "תמשיך עד המטרה" — monitor mode, MCP server, OTel SDK, wheel
|
|
57
|
+
**החלטה:** להמשיך אוטונומית עד סגירת כל הסקופ הבר-בנייה (בלי MeiroX, בלי פרסום חיצוני שדורש הרשאות).
|
|
58
|
+
- **Monitor mode** (`mode="monitor"` / `SENTINEL_MODE=monitor`): observe-only — מתעד את ההכרעה-שהייתה אבל לא חוסם; ה-kill switch עדיין אוכף. גשר האמון: אפשר "shadow" על סוכן אמיתי בלי סיכון — בלי לגעת ב-MeiroX החי.
|
|
59
|
+
- **SentinelMCPServer**: שרת MCP אמיתי (חבילת `mcp`, optional extra) שחושף tools עם אכיפה מובנית; `handle_call` טהור ונבדק בלי תלות ב-mcp.
|
|
60
|
+
- **OTel SDK exporter** (`record_spans`, extra `otel`): פולט spans אמיתיים, לא רק JSON.
|
|
61
|
+
- **wheel + sdist** נבנו ואומתו בהתקנה ל-venv נקי → `pip install sentinel` עובד.
|
|
62
|
+
**סטטוס:** ✅ 58 טסטים. נשאר רק לא-קוד (design partner אמיתי) + פרסום PyPI (דורש חשבון — לא מבוצע אוטומטית).
|
|
63
|
+
|
|
64
|
+
## 2026-06-13 · Trust hardening (תשובה ל"מה עוד נשאר")
|
|
65
|
+
**החלטה:** לסגור 3 פערים אמיתיים שמעלים אמינות (לא gold-plating): (1) SQLite **WAL + busy_timeout** דרך `db.py` משותף — מונע "database is locked" כשהדאשבורד קורא בזמן שסוכן כותב; (2) `SENTINEL_API_PROTECT_READS` לנעילת קריאות ה-audit הרגישות מאחורי token; (3) **ruff** lint gate ב-CI.
|
|
66
|
+
**הערה כנה:** בקומיט הראשון של הסבב טענתי בטעות "lint clean" — ruff מצא 5 (B008/B904). תוקן בקומיט עוקב; עכשיו נקי באמת (exit 0).
|
|
67
|
+
**סטטוס:** ✅ 61 טסטים, ruff נקי. **מכאן והלאה עוד קוד = תשואה פוחתת בלי משתמש אמיתי** — ההמלצה לעצור את הגולת-זהב ולתקֵף עם monitor-mode dogfood.
|
|
68
|
+
|
|
69
|
+
## 2026-06-13 · "תעשה את שאר הדברים" (חוץ מ-MeiroX) — סבב אחרון
|
|
70
|
+
**החלטה:** Itamar ביקש מפורשות: לא לחבר את הבוט, אבל לבנות את כל השאר. בוצע:
|
|
71
|
+
- **detector חזק** — full trifecta (untrusted-content tracking), dangerous-arg (cmd/SQL/path/URL), PII.
|
|
72
|
+
- **Retention** — approval TTL + purge, rate-limit purge, `sentinel gc`. (ה-audit לא נמחק לעולם — רשומת compliance; מחיקה תשבור את השרשרת.)
|
|
73
|
+
- **Upstream MCP MITM אמיתי** — `AsyncMCPProxy` מעל `mcp.ClientSession` חי (refactor ל-`aenforce` async; ה-sync לא השתנה).
|
|
74
|
+
- **EU AI Act Art.12 report** רציני (`export --format art12`).
|
|
75
|
+
- **release ל-PyPI** (Trusted Publishing) + PUBLISHING.md — מוכן, **לא בוצע** (דורש חשבון PyPI; פעולה כלפי-חוץ).
|
|
76
|
+
**סטטוס:** ✅ 71 טסטים, ruff נקי. נשאר: פרסום (שלך), design partner (אנושי), MeiroX (הוחרג מפורשות).
|
|
77
|
+
|
|
78
|
+
## 2026-06-13 · Pre-launch hardening + שכבת compliance רב-מסגרתית
|
|
79
|
+
**החלטה:** לפני השקה — (א) תיקון ממצאי pre-launch: XSS בדאשבורד (escaping), disclaimers (alpha/not-legal-advice ב-README + Art.12), retry על כתיבת audit מקבילית, מדיניות disclosure. (ב) "כל מה שחסר לפי החוקים ל-AI": `frameworks.py` — קטלוג של 6 רגולציות אמיתיות (EU AI Act, GDPR, NIST AI RMF, ISO 42001, Colorado AI Act, SEC/FINRA) עם מיפוי **כֵּן** full/partial/none, `sentinel compliance` CLI, ו-COMPLIANCE.md.
|
|
80
|
+
**כנות:** מתוך 27 חובות — רק 1 full, 20 partial, 6 none. Sentinel = שכבת evidence/control, *לא* "הופך אותך ל-compliant". הכל מסומן indicative/not-legal-advice.
|
|
81
|
+
**סטטוס:** ✅ 78 טסטים, ruff נקי. נשאר רק: מילוי איש קשר אבטחה, שם PyPI, push ל-CI — ואז השקה.
|
|
82
|
+
|
|
83
|
+
## 2026-06-14 · הכללה: לכל סוכן AI, לא רק MeiroX/מסחר
|
|
84
|
+
**החלטה:** Itamar ביקש שזה יהיה לכל סוכן שאנשים בונים עם AI, לא רק הבוט שלו. בוצע: `policies/starter.yaml` גנרי (read/write/destructive/payments/egress/code-exec), `examples/generic_agent.py` כ-demo הראשי (`sentinel demo` מצביע עליו), `Sentinel.wrap_all()` לעטיפת toolset שלם, ו-`INTEGRATIONS.md` (plain/LangChain/OpenAI/CrewAI/LlamaIndex/MCP). default policy ב-Config שונה ל-starter.yaml; trading_agent נשאר כדוגמה vertical (מצמיד example.yaml). README/DEMO/PyPI שם = guardledger.
|
|
85
|
+
**סטטוס:** ✅ 79 טסטים, ruff נקי. שני ה-demos עובדים (גנרי + מסחר).
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# DEMO.md — running Sentinel end-to-end
|
|
2
|
+
|
|
3
|
+
## Setup (once)
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
cd sentinel
|
|
7
|
+
python3 -m venv .venv && source .venv/bin/activate
|
|
8
|
+
pip install -e ".[dev]"
|
|
9
|
+
cp .env.example .env # optional; sensible defaults work without it
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## 1. The end-to-end demo (the headline)
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
sentinel demo # a GENERIC agent; vertical example: python examples/trading_agent.py
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
A generic AI agent runs **through** Sentinel (the trading version shows the same controls
|
|
19
|
+
for a financial agent). You'll see the same scenarios either way:
|
|
20
|
+
|
|
21
|
+
| Scenario | Tool call | What Sentinel does |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| Normal trading | `get_quote`, `get_balance`, `place_order($100)` | **allowed** + logged |
|
|
24
|
+
| Oversized order | `place_order(TSLA, $5000)` | **blocked** — policy needs approval above $500 |
|
|
25
|
+
| Suspicious (trifecta) | `read_api_secret()` then `http_post(...)` | **allowed but FLAGGED** — secret-then-egress |
|
|
26
|
+
| Suspicious (injection) | `get_news("…ignore previous instructions…")` | **allowed but FLAGGED** — injection signature |
|
|
27
|
+
| Destructive | `delete_account()` | **blocked** — forbidden by policy |
|
|
28
|
+
| Kill switch | `get_quote()` after `kill` | **blocked** — agent stopped |
|
|
29
|
+
|
|
30
|
+
It ends by printing the audit summary and confirming the hash chain is intact.
|
|
31
|
+
|
|
32
|
+
## 2. Prove the audit is tamper-evident
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
sentinel verify # -> ok: true
|
|
36
|
+
|
|
37
|
+
# now tamper with the SQLite log directly (simulating an attacker hiding a trade)
|
|
38
|
+
python - <<'PY'
|
|
39
|
+
import sqlite3
|
|
40
|
+
c = sqlite3.connect("data/sentinel.db")
|
|
41
|
+
c.execute("UPDATE audit SET args=? WHERE seq=4", ('{"amount": 1}',))
|
|
42
|
+
c.commit(); c.close()
|
|
43
|
+
PY
|
|
44
|
+
|
|
45
|
+
sentinel verify # -> ok: false, first_bad_seq: 4 (exit code 1)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This is the wedge: you cannot quietly rewrite what the agent did.
|
|
49
|
+
|
|
50
|
+
## 3. Export a compliance report
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
sentinel export --out report.json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Every record carries an integrity status plus `eu_ai_act_art12` and OWASP Agentic
|
|
57
|
+
tags — hand it to a compliance reviewer or auditor.
|
|
58
|
+
|
|
59
|
+
## 4. The dashboard (live control plane)
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
sentinel serve # -> http://127.0.0.1:8787
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The dashboard polls the same audit DB, so:
|
|
66
|
+
|
|
67
|
+
- **watch** actions land live with their decision, status, flags, and matched rule;
|
|
68
|
+
- click **VERIFY CHAIN** to re-check integrity on demand;
|
|
69
|
+
- click **KILL ALL** — then in another terminal run `sentinel demo` again: the agent
|
|
70
|
+
is **blocked on its next call**, because the kill state is shared through SQLite.
|
|
71
|
+
This is a real cross-process kill switch, not a toy.
|
|
72
|
+
- edit the **policy** YAML and save (validated before it's written).
|
|
73
|
+
|
|
74
|
+
> Note: the live dashboard couldn't be auto-screenshotted here because the preview
|
|
75
|
+
> sandbox blocks the project's `.venv`; it runs fine under plain `sentinel serve`,
|
|
76
|
+
> and its endpoints are covered by `tests/test_api.py`.
|
|
77
|
+
|
|
78
|
+
## 5. Measure the overhead
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
python examples/benchmark.py # ~0.4 ms/call on a dev laptop (incl. 2 durable audit writes)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 6. See the compliance mapping
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
sentinel compliance --all # full/partial/none across 6 regulations
|
|
88
|
+
sentinel compliance --framework eu_ai_act # mapping + your audit evidence
|
|
89
|
+
```
|
|
90
|
+
|