Bindu extension for Ed25519-signed authorization receipts in the Veritas Acta format. Shadow mode is the default; enforcement is an explicit opt-in. No embedded-key fallback, ever.
Ships as a separate installable package (per the design discussion on GetBindu/Bindu#459): keeps the Bindu core review surface narrow and lets this extension iterate on its own cadence.
Status. Public Preview (0.1.0a1). Call-prep artifact for a design review with the Bindu maintainers scheduled for the week of 2026-04-22. API is expected to stabilize before 0.1.0.
pip install bindu-scopeblind # core: Ed25519 + JCS + agent card extension
pip install "bindu-scopeblind[cedar]" # + Cedar policy evaluation (enforce mode)| Property | Choice | Rationale |
|---|---|---|
| Default mode | shadow |
Receipts observable before enforcement lands. Aligns with GetBindu/Bindu#459 review guidance. |
| Verification key source | External only (agent card, DID doc, JWKS, pinned trust anchor) | Embedded keys fail verification because a malicious issuer could sign any payload with a fresh key pair. See draft-farley-acta-signed-receipts-02 §9. |
| Cedar policies | File directory only | Avoids silent-fallback-to-inline-string path typos. Enforce mode with no .cedar files is a configuration error. |
| Receipts format | Veritas Acta (draft-02) | Byte-compatible with @veritasacta/verify@0.5 and AGT integrations (protect-mcp, sb-runtime, protect-mcp-adk). |
| Scope | Ed25519 receipts only (tier T1) | VOPRF issuer-blind tokens (tier T4) are a separate primitive served by a different product (@scopeblind/verifier). This extension does NOT emit VOPRF tokens. |
from pathlib import Path
from bindu import BinduConfig
from bindu_scopeblind import ScopeBlindExtension
config = BinduConfig(
name="my-agent",
extensions=[
ScopeBlindExtension(
signer_key_path=Path("/etc/scopeblind/issuer.key"), # PEM Ed25519 private key
cedar_policy_dir=Path("./policies"), # directory of .cedar files
# mode=ReceiptMode.SHADOW is the default; omit to get it.
)
],
)Every governed request produces a signed receipt attached to request.state.scopeblind_receipt. Task / artifact metadata includes the receipt. Nothing in the task flow gates on the decision in shadow mode.
from bindu_scopeblind import ScopeBlindExtension, ReceiptMode
ScopeBlindExtension(
signer_key_path=Path("/etc/scopeblind/issuer.key"),
cedar_policy_dir=Path("./policies"), # required in enforce mode
mode=ReceiptMode.ENFORCE,
require_conformance_check=True, # CI gate
)require_conformance_check=True runs a minimal negative-conformance vector at construction: confirms the build rejects receipts carrying their own verification key. Construction fails if the check fails closed. CI operators SHOULD wire the full negative-vector set from ScopeBlind/agent-governance-testvectors into their build.
Receipts verify with @veritasacta/verify with no runtime dependency on Bindu or this extension:
# Operator publishes the issuer public key out-of-band (agent card / DID doc / JWKS)
npx @veritasacta/verify receipt.json --jwks https://agent.example/.well-known/jwks.jsonOr, from Python, using one of the provided KeySource subclasses:
from bindu_scopeblind import (
AgentCardKeySource,
JwksKeySource,
DidDocumentKeySource,
PinnedTrustAnchor,
verify_receipt,
)
source = AgentCardKeySource(agent_card=agent_card_json)
pub = source.resolve(receipt["signature"]["kid"])
assert verify_receipt(receipt, pub)Four reference sources ship in bindu_scopeblind.key_sources:
PinnedTrustAnchor: single pinned Ed25519 public key. Simplest case.JwksKeySource: resolves from a parsed JWKS document.DidDocumentKeySource: resolves from a DID document'sverificationMethodlist. Fits Bindu's existing DID-first agent identity model.AgentCardKeySource: resolves from an A2A agent card'sextensions["veritasacta:issuer"]block. Returned byScopeBlindExtension.agent_card_extension()so Bindu can publish it.
The extension does not bake in HTTP-fetching behavior; operators choose the transport. This keeps the core module offline-by-default and testable without network.
{
"payload": {
"type": "scopeblind:decision",
"issuer_id": "scopeblind:<12-char-thumbprint>",
"agent_id": "did:bindu:acme:searchbot",
"action": "message/send:search",
"decision": "allow",
"mode": "shadow",
"policy_id": "scopeblind-policy:policies",
"policy_digest": "sha256:...",
"jsonrpc_method": "message/send",
"path": "/a2a",
"request_id": "req-1234",
"issued_at": "2026-04-19T...Z",
"previousReceiptHash": "..."
},
"signature": {
"alg": "EdDSA",
"kid": "<operator JWK thumbprint>",
"sig": "<base64url>"
}
}All fields covered by the Ed25519 signature. Tampering with any field fails verification.
DESIGN.md: key-anchoring decision, shadow-mode semantics, threat model.CALL-AGENDA.md: proposed agenda for the Bindu maintainer design review call.
MIT. See LICENSE (to be added on repo publication).
- GetBindu/Bindu#439: originating feature request.
- GetBindu/Bindu#459: alternative implementation in the Bindu core repo (superseded by this standalone package per maintainer guidance).
- draft-farley-acta-signed-receipts-02: receipt format specification.
- VeritasActa/agt-integration-profile: normative AGT-to-receipt field mapping.