Proof of Delegation · how it works
Four things, one name.
Search a well-known product on an app registry and several listings answer to its name. Some may be the company’s; most are other people’s; the listing itself cannot say which is which. Proof of Delegation is the missing piece of paper — a note the company signs, and four questions anyone can ask of it.
Which one does the company stand behind? The listing has nowhere to say it.
one of these is our real package — the look-alikes are invented for this page
The note
The missing piece of paper
The controller of a domain proves that control to the issuer. The issuer writes out a stamped note — this artifact acts for the company, for these capabilities, until this date — and the company can cancel it any day. On the note, the company is the principal; the thing it stands behind is the delegate. Ours looks like this:
who wrote it · principal
The company, named by its domain. The one line a reader should always look at.
who it’s about · delegate
Exactly one artifact, typed and named in full — never a family of things.
until when · iat → exp
The note runs out on its own, and can be cancelled sooner.
what it covers · scope
The capabilities the company put in writing — nothing outside them is being claimed.
revocable anytime — the domain proof stays valid
End to end
The whole trip, in five lines
Everything below is one of these five lines, enlarged.
Different delegations
One grammar, three kinds of thing
The delegate is typed — an https URL or a package URL — so a note points at exactly one thing. Three notes, identical grammar, three different things to stand behind:
Same stamp, same four questions — only the principal, delegate and scope rows change, and each note is cancellable on its own without touching the domain proof or any sibling note. Both domains here are our own. The first of these notes — the MCP server’s — is the one we are about to write; until a note is issued, it is an illustration, not a record.
The four questions
What anyone can ask
Whoever finds the note — a gateway, a registry, you — can ask four questions of it. None of them is “is this artifact good.” Four smaller ones, each with a yes-or-no answer.
Is the stamp real?
Checked against stamps you chose to trust — the reference verifier ships with an empty trust list, and the note does not get a vote.
needs — the issuer’s published keys · fetched once, cached
Is it from the company you mean?
Read who wrote it. A perfect note from a look-alike name is caught here and only here — by reading it against the domain you expected.
needs — the note + your intent · no network
Is it about this artifact?
The note names one delegate, and the check compares it against the artifact you actually resolved — never against what the note says about itself. A mismatch has a name: delegate_mismatch.
needs — the note + what you fetched · no network
Does it still count today?
The note cannot say — it can be cancelled any day. The issuer is asked, over the published status list and the status endpoint, and silence is a refusal, not a pass.
needs — the issuer · asked every time
and when there is no note at all
Silence is not a verdict either. It means the domain has not spoken for this artifact — so the honest answer is “no note,” never “bad.”
The copy attack
A real note, in the wrong hands
A published note is data, and data can be photocopied into a different listing with its stamp intact — nothing on it was altered. Question 3 is built for this exact move: the check refuses to run unless you supply the artifact you resolved yourself. Run the same four questions twice and watch where the copy fails:
proof.holdings
the honest rendering — the domain, a door, never a checkmark
a named failure, before a single network call
The reverse move exists too: any domain owner can sign a genuine note naming someone else’s artifact — the issuer checked their domain, not the artifact’s parentage. That is why a check is only meaningful against the domain you expected: pinned, a note minted by the wrong party fails at question 2; unpinned, the result honestly reads “this domain says so,” and nothing more.
Liveness
The question the note can’t answer about itself
Anyone can check the stamp without asking us. Nobody can check the note still counts without asking.
That is the design, not a limitation. A note that promised “valid forever” could never be taken back — the cancel switch has to live outside the note, with the issuer.
So the check asks twice: a signed status list — fetched whole, so the issuer never learns which note you cared about — and the issuer’s status endpoint, which alone sees the domain proof a note rests on. A no from either is final, and if neither can answer, the check fails closed: unavailable is not the same as valid.
counts today
no
fails closed — unavailable is not valid
The rendering
Show the domain, not a checkmark
Either name can carry a perfectly stamped note — all four questions can answer yes for both. What tells them apart is a person reading the principal against the domain they expected. A checkmark would cover exactly the part that matters, so the honest rendering is the domain itself — a door to the principal’s public profile, never a verdict.
In code
Writing one, in code
One call stands between a proven domain and a published note. Everything else in the surface exists to list them, read one back, and cancel it.
import { Proof } from '@proof-holdings/sdk';
const proof = new Proof('pk_live_...');
const delegation = await proof.delegations.create({
control_proof: 'ph_ctl_...', // the domain you proved
delegate: { type: 'purl', value: 'pkg:npm/@proof-holdings/mcp-server' },
// or a live endpoint: { type: 'url', value: 'https://team.management/mcp' }
scope: ['proof-verification'], // capability tokens, kebab-case
});
console.log(delegation.token); // publish this on the artifactIssue a delegation over a url/purl artifact (mints the token)
List delegations
Get a delegation incl. its token
Revoke a delegation
The token comes back once, on the write. Publish it on the artifact’s own card, or point a one-line DNS record at where it lives.
Withdrawing a delegation is instant. Delivering that withdrawal is not.
Every published route to a revocation — the status lookup, the revocation list, the status list — reaches a verifier who asks. Plenty of callers never ask, and nothing you do at revocation time changes that.
The path that does not depend on the caller is the artifact refusing itself. Install @proof-holdings/delegation-self-refusal in your own MCP server and it checks its delegation on a schedule: once you revoke, every tool call it serves refuses on its own, whether or not anyone was checking.
Fine print
- The paper questions run before any network call, so a note that fails on them costs zero requests — and the signature algorithm is chosen by the verifier, never read from the note.
- Read a failure as “this did not verify,” never as evidence about who tried: claims are checked before signatures, so a forged note can be made to produce any failure it likes.
- A note travels on the artifact’s own card, or a one-line DNS record at the domain points to where it lives — the record carries an address, never the note itself.
Start with the domain you already stand behind. Prove it once, then write a note for each thing that acts under your name — and cancel any of them, any day, on its own.