SentinelAI β Architecture
AI-Powered Endpoint DLP for AI Tools Status: MVP Β· Confidential
1. MVP Focus
Real-time Data Loss Prevention (DLP) for web-based AI tools ("Copilots"): ChatGPT, Claude, Gemini, Microsoft Copilot, and M365 Copilot (web). The MVP intercepts prompts before they are sent to the AI provider, classifies the content locally, scores risk, and enforces an action (allow / warn / block) β with all sensitive analysis happening on the endpoint.
Event Collection decision (ADR-001): the MVP collects and enforces at the browser via a managed MV3 browser extension, not via TLS/API interception. See ADR below.
2. High-Level Architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ENDPOINT (Windows) β
β β
β βββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββ β
β β Browser Extension (MV3) β β Local Agent (FastAPI) β β
β β β inject.js (page ctx) β β β Classifier (rules) β β
β β monkeypatch fetch/XHR βββββββΆβ β Risk Engine (0β100) β β
β β β content.js (bridge) β HTTP β β Local LLM (Ollama) β β
β β β background (SW) ββββββββ β Decision + reasons β β
β β β coaching popup UI β allowβ β β
β βββββββββββββββββββββββββββββ warn βββββββββββββ¬βββββββββββββββ β
β block β telemetry β
ββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββ
β HTTPS
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CENTRAL PLATFORM β serverless, in your AWS (SaaS) β
β Lambda (FastAPI+Mangum, Function URL) βββΊ DynamoDB β
β β² β
β Static Next.js dashboard on S3 + CloudFront βββ (calls the API)β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Deployment decision (ADR-002): the central platform is serverless β AWS Lambda + DynamoDB + static S3/CloudFront, deployed with AWS SAM. Chosen for low friction and zero-idle cost over containers/RDS. See ADR-002 below.
LLM decision (ADR-003): the MVP ships rules-only (no LLM) for low-friction rollout. The local endpoint LLM (Ollama) is a Phase-2 enhancement,
SENTINEL_LLM=1. The cloud never runs inference. See ADR-003 below.
Design principle β thin sensor, local brain: the extension is a thin sensor + enforcer. All classification, LLM reasoning, and policy live in the local agent, so the same brain also serves future collectors (clipboard, file, USB, IDE) without duplicating logic.
3. Components
3.1 Browser Extension (extension/)
| File | Role |
|---|---|
manifest.json |
MV3 manifest; host permissions for AI sites + 127.0.0.1 agent |
src/inject.js |
Runs in page context; monkeypatches window.fetch and XMLHttpRequest; pauses matching outbound requests until a decision returns |
src/content.js |
Isolated content script; bridges page β background; renders coaching/block overlay |
src/background.js |
Service worker; calls the local agent, caches decisions, holds config |
src/popup.html/js |
Status + recent-decision UI |
Interception flow:
inject.jswrapsfetch/XHR. When a request targets a known AI completion endpoint, it extracts the prompt text from the body.- It
postMessages the candidate tocontent.js, then awaits a decision (the wrapped fetch returns a pending promise). content.jsβbackground.jsβPOST http://127.0.0.1:8787/classify.- Decision returns:
allowresumes the original request;warnshows a coaching overlay and resumes on user acknowledgement;blockrejects the request and shows a block overlay.
Why the fetch hook (not just DOM hooks): patching fetch/XHR captures the actual outbound
payload regardless of DOM redesigns, and lets us block by simply not forwarding the request.
Keydown/send-button and paste hooks are secondary UX signals.
Deployment: force-installed via browser enterprise policy
(ExtensionInstallForcelist for Chrome/Edge) so users cannot remove it.
3.2 Local Agent (agent/)
FastAPI service on 127.0.0.1:8787.
| Module | Role |
|---|---|
app/main.py |
/classify, /health; CORS for chrome-extension:// |
app/classifier.py |
Regex/rules: PII, secrets/API keys, source code, financial, contract |
app/risk.py |
Combines sensitivity + destination + (optional) LLM into a 0β100 score + decision |
app/llm.py |
Optional Ollama call (Phi-4 Mini / Qwen3 4B); safe fallback when unavailable |
app/telemetry.py |
Best-effort async forward of events to the central backend |
Latency budget: rules run synchronously (<5 ms). The LLM call is optional and used to refine borderline scores; if Ollama is unavailable or slow, the agent falls back to rules-only so enforcement never stalls.
Privacy: only a hash + truncated snippet + metadata are forwarded to the central platform by default. Full prompt capture is a policy-gated option (see Clarification Query #8).
3.3 Central Backend (backend/)
FastAPI on AWS Lambda (via Mangum) behind a Function URL; DynamoDB store. Endpoints:
POST /api/eventsβ ingest an endpoint decision eventGET /api/eventsβ event feed (dashboard), filterable by org/app/decision/categoryGET /api/statsβ 7-day aggregates for overview tiles
DynamoDB single-table design (backend/app/repository.py): pk = ORG#<org_id>,
sk = EVENT#<ts>#<id> β one partition per tenant, sorted by time. Stats aggregate the tenant's
recent partition in the Lambda (fine at MVP volumes).
3.4 Dashboard (dashboard/)
Next.js static export (output: "export") hosted on S3 + CloudFront. It calls the backend
Function URL client-side (NEXT_PUBLIC_API_URL, baked at build). No SSR server to run. MVP views:
Overview stats, Event feed, Shadow-AI usage.
4. Data Model (MVP)
DynamoDB item (single table, per-tenant partition):
pk "ORG#<org_id>" -- tenant partition
sk "EVENT#<ts>#<id>" -- time-ordered within tenant
id uuid
org_id text -- tenant key (MVP: "default")
ts iso8601
user text -- endpoint user / SSO identity
host text -- device hostname
app text -- "chatgpt" | "claude" | "gemini" | "copilot" | "m365-copilot"
url text
category text -- pii | secret | source_code | financial | contract | none
risk_score number -- 0β100
decision text -- allow | warn | block
reasons list -- matched rules / (Phase 2) LLM rationale
snippet_hash text -- sha256 of matched content
snippet text -- truncated + policy-gated
5. Risk & Enforcement Bands
| Decision | Score | Action |
|---|---|---|
| allow | 0β25 | proceed, log only |
| warn | 26β50 | coaching overlay, proceed on ack |
| block | 51β80 | reject request |
| block + alert SOC | 81β100 | reject + high-priority central alert |
Bands are configurable; defaults above are indicative (Clarification Query #6).
6. Tech Stack
| Layer | Tech |
|---|---|
| Extension | MV3, vanilla JS (no build step for MVP) |
| Local Agent | Python, FastAPI, Uvicorn; Ollama runtime (Phase 2) |
| Models | Phi-4 Mini / Qwen3 4B (local, Phase 2) |
| Backend | Python, FastAPI + Mangum on AWS Lambda |
| Database | DynamoDB |
| Dashboard | Next.js static export (S3 + CloudFront) |
| IaC / deploy | AWS SAM (template.yaml) |
| CI/CD | GitHub Actions + OIDC (CI β staging β prod) |
7. Environments & CI/CD
| Env | Trigger | Notes |
|---|---|---|
| CI | every PR & push | lint + test agent/backend, build extension zip, next build |
| Staging | push to main |
build & push images, deploy to staging (GitHub Environment: staging) |
| Production | GitHub Release / manual dispatch | requires approval (GitHub Environment: production) |
Target: SaaS in your AWS account (Clarification #9 resolved). Deploy is sam deploy +
aws s3 sync; auth is GitHub OIDC (no static keys). One-time bootstrap: sam deploy --guided
locally (creates the OIDC role), then set repo vars AWS_DEPLOY_ROLE_ARN / AWS_REGION.
Production is a separate CloudFormation stack (sentinelai-production) gated by the production
GitHub Environment's required reviewers.
8. ADR-001 β Browser extension over API/TLS interception
Context: the MVP must do real-time DLP for web AI tools and block before send.
Options considered:
- Browser extension (MV3) β hook
fetch/XHRin page context. - Local TLS-inspecting proxy (MITM) β intercept HTTPS to provider APIs.
- OS/UI Automation hooks β read app windows via Windows UIA.
Decision: Option 1 for the MVP.
Rationale:
- Sees prompt content decrypted, pre-send β no root CA install, no TLS interception.
- Cert pinning in desktop AI apps breaks MITM (Option 2); the extension avoids this entirely.
- One integration surface (the web UIs) covers all major web AI tools; no per-provider API schema reverse-engineering to maintain.
- Genuine real-time blocking by withholding the request.
- Enterprise-deployable and tamper-resistant via browser MDM policy.
Consequences / limits (tracked in backlog):
- Covers web AI tools only. IDE Copilot (VS Code/JetBrains) and Office/desktop Copilots are separate surfaces β Phase 2.
- Requires a managed browser; usage in an unmanaged browser is out of scope for MVP.
ADR-002 β Serverless (SAM) over containers/RDS
Context: the central platform must be low-friction and cheap at idle for the MVP SaaS.
Decision: AWS Lambda (FastAPI+Mangum, Function URL) + DynamoDB + static S3/CloudFront, deployed with AWS SAM. An earlier App Runner + RDS + Terraform draft was rejected as too heavy.
Rationale: zero-idle cost, no VPC/cluster/DB server to operate, one sam deploy, matches the
team's serverless pattern. Consequence: DynamoDB access patterns (not SQL) β stats aggregate in
the Lambda; revisit with a GSI or counters if event volume grows large.
ADR-003 β Rules-only MVP; LLM is Phase 2
Decision: ship the rules/regex classifier alone for the MVP. Rationale: a local per-endpoint
LLM (Ollama + 4B model) means multi-GB installs and hardware requirements on every machine β the
opposite of low-friction. Rules already catch secrets/PII/source/financial/contract with zero
install. Consequence: contextual "is this proprietary?" judgment waits for Phase 2
(SENTINEL_LLM=1); the code path exists in agent/app/llm.py, off by default.
9. Out of Scope for MVP (see BACKLOG.md)
Clipboard/file/USB collectors Β· IDE Copilot Β· Office/desktop Copilots Β· attachment/file-upload DLP Β· local LLM refinement Β· SIEM integration Β· behavioral baselines Β· full-payload capture.