Attesto

SDKs

Python, TypeScript, CLI, and Go SDKs

Attesto exposes four first-class developer surfaces: Python, TypeScript, Go, and the Attesto CLI. They share the same Proofstream protocol, golden vectors, verifier matrix, production origin, and secret-handling rules.

Package registries

The official package identifiers are attesto for Python and @attesto/sdk for TypeScript. The current release family is 0.5.0 across Python, TypeScript, Go, and CLI, and it is the first release that carries the Attesto 3 provenance verifiers. The Go module go.attesto.eu/sdk v0.5.0 and its curve module go.attesto.eu/sdk/zk v0.5.0 are published. The PyPI attesto==0.5.0 wheel and the npm @attesto/sdk==0.5.0 package are published (2026-08-23) and both registries resolve 0.5.0 as latest; the signed CLI channel at get.attesto.eu serves 0.5.0 as well, with installers for Linux/macOS (curl | sh) and Windows (irm | iex). Install only from the official PyPI and npm registries; do not install SDKs from mirrors, random tarballs, or source snapshots.

The release gate separates packages from surfaces: registry readiness expects three package/module distributions (attesto, @attesto/sdk, and the Go module) and four production developer surfaces because the attesto CLI is a first-class Go-backed verifier surface. The gate must report surfacesExpected=4, surfacesReady=4, cliReady=true, and cliVersionMatches=true.

Package artifacts are intentionally minimal. npm artifacts contain runtime JavaScript, declaration files, README.md, and package metadata only. PyPI production releases are wheel-only. Sourcemaps, raw TypeScript source, tests, caches, source archives, frontend bundles, API keys, private keys, and secret-like material are forbidden.

Authentication model

System-key clients are used for event ingest, stream heads, receipts, public proof objects, bundles, and remote verification. Tenant/operator clients use a dashboard bearer token for tenant stream lists, connector installation, Local Vault installation, fork evidence inspection, proof-state views, and tenant audit-pack creation. Do not put either credential in frontend code.

Article 13 support and Article 12 evidence with one integration line

For high-risk AI systems, Article 12 is about technical logging capability and traceability, while Article 13 is about transparency and information that helps deployers and users understand the system. In Attesto terms, the exact one-line integration is export OPENAI_BASE_URL=http://localhost:8765/v1: it points OpenAI-compatible calls at the Attesto Gateway so automatic evidence capture can start. The deterministic attesto report article12 output explains what was recorded and independently verifiable, and teams can use that verified trail as support material for Article 13 documentation. This is evidence support, not a legal conformity statement.

The concrete one-line gateway integration that makes this true is:

export OPENAI_BASE_URL=http://localhost:8765/v1

In production, replace localhost with the deployed gateway host and keep both the provider key and Attesto system key in server-side secret storage.

Use this pattern when you own a Python function boundary. The decorator records commitments over arguments, return value, timing, source reference, and failures; the report summarizes coverage without using an LLM.

from attesto import AttestoV2Client, attest, article12
import os

with AttestoV2Client(api_key=os.environ["ATTESTO_API_KEY"]) as capture:
    @attest(capture, stream_id="str_...")
    def score_case(case: dict) -> dict:
        return {"decision": "manual_review", "policy_id": "policy-2026-01"}

    score_case({"case_id": "case-2026-0001"})
with AttestoV2Client.with_bearer_token(os.environ["ATTESTO_TENANT_TOKEN"]) as operator:
    print(article12(operator, "str_..."))

The capture path uses a system API key; the report path reads tenant stream events and therefore requires a tenant/operator bearer token.

attesto --token-env ATTESTO_TENANT_TOKEN \
  report article12 --stream str_... --output report.md

What the SDK handles

The SDKs are intentionally thin server-side clients. They do not hide the evidence model, but they remove repetitive transport work so your application can focus on choosing the right event shape and verifying the returned evidence.

ConcernSDK behaviorDeveloper responsibility
Base URLDefaults to https://verify.attesto.eu.Override only for private/staging deployments.
AuthenticationSupports system API-key mode and tenant bearer-token mode.Use the narrowest credential needed for the task.
IdempotencyCreates idempotency keys for writes when not supplied.Reuse the same key when retrying the same body from your own job system.
RetriesRetries transient 429, 5xx, and transport errors with backoff.Do not mutate payloads between retries.
Proofstream helpersExposes stream, receipt, checkpoint, anchor, IVC, bundle, and verify helpers.Choose stream granularity and policy IDs deliberately.
ErrorsRaises typed auth, validation, rate-limit, and server errors.Log safe error categories, not API keys or raw secret-bearing payloads.

Capability matrix

CapabilityPythonTypeScriptGoCLI
Streams/events/receiptsYesYesYesYes
Windows/checkpoints/consistencyYesYesYesYes
Remote verifier APIYesYesYesYes
Offline receipt verificationVerifier helper/APIVerifier helper/APIYesYes
Witness policy and fork evidenceYesYesYesYes
Anchors and IVC epochsYesYesYesYes
ConnectorsYesYesYesYes
Local Vault relay/witnessYesYesYesYes
Provenance verification (Attesto 3): disclosure, bundle provenance, key revocation, effective assurance, ZK range resultYes (offline)Yes (offline)Yes (offline)No
Exact private-numeric opening (Pedersen)attesto[zk] extra@noble/curves peergo.attesto.eu/sdk/zk moduleNo
Release readiness evidenceVia scriptsVia scriptsVia CLI/module testsYes

Python

pip install attesto
import os
from datetime import UTC, datetime
from attesto import AttestoClient

attesto = AttestoClient(api_key=os.environ["ATTESTO_API_KEY"])
ack = attesto.log_event(
    type="inference",
    status="verified",
    ts=datetime.now(UTC),
    payload={
        "model": "risk-service-v4",
        "score": 0.91,
        "policy_id": "policy-2026-01",
    },
)
print(ack.id)

Python async

import os
from datetime import UTC, datetime
from attesto import AsyncAttestoClient

async with AsyncAttestoClient(api_key=os.environ["ATTESTO_API_KEY"]) as attesto:
    ack = await attesto.log_event(
        type="ai.decision",
        status="verified",
        ts=datetime.now(UTC),
        payload={"decision": "manual_review", "score": 91},
    )
    print(ack.id)

TypeScript

npm install @attesto/sdk
import { AttestoClient } from "@attesto/sdk";

const attesto = new AttestoClient({
  apiKey: process.env.ATTESTO_API_KEY!,
});

const ack = await attesto.logEvent({
  type: "inference",
  status: "verified",
  ts: new Date(),
  payload: {
    model: "risk-service-v4",
    score: 0.91,
    policy_id: "policy-2026-01",
  },
});
console.log(ack.id);

TypeScript attestedFetch

Use attestedFetch when an OpenAI-compatible SDK or framework accepts a custom fetch implementation. It records commitments only, never raw prompts or completions. strict: true fails closed when evidence cannot be submitted; fail-open mode must be monitored.

import { AttestoV2Client, attestedFetch } from "@attesto/sdk";

const client = new AttestoV2Client({ apiKey: process.env.ATTESTO_API_KEY! });
const fetchWithEvidence = attestedFetch(client, {
  streamId: "str_...",
  capture: "commitments",
  strict: true,
});

Proofstream v2 client

Use AttestoV2Client when you need stream-level receipts, checkpoint consistency, witness policy visibility, verifier bundles, and offline verification helpers.

from attesto import AttestoV2Client
from datetime import UTC, datetime
import os

with AttestoV2Client(api_key=os.environ["ATTESTO_API_KEY"]) as attesto:
    stream = attesto.create_stream(
        use_case="ai-decision-history",
        policy_id="policy-2026-01",
    )
    receipt = attesto.log_event(
        stream_id=stream.stream_id,
        source_ref="source-event-001",
        event_type="decision",
        occurred_at=datetime.now(UTC),
        payload={"decision": "review", "score": 91},
    )
    stored = attesto.get_receipt(receipt.stream_event_id)
    report = attesto.verify_receipt(
        receipt=stored.receipt,
        public_key_hex=os.environ["ATTESTO_RECEIPT_SIGNER_PUBLIC_KEY_HEX"],
        stream_event_id=receipt.stream_event_id,
    )
    assert report.ok

TypeScript Proofstream:

import { AttestoV2Client } from "@attesto/sdk";

const attesto = new AttestoV2Client({
  apiKey: process.env.ATTESTO_API_KEY!,
});

const stream = await attesto.createStream({
  useCase: "ai-decision-history",
  policyId: "policy-2026-01",
});

const receipt = await attesto.logEvent(stream.streamId, {
  sourceRef: "case-2026-0001:decision-1",
  eventType: "ai.decision",
  occurredAt: new Date(),
  payload: { decision: "manual_review", score: 91 },
});

const report = await attesto.verifyReceipt({
  receipt: receipt.receipt,
  streamEventId: receipt.streamEventId,
  publicKeyHex: process.env.ATTESTO_RECEIPT_SIGNER_PUBLIC_KEY_HEX!,
});
if (!report.ok) throw new Error(report.problems.join("; "));

Go

Use Go for infrastructure automation, security tooling, cloud workers, and verifier services. The Go SDK currently uses only the Go standard library and is resolved from the public go.attesto.eu/sdk module path.

go get go.attesto.eu/sdk
package main

import (
  "context"
  "fmt"
  "log"
  "os"

  attesto "go.attesto.eu/sdk"
)

func main() {
  client, err := attesto.NewClient(os.Getenv("ATTESTO_API_KEY"))
  if err != nil {
    log.Fatal(err)
  }

  stream, err := client.CreateStream(context.Background(), attesto.StreamCreateInput{
    UseCase: "ai-decision-history",
    PolicyID: "policy-2026-01",
  })
  if err != nil {
    log.Fatal(err)
  }

  receipt, err := client.LogEvent(context.Background(), stream.StreamID, attesto.EventInput{
    SourceRef: "case-2026-0001:decision-1",
    EventType: "ai.decision",
    Payload: attesto.M{"decision": "manual_review", "score": 91},
  })
  if err != nil {
    log.Fatal(err)
  }

  fmt.Println(receipt.StreamEventID, receipt.EventHash)
}

CLI

The Attesto CLI is the operator and verifier surface for scripted workflows. It supports JSON output, local config, stream/event actions, receipt verification, bundle verification, fork evidence, quorum evidence, connectors, Local Vault, and release-readiness evidence checks. It never prints stored API keys, tenant tokens, or connector secrets.

Install the signed CLI from get.attesto.eu. The installers verify the release SHA256 checksum before installing anything, and the manifest signature can be verified with cosign. The Homebrew formula and the native Linux packages repackage the same channel binaries: their hashes come from the cosign-signed SHA256SUMS manifest, never from a separate build:

# Linux / macOS
curl -fsSL https://get.attesto.eu | sh

# Windows (PowerShell; user-level install, no admin rights)
irm https://get.attesto.eu/install.ps1 | iex

# macOS / Linux (Homebrew)
brew tap attesto/attesto https://git.attesto.eu/attesto/homebrew-attesto.git
brew trust attesto/attesto
brew install attesto

# Native Linux packages: verify the signed manifest first
curl -fsSLO https://get.attesto.eu/0.5.0/SHA256SUMS
curl -fsSLO https://get.attesto.eu/0.5.0/SHA256SUMS.sig
cosign verify-blob --key https://get.attesto.eu/cosign.pub --insecure-ignore-tlog --signature SHA256SUMS.sig SHA256SUMS

# Debian / Ubuntu (run the install as root; arm64 debs and aarch64 rpms
# are on the same channel)
curl -fsSLO https://get.attesto.eu/0.5.0/attesto_0.5.0-1_amd64.deb
sha256sum -c --ignore-missing SHA256SUMS
apt install ./attesto_0.5.0-1_amd64.deb

# Fedora / RHEL (run the install as root)
curl -fsSLO https://get.attesto.eu/0.5.0/attesto-0.5.0-1.x86_64.rpm
sha256sum -c --ignore-missing SHA256SUMS
dnf install ./attesto-0.5.0-1.x86_64.rpm

arm64/aarch64 packages are metadata-verified against the signed manifest but have not been executed on arm hardware.

CLI command reference

Command groupSubcommandsUse
version, config, login, logoutconfig get, config setInspect version and manage local redacted configuration.
streamscreate, get, headCreate streams, inspect tenant-visible stream metadata, and fetch the append-only head.
eventslog, batchSubmit one event or a JSON event batch with source timestamps and payload files.
receiptsget, verifyFetch a stored receipt and verify it locally or through /v2/verify/receipt.
windows, checkpoints, anchors, ivcget, verify, checkpoints consistency, ivc epochs get/verifyFetch and verify Proofstream windows, checkpoint roots, consistency proofs, anchor epochs, and IVC epochs.
witnesses, quorum, fork-evidencepolicies, status, receipts, inspect, verifyInspect witness policy, proof state, quorum material, and fork evidence.
bundles, verifybuild, get, verify, offline-verify, verify file, verify truth-packageBuild verifier bundles and verify bundles, portable receipt files, or Truth Package ZIPs.
connector, connectorsconnector init, connectors create, ingest, revoke, verifyScaffold connector manifests, manage tenant connectors, ingest events, and verify signed connector payloads.
local-vaultinstall, relay, spool, status, witness, fork-evidence, revokeOperate Local Vault installations, encrypted spool workflows, witness receipts, fork evidence, and revocation.
marketplaceinit, validate, submitPrepare publisher manifests, validate them locally, and submit assets into private Attesto review.
doctor, report, readinessreport article12, readiness lifecycle/fork-defense/quorum/assurance/connectors/local-vault/nova/productionRun install diagnostics, deterministic Article 12 reporting, and release-readiness evidence checks.
cd sdk/go
go run ./cmd/attesto --json version

go run ./cmd/attesto --json \
  --api-key-env ATTESTO_API_KEY \
  streams create \
  --use-case ai-decision-history \
  --policy-id policy-2026-01

Offline receipt verification:

go run ./cmd/attesto --json receipts verify \
  --file receipt.json \
  --public-key-hex "$ATTESTO_RECEIPT_SIGNER_PUBLIC_KEY_HEX"

Production readiness evidence check:

go run ./cmd/attesto --json readiness lifecycle
go run ./cmd/attesto --json readiness fork-defense
go run ./cmd/attesto --json readiness production

Marketplace publisher automation:

go run ./cmd/attesto --json marketplace init \
  --output attesto.connector.json \
  --slug signed-webhook-evidence \
  --name "Generic Signed Webhook Evidence" \
  --version 1.0.0 \
  --category compliance \
  --summary "Produces Attesto evidence for signed webhook events." \
  --description "Produces verifiable Proofstream events for signed webhook payloads." \
  --publisher-slug attesto \
  --publisher-name Attesto \
  --repository-url https://git.rotz.ai/attesto/attesto-v1/src/branch/attesto-2.0/connectors/webhook \
  --docs-url https://docs.attesto.eu/manuals/connectors.html#signed \
  --provider-url https://docs.attesto.eu/manuals/connectors.html#signed \
  --auth-mode signed-webhook \
  --auth-scopes webhook:read \
  --sync-modes webhook \
  --event-types webhook.event.received \
  --canary-ref release/attesto-2.0-connector-assurance-readiness/result.json \
  --capabilities proofstream,offline-verification

go run ./cmd/attesto --json marketplace validate \
  --manifest-file attesto.connector.json

go run ./cmd/attesto --json \
  --token-env ATTESTO_TENANT_TOKEN \
  marketplace submit \
  --manifest-file attesto.connector.json \
  --source-ref https://git.rotz.ai/attesto/attesto-v1/src/branch/attesto-2.0/connectors/webhook \
  --visibility public \
  --pricing-model free

Operator endpoints

Tenant/operator endpoints require bearer-token mode. Use this only in trusted operator automation and never in public clients.

from attesto import AttestoV2Client

operator = AttestoV2Client.with_bearer_token(
    os.environ["ATTESTO_TENANT_TOKEN"],
)
streams = operator.list_tenant_streams()
forks = operator.list_fork_evidence(streams[0]["streamId"])
const operator = new AttestoV2Client({
  apiKey: process.env.ATTESTO_TENANT_TOKEN!,
  authMode: "bearer",
});

const streams = await operator.listTenantStreams();
const forks = await operator.listForkEvidence(String(streams[0].streamId));
operator, err := attesto.NewBearerClient(os.Getenv("ATTESTO_TENANT_TOKEN"))
if err != nil { log.Fatal(err) }
streams, err := operator.ListTenantStreams(context.Background(), "", 100, 0)
if err != nil { log.Fatal(err) }

Offline and online verify helpers

SDK verification methods are useful in services that receive Attesto receipts or bundles and need to fail closed before accepting them.

from attesto import AttestoV2Client
from datetime import UTC, datetime
import os

with AttestoV2Client(api_key=os.environ["ATTESTO_API_KEY"]) as attesto:
    report = attesto.verify_object(
        kind="bundle",
        proof_object=bundle_object,
    )
    if not report.ok:
        raise RuntimeError(report.problems)
const report = await attesto.verifyObject({
  kind: "bundle",
  object: bundleObject,
});

if (!report.ok) {
  throw new Error(report.problems.join("; "));
}

Provenance verification (Attesto 3)

The 0.5.0 SDKs add a verification client for the Attesto 3 provenance lane: commitment-only provenance streams fed by a customer-controlled Local Vault. The vault's pinned Rust edge core builds capsules, commitments and signatures; the SDK re-derives and checks them and deliberately cannot construct a capsule or a randomizer. Every function in this section runs offline, with no call to Attesto, and every report carries a not_claimed list that a verifier screen must render next to the result. Protocols: ATTESTO-PROVENANCE-001, ATTESTO-DISCLOSURE-001, ATTESTO-ZK-RANGE-001 and the bundle provenance binding of ATTESTO-PROOFSTREAM-001. Conformance is pinned by the shared golden-vector corpus in all three languages.

VerifierPython (attesto.provenance)TypeScript (@attesto/sdk)Go (go.attesto.eu/sdk)
Disclosure presentationverify_disclosureverifyDisclosureVerifyDisclosure
Bundle provenance inclusion + key revocationverify_bundle_provenance, evaluate_key_revocationverifyBundleProvenance, evaluateKeyRevocationVerifyBundleProvenance, EvaluateKeyRevocation
Effective assuranceeffective_assuranceeffectiveAssuranceEffectiveAssurance
Exact private-numeric openingverify_pedersen_opening (attesto[zk])verifyPedersenOpening (@noble/curves peer)zk.VerifyOpening (go.attesto.eu/sdk/zk)
ZK range resultinspect_predicate_result, validate_range_statementinspectPredicateResult, validateRangeStatementInspectPredicateResult, ValidateRangeStatement

Verify a disclosure presentation offline

A holder's Local Vault issues a selective-disclosure presentation: the revealed leaves with their randomizers, two-hop inclusion proofs to the capsule root, and an Ed25519 signature by the issuing installation. The verifier opens each revealed commitment and replays each proof to the presented capsule_root. Problems are collected, not raised, so the caller sees everything that is wrong. Pass the nonce you issued for challenge mode; without it the presentation is bounded only by its expires_at and the report says bounded_lifetime rather than implying a freshness it did not check. Non-claim: the disclosure proves the revealed leaves are in the capsule; it is not a statement that the capsule holds nothing else.

from attesto.provenance import verify_disclosure

report = verify_disclosure(
    presentation,
    expected_nonce=challenge,
    subject_commitment=asset_commitment,
)
report.ok               # every leaf opened and every proof folded to capsule_root
report.verified_leaves  # ({"subtree": "claims", "leaf_role": "c2pa_manifest_valid", "value": ...},)
report.freshness        # "challenge" | "bounded_lifetime"
report.subject_checked  # True only when subject_commitment matched
report.problems         # () or every problem found
report.not_claimed      # ({"id": "undisclosed_facts_absent", "statement": ...},)
import { verifyDisclosure } from "@attesto/sdk";

const report = await verifyDisclosure(presentation, {
  expectedNonce: challenge,
  subjectCommitment: assetCommitment,
});
report.ok; report.verified_leaves; report.freshness;
report.subject_checked; report.problems; report.not_claimed;
report := attesto.VerifyDisclosure(presentation,
	attesto.WithExpectedNonce(challenge),
	attesto.WithSubjectCommitment(assetCommitment),
)
report.Ok; report.VerifiedLeaves; report.Freshness
report.SubjectChecked; report.Problems; report.NotClaimed

Verify bundle provenance inclusion and key revocation offline

A verifier bundle over a provenance stream carries provenance_root, provenance_event_count and vault_key_lifecycle inside its hashed payload. An inclusion object, returned by GET /v2/streams/{streamId}/provenance-events/{sourceRef}/bundle-inclusion?from_checkpoint_id=...&to_checkpoint_id=... or carried as provenance_inclusions next to the bundle, proves one capsule root under that root. The verifier recomputes the bundle hash, re-hashes the leaf from its fields, replays the proof, takes the receipt time for the leaf's seq_no from the bundle's own receipts, and applies the frozen revocation rule to the installation the leaf names. inclusion and key_status stay separate: a capsule root can be provably under the bundle while its key was revoked before receipt, and not_evaluated is never a pass. Revocation is evaluated against the platform receipt time, never the vault-claimed occurred_at, with an inclusive boundary; a claim that predates the revocation is flagged suspect_backdated. Non-claims: the root proves the capsule root existed under the bundle and nothing about the capsule's contents; the key lifecycle is as of bundle build, so a later revocation is not in the bundle.

from attesto.provenance import evaluate_key_revocation, verify_bundle_provenance

report = verify_bundle_provenance(bundle, inclusion)
report.ok          # bundle hash holds, inclusion VALID, key live at receipt
report.inclusion   # "VALID" | "INVALID"
report.key_status  # "valid" | "revoked_at_receipt" | "unknown_installation" | "not_evaluated"
report.flags       # e.g. ("revoked_at_receipt", "suspect_backdated")
report.not_claimed # three statements

verdict = evaluate_key_revocation(
    revoked_at=key_status["revokedAt"],          # None when never revoked
    receipt_time=receipt["payload"]["issued_at"],
    claimed_occurred_at=envelope["occurred_at"],
    reason=key_status["revocationReason"],
)
verdict.accepted   # status == "valid"
import { evaluateKeyRevocation, verifyBundleProvenance } from "@attesto/sdk";

const report = await verifyBundleProvenance(bundle, inclusion);
report.ok; report.inclusion; report.key_status; report.flags; report.not_claimed;

const verdict = evaluateKeyRevocation(
  keyStatus.revokedAt,
  receipt.payload.issued_at,
  envelope.occurred_at,
  keyStatus.revocationReason,
);
verdict.accepted;
report := attesto.VerifyBundleProvenance(bundle, inclusion)
report.Ok; report.Inclusion; report.KeyStatus; report.Flags; report.NotClaimed

verdict := attesto.EvaluateKeyRevocation(revokedAt, receiptTime, claimedOccurredAt, reason)
verdict.Accepted()

Derive effective assurance (L3 is derived, never signed)

A vault signs L0 (software-held key), L1 (key in a non-extractable PKCS#11 token) or L2 (L1 plus a TPM 2.0 quote over the vault's measurement) in its envelope, and the platform refuses an L1/L2 envelope it cannot substantiate from a registered attestation. L3 has no on-wire representation: the verifier derives it from L2 plus a met witness quorum on the containing checkpoint, and an envelope claiming L3 is refused. Anchor state is reported alongside and never promotes a level. The report keeps vault assurance, witness quorum, anchor state and the derived level as four separate facts. How the levels are earned is described in the Local Vault guide.

from attesto.provenance import effective_assurance

report = effective_assurance("L2", witness_quorum_met=True, anchor_confirmed=True)
report.effective  # "L3"
report.derived    # True: derived here, signed by nobody
report.reasons    # ("anchor confirmed; anchoring does not promote assurance", "L3 derived from L2 plus a met witness quorum")
effective_assurance("L2").effective  # "L2": quorum not evaluated withholds L3
effective_assurance("L3")            # raises AttestoProvenanceError
import { effectiveAssurance } from "@attesto/sdk";

const report = effectiveAssurance("L2", { witnessQuorumMet: true, anchorConfirmed: true });
report.effective; // "L3"
report.derived;   // true
report.reasons;
met := true
report, err := attesto.EffectiveAssurance("L2", &met, &met)
report.Effective // "L3"
report.Derived   // true
report.Reasons

Verify an exact private-numeric opening

A private numeric claim commits its encoded value as a Pedersen commitment over ristretto255. When a holder reveals the value and the blinding, the verifier recomputes the commitment and compares it byte for byte. Curve arithmetic is optional because the rest of verification is SHA-256 and Merkle work: Python needs attesto[zk], TypeScript the @noble/curves peer dependency, and Go the separate go.attesto.eu/sdk/zk module. A client without it reports not_checked. The descriptor must already have opened its claim leaf under the capsule root, otherwise a matching pair can be fabricated whole. A value of exactly zero is a legal opening. This does not verify a range proof.

from attesto.provenance import pedersen_available, verify_pedersen_opening

opened = (
    verify_pedersen_opening(descriptor, encoded_value, blinding_scalar)
    if pedersen_available()
    else None  # report "not_checked"
)
import { pedersenAvailable, verifyPedersenOpening } from "@attesto/sdk";

const opened = (await pedersenAvailable())
  ? await verifyPedersenOpening(descriptor, encodedValue, blindingScalar)
  : null; // report "not_checked"
import "go.attesto.eu/sdk/zk"

opened, err := zk.VerifyOpening(descriptor, encodedValue, blindingScalar)

Inspect a ZK range result

Selective disclosure v2 proves that a named detector's measurement fell inside an interval without revealing it. No SDK verifies the range proof itself; that remains the Rust core's job. The SDK reports zk_predicate: not_checked under verified_here, keeps what the issuer claimed under reported_by_issuer, and refuses a result that drops one of the three required non-claims or carries a verdict-shaped field such as authentic, score or probability. A proven bound says nothing about whether the content is machine-generated. Capsule evidence from an AttestoMark Image, Audio or Video provider is an ATTESTO-PROVIDER-RESULT-001/0.2 object whose presented_matches_record field reports whether the bytes presented were the exact asset that was marked; a mismatch is an observation an honest transcode also produces, never a refusal.

from attesto.provenance import inspect_predicate_result, validate_range_statement

report = inspect_predicate_result(result)
report["verified_here"]       # {"zk_predicate": "not_checked", "capsule_inclusion": "not_checked"}
report["reported_by_issuer"]
report["not_claimed"]         # detector_correctness_not_proven, content_truth_not_proven, ai_generation_not_proven
width = validate_range_statement(statement)  # 8 | 16 | 32 | 64
import { inspectPredicateResult, validateRangeStatement } from "@attesto/sdk";

const report = inspectPredicateResult(result);
report.verified_here; report.reported_by_issuer; report.not_claimed;
const width = validateRangeStatement(statement);
report, err := attesto.InspectPredicateResult(result, nil)
report.VerifiedHere; report.ReportedByIssuer; report.NotClaimed
width, err := attesto.ValidateRangeStatement(statement)

Not in the SDKs: capsule construction, randomizer generation and envelope signing live in the Local Vault's edge core; range proofs are verified only by the Rust core; there is no client wrapper yet for POST /v2/provenance/streams; and the attesto CLI does not verify disclosures or bundle provenance in 0.5.0.

MockAttesto for local tests

attesto.testing.MockAttesto is a Python test harness for local CI and integration tests. It uses the same canonical hashing and receipt shapes as the SDK, but signs with a per-instance throwaway mock key and marks objects as mock evidence. Use it to test your application flow without network access or an Attesto account; do not use mock receipts in production evidence or customer bundles.

MockAttesto is intentionally fail-closed against real trust roots: verification with a production witness key must reject mock evidence. That keeps tests fast without creating a path for synthetic evidence to pass as production proof.

Companion packages and edge surfaces

The core SDKs stay small. Separate packages cover edge relay, MCP tooling, workflow nodes, and the future independent witness node. These packages must never become hidden transitive dependencies of the core SDKs.

SurfacePackageUseStatus rule
MCP serverattesto-mcpExpose deterministic Attesto tools to MCP hosts.Install only from PyPI release evidence.
Local Vaultattesto-local-vaultCustomer-edge encrypted spool, relay, and optional witness mode.Keys stay local; no frontend use.
n8n noden8n-nodes-attestoWorkflow receipts and signed webhook verification.Credentials stay in n8n credentials.
Independent witness nodeattesto-witness, @attesto/witness, go.attesto.eu/witnessPrivacy-preserving observation of public or explicitly shared heads.Phase-gated; not a core SDK dependency.
pip install attesto-mcp
pipx install attesto-local-vault
npm install n8n-nodes-attesto

Specified as a privacy-preserving observation node package. Current customer-operated witness behavior is available through Local Vault witness mode; standalone attesto-witness, @attesto/witness, and go.attesto.eu/witness should be installed only after release evidence marks that package green.

Security rules