{
    "componentChunkName": "component---src-templates-protocol-protocol-tsx",
    "path": "/poe/1.0/",
    "result": {"data":{"markdownRemark":{"html":"<h2 id=\"Summary\">Summary</h2>\n<p>The Proof of Execution (PoE) 1.0 protocol lets a Requester ask a Prover to run a named program and return a zero-knowledge proof that the program executed correctly on inputs bound to a transaction context — while keeping private inputs confidential. It is generic and supports many programs (e.g., device checks, policy evaluators, cryptographic attestations) with program-specific public schemas validated by the Requester.</p>\n<hr>\n<h2 id=\"Goals\">Goals</h2>\n<ul>\n<li>Generic request/response flow for program execution proofs</li>\n<li>Strong anti-replay via binding to <code>{nonce, context_hash, session_id}</code></li>\n<li>Minimal disclosure: <code>proof-only</code> by default; optional summaries or encrypted evidence references</li>\n<li>Program capability negotiation when needed</li>\n<li>Local registry enforcement for verifying keys and program parameters</li>\n</ul>\n<hr>\n<h2 id=\"Roles\">Roles</h2>\n<ul>\n<li><code>requester</code>: Verifier relying on the PoE result (e.g., login, payments, issuance)</li>\n<li><code>prover</code>: Holder/Agent that executes or delegates the program and returns the proof</li>\n<li><code>attester</code> (optional): Compute service (possibly TEE-backed) that can generate PoE on Prover’s behalf</li>\n</ul>\n<h3 id=\"Security-Model-Summary\">Security Model (Summary)</h3>\n<ul>\n<li>Binding: Every PoE instance MUST bind to <code>{nonce, context_hash, session_id}</code> to prevent replay/cross-use.</li>\n<li>Freshness: Messages carry short TTLs; programs may enforce timing/sequence constraints in-proof.</li>\n<li>Privacy: Only the ZK proof and public outputs are revealed. Private inputs never leave the Prover unless policy demands by-reference encrypted evidence.</li>\n<li>Unlinkability: Use pairwise DIDs and ephemeral keys per thread.</li>\n</ul>\n<hr>\n<h2 id=\"Discovery\">Discovery</h2>\n<p>Provers advertise PoE support with Discover-Features 2.0. They should disclose supported <code>program_id</code>s and optional resource hints.</p>\n<pre><code class=\"language-json\">{\n  \"type\":\"https://didcomm.org/discover-features/2.0/disclose\",\n  \"body\":{\n    \"disclosures\":[\n      {\"feature_type\":\"protocol\",\"id\":\"https://didcomm.org/poe/1.0\",\"roles\":[\"prover\"]},\n      {\"feature_type\":\"goal-code\",\"id\":\"poe/programs\",\"claims\":{\"programs\":[\n        {\"program_id\":\"vendor.policy.eval.v1\",\"max_runtime_s\":60,\"max_artifact_mb\":8}\n      ]}}\n    ]\n  }\n}\n</code></pre>\n<hr>\n<h2 id=\"States\">States</h2>\n<p>Requester</p>\n<pre><code>IDLE → REQUEST_SENT → (optional) CHALLENGE_SENT* ← SUBMIT_RECEIVED → COMPLETE | PROBLEM\n</code></pre>\n<p>Prover</p>\n<pre><code>IDLE ← REQUEST_POE ↔ (optional) PROPOSE/ACCEPT ↔ (optional) CHALLENGE ← → SUBMIT_POE ← COMPLETE | PROBLEM\n</code></pre>\n<hr>\n<h2 id=\"Basic-Walkthrough\">Basic Walkthrough</h2>\n<ol>\n<li>Requester sends <code>request-poe</code> naming one or more <code>program_id</code>s with public constraints and binds them to <code>{nonce, context_hash, session_id}</code>.</li>\n<li>Prover may reply with <code>propose-poe</code> to adjust capabilities or proceed directly.</li>\n<li>For interactive programs, Requester MAY send a <code>challenge</code> describing steps.</li>\n<li>Prover returns <code>submit-poe</code> with <code>public</code> block and <code>zk</code> proof.</li>\n<li>Requester verifies registry, binding, proof, and policy, then responds with <code>complete</code> or <code>problem-report</code>.</li>\n</ol>\n<hr>\n<h2 id=\"Message-Reference\">Message Reference</h2>\n<p>All PoE messages use DIDComm v2 with type: <code>https://didcomm.org/poe/1.0/&#x3C;message-name></code> and standard headers (<code>id</code>, <code>thid</code>/<code>pthid</code>, <code>from</code>, <code>to</code>, <code>expires_time</code>).</p>\n<h3 id=\"request-poe\">request-poe</h3>\n<p>Message Type URI: <code>https://didcomm.org/poe/1.0/request-poe</code></p>\n<p>Purpose: Ask the Prover to run a program and return PoE.</p>\n<p>From: requester → prover</p>\n<pre><code class=\"language-json\">{\n  \"type\": \"https://didcomm.org/poe/1.0/request-poe\",\n  \"id\": \"req-123\",\n  \"pthid\": \"txn-abc123\",\n  \"body\": {\n    \"programs\": [\n      {\n        \"program_id\": \"vendor.policy.eval.v1\",\n        \"public_constraints\": { \"params_hash\": \"0x…32B\" }\n      }\n    ],\n    \"bind_to_context\": {\n      \"nonce\": \"0x…32B\",\n      \"context_hash\": \"0x…32B\",\n      \"session_id\": \"0x…16B\"\n    },\n    \"inputs\": {\n      \"schema\": \"vendor.policy.eval.v1/inputs@1\",\n      \"by_value\": { \"params\": { \"ttl_s\": 60, \"policy_ref\": \"policy-abc@1\" } }\n    },\n    \"disclosure\": \"proof-only\",\n    \"expiry\": \"2025-11-11T14:35:00Z\",\n    \"transport_hints\": { \"webrtc_ok\": true, \"offline_ok\": true },\n    \"policy\": { \"max_runtime_s\": 60, \"max_artifact_mb\": 8 }\n  }\n}\n</code></pre>\n<p>Notes:</p>\n<ul>\n<li><code>programs</code> MAY include several options ordered by preference.</li>\n<li><code>inputs</code> describe public inputs supplied by the requester; others may be computed by the Prover or Attester.</li>\n<li><code>disclosure</code> controls summaries or encrypted evidence refs beyond the ZK proof.</li>\n</ul>\n<hr>\n<h3 id=\"propose-poe\">propose-poe</h3>\n<p>Message Type URI: <code>https://didcomm.org/poe/1.0/propose-poe</code></p>\n<p>Purpose: Negotiate capabilities or parameters (optional).</p>\n<p>From: prover → requester</p>\n<pre><code class=\"language-json\">{\n  \"type\": \"https://didcomm.org/poe/1.0/propose-poe\",\n  \"id\": \"prop-1\",\n  \"thid\": \"req-123\",\n  \"body\": {\n    \"program\": {\n      \"program_id\": \"vendor.policy.eval.v1\",\n      \"public_constraints\": { \"params_hash\": \"0x…32B\" }\n    },\n    \"disclosure\": \"proof-only\"\n  }\n}\n</code></pre>\n<hr>\n<h3 id=\"accept-poe--decline-poe\">accept-poe / decline-poe</h3>\n<p>Message Type URI: <code>https://didcomm.org/poe/1.0/accept-poe</code> and <code>…/decline-poe</code></p>\n<p>Purpose: Confirm or decline the chosen program/params.</p>\n<p>From: requester ↔ prover</p>\n<pre><code class=\"language-json\">{\n  \"type\": \"https://didcomm.org/poe/1.0/accept-poe\",\n  \"id\": \"acc-1\",\n  \"thid\": \"req-123\",\n  \"body\": {\n    \"program_id\": \"vendor.policy.eval.v1\",\n    \"public_constraints\": { \"params_hash\":\"0x…32B\" },\n    \"inputs_digest\": \"0x…32B\"\n  }\n}\n</code></pre>\n<p>Parties MAY skip propose/accept if capabilities already match and proceed directly to <code>submit-poe</code>.</p>\n<hr>\n<h3 id=\"challenge\">challenge</h3>\n<p>Message Type URI: <code>https://didcomm.org/poe/1.0/challenge</code></p>\n<p>Purpose: For interactive programs, carry step schedule or updates.</p>\n<p>From: requester → prover</p>\n<pre><code class=\"language-json\">{\n  \"type\": \"https://didcomm.org/poe/1.0/challenge\",\n  \"id\": \"chal-1\",\n  \"thid\": \"req-123\",\n  \"body\": { \"challenge_spec\": { \"steps\":[{\"action\":\"perform\",\"payload\":[\"taskA\",\"taskB\"]}], \"ttl_s\": 10 }, \"sequence\": 1 }\n}\n</code></pre>\n<hr>\n<h3 id=\"submit-poe\">submit-poe</h3>\n<p>Message Type URI: <code>https://didcomm.org/poe/1.0/submit-poe</code></p>\n<p>Purpose: Deliver the ZK proof and optional summary/evidence.</p>\n<p>From: prover → requester</p>\n<pre><code class=\"language-json\">{\n  \"type\": \"https://didcomm.org/poe/1.0/submit-poe\",\n  \"id\": \"sub-1\",\n  \"thid\": \"req-123\",\n  \"body\": {\n    \"program_id\": \"vendor.policy.eval.v1\",\n    \"result\": \"pass\",                        \n    \"public\": {\n      \"schema\": \"vendor.policy.eval.v1/public@1\",\n      \"nonce\": \"0x…32B\",\n      \"context_hash\": \"0x…32B\",\n      \"session_id\": \"0x…16B\",\n      \"outputs_hash\": \"0x…32B\",\n      \"vk_hash\": \"0x…32B\"\n    },\n    \"zk\": {\n      \"scheme\": \"stark\",\n      \"circuit_id\": \"vendor-policy-eval-v1\",\n      \"vk_hash\": \"0x…32B\",\n      \"proof_b64\": \"base64(urlsafe)…\"\n    },\n    \"summary\": { \"evidence_summary\": [\"constraint_A_met\",\"constraint_B_met\"] }\n  },\n  \"attachments\": [\n    { \"id\": \"evidence-ref\", \"format\": \"by-reference\", \"media_type\": \"application/json\",\n      \"data\": { \"links\": [\"ipfs://…\", \"https://…/cap/…\"], \"alg\": \"A256GCM\", \"keyref\": \"eke-1\" } }\n  ]\n}\n</code></pre>\n<p>Requirements:</p>\n<ul>\n<li><code>public</code> MUST match the program’s public schema.</li>\n<li><code>zk.vk_hash</code> MUST be in the Requester’s registry for the <code>circuit_id</code>.</li>\n<li>If <code>result = pass</code>, the proof MUST verify and assert the program’s declared constraints/policy are satisfied.</li>\n</ul>\n<hr>\n<h3 id=\"complete--problem-report\">complete / problem-report</h3>\n<p>Message Type URI: <code>https://didcomm.org/poe/1.0/complete</code> and <code>…/problem-report</code></p>\n<p>Purpose: Signal success (optionally with a receipt) or report a canonical error.</p>\n<p>From: requester ↔ prover</p>\n<pre><code class=\"language-json\">{\n  \"type\": \"https://didcomm.org/poe/1.0/problem-report\",\n  \"id\": \"err-1\",\n  \"thid\": \"req-123\",\n  \"body\": { \"code\": \"invalid_proof\", \"explain\": \"ZK verification failed or vk_hash not allowed\", \"details\": { \"circuit_id\": \"vendor-policy-eval-v1\" } }\n}\n</code></pre>\n<hr>\n<h2 id=\"Registry--Schemas\">Registry &#x26; Schemas</h2>\n<p>Requesters maintain a local registry mapping <code>program_id</code>/<code>circuit_id</code> to allowed verifying keys and program parameters/hashes.</p>\n<p>Example registry:</p>\n<pre><code class=\"language-json\">{\n  \"vendor-policy-eval-v1\": {\n    \"vk_hash\": [\"0xVK_A\", \"0xVK_B\"],\n    \"params\": [\"0xPARAMS_A\",\"0xPARAMS_B\"],\n    \"public_schema\": \"vendor.policy.eval.v1/public@1\"\n  }\n}\n</code></pre>\n<p>Example public schema (program-defined):</p>\n<pre><code class=\"language-json\">{\n  \"type\":\"object\",\n  \"required\":[\"nonce\",\"context_hash\",\"session_id\",\"vk_hash\"],\n  \"properties\":{\n    \"nonce\":{\"type\":\"string\"},\n    \"context_hash\":{\"type\":\"string\"},\n    \"session_id\":{\"type\":\"string\"},\n    \"outputs_hash\":{\"type\":\"string\",\"pattern\":\"^0x[0-9a-fA-F]{64}$\"},\n    \"vk_hash\":{\"type\":\"string\"}\n  }\n}\n</code></pre>\n<p>Requesters MUST reject any <code>vk_hash</code> or program parameter/hash not in the registry.</p>\n<hr>\n<h2 id=\"Transport--Packaging\">Transport &#x26; Packaging</h2>\n<ul>\n<li>Encryption: DIDComm v2 Authcrypt or Anoncrypt</li>\n<li>Delivery: mediator-optional; Out-of-Band deep links or QR are fine</li>\n<li>Attachments: DIDComm v2 Attachments 2.0</li>\n<li>Streaming: Optional upgrade (e.g., WebRTC datachannel) for interactive challenges; the final proof still returns via DIDComm unless both parties agree otherwise</li>\n</ul>\n<hr>\n<h2 id=\"Verification-Pipeline-Requester\">Verification Pipeline (Requester)</h2>\n<ol>\n<li>Expiry: Reject if <code>expiry</code> or TTL violated.</li>\n<li>Registry: Check <code>program_id ∈ registry</code>; <code>vk_hash</code> and any pinned parameters/hashes are allowed.</li>\n<li>ZK Verify: <code>verify_zk(proof_b64, public, circuit_id, vk_hash)</code> MUST pass.</li>\n<li>Binding: Confirm <code>nonce</code>, <code>context_hash</code>, <code>session_id</code> match the ones issued.</li>\n<li>Program Policy: Enforce program-specific constraints and any additional contextual policy (e.g., device attestation, geo-velocity).</li>\n<li>Issue Receipt: Optionally issue a short-lived VC (e.g., <code>ExecutionReceiptCredential</code>) embedding a <code>proof_hash</code> for audit.</li>\n</ol>\n<hr>\n<h2 id=\"Error-Codes\">Error Codes</h2>\n<ul>\n<li><code>program_not_supported</code></li>\n<li><code>inputs_invalid</code></li>\n<li><code>expired_challenge</code></li>\n<li><code>policy_violation</code></li>\n<li><code>invalid_proof</code></li>\n<li><code>vk_unknown</code></li>\n<li><code>params_unknown</code></li>\n<li><code>context_mismatch</code></li>\n<li><code>too_large</code></li>\n<li><code>rate_limited</code></li>\n<li><code>attester_unavailable</code></li>\n</ul>\n<p>Every <code>problem-report</code> MUST include <code>code</code> and SHOULD include <code>details</code>.</p>\n<hr>\n<h2 id=\"Privacy--Retention\">Privacy &#x26; Retention</h2>\n<ul>\n<li>Default <code>disclosure = proof-only</code>.</li>\n<li>If <code>proof+summary</code>, include only aggregate fields (e.g., step booleans or aggregate metrics).</li>\n<li>If <code>proof+evidence-ref</code>, references MUST be E2EE (e.g., AES-GCM with DIDComm-negotiated key).</li>\n<li>Server retention SHOULD be hashes/receipts only, with short TTLs (≤30 min) unless law/policy demands more.</li>\n</ul>\n<hr>\n<h2 id=\"Program-Examples\">Program Examples</h2>\n<h3 id=\"WebAuthn-presence-as-PoE-vendordevicewebauthnv1\">WebAuthn presence as PoE (<code>vendor.device.webauthn.v1</code>)</h3>\n<ul>\n<li>Public: <code>nonce</code>, <code>context_hash</code>, RP ID hash, flags (UP/UV policy)</li>\n<li>Proof: zkVM/zk-circuit proving assertion verified and flags met, bound to <code>nonce||context_hash</code></li>\n<li>Result: <code>pass|fail</code></li>\n</ul>\n<p>Additional programs can follow the same mold.</p>\n<hr>\n<h2 id=\"Conformance\">Conformance</h2>\n<ol>\n<li>Nominal PASS: valid proof; binding matches; in-policy.</li>\n<li>Policy FAIL: valid proof but public outputs do not satisfy constraints → <code>result=fail</code> or reject per policy.</li>\n<li>Replay FAIL: wrong <code>nonce/context_hash</code> → verify fails.</li>\n<li>Tamper FAIL: integrity/public hash mismatch → verify/reject.</li>\n<li>Unknown VK/Params: registry rejects.</li>\n<li>Expired: TTL exceeded → reject before verify.</li>\n</ol>\n<hr>\n<h2 id=\"Versioning\">Versioning</h2>\n<ul>\n<li>Protocol version is part of the PIURI (<code>/poe/1.0</code>).</li>\n<li>Program versions live in <code>program_id</code> (e.g., <code>vendor.program.v1</code>).</li>\n<li>Verifiers MUST pin <code>vk_hash</code> to a <code>circuit_id</code> and rotate via registry updates.</li>\n</ul>\n<hr>\n<h2 id=\"Example-Generic-Program\">Example Generic Program</h2>\n<ol>\n<li>Requester → Prover: <code>request-poe</code> with <code>program_id=\"vendor.policy.eval.v1\"</code>, <code>public_constraints.params_hash=0x…</code>, program inputs, and <code>{nonce, context_hash, session_id}</code>.</li>\n<li>Prover executes and generates proof.</li>\n<li>Prover → Requester: <code>submit-poe</code> with <code>public</code> block and <code>zk</code> proof, <code>result=\"pass\"</code>.</li>\n<li>Requester verifies ZK + registry + policy and replies <code>complete</code> (optionally minting a short-lived receipt VC).</li>\n</ol>","frontmatter":{"title":"Proof of Execution (PoE)","tags":["poe","zk","proof","didcomm","policy","attestation","generic"],"license":"MIT","publisher":"vinaysingh8866","status":"Proposed","piuri":"https://didcomm.org/poe/1.0","summary":"A DIDComm v2 protocol for requesting and receiving zero-knowledge proofs that a named program executed correctly on inputs bound to a transaction context, without revealing private inputs.","authors":[{"name":"Vinay Singh","email":"vinay@verid.id"}]},"fields":{"modifiedDate":"Wed Jul 22 2026 15:46:37 GMT+0000 (Coordinated Universal Time)","avatar":"https://avatars.githubusercontent.com/u/12121665?v=4&s=48","version":"1.0"}}},"pageContext":{"matchPath":"poe/1.0/*","id":"e879786e-afa2-5a1b-8977-199148d8ce86","html":"<h2 id=\"Summary\">Summary</h2>\n<p>The Proof of Execution (PoE) 1.0 protocol lets a Requester ask a Prover to run a named program and return a zero-knowledge proof that the program executed correctly on inputs bound to a transaction context — while keeping private inputs confidential. It is generic and supports many programs (e.g., device checks, policy evaluators, cryptographic attestations) with program-specific public schemas validated by the Requester.</p>\n<hr />\n<h2 id=\"Goals\">Goals</h2>\n<ul>\n<li>Generic request/response flow for program execution proofs</li>\n<li>Strong anti-replay via binding to <code>{nonce, context_hash, session_id}</code></li>\n<li>Minimal disclosure: <code>proof-only</code> by default; optional summaries or encrypted evidence references</li>\n<li>Program capability negotiation when needed</li>\n<li>Local registry enforcement for verifying keys and program parameters</li>\n</ul>\n<hr />\n<h2 id=\"Roles\">Roles</h2>\n<ul>\n<li><code>requester</code>: Verifier relying on the PoE result (e.g., login, payments, issuance)</li>\n<li><code>prover</code>: Holder/Agent that executes or delegates the program and returns the proof</li>\n<li><code>attester</code> (optional): Compute service (possibly TEE-backed) that can generate PoE on Prover’s behalf</li>\n</ul>\n<h3 id=\"Security-Model-Summary\">Security Model (Summary)</h3>\n<ul>\n<li>Binding: Every PoE instance MUST bind to <code>{nonce, context_hash, session_id}</code> to prevent replay/cross-use.</li>\n<li>Freshness: Messages carry short TTLs; programs may enforce timing/sequence constraints in-proof.</li>\n<li>Privacy: Only the ZK proof and public outputs are revealed. Private inputs never leave the Prover unless policy demands by-reference encrypted evidence.</li>\n<li>Unlinkability: Use pairwise DIDs and ephemeral keys per thread.</li>\n</ul>\n<hr />\n<h2 id=\"Discovery\">Discovery</h2>\n<p>Provers advertise PoE support with Discover-Features 2.0. They should disclose supported <code>program_id</code>s and optional resource hints.</p>\n<pre><code class=\"language-json\">{\n  \"type\":\"https://didcomm.org/discover-features/2.0/disclose\",\n  \"body\":{\n    \"disclosures\":[\n      {\"feature_type\":\"protocol\",\"id\":\"https://didcomm.org/poe/1.0\",\"roles\":[\"prover\"]},\n      {\"feature_type\":\"goal-code\",\"id\":\"poe/programs\",\"claims\":{\"programs\":[\n        {\"program_id\":\"vendor.policy.eval.v1\",\"max_runtime_s\":60,\"max_artifact_mb\":8}\n      ]}}\n    ]\n  }\n}\n</code></pre>\n<hr />\n<h2 id=\"States\">States</h2>\n<p>Requester</p>\n<pre><code>IDLE → REQUEST_SENT → (optional) CHALLENGE_SENT* ← SUBMIT_RECEIVED → COMPLETE | PROBLEM\n</code></pre>\n<p>Prover</p>\n<pre><code>IDLE ← REQUEST_POE ↔ (optional) PROPOSE/ACCEPT ↔ (optional) CHALLENGE ← → SUBMIT_POE ← COMPLETE | PROBLEM\n</code></pre>\n<hr />\n<h2 id=\"Basic-Walkthrough\">Basic Walkthrough</h2>\n<ol>\n<li>Requester sends <code>request-poe</code> naming one or more <code>program_id</code>s with public constraints and binds them to <code>{nonce, context_hash, session_id}</code>.</li>\n<li>Prover may reply with <code>propose-poe</code> to adjust capabilities or proceed directly.</li>\n<li>For interactive programs, Requester MAY send a <code>challenge</code> describing steps.</li>\n<li>Prover returns <code>submit-poe</code> with <code>public</code> block and <code>zk</code> proof.</li>\n<li>Requester verifies registry, binding, proof, and policy, then responds with <code>complete</code> or <code>problem-report</code>.</li>\n</ol>\n<hr />\n<h2 id=\"Message-Reference\">Message Reference</h2>\n<p>All PoE messages use DIDComm v2 with type: <code>https://didcomm.org/poe/1.0/&lt;message-name&gt;</code> and standard headers (<code>id</code>, <code>thid</code>/<code>pthid</code>, <code>from</code>, <code>to</code>, <code>expires_time</code>).</p>\n<h3 id=\"request-poe\">request-poe</h3>\n<p>Message Type URI: <code>https://didcomm.org/poe/1.0/request-poe</code></p>\n<p>Purpose: Ask the Prover to run a program and return PoE.</p>\n<p>From: requester → prover</p>\n<pre><code class=\"language-json\">{\n  \"type\": \"https://didcomm.org/poe/1.0/request-poe\",\n  \"id\": \"req-123\",\n  \"pthid\": \"txn-abc123\",\n  \"body\": {\n    \"programs\": [\n      {\n        \"program_id\": \"vendor.policy.eval.v1\",\n        \"public_constraints\": { \"params_hash\": \"0x…32B\" }\n      }\n    ],\n    \"bind_to_context\": {\n      \"nonce\": \"0x…32B\",\n      \"context_hash\": \"0x…32B\",\n      \"session_id\": \"0x…16B\"\n    },\n    \"inputs\": {\n      \"schema\": \"vendor.policy.eval.v1/inputs@1\",\n      \"by_value\": { \"params\": { \"ttl_s\": 60, \"policy_ref\": \"policy-abc@1\" } }\n    },\n    \"disclosure\": \"proof-only\",\n    \"expiry\": \"2025-11-11T14:35:00Z\",\n    \"transport_hints\": { \"webrtc_ok\": true, \"offline_ok\": true },\n    \"policy\": { \"max_runtime_s\": 60, \"max_artifact_mb\": 8 }\n  }\n}\n</code></pre>\n<p>Notes:</p>\n<ul>\n<li><code>programs</code> MAY include several options ordered by preference.</li>\n<li><code>inputs</code> describe public inputs supplied by the requester; others may be computed by the Prover or Attester.</li>\n<li><code>disclosure</code> controls summaries or encrypted evidence refs beyond the ZK proof.</li>\n</ul>\n<hr />\n<h3 id=\"propose-poe\">propose-poe</h3>\n<p>Message Type URI: <code>https://didcomm.org/poe/1.0/propose-poe</code></p>\n<p>Purpose: Negotiate capabilities or parameters (optional).</p>\n<p>From: prover → requester</p>\n<pre><code class=\"language-json\">{\n  \"type\": \"https://didcomm.org/poe/1.0/propose-poe\",\n  \"id\": \"prop-1\",\n  \"thid\": \"req-123\",\n  \"body\": {\n    \"program\": {\n      \"program_id\": \"vendor.policy.eval.v1\",\n      \"public_constraints\": { \"params_hash\": \"0x…32B\" }\n    },\n    \"disclosure\": \"proof-only\"\n  }\n}\n</code></pre>\n<hr />\n<h3 id=\"accept-poe--decline-poe\">accept-poe / decline-poe</h3>\n<p>Message Type URI: <code>https://didcomm.org/poe/1.0/accept-poe</code> and <code>…/decline-poe</code></p>\n<p>Purpose: Confirm or decline the chosen program/params.</p>\n<p>From: requester ↔ prover</p>\n<pre><code class=\"language-json\">{\n  \"type\": \"https://didcomm.org/poe/1.0/accept-poe\",\n  \"id\": \"acc-1\",\n  \"thid\": \"req-123\",\n  \"body\": {\n    \"program_id\": \"vendor.policy.eval.v1\",\n    \"public_constraints\": { \"params_hash\":\"0x…32B\" },\n    \"inputs_digest\": \"0x…32B\"\n  }\n}\n</code></pre>\n<p>Parties MAY skip propose/accept if capabilities already match and proceed directly to <code>submit-poe</code>.</p>\n<hr />\n<h3 id=\"challenge\">challenge</h3>\n<p>Message Type URI: <code>https://didcomm.org/poe/1.0/challenge</code></p>\n<p>Purpose: For interactive programs, carry step schedule or updates.</p>\n<p>From: requester → prover</p>\n<pre><code class=\"language-json\">{\n  \"type\": \"https://didcomm.org/poe/1.0/challenge\",\n  \"id\": \"chal-1\",\n  \"thid\": \"req-123\",\n  \"body\": { \"challenge_spec\": { \"steps\":[{\"action\":\"perform\",\"payload\":[\"taskA\",\"taskB\"]}], \"ttl_s\": 10 }, \"sequence\": 1 }\n}\n</code></pre>\n<hr />\n<h3 id=\"submit-poe\">submit-poe</h3>\n<p>Message Type URI: <code>https://didcomm.org/poe/1.0/submit-poe</code></p>\n<p>Purpose: Deliver the ZK proof and optional summary/evidence.</p>\n<p>From: prover → requester</p>\n<pre><code class=\"language-json\">{\n  \"type\": \"https://didcomm.org/poe/1.0/submit-poe\",\n  \"id\": \"sub-1\",\n  \"thid\": \"req-123\",\n  \"body\": {\n    \"program_id\": \"vendor.policy.eval.v1\",\n    \"result\": \"pass\",                        \n    \"public\": {\n      \"schema\": \"vendor.policy.eval.v1/public@1\",\n      \"nonce\": \"0x…32B\",\n      \"context_hash\": \"0x…32B\",\n      \"session_id\": \"0x…16B\",\n      \"outputs_hash\": \"0x…32B\",\n      \"vk_hash\": \"0x…32B\"\n    },\n    \"zk\": {\n      \"scheme\": \"stark\",\n      \"circuit_id\": \"vendor-policy-eval-v1\",\n      \"vk_hash\": \"0x…32B\",\n      \"proof_b64\": \"base64(urlsafe)…\"\n    },\n    \"summary\": { \"evidence_summary\": [\"constraint_A_met\",\"constraint_B_met\"] }\n  },\n  \"attachments\": [\n    { \"id\": \"evidence-ref\", \"format\": \"by-reference\", \"media_type\": \"application/json\",\n      \"data\": { \"links\": [\"ipfs://…\", \"https://…/cap/…\"], \"alg\": \"A256GCM\", \"keyref\": \"eke-1\" } }\n  ]\n}\n</code></pre>\n<p>Requirements:</p>\n<ul>\n<li><code>public</code> MUST match the program’s public schema.</li>\n<li><code>zk.vk_hash</code> MUST be in the Requester’s registry for the <code>circuit_id</code>.</li>\n<li>If <code>result = pass</code>, the proof MUST verify and assert the program’s declared constraints/policy are satisfied.</li>\n</ul>\n<hr />\n<h3 id=\"complete--problem-report\">complete / problem-report</h3>\n<p>Message Type URI: <code>https://didcomm.org/poe/1.0/complete</code> and <code>…/problem-report</code></p>\n<p>Purpose: Signal success (optionally with a receipt) or report a canonical error.</p>\n<p>From: requester ↔ prover</p>\n<pre><code class=\"language-json\">{\n  \"type\": \"https://didcomm.org/poe/1.0/problem-report\",\n  \"id\": \"err-1\",\n  \"thid\": \"req-123\",\n  \"body\": { \"code\": \"invalid_proof\", \"explain\": \"ZK verification failed or vk_hash not allowed\", \"details\": { \"circuit_id\": \"vendor-policy-eval-v1\" } }\n}\n</code></pre>\n<hr />\n<h2 id=\"Registry--Schemas\">Registry &amp; Schemas</h2>\n<p>Requesters maintain a local registry mapping <code>program_id</code>/<code>circuit_id</code> to allowed verifying keys and program parameters/hashes.</p>\n<p>Example registry:</p>\n<pre><code class=\"language-json\">{\n  \"vendor-policy-eval-v1\": {\n    \"vk_hash\": [\"0xVK_A\", \"0xVK_B\"],\n    \"params\": [\"0xPARAMS_A\",\"0xPARAMS_B\"],\n    \"public_schema\": \"vendor.policy.eval.v1/public@1\"\n  }\n}\n</code></pre>\n<p>Example public schema (program-defined):</p>\n<pre><code class=\"language-json\">{\n  \"type\":\"object\",\n  \"required\":[\"nonce\",\"context_hash\",\"session_id\",\"vk_hash\"],\n  \"properties\":{\n    \"nonce\":{\"type\":\"string\"},\n    \"context_hash\":{\"type\":\"string\"},\n    \"session_id\":{\"type\":\"string\"},\n    \"outputs_hash\":{\"type\":\"string\",\"pattern\":\"^0x[0-9a-fA-F]{64}$\"},\n    \"vk_hash\":{\"type\":\"string\"}\n  }\n}\n</code></pre>\n<p>Requesters MUST reject any <code>vk_hash</code> or program parameter/hash not in the registry.</p>\n<hr />\n<h2 id=\"Transport--Packaging\">Transport &amp; Packaging</h2>\n<ul>\n<li>Encryption: DIDComm v2 Authcrypt or Anoncrypt</li>\n<li>Delivery: mediator-optional; Out-of-Band deep links or QR are fine</li>\n<li>Attachments: DIDComm v2 Attachments 2.0</li>\n<li>Streaming: Optional upgrade (e.g., WebRTC datachannel) for interactive challenges; the final proof still returns via DIDComm unless both parties agree otherwise</li>\n</ul>\n<hr />\n<h2 id=\"Verification-Pipeline-Requester\">Verification Pipeline (Requester)</h2>\n<ol>\n<li>Expiry: Reject if <code>expiry</code> or TTL violated.</li>\n<li>Registry: Check <code>program_id ∈ registry</code>; <code>vk_hash</code> and any pinned parameters/hashes are allowed.</li>\n<li>ZK Verify: <code>verify_zk(proof_b64, public, circuit_id, vk_hash)</code> MUST pass.</li>\n<li>Binding: Confirm <code>nonce</code>, <code>context_hash</code>, <code>session_id</code> match the ones issued.</li>\n<li>Program Policy: Enforce program-specific constraints and any additional contextual policy (e.g., device attestation, geo-velocity).</li>\n<li>Issue Receipt: Optionally issue a short-lived VC (e.g., <code>ExecutionReceiptCredential</code>) embedding a <code>proof_hash</code> for audit.</li>\n</ol>\n<hr />\n<h2 id=\"Error-Codes\">Error Codes</h2>\n<ul>\n<li><code>program_not_supported</code></li>\n<li><code>inputs_invalid</code></li>\n<li><code>expired_challenge</code></li>\n<li><code>policy_violation</code></li>\n<li><code>invalid_proof</code></li>\n<li><code>vk_unknown</code></li>\n<li><code>params_unknown</code></li>\n<li><code>context_mismatch</code></li>\n<li><code>too_large</code></li>\n<li><code>rate_limited</code></li>\n<li><code>attester_unavailable</code></li>\n</ul>\n<p>Every <code>problem-report</code> MUST include <code>code</code> and SHOULD include <code>details</code>.</p>\n<hr />\n<h2 id=\"Privacy--Retention\">Privacy &amp; Retention</h2>\n<ul>\n<li>Default <code>disclosure = proof-only</code>.</li>\n<li>If <code>proof+summary</code>, include only aggregate fields (e.g., step booleans or aggregate metrics).</li>\n<li>If <code>proof+evidence-ref</code>, references MUST be E2EE (e.g., AES-GCM with DIDComm-negotiated key).</li>\n<li>Server retention SHOULD be hashes/receipts only, with short TTLs (≤30 min) unless law/policy demands more.</li>\n</ul>\n<hr />\n<h2 id=\"Program-Examples\">Program Examples</h2>\n<h3 id=\"WebAuthn-presence-as-PoE-vendordevicewebauthnv1\">WebAuthn presence as PoE (<code>vendor.device.webauthn.v1</code>)</h3>\n<ul>\n<li>Public: <code>nonce</code>, <code>context_hash</code>, RP ID hash, flags (UP/UV policy)</li>\n<li>Proof: zkVM/zk-circuit proving assertion verified and flags met, bound to <code>nonce||context_hash</code></li>\n<li>Result: <code>pass|fail</code></li>\n</ul>\n<p>Additional programs can follow the same mold.</p>\n<hr />\n<h2 id=\"Conformance\">Conformance</h2>\n<ol>\n<li>Nominal PASS: valid proof; binding matches; in-policy.</li>\n<li>Policy FAIL: valid proof but public outputs do not satisfy constraints → <code>result=fail</code> or reject per policy.</li>\n<li>Replay FAIL: wrong <code>nonce/context_hash</code> → verify fails.</li>\n<li>Tamper FAIL: integrity/public hash mismatch → verify/reject.</li>\n<li>Unknown VK/Params: registry rejects.</li>\n<li>Expired: TTL exceeded → reject before verify.</li>\n</ol>\n<hr />\n<h2 id=\"Versioning\">Versioning</h2>\n<ul>\n<li>Protocol version is part of the PIURI (<code>/poe/1.0</code>).</li>\n<li>Program versions live in <code>program_id</code> (e.g., <code>vendor.program.v1</code>).</li>\n<li>Verifiers MUST pin <code>vk_hash</code> to a <code>circuit_id</code> and rotate via registry updates.</li>\n</ul>\n<hr />\n<h2 id=\"Example-Generic-Program\">Example Generic Program</h2>\n<ol>\n<li>Requester → Prover: <code>request-poe</code> with <code>program_id=\"vendor.policy.eval.v1\"</code>, <code>public_constraints.params_hash=0x…</code>, program inputs, and <code>{nonce, context_hash, session_id}</code>.</li>\n<li>Prover executes and generates proof.</li>\n<li>Prover → Requester: <code>submit-poe</code> with <code>public</code> block and <code>zk</code> proof, <code>result=\"pass\"</code>.</li>\n<li>Requester verifies ZK + registry + policy and replies <code>complete</code> (optionally minting a short-lived receipt VC).</li>\n</ol>"}},
    "staticQueryHashes": ["3000541721","3766577012"],
    "matchPath": "poe/1.0/*"}