diff --git a/402sentinel/catalog.json b/402sentinel/catalog.json new file mode 100644 index 0000000000..89b17344b9 --- /dev/null +++ b/402sentinel/catalog.json @@ -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: \"\", 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" + } +} \ No newline at end of file diff --git a/402sentinel/references/api-reference.md b/402sentinel/references/api-reference.md new file mode 100644 index 0000000000..94010f7e7a --- /dev/null +++ b/402sentinel/references/api-reference.md @@ -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:::` 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:, 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`. diff --git a/402sentinel/references/error-handling.md b/402sentinel/references/error-handling.md new file mode 100644 index 0000000000..09742e1742 --- /dev/null +++ b/402sentinel/references/error-handling.md @@ -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. diff --git a/402sentinel/references/x402-flow.md b/402sentinel/references/x402-flow.md new file mode 100644 index 0000000000..08a820e09d --- /dev/null +++ b/402sentinel/references/x402-flow.md @@ -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. diff --git a/402sentinel/skill.md b/402sentinel/skill.md new file mode 100644 index 0000000000..31b521e416 --- /dev/null +++ b/402sentinel/skill.md @@ -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:::` 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:, 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` diff --git a/README.md b/README.md index bc5b17c034..882eb1df61 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ Bankr Skills equip builders with plug-and-play tools to build more powerful agen | [qrcoin](https://qrcoin.fun) | [qrcoin](qrcoin/) | QR code auction game. Scan QR codes to place bids in on-chain auctions with unique token mechanics. | | [Quicknode](https://www.quicknode.com) | [quicknode](quicknode/) | Blockchain RPC and data access for all supported chains. Native/token balances, gas estimation, transaction status, and onchain queries for Base, Ethereum, Polygon, Solana, and Unichain. Supports API key and x402 pay-per-request access. | | [Quotient](https://quotient.social) | [quotient](quotient/) | Market intelligence API with x402 micropayment and API key auth. Access onchain/social analytics, OpenAPI discovery, and pricing data via `q-api.quotient.social`. | +| [402Sentinel](https://402sentinel.com) | [402sentinel](402sentinel/) | Pre-payment counterparty risk + compliance gate for agents — call it BEFORE paying an x402 counterparty. Score the seller (0-100 risk + allow/review/block + key_factors), run a buyer-side payment firewall (routing/amount/velocity anomalies + prompt-injection-destination + intent-mismatch hard blocks), screen OFAC/FATF compliance, and gate tokenized-RWA tokens (proxy-aware transfer-restriction / live-pause / issuer screening). x402 pay-per-call (USDC on Base + Solana, no API key); free preview + public verified allow-list. Independent and audited. | | [SIGNA](https://www.signaagent.xyz) | [signa](signa/) | Give your Bankr agent a brain and a wallet-signed line to every other agent on any framework, keyless. Resolve any identity to a wallet, DM agents, invoke capabilities, and run a brain that reasons on decentralized inference and acts. No API key. | | [Axiom](https://clawbots.org) | [signals](signals/) | Transaction-verified trading signals on Base. Register as provider, publish trades with TX hash proof, consume signals from top performers. | | [Builder's Garden](https://builders.garden) | [siwa](siwa/) | Sign-In With Agent (SIWA) authentication for ERC-8004 registered agents. Sign messages using Bankr wallets, verify on the server, and protect API routes with ERC-8128. |