The short version.
Some tables hold request or answer text: schedule_runs.reply_enc, agreement_evidence.content, agreement_jury.statement, kv.value, and schedules.prompt_enc.
- Every one of the 115 tables and 1,230 columns in the database schema is described on this page, and the build fails if a table or column is added without one.
- No table has a column for a network address, and no line the code writes to its log records one. Calls without an API key are rate-limited by the caller's address, which appears only inside a Redis key that expires between 61 seconds and 3,601 seconds after the counting window begins. Over Tor no address is used at all.
Where something is kept, exactly
Retry without paying twice keeps a reply when you ask
Opt-in retry protection for API-key inference calls with Idempotency-Key. The key hashes account id, API key hash and the caller's idempotency key. AES-256-GCM ciphertext under APP_SECRET and this scope contains a canonical request-body and endpoint hash, an ownership marker, and the final status, reply and receipt headers. The request body and raw idempotency key are not stored. Replies can echo request text. Stream replies are not retained; a completed marker keeps status and receipt headers instead. An unfinished call or failed retention leaves an in-progress marker; retries never run inference again while it remains. Redis failure refuses a new protected call before billing. No new database row or log field is added. 86,400 seconds (24 hours) from the first request; completion does not extend it. Redis deletes the entry at expiry. After expiry the same key starts a new billable call. Without Redis, entries live in one router process only and are lost at restart. The router still reads request and reply text in memory.
The response cache keeps answers when you ask it to
A request that turns the response cache on has its answer kept, sealed with AES-256-GCM, in Redis and in the router's memory. It is kept for the time-to-live the request asked for in cache.ttl: at most CACHE_TTL_S, which is 3,600 seconds unless the operator changed it, and also the default when the request names none. Requests that do not ask for caching leave nothing here, and a call paid with a blind token, a call on the attested lane or with any disclosure ceiling, a restricted model variant and a streamed answer are never cached. A semantic cache also keeps a 1,024-number hashed word vector of the prompt in memory.
A call paid with x402 keeps its answer for 24 hours, so a lost answer is never paid for twice
Where x402 is switched on, the answer to a call paid with x402 is kept, sealed with AES-256-GCM, in Redis (or the router's memory without Redis), never in the database, so the payer can have it sent again with PAYMENT-RECOVERY if it was lost on the way. 86,400 seconds (24 hours) from the answer, set when it is written; the x402-recovery-expire job also deletes it with its row. Calls not paid with x402 leave nothing here. For that time the database keeps only the payer, the authorization nonce, two hashes and the name of the Redis key.
The Batch API keeps a batch's requests and answers until its results expire
A batch sent to POST /api/v1/batches has its requests and answers kept, sealed with AES-256-GCM, in Redis (or the router's memory without Redis), never in the database. The sealed requests are deleted when the batch finishes; the sealed answers BATCH_RESULTS_TTL after that (86,400 seconds, 24 hours, unless the operator changed it). A batch that never finishes ends when its 24-hour completion window closes, so nothing outlives the window plus that time. Calls that are not part of a batch leave nothing here.
A failed provider attempt can keep a short piece of the provider's own error message
generations.attempts: up to 200 characters of the message a provider sent back when an attempt failed, with URLs, keys, emails and long hex removed. The text is the provider's, not ours; a provider could quote part of a rejected request in it.
Two request headers are kept as you wrote them
apps.url and apps.title: the HTTP-Referer and X-Title headers of a chat call, cut to 500 and 200 characters, so apps can be ranked. Leave the headers out and nothing is kept. They are not recorded on the unlinkable lane.
Settings you type are stored as you typed them
agent_approvals.intent, agent_policies.spec, agent_policy_events.intent, agent_profiles.settings, agent_sessions.metadata, keys.routing, keys.guardrails, keys.tracing, keys.topup, playbook_changes.spec, playbooks.spec, policy_versions.spec, team_audit.detail, characters.card, facilitator_sellers.result_schema, model_watches.state, preset_versions.config, saved_routes.description, saved_routes.config, skills.description, status_incidents.title, status_incidents.updates, tool_listings.canary, and webhook_destinations.events hold configuration you write: descriptions, routing and guardrail settings, the system prompts and tool definitions of your presets, the character cards you publish, session labels. The API checks their shape and size, but it cannot know what you choose to write in a description or a label.
Character memory is kept only as ciphertext, with a vector if you opt in
Memories you keep for a character are sealed on your device under a key the router never receives; the database holds the ciphertext. If you opt in to memory search, it also holds a vector your client computed from each memory, which cannot be turned back into the text but can reveal what it is about.
This page is about what is kept. It is not a claim that nobody can read a request while it is in flight: on ordinary chat routes on every lane the router reads the text of a request in memory, and the provider reads it too under its own policy. The dedicated, off-by-default E2EE adapter forwards encrypted content without decryption; the gateway enclave restores it. Clear routing and billing metadata remains visible.
Which version this is.
This page and /keep/inventory.json are generated from the same source, so they always agree. The hash is the SHA-256 of the exact bytes of that file.
- Built from commit
3a3d3849689035578e2d54588c29225e63f27c85- Inventory SHA-256
b00d8286cd165487b542d8d234479c8279a156409aed2914ce8998d22b610c86- Size
- 115 tables, 1,230 columns, 126 columns that looked like request content or an address and carry a written review
- Check it yourself
curl -s https://<this site>/keep/inventory.json | sha256sumprints the hash above. The file is canonical JSON: keys sorted, no whitespace.
GET /api/v1/tlog/proof?kind=data_inventoryAsking the router’s log about this hash…
The hash is appended to the router’s public transparency log as a data_inventory entry when a router with a new inventory starts, where the operator has switched that on. Anyone can look it up by hash at /api/v1/tlog/lookup, and, where the log is anchored in Rekor, follow the link above to that entry.
Where a request’s text and a caller’s address are read.
An automated check scans the router’s source for every route that reads a request body and every piece of code that reads a caller’s address, and fails until each one is described here. The rows below say what is read, what happens to it and what is kept.
Request text
| Where | What is read, and what happens | What is kept |
|---|---|---|
| src/telegram/photos.ts | With TELEGRAM_PHOTOS_ENABLED, the bot reads photo size identifiers and the optional caption from a private Telegram message, calls getFile and downloads the largest photo that fits 8 MB. The downloaded JPEG and caption are readable in router memory for this request. An in-memory JPEG segment filter copies the image data unchanged and drops EXIF and other application metadata, comments and trailing bytes. Malformed or oversized images are refused. The caption, or a fixed question, and an inline JPEG go through the same API-key chat route, billing, limits, private-mode lane guard and signed receipts as text. Telegram and the chosen model provider can read the image and caption and apply their own retention policies. | No photo bytes, caption, file id, download path or image URL are saved in Postgres, Redis, logs, filesystem or a bot history. The request's digest and ordinary billing and receipt metadata are retained by the chat path. The bot never opts into response caching. Existing sealed key, model, private-mode setting, polling offset and Telegram-user rate counter retention are unchanged. Disabled by default; no download while off. |
| src/idempotency/middleware.ts | API-key request JSON only when Idempotency-Key is present on a supported inference endpoint. Authenticates the current key and role, hashes the canonical body and endpoint in memory, and claims a scoped retry guard before approval consumption or billing. Ordinary router paths still read request text in memory on every lane; encryption at rest does not hide replies from the router. | Only a request hash plus an encrypted final reply, status and selected response headers for 24 hours, in Redis or memory. Streaming keeps no answer text. The same key with a different request gets 422; an unfinished call gets 409. Unsupported credential types cannot opt in. |
| src/api/schedules.ts | Owner-chosen name, prompt, model, paying key hash, recurrence, UTC time, cost ceiling and pause state. Requires an active owner or management key, excludes inference and session keys, verifies ownership of the paying key, and encrypts the prompt before saving it. | Prompt ciphertext and schedule metadata in schedules; last ten encrypted replies and bounded failure reasons in schedule_runs. Deleted with the schedule. Ordinary chat still reads text in memory and retains billing metadata. |
| src/model-alternatives/suggest.ts | Resolved request messages, content-part types, tool declarations, output modalities and token bounds in router memory, plus model metadata, current provider health and routing preferences. Checks the abilities needed by the request and ranks up to three currently eligible alternatives by estimated request cost. Reads message text to estimate token counts. Never forwards a suggestion request to a provider, switches a model or charges for suggestions. | No new database table or column, Redis family, log field or server-side store. Suggestions are unsigned error response metadata. Existing batch error outputs may retain them until their ordinary expiry. Chat keeps suggestions with the failed reply in active-tab memory only; its existing history snapshots omit failed replies and their suggestions from storage and exports; clicking a suggestion resends the same conversation through ordinary authorization, policy, lane and billing checks. |
| src/hardening/body.ts | Request bytes before route dispatch, including ordinary plaintext inference, files and encrypted envelopes. Reads the declared Content-Length and streams up to each route's wire cap; an over-cap chunk is discarded. Rejects excess bytes with 413 before route side effects; passes a bounded replacement request to existing handlers, preserving the gateway origin record. | Bounded bytes in request memory only. This guard does not hide plaintext prompts from the router. No new database columns or body logging. |
| src/hardening/middleware.ts | The bounded MCP JSON message or batch, including tool arguments and any prompt. Rejects batches over 20 messages and charges each message against the anonymous minute limit. Existing MCP tool and rulebook guards still apply. | Parsed message in request memory only; count in the anonymous limiter. No tool arguments or prompts in the counter or logs. |
| src/tools/routes.ts | A paid tool call: the tool's address, method, a JSON body of at most 64 KiB for the tool, max_price and optionally a model and prompt to hand the answer to. A tool listing: name, summary, address and a canary probe. Sends the body to the tool through the egress guard and reads its answer (2 MB at most, JSON or plain text only) in memory, returning it to the caller marked untrusted. Only when the rulebook sets tools.pass_to_models and the call asks for it is the answer sent to a model through the ordinary chat route. | tool_calls keeps hashes of the request and answer, amounts, the address without its query and the signed receipt; tool_listings keeps the listing. The body, the query string and the answer are not stored or logged. No new Redis family beyond the two rate limits, no caller-address reader. |
| src/structured-output/chat.ts | Resolved chat messages and response_format schema, the final answer, and the opt-in anyroute.json_check setting when STRUCTURED_OUTPUT_CHECK_ENABLED is enabled. Reads request and answer text in router memory to check JSON and supported schema assertions. Repair may send the same provider and model one extra request containing the conversation, original answer, schema and validation errors. Each call passes the ordinary authorization, lane, agent and billing checks. Streams validate only. | No new database column, Redis family or log field. Both calls keep ordinary generation hashes, token counts, costs and signed receipts. Validation errors, JSON Pointer paths, combined charges and nested call receipts are unsigned response metadata, not written to generation receipts or returned by receipt lookup. Existing batch outputs can retain that metadata with the answer. Preset json_check settings live in the existing preset_versions.config JSON. Existing optional cache and batch retention rules still apply; non-streaming repair bypasses the response cache. |
| src/pay/recovery.ts | The body of a paid x402 call on the chat, completions, embeddings, rerank and character chat routes, and of a recovery request; and the answer's bytes once the call is answered. Hashes the request (the receipt's request_sha256) to bind the answer to it, or to compare a recovery request with it. Seals the answer's bytes with AES-256-GCM. A recovery checks the payer's EIP-191 signature first and never relays the payment again. | The two SHA-256 hashes, the payer, the nonce and the Redis key name in x402_paid_results, and the sealed answer in Redis (or the router's memory without Redis), each for 24 hours. The request text is not kept. No log field, no caller-address reader. |
| src/agreements/internal-transport.ts | Decrypted party evidence bundle and structured provider verdict text in router memory. Fixed rubric sent through attested-lane selection with fresh non-development attestation, stored provider credentials and quote-pinned TLS where configured. Gateway receipts must verify upstream attestation and exchange digests. No customer account or billing rows. | Existing agreement_jury.statement stores model reasons (which may quote evidence), signed operational receipt with request/response hashes, provider attestation and checked gateway receipt references, usage and provider-list-price operator cost estimates. Canaries have no separate operational-cost ledger. Failed calls may incur unmeasured cost. No evidence text in logs; no new Redis keys or caller-address readers. Same resolution-based jury retention applies. |
| src/agreements/routes.ts | Bounded party evidence text or JSON, or a strict create-agreement preparation with payee wallet, milestone USDG amounts, terms hash and future deadline. Requires an authenticated wallet-linked account matching the indexed payer/payee. Caps streams without trusting Content-Length. Preparation checks inherited rulebooks and returns unsigned calldata; jury calls use the attested chat path with a configured API key, or the optional internal provider transport. | Evidence hash and APP_SECRET-encrypted content in agreement_evidence, up to 32 items per party. Jury statement stores per-model answer reasons, receipt references and a signed ruling; reasons can quote evidence. Router reads evidence in memory. Parties can read both parties evidence through the API. Resolution plus 30 days by default permits deletion; a fresh-index retention job removes evidence and jury rows. No new Redis family, log field or caller-address reader. |
| src/api/e2ee.ts | A bounded encrypted JSON envelope and encrypted SSE or JSON response; model, roles, lengths, public keys, timestamp, nonce and clear usage remain visible. A caller must actually encrypt content; framing checks cannot prove encryption. Validates a strict text envelope, forwards the original bytes without decryption, hashes wire bytes, observes usage and completion for billing. No tools, files, search, cache, alias or content transformations. | Only hashes, counts or reservation bounds, charge and timing in generations and the ledger. The signed receipt adds end_to_end_encrypted, e2ee version/suite/gateway_attested/complete/billing_basis/input_byte_bound/max_tokens/request_bytes/response_bytes and gateway_receipt (id, keyset digest, response-hash/request-hash/upstream check states and upstream session id and GPU claim). Existing retention and deletion apply. No envelope, response ciphertext, public key, replay nonce, timestamp or credential is persisted; no new log fields or Redis families. |
| src/api/chat.ts | The whole JSON body of a chat or text completion: the messages, the model and the parameters (readJson). Read in memory to route the call on every lane: validated, checked against guardrails, priced, then sent to the provider chosen. The request is hashed (request_sha256) and the answer is hashed (response_sha256). Streaming answers are passed through chunk by chunk. | Not stored. Kept in memory for the length of the call. The opt-in response cache and batch content are kept sealed outside the database (see the Redis section), and a failed provider attempt can keep up to 200 characters of that provider's own error message. |
| src/api/batches.ts | The JSON body of a batch: up to BATCH_MAX_LINES chat or embeddings requests (requests or input_jsonl). Checked line by line, then sealed at once and kept in Redis (or memory) for the worker, which runs each line through the chat or embeddings handler as the key that sent the batch. | Not in the database: the database gets counts, statuses, costs and generation ids. The sealed requests are deleted when the batch finishes and the sealed answers when its results expire (see the Redis section). |
| src/api/embeddings.ts | The JSON body of an embeddings call: the input text. Sent to the provider chosen and the vectors returned. | Not stored; a generation row and receipt with hashes and counts are written. |
| src/api/rerank.ts | The JSON body of a rerank call: the query and the documents. Sent to the provider chosen; its scores are checked and returned, with the documents' own text when asked. | Not stored; a generation row and receipt with hashes and counts are written. |
| src/api/anthropic.ts | The JSON body of an Anthropic-format messages call and free onion count requests. The router reads code, prompts and tools in memory. Converted to a chat request and sent through the router's own chat route, so it is handled and kept exactly as a chat call is. | Nothing beyond what src/api/chat.ts keeps; token counts alone create no payment or request record. |
| src/api/responses.ts | The JSON body of a Responses-format call. Converted to a chat request and sent through the router's own chat route. | Nothing beyond what src/api/chat.ts keeps. |
| src/ollama/routes.ts | The JSON body of an Ollama-format chat, generate or embed call. Converted to a chat or embeddings request and sent through the router's own route, so it is handled and kept exactly as that call is. | Nothing beyond what src/api/chat.ts and src/api/embeddings.ts keep. |
| src/api/mcp.ts | The JSON-RPC body of a tool call for the MCP endpoint, which can include a prompt. Chat is forwarded to the router's own chat route. Rulebook tools forward caller authentication and prompt-free intent identifiers to the existing agents routes; token estimates use catalog prices. Reading and checking rules does not create policy events. | Nothing beyond what src/api/chat.ts and its existing policy enforcement keep. Rulebook reads and dry runs add no stored data. |
| src/api/rag.ts | The documents and the question of a retrieval call. Cut into chunks and embedded through the router's own embeddings route, ranked in memory, and the best chunks sent to the router's chat route. | Nothing of the documents, question or answer is kept; the chunks and vectors are dropped when the request ends. The response cache is never used. |
| src/ohttp/gateway.ts | An encapsulated request (Oblivious HTTP). The gateway opens it with its own private key, in memory. Dispatched to the router's own routes as an ordinary request without a client address. | Nothing beyond what the route it reaches keeps. The private key for an epoch is destroyed when its window ends. |
| src/services/telegram.ts | A Telegram message a user sent to the bot (fetched from Telegram by long polling). Sent to the router's own chat route with the user's own API key, so limits, billing and receipts apply. | The message text is not stored or logged; only the user's sealed key and chosen model are (kv table). |
| src/gateway/cache.ts | The request and the answer, only when the caller opted in. Encrypted and stored with a time-to-live (memory and, when configured, Redis). A hit is served without asking a provider. | The sealed answer, for the time-to-live the caller asked for (at most CACHE_TTL_S). A semantic cache also keeps, in memory only, a 1,024-number hashed word vector of the prompt so near-duplicates can match. |
| src/api/characters.ts | A character card (JSON or PNG) or, for a private card, only its ciphertext and hash; and on POST /api/v1/characters/:id/chat a chat request with the conversation, the memory the client decrypted and, for a private card, the decrypted card. A public or unlisted card is normalized and stored. A chat is assembled into a prompt in memory and sent through the chat route (src/api/chat.ts), like any other call; a private card sent with it is checked against its stored hash and used for that call only. | Public and unlisted cards in characters; for a private card only the ciphertext and hash. Nothing of a chat, its memory or a decrypted private card; public characters add one to a daily call and cost counter (character_usage). |
57 routes that read a body but carry no prompt (settings, payments, public data)
| Where | Carries | What is read, and what happens | What is kept |
|---|---|---|---|
| src/api/business-details.ts | Settings | Optional user-entered business name (160 characters), multi-line postal address (1000), tax ID (120, free text) and reference (240, no email addresses). Unknown fields and control characters are rejected. With STATEMENTS_ENABLED, requires an active account management key to replace or clear the details, excluding sessions, team-only owner/admin keys and read-only keys. Other keys that can read statements can read this account's details; the existing read-only route guard still blocks the new settings route, so those keys use the opt-in statement response instead. | business-details:<account id> in the existing Postgres kv table stores the four fields in plain JSON with an update timestamp, until replaced or deleted. No inference text, new Redis key family, network address reader or log field is added. |
| src/key-rotation/routes.ts | Settings | One strict grace choice: 1h, 24h or 7d. Uses the existing key-edit owner/admin authentication, refuses restricted callers and agent sessions, checks the Credits deposited total directly on chain and account ownership and copies eligible account-backed keys in one transaction. Returns the new secret once with no-store; the router handles it in memory. | The old and new key hashes, rotation time, old-key grace deadline and original rulebook history link in key-rotation:<key hash> rows in kv. Key settings and saved rulebook revisions are copied to existing tables; new usage starts at zero. No secret is stored. |
| src/agent-duplicate/routes.ts | Settings | An optional new agent name, trimmed to 1–100 characters. The source key hash is read from the route. Requires account management or same-team owner/admin authentication, rejects restricted and session callers, rechecks authority inside the locked account transaction, and enforces team budgets and no permission escalation. Returns the fresh secret once with no-store; the router handles it in memory. | A new keys row, a fresh team_members API-key membership without a principal binding, current agent_policies rules detached from any playbook, one policy_versions save, and a new hash-chained agent_policy_events duplicated entry whose reasons hold Copied from plus the original readable name. Existing agent-approvers and quiet-agent-alert kv settings are copied, with quiet delivery history reset. No secret is stored. |
| src/model-watch/routes.ts | Settings | A strict object containing a public catalogue model id for watch or unwatch. Requires a current management owner key, excludes session, team and read-only keys; serializes watch cap changes under an account row lock and revalidates current authority in the transaction. | Account id, model id, creation time and worker availability state in model_watches. No prompt, answer, credential, caller address or new log field. Browser memory holds the watch list and a short shared read promise; no new browser storage. |
| src/api/agent-approvers.ts | Settings | Strict per-agent approval mode and bounded unique IDs selected from the agent's active team members. Requires management or owner/admin account/team access outside agent sessions, then rechecks access and member choices in a transaction serialized with approval decisions. | Mode and selected principal IDs or key hashes in existing kv, plus existing security notice metadata when enabled. No prompt, answer, secret or caller address is read or retained. |
| src/api/quiet-agent-alerts.ts | Settings | A strict JSON object with hours null or one of 1, 3, 6, 12, 24, 72; no other field is accepted. Requires the existing agent owner/admin principal and same account/team ownership, explicitly refuses inference keys, and writes settings outside the rulebook under the account lock. Disabled endpoints return 404 before reading a body. | quiet-agent-alert:<key hash>: per-agent hours (null means off), enable timestamp, last claimed quiet-period activity timestamp, and newest 100 notices with random id, timestamp, readable agent-name title, hour window and last charged-call/Guard-decision time. Settings and the dedupe anchor persist until operator deletion. Enabled runs and changed settings prune notices older than 90 days; disabled cleanup pauses, while inbox reads hide expired notices. Deleted keys leave inaccessible settings until operator deletion. No rulebook field, table, column, Redis family, address reader or log field is added. |
| src/security-alerts/routes.ts | Settings | An account management key's strict enabled boolean for security alerts. Requires the existing owner/admin principal guard plus management rights; session keys and team administrators cannot change account-wide preferences. Returns no-store. SECURITY_ALERTS_ENABLED defaults to false, returning 404 while off. | The boolean under security-alerts:preference:<account id> in existing kv until changed or account data is removed. No request text or caller network address. |
| src/notifications/routes.ts | Settings | A strict complete set of Inbox and Telegram booleans for supported notice types, including opt-in status_incidents, plus nullable daily UTC quiet-hour clocks. Requires an active management owner principal, excludes session and team keys, revalidates authority under the Telegram link lock and returns no-store. | notification-prefs:<account id> in kv stores channel choices and UTC quiet hours. Weekly Telegram reuses weekly_summary_opted_in on existing links; security switches extend the existing security-alerts:preference row. No credentials or network address. |
| src/api/weekly-summary.ts | Settings | An authenticated owner/admin's strict opted_in boolean for this key's Telegram link. Rechecks current link authority under the same lock as unlink and delivery. Writes the preference only for the caller's link. | Only the nullable weekly_summary_opted_in flag in kv; the worker keeps last_sent_week on the existing account. No prompt or answer text, new address reader or new tracking. |
| src/api/account-runway.ts | Settings | One nullable numeric low_balance_usd threshold between zero and one million dollars. Authenticates an active owner key, excludes session and inference-only keys, and accepts edits only when LOW_BALANCE_ALERTS_ENABLED is on. | Threshold in accounts.low_balance_pico and the crossing claim in accounts.low_balance_alerted. Each observed crossing keeps balance and threshold snapshots in low_balance_alerts. No prompt, answer or caller network address is read. |
| src/api/project-budgets.ts | Settings | A numeric budget_usd setting, zero to one million USD, and a validated project name in the route. Requires an active account management owner key, excludes sessions, and serializes changes with ledger reservations using the account lock. | The cap in project_budgets; saving below current spend may also create the month's deduplicated project_budget_notices row. No prompt, answer or network address is read. |
| src/api/guard.ts | Settings | A strict bounded action name, optional target label and order digest, decimal amount and approval identifier, or a reported outcome. Authenticates the deciding key and serializes checks and reports with the account lock. Action and target are readable caller-chosen labels; targets can name a wallet or host. No full order details are accepted. When DECISION_TAGS_ENABLED is on and an order digest is given, the decision also reads the same agent's calls from the preceding 24 hours whose stored receipt carries that digest as decision_tag and returns their ids, model, provider and time as informed_by; GET /api/v1/guard/decisions reads decisions by digest or receipt id within the Activity scope. Neither stores anything new. | Decision metadata and reported outcomes in agent_action_decisions, with action decisions and outcomes on agent_policy_events and action approval projections in agent_approvals. Reported amounts are not verified execution. |
| src/api/deposits.ts | Settings | A strict transaction hash and deposit lane only. Form amounts and sender addresses are not accepted. Authenticates the key, excludes session and agent-only roles, scopes reads and submitted hashes to its account. Chain logs determine observed amounts, senders and credit values; submission never credits funds. | deposit-watch rows in kv keep account id, lane, hash and submission time across reloads. At most 20 submitted hashes per account; removed after indexed credit, otherwise retained until operator deletion. No new Redis keys, caller-address readers or log fields. |
| src/api/agent-pay.ts | Settings | A recipient (public profile id or 0x wallet), a decimal USD amount, an optional memo digest and approval id; or a transaction hash to confirm. Authenticates the agent key, decides with its rulebook through Agent Guard (action pay.agent), and returns unsigned USDG transfer instructions for the payer's own wallet. A confirmation reads that transaction's receipt, Transfer logs and block hash from Robinhood Chain and signs a receipt. The router never signs or sends the payment. | agent_payments and the existing Agent Guard decision, outcome and decision-chain records. One new rate-limit family; no caller-address reader or log field. |
| src/api/linked-wallets.ts | Settings | A secondary wallet address, or a one-time nonce and personal signature, or explicit unlink confirmation. Requires an account owner key. Verifies the configured origin, chain id, five-minute expiry and secondary wallet signature; consumes the nonce once. Refuses existing wallet accounts, other secondary links and verified owner wallets of organisations owned by other accounts. Unlink affects later first deposit credits and agent payment eligibility; earlier credits remain assigned. | The link address, account id and linked date in account_linked_wallets; challenge metadata in kv; no signature, prompt, answer, caller network address or new log field. |
| src/api/agent-approve-and-allow.ts | Settings | A strict confirmation body containing only the 64-character SHA-256 of the rulebook reviewed by the principal. Checks approval owner/admin scope, original amount-only decision reasons, current rulebook hash and pending status. Approves once and raises only that agent's ask-first amount in one account-locked transaction; playbook followers are refused. | The updated rulebook, its schema version, digest, principal key hash and update time in existing agent_policies; policy_set and approval_approved events in existing agent_policy_events; decision status, actor and time in existing agent_approvals, plus the existing approval webhook when configured. No new Redis families, log fields or address readers. The confirmation hash is checked in memory and is not separately persisted. Ordinary request text remains readable by the router in memory. D144: Each rulebook save or playbook copy also retains its full readable rules, digest, date, saving key hash and source in policy_versions, in the same transaction. These revisions remain until operator deletion, including after the current rulebook is removed. |
| src/api/agent-policy-history.ts | Settings | A strict object containing only a 64-character rulebook SHA-256 to restore from the target key's history. Requires the same owner/admin, management, account and team permissions as PUT policy. Validates saved rules and digest, refuses following playbook keys, and atomically appends a revision and a policy_set event while keeping Stop state. | Full readable saved rules, digest, time, saving key hash and change source in policy_versions. The current rulebook in agent_policies and its digest in the existing event chain. No new Redis families, log fields or address readers. Ordinary request text remains readable by the router in memory. |
| src/provisioning/scope.ts | Settings | A strict scope setting: inference or account. Authorization and x-api-key credentials are hashed in memory for route restrictions; receipt identifiers are checked against generation ownership. Requires a management key for account defaults; refuses inference-only keys on every route outside the model-call and own-generation/receipt allow-list. Newly minted child keys inherit the default, including sessions and team sign-ins. | A boolean in accounts.inference_keys_default; keys.scope stores the issued scope and keys.include_byok_in_limit stores the compatibility selection. Existing rows retain their access. No new request text, address readers, Redis families or log fields. Model calls still pass through existing routing and billing. |
| src/provisioning/inference.ts | Settings | Only model and fallback-model identifiers from the already parsed inference request, after per-key aliases resolve. No prompt or answer text is inspected by this check. Refuses @ references for inference-only keys before chat reads account routes, presets or character records. Catalog model calls continue through unchanged billing. | Nothing additional: no model identifier, body, Redis family, log field or address is stored by this scope check. |
| src/webhooks/routes.ts | Settings | Bounded JSON containing an HTTPS destination URL and selected fixed event types. Requires an authenticated owner/admin outside agent sessions. New account-wide destinations require a management key; non-management callers see and control only destinations scoped to their own key. | URL and generated signing key are encrypted under APP_SECRET. Selected event identifiers are retained. Subsequent responses redact the path/query and omit credentials. No new Redis family, log field, prompt/answer reader or caller-address reader. |
| src/facilitator/routes.ts | Payments or signatures | x402 verify and settle bodies (a payer's signed USDG authorization and the seller's payment requirements), signed seller listings, and gas float top-ups, each at most 64 KB. Checks signatures, amounts, time windows and nonces, relays a valid authorization from the payer straight to payTo with the relay key, and screens a listed payTo against the sanctions list. | Settled and failed attempts in facilitator_settlements, signed listings in facilitator_sellers and float balances in seller_gas_floats. Request bodies are not stored and carry no prompts. |
| src/api/agent-profiles.ts | Settings | Owner-written public profile fields (including an optional HTTPS agent endpoint and payout wallet), explicit rulebook category selections and bounded certificate claim identifiers. Authenticates the owner or authorised account administrator, checks key ownership, validates selected record claims, strips control and Unicode format characters from bounded owner text, and publishes the card at an independent random slug. Public reads sanitize existing owner text again and project only opted fields and verify certificate signatures and expiry. | Public settings, latest selected certificate and a private key-hash association in agent_profiles until unpublish. No new address reader, Redis family or log fields. Existing receipt signing key entries are published when certificates are requested. |
| src/identity/routes.ts | Settings | Owner identity choices (two booleans), a registration transaction hash, a publish flag for a track record; a reviewer's receipt id, receipt kind, 0 to 100 score and two short tags; or a track-record certificate to verify. Owner routes require an owner or administrator key of the same account, not a session key. Feedback is accepted only when the router's own receipt names the reviewer's account as payer and the agent as payee or the agent served, and never from the agent's own account. Free text is refused. | Choices and registration progress in agent_identities, entries in agent_feedback, issued certificates in agent_track_records. Verification keeps nothing. One new account rate-limit family (agent-feedback). No prompt, answer, caller address or log field. |
| src/api/agent-sealed.ts | Settings | Strict registration settings: HTTPS /attest URL without query, image digest and measured compose hash. Requires principal ownership of the active non-management key, obtains fresh quote evidence through guarded public-only pinned TLS and verifies key fingerprint and measured deployment. | Registration settings, random revision, fixed result codes, verifier names, TLS key hash and check time in the sealed-agent kv family; never inference bodies or API credentials. No new Redis family or log field. |
| src/telegram/delivery.ts | Settings | Private Telegram /link and /unlink commands and approval callbacks fetched by the existing bot poller. Link codes and callback identifiers are read in memory. The link is role-checked and recorded without a key secret. Callbacks run the same approval decision as the dashboard; inference consumption is unchanged. Telegram receives approval intent metadata and alerts, plus current rulebook amount caps and ask-first thresholds when AGENT_RULEBOOK_WORDS_ENABLED is enabled. | Only the link identifiers, code hash, expiry and delivery markers described under kv. No Telegram message text or inference text is copied. No new request-body or network-address reader. |
| src/telegram/balance-spend.ts | Settings | Private Telegram /balance and /spend commands, Telegram user and chat identifiers, the existing account link and its current key authority. Reads existing settled account balance, charged ledger entries and visible key names to answer the command. Reuses account runway and agent spend reads. Balance and rolling seven-day pace are account-wide as on Home; spend uses UTC days and Monday-start weeks with the linked key's team visibility. Revalidates the link and authority before sending. Telegram receives readable amounts, estimated days, visible key names and, for /spend top agents, Activity links containing their key hashes and the exact UTC settlement range (J182) and applies its own retention policies. | No new table, column, Redis counter, log field or saved reply. The existing link, ledger and keys are read without changing them. No API key secret or inference text is needed for these commands; existing Telegram chat keys remain separate. |
| src/telegram/agent-stop.ts | Settings | Private Telegram /agents, /stop and /start commands, user/chat identifiers, and inline callback action, complete key digest and link generation. Reads the existing link, current key role/team/scope and expiry, visible key names and Stop state, including inherited session policies for list status. Rechecks current linked owner/admin authority and account/team ownership under the existing link lock. Read-only, inference-only and session authority is refused. Uses the same changeKill operation and security context as web Stop/Resume, under the existing account lock. Telegram receives short agent names, current status, UTC deadlines, confirmation text and digest/generation callback identifiers. Commands and replies are readable by Telegram and subject to its retention policies. | No new table, column, Redis family, log field or button-state record. Uses the existing telegram-link callback limiter counter (20 commands or button presses per minute per Telegram user). Stop changes existing agent_policies killed/kill_until/killed_at/killed_reason/updated_at/updated_by fields, and appends existing hash-chained agent_policy_events and existing alert/security records with their existing retention and notification preferences. Raw command text is not copied to storage. No inference prompt, API key secret or wallet address is read by these commands. |
| src/api/agent-certificates.ts | Settings | Bounded record claim identifiers for issuance; a signed certificate supplied by body or query for public verification. Checks retained generation counts and rulebook events, signs true claims with a fresh random pseudonym, or checks certificate signature and expiry. The router knows the authenticated issuing key. | No certificate, pseudonym, claims, query or body is persisted. Only an account issuance limiter counter and the reused public receipt signing key log entry are kept; no prompt fields are accepted. |
| src/api/playbooks.ts | Settings | A playbook name of at most 100 characters with a strict bounded rulebook and an optional team id, or a playbook id (or null) for a key to follow. Requires the same owner/admin permissions as editing a key's rulebook; account-wide playbooks change only with a management key. A rules change is copied to every following key under the account lock. | The playbook in playbooks, each change with its digest and rules in playbook_changes, the following keys' copies in agent_policies with policy_set events in agent_policy_events, and team audit entries. No prompt or answer fields are accepted. D144: Each rulebook save or playbook copy also retains its full readable rules, digest, date, saving key hash and source in policy_versions, in the same transaction. These revisions remain until operator deletion, including after the current rulebook is removed. |
| src/api/agents.ts | Settings | A strict bounded rulebook, a kill reason, a metadata-only Intent for a dry run, or a draft rulebook and a number of days (1 to 7) to replay. Requires the same owner/admin permissions as editing the target key. Evaluates dry runs deterministically without event writes or kill changes. A replay reads that key's recorded calls (model, lane, cost, tokens and time from generations, plus the linked rulebook events) and its Agent Guard checks in a read-only transaction, and evaluates the draft against them. | Current rulebooks and optional principal-written kill reasons in agent_policies; decision metadata and changes in agent_policy_events. Dry runs and replays keep nothing. No prompt or answer fields are accepted. D144: Each rulebook save or playbook copy also retains its full readable rules, digest, date, saving key hash and source in policy_versions, in the same transaction. These revisions remain until operator deletion, including after the current rulebook is removed. |
| src/agents/enforce.ts | Settings | Declared tool and function names from the inference body already parsed by the router. Projects only identifiers into the rulebook Intent, alongside the resolved model, lane, token bound and cost reservation. | Only Intent metadata and fixed decision reasons in agent_policy_events. Never arguments, descriptions, prompt or answer text; no new Redis key family or log field. |
| src/api/network-hosts.ts | Settings | Up to 8 KiB of host signup JSON or an operator-generated sidecar credential, with an existing wallet signature over the canonical JSON hash. Strictly validates signup fields, verifies the wallet and performs attestation, policy and sanctions checks. Credentials are accepted only for the recovered operator wallet. | Provider name, endpoint, operator and payout wallets, requested model IDs, optional contact, status and refusal reasons. Credential stored only in existing AES-GCM api_key_enc. The router sees it in memory. No whole-body log or signature column. |
| src/network/waitlist.ts | Settings | At most 4 KiB of JSON: waitlist fields or a deletion code. Validated strictly; a filled honeypot is discarded. The deletion code is hashed for an atomic delete. | Only sign-up fields, optional contact, id, deletion digest and time in network_waitlist. No raw deletion code, body log, IP or user agent. Free text is readable by the owner; public stats return counts only. |
| src/admin/trpc.ts | Settings | For network.publishPolicy, the operator's policy document decoded by the tRPC transport and validated by hostPolicySchema. No prompt fields are accepted. Checked for consecutive version and issue time, canonically encoded, signed with the log key, and committed with its transparency-log entry and checkpoint. | The public canonical policy, hash, signature, public verifier key, version and timestamps in host_policies, and a host_policy hash entry in tlog_entries. No caller address, operator token or request headers are retained by this publication path. |
| src/api/common.ts | Settings | The shared JSON body reader used by the routes below: it reads the text, checks its size (16 MB at most) and parses it. Returned to the route. | Nothing. |
| src/api/keys.ts | Settings | Key settings (name, budget, limits, allowed models, tracing destination, scope, include_byok_in_limit and the auto top-up amounts), amounts, BYOK provider keys, team roles and wallet sign-in challenges. Validated and written to the keys, byok_keys, teams and kv tables as described above. | The settings and, for a BYOK key or a tracing destination, the key or the destination URL and credentials encrypted under APP_SECRET. |
| src/api/saved-routes.ts | Settings | A saved route: fallback models, provider preferences and sampling controls. Validated against a strict schema with no field for message text, then stored. | The route in saved_routes. |
| src/api/skills.ts | Public data | A skill to publish: a repository URL, ref and folder, or an uploaded .tar.gz, .tar or .zip of a skill folder (SKILL.md, scripts and resources), and an optional price; an author's new price; an operator's revocation reason. The archive is read in memory under size, file-count and path limits (nothing is extracted to disk), normalised into one canonical tar, hashed and scanned; a repository is fetched at depth 1 and its tree read without a checkout. | The published skill, its hash and scan report in skills; installs in skill_installs. |
| src/api/presets.ts | Settings | A preset: fallback models, provider preferences, sampling controls and the owner's own system prompt, response_format and tool definitions. Validated against a strict schema with size caps, then stored as a new version. | The preset's versions in preset_versions. |
| src/api/memory.ts | Settings | A memory blob the client sealed (ciphertext), its opaque scope, kind and key fingerprint, and an embedding vector only when the client opts in. Checked to be in sealed form (plaintext is refused), then stored. | The ciphertext and its labels in character_memory, and the vector when the client opted in. |
| src/api/teams.ts | Payments or signatures | Team settings (a name, an org budget, a role), invites, and the proofs members sign in with: a passkey registration or assertion (WebAuthn clientDataJSON, authenticator data, signature) or a wallet signature over a one-time message. Settings are validated and stored; passkey and wallet proofs are verified and only the passkey's public key or the wallet address is kept. Each change is appended to the team's audit log. | The team, team_members, team_principals and team_audit tables; nothing of the proofs themselves. |
| src/api/spend.ts | Settings | A spend alert rule. Validated and stored. | The rule in spend_alerts. |
| src/api/agent-sessions.ts | Settings | An agent session: name, budget, lifetime and labels. Validated and stored. | The session in agent_sessions. |
| src/api/lane.ts | Settings | An operator's description of a model for the model lane: variant, status, licence and weights source. Checked for an operator token, validated and stored. | models_lane. |
| src/api/status.ts | Settings | An operator's incident notice for the status page: title, affected lanes and surfaces, impact, status and update text. Checked for an operator token, validated against a strict schema with size caps and stored. | status_incidents. |
| src/api/disclosure.ts | Settings | A provider disclosure profile written by an operator. Validated and stored. | provider_disclosure. |
| src/api/dayzero.ts | Settings | An operator's request to evaluate or approve a day-zero candidate. Validated and stored. | The lane tables. |
| src/api/creator-claims.ts | Settings | A creator claim: model, wallet address and Hugging Face handle. Validated and stored. | lane_claims. |
| src/api/host-anchor.ts | Public data | A request for an inclusion proof: a receipt envelope from an attested host (hashes and counts, no text) or a leaf hash. Looked up in host_anchor_leaves and answered. | Nothing. |
| src/api/ipx.ts | Settings | An operator's switch that halts or resumes the index-price oracle. Checked for an operator token and stored. | The halt flag in the kv table. |
| src/api/paymaster.ts | Payments or signatures | A paymaster (gas sponsorship) request. Checked and answered. | Nothing beyond the Redis rate-limit key. |
| src/api/public.ts | Payments or signatures | Receipt verification requests, pay-with authorisations, provider applications and creator claim challenges. Verified and, for a provider application or a pay-with authorisation, stored. | The provider and pay-with tables described above. |
| src/blind/routes.ts | Payments or signatures | A blinded token request. Signed by the issuer. | Nothing that links the buyer to the token. |
| src/tlog/routes.ts | Public data | A signed checkpoint note from a witness (16 KB at most). Verified and stored as a cosignature. | tlog_cosignatures. |
| src/api/agent-stop-all.ts | Settings | Optional Stop reason and absolute until time for bulk Stop. Authenticated owner/admin/management authority and current account/team rulebooks. Rechecks current role, scope, expiry and session authority within the account-locked transaction; changes only permitted agents through the existing per-agent changeKill operation. Returns the number changed. | Uses existing agent_policies Stop fields, updated time and actor, hash-chained agent_policy_events, and existing alert/security records and notification preferences. Reason is stored in killed_reason as on individual Stop. No new table, column, Redis family or log field; no inference prompt or answer reader. |
| src/telegram/agent-stop-all.ts | Settings | Private human Telegram /stopall and /startall text and user/chat identifiers. Current linked account/key authority, role/team/scope and expiry; optional duration preset. Rechecks authority under the existing link and account locks. Telegram receives changed-agent counts, confirmations and UTC tomorrow deadlines; Telegram can read them and applies its retention policies. | Raw command text is not copied to storage. Reuses the telegram-link callback limiter family and existing link records, policy Stop fields, policy events and alert/security records with existing retention and notification preferences. No new table, column, Redis family, log field or button state; no API secret, wallet address or inference prompt reader. |
| src/telegram/menu.ts | Settings | Private human /menu messages, Telegram user/chat identifiers and callback action plus link generation. Reads the existing link and current principal authority. Delegates to existing balance, spend, agent list, Stop all and approval readers with their existing permissions. Sends readable command replies and inline buttons to Telegram, which can read them and applies its retention policies. Inbox and Settings buttons open the configured site URL at the existing dashboard sections and carry no credential. Approval-only teammates may open the menu but retain their existing approval-only permissions. Each delegated command checks the generation at its authoritative link read. Waiting approvals reuses delivery.ts, current approver visibility, the approvals Telegram switch and deferTelegram; approvals retain the existing immediate-delivery exception to quiet hours. | No new table, column, Redis family, log field or durable menu state. Process-local WeakMap metadata binds a delegated update to its generation only while the update is reachable. Reuses the existing telegram-link callback limiter. Explicit approval listing sends up to ten oldest pending, unexpired approvals, including previously delivered ones, and refreshes their existing telegram-approval message_id and status markers. Successful refresh replaces the old message and reminder bindings; failure preserves existing markers. Existing marker expiry, unlink deletion and atomic single-use decision rules apply. No raw menu or reply text is persisted. No API key secret, wallet address or inference prompt is read by the menu; ordinary inference paths still read request text in router memory. |
A caller’s network address
| Where | What is read, and what happens | What is kept |
|---|---|---|
| src/key-ip/allowlist.ts | The existing trusted client-IP helper for API keys with owner-set IP restrictions and for the authenticated current-IP helper. Both Bearer and x-api-key credentials are checked. No address is read on onion or Oblivious HTTP ingress. In-process adapters retain the verified originating address for the same key in asynchronous request-scoped memory, rechecking its current allowlist at every hop. Compares IPv4, IPv6 and CIDR ranges in request memory and refuses a mismatch before routing or charging. The current-IP endpoint echoes the selected address once with Cache-Control: no-store. Unknown addresses fail closed. Scheduled and batch inference has no verifiable originating client IP and is refused for restricted keys. | The observed caller address is never stored or logged by this feature. Only the owner-supplied allowlist is retained in keys.allowed_ips under existing key retention. The browser editor holds entered addresses and a requested current-IP response in component memory until the dialog closes; saving stores the selected list as owner settings. Existing ingress limiter retention remains unchanged. No new Redis key family or log field. |
| src/hardening/client.ts | The socket address, trusted X-Forwarded-For hop selected from the right by TRUST_PROXY_HOPS, and CF-Connecting-IP only when the enabled origin lock secret matches. The socket is also read to exempt direct private-network callers without forwarding headers from ingress guards. Validates IP syntax, selects the trusted client address for existing limiters, and rejects public forwarding traffic from private-socket exemptions. No caller address is read for authenticated Tor ingress. | Address held in request memory and anonymous Redis counter keys for 61 seconds. Existing limit families retain their lifetimes. No database or log address field. |
| src/hardening/middleware.ts | Existing per-address bucket for anonymous public API reads and MCP messages; all Tor callers use onion. Counts against anon with the configured minute limit. Keyed requests, health and readiness, and internal callers are exempt. Redis failure permits the call and logs a fixed warning. | Counter only; 61 seconds in Redis or until the memory limiter sweep. Never a prompt, key, header, secret or address in logs. |
| src/facilitator/routes.ts | The caller address bucket on every /facilitator route; over Tor the shared onion bucket. Counts requests in the facilitator's own per-address limiter; trusted proxy and onion rules apply. | Raw address in the limiter key for 61 seconds in Redis, or until the memory limiter sweeps; never in a settlement, listing, receipt or log line. |
| src/api/network-hosts.ts | The caller address bucket on host signup and credential writes. Counts attempts through the existing per-address limiter; trusted proxy and onion rules apply. | Raw address in the limiter key for 61 seconds in Redis, or until the memory limiter sweeps; never in the host row or application log. |
| src/network/waitlist.ts | Address bucket for a waitlist POST or DELETE; onion requests use the shared onion bucket. A secret-keyed HMAC of the address and current minute is passed to the existing limiter; onion stays the word onion. | Only a minute-specific keyed digest and counter: 61 seconds in Redis, or up to six minutes without Redis until the memory limiter sweeps old windows. No raw IP or user agent, and no address-derived value in the waitlist table. |
| src/api/e2ee.ts | The address only for encrypted calls without a key outside the Oblivious HTTP gateway; over Tor the fixed onion bucket is used. Uses the existing blind-ip rate-limit family. | Only the counter key, for 61 seconds; no address in a generation, receipt or log. |
| src/api/common.ts | The selected client address from the shared ingress helper: socket by default, the trusted hop counted from the right when TRUST_PROXY is on, or CF-Connecting-IP when the enabled origin lock secret is valid. Returned to a caller as the key of a per-address rate limit. Requests that arrived over Tor get the fixed word onion instead of an address (addressBucket). | Not written to Postgres and not logged. It exists in Redis only as part of the rate-limit keys listed above, for at most an hour. |
| src/api/chat.ts | The caller's address, only for a call that carries no API key and did not arrive through the Oblivious HTTP gateway. Counted against ip:<address> (or blind-ip:<address> for a blind token). | Only as the Redis rate-limit key. |
| src/api/embeddings.ts | The caller's address, only for a call without an API key. Counted against ip:<address> or blind-ip:<address>. | Only as the Redis rate-limit key. |
| src/api/rerank.ts | The caller's address, only for a call without an API key. Counted against ip:<address> or blind-ip:<address>. | Only as the Redis rate-limit key. |
| src/api/keys.ts | The caller's address when a key is created and when a wallet sign-in challenge is requested. Counted against newkey:<address> and wallet-login:<address>. | Only as the Redis rate-limit keys. |
| src/api/teams.ts | The caller's address when joining a team or signing in to one with a passkey or wallet (no API key yet). Counted against team-auth:<address>. | Only as the Redis rate-limit key. |
| src/api/paymaster.ts | The caller's address on a paymaster request. Counted against pm:<address>. | Only as the Redis rate-limit key. |
| src/ohttp/gateway.ts | The caller's address, only for a request that did not come through an authenticated relay. A request through a relay is counted by the relay's key id instead. Counted against ohttp-gw:ip:<address>. | Only as the Redis rate-limit key. |
| src/tlog/routes.ts | The submitter's address when a witness posts a cosignature. Counted against tlog-cosign:<address>. | Only as the Redis rate-limit key. |
| src/api/creator-claims.ts | The caller's address when a creator claim is issued or verified. Handed to services/creators.ts as an address bucket. | Only as the Redis rate-limit keys. |
| src/services/creators.ts | The address bucket it was given. Counted against claim-issue-ip:<address> and claim-verify-ip:<address>. | Only as the Redis rate-limit keys. |
| src/api/responses.ts | The caller's address, so the internal chat call it makes on the caller's behalf is limited exactly as the caller's own call would be. Passed to the chat route as an in-process value (requestIP) and then handled as in src/api/chat.ts. | Nothing beyond what src/api/chat.ts keeps. |
| src/ollama/routes.ts | The caller's address, so the internal chat or embeddings call it makes on the caller's behalf is limited exactly as the caller's own call would be. Passed to the chat or embeddings route as an in-process value (requestIP) and then handled as in src/api/chat.ts. | Nothing beyond what src/api/chat.ts keeps. |
| src/onion/ingress.ts | Nothing. It deletes every header that names a client address (X-Forwarded-For, X-Real-IP, CF-Connecting-IP and others) from requests that arrived over Tor, before any route runs. Requests over Tor therefore carry no client address for a route, a limiter or a log line to use. | Not applicable. |
| relay/src/relay.ts | The separate Oblivious HTTP relay (run by relay operators, not by the router) forwards a request's body to a gateway without any header, address or cookie of the client. The forwarded request is built from configuration and the body only. The relay's automated checks fail if its source logs a request or reads a client address. | The relay keeps counters only: totals and fixed reason labels. |
| sidecar/src/headers.ts | The model-server sidecar inside a provider's enclave forwards only allow-listed headers, so a proxy header cannot carry a client address to the model server. Forwarded by allow-list, not deny-list; a header that names a network address is refused even in configuration. | Not applicable. |
Redis.
Redis holds rate-limit counters, the opt-in response cache, the sealed answers of x402 calls kept 24 hours for payment recovery, replay markers and the job queue. It is optional in development and required in production. Every key expires; the rate-limit keys below are the only place a caller's network address is used, and only for calls without an API key.
| Key | What it is for | Part of the key | Lives for |
|---|---|---|---|
idempotency:<sha256>src/idempotency/store.ts | Opt-in retry protection for API-key inference calls with Idempotency-Key. The key hashes account id, API key hash and the caller's idempotency key. AES-256-GCM ciphertext under APP_SECRET and this scope contains a canonical request-body and endpoint hash, an ownership marker, and the final status, reply and receipt headers. The request body and raw idempotency key are not stored. Replies can echo request text. Stream replies are not retained; a completed marker keeps status and receipt headers instead. An unfinished call or failed retention leaves an in-progress marker; retries never run inference again while it remains. Redis failure refuses a new protected call before billing. No new database row or log field is added. | A SHA-256 digest | 86,400 seconds (24 hours) from the first request; completion does not extend it. Redis deletes the entry at expiry. After expiry the same key starts a new billable call. |
rl:anon:<caller address or onion>:<window start>src/hardening/middleware.ts | Anonymous public API reads and MCP messages share one per-client minute counter. Valid API keys retain their existing limits. Tor shares a separate onion counter with ONION_POOL_MULTIPLIER times the limit. Authenticated in-process dispatch and direct private-network traffic without forwarding headers are exempt. | The caller's network address | 61 seconds (the 60-second window plus one second) |
rl:tools-call:<key hash>:<window start>src/tools/call.ts | Paid tool calls per minute for one API key (60). | A SHA-256 of an API key | 61 seconds (the 60-second window plus one second) |
rl:tools-list:<account id>:<window start>src/tools/routes.ts | Tool listings per hour for one account (20); each listing asks the tool for its quote. | An account id | 3,601 seconds (the 3,600-second window plus one second) |
rl:agent-pay:<key hash>:<window start>src/api/agent-pay.ts | Payment confirmations and reads per minute for one agent key (60); each can read the chain. | A SHA-256 of an API key | 61 seconds (the 60-second window plus one second) |
rl:wallet-link:<account id>:<window start>src/api/linked-wallets.ts | Limits wallet link challenges to thirty per account per minute. | An account id | 61 seconds (the 60-second window plus one second) |
rl:agent-certificate:<account id>:<window start>src/api/agent-certificates.ts | Record-certificate and track-record issuance attempts: five per minute per account, shared across standalone, profile and track-record issuance, its keys and router replicas. Contains only the account id and a counter; no certificate pseudonym, claims or stats. | An account id | 61 seconds (the 60-second window plus one second) |
rl:agent-replay:<caller key hash>:<window start>src/api/agents.ts | Rulebook replays (POST /api/v1/agents/:key_hash/replay), ten per minute per calling key. Contains only the caller's key hash and a counter; no draft, call or result. | A SHA-256 of an API key | 61 seconds (the 60-second window plus one second) |
rl:agent-feedback:<account id>:<window start>src/identity/routes.ts | Paid-feedback submissions, thirty per minute per reviewing account. Contains only the account id and a counter. | An account id | 61 seconds (the 60-second window plus one second) |
rl:proof-pack:<key hash>:<window start>src/api/proof-pack.ts | Proof pack downloads, ten per minute per API key. Contains only the key hash and a counter. | A SHA-256 of an API key | 61 seconds (the 60-second window plus one second) |
rl:lane-report:<key hash>:<window start>src/api/lane-report.ts | Lane reports, thirty per minute per API key. Contains only the key hash and a counter. | A SHA-256 of an API key | 61 seconds (the 60-second window plus one second) |
rl:telegram-link:<action>:<account or Telegram user id>:<window start>src/telegram/linking.ts | Account link-code issuance (five per minute per account), code consumption (ten per minute per Telegram user) and approval callbacks (twenty per minute per Telegram user). Only identifiers and counters, no code or message text. | A Telegram user id | 61 seconds (the 60-second window plus one second) |
rl:facilitator:<caller address or onion>:<window start>src/facilitator/routes.ts | Facilitator requests per caller address per minute (FACILITATOR_RPM, 120 by default), a bucket apart from the API's. The raw address is part of the key; over Tor the shared onion bucket is used. | The caller's network address | 61 seconds (the 60-second window plus one second) |
rl:facilitator-payer:<payer wallet>:<window start>src/facilitator/routes.ts | Verify and settle calls per payer wallet per minute, so one payer cannot drain the relay with tiny payments. Links calls by the public payer wallet. | A wallet address | 61 seconds (the 60-second window plus one second) |
rl:facilitator-seller:<payTo wallet>:<window start>src/facilitator/routes.ts | Verify and settle calls per seller payTo wallet per minute. | A wallet address | 61 seconds (the 60-second window plus one second) |
rl:facilitator-listing:<payTo wallet>:<window start>src/facilitator/routes.ts | Signed listing writes per payTo wallet per hour (FACILITATOR_LISTINGS_PER_HOUR). | A wallet address | 3,601 seconds (the 3,600-second window plus one second) |
rl:network-host-wallet:<operator wallet>:<window start>src/api/network-hosts.ts | Wallet-authenticated host signup and credential updates, three per minute per wallet. Links attempts by the public operator wallet. | A wallet address | 61 seconds (the 60-second window plus one second) |
rl:network-host-address:<caller address or onion>:<window start>src/api/network-hosts.ts | Host signup and credential attempts, ten per minute per network address, with the existing scaled shared onion bucket. The raw address is temporarily part of the Redis key. | The caller's network address | 61 seconds (the 60-second window plus one second) |
rl:network-waitlist:<minute-keyed address digest or onion>:<window start>src/network/waitlist.ts | Waitlist POST and DELETE requests, ten per minute per address; onion requests share the existing scaled onion bucket. A secret-keyed HMAC rotates every minute; no raw IP or user agent is stored. The digest still links requests within that minute. | A SHA-256 digest | 61 seconds (the 60-second window plus one second) |
rl:ip:<caller address>:<window start>src/api/chat.ts | Requests per minute for a call that carries no API key. The caller's network address is part of the key. Over Tor the address is replaced by the word onion, so no address is used. | The caller's network address | 61 seconds (the 60-second window plus one second) |
rl:blind-ip:<caller address>:<window start>src/api/chat.ts | Requests per minute for a call paid with a blind token. The caller's network address is part of the key. Over Tor the address is replaced by the word onion, so no address is used. | The caller's network address | 61 seconds (the 60-second window plus one second) |
rl:newkey:<caller address>:<window start>src/api/keys.ts | New API keys per hour. The caller's network address is part of the key. Over Tor the address is replaced by the word onion, so no address is used. | The caller's network address | 3,601 seconds (the 3,600-second window plus one second) |
rl:wallet-login:<caller address>:<window start>src/api/keys.ts | Wallet sign-in challenges per minute. The caller's network address is part of the key. Over Tor the address is replaced by the word onion, so no address is used. | The caller's network address | 61 seconds (the 60-second window plus one second) |
rl:team-auth:<caller address>:<window start>src/api/teams.ts | Team join and sign-in attempts per minute (passkey or wallet), which need no API key. The caller's network address is part of the key. Over Tor the address is replaced by the word onion, so no address is used. | The caller's network address | 61 seconds (the 60-second window plus one second) |
rl:pm:<caller address>:<window start>src/api/paymaster.ts | Paymaster requests per minute. The caller's network address is part of the key. Over Tor the address is replaced by the word onion, so no address is used. | The caller's network address | 61 seconds (the 60-second window plus one second) |
rl:ohttp-gw:ip:<caller address>:<window start>src/ohttp/gateway.ts | Oblivious HTTP gateway requests per minute from a client that did not come through an authenticated relay. The caller's network address is part of the key. Over Tor the address is replaced by the word onion, so no address is used. | The caller's network address | 61 seconds (the 60-second window plus one second) |
rl:ohttp-gw:relay:<relay key id>:<window start>src/ohttp/gateway.ts | Oblivious HTTP gateway requests per minute for one authenticated relay. It names the relay, not the clients behind it. | Nothing personal | 61 seconds (the 60-second window plus one second) |
rl:tlog-cosign:<caller address>:<window start>src/tlog/routes.ts | Transparency-log cosignature submissions per minute. The caller's network address is part of the key. Over Tor the address is replaced by the word onion, so no address is used. | The caller's network address | 61 seconds (the 60-second window plus one second) |
rl:claim-issue-ip:<caller address>:<window start>src/services/creators.ts | Creator claim challenges per hour. The caller's network address is part of the key. Over Tor the address is replaced by the word onion, so no address is used. | The caller's network address | 3,601 seconds (the 3,600-second window plus one second) |
rl:claim-verify-ip:<caller address>:<window start>src/services/creators.ts | Creator claim verifications per hour. The caller's network address is part of the key. Over Tor the address is replaced by the word onion, so no address is used. | The caller's network address | 3,601 seconds (the 3,600-second window plus one second) |
rl:k:<key hash>:<window start>src/api/chat.ts | Requests per minute for one API key. Keyed by the SHA-256 of the key; no address is read for a call that carries a key. | A SHA-256 of an API key | 61 seconds (the 60-second window plus one second) |
rl:kc:<key hash>:<window start>src/api/anthropic.ts | Requests per minute for one API key on the Anthropic-compatible endpoint. | A SHA-256 of an API key | 61 seconds (the 60-second window plus one second) |
rl:kt:<key hash>:<window start>src/api/chat.ts | Tokens per minute for one API key: a running count of prompt tokens, not their text. | A SHA-256 of an API key | 61 seconds (the 60-second window plus one second) |
rl:skills-import:<key hash>:<window start>src/api/skills.ts | Skill imports per hour for one API key (each import may fetch a repository and runs the scanner). | A SHA-256 of an API key | 3,601 seconds (the 3,600-second window plus one second) |
rl:blind:buy:<key hash>:<window start>src/blind/purchase.ts | Blind-token purchases per minute for one API key. | A SHA-256 of an API key | 61 seconds (the 60-second window plus one second) |
rl:provider-applications:<window start>src/providers/application.ts | Provider applications per minute, counted across all callers in one key. There is no per-caller part. | Nothing personal | 61 seconds (the 60-second window plus one second) |
rl:claim:<model id>:<window start>src/api/public.ts | Creator claims per hour for one model. | A model id | 3,601 seconds (the 3,600-second window plus one second) |
rl:claim-issue:<model id>:<window start>src/services/creators.ts | Claim challenges per hour for one model. | A model id | 3,601 seconds (the 3,600-second window plus one second) |
rl:claim-verify:<claim id>:<window start>src/services/creators.ts | Claim verifications per hour for one claim. | Nothing personal | 3,601 seconds (the 3,600-second window plus one second) |
rl:telegram:<Telegram user id>:<window start>src/services/telegram.ts | Telegram bot messages per minute for one Telegram user. The user id is a number Telegram assigns; the message text is not part of the key. | A Telegram user id | 61 seconds (the 60-second window plus one second) |
rl:readiness:<window start>src/services/readiness.ts | The readiness probe checks the limiter works by taking zero from a fixed key. | Nothing personal | 61 seconds (the 60-second window plus one second) |
cache:<sha256>src/gateway/cache.ts | The opt-in response cache (a request that sends cache.mode or the X-Anyroute-Cache header). It holds the answer to a request, so for as long as it lives this is a place answer text is kept: sealed with AES-256-GCM under a key derived from the router's APP_SECRET and the caller's own scope, so only that caller's identical request can read it back. The Redis key is a SHA-256 of the scope and the request, not the request. | A SHA-256 digest | It is kept for the time-to-live the request asked for in cache.ttl: at most CACHE_TTL_S, which is 3,600 seconds unless the operator changed it, and also the default when the request names none. |
walletauth:<sha256>src/api/auth.ts | Replay protection for wallet-signed requests: a marker that a signature was already used. The key is a SHA-256 of the wallet address, the timestamp and the request's hash. | A wallet address | 600 seconds |
batch:<batch id>:in and batch:<batch id>:outsrc/services/batches.ts | The Batch API (POST /api/v1/batches). A batch's requests (:in) and its answers (:out), one field per line, each sealed with AES-256-GCM under a key derived from the router's APP_SECRET, the batch id and the hash of the key that sent it, so only that key's batch can read them back. They are kept here, never in the database, so the worker can run the lines and the key can fetch the results. | Nothing personal | The sealed requests are deleted when the batch finishes; the sealed answers BATCH_RESULTS_TTL after that (86,400 seconds, 24 hours, unless the operator changed it). A batch that never finishes ends when its 24-hour completion window closes, so nothing outlives the window plus that time. |
bull:anyroute-jobs-<group>:*src/services/jobs.ts | The background job queue (BullMQ) that makes exactly one replica run each recurring job. The job data is empty ({}), so no request or user data is in it; a finished job's result or failure message is kept for the last 100 completed and 100 failed jobs. | Nothing personal | Recurring job schedules stay while the router runs; only the most recent 100 completed and 100 failed jobs are kept. |
x402paid:<sha256>src/pay/recovery.ts | x402 payment recovery. The answer to a call paid with x402, kept so the payer can have it sent again, byte for byte, if it was lost on the way (PAYMENT-RECOVERY), instead of paying twice. It is sealed with AES-256-GCM under a key derived from the router's APP_SECRET, the payer, the authorization nonce and the request's hash, so only a recovery of that exact request by that payer can open it. The key is a SHA-256 of the payer and the nonce. | A SHA-256 digest | 86,400 seconds (24 hours) from the answer, set when it is written; the x402-recovery-expire job also deletes it with its row. Calls not paid with x402 leave nothing here. |
Without Redis (development): Without Redis (development) the same rate-limit counters live in the router process's memory and are removed once their window started more than five minutes ago (checked every minute). Nothing is written to disk.
Logs.
The router writes one JSON line per event to standard output (standard error for warnings and errors). A line is a time, a level, a fixed message and a few fields chosen at each call site. No call site writes a request or response body, a header, a client address, a query string or a prompt.
What a line can carry
- A provisional deposit reversal logs its durable chain/lane/transaction/log identifier once when the reversing ledger entry commits. A separate durable check per reversal enters the existing operator alert notifier; notifications require an operator webhook and are at-least-once on delivery failure or a crash.
- The time, the level and a message written in the code.
- Anonymous limiter failure: fixed warning that a request was allowed; no exception, address, header, key or body.
- Host slash dry-run intent: provider id, evidence commitment root, proposeSlash function name, whole-bond USDG amount, numeric contract reason, contract and chain id, bytes32 host id and delist flag. Logged once per evidence root; no signed bytes, key, raw quote or receipt envelope.
- Sanctions refresh counts (distinct EVM entries, ignored formats and digital currency entries), publication date and source hash; screening skip/refusal reasons and provider ids. Freshness exceptions for previously paid addresses and refresh failures use fixed reason codes. No payout wallet or identity fields are added to these logs.
- Identifiers and counts: provider ids, model ids, job names, hold and generation ids, epochs, block numbers, transaction hashes, hashed key ids and, on rare settlement and escrow events, an account id.
- Wallet addresses of payers on pay-per-call and pay-with events (public on chain).
- For an unhandled error: the path of the request without its query string, the error message and the first five lines of the stack.
- Error messages from libraries and upstream services, each cut to 200 characters where a call site truncates them. Configured private chain RPC URLs, including paths and queries on the same host, are redacted before log emission; chain transport failures are redacted before callers truncate them.
What the code never passes to the logger
- Client network addresses. No log call passes one; addresses are used for rate limits and direct private-network ingress checks. src/api/common.ts
- Request or response bodies and prompts. The unhandled-error line takes the path and the error, not the body. src/app.ts
- Request headers, cookies and API keys. The Telegram bot states the same rule for its own lines. src/services/telegram.ts
- Query strings: only the pathname of a failing request is logged. src/app.ts
What this cannot promise
- The text of an unexpected exception is logged as the library wrote it (src/app.ts unhandled error, src/lib/process-guard.ts uncaught exception, job failures). No code path puts request text into an error message on purpose, but only configured private chain RPC URLs are filtered, and a library error could quote a fragment of what it was parsing.
- The hosting platform's own network layer sees connection addresses and may keep its own access logs. This inventory covers what the router's code records; it cannot describe the platform's logs.
Retention. The router does not rotate or store its logs: it writes them to standard output and the hosting platform keeps them under its own retention. No log retention is set in this repository. Format. JSON lines: { t, level, msg, ...fields }.
Other places data lives.
Approval context summaries
Help already authorized approvers decide with existing agent metadata.
- Holds
- No new storage, schema, Redis family, log field, address or request-body reader. Reads existing keys, ledger posted charges, current agent policies and autonomy, agent approvals requested since Monday UTC, retained duplicated events and key-rotation links. Builds optional approval_context lines in response memory for approval lists and inbox items the caller may decide; the same builder supplies linked Telegram approval messages and reminders. Telegram receives spend, caps, estimated spend if used, current work-hour status, weekly counts and duplicate or rotation notes when AGENT_APPROVAL_CONTEXT_ENABLED is enabled (default false), through existing notification preferences, quiet hours and approver guards. No prompts, tool arguments, source names or key hashes are added to the text.
- Lives for
- The summary is not saved by the router. Telegram retains delivered messages under its own policy. Existing source retention applies, including the 90-day agent-event pruning. Ordinary request text is still read by the router in memory.
Agent status view
Compose existing agent metadata for the authenticated policy audience.
- Holds
- No new durable data. Reads current and inherited agent_policies Stop/timed Stop and work_hours, unexpired agent_approvals counts for this key, the existing per-key runway ledger/autonomy readers, and existing quiet-agent-alert kv settings plus the quiet worker’s ledger and Guard activity including session keys. Guard stops are derived only from saved action-restriction reason codes. No new table, column, Redis family, log field, body reader or address reader. Ordinary inference request text is still read in router memory.
- Lives for
- Response uses no-store. The browser holds the current status in component memory until refreshed, disconnected or unmounted; nothing is written to browser storage. Existing source retention is unchanged.
Key replacement links
Links retired and replacement account-backed keys while the existing expiry guard ends the old key's access. The account lock serializes rotation. Account-wide notification choices and linked Telegram chats continue on the same account.
- Holds
- key-rotation:<key hash> in kv stores from and to key hashes, at, grace_ends_at and history_key_hash. The replacement keeps the old key's settings, team membership and principal, current policy and saved policy_versions (including saved-by attribution and dates), agent approvers, quiet-alert hour choice and spend-alert rules including sealed webhook destinations. Usage, delivery history, existing agent approvals and spend records stay with the old key. Quiet-alert delivery state and spend-alert history restart for the replacement. The security-alerts event stores a sanitized Key rotated title and actor under its existing family, and uses the existing security_alerts notification type, preferences and quiet-hour delivery. Browser sign-ins, Telegram link credentials and attestation records are not cloned; there is no new address reader, Redis family or log field.
- Lives for
- Rotation links remain with key history until account data is removed. Copied settings use the existing tables' retention. The secret exists in router response memory and the browser's reveal state until dismissed; it is never persisted by the rotation interface.
Independent agent settings copy
An explicit owner action makes a fresh key on the same account balance; it copies configuration, not runtime state.
- Holds
- Existing keys columns retain the new name, account and creating parent key hashes, scope, management rights, project, team, limits/reset, expiry, allowed models/IPs, rate limits, routing, guardrails, sealed tracing destination and auto top-up. Existing agent_policies and policy_versions keep the current readable rulebook including work_hours and saving caller hash. Existing agent_policy_events retains the readable source-name note. Existing kv agent-approvers:<new key hash> retains approval authority settings, quiet-agent-alert:<new key hash> retains the hour choice and new enable time with empty notices. Team creation audit records use the existing key.create fields. Agent duplicated titles use the existing security-alerts:event family and security_alerts channel preferences and Telegram quiet-hour delivery. No new Redis family, log field, table, column or address reader is added. Spend/history, approvals, disabled/Stop state, rotation links, Telegram credentials, browser sign-ins, principal bindings, public profiles, attestation and per-key spend-alert destinations are not copied. Account notification settings and account-linked Telegram deliveries still apply.
- Lives for
- Copied configuration follows existing table retention, until operator deletion; the new event log follows its existing 90-day pruning. The source-name note remains on that new event, not on saved revisions. A fresh secret exists in router response memory and browser component state until dismissal, switching agents, disconnecting or navigation; the duplication interface never writes it to browser storage. Ordinary inference request text is still read by the router in memory.
Approval reminder claims
Remind currently authorized decision makers once before a pending agent approval expires; highlight its existing inbox row.
- Holds
- approval-nudged:<approval id> in kv stores the claim time and approval expiry time. Existing telegram-approval:<approval id>:<Telegram user id>:<link generation> values additionally store reminder_message_id, the reminder's Telegram message identifier; original and reminder buttons use the same single-use approval. notification-prefs:<account id> adds Inbox and Telegram booleans for approval_reminders, both on by default. No new table, column, Redis family, log field, address or body reader. Reminder text uses existing readable approval metadata: agent name, routing or action identifiers, amounts and rulebook summaries, never prompt or answer text. Telegram can read delivered details. The router reads ordinary request text in memory.
- Lives for
- APPROVAL_NUDGES_ENABLED defaults false. Enabled non-API workers inspect up to 100 eligible approvals each minute. Claims commit before outbound delivery, preventing repeats across concurrent workers. Each current linked recipient is attempted once, with current authority and channel settings checked under the link and account locks. Quiet hours never delay reminders. A crash after claiming, an unavailable destination or a failed send can lose a reminder; it is not retried. Claims are deleted after approval expiry by enabled ticks, and pause while off; decided claims remain until expiry. Existing Telegram notices are pruned by Telegram delivery after expiry or unlinking. Preferences remain until changed or removed. The inbox countdown appears only to current decision makers, only while pending and unexpired, and uses existing approval response fields. No expiry or approval consumption changes.
Signed-in browser labels
Account management keys can list their own active wallet-issued browser keys in Settings. A single sign-out uses the existing key-disable path; signing out all others sends one disable request per listed other browser after one confirmation. The caller's key is excluded from that selection. There is no new worker, flag, table, column, Redis family or log field.
- Holds
- browser-session:<key hash> in kv keeps only a fixed browser-family and operating-system label derived from User-Agent at wallet sign-in. No full header, version, device model or network address is retained by this feature. Rows remain after sign-out because existing keys are disabled, not deleted; retained until operator deletion. Existing keys.created_at records sign-in, and keys.last_used records the last charged call, not browsing or every API request. Older wallet-issued root management keys have no browser label. Sub-keys, team keys and agent sessions are excluded from the browser list. User-Agent is read in memory during the existing wallet sign-in route. The browser holds session metadata and pending confirmation in component memory; no new browser storage. Existing sign-in and key-disable security alerts still apply.
- Lives for
- Labels remain until operator deletion. Disabled and expired keys disappear from the list. Signing out this browser clears its saved key after server confirmation. Bulk sign-out can partly succeed; failed rows remain visible for retry. Already-running requests may finish, and an owner can re-enable a disabled key using existing key management.
Quiet-agent settings, inbox notices and Telegram delivery
With QUIET_AGENT_ALERTS_ENABLED and agent rulebooks on, a five-minute non-API worker reads saved settings, current keys and Stop state, existing charged ledger timestamps (usage/tool_call/data_tool) and Guard decision timestamps, including agent session children in the same account. Disabled, expired and stopped keys are excluded. A keyset scan covers settings in pages of 100. Per-agent claims commit under the account lock before sending. A new activity timestamp re-arms the alert, with no writes on the call path. Free uncharged generations and rulebook previews do not count. The clock begins at the last recorded activity, or enable time when no activity is recorded. Resumed keys become eligible using the existing clock.
- Holds
- quiet-agent-alert:<key hash>: per-agent hours (null means off), enable timestamp, last claimed quiet-period activity timestamp, and newest 100 notices with random id, timestamp, readable agent-name title, hour window and last charged-call/Guard-decision time. Settings and the dedupe anchor persist until operator deletion. Enabled runs and changed settings prune notices older than 90 days; disabled cleanup pauses, while inbox reads hide expired notices. Deleted keys leave inaccessible settings until operator deletion. No rulebook field, table, column, Redis family, address reader or log field is added. The account inbox exposes these notices only to management keys and team owner/admin principals outside sessions, scoped by current account/team ownership. The browser keeps settings and save status in component memory only. Agent names enter readable notice titles and Telegram messages; user-chosen names can contain personal text. No inference prompt, answer, action target, Guard details, wallet address or API secret is read by this feature.
- Lives for
- History is bounded to 100 per agent and 90 days when cleanup runs. Settings and notified_for remain even while off. Saving or changing the choice preserves the last claimed activity timestamp; only later activity re-arms a previously reported period. Telegram uses existing linkedAlertTargets/sendLinkedAlert and their current principal checks and unlink lock. One attempt per eligible link after each saved claim; a crash or failed send can lose delivery with no retry. No message id or send-result metadata is added.
Account security changes and delivery cursor in kv
With SECURITY_ALERTS_ENABLED, existing key rows, agent policy events and team audit writers record security changes, including those made by the signed-in key. A thirty-second worker claims pending events once, adds inbox items and attempts Telegram delivery through the existing linked-alert helper. Management keys see their account; team owners and administrators see only their team; ordinary and session keys see no security items. Account preferences default on while the feature is enabled.
- Holds
- security-alerts:event:<change id, policy event id, or team id and sequence> holds account id, nullable team id, inbox-arrival timestamp (recording time while pending), readable title and pending/inbox/muted state. Titles contain sanitized key and team names, management status, the kind of change and the acting key name. The request middleware holds only a digest of the presented Bearer key in an asynchronous request scope to correlate the already-authenticated team audit writer with its exact acting key; no credential is retained. Team audit entries authenticated by wallet or passkey name that member type instead of inventing a key. Wallet sign-in reads the already-verified account wallet in memory, keeping only its first six and last four characters in a sign-in title. Full wallet addresses, key secrets, prompt text, policy contents, stop reasons and Telegram messages are not copied. security-alerts:cursor keeps a processed-event count and lock; per-event states are the durable cursor so late commits and equal timestamps remain eligible. security-alerts:preference:<account id> keeps the enabled boolean. Telegram can read the security titles and key names it receives. Unlinked members receive no later alert, including their unlink notice; other eligible links may receive it.
- Lives for
- Claimed and muted event rows are removed after ninety days by enabled worker runs; pending events remain until claimed. Flag off pauses recording, delivery, inbox projection and cleanup. Events from before recording was enabled are not reconstructed. Preference and cursor rows remain until removed. Claims commit before one send attempt per eligible link: worker crashes, failed and ambiguous sends can leave an inbox item without Telegram delivery; sends are not retried. Key change hooks use the existing write boundaries; changes whose key write commits but notice write fails can miss a notice. Policy, team audit and Telegram notices commit with their source transaction. No new database table/column, Redis family or log field; the settings route is the only new request-body reader.
Account notification settings and encrypted quiet-hour queue
One account page controls Inbox and Telegram for approvals, agent alerts, credited deposits, low balance, weekly summaries, security changes, quiet agents, model rate changes, project budgets, scheduled results and approval reminders. Underlying activity and approval records are retained. Feature flags and existing feature choices still apply. Inbox is filtered at read time; weekly Inbox, off by default, projects the latest completed week from existing records for management keys.
- Holds
- notification-prefs:<account id> stores channel booleans and nullable from_utc/to_utc daily clocks. Weekly Telegram reads and writes only existing telegram-link weekly_summary_opted_in columns, and security Inbox/Telegram use the existing security-alerts:preference value with enabled as their aggregate for recording; the older security switch replaces that value and controls both. notification-quiet:<random id> stores account id, Telegram user id and link generation, source and principal key hashes, team id and management snapshot, notice category, due/creation times, a legacy-link marker and text encrypted under APP_SECRET. Text includes notice names and amounts, and can include scheduled answer previews. The router can decrypt these previews; Telegram can read delivered messages. No inference credential, new Redis key, address reader or log field is added. Browser component memory holds the settings and current local clock conversion; nothing new enters browser storage.
- Lives for
- Preferences remain until changed or removed. NOTIFICATION_QUIET_HOURS_ENABLED defaults false: only the enabled minute worker queues and flushes delayed Telegram notices. Approvals and approval reminders are never queued. Each tick reads at most 500 queue entries and sends one bounded-excerpt bundle per recipient and generation; larger backlogs can yield later bundles. Successful delivery removes entries; muted, revoked, unlinked or changed-scope entries are discarded. Failed sends remain for a later attempt. Entries older than seven days are discarded by enabled ticks; flag off pauses queue delivery and cleanup. Delivery can repeat after Telegram accepts a message before transaction commit. The worker revalidates current link, role, team, management status, source key ownership and scheduled-result owner rights. A source feature switched off pauses its queued notices until enabled or expired. Existing sender success counters treat skipped channels or durable queue acceptance as acknowledged delivery. Weekly last_sent_week is marked when a summary enters the queue; a later discarded summary is not resent. Daily clocks are saved in UTC using the device's current offset; saving again is needed after clock or time-zone changes. Future Telegram links retain the existing weekly opt-in default.
Watching settings in browser memory
J180: read-only composition of existing account notification, model watch, agent rulebook, quiet-agent, project budget, balance threshold and schedule GET readers. Each reader keeps its existing authorization and feature guards.
- Holds
- Existing responses pass through browser memory, including names, public model ids, key hashes, inherited alert rules, monthly budgets, balance thresholds, cadence, maximum run costs and channel preferences. The existing schedules list also returns decrypted prompt text; the composition discards it and retains only active schedules' names, ids, cadence, UTC clock and maximum cost for display. Summary rows and per-reader failure states are held only in React component memory. No new database table or column, Redis key family, application log field, body/address reader, browser storage, outbound notice or server snapshot is added. The router still reads ordinary inference requests in memory.
- Lives for
- Component state is replaced on refresh and cleared on account change or unmount. In-flight requests are aborted on change or unmount; no durable copy is created by this view. Existing source storage and retention are unchanged.
Retry protection without Redis
The same opt-in retry guard and encrypted reply as Redis, scoped to this router process only. Up to 5,000 live entries; a full store refuses new protected calls rather than evicting a guard.
- Holds
- AES-256-GCM sealed request hash, ownership marker, status, reply and receipt headers. No raw key, prompt or address. Replies may contain request text.
- Lives for
- 24 hours from the first request. A timer deletes ciphertext at expiry, and lookups also sweep expired entries. Process restart loses entries. Without Redis, retries routed to another process are not protected.
Scheduled result notifications and browser view
Authorized owners read their saved schedules and results. The existing inbox shows one item per finished retained run. Linked Telegram delivery receives the name, first 300 reply characters or a failure code, and an authenticated result link.
- Holds
- Decrypted prompt and reply text in router and browser memory, and a reply excerpt in Telegram, which can read and retain it under its own policy. The browser does not persist scheduled prompt or reply text. No new Redis key family or application log field.
- Lives for
- Router and browser memory lasts for the request or open page. Telegram follows its own retention policy; deleting a schedule does not erase delivered Telegram messages. Saved database content and its inbox item disappear with the schedule; billing records and backups retain their existing policies.
Model price snapshots and account price notices in kv
With PRICE_NOTICES_ENABLED, an hourly worker compares published catalogue input and output token rates with its previous snapshot. Only changes of at least one percent target accounts with an attributed generation for that model in the last thirty days. The first snapshot and models without funded endpoints produce no notice. Snapshot, account inbox items and daily caps commit together under a row lock. GET /api/v1/inbox returns these account-wide items only to management keys, excluding session keys and team administrators.
- Holds
- kv key price-notices:snapshot holds model ids, public model names and integer pico-USD input/output rates. price-notices:daily:<SHA-256 of account id>:<UTC date> holds account id, date, up to five notice ids, timestamps, model ids, fixed price-change titles and the count of grouped changes. The first four changes are individual items; the fifth groups the rest, including later checks that day. Existing generations account_id, model_id and ts are read; no new usage tracking, prompt, answer, wallet address or request body is added. Authorized management Telegram links receive one send attempt per newly created item through the existing delivery helper. Telegram can read model names and rates. Later grouped-count updates are retained in the inbox without another Telegram send.
- Lives for
- The latest snapshot is overwritten each run. Daily rows older than thirty UTC days are deleted by enabled runs; while disabled cleanup pauses. Claim-before-send avoids duplicate attempts across retries and workers, but a crash or failed outbound attempt can leave an inbox item without a Telegram message. No Telegram message id or delivery result is stored. No new table, column, Redis key family, body/address reader or log field.
Operator capacity and daily counts
The operator-only GET /trpc/rush reads daily aggregate milestones over at most 90 UTC days. New wallet sign-ins mean wallet accounts created with a management key at the same transaction timestamp; an account created earlier by a deposit is excluded. First credited deposits mean the first positive deposit, stock_deposit, anyr_deposit or usdg_deposit ledger row per account. First successful calls mean the first signed generation per account that was not cancelled and did not finish with an error. Earlier retained rows are checked to exclude repeats; deleted historical records cannot be reconstructed. No per-account rows leave these queries.
- Holds
- Daily counts and dates; latest upstream USD balances, check states and hold expiry times on the operator surface only. In memory the enabled monitor reads the existing encrypted provider credential and configured headers to authenticate a documented balance check; neither credential nor upstream response text is retained in the new state or logs. API replicas refresh balances and temporary holds on health flushes; catalogue requests also refresh them before reading the cache, with starts at least five seconds apart per process. Both catalogue routes share one in-flight refresh promise and its monotonic start time in memory; failed reads preserve the previous availability state. Changed exhausted state invalidates that process’s catalogue cache. The catalogue cache holds up to 64 public catalogue JSON variants and 64 in-flight computations, keyed only by the four supported public catalogue filters. It contains catalogue metadata, prices, capabilities and provider evidence, never inference text or caller addresses. No new table, column or Redis family.
- Lives for
- Aggregate responses discarded after delivery with no-store. Catalogue JSON expires after 30 seconds, successful catalogue sync or an observed exhausted-state change; process memory disappears on exit. Failure-based routing holds expire after five minutes; exhausted balance readings persist until a reading exceeds the configured threshold. Balance readings and alert delivery times are overwritten in place and remain until operator deletion. Existing source retention applies.
Public tool catalog in the router's memory
When TOOLS_PUBLIC_CATALOG_URL is set, the router fetches that public x402 catalog through the egress guard to answer tool searches.
- Holds
- Public tool names, summaries, addresses, prices and payTo wallets. No caller data.
- Lives for
- TOOLS_PUBLIC_CATALOG_TTL_S (900 seconds by default); a failed refresh keeps the previous copy; lost on restart.
Signed account event delivery
When WEBHOOK_SIGNING_ENABLED is enabled, a minute worker reads at most 50 destinations, one 100-row activity page per destination, and sends at most 100 due notices per tick. Activity readers retain account, key, team and wallet-party guards. It delivers metadata references, fixed types/statuses and timestamps; existing Spend Watch and agent delivery retain their original alert fields. Signing covers exact wire JSON bytes plus a timestamp. The signed body binds event_id to the header. Secrets use the existing APP_SECRET encryption helper. Legacy URLs remain unsigned until rotation. Revocation stops future deliveries; an already in-flight request can finish. The disabled flag retains original alert delivery without signing, imports or worker writes.
- Holds
- Decrypted URLs and signing secrets enter router process memory only for delivery or credential issuance. Account wallet and host operator addresses are read by the status-write hook to match operated hosts. No prompt/answer is added to deliveries, and no arbitrary response or transport error text is logged. The browser holds a newly revealed signing secret in component memory until dismissed, disconnected or navigation; it is not written to browser storage.
- Lives for
- Activity discovery begins at destination creation, uses five minutes of overlap and durable pagination, and can miss source rows removed before discovery or commits delayed beyond the overlap. Approval requests/decisions and operated host status changes enqueue references in the transaction that records the change, so changes between worker ticks are retained. Approval references are approval ids. Direct database writes outside the router do not generate these notices. Delivery can repeat after a crash before result persistence: receivers must verify exact bytes with a five-minute timestamp tolerance and atomically deduplicate event ids. Delivery metadata is retained for 90 days; the API shows 100 attempts. Three attempts per event, five minutes apart. Owner-requested connectivity notices are limited to one per destination per minute.
Make-good refund decisions
With MAKEGOOD_ENABLED (off by default), the call finaliser, the all-providers-failed path and the JSON repair check record a pending candidate when a call meets a refund rule; the hourly settlement job issues it as a ledger line linked to the generation, a signed refund receipt naming the original receipt, a refund.issued webhook reference and, for a network host that caused it, review-only host slashing evidence. Calls paid on-chain per call are refunded by the makegood-payouts job from MAKEGOOD_REFUND_PRIVATE_KEY, which refuses to run without that key.
- Holds
- Rule decisions use token counts, prices, provider ids, error classes, lane and attestation results already in router memory. The JSON rule parses the repair answer in memory only to decide whether it is JSON; the text is not stored. Refund rows keep amounts, fixed codes, ids, transaction hashes and the payer wallet address for on-chain refunds. The treasury key stays in worker memory and is never logged or stored; signed transfers are stored encrypted.
- Lives for
- Refund rows and transfers are kept with the ledger (no automatic deletion). Webhook references follow the webhook delivery retention. No new Redis family or log field carries request text or a caller address.
Liveness probes to listed agent endpoints
When AGENT_IDENTITY_ENABLED is on, the agent-liveness job sends one GET a day to each listed profile's owner-declared HTTPS endpoint, to a public address only (no redirects, a ten-second timeout by default), with a fixed Anyroute-Liveness user agent and no credentials, and does not read the response body.
- Holds
- The status code, latency and a fixed failure code in agent_liveness with a signed probe receipt. The endpoint's operator sees the router's network address and the request.
- Lives for
- Each probe replaces the previous result. Nothing is kept in memory between runs.
ERC-8004 registries on Robinhood Chain
An identity registration (owner-sent, or sent by the isolated registrar worker) writes a public, permanent record: the registration file URL, a metadata entry pointing at the router's receipt keys, and the holding wallet. Optional feedback and validation calldata the router prepares is sent only by the reviewer's or validator's own wallet.
- Holds
- Public chain data: agent ids, registration URLs, wallets, scores, tags and document hashes. No key hash, account id, receipt id or amount is placed in calldata the router prepares.
- Lives for
- Permanent on chain; opting out stops the router serving the registration file and links, but cannot remove a sent transaction.
Track-record Merkle trees in memory
Proof requests rebuild a certificate's tree from the router's generation records and keep at most 32 trees in process memory.
- Holds
- Receipt anchor leaves (hashes) and generation ids of the certified key's counted receipts.
- Lives for
- Until evicted by newer trees or the process exits.
Account activity response in memory
GET /api/v1/activity merges existing generations, ledger entries, agent approvals, policy events, the retained agent alert feed, spending alert history, escrow deposit statuses, key auto top-up records and wallet-party agreement events. Each source and response is limited to 100 rows. Ordinary and session keys read only their own key records; management and owner/admin keys read account records. Non-management administrators retain the agent routes' team boundary. Key, model, project, lane, missing-metadata and date filters further restrict results. J182: opt-in basis=charges reads negative usage/tool_call/data_tool ledger entries at settlement time with the same account/key/session call visibility, optionally restricted to statement usage or rulebook charge kinds. It joins existing generation ids, key/account stamps and recorded receipt signatures to expose a call receipt only when present; missing models and receipts stay missing. Spending alerts keep their existing management-or-own-key boundary. CSV and JSON contain the same selected page; a cursor continues the filtered range.
- Holds
- Times, fixed event titles, exact signed USDG amounts, model and provider ids, recorded lanes, key names or existing short labels, receipt references, status and approval limits. It reads account wallet addresses and existing on-chain payer/payee and deposit sender addresses to select matching records, without returning those addresses. Agreement amounts describe wallet escrow movements, not router balance changes. It reads only model and lane from stored approval/policy intents and only lane from receipts; no request body, agreement evidence, delivery targets, key secrets or full key hashes enter the response. Oracle-only events require an indexed ruling linking their key to the agreement; until then they remain in the agreement view.
- Lives for
- Discarded after the response; cache-control is no-store. No new durable storage, logs or Redis keys. Downloads stay on the caller's device. Existing source retention still applies; the agent alert feed retains at most 100 records for 90 days and spending alerts retain up to 20 firings per rule.
Signed monthly statements in memory
With STATEMENTS_ENABLED (off by default), GET /api/v1/statements/:month aggregates the existing ledger in one SQL snapshot and signs canonical JSON with the existing receipt signer. Management and owner/admin keys see account totals; ordinary and session keys see only movements attributed to their key. The account creation month sets the earliest readable month. UTC month bounds exclude the next month; the current month ends at the read time.
- Holds
- Account creation date, key hashes and existing names or labels, exact pico-USDG ledger totals converted to decimal strings, movement kinds, model ids and lanes from linked generation receipts, call counts and reconciliation results. Reads only lane from receipt JSON, no request text, wallet or network addresses, key secrets, ledger descriptions or receipt content hashes. Unrecorded group values are null. Key-only balances are attributed ledger sums rather than the shared account balance. Separate fee entries are distinguished from fees embedded in usage. Call time and settlement time can differ; external payments are outside the router balance ledger.
- Lives for
- Discarded after response with cache-control no-store. No new tables, columns, Redis keys or log fields. Signing uses existing receipt key storage and retention. Downloaded JSON and printed statements remain on the caller's device; the signature is the router's statement, not an independent ledger audit.
Account export on the caller's device
The account shell builds a JSON bundle in the browser by paging existing authenticated read APIs. It includes accessible account and key metadata, rulebooks, policy events, sessions, approvals, activity, signed statements, wallet-party agreements and owned profile settings. A manifest describes included sections, access failures, retention and omitted records; this is not a complete storage dump.
- Holds
- Existing endpoint response data, including key hashes, wallet metadata or addresses where the endpoints expose them, policies and readable policy-event intents, session metadata, approval intents, activity and agreement projection records, owned profile settings and signed statements. Key secrets and credential-shaped fields are stripped. Chat history, private files, saved content, raw statement ledger, agreement evidence and dispute details are outside this export. Approvals are limited by the existing endpoint to 100 per stored status. Agent events and profiles retain per-agent access errors in the bundle.
- Lives for
- Kept in browser memory during export, then downloaded as JSON to the caller's device. Cancel stops requests and prevents download. No new server-side bulk endpoint, persistence or logs. Existing endpoint and source retention apply; APIs are read sequentially, not in one database snapshot.
User-entered statement business identity in kv
Account management keys optionally save business identity for a Billed to block on statements. Anyroute can read these fields and does not verify them. They are outside the signed statement payload; changing them never changes what is signed.
- Holds
- business-details:<account id> holds business_name, multi-line address, tax_id and reference in kv.value, linked to the account id in kv.key, plus kv.updated_at. The router reads these optional settings in memory. Statement reads with business_details=true add them beside payload, alg, key_id and sig; default statement responses are unchanged. The browser uses these current fields, including for earlier months, for the unsigned Billed to block, CSV and print/PDF. Signed JSON downloads omit them. There is no billing email field; the reference rejects email addresses, but free-text business identity fields can contain personal information supplied by the owner.
- Lives for
- Kept until replaced or deleted, without automatic expiry. Delete in Settings > Statements sends PUT with an empty object and removes the kv row; it does not remove earlier backups or exports on the caller's device. Browser memory holds the form and loaded statement details until navigation; no new browser storage. No new table, column, Redis family or log field.
Proof pack in memory
With STATEMENTS_ENABLED (off by default), GET /api/v1/proof-pack?from=&to= builds one JSON file for at most 31 UTC days: the calls Activity lists for the key's scope with their stored signed receipts and Merkle paths, issued refund receipts, the signed monthly statements covering the range, the published receipt keys, a lane report of the listed calls and a manifest signed with the existing receipt signer. Management and owner/admin keys read the account; ordinary and session keys read only their own key. A range with more than 2,000 calls, or calls under more than 200 anchors, is split into parts with a cursor.
- Holds
- Generation ids, call times, key hashes, model and provider ids, mode, lane, exact charged amounts, the stored signed receipt payloads and COSE claims (request and response hashes, token counts or buckets, amounts, attestation references, and the payer key hash or per-call payer wallet and payment transaction a receipt was signed with), anchor roots, indexes and Merkle paths, refund receipts with their stored evidence and any on-chain refund wallet, signed statements, public receipt keys and the manifest of listed receipt ids and leaves. No request or answer text, key secrets or network addresses; recorded provider attempts are not read.
- Lives for
- Discarded after the response with cache-control no-store. No new tables, columns or log fields; one rate-limit counter per key. Downloaded files remain on the caller's device. Existing receipt, refund, ledger and anchor retention apply.
Lane report in memory
With STATEMENTS_ENABLED (off by default), GET /api/v1/lane-report?from=&to= groups the calls Activity lists for the key's scope over at most 31 UTC days by the lane each receipt records, provider and model, and returns calls and charged spend per lane, the share on the attested and unlinkable lanes, and per provider and model rows for those lanes with links to the provider's public attestation record. Management and owner/admin keys read the account; ordinary and session keys read only their own key. The proof pack carries the same summary for the calls in each file.
- Holds
- Lane names read from receipt JSON, provider and model ids, call counts, exact charged amounts, the range and the key hash for key-scoped reports. No request or answer text, receipt hashes, key secrets or network addresses.
- Lives for
- Discarded after the response with cache-control no-store. No new tables, columns or log fields; one rate-limit counter per key.
Spend insights response in memory
GET /api/v1/insights aggregates existing call charges and ledger refunds over at most 92 days, with UTC day or Monday-week buckets. It uses Activity's account-or-own-key access, including session restrictions. Each model/key breakdown includes the first 100 by cost or calls; totals include all visible records. Refunds count when posted; linked refunds use their generation's model and lane. Unlinked refunds have unknown model/lane.
- Holds
- Exact decimal charges, refunds, net spending, call and token counts, model ids, recorded lanes/disclosure classes, existing key names/short labels, and historical hardware-check counts from signed v1 receipts. Missing evidence and cache calls do not count as proven. An average includes its exact numerator/denominator and a decimal truncated to 12 places. It reads key hashes internally for grouping but returns response-local key numbers. Price comparisons read live catalog capabilities, endpoint lane/disclosure availability and token/request prices at the observed input/output mix; estimates exclude royalties, account fees, cache discounts, reasoning/media/search charges and refunds. No request text, wallet addresses, key secrets, new logs, tables, columns or Redis keys are read or written.
- Lives for
- Discarded after the response; cache-control is no-store. Existing source retention applies. No durable storage added.
Savings finder response in memory
GET /api/v1/account/savings aggregates only the caller's visible charged generation records over 1 to 30 rolling days. Uses Activity's account-or-own-key access, including sessions, team roles and deleted-key account stamps. No new durable storage.
- Holds
- Model identifiers, call and input/output token totals, largest recorded context/output counts, actual charged pico amounts, safe billing-mode/cache/reasoning flags, and existing receipt lane/disclosure codes only. Reads current catalogue modalities, endpoint supported parameters, context/output limits, eligibility, health, lanes, disclosure and token/request rates. Historical used abilities are not retained: all declared source abilities, parameters and full context are preserved conservatively; missing metadata and unsafe billing records omit a model. Candidate must be cheaper than both current source rates and actual charges. Estimates exclude refunds, royalties, account fees and extra charges; no equal quality claim. No messages, bodies, addresses, key secrets, new tables, columns, logs or Redis keys are read or written. Ordinary inference still reads request text in router memory.
- Lives for
- Response discarded after completion, cache-control no-store. Browser state cleared on key change or leaving Insights; no browser persistence. Source retention unchanged.
Your view of a model response in memory
J178: GET /api/v1/account/models/:id/summary composes existing Insights, reliability, savings and price notice readers. Uses Activity account-or-own-key visibility including sessions and deleted-key account stamps. Insights filters the model before aggregation and group limits. No new storage or background work.
- Holds
- Public model id; 30-day exact decimal call charges, posted refunds and net spend with call counts; seven-day recorded completion counts and success percentage; existing conservative savings suggestion and current catalogue rates/abilities; latest matching price notice time/title among the existing latest 101 retained notices over 30 days. Notices require a non-session management key and enabled inbox preference and feature switch. The panel reuses existing watch and comparison controls and their guards/storage. No new notices, messages, body or address readers, key secrets, tables, columns, log fields or Redis families. Ordinary inference still reads request text in router memory.
- Lives for
- No-store HTTP response; browser component memory cleared on key/model change or leaving the page. Signed-out visitors make no summary request and render no panel. Existing source retention unchanged.
Account reliability response in memory
GET /api/v1/account/reliability aggregates up to seven rolling days of existing generations and denied inference agent policy decisions. It uses Activity's account-or-own-key visibility including sessions, deleted-key account stamps and the agent team boundary. Agent decisions are omitted while agent policies are off.
- Holds
- Model identifiers; counts of recorded calls, non-cancelled/non-error completions, route records marked as fallback, and denied inference decisions grouped by lane, budget or other rulebook reasons; recorded streamed first-token latency and generation total time with interpolated median and p95. It reads only route presence/reason from existing receipt JSON and model/kind and reason codes from policy JSON, never messages, request text, arbitrary error strings, hashes, wallet addresses or key secrets. Percentages cover recorded calls or recorded routes only; pre-generation failures and general lane/balance refusals are missing. Decision counts are not unique requests and reason groups can overlap. No tables, columns, logs or Redis keys are added.
- Lives for
- Discarded after the response; cache-control is no-store. Browser state lasts until refresh, key change or leaving the view; no report persistence. Existing source retention applies.
Market-data tool readings in memory
When DATA_TOOLS_ENABLED is on, GET /api/v1/data/stock/:symbol and /actions read a Stock Token's Chainlink feed and its uiMultiplier, newUIMultiplier, effectiveAt, paused and oraclePaused views from Robinhood Chain; GET /api/v1/data/ipx/:class reuses the inference price index snapshot. A paid call is charged once, after the reading passed its checks: a prepaid key through the ordinary hold and ledger (kind data_tool), a keyless caller through the existing per-call payment, whose quote binds the method and path.
- Holds
- Public chain readings per token (feed answer, decimals, update time, multiplier values, pause flags) and the read time, and the public index snapshot per class and hour. Nothing about the caller is kept here; the charge is the existing ledger line and, for per-call payments, the existing quote row with the payer's wallet address. No request text: these are GET requests without a body.
- Lives for
- A token reading is reused for 15 seconds and an index snapshot for 60 seconds; both are lost when the router instance exits.
Decision tags in signed receipts
When DECISION_TAGS_ENABLED is on, a chat or completion call may send X-Anyroute-Decision-Tag: a SHA-256 digest the caller computed, for example of an order intent. The router signs it into that call's v1 and v2 receipts as decision_tag, so the caller can later show which model answered before a decision. A malformed tag is refused before anything is charged, and the unlinkable lane refuses a tag because a reused tag joins calls together. An Agent Guard decision whose details_sha256 equals a tag names the same agent's tagged calls as informed_by, and a proof pack lists the tags its receipts carry; both read the stored receipts and store nothing new.
- Holds
- The 64-hex digest as sent, inside the generation's stored receipt and receipt_v2. Never the intent itself, which the router never receives.
- Lives for
- Kept with the generation record and its receipt, under their existing retention.
Account inbox response and browser seen time
GET /api/v1/inbox reuses Activity's account, ordinary-key, session-key, team, spending-alert and wallet-party agreement visibility. It merges retained alerts, posted deposit credits, key auto top-ups, indexed disputes/rulings and, when AGENT_PAY_ENABLED, confirmed agent payments sent by this account's keys or received by a published wallet of its agents, since the browser's seen time, with unexpired pending approvals regardless of that time. It reads up to 100 records per activity kind and up to 100 pending approvals and operated host records; capped indicates a source may have more. The count describes returned items, not an unbounded total. Owner/admin access follows the existing agent decision endpoint, which remains the sole approval writer. POST /api/v1/inbox/seen authenticates the key and echoes a validated displayed-snapshot timestamp; it does not read a body or persist state.
- Holds
- Fixed event titles, timestamps, recorded statuses, signed credited amounts, paid USDG amounts of agent payments, key names, approval ids, expiry and spending limits. Stored approval intents are read and projected to kind, model, lane, tool names, estimated cost and output limits; no request text or Telegram messages are added. Account wallet and provider operator addresses are read in memory to match this account's operated network hosts, without returning addresses or private provider configuration. Host items show current status at the provider record's update time, which can also change for reasons other than status; no transition history is inferred. A secret-keyed visibility digest separates account, team, management and ordinary/session key bookmarks, without exposing account ids or full key hashes.
- Lives for
- Responses live in memory and use cache-control no-store. The browser stores only a last-seen timestamp under anyroute-inbox-seen-v1:<visibility digest> in local storage until browser data is cleared; items and API keys are not stored there. Bookmarks do not sync between browsers. The unchanged API counts pending approvals until decided or expired. H173: the browser treats approvals at or before its bookmark as read while keeping them highlighted for a decision. Optional kinds filtering and six group counts are computed only from the authorized bounded response in request memory. Selected kinds stay in the page URL and browser history; an undo token holds only the visibility digest, previous/written timestamps and a ten-second deadline in component memory. Undo restores the matching browser bookmark only if not superseded. No additional storage family, body reader or address reader. No new database table/column, Redis key family, log field or Telegram message storage. Existing source retention still applies.
Network host routing evidence in memory
When NETWORK_HOSTS_ENABLED is on, routing uses existing signed generation records, health probes and attestation outcomes to limit admitted hosts during probation and exclude unavailable hosts.
- Holds
- Provider ids, probation deadlines, aggregate attested success and recent outcome counts, fresh canonical active bond base units matched to the host id and operator wallet, probe availability and median latency, the latest attestation failure flag and refresh time. No request text or caller address. Successful network probes also record latency in the existing health table.
- Lives for
- Rebuilt by health refreshes, including idle flushes; evidence older than 120 seconds is refused. Failed refreshes clear the evidence. Lost when the router instance is released or exits.
Host registration on the operator’s computer
The join command reads a dedicated operator wallet key from the explicitly selected file or environment variable and signs the router’s existing wallet-auth message. It optionally reads the host-generated sidecar API key from an explicitly selected UTF-8 file or environment variable, trims and validates it, and checks POSIX file read permissions. It submits host name, sidecar endpoint, payout address, model ids and optional contact to the selected router. After successful signup, or in credential-only mode, it sends the sidecar API key and provider id over HTTPS to the router’s existing wallet-authenticated credential endpoint; an explicitly selected loopback router may use HTTP. Status polling sends a provider id without a wallet key. It sends no inference text and no transactions.
- Holds
- The operator’s existing wallet and sidecar key files or environment variables are left in place. The command reads the key and signup fields in process memory; the wallet address, timestamp and signature leave as authentication. The sidecar API key leaves in the credential request body and is stored in the router’s existing AES-GCM encrypted provider-key column; the router can decrypt it to call the sidecar. The command writes no key or signup file, logs no key and redacts loaded sidecar credentials (including JSON-escaped forms) and wallet-key-shaped output. Dry runs read neither key and show a redacted credential body, with the signup-assigned provider id still unknown. File read buffers are cleared, but JavaScript strings and signing-library memory cannot be reliably erased. Signup details and resulting status are printed to the operator’s terminal; the operator controls terminal retention. The router still reads inference request text in memory on every lane.
- Lives for
- Process memory lasts until the command exits. The key source and terminal history remain under the operator’s control. Router storage for host admission is described by the admission endpoint’s inventory when available.
Public network statistics in router memory
When NETWORK_STATS_ENABLED is on, cache read-only network statistics and share one refresh among concurrent readers.
- Holds
- Only the public aggregate response: snapshot time, host status counts, fresh admitted host count, distinct eligible model IDs, 100,000-token ranges from retained public-lane generation counts, indexer total/active USDG bonds with freshness and block, waitlist counts and published policy version. Private-lane generation rows are excluded; existing router-wide DP releases cannot identify network-host totals. Database query results and public admission evidence are read temporarily to form the snapshot. The host query selects no credentials, operator wallets or contact fields. The existing bond adapter reads public on-chain projection metadata, which can include operator addresses; only aggregate amounts, freshness and indexed block enter this cache. No inference text or caller address is read. No new database rows, Redis keys or log fields.
- Lives for
- Cache freshness ends 30 seconds after refresh begins, with no stale-on-error serving. The single expired snapshot may remain allocated until replaced or the router exits. Query results are eligible for collection after refresh; process exit releases all cache memory.
Public commerce ledger in router memory
When COMMERCE_STATS_ENABLED is on, cache the public commerce ledger and share one refresh among concurrent readers.
- Holds
- Only the public aggregate response: snapshot time, receipt kinds, filter settings and transfer-index position, and per window and kind the gross and filtered settlement, distinct payer and payee counts, USDG volume, median price, refund count and rate, and the count excluded by each rule. To build it, the router reads in memory the payer and payee wallet or account identifiers, amounts, times, transaction hashes, anchor status and refund flags of settled payments, and public USDG transfers; none of these enter the cache. Figures are never split by privacy lane, so a private-lane settlement cannot be told apart. No inference text or caller network address is read. No Redis keys. A failed refresh logs one warning with the first line of the error, cut to 200 characters; database errors put the query text on that line, not its parameters.
- Lives for
- Cache freshness ends 60 seconds after refresh begins, with no stale-on-error serving. The single expired snapshot may remain allocated until replaced or the router exits. Settlement rows read for a refresh are eligible for collection when it ends.
Owner's sealed agent VM
The dedicated agent sidecar uses the guest agent's application-scoped GetKey with a measured-compose-specific path to seal a provisioned AnyRoute credential with AES-256-GCM. It obtains TDX quotes committing the key fingerprint, image, measured compose, version and TLS key. The internal proxy forwards agent request and response streams to fixed paths at the configured HTTPS router origin.
- Holds
- An encrypted credential file in the VM's sealed volume. Raw credential and guest-derived key enter process memory during provisioning or boot; the API credential is sent to AnyRoute as Bearer authentication over TLS. The agent container receives no credential. Provisioning input, guest console retention and any owner-held credential copies remain the owner's responsibility. VM software and administrators can access guest memory. JavaScript strings cannot be reliably erased. No prompt or answer file is written by the sidecar.
- Lives for
- Ciphertext survives restarts until volume removal or replacement. Memory lasts for the sidecar process; the KMS key is scoped to app identity and a path containing the measured compose. Manifest changes require fresh provisioning. No anti-rollback guarantee is provided.
Agreement escrow and dispute records on chain
Agreements are switched on at anyroute.tech, with the escrow and dispute contracts deployed on Robinhood Chain. A payer funds individual milestones in USDG and an oracle can pay only that agreement's payer or payee. The optional agreements service indexes this public state, stores party evidence and model verdict statements, and prepares payer-signed funding transactions; its separate database and reader disclosures appear in this inventory.
- Holds
- Public permanent blockchain state, transaction calldata and events: payer, payee, token, escrow, oracle, owner, panel and jury wallet addresses; agreement and milestone ids; amounts, deadline, immutable review window and dispute timeout, delivery and dispute-opening timestamps and status; terms and deliverable digests, opening evidence digest and evidence root; jury version, signer order, threshold, participation and consensus bitmaps, signed per-signer basis-point verdicts, tally digest, final verdict, neutral stale-dispute 50/50 recovery events and payouts; a panel-pending tally remains historical metadata after escrow recovery. The digest fields accept arbitrary caller-supplied bytes32 values; they do not prove the absence of encoded text or conceal low-entropy content. Evidence text is not required by the contracts, and any off-chain jury service needs its own retention disclosure. Deployment prints only escrow and oracle addresses.
- Lives for
- Permanent public chain history; the contracts have no deletion function. When enabled, the agreement service indexes chain records into the separately described agreement tables.
Messages proxy prices on the caller's computer
The local proxy estimates a Messages budget using model prices fetched over Tor. The request text, code, tool schemas and results are read in memory to count tokens, then forwarded over Tor; count_tokens is answered locally without any network request.
- Holds
- The public unlinkable model directory in memory. The existing local tokens.json file atomically moves every selected bearer token to unconfirmed before sending; uncertainty keeps all members there, while a definite unserved refusal returns them. No request or answer text is written to that file or logged.
- Lives for
- Model prices are refreshed after one minute and lost on process exit. Local token credentials remain until expiry filtering, successful settlement or removal by the caller; uncertain sent sets are never automatically reused.
Batch requests and answers in the router's memory, without Redis
Without Redis (a single router in development), the Batch API keeps the same sealed requests and answers in the router process's memory instead.
- Holds
- The same sealed requests and answers as the Redis keys batch:<batch id>:in and :out.
- Lives for
- The sealed requests are deleted when the batch finishes; the sealed answers BATCH_RESULTS_TTL after that (86,400 seconds, 24 hours, unless the operator changed it). A batch that never finishes ends when its 24-hour completion window closes, so nothing outlives the window plus that time. A restart loses them.
Response cache in the router's memory
The opt-in response cache also keeps each entry in the router process's memory (up to 5,000 entries), whether or not Redis is configured.
- Holds
- The same sealed answer as the Redis entry, and for the semantic mode a hashed word vector of the prompt.
- Lives for
- An entry is not served after its time-to-live, but it stays in memory until newer entries push it out (oldest first, at 5,000) or the process restarts.
Replay guards in memory
Two small in-memory sets stop replays: a used wallet signature (when Redis is not configured) and an Oblivious HTTP encapsulated request prefix.
- Holds
- SHA-256 digests of a wallet address, timestamp and request hash, and of the first bytes of an encapsulated request. Not the request.
- Lives for
- Ten minutes for a wallet signature (old entries are swept once the set passes 50,000); until the key's acceptance window ends for an encapsulated request, with at most 100,000 kept.
Private-lane counters in memory
Differentially private hourly counters for the attested and unlinkable lanes: how many requests, how many were refused and why, latency and token buckets. They contain no request, no address, no key and no timestamp finer than an hour.
- Holds
- Four families of counts for the current hour, released once with noise when the hour ends; the raw counts are then discarded.
- Lives for
- Released hours are kept for 48 hours; the privacy-budget ledger for 30 days.
Trace export (OpenTelemetry), off unless an endpoint is set
When OTEL_EXPORTER_OTLP_ENDPOINT is set, one span per chat or text-completion call is sent to that endpoint: model, provider, token counts, cost, generation id, mode, attempt count, whether it streamed, and the trace id from a traceparent header if the caller sent one. Calls on the attested and unlinkable lanes send no span. Spans carry no prompt or completion.
- Holds
- The attributes listed, buffered in memory for up to five seconds before export.
- Lives for
- In memory for seconds; kept by whatever receives it, which the operator chooses.
Trace export to a key owner's own destination, off unless the owner sets one
A key's owner can set a tracing destination on the key (their OpenTelemetry collector, Langfuse or Helicone). Each public-lane call made with that key is then sent there: model, provider, token counts, sampling settings, finish reason, latency, cost, receipt id and lane. Prompt and completion text is included only if the owner set include_content. Calls on the attested and unlinkable lanes are never sent.
- Holds
- The listed fields of recent calls, in a bounded in-memory queue (2,000 calls at most across all keys; more are dropped and counted) until they are delivered or given up.
- Lives for
- In memory for seconds, or until retries end; kept by the destination the key's owner chose.
Encrypted database backups
A scheduled pg_dump (daily in the reference deployment) of the whole database, encrypted to public age recipients and uploaded to S3-compatible storage. Every table listed on this page is in it. The private key that opens it is never on the host that makes the backup.
- Holds
- The database as it was when the backup ran.
- Lives for
- The code writes each archive under a new key and never deletes one; how long archives last is set by the storage bucket's own rules, which are not in this repository.
The database, table by table.
115 tables and 1,230 columns, grouped by what they are for. “About a request” says whether a value is recorded for each call, summed from calls, or has nothing to do with calls. A column whose name or type suggests request content or a network address (a name such as prompt, body, ip or address, or a free-form JSON or network type) carries a written review, shown with the column.
Request records
Ordinary call rows hold the model, provider, token counts, cost and timing, without the text. Owner-chosen scheduled run replies are also described here and stored encrypted at rest.
apps
Where calls come from, for app rankings: the HTTP-Referer and X-Title headers a caller chose to send, kept as the caller wrote them (truncated). Not recorded for the unlinkable lane.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idtext | First 24 hex characters of SHA-256 of the referer and title, so the same app maps to one row. | Per request |
urltext | The HTTP-Referer header value, cut to 500 characters. It is whatever the calling application sent, usually its own site address.A request header, kept as written. A request header kept on purpose so apps can be ranked. It names an application's site, not the caller's network address, and callers can omit it. | Per request |
titletext | The X-Title header value, cut to 200 characters: the application's display name.A request header, kept as written. A request header kept on purpose for app rankings. It is a short label the caller chooses, not a prompt. | Per request |
created_attimestamp with time zone | When the row was created. | Per request |
batch_lines
One row per line of a batch: its status, the HTTP status its call returned, the generation (and so the signed receipt) it produced and what it was charged. No request or answer text: that is sealed outside the database.
How long: Deleted with the batch's sealed answers when its results expire (BATCH_RESULTS_TTL after the batch finished, 24 hours unless the operator changed it).
| Column | What it holds | About a request |
|---|---|---|
batch_idtext | The batch the line belongs to. | Per request |
idxinteger | The line's position in the batch, from 0. | Per request |
apitext | chat or embeddings. | Per request |
statustext | queued, running, succeeded, failed, cancelled or expired. | Per request |
attemptsinteger | How many times the worker started the line (a line whose providers were all unavailable is tried again, up to BATCH_LINE_MAX_ATTEMPTS). | Per request |
status_codeinteger | The HTTP status the line's call returned. | Per request |
generation_idtext | The generation the line produced, whose receipt it has. | Per request |
costbigint | What the line was charged, after the batch discount, in pico-USD. | Per request |
list_costbigint | What the line would have cost without the discount, in pico-USD. | Per request |
failure_codetext | For a line that did not succeed, the error type (for example insufficient_credits or batch_cancelled). A fixed code, never text from a request. | Per request |
not_beforetimestamp with time zone | The earliest the line runs (a rate-limited line waits), or, while it runs, when it counts as interrupted. | Per request |
finished_attimestamp with time zone | When the line ended. | Per request |
batches
One row per batch sent to the Batch API (POST /api/v1/batches): the key that sent it, its status, how many lines it has and how many succeeded or failed, and what it cost. The requests and answers of its lines are never written to the database: they are kept sealed in Redis or the router's memory (see the Redis section) until the batch's results expire.
How long: No automatic deletion of the row itself; when the batch's results expire (results_expire_at), its line rows and its sealed requests and answers are deleted and purged_at is set.
| Column | What it holds | About a request |
|---|---|---|
idtext | The batch id (batch_ and random hex). | Summed from requests |
account_idtext | The account the batch's lines are billed to. | Summed from requests |
key_hashtext | The hash of the API key that sent the batch; only that key can read or cancel it. | Summed from requests |
apitext | Which API every line calls: chat or embeddings. | Summed from requests |
statustext | validating, in_progress, cancelling, completed, failed, expired or cancelled. | Summed from requests |
totalinteger | How many lines the batch has. | Summed from requests |
completedinteger | How many lines succeeded. | Summed from requests |
failedinteger | How many lines failed. | Summed from requests |
costbigint | What the batch's lines were charged, after the batch discount, in pico-USD. | Summed from requests |
list_costbigint | What the same calls would have cost without the batch discount, in pico-USD. | Summed from requests |
discount_bpsinteger | The batch discount in basis points (BATCH_DISCOUNT_BPS when the batch was sent; 5000 is half price). | Summed from requests |
created_attimestamp with time zone | When the row was created. | Summed from requests |
started_attimestamp with time zone | When the worker started the batch. | Summed from requests |
cancelling_attimestamp with time zone | When the key asked to cancel the batch. | Summed from requests |
finished_attimestamp with time zone | When the batch's last line ended. | Summed from requests |
expires_attimestamp with time zone | The end of the 24-hour completion window: lines not run by then end unrun and unbilled. | Summed from requests |
results_expire_attimestamp with time zone | When the batch's answers and line rows are deleted (finished_at plus BATCH_RESULTS_TTL). | Summed from requests |
purged_attimestamp with time zone | When they were deleted. | Summed from requests |
generations
One row per call the router served: who was billed, which model and provider answered, token counts, cost, timing, how it was paid and the signed receipt. It holds hashes of the request and the response, never their text.
How long: No automatic deletion: no job or route in the code removes rows from this table. Rows are read back for receipts, usage history, settlement and provider scoring.
| Column | What it holds | About a request |
|---|---|---|
projecttext | Owner-chosen project label from X-Anyroute-Project or the key default, captured for this call. Null when absent. Retained with the call; not included in the signed receipt. Anyroute can read it. Activity JSON/CSV and Insights return labels and use them to filter within existing account/key permissions. A project-filtered Activity feed includes calls only; generation-linked refunds in Insights follow the original call label, unlinked refunds have no project. Labels can encode sensitive details; use non-sensitive names. No request text is read to derive the label. The unlinkable lane refuses project tags to preserve separation between calls. Statements are unchanged. | Per request |
idtext | Generation id, random. It is also the id of the signed receipt (the X-Receipt-Id response header). | Per request |
tstimestamp with time zone | When the call was recorded. | Per request |
key_hashtext | SHA-256 of the API key that made the call (the key itself is never stored). Empty for wallet-paid and blind-token calls. | Per request |
account_idtext | The account that was billed. For a blind-token call it is the shared token pool, not a person. | Per request |
model_idtext | The catalogue model id that answered, such as author/slug. | Per request |
provider_idtext | The provider that served the call. | Per request |
tokens_ininteger | Prompt tokens billed, as a count. | Per request |
tokens_outinteger | Completion tokens billed, as a count. | Per request |
reasoning_tokensinteger | Reasoning tokens billed, as a count. | Per request |
cached_tokensinteger | Prompt tokens the provider served from its cache, as a count. | Per request |
cache_write_tokensinteger | Prompt tokens written to the provider's cache, as a count. | Per request |
costbigint | Total charged to the caller, in pico-USD (1e-12 USD). | Per request |
upstream_costbigint | What the provider charged the router for the call, in pico-USD. | Per request |
royaltybigint | The share of the cost owed to the model's creator, in pico-USD. | Per request |
marginbigint | The router's fee on the call, in pico-USD. | Per request |
cache_discountbigint | The discount given for cached prompt tokens, in pico-USD. | Per request |
modetext | How the call was paid: prepaid, per_call, paywith, byok, cache or blind. | Per request |
latency_msinteger | Milliseconds until the provider's first response. | Per request |
generation_time_msinteger | Milliseconds for the whole call. | Per request |
finish_reasontext | Why the model stopped, such as stop or length. | Per request |
native_finish_reasontext | The stop reason as the provider reported it. | Per request |
streamedboolean | Whether the answer was streamed. | Per request |
cancelledboolean | Whether the caller cancelled before the answer finished. | Per request |
quanttext | Quantisation of the endpoint that answered (for example fp8), or unknown. | Per request |
data_regiontext | The first datacenter region the provider lists, not the caller's location. | Per request |
is_byokboolean | Whether the caller's own provider key paid for the call. | Per request |
privateboolean | Whether the caller asked for a private route (provider.private or a :private model). | Per request |
attestation_hashtext | Hash of the attestation report of the provider, when an attested provider served the call. | Per request |
receipt_idtext | The receipt's id (the same as id). | Per request |
receipt_sigtext | The router's Ed25519 signature over the receipt. | Per request |
receipt_key_idtext | Which receipt signing key signed it. | Per request |
receiptjsonb | The signed v1 receipt payload: model, provider, token counts, cost, timing, mode, lane, disclosure class, payer (a key hash or a wallet address), the two SHA-256 digests and a summary of the provider's attestation. Blind payment adds a single nullifier and issuer key id, or token_count, nullifiers and token_key_ids for a set; no buyer or credential bytes. The ciphertext chat adapter also signs end_to_end_encrypted and e2ee: version, suite, gateway_attested, complete, billing_basis, input_byte_bound, max_tokens, request_bytes, response_bytes and gateway_receipt with id, keyset digest, response-hash, request-hash and upstream verification state plus upstream session id and GPU claim. Request-hash verification remains false in the router. No public keys, replay nonces, credentials or content are retained. When ROUTE_EXPLAIN_ENABLED is true, route stores version, serving provider id, selection reason, eligible count, aggregate skip and fallback error-class counts, lane, required parameter names from a fixed allowlist and whether the provider is a network host. No other provider ids, weights, URLs, messages or content are added. With DECISION_TAGS_ENABLED, decision_tag stores the caller's X-Anyroute-Decision-Tag: a validated sha256 digest the caller computed, never what it was computed from. Fixed fields chosen by the router.Cannot hold request content. Every field is set by the router's receipt code from numbers, ids and hashes; it never copies request or answer text into the payload. | Per request |
receipt_leaftext | This receipt's leaf hash in the anchoring tree. | Per request |
anchor_indexinteger | Which anchor (Merkle root) this receipt was included in, once anchored. | Per request |
leaf_indexinteger | The receipt's position in that anchor tree. | Per request |
receipt_v2jsonb | The v2 receipt claims as JSON: model, provider, lane, hashed request and response, power-of-two token-count buckets and cost units. The optional route claim carries the same versioned selection summary as v1, without other provider ids, raw errors or weights. The optional decision_tag claim is the same caller-computed sha256 digest as v1. Null for receipts made before v2.Cannot hold request content. Built by buildClaimsV2 from ids, hashes and buckets; the claims carry no payer, address, IP or content. | Per request |
receipt_cosetext | The v2 receipt as signed COSE_Sign1 bytes, base64. | Per request |
receipt_leaf_v2text | The v2 receipt's leaf hash in the anchoring tree. | Per request |
leaf_index_v2integer | The v2 leaf's position in the anchor tree. | Per request |
paid_withjsonb | For a pay-with call: the token symbol and address, raw units accrued, the fair price used and the swap transaction, when there is one.Cannot hold request content. Written by the pay-with code from token symbols, addresses and amounts. | Per request |
payment_txtext | For a per-call payment: the transaction hash that paid. | Per request |
app_idtext | Links to the apps row when the caller sent HTTP-Referer or X-Title. Not recorded for the unlinkable lane. | Per request |
attemptsjsonb | Every provider the router tried for the call: provider, model, whether it worked, error kind, HTTP status and latency. A failed attempt also keeps up to 200 characters of the provider's own error message, with URLs, keys, emails and long hex removed.May hold a short piece of request text. The failure message is the provider's text, not ours. Providers normally send a generic reason, but a provider could quote part of a rejected request in it, so up to 200 characters of request text could end up here. | Per request |
request_sha256text | Ordinary chat: SHA-256 of canonical request JSON (stream flags excluded). The E2EE adapter hashes the exact forwarded encrypted envelope bytes, including whitespace and stream flags. Someone who already has the exact request can check it against this; the text cannot be recovered from it.A hash, not the text. A hash of the request, kept so a receipt can be checked against a request the caller holds; it is 64 hex characters and holds no text. | Per request |
response_sha256text | Ordinary chat: SHA-256 of response text (all choices joined). The E2EE adapter hashes encrypted JSON or SSE wire bytes, including framing; an interrupted response hashes the observed prefix. The text cannot be recovered from it.A hash, not the text. A hash of the answer, kept for the receipt; it is 64 hex characters and holds no text. | Per request |
settled_periodtext | The UTC hour in which the call was settled to the provider, for example 2026-09-26T13. | Per request |
health
One row per provider attempt (and per probe): did it work, how fast, which status. It feeds routing and provider scores. It has no request or answer text and no account id.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
model_idtext | The model that was tried. | Per request |
provider_idtext | The provider that was tried. | Per request |
tstimestamp with time zone | When the attempt finished. | Per request |
okboolean | Whether the attempt produced a usable answer. | Per request |
latency_msinteger | Milliseconds until the first response. | Per request |
tpsreal | Output tokens per second, when it could be measured. | Per request |
empty200boolean | Whether the provider answered 200 with an empty completion. | Per request |
status_codeinteger | The HTTP status the provider returned, when there was one. | Per request |
error_kindtext | A fixed code for the failure from the router's ErrorKind list, such as http_5xx, rate_limited, provider_auth, rejected, empty200 or interrupted. Null when the attempt worked.Cannot hold request content. One of a short list of codes chosen by the router (ErrorKind); the provider's message is not stored here. | Per request |
sourcetext | traffic for a real call, probe for the router's own health probe. | Per request |
callertext | A 16-character truncation of the SHA-256 of the account id, set only on failed attempts, so one caller cannot single-handedly mark a provider as failing. It is not the account id. | Per request |
schedule_runs
The last ten claimed scheduled runs, including encrypted replies and bounded failure reasons.
How long: Last ten runs per schedule, pruned at the next claim; all removed when the schedule is deleted. Ordinary billing and receipt records retain their existing lifetimes.
| Column | What it holds | About a request |
|---|---|---|
idtext | Random run identifier. | Per request |
schedule_idtext | Parent schedule identifier; deletion cascades. | Per request |
due_attimestamp with time zone | Unique due slot per schedule; coordinates competing workers without Redis. | Per request |
started_attimestamp with time zone | When the run was claimed. | Per request |
finished_attimestamp with time zone | When the run succeeded, failed or was marked interrupted. | Per request |
statustext | Running, succeeded or failed. | Per request |
reply_enctext | The full returned reply, encrypted with the same account-and-schedule AES-GCM scope as the prompt.Holds request text. This column keeps actual answer text encrypted under a router-held secret. It is decrypted for authorized owners and the first 300 characters are included in inbox and Telegram notices. | Per request |
reasontext | Bounded machine error code, never the upstream message or request text. | Per request |
generation_idtext | Preselected ordinary generation identifier linking the run to its charge and receipt, including an uncertain interrupted call. | Per request |
notifiedboolean | One outbound Telegram attempt claimed before delivery; failed or interrupted sends are not retried. | Per request |
Billing
Balances, the append-only ledger, spending holds, per-call payment quotes and what providers are owed.
accounts
One row per billing account: an API-key account or a wallet account, with its settled balance and the amount held for calls in flight.
How long: No automatic deletion. The ledger refers to accounts and is append-only, so an account row stays.
| Column | What it holds | About a request |
|---|---|---|
idtext | The account id. For a wallet account it is derived from the wallet address. | Not about requests |
low_balance_picobigint | Optional owner-selected low-balance threshold in pico-USD; null disables alerts. Kept until changed or cleared. | Not about requests |
low_balance_alertedboolean | Whether the current threshold crossing has been recorded. Re-armed only after a worker observes settled balance above the threshold; false by default. | Not about requests |
inference_keys_defaultboolean | Whether newly provisioned child keys default to inference-only access. Management keys can explicitly select account scope. | Not about requests |
last_sent_weektext | Nullable previous ISO week identifier (YYYY-Www) last successfully sent as a weekly Telegram summary. Overwritten after delivery; retained with the account, including after unlink, to avoid sending that week again after relinking. No message text. With quiet hours, the week is marked after durable queue acceptance, before actual Telegram delivery. A later revoked, muted or expired queued summary is not resent. | Not about requests |
kindtext | key for an API-key account, wallet for a wallet account. | Not about requests |
wallettext | The wallet address of a wallet account. Empty for a key account. | Not about requests |
balancebigint | The spendable balance, including provisional deposit credits: the sum of the account's ledger lines, in pico-USD. A database trigger keeps it equal to that sum. | Summed from requests |
heldbigint | The amount reserved by open holds for calls in flight, in pico-USD. | Summed from requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
holds
A reservation of balance made before a call runs, settled to the real cost afterwards or released. One hold per call.
How long: The database refuses to delete holds (trigger holds_apply_held), so they are kept permanently.
| Column | What it holds | About a request |
|---|---|---|
idtext | Hold id; for a chat call it is the generation id. | Per request |
account_idtext | The account the amount is reserved on. | Per request |
key_hashtext | The key hash that made the call, when there is one. | Per request |
amountbigint | The reserved amount in pico-USD; it cannot change after creation. | Per request |
statustext | held, settled or released. | Per request |
kindtext | What the hold was for; usage for a call, tool_call for a paid x402 tool, data_tool for a market-data tool call. | Per request |
resultjsonb | How the hold ended: the amount charged and any uncovered amount, as strings in pico-USD, and expired: true when the hold timed out.Cannot hold request content. Written only by settle() and release() in ledger.ts as { charged, uncovered, expired } amounts. | Per request |
created_attimestamp with time zone | When the row was created. | Per request |
expires_attimestamp with time zone | When an unsettled hold is released automatically (the holds-expire job). | Per request |
ledger
The append-only money ledger: deposits, credits, usage charges, refunds, withdrawals and adjustments. A usage line names the generation it paid for; it does not say what the call was about.
How long: The database refuses every update and delete on this table (trigger ledger_no_update), so lines are kept permanently.
| Column | What it holds | About a request |
|---|---|---|
idtext | Ledger line id. | Per request |
account_idtext | The account the line applies to. | Per request |
key_hashtext | The key hash the line came from, when there is one. | Per request |
amountbigint | The signed amount in pico-USD: positive adds to the balance, negative takes from it. | Per request |
kindtext | What the line is: provisional (early escrow credit), deposit, credit, usage, refund, paywith, change, adjustment, withdrawal_lock, withdrawal, blind_purchase, tool_call (a paid x402 tool), data_tool (a market-data tool call) and similar. | Per request |
reftext | A unique idempotency reference, such as usage:<generation id> or escrow:<transaction>:<log index>, so a line can never be posted twice. | Per request |
generation_idtext | For a usage line, the generation it paid for. | Per request |
descriptiontext | A short line written by the router, such as "<model> via <provider>", "USDG deposit <transaction hash>" or "Model usage". Never text from a request.Cannot hold request content. Every description is built in code from model ids, provider ids, transaction hashes and fixed phrases (ledger.ts, escrow.ts, indexer.ts); no caller-supplied string is used. | Per request |
created_attimestamp with time zone | When the row was created. | Per request |
low_balance_alerts
One durable inbox item per observed low-balance crossing, claimed together with the account alert flag.
How long: No automatic deletion. Earlier crossings remain after the balance recovers or the setting changes.
- With LOW_BALANCE_ALERTS_ENABLED, the worker checks every five minutes. Authorized linked Telegram accounts receive balance, threshold and an Add funds link through the existing Telegram delivery path. The inbox claim is committed before a single send attempt; failures are not retried. No message body or Telegram delivery result is retained here. No new Redis key family or log field is added. Runway uses seven days of posted usage and paid-tool debits, scoped like credits, and stores no report.
| Column | What it holds | About a request |
|---|---|---|
idtext | Random alert identifier. | Summed from requests |
account_idtext | Billing account whose balance crossed its threshold. | Summed from requests |
balance_picobigint | Settled balance at the crossing check, in pico-USD; not reduced by open holds. | Summed from requests |
threshold_picobigint | Owner-selected threshold at the crossing check, in pico-USD. | Summed from requests |
created_attimestamp with time zone | When the worker recorded the crossing. | Summed from requests |
makegood_refunds
One row per call (or per unserved per-call payment) that met a make-good refund rule: the rule, the capped refund, the signed refund receipt and, for calls paid on-chain per call, the on-chain refund still owed or paid. Disabled unless MAKEGOOD_ENABLED.
How long: No automatic deletion: no job or route in the code removes rows from this table. At most one row per source: the source id is unique, so a call is never refunded twice.
| Column | What it holds | About a request |
|---|---|---|
idtext | Refund id, also the id of its signed refund receipt (GET /api/v1/receipts/{id}). | Per request |
source_idtext | What is refunded: the generation id, or payment:<transaction hash> for a per-call payment no provider served. Unique. | Per request |
generation_idtext | The refunded generation, whose id is also its original receipt id. Null for an unserved paid call. | Per request |
account_idtext | Account credited (or whose per-call wallet is refunded on-chain). | Per request |
key_hashtext | Hash of the API key that made the call, copied from the generation; null for a per-call wallet payer. | Per request |
ruletext | Fixed rule name: upstream_failure, fallback_price, truncated_stream, structured_output or unattested_lane. | Per request |
statustext | pending until the settlement job decides it, then issued, or void when nothing charged is left to refund. | Per request |
amountbigint | Refund in pico-USD: the rule's amount capped by what the ledger charged (or, for an unserved paid call, by the payment still unspent). | Per request |
chargedbigint | What the ledger charged for the call, or what the unserved per-call payment was, in pico-USD. | Per request |
evidencejsonb | Fixed facts behind the rule: error class counts, provider ids, token counts, costs, lane and disclosure class, a payment transaction hash or the first call id of a JSON repair.Cannot hold request content. Written only by the make-good hooks from numbers, fixed codes, provider ids, generation ids and transaction hashes; never request or answer text, headers or caller addresses. | Per request |
provider_idtext | Provider whose failure caused the refund, when one did; null when no provider is responsible (a JSON answer that does not parse). | Per request |
strikeboolean | Whether the refund is also a strike against that provider (an attested-lane call served without a fresh attestation). | Per request |
payertext | Wallet address that paid the call on-chain per call, refunded on-chain; null for credits to a prepaid balance. | Per request |
onchain_usdgbigint | USDG base units owed on-chain for this refund (whole units; any remainder below one unit stays as balance). | Per request |
payout_statustext | none, owed, batched (in a signed transfer) or paid. | Per request |
payout_idtext | The makegood_payouts transfer that pays this refund. | Per request |
receiptjsonb | The signed refund receipt payload (kind refund): ids, rule, amounts, settlement, provider and the evidence above.Cannot hold request content. Canonical JSON built by issueRefund from the fields of this row and the original generation id; it carries amounts, fixed codes and hashes, no request or answer text. | Per request |
receipt_sigtext | Ed25519 signature over the canonical refund receipt, by the router's receipt key. | Per request |
receipt_key_idtext | Id of the receipt key that signed it. | Per request |
receipt_leaftext | Hash of the signed receipt in the form receipt anchoring uses; refund receipts are not yet anchored. | Per request |
detected_attimestamp with time zone | When the rule was met (the call settled or failed). | Per request |
issued_attimestamp with time zone | When the settlement job issued or voided the refund. | Per request |
network_fee_ledger
Network host fees from confirmed per-host receipt roots, grouped in the UTC hour when they accrue. Gross and fee are pico-USD; net is invoiced through settlements. Closed-hour fees are swapped through the guarded buyback oracle path and transferred to the token dead address. Swap and burn transactions are public through the network burns API.
How long: No automatic deletion, and rows are never changed after they are written.
- The planned executor reads its public token, adapter, oracle and keeper addresses, daily cap, operation state and transaction events from the chain in memory to check configured settings and reconcile swaps. Quotes use a pinned block and may add an independent pool TWAP. No request text, caller address, new log field or Redis key is read or stored by these checks. Payouts and fee burns are not switched on yet.
- Sub-USDG-unit fee dust remains unswapped and is reported separately. Burns transfer to the dead address; the token's totalSupply is unchanged. Public totals aggregate across hosts; recent entries expose transactions, status and token amounts, without host invoice amounts. Transactions themselves are public on chain and can be correlated with hosts. Amounts above the configured per-run or remaining daily cap wait for a later run or operator reconciliation.
| Column | What it holds | About a request |
|---|---|---|
idtext | Provider and accrual-hour identifier; also the input to the on-chain operation digest. | Summed from requests |
provider_idtext | The host owed a net payout. | Summed from requests |
periodtext | UTC hour when anchored receipts accrue, which may follow the served hour. | Summed from requests |
gross_piconumeric(78, 0) | Sum of upstream_cost for eligible linked generations, before the network fee. | Summed from requests |
fee_piconumeric(78, 0) | Floor of gross times configured basis points divided by 10000. | Summed from requests |
statustext | accrued, swapped or burned, reconciled with on-chain operation state. | Summed from requests |
swap_txtext | Confirmed swap transaction hash, not request content. | Summed from requests |
burn_txtext | Confirmed dead-address transfer transaction hash. | Summed from requests |
anyr_amountnumeric(78, 0) | ANYR base units measured by the executor's balance delta. | Summed from requests |
created_attimestamp with time zone | When the row was created. | Summed from requests |
payouts
A payout to a provider: the amount in USDG, where it went and its status.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idtext | Payout id. | Not about requests |
provider_idtext | The provider paid. | Not about requests |
usdgbigint | Amount in USDG base units. | Not about requests |
totext | The destination address for the payout. | Not about requests |
statustext | pending, submitted, paid or invoice. | Not about requests |
txtext | The payment transaction. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
project_budget_notices
Durable 80 percent budget notice, at most once per account/project/UTC month.
How long: No automatic deletion. Removing or editing a budget preserves notice history and does not re-arm that month's notice.
- PROJECT_BUDGET_TELEGRAM_ENABLED defaults false; the worker sends only when Telegram linking and a bot token are also configured. Current management principals only receive these account-wide notices. Telegram receives project label, spend, budget and a dashboard link. No new Redis families, caller address readers or log fields.
| Column | What it holds | About a request |
|---|---|---|
account_idtext | Billing account receiving this notice. | Summed from requests |
nametext | Project label included in the inbox and optional Telegram text. | Summed from requests |
monthtext | UTC calendar month as YYYY-MM, the deduplication boundary. | Summed from requests |
spent_picobigint | Month-to-date charged spend when the threshold was reached, excluding refunds. | Summed from requests |
budget_picobigint | Budget in effect when the notice was created. | Summed from requests |
attimestamp with time zone | Time of threshold observation at settlement or budget save. | Summed from requests |
telegram_claimedboolean | Durable claim before a single Telegram delivery attempt; default false. No retries after failed or ambiguous sends. | Summed from requests |
project_budgets
Owner-selected monthly project spending caps in calendar months UTC.
How long: Until the account owner removes the budget; no automatic deletion.
| Column | What it holds | About a request |
|---|---|---|
account_idtext | Billing account that owns this cap. | Not about requests |
nametext | Lowercase non-sensitive project label, 1–48 ASCII letters, digits, dots, underscores or hyphens. | Not about requests |
budget_picobigint | Monthly spending cap in pico-USD, zero refuses positive estimates. | Not about requests |
project_reservations
Project attribution on existing ledger holds; settlements count charged spending before the generation record is written.
How long: No automatic deletion; retained with billing records even when a budget is removed.
- Tracks tagged calls even without a cap. Open holds count across month boundaries until settled or released by the existing expiry job. Earlier generations count once; refunds do not restore monthly allowance. No prompt or answer text is kept here. The router still reads ordinary request text in memory.
| Column | What it holds | About a request |
|---|---|---|
idtext | Existing ledger hold identifier; also the generation identifier for inference calls. | Per request |
account_idtext | Billing account paying for the call. | Per request |
nametext | Validated label from the existing project header or key default; Anyroute can read it. | Per request |
charged_picobigint | Actual ledger charge in pico-USD; zero before settlement or on released calls. | Per request |
charged_attimestamp with time zone | Ledger settlement time, used to assign charged spend to a UTC month; null until settlement. | Per request |
quotes
A price quoted for one pay-per-call request (HTTP 402 and x402), so a payment can be matched to exactly the request it was for.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
noncetext | The quote id (32 bytes hex). For an x402 payment claim it is x402:<payer wallet>:<authorization nonce>. | Per request |
price_usdgbigint | The quoted price in USDG base units (1e-6). | Per request |
price_picobigint | The same price in pico-USD. | Per request |
request_sha256text | SHA-256 of the request the quote is for. It binds the quote to that one request; the request cannot be recovered from it.A hash, not the text. A hash of the request body, used to check that a payment belongs to the request it quoted. | Per request |
model_idtext | The model the quote is for. | Per request |
expires_attimestamp with time zone | When the quote stops being payable. | Per request |
statustext | open, paid, used, expired or failed. | Per request |
payertext | The wallet address that paid, once a payment is seen. | Per request |
tx_hashtext | The payment transaction. | Per request |
account_idtext | The account the payment was credited to. | Per request |
created_attimestamp with time zone | When the row was created. | Per request |
royalties
The royalty a model's creator earned in one period, and whether it was claimed.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
model_idtext | The model. | Summed from requests |
periodtext | The settlement period. | Summed from requests |
amountbigint | Royalty in pico-USD. | Summed from requests |
usdgbigint | Royalty in USDG base units. | Summed from requests |
creatortext | The creator's payout address, when one is known. | Summed from requests |
stream_txtext | The transaction that streamed the royalty. | Summed from requests |
claimedboolean | Whether the creator claimed it. | Summed from requests |
seller_gas_floats
USDG a seller prepaid to the treasury so the facilitator settles its payments below the minimum; each such settle is debited at its measured gas times a buffer.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
seller_idtext | The listing the float belongs to. | Summed from requests |
balancenumeric(78, 0) | USDG base units left. | Summed from requests |
fundednumeric(78, 0) | USDG base units paid in, in total. | Summed from requests |
debitednumeric(78, 0) | USDG base units taken for gas, in total. | Summed from requests |
updated_attimestamp with time zone | When the row was last changed. | Summed from requests |
settlements
What one provider is owed for one UTC hour: token totals, request count, upstream cost, the router's fee and the USDG owed. Network hosts use only confirmed per-host receipts and the configured network fee; their period is the accrual hour.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
provider_idtext | The provider owed. | Summed from requests |
periodtext | The UTC hour, such as 2026-09-26T13. | Summed from requests |
tokensbigint | Total tokens invoiced in the hour; network hosts include only newly eligible anchored work. | Summed from requests |
requestsinteger | Number of calls invoiced in the hour; network hosts include only newly eligible anchored work. | Summed from requests |
upstreambigint | Upstream cost for the hour, in pico-USD. | Summed from requests |
feebigint | The router's fee for the hour, in pico-USD. | Summed from requests |
usdg_owedbigint | USDG base units owed to the provider for the hour. | Summed from requests |
payout_idtext | The payout that included the hour, once paid. | Summed from requests |
paid_txtext | The transaction that paid it. | Summed from requests |
created_attimestamp with time zone | When the row was created. | Summed from requests |
skill_installs
One row per (skill, installing account): the price paid, the author's share, the network fee and the signed install receipt. The ledger rows of a paid install use refs derived from the same pair, which makes an install idempotent.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idtext | Install id (si_...). | Not about requests |
skill_idtext | The skill installed. | Not about requests |
account_idtext | The installing account. | Not about requests |
key_hashtext | The key that installed it. | Not about requests |
price_usdgbigint | The price paid in USDG base units; 0 for a free skill or the author's own. | Not about requests |
author_sharebigint | Pico-USD credited to the author's account (the price less SKILLS_FEE_BPS). | Not about requests |
feebigint | Pico-USD credited to the network fee account. | Not about requests |
receiptjsonb | The install receipt: skill id, content hash, level, installer and author accounts, amounts and time, with an Ed25519 signature from the receipt key.Cannot hold request content. Ids, hashes, amounts and a timestamp chosen by our code, plus the signature over them. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
tool_calls
One row per paid x402 tool call made with a key's balance: the seller, the tool address, the price and take, the hold, the signed authorization's nonce and the settlement transaction, the answer's hash and the signed tool.call receipt. Never the tool arguments, the query string or the answer.
How long: No automatic deletion: these are billing records, like generations and the ledger.
| Column | What it holds | About a request |
|---|---|---|
idtext | Call id (tc_...), also the id of its hold. | Per request |
key_hashtext | The key that paid. | Per request |
account_idtext | The account charged. | Per request |
seller_idtext | The tool listing id when the address is listed, else null. | Per request |
pay_totext | The seller's payTo wallet (public on chain). | Per request |
resourcetext | The tool's https origin and path that was paid, without the query string. | Per request |
methodtext | GET or POST. | Per request |
networktext | The x402 network of the paid offer. | Per request |
x402_versioninteger | 1 or 2: which x402 wire format the seller spoke. | Per request |
price_unitsbigint | The seller's price in USDG base units. | Per request |
pricebigint | The seller's price in pico-USD. | Per request |
takebigint | The router's take in pico-USD (TOOLS_TAKE_BPS). | Per request |
hold_idtext | The hold on the key's balance. | Per request |
payertext | The router's own buyer wallet that signed the authorization. | Per request |
noncetext | The EIP-3009 nonce of that authorization; the reconcile job asks the chain whether it was used. | Per request |
valid_beforetimestamp with time zone | When that authorization expires. | Per request |
settle_txtext | The settlement transaction hash the seller reported, if any. | Per request |
response_sha256text | SHA-256 of the tool's answer bytes, as in the receipt. The answer cannot be recovered from it.A hash, not the text. A hash of the tool answer kept for the signed receipt; 64 hex characters, no text. | Per request |
seller_statusinteger | The tool's HTTP status code. | Per request |
statustext | paying, ok, failed, released or charged_after_failure. | Per request |
failuretext | A fixed failure code, such as seller_status_500 or response_too_large. | Per request |
receiptjsonb | The tool.call receipt: COSE_Sign1 bytes (base64), key id, leaf and the signed claims (hashes, amounts, seller, address, settlement).Cannot hold request content. Ids, hashes, amounts, the public tool address and wallet, and the signature over them; no arguments or answer text. | Per request |
created_attimestamp with time zone | When the row was created. | Per request |
closed_attimestamp with time zone | When the hold was charged or released. | Per request |
x402_paid_results
One row per x402 payment whose call was answered, so a payer who lost the answer can have it sent again instead of paying twice. It names the paying wallet and the authorization nonce and holds hashes; the answer itself is sealed outside the database.
How long: 24 hours. Recovery refuses an older row, and the x402-recovery-expire job (and, at most hourly, each router replica that keeps answers) deletes it together with any sealed answer still held for it.
| Column | What it holds | About a request |
|---|---|---|
payertext | The wallet that signed the payment authorization (lowercase hex), as on the public settlement. | Per request |
noncetext | The authorization's EIP-3009 nonce (32 bytes hex), public on-chain once settled. | Per request |
request_sha256text | SHA-256 of the request the payment paid for (the receipt's request_sha256). A recovery must send the identical request.A hash, not the text. A hash of the request body, compared with the hash of a recovery request so an answer is sent again only for the request it answered. | Per request |
response_sha256text | SHA-256 of the answer's bytes as they were sent, checked before the sealed answer is sent again.A hash, not the text. A hash of the answer bytes, so the answer sent again is checked to be byte-identical to the one first sent; the answer cannot be recovered from it. | Per request |
body_reftext | The name of the Redis key that holds the sealed answer: x402paid: and a SHA-256 of the payer and the nonce.Cannot hold request content. A fixed prefix and a hash of the payer and the nonce naming where the sealed answer lives; the answer bytes are never written to this column. | Per request |
created_attimestamp with time zone | When the row was created. | Per request |
Receipts & proofs
Signing keys, anchors and the transparency log that let anyone check a receipt without asking us.
agent_track_records
Portable track-record certificates: a router-signed count, total spend, refund and dispute rates of one key's anchored receipts, with a Merkle root over those receipts' anchor leaves.
How long: Until the key is deleted (cascade). Certificates expire after seven days but stay stored; published ones show on the card until they expire.
| Column | What it holds | About a request |
|---|---|---|
idtext | Random public certificate id. | Summed from requests |
key_hashtext | The certified key; never published. | Summed from requests |
certificatejsonb | The signed certificate: random pseudonym, aggregate stats, Merkle root and anchor counts, the public profile slug and ERC-8004 agent id when registered.Cannot hold request content. Aggregates and hashes written by the router: no counterparty, no amount per counterparty, no request or answer text and no key hash. | Summed from requests |
publishedboolean | Whether the owner chose to show it on the public card. | Summed from requests |
created_attimestamp with time zone | When it was issued. | Summed from requests |
expires_attimestamp with time zone | Seven days after issuance. | Summed from requests |
anchors
A Merkle root over the receipts signed in one interval, and the chain transaction that recorded it. Lets anyone check that a receipt existed at that time.
How long: No automatic deletion, and rows are never changed after they are written.
| Column | What it holds | About a request |
|---|---|---|
indexinteger | Anchor number, counting up from zero. | Summed from requests |
roottext | The Merkle root of the interval's receipt leaves (32 bytes, hex). | Summed from requests |
from_tstimestamp with time zone | Start of the interval covered. | Summed from requests |
to_tstimestamp with time zone | End of the interval covered. | Summed from requests |
countinteger | How many receipts the root covers. | Summed from requests |
tx_hashtext | The chain transaction that recorded the root. | Summed from requests |
statustext | pending, submitted, confirmed or local. | Summed from requests |
created_attimestamp with time zone | When the row was created. | Summed from requests |
host_anchor_leaves
The receipt leaves collected from attested hosts. A row holds a leaf hash, the receipt id and the time; not the receipt's own hashes or usage.
How long: No automatic deletion, and rows are never changed after they are written.
| Column | What it holds | About a request |
|---|---|---|
provider_idtext | The attested host that produced the receipt. | Per request |
leaftext | The receipt's leaf hash. | Per request |
anchor_idinteger | The host_anchors row that includes it. | Per request |
leaf_indexinteger | Its position in that root's tree. | Per request |
receipt_idtext | The receipt's id. | Per request |
receipt_tstimestamp with time zone | The time the receipt itself states. | Per request |
collected_attimestamp with time zone | When the router collected the leaf. | Per request |
host_anchors
A Merkle root over the receipts one attested host signed in an interval, tied to the attestation its receipt key was bound in.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idserial | Row number, counting up from 1. | Summed from requests |
provider_idtext | The attested host. | Summed from requests |
attestation_reftext | SHA-256 of the boot quote the router verified for that host. | Summed from requests |
receipt_key_idtext | The host's receipt key id. | Summed from requests |
receipt_public_keytext | The host's raw Ed25519 receipt public key, hex, as its verified quote bound it. | Summed from requests |
roottext | The Merkle root of the collected leaves. | Summed from requests |
from_tstimestamp with time zone | Start of the interval the leaves were collected in. | Summed from requests |
to_tstimestamp with time zone | End of that interval. | Summed from requests |
countinteger | How many leaves the root covers. | Summed from requests |
statustext | pending, confirmed or local. | Summed from requests |
tx_hashtext | The chain transaction that recorded the root. | Summed from requests |
block_numberbigint | The block of that transaction. | Summed from requests |
chain_indexinteger | The anchor's index in the on-chain receipt anchor contract once posted. | Summed from requests |
created_attimestamp with time zone | When the row was created. | Summed from requests |
network_receipt_links
Links a router generation to a sidecar receipt ID from the response header, so only work included in that host's confirmed root can be invoiced. The collected leaf's signature is checked by host-anchor. Each sidecar receipt may be linked once per provider.
How long: No automatic deletion, and rows are never changed after they are written.
| Column | What it holds | About a request |
|---|---|---|
generation_idtext | Router generation ID; no prompt or response bytes. | Per request |
provider_idtext | Provider that served the call. | Per request |
receipt_idtext | Strict rcpt_ identifier from the upstream response header, not caller-provided text. | Per request |
accrued_periodtext | Null until included in a network invoice; then the UTC accrual hour preventing repeated accrual. | Per request |
receipt_keys
The Ed25519 keys that sign receipts, with the dates each was valid. Public halves are published; the private half is encrypted at rest.
How long: Keys are rotated (RECEIPT_KEY_ROTATION_DAYS) and retired, never deleted, so old receipts stay verifiable.
| Column | What it holds | About a request |
|---|---|---|
idtext | Key id: 16 hex characters, the first bytes of the public key's digest. | Not about requests |
public_keytext | The raw 32-byte public key, hex. Published at /api/v1/receipts/keys. | Not about requests |
private_key_enctext | The private key, AES-256-GCM encrypted with the router's APP_SECRET. Null for a key that can no longer sign; the router then makes a new one. | Not about requests |
valid_fromtimestamp with time zone | When the key started signing. | Not about requests |
retired_attimestamp with time zone | When it stopped signing, once rotated out. | Not about requests |
onchain_txtext | The transaction that published the public key on chain. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
tlog_checkpoints
Signed checkpoints of the transparency log: its size and root, signed by the log's key.
How long: No automatic deletion, and rows are never changed after they are written.
| Column | What it holds | About a request |
|---|---|---|
sizebigint | The tree size the checkpoint is for. | Not about requests |
root_hashtext | The tree's root hash, hex. | Not about requests |
checkpointtext | The checkpoint text: origin, size and base64 root hash. | Not about requests |
signaturetext | The log's signature line over that text. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
tlog_cosignatures
Witness cosignatures on checkpoints: independent parties confirming the log showed them the same tree.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
sizebigint | The checkpoint size the witness signed. | Not about requests |
witnesstext | The witness's key name. | Not about requests |
key_idtext | Hex of the 4-byte signed-note key id. | Not about requests |
timestampbigint | The cosignature's own time, in seconds. | Not about requests |
linetext | The signature line as the witness sent it. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
updated_attimestamp with time zone | When a newer cosignature from the same witness replaced the row. | Not about requests |
tlog_entries
The entries of the public transparency log: receipt keys, Oblivious HTTP key configurations, blind-token issuer keys, measurement bundles, attestation bindings and data inventories (this page's own hash).
How long: Append-only by design: entries are never updated or deleted, because the log's tree hashes them.
| Column | What it holds | About a request |
|---|---|---|
idxbigint | The entry's leaf index in the log. | Not about requests |
kindtext | receipt_key, ohttp_key_config, blind_issuer_key, measurement_bundle, attestation_binding or data_inventory. | Not about requests |
sha256text | Hex digest of the key or configuration the entry names. | Not about requests |
subjecttext | The key id, epoch, provider or inventory the entry is about. | Not about requests |
entrytext | The exact canonical JSON that was hashed into the log: public keys, digests and configuration, never request data. Sidecar bindings v2 include the source archive hash, engine name and image digest, and model ID and digest. | Not about requests |
leaf_hashtext | The entry's RFC 6962 leaf hash. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
tlog_rekor_anchors
Records of checkpoints the router anchored in a public Rekor log, with the proof that the entry is included.
How long: A pending row that turns out not to be an entry for its checkpoint is dropped and the checkpoint is submitted again; verified rows are kept.
| Column | What it holds | About a request |
|---|---|---|
idserial | Row number, counting up from 1. | Not about requests |
sizebigint | The checkpoint's tree size. | Not about requests |
root_hashtext | The checkpoint's root hash, hex. | Not about requests |
notetext | The signed checkpoint note that was anchored: checkpoint text, a blank line and the log's signature line.Cannot hold request content. The note is the transparency-log checkpoint text (origin, size, root hash) plus a signature line; nothing else is ever placed in it. | Not about requests |
artifact_sha256text | The SHA-256 the Rekor entry holds. | Not about requests |
key_idtext | SHA-256 of the anchoring key's public key info, hex. | Not about requests |
rekor_urltext | The address of the Rekor log the entry was submitted to.A public address, not a caller's. The address of a public transparency log server, set by the operator; it is not a caller's address. | Not about requests |
uuidtext | The Rekor entry id. | Not about requests |
statustext | pending or verified. Only verified rows are served. | Not about requests |
log_indexbigint | The entry's index in Rekor. | Not about requests |
integrated_timebigint | When Rekor integrated the entry, in seconds. | Not about requests |
log_idtext | Rekor's log id. | Not about requests |
entry_base64text | The entry body as Rekor returned it, base64. | Not about requests |
inclusion_proofjsonb | The inclusion proof: log index, tree size, root hash, hashes and Rekor's checkpoint.Cannot hold request content. Copied from Rekor's inclusion-proof response and typed as { logIndex, treeSize, rootHash, hashes, checkpoint }. | Not about requests |
signed_entry_timestamptext | Rekor's signed entry timestamp, base64. | Not about requests |
checkpoint_verifiedboolean | Whether Rekor's checkpoint signature verified against the pinned key. | Not about requests |
set_verifiedboolean | Whether the signed entry timestamp verified against the pinned key. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
verified_attimestamp with time zone | When the inclusion proof verified. | Not about requests |
Keys & auth
API keys (stored as hashes), teams with their passkey and wallet members and audit log, agent sessions, keys you bring, and the issuer and gateway keys behind blind tokens and Oblivious HTTP.
account_linked_wallets
Signature-verified secondary wallets associated with an account for escrow deposit crediting and paying another agent.
How long: Until the owner unlinks the wallet; unlink deletes this association. Existing deposit, ledger and payment records remain under their original account.
- Wallet addresses are public chain identifiers that can correlate this account with its deposits and agent payments. Linking does not merge accounts or let the secondary wallet sign in to the owner account.
| Column | What it holds | About a request |
|---|---|---|
wallettext | Lowercase secondary wallet address verified by a personal signature, unique across accounts. | Not about requests |
account_idtext | Owning account whose owner requested and verified the link. | Not about requests |
linked_attimestamp with time zone | When verification linked the wallet to the account. | Not about requests |
agent_action_decisions
Action checks, reported outcomes and rolling action limits for the deciding agent key, separate from model spend.
How long: Rows remain until operator deletion. Rolling day and hour limits read only the preceding 24 hours and hour; those windows do not delete records.
- Action and target labels remain readable, including symbols, recipient wallet addresses or hosts supplied by the agent. Do not send secrets or request text in these labels. Only a SHA-256 digest of order details is accepted; full orders are not accepted here.
- Unreported allowed actions count their requested amount. Executed outcomes count the agent-reported amount; skipped and failed outcomes release the daily amount. All allowed checks still count toward the hourly count. These records do not prove execution or control brokerage or wallet keys.
| Column | What it holds | About a request |
|---|---|---|
idtext | Random URL-safe decision identifier, not an authentication credential. | Per request |
key_hashtext | Hash of the deciding API key; only that key can report an outcome. | Per request |
event_idbigint | Identifier of the aggregate action decision on the existing agent event hash chain; events have their own retention. | Per request |
actiontext | Caller-chosen bounded action name such as trade.order or transfer.send. | Per request |
targettext | Optional caller-chosen symbol, recipient wallet address or host label, stored verbatim; this is not the caller's network address. | Per request |
amount_piconumeric(78, 0) | Requested action amount in integer pico-USD; an unreported allow holds this amount against the daily action limit. | Per request |
details_sha256text | Optional SHA-256 digest of canonical order JSON; order details themselves are not stored. | Per request |
decisiontext | allow, deny or approval_required from the rulebooks checked at decision time. | Per request |
created_attimestamp with time zone | When the decision was recorded. | Per request |
outcome_statustext | Null before reporting; executed, skipped or failed afterward, accepted once only for an allowed action. | Per request |
outcome_amount_piconumeric(78, 0) | Optional agent-reported actual pico-USD amount, required for executed; it may exceed the allowed amount and is not verified against a brokerage or chain. | Per request |
outcome_attimestamp with time zone | When the deciding key reported its outcome, or null before reporting. | Per request |
agent_approvals
Principal approval of an agent's estimated inference spend or reported action amount, consumed once by the requesting key.
How long: Approval validity defaults to 15 minutes (AGENT_APPROVAL_TTL_S). Pending and approved rows become expired on access or another approval evaluation. Rows remain until operator deletion; validity expiry does not delete records.
- No prompt or answer fields are stored. Model and declared tool names remain readable; callers choose these identifiers. The router still reads request text in memory on every lane. Action approvals store the action name, optional readable target (including wallet or host labels), optional order digest and amount, never full order details. Council and dual requests store the entire set of model intents with a shared total cost ceiling.
| Column | What it holds | About a request |
|---|---|---|
idtext | Random URL-safe approval identifier, not an authentication credential. | Per request |
key_hashtext | The API or session key requesting this approval; approval cannot transfer to another key. | Per request |
intentjsonb | Explicit projection of model, lane, declared tool names, output token limit and estimated pico-USD cost, or action name, target, order digest and pico-USD amount; a multi-model request stores an intents array.Settings written by you or an operator. Only routing or action metadata is copied; action targets can be symbols, recipient wallets or hosts. messages, answers, tool arguments and descriptions are excluded. Declared model and tool identifiers are caller-chosen labels whose meaning cannot be inferred by shape checks. | Per request |
intent_hashtext | SHA-256 of canonical projected intents including the estimated cost, used to reuse an identical pending approval. | Per request |
max_cost_piconumeric(78, 0) | The original estimated pico-USD cost ceiling; retries may cost less but cannot exceed this amount. | Per request |
statustext | pending, approved, denied, expired or used. Only approved, unexpired approvals can be consumed. | Per request |
requested_attimestamp with time zone | When the approval was created. | Per request |
decided_attimestamp with time zone | When the principal approved or denied the request, or null. | Per request |
decided_bytext | The deciding principal's API key hash, or null before a decision. | Per request |
expires_attimestamp with time zone | The fixed validity deadline from request time; approval does not extend it. | Per request |
used_attimestamp with time zone | When the router consumed the approval after a successful spend reservation, on an allowed cache hit, or on an allowed action check. | Per request |
agent_feedback
Paid feedback: a 0 to 100 score and up to two short tags per receipt, accepted only from the receipt's payer about its payee or the agent it served.
How long: Until the subject key is deleted (cascade). A reviewer can withdraw an entry, which stops counting it; the row is kept with its withdrawal time. No automatic deletion.
- Public: the score, tags, receipt kind, a coarse payment band and the payment day, linked to the agent's public profile slug. Never public: the reviewer's account, the receipt id and the exact amount. One entry per receipt.
| Column | What it holds | About a request |
|---|---|---|
idtext | Random public feedback id. | Not about requests |
subject_key_hashtext | The reviewed agent's key; never published. | Not about requests |
reviewer_account_idtext | The paying account, kept to enforce one entry per receipt and the reviewer's right to withdraw; never published. | Not about requests |
receipt_kindtext | Fixed receipt kind such as model.call or agreement.release. | Not about requests |
receipt_idtext | The router's own receipt or agreement milestone id that backs the entry; never published. | Not about requests |
scoreinteger | Score from 0 to 100. | Not about requests |
tag1text | Optional short tag (letters, digits, spaces and . _ : - only, up to 32 characters). | Not about requests |
tag2text | Optional second short tag, same limits. | Not about requests |
paid_picobigint | What the reviewer paid on the receipt, net of recorded refunds, in pico-USD; used for weighting and shown only as a band. | Not about requests |
paid_attimestamp with time zone | When the payment happened; weights halve every PAID_FEEDBACK_HALF_LIFE_DAYS after it. | Not about requests |
created_attimestamp with time zone | When the entry was written. | Not about requests |
revoked_attimestamp with time zone | When the reviewer withdrew it; null while it counts. | Not about requests |
agent_identities
Per agent key: the owner's identity opt-out and reputation opt-in, and the progress of an ERC-8004 identity registration the owner asked for.
How long: Until the key is deleted (cascade). Opting out keeps the row so the choice persists. A registration sent to the chain is public and permanent there; deleting this row does not remove it.
- The ERC-8004 identity registry is a public contract the router does not operate. The registration file it points to is served only while the key has not opted out and contains owner-written profile fields and router links, never the key hash or account. Keys whose rulebook allows only the unlinkable lane are opted out unless the owner opts in.
| Column | What it holds | About a request |
|---|---|---|
key_hashtext | The agent key these choices belong to; never published. | Not about requests |
idtext | Random 144-bit public id used in the registration file URL; independent of the key hash and the profile slug. | Not about requests |
identity_opt_outboolean | Owner's choice; null means the default (opted out only when the key's rulebook allows only the unlinkable lane). | Not about requests |
reputation_opt_inboolean | Owner's choice to accept paid feedback; false by default. | Not about requests |
statustext | Fixed registration state: none, awaiting_owner, queued, submitted, registered or failed. | Not about requests |
modetext | owner (the owner's wallet sends the transaction) or registrar (the isolated worker sends it). | Not about requests |
registrytext | Public registry identifier eip155:<chain id>:<contract address>. | Not about requests |
agent_idtext | The public ERC-8004 agent id read from the registration transaction. | Not about requests |
owner_addresstext | The wallet that holds the identity token, read from the public registration event.A wallet address, not a network address. A blockchain wallet address from a public on-chain event, not a network address; it is shown to the owner only. | Not about requests |
tx_hashtext | The public registration transaction hash. | Not about requests |
errortext | Fixed failure code of the last registration attempt.Cannot hold request content. Only fixed codes written by the router (reverted, no_registration, uri_mismatch, send_failed); never library text, a request or an answer. | Not about requests |
updated_attimestamp with time zone | When the row last changed. | Not about requests |
agent_ledger_links
Explicit correlation of rulebook decision events, requesting keys and generation identifiers for the agent activity ledger.
How long: 90 days; the agent-ledger-retention worker removes older links hourly when AGENT_POLICY_ENABLED is on. Deleting a linked event also removes that event's link. Generations retain their existing lifetime. With the flag off or worker absent, deletion waits.
- Only router-generated identifiers, timestamps and key hashes are stored. No prompt or answer text is added. A reservation link can precede a generation or remain without one after a provider failure. Existing records without correlation remain separate and are marked unlinked in the API. Parent policy events are attributed to the session key that made the request. The ledger describes policy evaluations and recorded generations through AnyRoute; errors before policy evaluation or generation creation have no ledger row.
| Column | What it holds | About a request |
|---|---|---|
idbigserial | Allocated correlation identifier. | Per request |
request_idtext | Router-generated request scope identifier; groups multiple models and inherited policy evaluations in one request.Cannot hold request content. A random UUID is generated inside the router for correlation. It never includes a URL, body, prompt, answer, or any caller-supplied string. | Per request |
key_hashtext | The actual requesting API key or session key, rather than the parent policy key. | Per request |
tstimestamp with time zone | When the correlation was recorded, in UTC. | Per request |
event_idbigint | The exact policy decision or approval-use event; null for generation links. Removed with its event. | Per request |
generation_idtext | The exact generation or reservation identifier; null for event links. A failed reservation or provider call need not produce a generation. | Per request |
approval_idtext | The approval identifier on a recorded approval-use event; otherwise null. | Per request |
agent_liveness
The latest signed liveness probe of each listed agent's declared endpoint (daily agent-liveness job).
How long: Replaced by each probe; deleted with the key (cascade). A result for an endpoint the owner has since changed is not shown.
| Column | What it holds | About a request |
|---|---|---|
key_hashtext | The listed agent key; never published. | Not about requests |
endpoint_sha256text | SHA-256 of the probed endpoint URL, so a changed endpoint invalidates the old result.A hash, not the text. A digest of the owner-declared public endpoint URL; never a caller's network address. | Not about requests |
liveboolean | Whether the endpoint answered with a status below 500, other than 404 and 410, within the timeout. | Not about requests |
http_statusinteger | The status code the endpoint answered with; null when it did not answer. | Not about requests |
latency_msinteger | Time to the response headers in milliseconds. | Not about requests |
errortext | Fixed failure code: timeout, network, blocked or http.Cannot hold request content. Only fixed codes chosen by the router; no response body, header or library message is stored. | Not about requests |
probed_attimestamp with time zone | When the probe ran. | Not about requests |
receiptjsonb | The probe receipt the router signed with its receipt key: the public profile slug, endpoint digest, time, result, status and latency.Cannot hold request content. Fixed fields written by the router, signed with the published receipt key; no response body, headers or key hash. | Not about requests |
agent_policies
The principal's current agent rulebook and kill state, enforced by the router for requests through AnyRoute.
How long: Until the principal removes the rulebook. Updating a rulebook replaces its current specification and preserves kill state.
- Model and tool identifiers and a kill reason are user-supplied text. Shape and size checks cannot judge the meaning a principal assigns to these labels. Action rules retain owner-chosen action names and target allow/deny labels, including recipient wallets or hosts; amount limits are separate from model caps. No prompt or answer fields are accepted.
- D144: Saving replacements also appends full rules to policy_versions; removing the current rulebook does not remove those revisions.
- G161: Optional work_hours keeps selected weekdays, local start/end clocks, an Intl-validated IANA time zone and refuse/ask_first mode in the existing readable rulebook JSON. Current rules, playbook copies and saved history retain it under their existing retention rules. No new table, column, Redis family, log field or request-body/address reader. The router still reads ordinary request text in memory.
| Column | What it holds | About a request |
|---|---|---|
key_hashtext | The API key this rulebook governs. | Not about requests |
versioninteger | Rulebook schema version, currently 1. | Not about requests |
specjsonb | Optional agreements.max_escrow_usd and counterparties_allow restrict preparation through the router; they do not enforce transactions sent elsewhere. Strict bounded rulebook: model and tool allow/deny names, lanes, an optional default privacy route (route_default) for requests that name no lane, cost and output caps, UTC windows, approval threshold, optional spend/request/denial/distinct-model circuit breakers and breach action, plus optional action and target allow/deny lists, separate action amount and count caps and an action approval threshold. Optional autonomy stores bounded rung requirements, spending multipliers and selected reset event kinds; it contains no prompt fields.Settings written by you or an operator. A strict schema excludes prompt and answer fields. Model and tool labels are owner-written identifiers of at most 160 characters; their contents are whatever the owner chooses to write. | Not about requests |
sha256text | SHA-256 of the canonical rulebook JSON. | Not about requests |
killedboolean | Whether the router refuses the next request under this rulebook. | Not about requests |
killed_attimestamp with time zone | When the rulebook was killed, if it is killed. | Not about requests |
killed_reasontext | A principal-supplied reason of at most 160 characters, or fixed policy reason codes for an automatic kill, including breaker:<field> for circuit breakers. | Not about requests |
kill_untiltimestamp with time zone | B117: Optional owner-selected stop deadline (future when set, at most 30 days ahead). Null means stopped until manually resumed. Cleared by manual Resume or atomically at the next enforcement check after expiry, including following playbook keys. | Not about requests |
updated_attimestamp with time zone | When the policy or kill state last changed. | Not about requests |
updated_bytext | The principal key hash or the agent key hash for an automatic kill or scheduled resume. | Not about requests |
playbook_idtext | The playbook this key follows, or null. While set, spec and sha256 hold a copy of that playbook's current rules, rewritten in the same transaction as every playbook change; stopping following keeps the copy as the key's own rulebook. | Not about requests |
agent_policy_events
A per-key hash chain of rulebook decisions and policy, kill and resume changes. Decisions contain routing metadata, never prompts or answers.
How long: 90 days; the agent-policy-retention worker removes older events hourly when AGENT_POLICY_ENABLED is on and the worker runs this job. With the flag off or the worker absent, deletion waits. A retained suffix starts with its prior hash as a checkpoint. For active autonomy rulebooks, the latest autonomy_state checkpoint and following suffix remain until superseded or the rulebook is removed, even beyond 90 days, to preserve earned progress.
| Column | What it holds | About a request |
|---|---|---|
idbigserial | Monotonically allocated event identifier for pagination. | Per request |
key_hashtext | The key whose rulebook was evaluated or changed; parent decisions are recorded under the parent key. | Per request |
tstimestamp with time zone | When the event was recorded, at millisecond precision. | Per request |
kindtext | action_decision and action_outcome (readable action/target identifiers, order digest and reported amounts), decision, breaker_request (one observation per policy admission batch with breakers), policy_set, killed, resumed, resume (scheduled stop expiry), approval_requested, approval_approved, approval_denied or approval_used. Approval events are recorded under the requesting key. Removing a rulebook records policy_set with a null intent. Autonomy also records autonomy_clean once per allowed reservation or cache/tool authorization, autonomy_state for derived progress, and breaker for an agent breaker event. | Per request |
decisiontext | allow, deny or approval_required for a decision; null for changes; breaker_request stores the batch decision. | Per request |
reasonsjsonb | Fixed reason codes and router-written messages; policy change events carry an empty list except a scheduled resume, which carries code scheduled and the fixed message Scheduled stop ended. G161: outside_work_hours and approval_work_hours messages include the computed next opening, its UTC instant and the owner-selected validated time zone.Cannot hold request content. Only evaluator-defined codes and router-written messages are stored. No request text or principal-written kill reason is copied into this field. Work-hour messages also contain a derived date and validated time zone configuration; they do not contain inference text. | Per request |
intentjsonb | Inference model, lane, estimated pico-USD cost, maximum output tokens and declared tool names; or an MCP tool name; action intents include a readable action and optional target (including recipient wallets or hosts), an amount and optional order digest, never full order details. Outcome events include the decision id, reported status and amount and whether it exceeded the requested amount. Approval and breaker_request events may contain an intents array for the full model set. Breaker counters read these routing identifiers and decisions; legacy decision events without a batch marker count individually. Resume resets breaker observations, leaving cap spend unchanged. Null for policy changes. An autonomy_state checkpoint stores only rung number, rung since timestamp, clean request count and last clean timestamp. Autonomy clean and breaker events have null intent; none stores prompt text.Settings written by you or an operator. Explicit metadata projection excludes messages, tool arguments, descriptions and answers. Model and tool identifiers are readable labels from the request or catalogue; a caller can choose what a declared tool name means. | Per request |
policy_sha256text | Digest of the evaluated or changed rulebook. | Per request |
prev_hashtext | The previous retained chain head, or 64 zeros when no preceding event remains. | Per request |
hashtext | SHA-256 of prior hash bytes and canonical event fields excluding id, prev_hash and hash. | Per request |
agent_profiles
Opt-in public agent cards and an internal mapping to the owned key for updates, removal and selected live rulebook summaries.
How long: Until unpublish or deletion of the key. Profile updates replace settings and certificates. Database backups and copies made by public readers can outlive deletion.
- Public: random slug, owner-written name, description, optional homepage, optional payout wallet, capability tags, only selected boolean rulebook categories, and selected router-issued certificates while signatures and expiry are valid. Publishing intentionally links certificate pseudonyms to this profile. The private key-hash mapping is never returned publicly; the router still knows it. Disabled or expired keys are hidden. No certificate or rulebook proves host sealing or hardware attestation, which is reported unavailable. User-written text can identify its owner. No inference prompt or answer is collected here.
| Column | What it holds | About a request |
|---|---|---|
slugtext | Random 144-bit public identifier independent of the key hash; regenerated after unpublish and republish. | Not about requests |
key_hashtext | Internal unique key association for ownership checks and current opted-in policy categories; never returned in public cards. | Not about requests |
settingsjsonb | Validated public display name, short description, optional HTTP(S) homepage, optional HTTPS agent endpoint (probed daily for liveness when AGENT_IDENTITY_ENABLED is on), optional payout wallet that other agents pay directly in USDG, capability tags and selected rulebook categories.Settings written by you or an operator. Owner-supplied publication settings deliberately become public. They contain bounded text and chosen category names, never a copied private rulebook or automatic key identifiers. | Not about requests |
certificatesjsonb | Latest router-issued certificate for the selected key and chosen claims; replaced or cleared on each publication update.Cannot hold request content. Strict signed claim identifiers, fresh pseudonym, issuance and expiry times, signing key identifier and signature. Valid certificates are public; expired or invalid certificates stay stored until update or deletion but are not returned publicly. | Not about requests |
agent_sessions
A short-lived sub-key for one agent run, with its own budget and expiry, so an agent's spending can be capped and ended.
How long: Ended sessions keep their row; a session ends at its expiry, when its budget is spent or when its owner ends it.
| Column | What it holds | About a request |
|---|---|---|
idtext | Session id. | Not about requests |
account_idtext | The account the session belongs to. | Not about requests |
parent_key_hashtext | The key that created the session. | Not about requests |
key_hashtext | The session's own key hash (a row in keys). | Not about requests |
nametext | A label the creator gave the session. | Not about requests |
budgetbigint | The session's spend cap in pico-USD; empty means only the parent key's limits apply. | Not about requests |
expires_attimestamp with time zone | When the session ends by itself. | Not about requests |
ended_attimestamp with time zone | When it ended. | Not about requests |
end_reasontext | ended, expired or budget. | Not about requests |
metadatajsonb | Labels the creator attached to the session: up to 32 short string, number or boolean values, 2 KB in all.Settings written by you or an operator. checkMetadata refuses key names that look like prompt or completion text (such as prompt or messages), at most 32 keys, string values of at most 256 characters and 2,048 bytes in all. It cannot judge what a creator types into a value, so the text is whatever the creator wrote. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
blind_keys
Issuer keys for blind tokens (Privacy Pass): one per epoch and denomination. Nothing here links a buyer to a token.
How long: The private half is wiped when the epoch stops issuing; the public half stays so old tokens remain verifiable.
| Column | What it holds | About a request |
|---|---|---|
key_idtext | The token key id: hex SHA-256 of the RFC 9578 public key info. | Not about requests |
epochinteger | The epoch the key issues in. | Not about requests |
denominationinteger | Token units a token from this key is worth. | Not about requests |
unit_pricebigint | Pico-USD per token unit, fixed when the key is made. | Not about requests |
spkitext | The public key, base64url. | Not about requests |
private_enctext | The private key, AES-GCM encrypted with APP_SECRET. Null once the key no longer issues. | Not about requests |
valid_fromtimestamp with time zone | When the key started. | Not about requests |
issue_untiltimestamp with time zone | When it stops signing new tokens. | Not about requests |
redeem_untiltimestamp with time zone | When tokens from it stop being accepted. | Not about requests |
revoked_attimestamp with time zone | When it was revoked, if it was. | Not about requests |
issuedbigint | How many tokens were signed: a count and nothing else. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
blind_nullifiers
Spent blind tokens, one row per token including each member of a request set reserved atomically. A row holds the SHA-256 of a token so it cannot be spent twice; the issuer cannot connect that hash to the blinded request it signed.
How long: A reservation is deleted if the request fails before anything is served; spent rows are kept so a token cannot be replayed.
| Column | What it holds | About a request |
|---|---|---|
nullifiertext | SHA-256 of the token. | Per request |
key_idtext | The issuer key that signed it. | Per request |
statustext | reserved while a request runs, spent once served. | Per request |
reserved_attimestamp with time zone | When the token was reserved. | Per request |
spent_attimestamp with time zone | When the request it paid for was served. | Per request |
generation_idtext | The generation the token paid for; all members of a set share it, linking those redeemed tokens to the same request but never to a purchase. | Per request |
byok_keys
A provider API key an account brought so calls to that provider use its own account there. Stored encrypted; only the router can decrypt it, to make calls for that account.
How long: Kept until the owner deletes it (DELETE /api/v1/byok/:provider removes the row).
| Column | What it holds | About a request |
|---|---|---|
idtext | Row number, counting up from 1. | Not about requests |
account_idtext | The account that brought the key. | Not about requests |
provider_idtext | The provider the key is for. | Not about requests |
key_enctext | The provider key, AES-256-GCM encrypted with the router's APP_SECRET. | Not about requests |
labeltext | A masked label so the owner can tell keys apart. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
key_topups
One row per auto top-up of a key's limit, and one per top-up the router skipped and why (once per key, reason, limit and week). No money moves: the limit is an allowance on the account's own balance. Activity and the inbox show these rows.
How long: No automatic deletion, and rows are never changed after they are written.
| Column | What it holds | About a request |
|---|---|---|
idtext | Random record id. | Summed from requests |
reftext | What triggered it: settle:<hold id> after a debit, reserve:<request id> when the key's limit would refuse a request, or skip:<key hash>:<reason>:<limit>:<week> for a skipped top-up. Unique, so each is recorded once. | Summed from requests |
key_hashtext | The key whose limit was raised. | Summed from requests |
account_idtext | The account the key belongs to. | Summed from requests |
outcometext | added, skipped_balance (the account's available credits did not cover the key's allowance after it), skipped_weekly (the rule's weekly maximum) or skipped_org_budget (the team's org budget). | Summed from requests |
amount_picobigint | The rule's top-up amount in pico-USD. | Summed from requests |
limit_before_picobigint | The key's limit before, in pico-USD. | Summed from requests |
limit_after_picobigint | The key's limit after; the same as before when skipped. | Summed from requests |
spent_picobigint | The key's spend counted against its limit when checked, in pico-USD. | Summed from requests |
available_picobigint | The account's balance minus open holds when checked, in pico-USD. | Summed from requests |
week_starttimestamp with time zone | UTC Monday 00:00 of the week the top-up counts in. | Summed from requests |
week_total_picobigint | Top-ups added to the key that week, including this one when added, in pico-USD. | Summed from requests |
max_per_week_picobigint | The rule's weekly maximum, in pico-USD. | Summed from requests |
created_attimestamp with time zone | When the row was created. | Summed from requests |
keys
One row per API key. The secret is never stored: the row holds its SHA-256 and a masked label. It also holds the key's limits, budget and spend.
How long: Deleting a key only disables it (DELETE /api/v1/keys/:hash sets disabled); the row stays because generations and balances refer to it.
| Column | What it holds | About a request |
|---|---|---|
key_hashtext | SHA-256 of the key's secret. The secret itself is never stored. | Not about requests |
chain_key_hashtext | keccak256 of the address derived from the secret, the id the on-chain contracts use for the key. | Not about requests |
key_addresstext | The blockchain address derived from the key's secret. It is public on chain when the key is funded.A wallet address, not a network address. A blockchain address derived from the key, not a network address of a caller. | Not about requests |
account_idtext | The account the key belongs to. | Not about requests |
parent_hashtext | For a key made from another key (an agent session), the parent's key hash. | Not about requests |
projecttext | Owner-chosen default project label, lowercased, 1–48 letters, digits, dots, underscores or hyphens. PATCH replaces or clears it. Not a secret; retained with the key even after disabling. | Not about requests |
nametext | The label the owner gave the key. | Not about requests |
labeltext | A masked display form of the key, such as sk-ar-v1-abcd...wxyz: the first and last few characters only. | Not about requests |
budgetbigint | The key's spend limit in pico-USD. Empty means unlimited. | Not about requests |
budget_resettext | How often the budget resets: daily, weekly or monthly, or never. | Not about requests |
period_starttimestamp with time zone | When the current budget period began. | Not about requests |
spentbigint | Spend in the current budget period, in pico-USD. | Summed from requests |
spent_totalbigint | All-time spend of the key, in pico-USD. | Summed from requests |
rpminteger | Requests-per-minute limit for the key. | Not about requests |
tpminteger | Tokens-per-minute limit for the key. | Not about requests |
team_idtext | The team the key belongs to, when it has one. | Not about requests |
allowed_modelstext[] | If set, the only models the key may call. | Not about requests |
allowed_ipstext[] | The owner-set list of up to 32 IPv4 or IPv6 addresses or CIDR ranges from which this key may be used. Null means no IP restriction. Observed request addresses are compared in memory and never copied here or logged by this feature.Settings written by you or an operator. Network restrictions written explicitly by the owner through key-edit authentication, validated as IPs or CIDRs. This is retained configuration, not a record of callers or calls. | Not about requests |
pay_with_defaulttext | The Stock Token symbol the key pays with by default. | Not about requests |
scopetext | Null keeps account access; inference permits model calls and this key’s own generation and receipt reads only; read permits only explicitly listed account GET records, with owner read visibility and no spending, writes, wallet actions or secret access. | Not about requests |
include_byok_in_limitboolean | Stored compatibility selection. Provider-side BYOK expenditure is not tracked; usage counts router-billed charges once. | Not about requests |
managementboolean | Whether the key may manage other keys. | Not about requests |
routingjsonb | Imported routing presets: model aliases and default provider preferences the owner set for this key.Settings written by you or an operator. Routing settings written by the key's owner and validated as aliases and provider preferences; there is no field for message text. | Not about requests |
guardrailsjsonb | The key's input guardrails: PII mode, phrases to block, a maximum input length and whether to redact output.Settings written by you or an operator. The owner's filter settings. Deny phrases are words the owner wants blocked (up to 50 of 200 characters); they are rules, not requests. | Not about requests |
tracingjsonb | Where the key's owner asked for traces of this key's public-lane calls to go (their own OpenTelemetry collector, Langfuse or Helicone), and whether to include prompt and completion text. The destination URL and credentials are AES-256-GCM encrypted with APP_SECRET and never returned by the API.Settings written by you or an operator. Destination settings written by the key's owner: a type, flags, a masked host, header names and one sealed string. The schema has no field for message text; content is only ever sent to the owner's destination, never stored here. | Not about requests |
topupjsonb | The key's auto top-up rule, or empty: below_usd, add_usd and max_per_week_usd. When the key has less than below_usd of its limit left, the router raises the limit by add_usd from the account's own credits, at most max_per_week_usd per UTC week.Settings written by you or an operator. Three numbers written by the key's owner and checked against a strict schema; there is no field for text. | Not about requests |
disabledboolean | Whether the key is turned off. | Not about requests |
expires_attimestamp with time zone | When the key stops working, if it expires. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
last_usedtimestamp with time zone | When the key last made a call. | Per request |
ohttp_keys
Oblivious HTTP gateway keys, one per epoch. Their public halves are published; each private half is destroyed when its epoch's window ends.
How long: The private half is destroyed when the epoch's acceptance window ends, after which recorded traffic for that epoch can no longer be opened. The public half stays.
| Column | What it holds | About a request |
|---|---|---|
epochinteger | The key's epoch. | Not about requests |
key_idinteger | The 8-bit key identifier of the key configuration (epoch mod 256). | Not about requests |
kem_idinteger | The HPKE KEM identifier. | Not about requests |
public_keytext | The public key, base64url. | Not about requests |
configtext | The encoded key configuration (RFC 9458), base64url. | Not about requests |
config_sha256text | SHA-256 of that configuration. | Not about requests |
private_enctext | The private key, AES-GCM encrypted with APP_SECRET. Null once destroyed. | Not about requests |
valid_fromtimestamp with time zone | When the key starts to be used. | Not about requests |
accept_untiltimestamp with time zone | Requests to this key are opened until here. | Not about requests |
revoked_attimestamp with time zone | When it was revoked, if it was. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
playbook_changes
A record of every playbook change (create, update, rename, delete) with its version, digest, rules and the number of keys following it; changes to a team's playbooks also appear in the team inbox.
How long: Rows remain until operator deletion, including after the playbook is deleted.
- G161: Optional work_hours keeps selected weekdays, local start/end clocks, an Intl-validated IANA time zone and refuse/ask_first mode in the existing readable rulebook JSON. Current rules, playbook copies and saved history retain it under their existing retention rules. No new table, column, Redis family, log field or request-body/address reader. The router still reads ordinary request text in memory.
| Column | What it holds | About a request |
|---|---|---|
idbigserial | Monotonically allocated change identifier. | Not about requests |
playbook_idtext | The playbook changed; kept after the playbook is deleted. | Not about requests |
account_idtext | The owning account. | Not about requests |
team_idtext | The owning team, or null for an account-wide playbook. | Not about requests |
nametext | The playbook's name after this change. | Not about requests |
actiontext | create, update (new rules and version), rename or delete. | Not about requests |
versioninteger | The playbook's version after this change. | Not about requests |
sha256text | SHA-256 of the canonical rules after this change. | Not about requests |
specjsonb | The rules as of this change, so each recorded digest can be checked.Settings written by you or an operator. A copy of a playbook's strict rulebook: owner-written configuration validated against a schema that excludes prompt and answer fields. | Not about requests |
followersinteger | How many keys followed the playbook when it changed. | Not about requests |
actortext | Hash of the principal key that made the change. | Not about requests |
notifyboolean | Whether the change belongs to a team (a team playbook, or an account-wide one in an account with teams); updates marked so appear in the inbox of the team's owners and admins. | Not about requests |
attimestamp with time zone | When the change was recorded, at millisecond precision. | Not about requests |
playbooks
Shared rulebooks (playbooks): one named rulebook that many keys of an account or team follow, so one change applies to all of them.
How long: Until a principal deletes the playbook. Deleting is refused while keys follow it unless they each keep its rules as their own.
- The rules are the same strict rulebook as agent_policies.spec and carry the same owner-written labels. The name is owner-written text of at most 100 characters. No prompt or answer fields are accepted.
- G161: Optional work_hours keeps selected weekdays, local start/end clocks, an Intl-validated IANA time zone and refuse/ask_first mode in the existing readable rulebook JSON. Current rules, playbook copies and saved history retain it under their existing retention rules. No new table, column, Redis family, log field or request-body/address reader. The router still reads ordinary request text in memory.
| Column | What it holds | About a request |
|---|---|---|
idtext | Random playbook identifier. | Not about requests |
account_idtext | The account that owns the playbook. | Not about requests |
team_idtext | The team whose owners and admins may change it, or null for an account-wide playbook that only management keys change. | Not about requests |
nametext | Owner-chosen name, unique within the account regardless of case. | Not about requests |
specjsonb | The playbook's current rulebook, validated by the same strict schema as a key's own rulebook.Settings written by you or an operator. The strict rulebook schema excludes prompt and answer fields. Model, tool and action labels are owner-written identifiers of at most 160 characters; their contents are whatever the owner chooses to write. | Not about requests |
sha256text | SHA-256 of the canonical rulebook JSON, the same digest each following key's rulebook carries. | Not about requests |
versioninteger | Counts rule changes: 1 at creation, plus one for each change of rules. A rename keeps it. | Not about requests |
created_attimestamp with time zone | When the playbook was created. | Not about requests |
updated_attimestamp with time zone | When its name or rules last changed. | Not about requests |
updated_bytext | Hash of the principal key that made the last change. | Not about requests |
policy_versions
Saved revisions of each key's rulebook, copied atomically when its rules are saved, restored, allowed next time or copied from a playbook.
How long: Until operator deletion, including after removal of the current rulebook. The migration copies the current rules only; it cannot recover earlier versions.
- Readable rulebooks include owner-written model, tool, action and target labels. Shape checks cannot judge the meaning an owner gives a label. No inference prompt or answer fields are accepted. Backfilled date and actor use the current row's last update, which can be a Stop or Resume.
- G161: Optional work_hours keeps selected weekdays, local start/end clocks, an Intl-validated IANA time zone and refuse/ask_first mode in the existing readable rulebook JSON. Current rules, playbook copies and saved history retain it under their existing retention rules. No new table, column, Redis family, log field or request-body/address reader. The router still reads ordinary request text in memory.
| Column | What it holds | About a request |
|---|---|---|
idbigserial | Monotonically allocated revision identifier; repeated saves of the same digest remain separate revisions. | Not about requests |
key_hashtext | The API key governed by this saved rulebook. | Not about requests |
sha256text | SHA-256 of the canonical rulebook JSON. | Not about requests |
specjsonb | Complete strict rulebook as saved, including caps, models, lanes, tools, hours, approvals, actions and optional rules.Settings written by you or an operator. The strict rulebook schema excludes inference prompt and answer fields; owner-written labels remain readable and may carry whatever meaning the owner chooses. | Not about requests |
saved_attimestamp with time zone | When the revision was retained; for the migration copy, the current rulebook row's last update time. | Not about requests |
saved_bytext | Hash of the principal key that saved this revision; backfill uses the current row's last updater. | Not about requests |
sourcetext | save, approve_and_allow, restore or playbook; backfill uses save for own rules and playbook for following keys. | Not about requests |
team_audit
A team's audit log: who changed members, keys, budgets, presets, routes and lane settings, and when. Each entry is hash-chained to the one before it, so an export can be checked offline (scripts/verify-audit.mjs). It records settings changes only, never what anyone asked a model.
How long: No automatic deletion, and rows are never changed after they are written. A database trigger rejects UPDATE and DELETE.
| Column | What it holds | About a request |
|---|---|---|
team_idtext | The team. | Not about requests |
seqinteger | The entry's position in the team's chain: 1, 2, 3, ... | Not about requests |
attimestamp with time zone | When the change was made. | Not about requests |
actortext | Who made it: key:<first 16 hex digits of the key hash>, passkey:<member id> or wallet:<address>. | Not about requests |
actiontext | What changed, such as member.join, key.create, budget.set, preset.save or route.update. | Not about requests |
targettext | What it changed: a key hash, member id, invite hash prefix, preset or route name. | Not about requests |
detailjsonb | A few fixed fields about the change: a role, a limit, a lane, a version and hash, the names of the fields that changed.Settings written by you or an operator. Fields chosen by the router for each action (src/teams/audit.ts, src/api/teams.ts): no free text from a call, and for presets only the version, hash and lane, never the system prompt. | Not about requests |
prev_hashtext | The previous entry's hash (64 zeros for the first entry). | Not about requests |
hashtext | sha256(prev_hash bytes || canonical JSON of the entry). | Not about requests |
team_members
Which keys are in which team and their role.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
team_idtext | The team. | Not about requests |
key_hashtext | The member key's hash. | Not about requests |
roletext | owner, admin, dev, viewer or agent (member is the older default). | Not about requests |
principal_idtext | For a key issued when a member signed in with a passkey or wallet, that member (team_principals.id). | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
team_principals
Members of a team who sign in without an API key: a passkey (WebAuthn) or a wallet. There is no email, name or device information: a passkey row holds only its credential id and public key (attestation is not requested), a wallet row only its address.
How long: Kept while the team exists; revoking a member disables the row and the keys issued to it.
| Column | What it holds | About a request |
|---|---|---|
idtext | Member id (tp_...). | Not about requests |
team_idtext | The team. | Not about requests |
kindtext | passkey or wallet. | Not about requests |
subjecttext | For a passkey, its credential id (random bytes the authenticator chose, base64url); for a wallet, its address. | Not about requests |
public_keytext | The passkey's public key (COSE, base64url). It can check signatures, not make them. | Not about requests |
alginteger | The passkey's signature algorithm: -7 ES256, -8 EdDSA or -257 RS256. | Not about requests |
sign_countbigint | The passkey's signature counter, so a cloned authenticator is noticed. | Not about requests |
roletext | The member's role: owner (the bound owner wallet), admin, dev or viewer. | Not about requests |
disabledboolean | Whether the member was revoked. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
last_usedtimestamp with time zone | When the member last signed in. | Not about requests |
teams
A team, also called an organisation: a named group of keys under one owning account, optionally bound to a wallet or a Safe, with an optional org budget.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idtext | Team id. | Not about requests |
nametext | The team's name, chosen by its owner. | Not about requests |
owner_accounttext | The account that owns the team. | Not about requests |
owner_addresstext | The wallet or Safe that owns the team, once it signed a one-time message (checked by recovery for a wallet, by EIP-1271 isValidSignature for a contract wallet). Empty until one is bound.A wallet address, not a network address. A blockchain address the owner chose to bind, not a network address of a caller. | Not about requests |
owner_kindtext | account (no wallet bound), eoa (a wallet) or contract (a Safe or another smart wallet). | Not about requests |
owner_verified_attimestamp with time zone | When the owner's wallet signature was checked. | Not about requests |
budgetbigint | The org budget in pico-USD: a cap on the sum of the limits of the team's keys. Empty means no cap. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
Providers & attestation
The provider registry and model catalogue, attestation results, measurements, disclosure profiles and the day-zero model lane.
attestation_events
The public proof-time record: one row per attestor run, canary run or change of the health probe's outcome.
How long: Rows older than ATTESTATION_HISTORY_DAYS (default 30) are pruned by the attestor job (pruneAttestationEvents); 0 turns recording off.
| Column | What it holds | About a request |
|---|---|---|
idserial | Row number, counting up from 1. | Not about requests |
provider_idtext | The provider. | Not about requests |
kindtext | attestation, canary or probe. | Not about requests |
tstimestamp with time zone | When it happened. | Not about requests |
okboolean | Whether it passed. | Not about requests |
reasontext | A failure code from a fixed list, empty when it passed. | Not about requests |
simulatedboolean | Whether the evidence came from development mode; never counts as a fresh attestation. | Not about requests |
tee_kindtext | The hardware type. | Not about requests |
attestation_hashtext | The report hash of a passing run. | Not about requests |
tls_spki_sha256text | SHA-256 of the certificate key the connection was pinned to, when pinned. | Not about requests |
measurementsjsonb | Digests and hardware registers of a passing run.Cannot hold request content. Only digests (image, compose, model) and register values; the table's comment states nothing raw from the provider is stored. | Not about requests |
measurement_changedboolean | Whether the measurement differs from the previous passing run. | Not about requests |
verifiersjsonb | The names of the verifiers that accepted the quote.Cannot hold request content. A list of verifier names configured by the operator. | Not about requests |
detailjsonb | Further check results as codes and numbers.Cannot hold request content. Written by the attestation-events code from fixed fields; the table's comment states nothing raw from the provider is stored. | Not about requests |
attestations
The result of each attestation run against a provider: whether it passed, the report hash and the measurements it committed to.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idserial | Row number, counting up from 1. | Not about requests |
provider_idtext | The provider. | Not about requests |
tstimestamp with time zone | When the run happened. | Not about requests |
okboolean | Whether it passed. | Not about requests |
tee_kindtext | The hardware type. | Not about requests |
report_hashtext | Hash of the report. | Not about requests |
noncetext | The fresh nonce the router sent to prove the report was made for this run. | Not about requests |
measurementsjsonb | The image, compose and model digests and hardware registers the report committed to.Cannot hold request content. Digests and register values taken from a verified report. | Not about requests |
detailjsonb | Why a run failed, or which verifiers accepted it, with the signing address and classifier flag, as short strings and flags written by the attestor.Cannot hold request content. Written by attestProvider about a report the router fetched with a fresh nonce. An attestation run starts from the router's schedule, so no caller's request can reach this column. | Not about requests |
canaries
Results of quantisation checks: known prompts sent to a provider to see whether it serves the precision it declares. Made from fixed prompts the router wrote itself, not from any customer request.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
model_idtext | The model checked. | Not about requests |
provider_idtext | The provider checked. | Not about requests |
tstimestamp with time zone | When the check ran. | Not about requests |
quant_matchboolean | Whether the result matched the declared precision. | Not about requests |
quant_guesstext | The precision the result looks like. | Not about requests |
distancereal | How far the result was from the reference. | Not about requests |
qualityreal | A quality score for the result. | Not about requests |
detailjsonb | The check's accuracy, how many prompts were answered, the declared precision and the fingerprint length.Cannot hold request content. Numbers and the declared precision written by runCanaries (accuracy, answered, declared, logprobs, fingerprint_tokens); the canary prompts are the router's own. | Not about requests |
canary_references
The reference fingerprint of a model at each precision, which canary results are compared to.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
model_idtext | The model. | Not about requests |
quanttext | The precision the fingerprint is for: bf16, fp8, int4 and so on. | Not about requests |
fingerprintjsonb | The model's output fingerprint at that precision for the router's own canary prompts.Cannot hold request content. A model-behaviour fingerprint (token probabilities on the router's own fixed prompts), not a device or network fingerprint and not a customer request. | Not about requests |
sourcetext | Where the reference came from. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
lane_candidates
New open-weights uploads found on Hugging Face that derive from an approved base model, with their evaluation status.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idserial | Row number, counting up from 1. | Not about requests |
hf_repotext | The repository. | Not about requests |
base_modeltext | The base model. | Not about requests |
revisiontext | The revision seen at discovery. | Not about requests |
licensetext | The licence. | Not about requests |
varianttext | The variant. | Not about requests |
creator_handletext | The uploader's handle. | Not about requests |
statustext | discovered, rejected, evaluated, failed, approved or servable. | Not about requests |
reasontext | Why a candidate was rejected. | Not about requests |
model_idtext | The catalogue model id it is served under. | Not about requests |
endpoint_providertext | The provider whose offer for the model is evaluated.A public address, not a caller's. A provider slug (a short name such as deepinfra), not a network address. | Not about requests |
source_created_attimestamp with time zone | When the repository was created. | Not about requests |
approved_bytext | Who approved it. | Not about requests |
approved_attimestamp with time zone | When it was approved. | Not about requests |
approval_notetext | A note written by the approving operator.Settings written by you or an operator. Free text written by an operator when approving a candidate; not derived from any request. | Not about requests |
servable_attimestamp with time zone | When it became servable. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
lane_claims
Creator royalty claims: the router issues a challenge, the uploader publishes it in their Hugging Face repository, and the router checks it.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idtext | Claim id. | Not about requests |
model_idtext | The model. | Not about requests |
hf_repotext | The repository. | Not about requests |
handletext | The uploader's Hugging Face handle. | Not about requests |
addresstext | The wallet address royalties are to be sent to.A wallet address, not a network address. A blockchain wallet address supplied by the creator, not a network address. | Not about requests |
challengetext | The challenge text the uploader must publish. | Not about requests |
statustext | pending or verified. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
expires_attimestamp with time zone | When the challenge expires. | Not about requests |
verified_attimestamp with time zone | When it was verified. | Not about requests |
onchain_txtext | The transaction that recorded the claim. | Not about requests |
lane_evals
One row per evaluation run of a candidate endpoint: refusal rate, capability score and canary accuracy. Made from fixed prompts the router wrote itself, not from any customer request.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idserial | Row number, counting up from 1. | Not about requests |
candidate_idinteger | The candidate evaluated. | Not about requests |
tstimestamp with time zone | When it ran. | Not about requests |
provider_idtext | The provider evaluated. | Not about requests |
model_idtext | The model evaluated. | Not about requests |
refusal_ratereal | Share of the benign probe prompts that were refused. | Not about requests |
capability_scorereal | Share of the exact-check prompts answered correctly. | Not about requests |
canary_accuracyreal | The canary exact-match score. | Not about requests |
canary_quant_matchboolean | Whether the canary matched the declared precision. | Not about requests |
passedboolean | Whether the candidate passed. | Not about requests |
detailjsonb | Scores and counts for the run.Cannot hold request content. Numbers written by the evaluation code; the prompts used are the router's own fixed sets. | Not about requests |
measurement_bundles
Signed measurement bundles: what a provider's measurement is made of, signed with the measurement key, recorded in a public log and verified by the router.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idserial | Row number, counting up from 1. | Not about requests |
provider_idtext | The provider. | Not about requests |
compose_hashtext | The deployment hash the bundle describes. | Not about requests |
bundle_digesttext | SHA-256 of the canonical bundle bytes. | Not about requests |
bundlejsonb | The bundle itself: the components a measurement is made of.Cannot hold request content. A signed, canonical bundle of digests and component names that an operator hands over and the router verifies. | Not about requests |
signaturetext | The bundle's signature, base64. | Not about requests |
signer_key_idtext | SHA-256 of the signer's public key info. | Not about requests |
statustext | pending, verified or rejected. | Not about requests |
rekor_uuidtext | The public-log entry id. | Not about requests |
rekor_entrytext | The entry hash inside that id. | Not about requests |
rekor_log_indexbigint | The entry's index in the public log. | Not about requests |
rekor_integrated_attimestamp with time zone | When the public log integrated it. | Not about requests |
rekor_entry_jsonjsonb | The public-log entry as the log returned it.Cannot hold request content. The response of a public transparency log for the bundle's entry (body, proof, signed timestamp). | Not about requests |
rekor_inclusion_verifiedboolean | Whether the inclusion proof verified. | Not about requests |
rekor_checkpoint_verifiedboolean | Whether the log's checkpoint signature verified. | Not about requests |
rekor_set_verifiedboolean | Whether the signed entry timestamp verified. | Not about requests |
checked_attimestamp with time zone | When the log was last checked. | Not about requests |
verified_attimestamp with time zone | When the bundle verified. | Not about requests |
errortext | Why the bundle was rejected or could not be checked.Cannot hold request content. An error string produced while verifying a bundle and its public-log entry; nothing in that check involves a caller's request. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
measurements
The image, compose and model digests a provider's confidential endpoint has been seen running, each bound into a hardware quote a verifier accepted, with whether the digest was found in a public log.
How long: History is kept: a superseded measurement gets superseded_at and stays.
| Column | What it holds | About a request |
|---|---|---|
idserial | Row number, counting up from 1. | Not about requests |
provider_idtext | The provider. | Not about requests |
image_digesttext | The container image digest. | Not about requests |
compose_hashtext | The hash of the deployment definition. | Not about requests |
model_digesttext | The digest of the model weights. | Not about requests |
statustext | observed, ready, registered or revoked. | Not about requests |
verifiertext | Which verifiers accepted the quote, comma separated. | Not about requests |
tee_kindtext | The hardware type. | Not about requests |
quotetext | The verified hardware quote, hex. | Not about requests |
quote_proof_hashtext | keccak256 of the quote bytes. | Not about requests |
report_hashtext | The attestation report hash that produced the row. | Not about requests |
attested_attimestamp with time zone | When it was attested. | Not about requests |
last_seen_attimestamp with time zone | When it was last seen. | Not about requests |
rekor_uuidtext | The public-log entry id, when found. | Not about requests |
rekor_entrytext | The entry hash inside that id. | Not about requests |
rekor_log_indexbigint | The entry's index in the public log. | Not about requests |
rekor_kindtext | The entry type. | Not about requests |
rekor_integrated_attimestamp with time zone | When the public log integrated it. | Not about requests |
rekor_inclusion_verifiedboolean | Whether the inclusion proof verified. | Not about requests |
rekor_checkpoint_verifiedboolean | Whether the log's checkpoint signature verified. | Not about requests |
rekor_checked_attimestamp with time zone | When the public log was last checked. | Not about requests |
rekor_errortext | The last error from checking the public log, as a short code or message.Cannot hold request content. An error string produced while looking up a public log entry; nothing in this lookup involves a caller's request. | Not about requests |
calldatatext | Prepared registry call data, when built. | Not about requests |
calldata_targettext | The registry contract it is for. | Not about requests |
calldata_built_attimestamp with time zone | When it was built. | Not about requests |
tx_hashtext | The registering transaction. | Not about requests |
registered_attimestamp with time zone | When it was registered. | Not about requests |
revoked_attimestamp with time zone | When it was revoked. | Not about requests |
superseded_attimestamp with time zone | When a later verified quote committed to other digests. | Not about requests |
superseded_byinteger | The row that replaced this one. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
models
The model catalogue: id, name, context length, modalities and creator.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idtext | Model id, author/slug. | Not about requests |
authortext | The author part of the id. | Not about requests |
nametext | Display name. | Not about requests |
descriptiontext | A short description of the model, from the provider listing or an operator.Settings written by you or an operator. Descriptive text about a model from provider listings; it is catalogue data, not a request. | Not about requests |
ctxinteger | Context length in tokens. | Not about requests |
max_outinteger | Maximum output tokens. | Not about requests |
archjsonb | Modality, input and output modalities, tokenizer and instruction type.Cannot hold request content. Fixed catalogue fields about the model: modality, input_modalities, output_modalities, tokenizer, instruct_type. | Not about requests |
hf_repotext | The Hugging Face repository the weights come from, when known. | Not about requests |
creatortext | The creator's payout address, when known. | Not about requests |
royalty_bpsinteger | The creator's royalty in basis points. | Not about requests |
created_unixinteger | When the model was created, in Unix seconds. | Not about requests |
models_lane
Per-model metadata for open-weights variants: which lane a model can be served on, its base model, licence and weights source.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
model_idtext | The model. | Not about requests |
varianttext | mainstream, native_low_refusal or abliterated. | Not about requests |
statustext | servable or candidate (not approved for serving). | Not about requests |
base_modeltext | The model it derives from. | Not about requests |
licensetext | The licence identifier from the weights' model card. | Not about requests |
weights_sourcetext | Where the weights come from. | Not about requests |
weights_revisiontext | The commit the weights were taken from. | Not about requests |
weights_digesttext | SHA-256 of the weights manifest, when there is one. | Not about requests |
creator_handletext | The uploader's Hugging Face handle. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
offers
What one provider charges to serve one model, and the model's features at that provider.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
model_idtext | The model. | Not about requests |
provider_idtext | The provider. | Not about requests |
provider_model_idtext | The id the provider uses for the model. | Not about requests |
price_promptbigint | Pico-USD per prompt token. | Not about requests |
price_completionbigint | Pico-USD per completion token. | Not about requests |
price_requestbigint | Pico-USD per request. | Not about requests |
price_imagebigint | Pico-USD per image. | Not about requests |
price_web_searchbigint | Pico-USD per web search. | Not about requests |
price_reasoningbigint | Pico-USD per reasoning token. | Not about requests |
price_cache_readbigint | Pico-USD per cached prompt token. | Not about requests |
price_cache_writebigint | Pico-USD per token written to cache. | Not about requests |
quanttext | Quantisation, such as fp8, or unknown. | Not about requests |
ctxinteger | Context length at this provider. | Not about requests |
max_outinteger | Maximum output tokens at this provider. | Not about requests |
supported_parameterstext[] | Request parameters the provider supports. | Not about requests |
featuresjsonb | Feature flags such as tools or json mode.Cannot hold request content. Feature flags and limits read from the provider's model listing; about the offer, not any request. | Not about requests |
is_moderatedboolean | Whether the provider moderates content. | Not about requests |
statustext | live, shadow or disabled. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
provider_disclosure
What a provider says, and can prove, about how it handles a prompt: retention, jurisdiction, legal hold and training use, each with a source and a date. Curated by an operator, or retention alone set after network sidecar attestation and signed host policy verification; nothing here comes from traffic.
How long: Kept and replaced in place when an operator updates a provider's profile or a network host passes admission or scheduled policy renewal; removed on network rejection.
| Column | What it holds | About a request |
|---|---|---|
provider_idtext | The provider. | Not about requests |
retentiontext | attested, policy or logs (the most conservative when there is no row). | Not about requests |
jurisdictiontext | The provider's jurisdiction, or unknown. | Not about requests |
legal_holdboolean | Whether a legal hold is declared; empty means not declared. | Not about requests |
legal_hold_notetext | A note on the legal hold, written by an operator.Settings written by you or an operator. Free text written by an operator about a provider's declared legal hold; it is not derived from any request. | Not about requests |
training_usetext | none, opt_in, yes or unknown. | Not about requests |
claimsjsonb | For each stated value, the document it comes from and its date.Cannot hold request content. A map of claim name to { source, as_of } written by an operator. Network admission and scheduled renewal record only retention with the checked host policy version and current time; the host dashboard reads this version and time to describe current build approval without storing another record; jurisdiction, legal hold and training use remain undeclared. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
providers
The provider registry: each upstream that serves models, how to reach it, its status, whether its software is attested, and its bond and payout details.
How long: Kept while the provider is listed; a provider that leaves is delisted (status), not deleted.
| Column | What it holds | About a request |
|---|---|---|
network_hostboolean | Whether this provider was created by wallet-authenticated self-serve network signup; false for existing providers.Settings written by you or an operator. A boolean indicating the admission path, despite its network-related name. It cannot contain an address or any text. | Not about requests |
network_modelstext[] | One to eight distinct requested model IDs supplied by the wallet operator, retained for network admission and re-application; separate from priced catalogue entries. | Not about requests |
network_reasonsjsonb | Current admission or scheduled renewal refusal reasons, returned publicly by the network status and host dashboard APIs.Cannot hold request content. Admission and scheduled renewal write policy and screening explanations and attestor failure messages about operator-supplied endpoints and model IDs. No inference body, key or contact is included; endpoint failure messages may name the host server. | Not about requests |
idtext | Provider slug, such as deepinfra. | Not about requests |
nametext | Display name. | Not about requests |
base_urltext | The provider's API address that the router calls.A public address, not a caller's. The address of a provider's server, set by the operator. It is not a caller's address. | Not about requests |
api_key_enctext | The router's own key at that provider, AES-256-GCM encrypted with APP_SECRET. | Not about requests |
kindtext | openai for a standard API, tee for an attested endpoint, sidecar for a network host. | Not about requests |
headersjsonb | Extra HTTP headers the router sends to that provider on every call, usually credentials. Stored only as one AES-GCM ciphertext under the router's APP_SECRET.Settings written by you or an operator. Fixed headers the provider's operator supplied in its application, stored encrypted (encrypted_v1). Nothing from a caller's request is ever written to it. | Not about requests |
data_policyjsonb | What the provider says about training on prompts, retaining them, retention days and zero-data-retention, as entered by the operator or the provider.Cannot hold request content. Fixed fields (training, retains_prompts, retention_days, zdr, moderated) validated on entry; about the provider's policy, not about any request. | Not about requests |
datacentertext[] | Regions the provider lists. | Not about requests |
attestedboolean | Whether the provider's last verified attestation passed. | Not about requests |
attestation_urltext | Where the provider publishes its attestation report.A public address, not a caller's. The address of a report on a provider's server, set by the operator. | Not about requests |
attestation_hashtext | Hash of the last attestation report the router verified. | Not about requests |
attested_attimestamp with time zone | When it was verified. | Not about requests |
tee_kindtext | The hardware type: tdx, snp, nvidia-cc, tinfoil or dev. | Not about requests |
classifier_enabledboolean | Whether the last verified attestation reported the in-enclave hard-block classifier as enabled. | Not about requests |
bond_usdgbigint | The provider's bond in USDG base units. | Not about requests |
anyr_stakebigint | The provider's $ANYR stake in base units. | Not about requests |
operatortext | The operator's name. | Not about requests |
payout_modetext | invoice or usdg. | Not about requests |
payout_addresstext | The wallet address payouts go to, when the provider is paid in USDG.A wallet address, not a network address. A blockchain wallet address for payouts, not a network address of a caller. | Not about requests |
statustext | applied, shadow, live, suspended or delisted; network signup uses pending, probation or rejected. | Not about requests |
shadow_untiltimestamp with time zone | When a shadow provider is due to be considered for live, or the end of a network host probation period. | Not about requests |
timeout_msinteger | Request timeout for this provider. | Not about requests |
static_modelsjsonb | A model list with prices for providers whose own listing lacks pricing, or network probation offers copied from the signed policy for requested quote-bound model IDs. Rejection clears this list and disables retained offers.Cannot hold request content. A list of model IDs, catalogue slugs, names, optional Hugging Face IDs and quantization, prices, token limits and text modalities entered by an operator and checked before it is applied. Network admission copies these terms only after published-policy signature and hardware quote binding verification. | Not about requests |
contacttext | A contact for the provider's operator, as given in the provider application.Settings written by you or an operator. A contact detail for the provider's operator, given by the operator in a provider application. It is not about callers. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
Chain
Blockchain events the router has read, escrow deposits, pay-with sessions and swaps, provider payouts and slashes.
agent_payments
One row per allowed pay.agent decision: who asked, the recipient wallet and amount Agent Guard allowed, and, once confirmed, the USDG transfer found on Robinhood Chain and the signed payment receipt. Anyroute never holds or moves this money; no balance changes. Disabled unless AGENT_PAY_ENABLED.
How long: No automatic deletion: no job or route in the code removes rows from this table. The status changes from seen to final at the chain's finality point, or to reversed if the transfer leaves the canonical chain within ESCROW_REORG_HORIZON_BLOCKS.
- Recipient and payer wallets and the transaction are public on chain and can be correlated with the agent key that asked. Paying a public profile id also stores that profile and its key hash, so the recipient's owner sees the payment in their inbox. An optional memo is accepted only as a SHA-256 digest; the memo itself is never sent to the router.
| Column | What it holds | About a request |
|---|---|---|
decision_idtext | The Agent Guard decision (agent_action_decisions.id) this payment belongs to; random, not a credential. | Per request |
key_hashtext | Hash of the paying agent key; only that key confirms the payment. | Per request |
account_idtext | Account of the paying key, whose linked wallets may send the transfer. | Per request |
policy_sha256text | Digest of the rulebook (or sorted rulebook digests) the decision was made under. | Per request |
recipient_profiletext | Public profile id that was paid, or that publishes the paid wallet; null for a wallet with no single profile. | Per request |
recipient_key_hashtext | Key hash behind that profile, used only to show the payment in its owner's inbox; never returned publicly. | Per request |
recipient_wallettext | Lowercase 0x wallet that receives the USDG. | Per request |
amount_unitsnumeric(78, 0) | Allowed amount in USDG base units (6 decimals). | Per request |
memo_sha256text | Optional SHA-256 digest of the payer's memo; the memo is not stored. | Per request |
statustext | awaiting_transfer, seen (waiting for finality), final or reversed. | Per request |
status_attimestamp with time zone | When the status last changed. | Per request |
created_attimestamp with time zone | When the row was created. | Per request |
tx_hashtext | The confirming Robinhood Chain transaction (public); unique with its log index. | Per request |
log_indexinteger | Log index of the USDG Transfer that pays the decision. | Per request |
block_numberbigint | Block of that transfer. | Per request |
block_hashtext | Canonical hash of that block when last checked. | Per request |
payer_wallettext | Linked wallet the USDG was sent from. | Per request |
paid_unitsnumeric(78, 0) | USDG base units actually transferred; counted against the daily action limit. | Per request |
verified_attimestamp with time zone | When the router first verified the transfer. | Per request |
checked_attimestamp with time zone | When it was last re-verified. | Per request |
reasontext | Fixed reason text when a payment is reversed. | Per request |
receiptjsonb | The signed payment receipt payload (anyroute.agent.payment.v1): decision, rulebook digest, payer, recipient, amounts, chain, transaction, block and status.Cannot hold request content. Canonical JSON built by src/agents/pay.ts from the fields of this row; wallets, hashes, amounts and fixed codes only, no request or answer text. | Per request |
receipt_sigtext | Ed25519 signature over the canonical receipt, by the router's receipt key; re-signed on each status change. | Per request |
receipt_key_idtext | Id of the receipt key that signed it. | Per request |
agreement_cursor
Finality-aware resumable agreement event cursor and cross-worker serialization lock.
How long: Public chain journal and projections remain until the operator removes the agreement index. Orphaned events and projections are removed and replayed on reorganization.
| Column | What it holds | About a request |
|---|---|---|
scopetext | Chain id, configured escrow and oracle addresses; isolates deployments. | Not about requests |
blockbigint | Last canonical scanned block number. | Not about requests |
block_hashtext | Hash at the canonical scan endpoint. | Not about requests |
checkpointsjsonb | Up to 128 scan endpoint block/hash pairs used to find a canonical reorg rewind point.Cannot hold request content. Only decoded public agreement event values and canonical block metadata are stored: wallets, USDG amounts, hashes, identifiers, bps and timestamps. No inference or evidence content is accepted into the chain journal or projection. | Not about requests |
checked_attimestamp with time zone | Caught-up scan time, zero during backfill. Jury, posting and deletion require freshness within 120 seconds. | Not about requests |
agreement_events
Reversible public AgreementEscrow event journal, bounded by confirmation and finality checks.
How long: Public chain journal and projections remain until the operator removes the agreement index. Orphaned events and projections are removed and replayed on reorganization.
| Column | What it holds | About a request |
|---|---|---|
scopetext | Chain id, configured escrow and oracle addresses; isolates deployments. | Not about requests |
tx_hashtext | Public transaction hash, unique with deployment scope and log position. | Not about requests |
log_indexinteger | Canonical log position in a block. | Not about requests |
blockbigint | Canonical event block number. | Not about requests |
block_hashtext | Event block hash checked against the RPC. | Not about requests |
eventtext | AgreementEscrow milestone lifecycle events and DisputeOracle TallyRecorded, PanelRequired and RulingPosted ABI event names. | Not about requests |
argsjsonb | Public event arguments: agreement id, payer/payee wallets, USDG base-unit amount, terms/deliverable/evidence hashes, milestone index, deadline, oracle address, review deadline, payout amounts, ruling path and verdict encoding, evidence root, jury version, participation and consensus bitmaps and tally hash. indexedEscrow and indexedOracle identify configured contracts. indexedAt is the canonical block timestamp.Cannot hold request content. Only decoded public agreement event values and canonical block metadata are stored: wallets, USDG amounts, hashes, identifiers, bps and timestamps. No inference or evidence content is accepted into the chain journal or projection. | Not about requests |
agreement_evidence
Party-uploaded text or JSON evidence, encrypted with APP_SECRET and hash-committed. Only the parties have REST access; the router and jury providers read the decrypted bundle.
How long: Evidence and signed jury statements are deleted after canonical resolution plus AGREEMENT_RETENTION_DAYS (30 by default), while agreement-retention runs with a fresh index. Parties may delete their own evidence after that interval. Backups follow the operator backup policy; deletion is not erasure from backups or chain.
| Column | What it holds | About a request |
|---|---|---|
scopetext | Chain id, configured escrow and oracle addresses; isolates deployments. | Per request |
agreement_idtext | Composite decimal agreement.milestone identifier from the configured escrow contract. | Per request |
disputetext | Canonical dispute transaction hash and log index, or before-dispute plus the creation transaction/log identity for earlier evidence; prevents reuse of a reorged id from exposing old content. | Per request |
partytext | Authenticated account wallet matched to the indexed payer or payee, never a caller IP. | Per request |
sha256text | SHA-256 of canonical JSON content before encryption; public to both parties. | Per request |
contenttext | AES-GCM encrypted canonical JSON evidence; may contain arbitrary text including prompts, deliverables and personal information. The router decrypts it for party detail and jury calls. Default cap 16 KiB per item and 32 entries per party. Evidence is not end-to-end encrypted through the router.Holds request text. The feature explicitly persists party-uploaded evidence content. Encryption at rest does not prevent the router or an operator with APP_SECRET from reading it. Only wallet-linked parties can retrieve it through these routes, and configured attested models receive it for adjudication. | Per request |
created_attimestamp with time zone | Time this record was first saved by the router. | Per request |
agreement_jury
Router-signed model jury statement and durable ruling intent for the canonical dispute. Complete hung tallies may enter the panel path; failed or abstaining votes remain unresolved until a valid tally or expiry. Default consensus status is dry_run.
How long: Evidence and signed jury statements are deleted after canonical resolution plus AGREEMENT_RETENTION_DAYS (30 by default), while agreement-retention runs with a fresh index. Parties may delete their own evidence after that interval. Backups follow the operator backup policy; deletion is not erasure from backups or chain.
| Column | What it holds | About a request |
|---|---|---|
scopetext | Chain id, configured escrow and oracle addresses; isolates deployments. | Summed from requests |
agreement_idtext | Composite decimal agreement.milestone identifier from the configured escrow contract. | Summed from requests |
disputetext | Canonical dispute transaction hash and log index, or before-dispute plus the creation transaction/log identity for earlier evidence; prevents reuse of a reorged id from exposing old content. | Summed from requests |
roottext | RFC 6962 SHA-256 Merkle root of canonical header and ordered party-evidence leaves. | Summed from requests |
statustext | dry_run, panel, submitted, posting_failed or posted. A dry_run does not send a transaction. Posted denotes a successful transaction receipt, with escrow state reconciled separately by the index. | Summed from requests |
statementjsonb | Signed jury scope, dispute, root, leaf digests, fixed rubric digest, model list, majority threshold, per-model verdict/reason or fixed failure code, receipt id/link/policy hash, internal router-signed operational receipt with request/response hashes, provider attestation reference including report hash/time/TEE/TLS pin, checked gateway receipt reference and upstream claims, provider-list-price operator cost estimate and token usage (not an invoice; failed calls may incur unmeasured cost), consensus bps, agreeing-model bitmap (separate from on-chain signer-order bitmaps), issuance time and trust notice. Model reasons may quote evidence text.Holds request text. Structured model verdict reasons are answer text and can repeat uploaded evidence. This statement therefore stores answer content openly in the inventory, behind party-only API access and resolution-based retention. The public key log contains public signing material. Chain calldata contains evidence root and per-key basis-point votes with EIP-712 signatures; the oracle records signer-order bitmaps and tally hash. The worker holds one operator-configured private key per model; models do not hold these keys. | Summed from requests |
key_idtext | Existing router Ed25519 receipt signing key id, published in the transparency key log when enabled and always before posting; dry-run can omit the key log. | Summed from requests |
signaturetext | Base64 Ed25519 signature over canonical statement JSON. | Summed from requests |
posting_txtext | Hash of the persisted oracle transaction, public once broadcast. | Summed from requests |
posting_rawtext | APP_SECRET-encrypted signed oracle transaction, saved before broadcast for identical nonce/byte retries. No private signer key is saved here. | Summed from requests |
created_attimestamp with time zone | Time this record was first saved by the router. | Summed from requests |
agreement_projection
Canonical agreement state rebuilt from the journal; both parties' wallet-linked accounts have API access.
How long: Public chain journal and projections remain until the operator removes the agreement index. Orphaned events and projections are removed and replayed on reorganization.
| Column | What it holds | About a request |
|---|---|---|
scopetext | Chain id, configured escrow and oracle addresses; isolates deployments. | Not about requests |
kindtext | Fixed agreement projection kind; each row is an individual milestone. | Not about requests |
idtext | Composite decimal agreement.milestone identifier from the configured escrow contract. | Not about requests |
datajsonb | Agreement id and creation transaction/log identity, public payer/payee wallets, amount, terms hash, ordered deliverable hashes, agreement deadline, milestone index, oracle address, review deadline and exact payout amounts, dispute identity/evidence hash/time, resolution time and public on-chain ruling. No uploaded evidence or model reasons.Cannot hold request content. Only decoded public agreement event values and canonical block metadata are stored: wallets, USDG amounts, hashes, identifiers, bps and timestamps. No inference or evidence content is accepted into the chain journal or projection. | Not about requests |
chain_cursor
How far the router has read each chain.
How long: One row per cursor, overwritten as the chain advances.
| Column | What it holds | About a request |
|---|---|---|
idtext | The cursor's name. | Not about requests |
blockbigint | The last block read. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
chain_events
Contract events the router has read from the chain, each processed once.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
tx_hashtext | The transaction. | Not about requests |
log_indexinteger | The log's position in the transaction. | Not about requests |
contracttext | The contract that emitted it. | Not about requests |
eventtext | The event name. | Not about requests |
block_numberbigint | The block. | Not about requests |
argsjsonb | The event's decoded arguments: addresses, amounts and hashes.Cannot hold request content. Decoded on-chain event arguments; public blockchain data. | Not about requests |
processedboolean | Whether the router has acted on it. | Not about requests |
processed_attimestamp with time zone | When it did. | Not about requests |
errortext | Why processing the event failed, when it did.Cannot hold request content. An error string from the chain indexer while handling a public on-chain event; the indexer never sees a request. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
commerce_transfers
When COMMERCE_STATS_ENABLED and COMMERCE_FUNDING_FROM_BLOCK are set, every USDG Transfer on the configured chain from that block on, so the commerce ledger can tell which wallets funded which. Public chain data only; no account, key, receipt or request is linked to a row.
How long: No automatic deletion: the funding filter reads the whole copy from the start block. Removed only when the operator drops the table or clears the copy.
| Column | What it holds | About a request |
|---|---|---|
tx_hashtext | The public transaction hash. | Not about requests |
log_indexinteger | The log's position in the transaction. | Not about requests |
block_numberbigint | The block. | Not about requests |
block_timetimestamp with time zone | The block's time. | Not about requests |
from_addresstext | The wallet the USDG left.A wallet address, not a network address. A lowercase blockchain wallet or contract address copied from a public USDG Transfer log; not a caller's network address. | Not about requests |
to_addresstext | The wallet the USDG went to.A wallet address, not a network address. A lowercase blockchain wallet or contract address copied from a public USDG Transfer log; not a caller's network address. | Not about requests |
value_usdgbigint | The amount in USDG base units, capped at the bigint maximum. | Not about requests |
authorizedboolean | Whether an EIP-3009 authorization of the sender moved it (an AuthorizationUsed log by the sender in the same transaction). | Not about requests |
tx_fromtext | For an authorized transfer, the public address that sent the transaction (the relayer); null otherwise. | Not about requests |
escrow_deposits
Stock Token, $ANYR and USDG transfers into the escrow wallet: one row per transfer, its price, its status and whether it was credited.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idtext | <transaction>:<log index>. | Not about requests |
tx_hashtext | The transaction. | Not about requests |
log_indexinteger | The log's position in the transaction. | Not about requests |
block_numberbigint | The block. | Not about requests |
tokentext | The token contract. | Not about requests |
symboltext | The token symbol. | Not about requests |
from_addresstext | The wallet that sent the tokens, as recorded on chain.A wallet address, not a network address. A blockchain wallet address that is public in the transfer itself; not a network address. | Not about requests |
raw_amountnumeric(78, 0) | The amount in token base units. | Not about requests |
statustext | pending_finality, pending, provisional (credited while settling), credited, orphaned or reversed. | Not about requests |
block_hashtext | The block hash when recorded; the credit is checked against it. | Not about requests |
account_idtext | The account it was credited to. | Not about requests |
price18text | USD per whole token at 18 decimals, as read from the price feed (USDG: exactly 1, credited at par). | Not about requests |
price_updated_attimestamp with time zone | When the feed last updated. | Not about requests |
creditedbigint | The pico-USD credited after the haircut. | Not about requests |
errortext | Why crediting failed, when it did.Cannot hold request content. An error string from the escrow indexer about an on-chain transfer; no request is involved. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
credited_attimestamp with time zone | When it was credited. | Not about requests |
checked_attimestamp with time zone | When the credit was last re-verified against the canonical chain. | Not about requests |
reversed_attimestamp with time zone | When a credit was reversed. | Not about requests |
review_reasontext | Set when an operator has to look: a reversal, or an orphan after finality. | Not about requests |
reviewed_attimestamp with time zone | Set once an operator has reconciled it. | Not about requests |
facilitator_settlements
One row per facilitator settle that passed verification: the payer's signed USDG authorization relayed straight to the seller's payTo (or to the treasury for a gas float top-up). (payer, nonce) is unique, so an authorization settles at most once here. Settled rows carry a signed receipt of kind facilitator.settle that joins the hourly anchor.
How long: No automatic deletion: no job or route in the code removes rows from this table.
- Payer, payTo, amount, nonce and transaction hash are the same facts the public chain shows for the transfer. Payers are not screened: the facilitator never holds the funds it relays.
| Column | What it holds | About a request |
|---|---|---|
idtext | Random settlement identifier (fst_ followed by 24 hex characters); also the receipt id. | Per request |
kindtext | payment, or gas_float for a seller's gas float top-up. | Per request |
payertext | Lowercase wallet address that signed the authorization. | Per request |
pay_totext | Lowercase wallet address the USDG went to. | Per request |
valuenumeric(78, 0) | Authorized USDG base units. | Per request |
noncetext | The authorization's EIP-3009 nonce. | Per request |
tx_hashtext | Relay transaction hash, once settled. | Per request |
statustext | verified (claimed, relay in flight), settled or failed. | Per request |
errortext | A fixed code for a failed relay (relay_failed).Cannot hold request content. A fixed code written by the facilitator code, never chain error text, a request body or an answer. | Per request |
seller_idtext | Listing the payment belongs to, when the payTo has one. | Per request |
x402_versionsmallint | x402 protocol version of the payment, 1 or 2. | Per request |
fee_valuenumeric(78, 0) | USDG base units of the facilitator fee authorization, when a fee is charged. | Per request |
fee_tx_hashtext | Transaction hash of the relayed fee authorization. | Per request |
gas_debitnumeric(78, 0) | USDG base units taken from the seller's gas float for this settle. | Per request |
settled_attimestamp with time zone | When the relay landed and the receipt was signed. | Per request |
receipt_cosetext | The signed receipt (base64 COSE_Sign1): network, asset, transaction, amount, payTo and fee. It names no payer. | Per request |
receipt_leaftext | The receipt's leaf hash in the hourly anchoring tree. | Per request |
receipt_key_idtext | Receipt signing key id. | Per request |
anchor_indexinteger | Anchor (Merkle root) this receipt was included in, once rooted. | Per request |
leaf_indexinteger | Position of the receipt's leaf in that anchor's tree. | Per request |
created_attimestamp with time zone | When the row was created. | Per request |
host_bond_cursor
Resumable HostBond event scan cursor, isolated by chain and contract. Serializes scans and slash intents across workers.
How long: Kept until the operator removes the bond index. Orphaned journal events and projections are removed on a chain reorganization; slash intent and evidence commitments are retained for idempotency.
| Column | What it holds | About a request |
|---|---|---|
scopetext | Chain id and HostBond contract address; public chain identifiers. | Not about requests |
blockbigint | Last scanned canonical block, or the deployment block minus one before scanning. | Not about requests |
block_hashtext | Canonical block hash at the scan cursor. | Not about requests |
checkpointsjsonb | Up to 128 scan endpoints as block number/hash pairs. Reorgs rewind to the newest matching checkpoint, or the deployment block when none remain canonical.Cannot hold request content. Contains only public HostBond event values or projections: wallet and contract identifiers, amounts, reason codes, hashes, flags and block times. No inference content or caller connection address is read. | Not about requests |
checked_attimestamp with time zone | Last caught-up scan time. Zero during backfill; routing boosts and slashing stop after 120 seconds without a caught-up pass. | Not about requests |
host_bond_events
Every decoded event from the configured HostBond deployment, including ownership and parameter changes. Reversible journal; no inference records are changed.
How long: Kept until the operator removes the bond index. Orphaned journal events and projections are removed on a chain reorganization; slash intent and evidence commitments are retained for idempotency.
| Column | What it holds | About a request |
|---|---|---|
scopetext | Chain id and HostBond contract address. | Not about requests |
tx_hashtext | Public transaction hash, unique with scope and log index. | Not about requests |
log_indexinteger | Log position within the canonical block. | Not about requests |
blockbigint | Canonical event block number. | Not about requests |
block_hashtext | Block hash checked against the RPC's canonical chain. | Not about requests |
eventtext | ABI event name, including Bonded, UnbondRequested/Cancelled/Unbonded, slash lifecycle, role, ownership and minimum changes. | Not about requests |
argsjsonb | Decoded public ABI arguments: bytes32 host id/evidence root/dispute hash, slash id, operator/recipient/role wallets, amount, total, reason, cooldown/dispute deadline and delisting flag. Numbers are decimal strings; no arbitrary transaction calldata is stored.Cannot hold request content. Contains only public HostBond event values or projections: wallet and contract identifiers, amounts, reason codes, hashes, flags and block times. No inference content or caller connection address is read. | Not about requests |
host_bond_projection
Reversible HostBond state reduced from the journal, with one row per host, slash or parameter set. The provider's existing bond_usdg field is left unchanged.
How long: Kept until the operator removes the bond index. Orphaned journal events and projections are removed on a chain reorganization; slash intent and evidence commitments are retained for idempotency.
| Column | What it holds | About a request |
|---|---|---|
scopetext | Chain id and HostBond contract address. | Not about requests |
kindtext | Projection kind: host, slash or parameters. | Not about requests |
idtext | Bytes32 host id, decimal slash id, or the fixed current parameter key. | Not about requests |
datajsonb | Host projections contain operator wallet, total and queued bond, unbond deadline and delisting flag. Slash projections contain host id, amount, contract reason, evidence root, dispute deadline/hash, status, approval generation and transaction history. Parameter projection contains minimum bond, approval generation, owner/pending owner, slasher and refund pool wallets. All values are public on-chain data.Cannot hold request content. Contains only public HostBond event values or projections: wallet and contract identifiers, amounts, reason codes, hashes, flags and block times. No inference content or caller connection address is read. | Not about requests |
host_slash_evidence
Hash-committed evidence of quote-bound host policy rejection and invalid receipts from the pinned host feed, plus durable proposal/execution intents. Disabled unless NETWORK_BONDS_ENABLED.
How long: Kept until the operator removes the bond index. Orphaned journal events and projections are removed on a chain reorganization; slash intent and evidence commitments are retained for idempotency.
| Column | What it holds | About a request |
|---|---|---|
scopetext | Chain id and HostBond contract address. | Summed from requests |
roottext | 0x-prefixed SHA-256 commitment of the exact canonical evidence bundle; primary key with scope prevents repeated proposal intents. | Summed from requests |
provider_idtext | Network provider id from the registry. | Summed from requests |
host_idtext | keccak256 of the provider id, matched to the HostBond operator before proposal.Cannot hold request content. A bytes32 contract host identifier, derived from the provider id with keccak256. It is not a caller connection address or a host's network endpoint. | Summed from requests |
canonicaltext | Exact canonical structured bundle: format, provider/host ids, fault kind, contract reason or null, policy version/hash where applicable, observed binding or receipt digest, attestation reference, receipt public key when applicable, and rejection digest. Contains hashes and identifiers only. Raw quotes, bindings, receipt envelopes, signature bytes, prompt and answer text are not retained here. A commitment does not by itself prove fault; review requires the source evidence. | Summed from requests |
reasoninteger | Contract MeasurementDrift code 0 for verified policy rejection; -1 means invalid receipt evidence awaiting policy review, never automatically proposed. | Summed from requests |
amounttext | Proposal amount in USDG base units: current whole bond at preparation, or would-be amount in dry run. Owner independently approves the exact proposal. | Summed from requests |
statustext | ready, review, dry_run, submitted, executing, cancelled or executed; always reconciled against the canonical journal before action. | Summed from requests |
proposal_txtext | Hash of the single persisted proposal transaction. | Summed from requests |
proposal_rawtext | APP_SECRET-encrypted signed proposal transaction. Saved before broadcasting; retries reuse identical bytes and nonce. The signed transaction becomes public on broadcast; no slasher key is persisted. | Summed from requests |
execution_txtext | Hash of the single persisted execution transaction. | Summed from requests |
execution_rawtext | APP_SECRET-encrypted signed execution transaction, saved before broadcast and reused on retry. Independent owner approval and the undisputed window are checked before preparation. | Summed from requests |
created_attimestamp with time zone | Time this exact evidence commitment was first stored. | Summed from requests |
makegood_payouts
On-chain make-good refund transfers: one USDG transfer from the refund treasury per payer per batch, signed and stored before it is broadcast so a retry resends the same transfer and never pays twice.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idtext | Transfer id. | Summed from requests |
payertext | Wallet address the refund is sent to. | Summed from requests |
usdgbigint | Amount in USDG base units: the sum of that payer's owed refunds in the batch. | Summed from requests |
statustext | signed (stored, possibly broadcast), paid (mined successfully) or failed (reverted; its refunds are owed again). | Summed from requests |
tx_hashtext | Hash of the signed transfer transaction. | Summed from requests |
signed_tx_enctext | The signed transaction bytes encrypted under APP_SECRET, kept to rebroadcast the identical transfer; never the treasury key. | Summed from requests |
created_attimestamp with time zone | When the transfer was signed. | Summed from requests |
settled_attimestamp with time zone | When it was seen mined or reverted. | Summed from requests |
network_payout_dispatch
Durable signed USDG transfer for a network payout. Written before broadcasting so recovery sends identical bytes and cannot pay again using another nonce.
How long: No automatic deletion, and rows are never changed after they are written.
- The signed transaction can authorize only its encoded transfer, but replaying it before inclusion broadcasts that transfer. It is encrypted with APP_SECRET and never exposed by public APIs. No private signing key is stored here. Reverted, destination-changed or nonce-conflicted transfers require operator reconciliation.
| Column | What it holds | About a request |
|---|---|---|
payout_idtext | The payout whose claimed invoices this transfer settles. | Not about requests |
signed_tx_enctext | Encrypted serialized signed blockchain transfer: chain, nonce, USDG contract, destination, amount and fees; no inference text or signing key. | Not about requests |
tx_hashtext | Hash of the signed transfer, fixed before first broadcast. | Not about requests |
paywith_debts
What a pay-with call owes in tokens, until a swap settles it.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idtext | Debt id. | Per request |
chain_key_hashtext | The key's chain hash. | Per request |
account_idtext | The account. | Per request |
generation_idtext | The generation that created the debt. | Per request |
tokentext | The token contract. | Per request |
amountbigint | Pico-USD owed. | Per request |
raw_estimatebigint | Estimated token units. | Per request |
fair_price18text | The fair price used, 18 decimals. | Per request |
swap_idtext | The swap that settled it. | Per request |
raw_allocatedbigint | Token units allocated to it by the swap. | Per request |
created_attimestamp with time zone | When the row was created. | Per request |
paywith_sessions
Pay-with sessions: a wallet's daily cap for paying with a Stock Token through a key.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
key_hashtext | The key's chain hash. | Not about requests |
wallettext | The wallet that opened the session. | Not about requests |
tokentext | The token contract. | Not about requests |
symboltext | The token symbol. | Not about requests |
cap_raw_daybigint | The daily cap in token base units. | Not about requests |
spent_raw_todaybigint | Spent today in token base units. | Summed from requests |
day_starttimestamp with time zone | When today's window began. | Not about requests |
activeboolean | Whether the session is active. | Not about requests |
opened_txtext | The transaction that opened it. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
paywith_swaps
Swaps that turn pay-with tokens into USDG to settle debts.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idtext | Swap id. | Summed from requests |
key_hashtext | The key's chain hash. | Summed from requests |
tokentext | The token contract. | Summed from requests |
raw_spentbigint | Token units spent. | Summed from requests |
fair_pricetext | The fair price used. | Summed from requests |
usdg_outbigint | USDG base units received. | Summed from requests |
txtext | The swap transaction. | Summed from requests |
statustext | pending, submitted, confirmed or failed. | Summed from requests |
errortext | Why the swap failed, when it did.Cannot hold request content. An error string from a swap transaction; no request is involved. | Summed from requests |
tstimestamp with time zone | When the swap was created. | Summed from requests |
allocationsjsonb | Which debts the swap settled and how much of it each got.Cannot hold request content. Debt ids and token amounts written by the pay-with aggregator. | Summed from requests |
slashes
Penalties proposed against a provider for empty answers, precision fraud, poor uptime or dropped parameters, with the evidence and where it stands.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
idtext | Slash id. | Summed from requests |
provider_idtext | The provider. | Summed from requests |
model_idtext | The model, when the penalty is per model. | Summed from requests |
kindtext | empty200, quant_fraud, uptime or param_drop. | Summed from requests |
amount_usdgbigint | The amount in USDG base units. | Summed from requests |
delistboolean | Whether the provider is delisted with it. | Summed from requests |
evidence_roottext | A Merkle root over the evidence. | Summed from requests |
evidencejsonb | The evidence: counts of requests and empty answers, canary results or uptime figures, and the window they cover.Cannot hold request content. Assembled by gatherEvidence in slasher.ts from counts, canary results and time windows; no request or answer text is read. | Summed from requests |
statustext | proposed, disputed, cancelled, executed or auto_refunded. | Summed from requests |
proposed_attimestamp with time zone | When it was proposed. | Summed from requests |
executable_attimestamp with time zone | When it may be executed. | Summed from requests |
executed_attimestamp with time zone | When it was. | Summed from requests |
dispute_hashtext | The hash of the provider's dispute. | Summed from requests |
disputed_attimestamp with time zone | When it disputed. | Summed from requests |
onchain_idtext | The id on chain. | Summed from requests |
tx_hashtext | The transaction. | Summed from requests |
refundedbigint | Pico-USD refunded to callers affected. | Summed from requests |
spent_roots
A Merkle root over every key's cumulative spend, posted on chain so balances can be settled.
How long: No automatic deletion: no job or route in the code removes rows from this table.
| Column | What it holds | About a request |
|---|---|---|
epochinteger | The epoch. | Summed from requests |
roottext | The Merkle root. | Summed from requests |
as_oftimestamp with time zone | The time the spend is counted to. | Summed from requests |
total_spent_usdgbigint | Total spend in USDG base units. | Summed from requests |
leavesjsonb | Pairs of a key's chain hash and its cumulative spend in USDG base units, in tree order.Cannot hold request content. [chainKeyHash, cumulativeSpentUsdg] pairs built from ledger totals. | Summed from requests |
tx_hashtext | The transaction that posted the root. | Summed from requests |
statustext | pending, submitted or confirmed. | Summed from requests |
created_attimestamp with time zone | When the row was created. | Summed from requests |
Operations
Settings you save (routes, presets, spend alerts) and the router's own key-value state.
character_memory
Character memory an account keeps: rolling summaries, facts and lorebook notes sealed on the account's own device (AES-256-GCM) under a viewing key the router never receives. The router stores ciphertext, never the memory's text, and cannot tell which character a memory belongs to.
How long: Kept until the account deletes it (DELETE /api/v1/memory/:id, or ?scope= / ?all=1 for many).
| Column | What it holds | About a request |
|---|---|---|
idtext | Memory id. | Not about requests |
account_idtext | The account that owns it. | Not about requests |
scopetext | An HMAC of the character id under the client's key: it groups one character's memories without naming the character. | Not about requests |
kindtext | summary, fact, lorebook or state, as the client labels it. | Not about requests |
sealedtext | The ciphertext the client sealed (arm1.<iv>.<ciphertext>); the API refuses anything that is not in this sealed form. | Not about requests |
key_idtext | A 16-hex fingerprint derived from the client's key, so the client can tell which key sealed it. The key cannot be recovered from it. | Not about requests |
bytesinteger | Size of the ciphertext in characters. | Not about requests |
embeddingreal[] | Only when the client opts in (embedding_opt_in): a vector the client computed from the memory, for similarity search. It cannot be turned back into the text, but it can reveal what the memory is about, so it is off by default. Empty otherwise. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
character_usage
Creator attribution for public characters: how many calls used each one and what they cost, summed per UTC day. It records no request, answer, key or caller.
How long: No automatic deletion: no job or route in the code removes rows from this table. Rows are deleted with their character.
| Column | What it holds | About a request |
|---|---|---|
character_idtext | The public character. | Summed from requests |
periodtext | The UTC day, YYYY-MM-DD. | Summed from requests |
callsinteger | Calls that used the character that day (never counted on the unlinkable lane). | Summed from requests |
costbigint | What those calls cost in total, in pico-USD. | Summed from requests |
characters
Character cards an account registers (Tavern Card v2 or v3). A public or unlisted card is text its creator publishes for others to use, kept as written. A private card is kept only as the ciphertext the owner's own device sealed, with the SHA-256 of the card; the router never receives its key or its text at rest.
How long: Kept until the owner deletes the character (DELETE /api/v1/characters/:id), which also deletes its attribution counters.
| Column | What it holds | About a request |
|---|---|---|
idtext | Character id, used as @character/<id>. | Not about requests |
account_idtext | The account that owns it. | Not about requests |
visibilitytext | public (listed in discovery), unlisted (readable by anyone with the id) or private (sealed, owner only). | Not about requests |
nametext | The card's name; empty for a private card. | Not about requests |
tagstext[] | The card's tags, lowercased, for discovery; empty for a private card. | Not about requests |
creatortext | The card's creator field as the card states it; empty for a private card. | Not about requests |
spectext | chara_card_v2 or chara_card_v3; empty for a private card. | Not about requests |
cardjsonb | The normalized card of a public or unlisted character: name, description, personality, scenario, greetings, example dialogue, system prompt, post-history instructions, tags, creator notes and lorebook. Empty for a private card.Settings written by you or an operator. Written by the card's owner through POST or PUT /api/v1/characters and normalized to the Tavern card fields, at most 512 KB. It is text a creator publishes for others to use, not text taken from a call: chats with the character are not stored here or anywhere else, and a private card is never stored in this column. | Not about requests |
sealed_cardtext | A private card as the owner's device sealed it: AES-256-GCM ciphertext under a key the router never receives. Empty for a public or unlisted card. | Not about requests |
card_hashtext | SHA-256 of the card's canonical JSON. For a private card the router checks a card sent with a chat against it before using it. | Not about requests |
default_modeltext | The model @character/<id> uses when a request names none. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
facilitator_sellers
Sellers who opted in to the facilitator's discovery index: the paid URL, a price hint, an output schema and tags, each listing signed by the seller's payTo key. Shown publicly at /facilitator/discovery/resources while listed.
How long: Kept until the seller replaces it with a later signed listing; listed false hides it from discovery. No job removes rows.
| Column | What it holds | About a request |
|---|---|---|
idtext | Random listing identifier (fsl_ followed by 24 hex characters). | Not about requests |
pay_totext | Lowercase wallet address the seller is paid at, which signed the listing. Public in every 402 response the seller sends. | Not about requests |
resourcetext | The seller's paid https URL as signed. The first payTo to list a URL owns that entry. | Not about requests |
price_hintnumeric(78, 0) | Price the seller states, in USDG base units; the seller's own 402 response stays authoritative. | Not about requests |
result_schemajsonb | JSON schema the seller published for its endpoint's result (x402 outputSchema), as signed.Settings written by you or an operator. Seller-written description of a public paid endpoint's result shape, signed by its payTo key and shown in discovery; never a caller's request or answer. | Not about requests |
tagstext[] | Up to ten lowercase words the seller chose for search. | Not about requests |
listedboolean | Whether the listing shows in discovery. | Not about requests |
signaturetext | The payTo key's EIP-712 signature over the listing. | Not about requests |
signed_attimestamp with time zone | issuedAt of the stored signature; only a later signature replaces the listing. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
host_policies
Public versions of the network host admission policy, signed with the transparency log's Ed25519 key. Publication alone does not admit providers; wallet-authenticated network admission verifies this policy before probation.
How long: No automatic deletion, and rows are never changed after they are written.
| Column | What it holds | About a request |
|---|---|---|
versioninteger | Consecutive policy version, beginning at 1. | Not about requests |
issued_attimestamp with time zone | The policy's issue time supplied by the operator. | Not about requests |
canonicaltext | Canonical JSON of the operator's policy: version, issue time, TEE kinds, approved sidecar image and source hashes, engine names and image digests, model IDs and digests, GPU CC requirements and optional model offer terms: catalogue slug, display name, Hugging Face ID, context and completion limits, quantization and positive USD-per-token prompt/completion prices. Offer terms are public operator-provided metadata, not inference content. A strict bounded schema accepts no prompt fields; names are operator-written identifiers with a restricted alphabet, so the router cannot know what meaning the operator assigns them. Public through the policy API. | Not about requests |
sha256text | SHA-256 of the exact canonical policy bytes. | Not about requests |
signaturetext | Base64 Ed25519 signature over the canonical policy bytes. | Not about requests |
verifier_keytext | The public signed-note verifier key identifying the log key that signed this version. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
kv
The router's small key-value store: job status, cursors, provider facts, sign-in challenges, Telegram state, notification settings and encrypted delayed notice text, including scheduled answer previews.
How long: Per key family: a wallet sign-in or team challenge is deleted when used and any older than 10 minutes is deleted when the next challenge is made; a team invite is deleted when used and expired ones when the next invite is made; a Telegram user's row is deleted by /forget; other families are overwritten in place.
- deposit-watch:<chain id>:<account id>:<transaction hash>: account-scoped submitted-deposit status. Keeps account id, lane (escrow or USDG), transaction hash and submission time, up to 20 submitted hashes per account. Removed after indexed credit, otherwise retained until operator deletion. No typed amount or sender is accepted; display amounts and senders come from public chain logs. The deposit list also caches decoded unindexed USDG logs in process memory for five seconds, containing public key hashes, sending wallets, amounts, transaction hashes and block numbers; it does not credit funds.
- fast-credit:lock: an empty singleton row locked during escrow crediting to serialize account and global outstanding-credit caps. Kept until operator deletion.
- fast-credit:deposit:<chain id>:<lane>:<transaction>:<log index>: durable provisional deposit bookkeeping. Stores chain and lane identity, account id, sending wallet, transaction and log index, block and canonical hash, fixed capped pico-USD total, provisional pico-USD amount, provisional/final/reversed status, ledger and reversal references and kinds, and escrow price with its timestamp and per-deposit cap marker. Final settlement changes state and credits only the remainder; reversals debit the provisional amount. Kept indefinitely for idempotency. No inference text or caller network address.
- deposit-ping:<chain id>:<deposit id>: account id, deposit id, notice timestamp and credited USD decimal amount. The worker reads newly credited $ANYR and stock deposits from the last day (including early credit), at most 100 per pass, and inserts one permanent marker per deposit. Inbox reads show up to 100 notices from the last 90 days under account-wide Activity access; ordinary and session keys receive none. Markers remain until operator deletion to prevent replay. Telegram sends once per eligible existing account link after the claim commits, using the current balance; a crash or failed send can lose delivery and is not retried. Telegram receives readable token amount, symbol, credited amount and account balance. No prompt, answer, API key, message text, new body reader or caller address is retained.
- telegram-link-code:<account id>: SHA-256 of a random single-use code, account id, principal key hash and expiry. One code per account, replaced on issuance, deleted on consumption/cancellation. Valid for five minutes; expired rows are purged on enabled polling or issuance. The code itself is returned once and stays in page memory until linking, cancellation or navigation; it is never saved in browser storage.
- telegram-link:<Telegram user id>: account id, owner/admin principal key hash, Telegram user id, random generation and linked timestamp. One account per Telegram identity and one identity per principal key. Kept until /unlink or DELETE /api/v1/telegram/link; disabling or expiring the key or removing its role prevents use. No API key or message text. Existing chat keys under telegram:user are separate.
- telegram-approval:<approval id>:<Telegram user id>:<link generation>: approval id, Telegram user id, generation, expiry, Telegram message id and fixed decision status. Delivery markers stop repeat polling sends and bind buttons to the originating message and current link. Deleted on unlink; expired markers are purged on enabled polling or issuance. Worker interruptions can repeat a notification; decisions use the dashboard's atomic logic. Telegram receives readable intent metadata and alerts, not inference messages or tool arguments. With AGENT_RULEBOOK_WORDS_ENABLED it also receives the current rulebook amount caps and approval thresholds (including inherited rules); this display text is not stored. Message text is never stored here.
- upstream-balance:<provider id>: latest USD balance (including zero and negative readings), check time and unknown/unsupported check state, with the last successful reading and its time retained across failed checks; upstream-credit-hold:<provider id>: expiry of a five-minute provider-wide routing hold after explicit insufficient credits. Balance readings at or below UPSTREAM_BALANCE_EXHAUSTED_USD (default 0) block routing until a later reading exceeds that threshold, including across restarts and failed polls. Enabled only by UPSTREAM_MONITOR_ENABLED. Overwritten in place; expired hold rows remain until operator deletion. No response text, API keys or caller identifiers are copied. Alerts use the existing alerts:state and alerts:lease rows and configured operations webhook. Balance state changes alert immediately with hashed provider check names; exhausted reminders are no more frequent than six hours. The alerts:state checks also retain the last delivered time for balance notices.
- agent-alerts:<account id>: newest 100 metadata-only owner alerts per account, visible for up to 90 days; expired feed, denial and dedupe metadata is purged on the next alert write or enabled worker cleanup, while inactive account rows remain until operator deletion; threshold cooldowns, denial counts with up to 10,000 recent timestamps and random transaction batch markers per key (10-minute rolling retention on writes/cleanup), timestamps, optional stopped_until deadline copied from the stopped policy for timed-stop alerts (also sent in webhook and Telegram delivery), key hashes, selected channels, delivery attempts, destination rule ids or Telegram ids and per-account delivery rate/lease state. No prompt, answer, intent, kill reason, webhook URL or API key is copied. Existing Spend Watch destinations are decrypted for guarded egress; existing Telegram principal links are decrypted and permission-checked before delivery. Email has no account destination. Delivery is at-least-once; a crash after sending can repeat an attempt.
- telegram:offset, telegram:user:<Telegram user id>: the update cursor, and per user the API key sealed under APP_SECRET, the chosen model and the private-mode switch (services/telegram.ts). Message text is not stored.
- wallet-login:<nonce>: a sign-in challenge (wallet address, the router's own origin, chain id, expiry and the message to sign). Deleted when used; older ones are pruned.
- team-invite:<sha256 of the invite>: a single-use team invite (team, role, how to join, expiry and the inviting key's hash). The invite itself is never stored. Deleted when used; expired ones are deleted when the next invite is made.
- team-challenge:<id>: a team join, sign-in or owner challenge (team, method, the WebAuthn challenge or the message to sign, and the wallet address when there is one). Deleted when used; older than 10 minutes are pruned.
- job-health:<job>, alerts:state, alerts:lease, backup:last: when each background job last ran, a fixed failure marker (operator job snapshots and queue failures redact configured private chain RPC URLs), alert state, an alert lease and the time and checksum of the last database backup.
- agreement-jury:heartbeat: written by the isolated agreement-jury worker each pass after its signer keys matched the DisputeOracle's jury on chain: the escrow and oracle addresses, threshold, the jury signers' public addresses and the time. GET /api/v1/status reads it to report whether automatic rulings are on. Overwritten in place; no evidence, verdict or key material.
- tls-pin:<provider>, aci-gateway:<provider>, aci-gpu:<model>, attest-policy:<provider>, attest-allow:<provider>, static-models-pending:<provider>, apply-token:<application id>: facts about providers (pinned certificate keys, verified gateway keysets, operator allow-lists, a pending model list, and the SHA-256 of an application token).
- paywith-allowance:<chain key hash>, paywith-intent:<chain key hash>, paywith-commitment:<commitment>: a signed pay-with allowance (wallet address and signature), the wallet and token a key holder registered for pay-with, and the swap a usage commitment belongs to.
- escrow:checkpoints, spent_settled:<epoch>, margin_unsent, holder-credits-run:<period>:<time>, ipx-oracle:*: chain cursors and settlement bookkeeping. margin_unsent retains accumulated protocol margin and provider-side fees in pico-USD; settlement reports the rounded USDG amount without transferring or clearing it.
- key-rotation:<key hash> in kv stores from and to key hashes, at, grace_ends_at and history_key_hash. The replacement keeps the old key's settings, team membership and principal, current policy and saved policy_versions (including saved-by attribution and dates), agent approvers, quiet-alert hour choice and spend-alert rules including sealed webhook destinations. Usage, delivery history, existing agent approvals and spend records stay with the old key. Quiet-alert delivery state and spend-alert history restart for the replacement. The security-alerts event stores a sanitized Key rotated title and actor under its existing family, and uses the existing security_alerts notification type, preferences and quiet-hour delivery. Browser sign-ins, Telegram link credentials and attestation records are not cloned; there is no new address reader, Redis family or log field. Rotation links remain with key history until account data is removed. Copied settings use the existing tables' retention. The secret exists in router response memory and the browser's reveal state until dismissed; it is never persisted by the rotation interface.
- agent-approvers:<agent key hash>: strict owners, owners_and_admins or specific_members mode and up to 100 unique team principal IDs or member key hashes. Stored only by an authenticated account management or team owner/admin key when AGENT_TEAM_APPROVERS_ENABLED is enabled; overwritten on each save and retained until removed by the operator or account data removal. No new table, column, Redis family or log field. Team membership, principal revocation, disabled/expired keys and agent sessions are rechecked at decision time; no requester can decide their own key or the same principal's requests. Existing agent_approvals.decided_by records the deciding key hash. Activity reads its current key name. With SECURITY_ALERTS_ENABLED, settings and decisions add existing security-alerts:event records with account/team, status, times and sanitized key names; the deciding name is captured then. Existing Telegram link families also accept eligible approvers when enabled; only delegated approval delivery uses their access, while other notifications and Stop retain owner/admin guards. Telegram receives readable approval metadata and current rulebook amount caps and thresholds, never inference text or tool arguments. Existing link-code expiry, single-use and delivery markers remain unchanged. Off preserves prior permissions and responses.
- security-alerts:event:<change id, policy event id, or team id and sequence> holds account id, nullable team id, inbox-arrival timestamp (recording time while pending), readable title and pending/inbox/muted state. Titles contain sanitized key and team names, management status, the kind of change and the acting key name. The request middleware holds only a digest of the presented Bearer key in an asynchronous request scope to correlate the already-authenticated team audit writer with its exact acting key; no credential is retained. Team audit entries authenticated by wallet or passkey name that member type instead of inventing a key. Wallet sign-in reads the already-verified account wallet in memory, keeping only its first six and last four characters in a sign-in title. Full wallet addresses, key secrets, prompt text, policy contents, stop reasons and Telegram messages are not copied. security-alerts:cursor keeps a processed-event count and lock; per-event states are the durable cursor so late commits and equal timestamps remain eligible. security-alerts:preference:<account id> keeps the enabled boolean. Telegram can read the security titles and key names it receives. Unlinked members receive no later alert, including their unlink notice; other eligible links may receive it. Claimed and muted event rows are removed after ninety days by enabled worker runs; pending events remain until claimed. Flag off pauses recording, delivery, inbox projection and cleanup. Events from before recording was enabled are not reconstructed. Preference and cursor rows remain until removed. Claims commit before one send attempt per eligible link: worker crashes, failed and ambiguous sends can leave an inbox item without Telegram delivery; sends are not retried. Key change hooks use the existing write boundaries; changes whose key write commits but notice write fails can miss a notice. Policy, team audit and Telegram notices commit with their source transaction. No new database table/column, Redis family or log field; the settings route is the only new request-body reader.
- sealed-agent:<key hash>: owner-selected HTTPS /attest URL, expected image digest and measured compose hash, random registration revision, last check timestamp, fixed success/failure code, verifier names and verified TLS SPKI hash. Overwritten on registration and each check; deleted by the principal's DELETE endpoint. No quote, certificate, API credential or inference content is stored. Owner-selected hostnames are settings and may carry meanings chosen by that owner. Records remain while disabled until explicitly removed; badge success expires after 30 minutes.
- J184: summaries also read existing reliability totals, savings estimates and catalogue metadata, retained watched-model notices (management only), current agent cap settings with posted ledger charges at week end and recorded cap refusals, and undecided approval expiry times. Sections and Inbox page links exist only in response memory or the existing Telegram delivery/quiet-hours payload. No new tables, columns, Redis families, logs, body or address readers. Historical cap settings are not retained; current settings apply. Source retention can omit older activity. Telegram can read these sections.
- Weekly summaries read existing agent call charges, key names, model names, approval statuses and stop events for the previous Monday–Sunday UTC. They send readable totals and names to Telegram, which can read them. The first eligible opted-in link receives one summary per account, restricted to that principal's current team if it is not a management key. Empty weeks are skipped. The existing link-action rate counter also limits summary attempts to twenty per minute per Telegram user; no message text is copied into Redis. The account's last_sent_week prevents ordinary repeat and concurrent sends. A crash or ambiguous network failure after Telegram accepts a send but before the database commits can repeat delivery.
- model-first-seen:<public model id>: the first catalogue observation in Unix seconds and a seeded flag. model-arrivals:seed: initialization marker and baseline time. Recorded during catalogue refresh only when MODEL_ARRIVALS_ENABLED is on (default false), retained until operator deletion including removed model IDs so reintroduction does not reset dates. Baseline model arrival dates are unknown and published as null; later observations are published as added_at and in the public models feed. No account, request, prompt, answer or address data, new Redis keys or log fields.
- quiet-agent-alert:<key hash>: per-agent hours (null means off), enable timestamp, last claimed quiet-period activity timestamp, and newest 100 notices with random id, timestamp, readable agent-name title, hour window and last charged-call/Guard-decision time. Settings and the dedupe anchor persist until operator deletion. Enabled runs and changed settings prune notices older than 90 days; disabled cleanup pauses, while inbox reads hide expired notices. Deleted keys leave inaccessible settings until operator deletion. No rulebook field, table, column, Redis family, address reader or log field is added.
- browser-session:<key hash> in kv keeps only a fixed browser-family and operating-system label derived from User-Agent at wallet sign-in. No full header, version, device model or network address is retained by this feature. Rows remain after sign-out because existing keys are disabled, not deleted; retained until operator deletion. Existing keys.created_at records sign-in, and keys.last_used records the last charged call, not browsing or every API request. Older wallet-issued root management keys have no browser label. Sub-keys, team keys and agent sessions are excluded from the browser list.
- notification-prefs:<account id> stores channel booleans and nullable from_utc/to_utc daily clocks. Weekly Telegram reads and writes only existing telegram-link weekly_summary_opted_in columns, and security Inbox/Telegram use the existing security-alerts:preference value with enabled as their aggregate for recording; the older security switch replaces that value and controls both. notification-quiet:<random id> stores account id, Telegram user id and link generation, source and principal key hashes, team id and management snapshot, notice category, due/creation times, a legacy-link marker and text encrypted under APP_SECRET. Text includes notice names and amounts, and can include scheduled answer previews. The router can decrypt these previews; Telegram can read delivered messages. No inference credential, new Redis key, address reader or log field is added. Browser component memory holds the settings and current local clock conversion; nothing new enters browser storage. Preferences remain until changed or removed. NOTIFICATION_QUIET_HOURS_ENABLED defaults false: only the enabled minute worker queues and flushes delayed Telegram notices. Approvals and approval reminders are never queued. Each tick reads at most 500 queue entries and sends one bounded-excerpt bundle per recipient and generation; larger backlogs can yield later bundles. Successful delivery removes entries; muted, revoked, unlinked or changed-scope entries are discarded. Failed sends remain for a later attempt. Entries older than seven days are discarded by enabled ticks; flag off pauses queue delivery and cleanup. Delivery can repeat after Telegram accepts a message before transaction commit. The worker revalidates current link, role, team, management status, source key ownership and scheduled-result owner rights. A source feature switched off pauses its queued notices until enabled or expired. Existing sender success counters treat skipped channels or durable queue acceptance as acknowledged delivery. Weekly last_sent_week is marked when a summary enters the queue; a later discarded summary is not resent. Daily clocks are saved in UTC using the device's current offset; saving again is needed after clock or time-zone changes. Future Telegram links retain the existing weekly opt-in default.
- approval-nudged:<approval id> in kv stores the claim time and approval expiry time. Existing telegram-approval:<approval id>:<Telegram user id>:<link generation> values additionally store reminder_message_id, the reminder's Telegram message identifier; original and reminder buttons use the same single-use approval. notification-prefs:<account id> adds Inbox and Telegram booleans for approval_reminders, both on by default. No new table, column, Redis family, log field, address or body reader. Reminder text uses existing readable approval metadata: agent name, routing or action identifiers, amounts and rulebook summaries, never prompt or answer text. Telegram can read delivered details. The router reads ordinary request text in memory. APPROVAL_NUDGES_ENABLED defaults false. Enabled non-API workers inspect up to 100 eligible approvals each minute. Claims commit before outbound delivery, preventing repeats across concurrent workers. Each current linked recipient is attempted once, with current authority and channel settings checked under the link and account locks. Quiet hours never delay reminders. A crash after claiming, an unavailable destination or a failed send can lose a reminder; it is not retried. Claims are deleted after approval expiry by enabled ticks, and pause while off; decided claims remain until expiry. Existing Telegram notices are pruned by Telegram delivery after expiry or unlinking. Preferences remain until changed or removed. The inbox countdown appears only to current decision makers, only while pending and unexpired, and uses existing approval response fields. No expiry or approval consumption changes.
- G159: notification-prefs channel choices and notification-quiet notice categories also include model_watch. Its delayed text contains only the public model name and availability wording, never inference content. Existing encrypted quiet-hour queue retention, feature rechecks and link authority apply.
- H169: notification-prefs channels also include status_incidents, default false for Inbox and Telegram. incident-notices:subscription:<account id> stores nullable per-channel opt-in timestamps, preserved across unrelated settings saves and reset when a channel is turned off and on. Subscriptions remain until changed or removed. incident-notices:change:<SHA-256 account id>:<SHA-256 incident/update identity> is both a unique claim and an inbox record; its value stores the claim id, account id, public update timestamp, incident id, public incident title with status prefix, public update text and whether Inbox was enabled at claim time. Only confirmed public investigating/identified/monitoring/resolved updates are read, never suggestion evidence, prompts, answers or addresses. SHA-256 update identity covers incident id, array index, update time, status and public text. The account hash is pseudonymous, not anonymous. An enabled worker checks every minute and replays up to 90 days after each channel's opt-in. Row locks and unique kv keys claim each account/change once across workers. Inbox records and claims older than 90 days are deleted by enabled ticks; disabling the feature pauses processing and cleanup. A claim commits before one Telegram attempt per current management link; a crash or failed send can lose that attempt and it is not retried by this worker. Quiet hours queue incident text using the existing encrypted notification-quiet family; its existing seven-day expiry, authority checks, channel checks and retry/possible repeated bundle delivery apply. Flag off pauses queued incident delivery. Inbox is management-only and filtered by the current channel preference. No new table, column, Redis family, application log field, body reader or address reader. Settings reuse the existing guarded notification settings reader. Ordinary inference request text remains readable by the router in memory.
- wallet-link:<random nonce> holds the owner account id, secondary wallet, origin, chain id, five-minute expiry and exact link message. Signatures are checked in memory and not retained. Successful linking consumes the row atomically. Expired rows are removed on later challenge requests once ten minutes old; without later requests they remain until removed.
- business-details:<account id> holds business_name, multi-line address, tax_id and reference in kv.value, linked to the account id in kv.key, plus kv.updated_at. The router reads these optional settings in memory. Statement reads with business_details=true add them beside payload, alg, key_id and sig; default statement responses are unchanged. The browser uses these current fields, including for earlier months, for the unsigned Billed to block, CSV and print/PDF. Signed JSON downloads omit them. There is no billing email field; the reference rejects email addresses, but free-text business identity fields can contain personal information supplied by the owner. Kept until replaced or deleted, without automatic expiry. Delete in Settings > Statements sends PUT with an empty object and removes the kv row; it does not remove earlier backups or exports on the caller's device. Browser memory holds the form and loaded statement details until navigation; no new browser storage. No new table, column, Redis family or log field.
| Column | What it holds | About a request |
|---|---|---|
keytext | The key, a family name plus an identifier (see the families above). | Not about requests |
weekly_summary_opted_inboolean | Nullable opt-in flag on telegram-link rows only. True enables a weekly Telegram summary for this link; false or empty means off. Deleted with the link on either unlink path. No request text or new tracking. | Not about requests |
valuejsonb | The value, as JSON. Its shape depends on the key family.Holds request text. Most families hold ids, hashes, timestamps, amounts and settings. The notification-quiet family additionally retains encrypted Telegram notice text, including previews copied from scheduled model answers. APP_SECRET lets the router decrypt them. Queue cleanup and retention are described under this table. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
model_watches
Account-selected models and durable availability debounce, pairing and inbox notice history.
How long: Until unwatch deletes the row, except a down claim within the rolling hour retains an inactive row with only the last-down cooldown and reset state. An enabled worker tick deletes expired inactive cooldowns and prunes active notices older than 30 days. Flag off pauses processing and pruning. Existing database backups follow operator retention.
- Up to 20 active rows per account; inactive cooldown rows do not count against the watch cap. Account and watch row locks enforce caps and single claims without new Redis keys. The worker reads shared health events and live offers/providers, including existing hashed health callers for the empty-answer outage rule. Five-minute holds reset on stale gaps; recovery requires a successful reading and a prior down claim. The one-hour cap is per account/model watch, measured from the down claim. Unwatch clears notices and open pairing state but preserves an unexpired last-down cooldown, so rewatching cannot bypass the hourly cap. Telegram attempts are claimed before sending and never retried after failure or interruption; unwatch does not erase already queued or delivered Telegram notices; an accepted quiet-hour queue entry uses the existing queue's delivery and retention rules. Inbox channel preferences filter notices at read time, and muting one channel can hide one half of the pair. No new application log fields, address readers or Redis families. Ordinary inference text remains readable by the router in memory.
| Column | What it holds | About a request |
|---|---|---|
account_idtext | Owning account id, associated with the owner's model choices. | Not about requests |
model_idtext | Public catalogue model identifier chosen by the account; never prompt or answer text. | Not about requests |
watchingboolean | Whether this is an active watch, or an inactive one-hour cooldown after unwatching. | Not about requests |
created_attimestamp with time zone | When the account most recently began watching this model. | Not about requests |
statejsonb | Candidate availability, candidate start time, last check, whether a down pair is open, last down claim time and up to 30 days of notices with random id, UTC time, public model id and availability title.Settings written by you or an operator. Only worker-created availability state and fixed notice wording plus a public catalogue model name are stored. The strict owner input is a catalogue id; this object never stores prompts, answers or caller addresses. | Not about requests |
network_waitlist
Network interest sign-ups, not host admission or attestation. Stores exactly the submitted role, hardware, readiness, continent, optional contact and payout preference, plus an id, deletion digest and time. Free text is private to the owner export; public statistics contain only counts.
How long: Until the participant deletes it with their code, or the owner deletes the list when the program launches or is cancelled. Program-wide removal is an owner operation; no automatic launch or cancellation signal exists.
- Hardware, readiness and contact are user-supplied text. Do not paste prompts or other sensitive information. The owner can read these fields through the ADMIN_TOKEN-protected read-only export. No network address or user agent is stored in this table. The delete code itself is returned once and never stored.
| Column | What it holds | About a request |
|---|---|---|
idtext | Random UUID identifying this sign-up, not an account or machine identity. | Not about requests |
roletext | Selected role: host_gpu, host_cpu, relay, witness or developer. | Not about requests |
hardwaretext | Hardware description typed by the participant, at most 200 characters; unverified free text, not a prompt sent to a model. | Not about requests |
readinesstext | Optional pasted readiness hints, at most 300 characters; unverified free text, not attestation or a prompt sent to a model. | Not about requests |
regiontext | Selected continent only; not inferred from a network address. | Not about requests |
contacttext | Optional contact typed by the participant, at most 120 characters; may identify them. Null when omitted or blank.Settings written by you or an operator. Voluntarily supplied contact for the owner to respond to interest, not a connection address read from the request. May contain an email, handle or any contact the participant chooses; kept privately until deletion. | Not about requests |
paid_intext | Payout preference only: usdg, anyr or any. Payouts are planned, not available. | Not about requests |
delete_code_hashtext | SHA-256 of a random 32-byte deletion code. The raw code is returned once to its holder. | Not about requests |
created_attimestamp with time zone | Server timestamp when the sign-up was saved. | Not about requests |
preset_versions
The versions of a preset an account calls as @preset/<name>[@<version>]: one row per saved version, never changed after it is written. A preset is a saved route plus the defaults a route cannot hold: a system prompt, a response_format and tool definitions the account owner writes.
How long: Kept until the account deletes the preset (DELETE /api/v1/presets/:name), which deletes every version.
| Column | What it holds | About a request |
|---|---|---|
idtext | Version id. | Not about requests |
account_idtext | The account that owns it. | Not about requests |
nametext | The name used in @preset/<name>. | Not about requests |
versioninteger | The version number: 1, 2, 3, ... per preset. | Not about requests |
hashtext | SHA-256 of the version's canonical JSON, so two versions with the same content have the same hash. | Not about requests |
configjsonb | The preset: models, provider preferences, sampling controls and, when the owner sets them, a description (up to 280 characters), a system prompt (up to 16,000 characters), a response_format and up to 32 tool definitions.Settings written by you or an operator. Written by the account owner through PUT /api/v1/presets/:name and validated by a strict schema (presetDocSchema) with size caps. The system prompt is text the owner saves as a setting, not text taken from a call: requests that use the preset are not stored here or anywhere else. | Not about requests |
sourcetext | put for a saved change, rollback for a version restored from an earlier one. | Not about requests |
restored_frominteger | The version a rollback copied; empty otherwise. | Not about requests |
created_bytext | The key that saved the version. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
sanctions_addresses
EVM-compatible digital currency addresses extracted from the public OFAC SDN XML for provider admission and USDG payout screening. No names or identity records are stored.
How long: Replaced atomically on a successful refresh; a failed refresh keeps the last good list.
| Column | What it holds | About a request |
|---|---|---|
addresstext | Lowercase 0x-prefixed 20-byte wallet address listed by OFAC.A wallet address, not a network address. A public digital currency wallet identifier from the SDN list, never a caller's IP or connection address. | Not about requests |
list_datetimestamp with time zone | Publication date from the SDN XML, at midnight UTC. | Not about requests |
source_hashtext | SHA-256 of the exact downloaded XML bytes; no XML or identity text is retained. | Not about requests |
sanctions_meta
Singleton metadata for the current sanctions list, exposed by GET /api/v1/network/sanctions.
How long: Replaced with the address list on a successful refresh; retained on failure.
| Column | What it holds | About a request |
|---|---|---|
idinteger | Singleton identifier, always 1. | Not about requests |
list_datetimestamp with time zone | Publication date from the SDN XML, at midnight UTC; this date determines freshness. | Not about requests |
source_hashtext | SHA-256 of the downloaded XML bytes. | Not about requests |
entry_countinteger | Number of distinct EVM-compatible wallet addresses stored. | Not about requests |
ignored_countinteger | Number of digital currency entries whose identifier is not an EVM-compatible 0x address. | Not about requests |
refreshed_attimestamp with time zone | When the successful download was stored, in UTC; does not reset the publication date's age. | Not about requests |
saved_routes
A saved routing policy an account calls as @route/<slug>: ordered fallback models, provider preferences and default sampling settings. It cannot hold prompt or system-prompt text.
How long: Kept until the account deletes the route (DELETE /api/v1/routes/:slug).
| Column | What it holds | About a request |
|---|---|---|
idtext | Route id. | Not about requests |
account_idtext | The account that owns it. | Not about requests |
slugtext | The name used in @route/<slug>. | Not about requests |
nametext | The route's display name, up to 80 characters. | Not about requests |
descriptiontext | A description written by the account, up to 280 characters.Settings written by you or an operator. A label the owner types about the route (limited to 280 characters). It is a setting, not a request; the API cannot tell what an owner chooses to write. | Not about requests |
configjsonb | The route: models, provider preferences and a closed list of sampling controls (temperature, top_p, max_tokens, seed, stop sequences and similar).Settings written by you or an operator. Validated by a strict schema (routeConfigSchema) that lists the allowed fields. There is no field for messages or system prompts; the only free text is up to four stop sequences of 32 characters. | Not about requests |
created_bytext | The key that created it. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
schedules
Owner-chosen recurring prompts and the key that pays for each ordinary chat call.
How long: Until the owner deletes the schedule. Deletion cascades to its saved runs. Database backups follow the operator's retention policy.
| Column | What it holds | About a request |
|---|---|---|
idtext | Random schedule identifier. | Not about requests |
account_idtext | Owning account identifier. | Not about requests |
owner_hashtext | Hash of the owner key that last saved the schedule; rechecked before each run. | Not about requests |
key_hashtext | Hash of the paying key; its normal budget, rulebook, lane and approval checks apply. | Not about requests |
nametext | Owner-chosen schedule name, also shown in inbox and Telegram. | Not about requests |
prompt_enctext | The complete owner-chosen prompt, encrypted with AES-GCM using APP_SECRET scoped to the account and schedule.Holds request text. This is stored prompt text, encrypted at rest with a router-held secret. The router decrypts it for scheduled inference; encryption does not prevent Anyroute from reading it. | Per request |
modeltext | Selected model identifier. | Not about requests |
cadencetext | Hourly, daily or Monday recurrence. | Not about requests |
time_utctext | UTC hour and minute for daily or Monday recurrence; null for hourly. | Not about requests |
max_cost_picobigint | Required per-run cost ceiling in pico-USD, checked against the normal worst-case hold before inference. | Not about requests |
pausedboolean | Whether automatic runs are paused, including after three consecutive failures. | Not about requests |
failuresinteger | Consecutive refused, failed or interrupted run count. | Not about requests |
next_attimestamp with time zone | Next due UTC instant; missed intervals are coalesced into one run. | Not about requests |
created_attimestamp with time zone | When the owner created the schedule. | Not about requests |
skills
Agent skills published to the Skills Hub: the manifest from SKILL.md, the files as one canonical tar, its SHA-256, where it came from and the static scan report. A skill is public content its author chose to publish; it is not a request.
How long: Kept while the hub lists the skill. A revoked skill stays, marked revoked, so its report and hash remain checkable.
| Column | What it holds | About a request |
|---|---|---|
idtext | Skill id: sk_ followed by the first 24 hex characters of content_hash. | Not about requests |
nametext | The skill's name from SKILL.md, up to 64 characters. | Not about requests |
slugtext | The name in lowercase letters, digits and hyphens. | Not about requests |
versiontext | The version from SKILL.md, up to 32 characters. | Not about requests |
descriptiontext | The description from SKILL.md, up to 1,024 characters.Settings written by you or an operator. Written by the skill's author in the SKILL.md frontmatter of a skill they publish; shown in the public registry. It is not a request to a model. | Not about requests |
authortext | The author named in SKILL.md, up to 80 characters. | Not about requests |
account_idtext | The publishing account, credited the author share of paid installs; empty for a mirrored skill. | Not about requests |
created_bytext | The key hash that imported the skill; empty for the mirror job. | Not about requests |
sourcejsonb | Where the skill came from: upload, git (repository URL, ref, commit, folder) or mirror (the registry index).A public address, not a caller's. The public repository URL, ref, commit and folder the importer named, or the registry index the operator configured in SKILLS_SOURCES. It identifies public code, not a caller. | Not about requests |
filesjsonb | The skill's files: path, type, mode, size and SHA-256 of each, in canonical order.Cannot hold request content. Paths, sizes, modes and hashes computed from the published archive. | Not about requests |
tar_sha256text | The content hash: SHA-256 of the canonical tar of the files, which a client checks after download and the key on chain (SkillRegistry). | Not about requests |
archivetext | The files as a gzipped canonical tar (base64), capped at SKILLS_MAX_BYTES unpacked. It is the published skill, served by the download route. | Not about requests |
sizeinteger | Unpacked bytes. | Not about requests |
file_countinteger | Number of files. | Not about requests |
leveltext | The scan level: trusted, caution or dangerous. | Not about requests |
scoreinteger | The scan score, 0 to 100. | Not about requests |
reportjsonb | The scan report: scanner version, score, level, counts per severity and each finding (rule, file, line, a 160-character excerpt of the skill's own file, severity).A public address, not a caller's. Computed by the scanner from the published skill's files; the excerpts are lines of those files. Nothing from any request is written here. | Not about requests |
price_usdgbigint | Install price in USDG base units (6 decimals); 0 for a free skill. | Not about requests |
revoked_attimestamp with time zone | When the operator revoked the skill. | Not about requests |
revoked_reasontext | The operator's reason for revoking it, up to 280 characters. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
spend_alerts
Alert rules on spend (threshold, share of a budget, anomaly), evaluated by the spend-watch job. They read spending totals, not requests.
How long: Kept until the account deletes the rule (DELETE /api/v1/spend/alerts/:id).
| Column | What it holds | About a request |
|---|---|---|
idtext | Rule id. | Not about requests |
account_idtext | The account. | Not about requests |
key_hashtext | The key the rule watches; empty means the whole account. | Not about requests |
kindtext | threshold, budget_pct or anomaly. | Not about requests |
windowtext | day, week or month. | Not about requests |
thresholdbigint | The spend threshold in pico-USD, for a threshold rule. | Not about requests |
pctinteger | The budget percentage, for a budget_pct rule. | Not about requests |
webhook_url_enctext | The address alerts are posted to, if the owner set one. Stored encrypted with the router's APP_SECRET.Settings written by you or an operator. A destination the account owner chose for alerts, stored only as ciphertext. It is not a caller's address. | Not about requests |
enabledboolean | Whether the rule is on. | Not about requests |
last_fired_attimestamp with time zone | When it last fired. | Not about requests |
last_periodtext | The period it last fired for, so it fires at most once per period. | Not about requests |
statejsonb | The rule's firing history and delivery status.Cannot hold request content. Firings and their delivery status written by the spend-watch job (period, amount, status, lease); it holds spend figures, never request content. | Not about requests |
created_bytext | The key that created it. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
status_dp_hours
The differentially private hourly releases of the private-lane counters (the same releases GET /api/v1/stats publishes), copied as released so the status page can show 90 days for the attested and unlinkable lanes. Copying and summing released values is post-processing: it spends no privacy budget and adds nothing about any request.
How long: Deleted after 91 days by the status loop (services/slo.ts pruneStatus).
| Column | What it holds | About a request |
|---|---|---|
instancetext | A random id of the router process that released the hour (a new one each start), so the releases of several processes can be summed. | Summed from requests |
hourtimestamp with time zone | The UTC hour the release covers. | Summed from requests |
epsilonreal | The privacy budget the release spent (the sum over its families). | Summed from requests |
countsjsonb | The released noisy counts: requests per lane, refusals per fixed reason and requests per fixed latency bucket.Cannot hold request content. Three objects of noisy integers keyed by the fixed, public label lists of lib/dpstats.ts and services/private-stats.ts, copied from a release that was already public. No request, key or time finer than the hour. | Summed from requests |
status_incidents
Incidents on the public status page: written by the operator through the incident API, or recorded as a suggestion when a lane's availability falls below its target (a suggestion is not shown until the operator confirms it).
How long: No automatic deletion: the incident history is part of the public record.
| Column | What it holds | About a request |
|---|---|---|
idtext | Incident id (inc_... for an operator's incident, sug_... for an automatic suggestion). | Not about requests |
titletext | The incident's headline, up to 140 characters.Settings written by you or an operator. Written by the operator through POST /api/v1/status/incidents (or a fixed sentence for a suggestion). It is a status notice, not a request. | Not about requests |
statustext | suggested, investigating, identified, monitoring, resolved or dismissed. | Not about requests |
impacttext | none, minor, major or critical. | Not about requests |
lanesjsonb | The privacy lanes affected.Cannot hold request content. An array of lane names from the fixed list public, attested, unlinkable. | Not about requests |
surfacesjsonb | The API surfaces affected; empty for all.Cannot hold request content. An array of surface names from the fixed list in services/slo.ts. | Not about requests |
sourcetext | operator or auto. | Not about requests |
updatesjsonb | The status updates, oldest first: time, status and the operator's text (up to 2,000 characters each).Settings written by you or an operator. Each update is a time, a status from a fixed list and text the operator writes through POST /api/v1/status/incidents/:id/updates; a suggestion's first update is a fixed sentence with numbers. No request text is ever written here. | Not about requests |
evidencejsonb | For an automatic suggestion: the lanes, surfaces, window, measured availability, target, request count and whether the figure was DP-noised.Cannot hold request content. Numbers and names from fixed lists, computed from status_windows or status_dp_hours, which are themselves sums. | Not about requests |
started_attimestamp with time zone | When the incident began. | Not about requests |
resolved_attimestamp with time zone | When it was resolved. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
status_windows
The public status page's record of the public lane (GET /api/v1/status/slo): per API surface and five-minute bucket, how many public-lane requests succeeded, failed with a 5xx, were refused with a 4xx or were rate limited, and how many served requests fell in each fixed latency bucket. Requests on the attested and unlinkable lanes are never counted here.
How long: Deleted after 91 days by the status loop (services/slo.ts pruneStatus).
| Column | What it holds | About a request |
|---|---|---|
surfacetext | The API surface: chat, embeddings, batch, messages, ollama or rerank. | Summed from requests |
buckettimestamp with time zone | Start of the five-minute bucket (UTC). | Summed from requests |
okinteger | Public-lane requests answered with a 2xx or 3xx. | Summed from requests |
failedinteger | Public-lane requests answered with a 5xx: these count against availability. | Summed from requests |
rejectedinteger | Public-lane requests refused with a 4xx other than 429: the caller's error, not counted against availability. | Summed from requests |
rate_limitedinteger | Public-lane requests refused with a 429. | Summed from requests |
latencyinteger[] | Served public-lane requests per fixed latency bucket (the edges in lib/dpstats.ts), in edge order: time to first token for streams, time to the full response otherwise. | Summed from requests |
tool_canary_runs
Results of the daily paid canary probe of each listed tool: whether the known answer came back, latency, a failure code, what the probe paid and the settlement transaction.
How long: Deleted after 90 days by the canary job; deleted with the listing.
| Column | What it holds | About a request |
|---|---|---|
idbigserial | Run id, a sequence number. | Not about requests |
seller_idtext | The tool listing probed. | Not about requests |
okboolean | Whether the answer matched the listing's known answer. | Not about requests |
latency_msinteger | Time for the probe. | Not about requests |
failuretext | A fixed failure code, or null. | Not about requests |
price_unitsbigint | What the probe paid, in USDG base units, if it paid. | Not about requests |
settle_txtext | The settlement transaction hash the seller reported, if any. | Not about requests |
attimestamp with time zone | When it ran. | Not about requests |
tool_listings
x402 tools a seller account listed for the paid tool catalog (/tools), each with a known-answer canary probe and its current probe state. A Skills Hub skill's paid invocation is a listing that names the skill.
How long: Until the listing account removes it (the row stays with status removed so the address cannot silently change hands); delisted rows stay to show why.
| Column | What it holds | About a request |
|---|---|---|
idtext | Listing id (tl_...), also the seller id on tool calls and canary runs. | Not about requests |
account_idtext | The account that listed the tool. | Not about requests |
created_bytext | Key hash that listed it; never a raw API key. | Not about requests |
skill_idtext | The Skills Hub skill whose paid invocation this is, or null. | Not about requests |
nametext | Seller-written tool name, up to 80 characters. | Not about requests |
summarytext | Seller-written one-line summary, up to 280 characters. | Not about requests |
resourcetext | The tool's public https origin and path, without a query string. | Not about requests |
methodtext | GET or POST. | Not about requests |
price_unitsbigint | The price the tool quoted in its 402 when listed, in USDG base units. | Not about requests |
pay_totext | The seller's payTo wallet from that quote; calls are refused if the live quote names another wallet. | Not about requests |
networktext | The x402 network name of that quote. | Not about requests |
canaryjsonb | The seller-written probe: method, optional query arguments and JSON body, and the expected substring or SHA-256 of a correct answer.Settings written by you or an operator. Written by the listing account and validated against a strict schema; it describes a public probe, never a caller's request or answer. | Not about requests |
statustext | listed, delisted (three failed probes in a row) or removed. | Not about requests |
failuresinteger | Consecutive failed canary probes. | Not about requests |
delisted_attimestamp with time zone | When the canary rule delisted it. | Not about requests |
checked_attimestamp with time zone | When it was last probed. | Not about requests |
created_attimestamp with time zone | When the row was created. | Not about requests |
updated_attimestamp with time zone | When the row was last changed. | Not about requests |
webhook_deliveries
Durable event references, duplicate suppression and delivery attempt metadata without webhook bodies.
How long: Terminal records are deleted after 90 days by the enabled worker; pending records remain until attempted or cancelled. Destination removal cascades deletion. Each event has at most three recorded attempts, and the API returns the last 100 attempts.
| Column | What it holds | About a request |
|---|---|---|
idtext | Random internal delivery identifier. | Not about requests |
destination_idtext | Owned destination association. | Not about requests |
event_idtext | Stable identifier sent in the event header, shared across retries for duplicate suppression. | Not about requests |
eventtext | Fixed event type name; endpoint.check is an owner-requested connectivity notice. | Not about requests |
referencetext | Source identifier only, such as a ledger, policy event, agreement or host id. No source body is copied. | Not about requests |
event_attimestamp with time zone | Source event time used for retention and ordering. | Not about requests |
event_statustext | Fixed source status at discovery, not arbitrary source text. | Not about requests |
attemptsinteger | Claimed delivery attempt count, capped at three. | Not about requests |
statustext | Fixed delivery state: pending, delivered, blocked, failed or cancelled. | Not about requests |
http_statusinteger | Receiver HTTP status code, never its response body. | Not about requests |
latency_msinteger | Elapsed time for the attempted send in milliseconds. | Not about requests |
attempted_attimestamp with time zone | When the most recent result was recorded. | Not about requests |
next_attempttimestamp with time zone | Retry lease and due time; ordinary retries wait five minutes. | Not about requests |
historyjsonb | Up to three attempt timestamps, delivery state, HTTP status, latency and retry count.Cannot hold request content. Fixed result codes and numeric timing/count metadata only; excludes webhook bodies, receiver bodies, URL, signature headers, signing secret and exception text. | Not about requests |
webhook_destinations
Owner-controlled HTTPS destinations, encrypted signing credentials and subscriptions for account event notices.
How long: Until destination removal or linked Spend Watch rule deletion. Revocation erases the encrypted signing key and stops deliveries; database backups can outlive removal.
| Column | What it holds | About a request |
|---|---|---|
idtext | Random destination identifier, scoped to one account. | Not about requests |
account_idtext | Account whose owner manages this destination. | Not about requests |
created_bytext | API key hash used for visibility and authorization; never a raw API key. | Not about requests |
key_hashtext | Optional key scope inherited from a Spend Watch rule; null is account-wide. | Not about requests |
rule_idtext | Optional linked Spend Watch rule identifier, removed with that rule. | Not about requests |
url_enctext | HTTPS URL encrypted under APP_SECRET; path and query can hold receiver credentials. API responses show scheme and host only.Settings written by you or an operator. Owner-supplied delivery endpoint sealed using APP_SECRET, never the caller network address. URLs can identify the receiver and carry credentials, so only scheme and host are returned. | Not about requests |
secret_enctext | Server-generated random signing secret encrypted under APP_SECRET, null for an unsigned legacy or revoked destination. Plaintext is revealed only on creation or rotation, never in subsequent reads or delivery logs. | Not about requests |
revokedboolean | Whether delivery has been stopped and its signing credential removed. | Not about requests |
eventsjsonb | Selected fixed event type identifiers.Settings written by you or an operator. Strict event names chosen by the owner, excluding arbitrary text, addresses, prompts or answers. | Not about requests |
scanjsonb | Bounded reader progress: time window, activity cursor and sweep time.Cannot hold request content. Only timestamps, pagination filter digest and event identifiers; no activity bodies, intent text, endpoint URL or credentials. | Not about requests |
created_attimestamp with time zone | Creation time and lower bound for event discovery. | Not about requests |
In your browser.
What this website keeps in your own browser. None of it is sent to us except the requests you make.
The prompt library keeps names, text, tags, pins, optional model choices and system prompts in this browser until you delete them or clear browser storage. Ordinary prompts use the anyroute-harness-prompts-v1 localStorage key without encryption. Private-mode prompts share the encrypted anyroute-private-history IndexedDB vault and its passphrase; locking or forgetting history also locks or deletes them. Where IndexedDB is unavailable, private prompts last only for this tab. The two libraries stay separate. JSON exports contain readable prompt data, including system prompts. Prompts are sent through the existing chat path only when you submit them. Prompt storage source · Encrypted storage source
IndexedDB (existing encrypted Chat history vault): Opt-in Chat folders keep up to 40 folder ids and names plus each saved chat's optional folderId inside the same passphrase-encrypted anyroute-private-history vault as chats and private prompts. No additional browser storage key or server table, column, Redis family or log field is created. Unlocked folder names, assignments, counts, selection and search text live in page memory; counts are derived from chats and selection/search are not persisted. A drag carries only a chat id in browser drag data. Deleting a folder removes its assignments and keeps every chat. Locking drops the decrypted folders with history; Forget deletes the vault. Without browser storage the existing memory fallback lasts only for the tab. JSON downloads expose readable chats, folder ids/names and assignments, including empty folders in a full-history export; single-chat downloads include only its folder. Import validates and merges this metadata in one encrypted write, maps colliding folder ids and keeps existing chats. Markdown exports omit folder organization. Folder operations do not upload data; ordinary inference requests are still read by the router in memory. web/lib/chat-folders.jsSession storage (anyroute-model-compare-v1): Up to three public model IDs selected for comparison. Clear picks removes the selection; session storage lasts until the tab closes. Blocked storage falls back to page memory until navigation. Comparison links expose selected IDs in the URL to recipients and ordinary web request handling. Public models, providers and endpoint responses are read without an account key and held in page memory. No prompts, answers, wallet addresses or account secrets are read by comparison code. No new table, column, Redis key family or log field. Ordinary Chat still sends request text that the router reads in memory. web/lib/model-compare.jsIndexedDB (existing encrypted Chat history vault): Each Chat folder may keep instructions of up to 4,000 characters in its optional instructions field, inside the existing passphrase-encrypted history document. There is no new browser key, server table, column, Redis family or log field. The editor draft, current folder and ordered system messages are decrypted page memory only; locking or forgetting history removes the active folder metadata and editor draft, so later requests no longer use them. System-message snapshots already attached to on-screen replies or linked summaries remain in page memory for context counting until those chats are reset or the page closes; they are not saved in history. Closing the editor drops its draft. JSON exports and imports carry readable instructions with folder metadata, including single-chat exports; matching folder names keep the existing instructions. Markdown omits this metadata. From the next message after a move or edit, inference sends the current folder instructions as the first system message before the chat prompt; the router reads request text in memory on every lane. Copy as code also contains readable instructions. Context and cost estimates read them in browser memory. Empty instructions add no request message. web/lib/folder-instructions.jsIndexedDB (existing encrypted Chat history vault): Optional lane branches metadata keeps message versions as parent-linked nodes and selected message ids in the existing passphrase-encrypted anyroute-private-history vault. Each node keeps user or assistant text, ids, file names, prepared input images, supported generated image links or bytes, image mode, model/provider, reported token counts and cost, latency, receipt id/lane/disclosure, reply status and errors, and tool call ids/names/arguments or tool result text. Document contents, audio and reasoning are not saved. Decrypted versions and unsaved attachments live in page memory; locking drops the vault key and decrypted history, while a conversation already on screen remains in page memory. Forget deletes the vault. Branches share the existing chat size limit, folders and saved answers; no browser storage key, server table, column, Redis family, log field or server reader is added. JSON downloads expose all versions as readable data; imports validate the optional fields and older clients can ignore them. Markdown shows the selected version. Only the selected path is sent for inference and counted in the displayed context and chat cost; earlier versions were billed when requested and switching does not refund them. The router reads ordinary inference requests in memory. Switching versions sends nothing to the router. web/lib/harness-branches.jsExisting passphrase-encrypted Chat history vault: Saved chats and folders may keep an optional project field (a lowercase label of 1–48 letters, digits, dots, underscores or hyphens, or null to follow the default). The chat override wins over its folder default; absent selections leave the key default to the router. Choices persist only with history enabled. The active chat choice, project editor draft, account project suggestions and budget details live in page memory; closing the editor drops its draft and suggestions. Locking history drops folder defaults from later requests; the visible chat choice stays in memory until reset or page close. Forget deletes the existing vault. JSON exports expose readable chat and folder project fields; validated imports preserve them, with existing same-name folders winning. Markdown includes only chat overrides. Copy as code contains the effective header. Every Chat send, summary, retry and continuation passes X-Anyroute-Project to existing server capture and budget checks. Anyroute can read these labels, and the router reads request text in memory on every lane. Labels do not change older charges or signed receipts. Existing owner-only project list and budget APIs supply suggestions and details using the current key; no guard is widened. No new browser store, server table, column, Redis key family, log field, address reader or body reader. web/lib/chat-projects.jsExisting encrypted Chat history vault and localStorage preferences: Each saved chat may keep spendingCap as a positive integer micro-dollar string in the existing passphrase-encrypted anyroute-private-history vault. Removing a cap omits the field. History must be enabled to keep a cap after closing the page; locked vaults drop decrypted history from memory and Forget deletes the vault. JSON history exports expose this readable field and validated imports retain it; Markdown exports include the cap as readable text. The existing anyroute-harness-prefs localStorage record holds defaultChatCap (a micro-dollar string or null) until changed or browser data is cleared. The default is not encrypted. Denied storage keeps the default in page memory only. Unlocked cap values, estimates, editor amounts and a held-send callback with its draft and attachments live in page memory. Editing the request or changing the chat clears the held action. A one-send override is not persisted. No new table, column, Redis family, log field, server address reader or body reader. Checks reuse chat costs and catalogue estimates in the browser and do not upload anything; ordinary inference requests still pass through the router, which reads their text in memory. This browser guard does not enforce a hard billing limit. web/lib/chat-cap.jsPage memory and existing Chat message handling: Highlighted assistant answer text and floating-button position stay in page memory while selected. Ask about this inserts at most 1,500 selected characters, including a truncation ellipsis, as a plain-text quote in the existing composer. There is no new storage key or separate saved selection. Once sent, quoted text is ordinary message content: it follows existing optional encrypted Chat history, exports and inference request handling. The router reads ordinary inference text in memory. No new table, column, Redis family, log field, server address reader or body reader. web/lib/ask-about-this.jsIndexedDB and browser memory: Continue adds text to the selected answer version in the existing opt-in, passphrase-encrypted Chat history vault and exports. Optional finish and servedModel keep the finish reason and responding model id. continuationCalls keeps browser-generated call ids for deduplicating copied comparison history, receipt ids, provider names, finish reasons and reported prompt tokens, completion tokens and dollar cost per call; the reply usage and chat cost include the additional reported charges. No full signed receipts, credentials or continuation instruction are added to saved call records. The conversation including the cut-off answer and a short user instruction is sent through the existing authenticated inference path; the router reads ordinary request text in memory. Folder instructions and system prompt still apply. No new table, column, Redis key family, log field, body reader, address reader or browser storage key. Lock and Forget use the existing vault controls. web/lib/harness-continue-history.jsIndexedDB: Chat history is opt-in and encrypted with the browser history passphrase in the existing anyroute-private-history vault (memory only when storage is unavailable). Alongside saved conversations, costSummary keeps microUsd as an integer decimal string and replies as a count, summed across comparison lanes from the displayed reply costs. Totals include replies omitted from saved content; failed replies add zero dollars. Totals and counts are encrypted with the conversation, not stored separately or sent to the router. Locking drops the decrypted history from memory; Forget deletes the vault. Older chats without this summary use the costs in their retained replies. web/lib/private-history.jsIndexedDB: The optional savedAnswers field in the existing anyroute-private-history encrypted vault holds separate copies of reply text, preceding question text, model, reported cost (or null), save date, receipt ID (or empty), chat ID, message ID and a deduplication ID. It uses the existing passphrase-derived key and serial write queue; there is no new browser database or router store. The collection is limited to 256,000 UTF-8 bytes and 1,000 entries. It survives deleting or trimming chats. Searching uses decrypted questions and answers in memory while history is unlocked. Locking discards decrypted answers; Forget deletes them with the vault. Without IndexedDB, storage lasts only for the tab. Existing history exports and imports include saved answers, including copies whose chats were deleted; downloads are readable text. Reply text excludes images, attachments, reasoning and tool results. This does not change the router's in-memory reading of requests. web/lib/saved-answers.jslocalStorage: Getting started keeps Hide, all-steps-complete and receipt-visit booleans plus at most 100 receipt ids read from authenticated account data under anyroute-getting-started-v1:<connected key public hash>. No API key secret, balance, call text, Telegram user id or rulebook is stored. Home reads existing balance, key, agent, activity and Telegram link APIs in memory within their existing access boundaries. Opening /verify with a remembered receipt id marks only a visit, not signature validity; arbitrary public receipt ids do not count. Preferences do not sync between devices and survive until browser storage is cleared. If storage is unavailable, Hide applies to the current view only and receipt visits cannot be remembered. These stored preferences and ids are not sent to the router; the existing verify page still requests the named receipt and its privacy label. web/lib/getting-started.jslocalStorage: Account checkup stores up to 2000 dismissed item identifiers under anyroute-account-checkup-v1:<connected key public hash>. Key and agent item identifiers include their public key hashes. No key secret, account value, network address, request text or rulebook is persisted by checkup. It composes existing authenticated key, agent, Telegram link, balance alert, security alert and notification settings reads in browser memory with their existing visibility and guards. Fix links carry a public key hash and fixed control name where needed; they open existing editors and do not save changes. Read-only keys are refused by the browser checkup reader. Dismissals are never sent to the router and remain until restored or browser storage is cleared; unavailable storage keeps dismissals in the current view only. Existing APIs do not expose counts of places using a key, so IP-list suggestions do not infer locations. No new server persistence or readers. web/lib/account-checkup.jsBrowser and service-worker memory: Phone sharing reads title, text and URL fields into an unsent Chat draft. GET query fields may reach hosting access logs and browser history before the page removes them from its address. The installed service worker intercepts the multipart POST without forwarding it; it reads at most 48 MB plus 64 KB of framing and fields. Up to two pending shares retain capped text and up to six original image files (8 MB each), including their original metadata and names, in worker memory only. Handoffs are single-use and expire after five minutes; expired entries are removed on the next share or handoff, and browser worker termination drops all entries. A third share evicts the oldest. The page holds received original files in memory until a vision model is selected, then the existing attachment path re-encodes JPEGs with metadata stripped; navigation releases page memory. No persistent share cache, new router body or address reader, database column, Redis key or log field. Sending uses normal Chat authentication and retention; ordinary request text is read by the router in memory. web/lib/share-worker.jslocalStorage: Appearance choice: anyroute-theme-v1 stores only light or dark until changed or browser data is cleared. Match device removes the key. The preference is never sent to the router; denied storage keeps the choice only on the current page. web/lib/theme.jsCache Storage: The installable Harness keeps only the static app shell, offline page, scripts, styles, fonts and icons in a browser cache named anyroute-shell- followed by a build digest. Each cached file must match its exported SHA-256. Requests, replies, API responses and URLs with query strings are never cached. A new active app version removes older app caches; browser settings can clear them at any time. No additional data is stored by the router. web/lib/harness-sw.jssessionStorage: The API key you pasted into the dashboard, for the length of the tab. It is removed when the tab closes and is never written to localStorage. web/lib/api.jslocalStorage: The Harness favourite models and view preferences, and the Eval Lab evaluation sets you write. Eval Lab results are kept in IndexedDB. The router never receives them; only the requests you run do. web/components/Harness.jsx
The inventory is read from src/privacy. The check that keeps it true is in the repository. The full text of the file this page is built from is at /keep/inventory.json (502 KB).