diff --git a/src/content/docs/sipher/sentinel/audit-log.mdx b/src/content/docs/sipher/sentinel/audit-log.mdx index 5307240..a89f338 100644 --- a/src/content/docs/sipher/sentinel/audit-log.mdx +++ b/src/content/docs/sipher/sentinel/audit-log.mdx @@ -6,7 +6,7 @@ description: SQLite audit-log schema for SENTINEL — four tables (blacklist, ri import { Aside } from '@astrojs/starlight/components' diff --git a/src/content/docs/sipher/sentinel/config.mdx b/src/content/docs/sipher/sentinel/config.mdx index c4106b6..9ce5d83 100644 --- a/src/content/docs/sipher/sentinel/config.mdx +++ b/src/content/docs/sipher/sentinel/config.mdx @@ -6,7 +6,7 @@ description: 15 environment variables that tune SENTINEL — modes, scanner inte import { Aside } from '@astrojs/starlight/components' All SENTINEL behavior is tuned via environment variables. Read at startup by `getSentinelConfig` in [`packages/agent/src/sentinel/config.ts`](https://github.com/sip-protocol/sipher/blob/main/packages/agent/src/sentinel/config.ts). Defaults shown below are verified against that file as of the `Last verified` date. @@ -25,7 +25,7 @@ Boolean env vars use string parsing and polarity matters: | Var | Type | Default | Valid values | What it tunes | |---|---|---|---|---| -| `SENTINEL_MODE` | enum | `yolo` | `yolo` \| `advisory` \| `off` | Whether SENTINEL blocks (`block` decisions only in `yolo`), also pauses for `flag` in `advisory`, or skips all assessments entirely in `off`. See [README operating modes](./README.md#operating-modes). | +| `SENTINEL_MODE` | enum | `yolo` | `yolo` \| `advisory` \| `off` | How SENTINEL acts on its verdict. A `block` verdict rejects the action in **all** modes. `yolo` auto-executes non-blocked (`warn`/`allow`) actions and lets SENTINEL run its own fund-moving tools; `advisory` never moves funds — it pauses flagged actions for human review and only analyzes/alerts; `off` skips assessment entirely. See [operating modes](/sipher/sentinel/overview/#operating-modes). | | `SENTINEL_PREFLIGHT_SCOPE` | enum | `fund-actions` | `fund-actions` \| `critical-only` \| `never` | Which agent tools trigger a pre-execution risk check. `fund-actions` covers all fund-moving tools; `critical-only` restricts to the highest-risk subset; `never` disables preflight entirely. | | `SENTINEL_PREFLIGHT_SKIP_AMOUNT` | number (SOL) | `0.1` | any non-negative | Skip preflight when the action amount is below this threshold. Reduces LLM calls for small routine transfers. | diff --git a/src/content/docs/sipher/sentinel/overview.mdx b/src/content/docs/sipher/sentinel/overview.mdx index 8cedd87..db99f23 100644 --- a/src/content/docs/sipher/sentinel/overview.mdx +++ b/src/content/docs/sipher/sentinel/overview.mdx @@ -6,14 +6,14 @@ description: Integrator-facing reference for SENTINEL — Sipher's LLM-backed se import { Aside } from '@astrojs/starlight/components' SENTINEL is Sipher's LLM-backed security analyst. Think of it as the security department of an office building: it watches every fund-moving action, flags suspicious wallets, can pause execution for human review, and logs every decision for audit. This folder is the integrator-facing reference for SENTINEL's external surface. ## Sub-references -- [REST API](/sipher/sentinel/rest-api/) — 10 endpoints under `/api/sentinel` +- [REST API](/sipher/sentinel/rest-api/) — 11 endpoints under `/api/sentinel` - [Agent Tools](/sipher/sentinel/tools/) — 14 LLM tools + `assessRisk` - [Configuration](/sipher/sentinel/config/) — 15 environment variables - [Audit Log Schema](/sipher/sentinel/audit-log/) — SQLite tables + decision record format diff --git a/src/content/docs/sipher/sentinel/rest-api.mdx b/src/content/docs/sipher/sentinel/rest-api.mdx index 37fb77f..427d4d8 100644 --- a/src/content/docs/sipher/sentinel/rest-api.mdx +++ b/src/content/docs/sipher/sentinel/rest-api.mdx @@ -1,12 +1,12 @@ --- title: SENTINEL REST API -description: All 10 SENTINEL endpoints under /api/sentinel — public + admin — with auth, error envelope, request/response shapes, and verified curl examples. +description: All 11 SENTINEL endpoints under /api/sentinel — public + admin — with auth, error envelope, request/response shapes, and verified curl examples. --- import { Aside } from '@astrojs/starlight/components' All endpoints live under `/api/sentinel`. JWT-based auth via `Authorization: Bearer `. @@ -137,7 +137,7 @@ curl -X POST http://localhost:5006/api/sentinel/assess \ ``` :::note -The captured response shows an empty array — this is a fresh local DB with no blacklist entries. In production the array contains objects with fields: `id`, `address`, `reason`, `severity`, `added_by`, `added_at`, `expires_at`, `source_event_id`. Schema detail in [`docs/sentinel/audit-log.md`](/sipher/sentinel/audit-log/). +The captured response shows an empty array — this is a fresh local DB with no blacklist entries. In production the array contains objects with fields: `id`, `address`, `reason`, `severity`, `added_by`, `added_at`, `expires_at`, `source_event_id`. Schema detail in the [audit log](/sipher/sentinel/audit-log/). ::: **Example:** @@ -160,7 +160,7 @@ curl -H "Authorization: Bearer $JWT" \ | Param | Type | Default | Description | |-------|------|---------|-------------| | `wallet` | string | — | Filter by originating wallet address | -| `status` | string | — | Filter by action status (e.g., `pending`, `cancelled`, `approved`) | +| `status` | string | — | Filter by action status — lifecycle is `pending` → `executing` → `executed` \| `cancelled` | **Response 200:** @@ -171,7 +171,7 @@ curl -H "Authorization: Bearer $JWT" \ ``` :::note -The captured response shows an empty array — fresh local DB. In production the array contains objects with fields: `id`, `tool`, `args`, `wallet`, `status`, `reason`, `created_at`, `resolved_at`. Schema detail in [`docs/sentinel/audit-log.md`](/sipher/sentinel/audit-log/). +The captured response shows an empty array — fresh local DB. In production the array contains objects with fields: `id`, `tool`, `args`, `wallet`, `status`, `reason`, `created_at`, `resolved_at`. Schema detail in the [audit log](/sipher/sentinel/audit-log/). ::: **Example:** @@ -343,7 +343,7 @@ Returned when the action ID exists and was cancelled. { "error": { "code": "NOT_FOUND", "message": "pending action not found or already resolved" } } ``` -Returned when the action ID does not exist or is already settled. (Behavior changed in this PR — previously this path returned `200 + {success: false}`.) +Returned when the action ID does not exist or is already settled. A missing or already-resolved action returns this `404` envelope (not `200 + {success: false}`). **Example:** @@ -378,7 +378,7 @@ curl -X POST http://localhost:5006/api/sentinel/circuit-breaker/01KQP25BM8RVZJ92 ``` :::note -The captured response shows an empty array — fresh local DB. In production each decision object contains: `id` (ULID), `action`, `wallet`, `risk`, `score`, `recommendation`, `reasons` (JSON array), `source`, `cost_usd`, `duration_ms`, `created_at`. Schema detail in [`docs/sentinel/audit-log.md`](/sipher/sentinel/audit-log/). +The captured response shows an empty array — fresh local DB. In production each decision object contains: `id` (ULID), `action`, `wallet`, `risk`, `score`, `recommendation`, `reasons` (JSON array), `source`, `cost_usd`, `duration_ms`, `created_at`. Schema detail in the [audit log](/sipher/sentinel/audit-log/). ::: **Example:** @@ -390,6 +390,40 @@ curl -H "Authorization: Bearer $JWT" \ --- +### GET /api/sentinel/config + +**Auth:** `verifyJwt + requireOwner` + +**Description:** Return the current SENTINEL configuration snapshot — operating `mode`, preflight scope/thresholds, `blacklistAutonomy`, rate limits, scan intervals, `autoRefundThreshold`, `model`, `dailyBudgetUsd`, accrued `dailyCostUsd`, `blockOnError`, and the `fundMovingTools` list. See [Configuration](/sipher/sentinel/config/) for what each field controls. + +**Response 200:** + +```json +{ + "mode": "advisory", + "preflightScope": "fund-moving", + "blacklistAutonomy": true, + "model": "openrouter:anthropic/claude-sonnet-4.6", + "dailyBudgetUsd": 10, + "dailyCostUsd": 0, + "blockOnError": false, + "fundMovingTools": ["executeRefund", "addToBlacklist"] +} +``` + +:::note +Response includes the full config (mode, preflight scope/skip-amount, large-transfer threshold, threat-check flag, cancel window, per-hour rate limits, scan intervals, auto-refund threshold, model, daily budget/cost, block-on-error). The example is abbreviated. +::: + +**Example:** + +```bash +curl -H "Authorization: Bearer $JWT" \ + http://localhost:5006/api/sentinel/config +``` + +--- + ### POST /api/sentinel/promise-gate/:flagId/resolve **Auth:** `verifyJwt + requireOwner` diff --git a/src/content/docs/sipher/sentinel/tools.mdx b/src/content/docs/sipher/sentinel/tools.mdx index a6d205c..c7ec18e 100644 --- a/src/content/docs/sipher/sentinel/tools.mdx +++ b/src/content/docs/sipher/sentinel/tools.mdx @@ -6,7 +6,7 @@ description: 14 SENTINEL tools (7 read + 7 action) plus the assessRisk tool — import { Aside } from '@astrojs/starlight/components' Tools that SENTINEL's LLM agent (`SentinelCore`) calls during risk assessment, plus the `assessRisk` tool exposed to the conversational SIPHER agent. @@ -14,7 +14,7 @@ Tools that SENTINEL's LLM agent (`SentinelCore`) calls during risk assessment, p Tools fall into two categories: - **Read tools (7):** Pure RPC/DB/cache reads, no on-chain or DB mutations. Safe in any `SENTINEL_MODE`. -- **Action tools (7):** Mutate state (DB writes, on-chain transactions, alerts to user). Subject to autonomy thresholds — see [config.md](/sipher/sentinel/config/#autonomy). +- **Action tools (7):** Mutate state (DB writes, on-chain transactions, alerts to user). Subject to autonomy thresholds — see [Configuration](/sipher/sentinel/config/#autonomy). Plus `assessRisk`, which is _not_ a SentinelCore tool — it is the SIPHER conversational tool that invokes SENTINEL's `/assess` flow. @@ -234,7 +234,7 @@ Action tools mutate state. SentinelCore's system prompt and `SentinelAdapter` en - Calls `insertBlacklist({ ...params, addedBy: 'sentinel' })` — inserts into `sentinel_blacklist`. - Emits `sentinel:blacklist-added` on `guardianBus`. -**Autonomy:** Gated by `SENTINEL_BLACKLIST_AUTONOMY` (default `false` — off unless explicitly enabled) and `SENTINEL_RATE_LIMIT_BLACKLIST_PER_HOUR`. +**Autonomy:** Gated by `SENTINEL_BLACKLIST_AUTONOMY` (default `true` — on unless `SENTINEL_BLACKLIST_AUTONOMY=false`) and `SENTINEL_RATE_LIMIT_BLACKLIST_PER_HOUR`. **When fired:** When SENTINEL identifies a high-confidence threat — e.g., mixer interaction, known scam address, or repeated `block` decisions — and `blacklistAutonomy` is enabled. In `advisory` mode the system prompt's principle _"Never take fund-moving actions in advisory mode"_ applies; the LLM should call `alertUser` instead.