Agentry
Checking a proof somebody handed you
You have been given a proof and you want to know what it is worth. You do not need an Agentry account, a key, or our permission, and you do not have to tell us that you looked. A proof is a compact JWS signed with ES256; everything you need to check it is inside it, apart from our public keys, which you fetch once.
What a proof states, and what it does not, is defined per standard version at /trust/standards/<version>. This page is about the checking.
There is no paste-your-proof box here, deliberately
We are not going to check the proof for you, and the reason is the point of the design rather than a gap in it. If the way to read a proof were to send it to us, then the proof would be worth only as much as our being reachable and honest at the moment you read it; we would see every proof anyone was ever shown, and who showed it, and when; and the offline guarantee would be a description of something you never actually did.
So the artefact is built to be checked by the reader, and this page tells you how rather than offering to be the oracle. The checks a verifier makes are described below and on the statement page for the proof's standard, so that you can make them with any JOSE library and our key set, without our code.
The three things you do
- Fetch the key set once, from
/.well-known/agentry-trust-jwksat Agentry's own address, and pin it. Take that address from somewhere other than the proof itself, and never from itsissorverifyfields: whoever signed a proof chose everything in it. The key set is unauthenticated, because a reader who has to present a credential in order to check a signature is not verifying offline. - Pass three things to the verifier: the proof, the keys you fetched, and that same address as the expected issuer. The keys are a value you pass in, not an address the verifier goes and reads, and a proof naming any other issuer is refused.
- Narrow on the result, which is described next, and read the limits text it hands you before you act on anything.
The result has three arms, and no field named valid
The result is a discriminated union on outcome. There is no field named valid anywhere in it, and that is deliberate: the default behaviour of a generic JWS library is to hand you a green tick the moment a signature checks out, and a boolean is exactly that signal. Narrowing on outcome is the only way to read the result, so there is no single flag that can be read as a green tick without naming the arm it belongs to.
- valid
When: its signature verifies against the live key set you pinned, it was issued in the live environment, the clock claims hold, and its contents are exactly what its standard allows, limits text included.
What you get: you are handed the facts the proof states and, in the same object, the limits text that says what those facts are not. There is no version of this function that gives you the first without the second.
- not_valid_for_reliance
When: the proof is well formed and its signature verifies, but it was issued in the sandbox and is a test artefact.
What you get: you are handed the same facts so that you can inspect them, labelled as not for reliance. If somebody presents you a sandbox proof in earnest, the answer is not to opt in. It is to ask them for a live one.
- invalid
When: the proof is not one of ours, or it is one of ours and something about it does not hold.
What you get: you are handed a reason saying which. A proof whose signature verifies but whose limits text has been softened lands here, refused outright rather than accepted with a warning.
A reader who collapses this to a boolean has thrown away the only thing that distinguishes a test artefact from evidence. The type system stops that inside our own code and stops nobody outside it, which is why the distinction is also written into the artefact itself: a different signed typ, a separately published key set, and a line in the proof that says it.
Sandbox proofs, and why the default answer is a refusal
A sandbox deployment mints real signed proofs, and they travel exactly as a live one would. They carry agentry-sandbox-proof+jwt where a live proof carries agentry-trust-proof+jwt, an env of sandbox, and a key identifier beginning sandbox-. All three must agree, and where they do not the proof is refused rather than read as a test artefact.
Reading a sandbox proof at all requires an explicit opt-in argument, so the default result on a sandbox proof is an outcome of invalid, with a reason of unknown key. It is that even if the only key set you were ever handed was the sandbox one at /.well-known/agentry-sandbox-trust-jwks, because the opt-in is a separate argument rather than a property of whichever keys you supplied. That reads as a fault if you meet it without warning, and it is the feature: somebody using this verifier who has never heard of our sandbox cannot be handed a green tick by one, and the answer does not depend on which document a caller happened to fetch.
A command line tool built on the verifier should exit non-zero on the sandbox arm and print exactly this line:
sandbox proof: a test artefact, not evidence about this company
The verifier never follows an address out of the payload
A proof carries verify.jwksUrl so that a reader knows where our keys are published. The verifier does not read it to decide which keys to check against, and neither should yours. The payload is the part somebody who can sign with any key at all controls, so letting the payload choose the trust anchor means the proof vouches for itself.
Fetch the key set from the address you decided on, pin it, and pass it in. The same holds for the header: it carries no address of any kind, precisely so that there is nothing in it for a verifier to be tempted to fetch.
What a proof is worth once it verifies
Read the limits text the verifier hands you, and read the date on each check. There is no revocation service and no status address to poll: a proof stops being good when it expires and at no other moment, and nothing about it is refreshed after issue. If the check dates are older than you are comfortable with for what you are about to do, ask the business for a proof whose check dates are recent enough. A proof issued today can carry checks performed weeks ago: the date on each check tells you how fresh the facts are, not the date the proof was issued.
A proof is issued to the business named in it, for that business to present. One forwarded on by somebody else is outside what it was issued for, whatever its signature says.
This page takes no proof, no identifier and no personal data, and it stores nothing about your visit beyond the request logs any web host keeps. Agentry checks a UK limited company against the Companies House register and an identity check, and issues a signed record of what was checked. It does not move, hold or initiate money.