Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions 402sentinel/catalog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"schemaVersion": 1,
"slug": "402sentinel",
"provider": "402Sentinel",
"providerUrl": "https://402sentinel.com",
"logo": null,
"demo": {
"title": "402sentinel-x402.ts",
"language": "typescript",
"code": "import { x402Client, x402HTTPClient } from \"@x402/core/client\";\nimport { encodePaymentSignatureHeader } from \"@x402/core/http\";\nimport { registerExactEvmScheme } from \"@x402/evm/exact/client\";\nimport { privateKeyToAccount } from \"viem/accounts\";\n\nconst signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);\nconst client = new x402Client();\nregisterExactEvmScheme(client, { signer });\nconst http = new x402HTTPClient(client);\n\n// Standard x402: 402 -> decode PAYMENT-REQUIRED -> sign -> retry with PAYMENT-SIGNATURE.\n// (Bankr agents can use Bankr wallet signing instead -- see setup.)\nasync function pay(url: string, init: RequestInit = {}) {\n let res = await fetch(url, init);\n if (res.status === 402) {\n const challenge = JSON.parse(Buffer.from(res.headers.get(\"PAYMENT-REQUIRED\")!, \"base64\").toString());\n const sig = encodePaymentSignatureHeader(await http.createPaymentPayload(challenge));\n res = await fetch(url, { ...init, headers: { ...init.headers, \"PAYMENT-SIGNATURE\": sig } });\n }\n return res.json();\n}\n\nconst BASE_URL = \"https://402sentinel.com\";\nconst seller = \"0xSELLER_PAYTO\"; // the x402 counterparty you are about to pay\nconst post = (b: object) => ({ method: \"POST\", headers: { \"content-type\": \"application/json\" }, body: JSON.stringify(b) });\n\nconst free = await (await fetch(`${BASE_URL}/api/assess/preview?payto=${seller}`)).json(); // FREE -- confirm the gate\nconst assess = await pay(`${BASE_URL}/api/assess`, post({ target: { payto_address: seller }, payment_context: { amount: \"0.50\", asset: \"USDC\" } })); // ~$0.002\nconst fw = await pay(`${BASE_URL}/api/firewall`, post({ agent_id: signer.address, payment: { payto_address: seller, amount: \"0.50\", resource_url: \"https://seller.example/api\" }, context: { source: \"web_content\", untrusted_text: \"<page/tool output you acted on>\", intended: { payto: seller, max_amount: \"0.50\" } } })); // ~$0.002"
},
"setup": [
"No signup and no API key — every paid endpoint speaks x402 directly.",
"Pay with any standard x402 client: the 402 challenge offers Base (eip155:8453) AND Solana — pick either, asset is USDC.",
"Prefer Bankr wallet signing (`/agent/sign`) when available — set `BANKR_API_KEY` (Agent API + signing enabled).",
"Otherwise set `EVM_PRIVATE_KEY` (a USDC-funded Base wallet) and install `@x402/core` + `@x402/evm` + `viem`.",
"Use your payer wallet address as `agent_id` so the buyer-side firewall is stateful per agent.",
"Discover zero-config: GET https://402sentinel.com/.well-known/x402 , /openapi.json , /llms.txt"
],
"install": {
"type": "bankr",
"repoPath": "402sentinel",
"command": "install the 402sentinel skill from https://github.com/BankrBot/skills/tree/main/402sentinel"
}
}
40 changes: 40 additions & 0 deletions 402sentinel/references/api-reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# 402Sentinel API Reference

Base URL `https://402sentinel.com`. Pre-payment counterparty risk + compliance gate. Prices are USDC per call. Most endpoints are POST with a JSON body. Canonical machine spec: `/openapi.json`. Scores are probabilistic estimates from limited public on-chain data + heuristics — informational, NOT advice, NOT an endorsement or accusation.

## Seller risk
| Endpoint | Price | Body | Returns |
|---|---|---|---|
| `POST /api/assess` | $0.002 | `{ target:{ payto_address }, payment_context?:{ amount, asset }, policy?:{ block_at_score, review_at_score, min_confidence } }` | `risk_score` (0-100), `decision` (allow/review/block), `confidence`, `coverage` (incl. `network`), per-dimension signals, `key_factors` (the signals that drove the score), `recommended_policy`, `assessment_id`. `payto_address` = 0x EVM (Base) OR base58 Solana. OFAC covers EVM lists (stated honestly for Solana). |
| `POST /api/assess/deep` | $0.02 | same as `/api/assess` | same shape; scans more on-chain settlement history → higher confidence. |
| `POST /api/policy` | $0.002 | `{ target:{ payto_address }, payment_context? }` | allow/limit/deny + wallet-ready policy: `max_payment_usdc`, `daily_cap_usdc`, `add_to_denylist`, `require_human_approval`. |

## Buyer-side payment firewall
| Endpoint | Price | Body | Returns |
|---|---|---|---|
| `POST /api/firewall` | $0.002 | `{ agent_id, payment:{payto_address,amount,resource_url}, context?:{source,untrusted_text,intended:{payto,max_amount}}, policy? }` | allow/hold/block + signals: `routing_anomaly`, `velocity_anomaly`, `amount_anomaly`, `provenance_flag`, `counterparty_risk`, **`injection_destination`** (pass the page/tool output as `untrusted_text`; if the payTo appears in it → hard block — catches prompt-injection payments), **`intent_mismatch`** (pass `intended`; any deviation → hard block), `new_counterparty_burst`, `recurring_flagged`. Stateful per `agent_id`. |
| `POST /api/firewall/record` | FREE | seed routing history | — |
| `POST /api/firewall/outcome` | FREE | `{assessment_id, outcome, owner_sig, owner_ts}` | trains per-signal precision. |

ANTI-POISON: to build TRUSTED history / train via outcomes, sign `402sentinel:<action>:<agent_id-lowercased>:<unix_ts>` with the agent_id wallet and pass `owner_sig` + `owner_ts` (action = `firewall` | `firewall_record` | `firewall_outcome`). Unsigned writes are accepted but never establish trusted history (so nobody can poison another agent's baseline).

## Compliance + tokenized-RWA
| Endpoint | Price | Body | Returns |
|---|---|---|---|
| `POST /api/compliance` | $0.02 | `{ target:{ payto_address, agent_id? }, payment_context?:{ amount, asset } }` | `compliance_decision` (pass/flag/block) + `diligence_tier` + `obligations` + checks: OFAC sanctions (hit = block), due-diligence tier, structuring/smurfing (needs `agent_id`), FATF Travel-Rule threshold (informational). |
| `POST /api/assess/rwa` | $0.02 | `{ target:{ payto_address:<token contract 0x…>, network:"eip155:8453"\|"eip155:1" } }` | `risk_score` + `decision` + `is_permissioned_security` + signals: proxy-aware transfer-restriction (ERC-1404/ERC-3643/allowlist/freeze/pause), behavioral transfer simulation (reverts = trapped funds), live pause state, token identity, issuer/admin identity + issuer OFAC. `not_checked` stated honestly. |

## Verification (opt-in trust credential)
| Endpoint | Price | Body / Query | Returns |
|---|---|---|---|
| `POST /api/verify` | $0.02 | `{ payto, resource_url?, claimed_buyers? }` | deep ecosystem-graph audit; IF it passes, a signed time-boxed credential + public allow-list entry. Positive-only (failures never published). |
| `GET /api/verified` | FREE | — | public allow-list of currently-verified services + the `issuer` address. |
| `GET /api/verification` | FREE | `payto=0x…` | is this service Verified? Returns the signed credential (recover signer == `issuer` to verify independently). |

## Free
| Endpoint | Query/Body | Returns |
|---|---|---|
| `GET /api/assess/preview` | `payto=0x…` | rate-limited: `{ decision, risk_score }` only — confirm the gate before paying. |
| `POST /api/report_outcome` | `{ assessment_id, outcome, tx_hash? }` | trains the settlement-reliability signal. |

Terms: `https://402sentinel.com/terms`.
16 changes: 16 additions & 0 deletions 402sentinel/references/error-handling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Error Handling

| Status | Meaning | Action |
|---|---|---|
| `402` | Payment required (first leg of every paid call). | Read `PAYMENT-REQUIRED`, sign, retry with `PAYMENT-SIGNATURE`. Not an error. |
| `200` | Success. | Read the body and the `PAYMENT-RESPONSE` settle receipt. |
| `400` | Bad params / body. | Fix the request. You were NOT charged (settlement only on status < 400) — do not retry blindly. |
| `402` after paying | Stale/duplicate payment, or a re-challenge. | Fetch a FRESH challenge and rebuild the payment payload (one nonce settles once). |
| `429` | Rate limited (mainly the FREE preview tiers, per-IP daily quota). | Back off; switch to the paid endpoint, or retry later. Paid calls are not quota-limited. |
| `5xx` | Transient upstream/server error. | Bounded retry with exponential backoff (e.g. 3 tries). You were NOT charged. |

## Rules
- Settlement is server-response-based: it occurs only when the handler returns status < 400, so a `4xx` never costs USDC.
- Do not mutate path/query/body between the challenge and the paid retry — it invalidates the signature.
- Treat the runtime `402` challenge (price/network/payTo) as authoritative over any cached pricing.
- Never log or echo the raw `PAYMENT-SIGNATURE` or the signer key.
48 changes: 48 additions & 0 deletions 402sentinel/references/x402-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# x402 Payment Flow

Two ways to pay, in order of preference.

## 1. Bankr wallet signing (preferred)
If running inside Bankr, let Bankr sign: call `/agent/sign` with a Bankr API key (`X-API-Key`, Agent API + signing enabled, not read-only). Bankr handles the 402 challenge/settle for you — you just issue the request.

## 2. Vanilla x402 (any agent)
For non-Bankr agents, do the standard challenge → sign → retry. This is the recipe verified end-to-end against these endpoints (the load-bearing detail is the `PAYMENT-SIGNATURE` request header — not `X-PAYMENT`).

### Protocol
1. Send the request (GET, or POST with a JSON body) without payment headers.
2. If status is `402`, base64-decode the `PAYMENT-REQUIRED` response header → the challenge JSON (`accepts` offers Base `eip155:8453` AND Solana; asset USDC; scheme `exact`).
3. Build a payment payload from the challenge and encode it as the `PAYMENT-SIGNATURE` header.
4. Retry the SAME request (do not mutate path/query/body) with that header.
5. On success, read the data and the `PAYMENT-RESPONSE` settle receipt.

### Reference implementation (TypeScript)
```ts
import { x402Client, x402HTTPClient } from "@x402/core/client";
import { encodePaymentSignatureHeader } from "@x402/core/http";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);
const client = new x402Client();
registerExactEvmScheme(client, { signer });
const http = new x402HTTPClient(client);

export async function pay(url: string, init: RequestInit = {}) {
let res = await fetch(url, init);
if (res.status === 402) {
const challenge = JSON.parse(Buffer.from(res.headers.get("PAYMENT-REQUIRED")!, "base64").toString());
const sig = encodePaymentSignatureHeader(await http.createPaymentPayload(challenge));
res = await fetch(url, { ...init, headers: { ...init.headers, "PAYMENT-SIGNATURE": sig } });
}
return res.json();
}
```

### Reliability rules
- Do NOT change path/query/body between the challenge and the paid retry.
- One nonce settles once: a duplicate/replayed `PAYMENT-SIGNATURE` is rejected (the facilitator dedups in-flight). Build a fresh payment per logical call.
- Settlement happens only when the handler returns status < 400 — a `4xx` (bad params) means you were NOT charged.
- Pay on EITHER rail; pick Solana if your wallet is SPL-funded, Base if EVM-funded.

### POST endpoints
Most 402Sentinel endpoints are POST with a JSON body. Keep the exact same body on the paid retry. Use your payer wallet address as `agent_id` so the buyer-side firewall keeps per-agent state.
66 changes: 66 additions & 0 deletions 402sentinel/skill.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
name: 402sentinel-api
description: Pre-payment counterparty risk + compliance gate for agents over x402. Use BEFORE paying an x402 counterparty to score the seller (0-100 risk + allow/review/block), run a buyer-side payment firewall (routing/amount/velocity + prompt-injection + intent-mismatch checks), screen OFAC/FATF compliance, and gate tokenized-RWA tokens (transfer-restriction / pause / issuer screening). Independent and audited.
---

# 402Sentinel API Skill

Use this skill when an agent is about to **pay an x402 counterparty** and should check it first — or needs OFAC/FATF compliance screening or a tokenized-RWA token safety check. 402Sentinel scores the seller, vets the specific payment against the agent's own behaviour, and screens compliance — all pre-pay.

Every paid endpoint is **x402 pay-per-call** — no signup, no API key. The skill's job is to pick the right endpoint and execute the x402 flow correctly.

## Base URL

- `SENTINEL_BASE_URL`: `https://402sentinel.com`
- Single origin for runtime requests AND discovery docs (`/.well-known/x402`, `/openapi.json`, `/llms.txt`).

## Access Model

- **x402 only** — no API-key path. Unpaid requests return HTTP `402`.
- The 402 challenge offers **two rails — Base (`eip155:8453`) and Solana (`solana:…`)**; pay on either, asset is USDC, scheme is standard x402 `exact`, settled via the Coinbase/CDP facilitator.
- Prefer **Bankr wallet signing** (`/agent/sign`) when available (`X-API-Key`, Agent API + signing, not read-only); otherwise any vanilla x402 client with a USDC-funded wallet.
- Most endpoints are **POST** with a JSON body. Use your payer wallet address as `agent_id` so the buyer-side firewall keeps per-agent state.

## x402 API Call Checklist

1. Send the request (usually POST with a JSON body) without payment headers.
2. If the response is `402`, parse the base64 `PAYMENT-REQUIRED` header (scheme, both networks, USDC asset, amount, payTo).
3. Sign the payment and retry with the `PAYMENT-SIGNATURE` header.
4. On success, read the verdict and the `PAYMENT-RESPONSE` settle receipt.
5. A `4xx` from the handler means you were NOT charged (settlement only on status < 400); apply retry/backoff on `402` re-challenge and transient `5xx`.

## Required Preflight (Deterministic)

Before the first call in a session, fetch the discovery docs (free, no payment): `GET /.well-known/x402`, `GET /openapi.json` (canonical routes + body schema — authoritative), `GET /llms.txt`. Treat the runtime `402` challenge as authoritative for price/network/payTo.

## Core Endpoints (price = USDC per call)

Seller risk:
- `POST /api/assess` — $0.002 — assess a counterparty before paying. Body `{ target:{ payto_address }, payment_context?:{ amount, asset }, policy?:{ block_at_score, review_at_score, min_confidence } }`. `payto_address` may be a 0x EVM (Base) OR a base58 Solana seller. Returns `risk_score` (0-100), `decision` (allow/review/block), `confidence`, `coverage`, per-dimension signals, `key_factors` (the signals that drove the score), `recommended_policy`, and an `assessment_id`. (OFAC screening here covers EVM lists; stated honestly in the output for Solana.)
- `POST /api/assess/deep` — $0.02 — same shape, scans more on-chain settlement history for higher confidence.
- `POST /api/policy` — $0.002 — risk → enforceable wallet policy: `max_payment_usdc`, `daily_cap_usdc`, `add_to_denylist`, `require_human_approval`. Apply directly to the agent wallet's spending limits.

Buyer-side payment firewall (vets THIS payment in the context of YOUR agent's behaviour):
- `POST /api/firewall` — $0.002 — Body `{ agent_id, payment:{payto_address,amount,resource_url}, context?:{source,untrusted_text,intended:{payto,max_amount}}, policy? }` → allow/hold/block + signals: `routing_anomaly` (payTo swapped vs history), `velocity_anomaly` (drain), `amount_anomaly` (overcharge), `provenance_flag` (untrusted source), `counterparty_risk` (folds assess), `injection_destination` (pass the page/tool output as `untrusted_text`; if the payTo appears in it → hard block — catches prompt-injection payments), `intent_mismatch` (pass `intended:{payto,max_amount}`; any deviation → hard block), `new_counterparty_burst`, `recurring_flagged`. Stateful per `agent_id`. Seed history free at `POST /api/firewall/record`; report what happened free at `POST /api/firewall/outcome` to train per-signal precision. ANTI-POISON: to build TRUSTED history, sign `402sentinel:<action>:<agent_id-lowercased>:<unix_ts>` with the agent_id wallet and pass `owner_sig`+`owner_ts`.

Compliance + tokenized-RWA:
- `POST /api/compliance` — $0.02 — pre-pay compliance screen. Body `{ target:{ payto_address, agent_id? }, payment_context?:{ amount, asset } }` → `compliance_decision` (pass/flag/block) + `diligence_tier` + `obligations` + checks: OFAC sanctions (hit = hard block), due-diligence tier, structuring/smurfing detection (needs `agent_id`), FATF Travel-Rule threshold (informational). Screening support — not legal advice.
- `POST /api/assess/rwa` — $0.02 — "is this TOKEN what it claims?" Body `{ target:{ payto_address:<token contract 0x…>, network:"eip155:8453"|"eip155:1" } }` → `risk_score` + `decision` + `is_permissioned_security` + signals: proxy-aware transfer-restriction detection (ERC-1404/ERC-3643/allowlist/freeze/pause), behavioral transfer simulation (reverts = trapped funds), live pause state, token identity, issuer/admin identity + issuer OFAC. `not_checked` stated honestly (backing/PoR, peg/NAV, holder concentration). Diligence support — not investment advice.

Verification (opt-in trust credential):
- `POST /api/verify` — $0.02 — a service submits its own payTo; a deep ecosystem-graph audit, and IF it passes, a signed time-boxed credential + public allow-list entry. Positive-only (failing audits never published). Body `{ payto, resource_url?, claimed_buyers? }`.

Free (no payment):
- `GET /api/assess/preview?payto=0x…` — FREE (rate-limited) — just `{ decision, risk_score }` for one address, to confirm the gate before paying.
- `GET /api/verified` — FREE — the public allow-list of currently-verified services + the `issuer` address.
- `GET /api/verification?payto=0x…` — FREE — is this service 402Sentinel-Verified? Returns the signed credential (recover the signer == `issuer` to verify independently).
- `POST /api/report_outcome` — FREE — after paying, report delivery (`delivered|partial|not_delivered|overcharged`, `tx_hash?`) to train the settlement-reliability signal.

## Notes

- Scores are probabilistic estimates from limited public on-chain data + heuristics — informational, NOT advice, NOT an endorsement or accusation. Do your own due diligence. Terms: `https://402sentinel.com/terms`.

## References
- API reference (all endpoints, params, response fields): `/skill/references/api-reference.md`
- x402 payment flow (Bankr signing + verified vanilla recipe): `/skill/references/x402-flow.md`
- Error handling (402 / 429 / 4xx / 5xx, retry rules): `/skill/references/error-handling.md`
Loading