The trust model
Which verdict you can use to decide access, and what a verified signature proves.
The trust model says which verdict you can use to decide access. Only the request's own verdict, checked with isVerified, is fit for that.
import { inspect, isVerified } from 'botscent/server'
export async function POST(request: Request) {
const own = await inspect(request)
const verified = isVerified(own, 'chatgpt')
// => true only for a signature verified against ChatGPT's bundled keys
return Response.json({ verified })
}Which verdict to use for what
| Verdict | Where Botscent computes it | Use it for |
|---|---|---|
The request's own verdict, with isVerified true | On your server, from a verified signature or the platform's verified-bot field | Access |
The request's own verdict, with isVerified false | On your server, from declarations and product shapes that anyone can produce | Measurement and adapting what you show |
| The page verdict | In the visitor's browser | Measurement and adapting what you show |
| A page report | In the visitor's browser, sent by the page's own scripts | Measurement and adapting what you show |
A verdict from combine | Partly in the visitor's browser | Measurement and adapting what you show |
The page verdict, a page report and a joined verdict all come from the visitor's browser. Scripts on the page can change them. So none of them is fit to decide access.
What isVerified checks
isVerified has two forms:
isVerified(verdict)is true whenreasonsholdssigner.web-bot-auth.verifiedorsigner.edge-verified-bot, without thepage.prefix. Onlyinspectgives those reasons.isVerified(verdict, name)is true whenreasonsholdssigner.web-bot-auth.verified,agent_nameisname, and no reason has thepage.prefix.
In Python, the function is botscent.is_verified, with the same two forms.
The platform's verified-bot field never passes the check with a name. The field says that some agent was verified, not which agent. So isVerified(verdict) && verdict.agent_name === 'chatgpt' can join the platform's check of one agent with a name that the agent only declared.
Warning: Do not use
agent_nameor a reason string to allow access. Anyone can send the headers that produce them. UseisVerified(verdict, 'chatgpt')for one agent.
What a verified signature proves
A verified signature proves that the agent operator's infrastructure signed the request. It does not prove who the person is, or which model runs the session.
Each signature has a time window, from 5 s before its created time to its expires time. Someone who captures a signed request can replay the signature to the same host within that window.
Keys are fixed in each release
The server half makes no request to fetch keys. Each release bundles the signers' keys as the maintainers fetched them for that release. The release notes give the date of that fetch.
So a signer's key changes reach you only when you upgrade:
- A key that a signer adds after the release gives
signer.web-bot-auth.declareduntil you upgrade. - A key that a signer removes, because it rotated or leaked, stays verified until you upgrade. Nothing in a deployed copy can revoke it.
If you allow access with isVerified, keep the package current. The age of your release limits how old your keys can be. A scheduled job in the repository opens a pull request when a signer's published keys change.
What no verdict tells you
- No verdict proves that a person is present.
humanmeans only that Botscent saw no agent evidence. - No verdict describes the person behind an agent.
- No verdict says who performed a particular action.
- Botscent does not authorize anything. Your code decides what a verified agent can do.
Related
- The verdict: what
type,agent_nameandreasonsmean. - From the page to the server: how a page report reaches your server and stays apart.
- Versions and stability: which releases change verdicts, and why to pin a version.