Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
public/evidence/aaif/** text eol=lf
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Published site: [docs.proofable.me](https://docs.proofable.me)

Start here: [github.com/proofable/sdk](https://github.com/proofable/sdk)

Use with any MCP client: `https://mcp.proofable.me/mcp`
Use with any MCP client: `https://mcp.proofable.me/mcp/oauth`

Product: [proofable.me](https://proofable.me)

Expand Down
2 changes: 1 addition & 1 deletion agents/team-agents.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Every tool uses the same endpoint.

<Steps>
<Step title="Connect">
Add `https://mcp.proofable.me/mcp`, then finish the sign-in your client opens.
Add `https://mcp.proofable.me/mcp/oauth`, then finish the sign-in your client opens.
</Step>
<Step title="Create each agent">
**`proofable_agent_create`** per agent. Default is your signed-in profile. Pass an existing dedicated account address only when that agent needs its own spend account.
Expand Down
2 changes: 1 addition & 1 deletion api/authentication.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Send users to your checkout with `gateId`; the enforcement policy bills your app

## MCP OAuth

MCP clients authenticate via **OAuth 2.0 Authorization Code with PKCE**. Register `https://mcp.proofable.me/mcp` and finish the sign-in your client opens. Only Claude connectors and Devin render a control called Connect. Official CLI: `npx -y @proofable/sdk`.
MCP clients authenticate via **OAuth 2.0 Authorization Code with PKCE**. Register `https://mcp.proofable.me/mcp/oauth` and finish the sign-in your client opens. Only Claude connectors and Devin render a control called Connect. Official CLI: `npx -y @proofable/sdk`.

Request only the scopes you need:

Expand Down
23 changes: 21 additions & 2 deletions changelog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,25 @@ Package records: [`proofable/sdk`](https://github.com/proofable/sdk/blob/main/CH
Published APIs and verifier schemas may change between minor versions. Breaking changes are listed in each entry and in the repo changelogs.
</Note>

<Update
label="October 5, 2026"
description="v0.1.4"
tags={["SDK", "Docs", "Agents"]}
rss={{
title: "Proofable SDK v0.1.4",
description: "Delegated runtime mounts fail closed when the permission carries no explicit allow-list."
}}
>
## Delegated mounts fail closed without an allow-list

`@proofable/sdk@0.1.4` makes an empty or missing `allowedActions` list grant nothing for a delegated permission, matching the hosted contract. A delegated host action is denied with `ACTION_NOT_ALLOWED`; controller-owned mounts keep their existing behavior. See [Run your first guarded action](/mcp/guarded-action).

```bash
npm install @proofable/sdk@0.1.4
```

</Update>

<Update
label="September 25, 2026"
description="Checking a proof is free"
Expand Down Expand Up @@ -150,9 +169,9 @@ Media placeholders for this changelog page. Drop the finished files under docs/i
</update-image-v0.1.1>

<update-image-v0.1.0>
TODO: screenshot — Connect flow: add https://mcp.proofable.me/mcp, click Connect, sign in.
TODO: screenshot — Connect flow: add https://mcp.proofable.me/mcp/oauth, complete sign-in.
Suggested path: docs/images/releases/mcp-0.1.0-connect.png
TODO: 30-60s clip — first run: register endpoint, Connect, ask for profile and current proofs.
TODO: 30-60s clip — first run: register endpoint, sign in, ask for profile and current proofs.
Suggested path: docs/images/releases/mcp-0.1.0-first-run.mp4
</update-image-v0.1.0>
*/}
2 changes: 1 addition & 1 deletion mcp/auth.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: "Pick the auth path for your caller: browser sign-in for interactiv
icon: lock
---

Interactive MCP clients sign in through the host. Register `https://mcp.proofable.me/mcp` (public-first: connects anonymously, then upgrades with sign-in) and finish the browser sign-in your client opens. The host runs OAuth 2.0 with PKCE and can refresh the session for up to 30 days.
Interactive MCP clients sign in through the host. Register `https://mcp.proofable.me/mcp/oauth` (auth-first: without a credential even `initialize` answers `401 + WWW-Authenticate`, which starts host OAuth) and finish the browser sign-in your client opens. The host runs OAuth 2.0 with PKCE and can refresh the session for up to 30 days.

For servers, CI, and environments that cannot open a browser, use a durable server key instead. Both paths hit the same endpoint and the same Proofable profile.

Expand Down
3 changes: 2 additions & 1 deletion mcp/endpoints.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ The **MCP URL** and the **HTTP API** use different transports and base paths. Di

| URL | Role |
|-----|------|
| `https://mcp.proofable.me/mcp` | MCP. [Setup](./setup) |
| `https://mcp.proofable.me/mcp/oauth` | MCP, auth-first lane. Interactive clients register this: without a credential even `initialize` answers `401 + WWW-Authenticate`, which starts host OAuth. [Setup](./setup) |
| `https://mcp.proofable.me/mcp` | MCP, public-first lane. Anonymous `initialize` and directory discovery, and the RFC 8707 resource for server-key (Bearer) callers. |

## OAuth discovery

Expand Down
8 changes: 4 additions & 4 deletions mcp/guarded-action.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,18 @@ For the permission above, `send_message` returns:
}
```

`read_proofs` returns `ACTION_ALLOWED`. An expired or missing permission fails closed. An irreversible action returns `HUMAN_APPROVAL_REQUIRED` when the permission requires approval.
`read_proofs` returns `ACTION_ALLOWED`. A delegated permission with an empty or missing `allowedActions` list grants no actions. An expired or missing permission fails closed. An irreversible action returns `HUMAN_APPROVAL_REQUIRED` when the permission requires approval.

## Decision order

`evaluateRuntimeAction` applies the mounted permission in this order:

1. Require a valid runtime mount and current permission proof.
1. Require a valid runtime mount and an unexpired mounted permission.
2. Apply `deniedActions`.
3. Apply a non-empty `allowedActions` list.
3. Require an explicit, non-empty `allowedActions` list for delegated authority, then check the action against it. Controller-owned mounts do not require a delegation allowlist.
4. Require approval for an irreversible action when configured.
5. Allow the host tool call.

The SDK evaluates one action. The host still owns the tool call and must stop when `allowed` is `false`.
The SDK evaluates one action against the mounted snapshot, as of `@proofable/sdk@0.1.4`. Load that snapshot from a trusted mount; caller-supplied JSON is not a verified proof. The host still owns the tool call and must stop when `allowed` is `false`. A mount file cannot discover a revocation that happens after it was written; refresh current authority through the connected Proofable host before a consequential action that needs current revocation status.

Runnable source: [`examples/guarded-agent-action`](https://github.com/proofable/mcp/tree/main/examples/guarded-agent-action).
2 changes: 1 addition & 1 deletion mcp/oauth.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ icon: shield-check
Proofable MCP uses the **Authorization Code** grant. The user signs in on Proofable with the same passkey or wallet flow as the product.

<Note>
**Default:** add `https://mcp.proofable.me/mcp` and finish the sign-in your client opens. Only Claude connectors and Devin render a control called Connect. Optional terminal installer: `npx -y @proofable/sdk setup`. Use this page for custom MCP hosts, security review, standalone sign-in, or raw HTTP integration.
**Default:** add `https://mcp.proofable.me/mcp/oauth` and finish the sign-in your client opens. The bare `https://mcp.proofable.me/mcp` endpoint serves directory discovery and server-key (Bearer) callers. Only Claude connectors and Devin render a control called Connect. Optional terminal installer: `npx -y @proofable/sdk setup`. Use this page for custom MCP hosts, security review, standalone sign-in, or raw HTTP integration.
</Note>

## Flow overview
Expand Down
2 changes: 1 addition & 1 deletion mcp/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Connect one endpoint and every client reads the same profile: the proofs you alr

Connect once. The same agents, selected context, limits, and current proofs are there in every supported client.

Add `https://mcp.proofable.me/mcp` to the client, then sign in.
Add `https://mcp.proofable.me/mcp/oauth` to an interactive client, then sign in. The bare `https://mcp.proofable.me/mcp` endpoint stays for directory discovery and server-key (Bearer) callers.

Interactive hosts use OAuth. For servers, CI, and headless agents, send a server key as a Bearer token. See [Add Proofable to any MCP client](./setup).

Expand Down
2 changes: 1 addition & 1 deletion mcp/setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ Use the [JavaScript SDK](/sdks/javascript), [HTTP API](/api/overview), or [hoste
- Confirm the connection. Run `npx -y @proofable/sdk doctor --live`.
- Two Proofable entries. Keep one plugin or manual server entry. Running setup again removes a leftover entry when the plugin already supplies it.
- Need agent context in a project. Run `npx -y @proofable/sdk mount <agentId> --apply <host>`. See [Load agent context](/agents/runtime-mount).
- Search-only endpoint. Use `https://mcp.proofable.me/mcp`. The docs MCP endpoint only searches documentation.
- Search-only endpoint. Use `https://mcp.proofable.me/mcp/oauth` in an interactive client (or the bare `https://mcp.proofable.me/mcp` for a server key). The docs MCP endpoint only searches documentation.

To disconnect, run `npx -y @proofable/sdk disconnect`. [MCP tools](/mcp/tools) and [authentication](/mcp/auth) cover the full reference.
31 changes: 31 additions & 0 deletions public/evidence/aaif/authority-at-dispatch/2026-10-05/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Proofable authority-at-dispatch evidence (17f17630166b)

On 5 October 2026, eight bounded assertions ran through Proofable's **live production hosted MCP
service** on protocol revision `17f17630166b1018804a5fca5bc485b6812580aa`. The execution principal was an
**ordinary non-admin Pro review tenant** (`admin:false`, so the Admin/CUSTOM job-ownership bypass
does not apply), operating the dedicated agent `proofable-authority-review` under a controller-signed
allow-list delegation. Every job pinned an explicit `delegationQHash`; each case varies only the
delegation/job state. The founder/admin profile was not the execution principal.

| Assertion | Observed production behavior | Result |
| --- | --- | --- |
| Hosted allow | Granted authority: the job completed and returned `REVIEW_OK`. | PASS |
| Binding veto | A grant omitting `run_command` was refused isolated execution before an executor was assigned. | PASS |
| Approval reachable | The job parked at `waiting_approval`, an authenticated decision was accepted, then it completed. | PASS |
| Approval unavailable | The job parked, was cancelled without approval, and a late approval was refused (`JOB_APPROVAL_STATE_CHANGED`). | PASS |
| Revoke before dispatch | A delegation revoked before dispatch returned `DELEGATION_PROOF_DENIED`; no job was created. | PASS |
| Expiry before dispatch | A delegation past its expiry returned `DELEGATION_PROOF_DENIED`; no job was created. | PASS |
| Stale authority | A revoked grant replayed was denied on every attempt; no job was created. | PASS |
| Post-dispatch revoke | A grant revoked while the job was in flight: the in-flight job completed and its committed effect was read back. | PASS |

Where the product produced a terminal receipt, it was read back as verified and private. The
deterministic review of the immutable private records is **8/8 PASS**. The
[manifest](manifest.json) pins the production revision and the private-source hashes; the
[public trace](trace.jsonl) holds one sanitized record per case; [checksums](SHA256SUMS) cover this
packet.

The operator ran and evaluated these checks. The denial cases intentionally produced no signed
decision record (that is a named product gap in the standards reconciliation, not an omission
here). This is bounded implementation evidence relevant to
[AAIF Identity & Trust WG issue #13](https://github.com/aaif/wg-identity-and-trust/issues/13). It is
not AAIF certification, AARM conformance, or an AgentGovBench leaderboard result.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
32b5cebe8bb6eb14442a2ab937e33fac9de586e11d152a41be7088051447fd5f README.md
1bc6ec1f9625bf7ffe3aef075a6c86c2a2d1724cc7b8dcefae58d273def685b2 manifest.json
fbd53edf273c65b10a8172716c9ac2005130899d3f4a21eacd4a9de506029bd0 trace.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"schema": "proofable-authority-at-dispatch-public-projection/v2",
"implementation": "Proofable",
"environment": "prod",
"protocol_revision": "17f17630166b1018804a5fca5bc485b6812580aa",
"execution_principal": {
"class": "ordinary Pro test/reviewer tenant",
"admin": false,
"controller_wallet": "0x0d4e513a3a7eb92bab65c97786c67b198d9dca15"
},
"agent": {
"agentId": "proofable-authority-review",
"agentWallet": "0x738f1729be00dee66e3451156097c20a34ad3540"
},
"private_source": {
"raw_manifest_sha256": "e5718502a3cc4b53a2991428796431b43b8598eecf3cb8f20f55b0df56c8caaf",
"raw_review_sha256": "ae2445d672c4832a6a13a4a40b66a32a1e47cc305a96e62175ff5e173ecd93f5",
"raw_trace_sha256": "d0930acb0cfe18ae8105c1289799597420a092cfcf72ddb94601b17f0fb15c80",
"case_count": 8,
"passed_count": 8
},
"public_trace": {
"file": "trace.jsonl",
"record_count": 8,
"sha256": "fbd53edf273c65b10a8172716c9ac2005130899d3f4a21eacd4a9de506029bd0"
},
"projection_method": "Expected assertions and observed job/receipt fields selected from the private epoch manifest and deterministic review. Raw delegated scope lists, prompts, keys and full job replies are omitted; receipt qHashes are included only as private-visibility references.",
"custody": "SELF; ordinary-Pro tenant, founder/admin not used as execution principal; receipts private",
"receipt_visibility": "private",
"matched_aaif_experiment": false,
"certification_claim": false,
"aarm_conformance_claim": false,
"agentgovbench_rank_claim": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{"case_id":"hosted_allow","expected":"A granted authority permits the bounded action; the job completes with a verified receipt.","observed":{"status":"completed","response":"REVIEW_OK","executor":null,"error":null},"passed":true,"delegation_qHash":"0xf4776e04c9079d241f7b642b59e5b3768bf0864df1f40157cccf1d3b3fdfbac5","job_id":"0ef8bcc0-d558-4050-b774-28fd2e209a62","terminal_receipt":{"qHash":"0x47493870a17caae394e019d861ef1273236c35b8deddcc2c0584be9ece8f6a8a","status":"verified","visibility":"private"}}
{"case_id":"binding_veto","expected":"A grant that omits run_command is refused isolated execution before an executor is assigned.","observed":{"status":"failed","response":null,"executor":null,"error":"JOB_AUTHORITY_DENIED: run_command is required for isolated harness execution."},"passed":true,"delegation_qHash":"0x4fe507c97fddaa84610cabedf8ea4a9a6a9f3ede8e6697bd11921b163fd40e33","job_id":"964d8684-094e-428c-b116-4132a9413ee0","terminal_receipt":{"qHash":"0xdff131f70709bb13db630becc592d7140a7ad4fd41710d4cbd894255121ac738","status":"verified","visibility":"private"}}
{"case_id":"approval_reachable","expected":"An approval-gated job parks, an authenticated decision is accepted, and it completes.","observed":{"status":"completed","response":"REVIEW_OK","executor":null,"error":null},"passed":true,"delegation_qHash":"0x79d513c66fa49c7d1fb9c8759a469bced4e37226ccfde503417772055c24fe46","job_id":"ef7fb843-6a91-4bb8-b275-517821945e41","terminal_receipt":{"qHash":"0x97d653c97ab6ed12a6d310b0bdced273a1e7433ec5b51fd5eaef154dad93eec5","status":"verified","visibility":"private"}}
{"case_id":"approval_unavailable","expected":"Without approval the job is cancelled and a late approval cannot resume it.","observed":{"status":"cancelled","response":null,"executor":null,"error":"Cancelled by owner"},"passed":true,"delegation_qHash":"0x74cb72c3e7e2b0786127e6c7979930e5250e71209bcaa87dd0c7f2b548dfcf8e","job_id":"aa1eefa3-e564-4cff-9d1a-2f22de34edbb","terminal_receipt":{"qHash":"0x0f4934ced3a3360d4ac42f083c2d23074710a56541a2545b1bfb0fa2e6a4f17b","status":"verified","visibility":"private"}}
{"case_id":"revoke_before_dispatch","expected":"A delegation revoked before dispatch is denied with no job created.","observed":{"dispatch_decision":"DENY","code":"DELEGATION_PROOF_DENIED","job_created":false},"passed":true,"delegation_qHash":"0x39f69960317f9b930e0fb7951a76ba5511f313187f541d2d428b8c180cde368e","job_id":null,"terminal_receipt":null}
{"case_id":"expiry_before_dispatch","expected":"A delegation past its expiry is denied with no job created.","observed":{"dispatch_decision":"DENY","code":"DELEGATION_PROOF_DENIED","job_created":false},"passed":true,"delegation_qHash":"0xffda3ab5dab98e60bba898d54e9892a3effb000cf33995afc3447a7aaf4b7b16","job_id":null,"terminal_receipt":null}
{"case_id":"stale_authority","expected":"A revoked grant replayed is denied every time, with no job created.","observed":{"dispatch_decision":"DENY","code":null,"job_created":false},"passed":true,"delegation_qHash":"0xb9b8cba0f63a3fc40c0b29561fff38de15fed4cad24ec65af19c71987c44fd1a","job_id":null,"terminal_receipt":null}
{"case_id":"post_dispatch_revoke","expected":"A grant revoked while the job is in flight: the committed effect is observed and read back.","observed":{"status":"completed","response":"REVIEW_OK","executor":"harness:opencode:acp:sandbox","error":null},"passed":true,"delegation_qHash":"0xc17bfb031a459d0a800cc15318661f2ec0a3f00bb20c1fff03d66f0418498966","job_id":"6812fda6-d018-408d-be2e-267ff8320002","terminal_receipt":{"qHash":"0xf8db8eeee7b191746738fdee625a605315ab9a7de0d9256f153c0131d490dea4","status":"verified","visibility":"private"}}
4 changes: 2 additions & 2 deletions reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Pick the surface that matches the caller. The table below maps each one to its e

| Surface | Use it for | Endpoint or package | Signs in with |
|---|---|---|---|
| [MCP](/mcp/overview) | Any app, chat, or agent that speaks MCP | `https://mcp.proofable.me/mcp` | OAuth, or an access key |
| [MCP](/mcp/overview) | Any app, chat, or agent that speaks MCP | `https://mcp.proofable.me/mcp/oauth` | OAuth, or an access key |
| [JavaScript SDK](/sdks/javascript) | Apps, backends, and React | `@proofable/sdk` | Hosted sign-in, or an access key on servers |
| [CLI](/sdks/cli) | Terminal setup and agent context | `npx -y @proofable/sdk` | OAuth, or an access key |
| [HTTP API](/api/overview) | Any language or backend | `https://api.proofable.me` | Signed requests, a session, or an access key |
Expand All @@ -31,7 +31,7 @@ Pick the surface that matches the caller. The table below maps each one to its e
| Full docs | `https://docs.proofable.me/llms-full.txt` |
| MCP discovery | `https://mcp.proofable.me/.well-known/mcp.json` |

This docs site also serves a search-only MCP endpoint at `https://docs.proofable.me/mcp`. It searches these pages. Your profile, proofs, and agents live at `https://mcp.proofable.me/mcp`.
This docs site also serves a search-only MCP endpoint at `https://docs.proofable.me/mcp`. It searches these pages. Your profile, proofs, and agents live at `https://mcp.proofable.me/mcp/oauth`.

## Sections

Expand Down
3 changes: 3 additions & 0 deletions scripts/validate-doc-copy.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const ROOT = path.resolve(import.meta.dirname, '..');
const IMPERATIVE = /^(add|authenticate|bind|bring|build|call|check|choose|combine|confirm|connect|control|create|decide|define|discover|drop|enforce|give|handle|import|install|keep|know|list|load|manage|mount|move|open|pass|pay|pick|prove|publish|pull|put|read|register|require|retry|reuse|roll|run|screen|see|select|sell|send|set|share|sign|start|stop|store|submit|track|use|verify|wire|wrap|write)\b/i;
/** Coverage and question openers orient the reader even without an imperative. */
const ORIENTED_OPENER = /^(every|how|what|when|where|which|whichever|who|why)\b/i;
/** A named audience explains who a compact description is for. */
const AUDIENCE = /\bfor\s+(people|teams|developers|operators|organizations|agents|buyers|customers)\b/i;
const CONSEQUENCE = /\b(so|before|instead|without|then|when|after|unless|rather|beyond|already|never|cannot|skip|reuse|unlock|grant|stop|prevent)\b/i;
const SECOND_PERSON = /\b(you|your)\b/i;

Expand Down Expand Up @@ -71,6 +73,7 @@ for (const file of walk(ROOT)) {
SECOND_PERSON.test(description) ||
IMPERATIVE.test(description) ||
ORIENTED_OPENER.test(description) ||
AUDIENCE.test(description) ||
CONSEQUENCE.test(description);
const commas = (description.match(/,/g) || []).length;
if (!oriented && commas >= 2) fail('INVENTORY', 'comma list with no reader orientation');
Expand Down
Loading
Loading