This release is a pre-release and may not be stable for production use.
arc-avs-sdk
Python SDK for the ARC Privacy AVS — a Sepolia-anchored validator network
that proves applications process user data without retention. Same wire format
as @arc-avs/sdk on npm; envelopes round-trip byte-exact between TS and Python.
Two custody modes:
key_custody="server"(default) — runtime generates and holds each user's KEM keypair. Backend can decrypt records on demand. Convenient for tests and managed-account flows.key_custody="client"— non-custodial. The user's KEM secret stays on the client (typically derived from a wallet PRF). The backend accepts pre-sealed envelopes viapersist_envelopeand serves them back as ciphertext viafetch_envelope.read/process/export_userraiseClientCustodyErrorbecause they need the secret the server doesn't have.
pip install arc-avs-sdk
# adapters & router are optional extras
pip install "arc-avs-sdk[postgres,neo4j,chain]"
Quick start
import asyncio
from arc_avs_sdk import arc, init
from arc_avs_sdk.adapter.memory import MemoryAdapter
schema = arc.schema(
app_id = "your-app.com",
compliance = ["GDPR", "CCPA"],
classes = {
"User": arc.identity({
"profile": arc.encrypted.struct({
"name": arc.encrypted.string(),
"email": arc.encrypted.email(),
}),
"events": arc.collection(
item_kind="event",
query="indexed",
index_fields=["kind"],
retention="permanent",
),
}),
},
)
async def main() -> None:
runtime = await init(schema, adapter=MemoryAdapter())
user, _ = await runtime.create_user("User", {"name": "Alice", "email": "a@b.c"})
ref, proof = await runtime.put_record(
user, "User", "event", {"kind": "login"}, index_fields={"kind": "login"}
)
print(proof.input_hash)
asyncio.run(main())
Non-custodial (key_custody="client")
The user's KEM secret never reaches the backend. Frontend (browser, mobile, any TS/JS runtime) seals envelopes locally and ships bytes to the Python backend; the backend persists, commits the proof to the validator network, and serves envelopes back as ciphertext on read. Decryption only happens client-side.
Backend (Python):
from arc_avs_sdk import arc, init, encode_envelope, UserHandle
from arc_avs_sdk.adapter.postgres import PostgresAdapter
runtime = await init(schema, adapter=PostgresAdapter(...), key_custody="client")
# 1. Register the client-derived identity. The user_kem_public_key arrives
# from the frontend (e.g. derived from a wallet PRF).
user = runtime.register_user("ar_alice", user_kem_public_key=client_pubkey_bytes)
# 2. Persist a pre-sealed envelope. The frontend already sealed it with
# @arc-avs/sdk's sealEnvelope; the backend just stores + commits the proof.
ref, proof = await runtime.persist_envelope(
user, "User", "event", envelope_from_client,
index_fields={"kind": b"\\x01..."}, # detEnc bytes from client
)
# 3. Serve envelopes back as ciphertext. encode_envelope produces the
# cross-language wire format the TS SDK can decode.
envelope = await runtime.fetch_envelope(user, ref)
return Response(content=encode_envelope(envelope), media_type="application/octet-stream")
# These raise ClientCustodyError — the server doesn't have the secret key:
# await runtime.create_user(...)
# await runtime.put_record(...)
# await runtime.read(...)
# await runtime.process(...)
# await runtime.export_user(...)
Frontend (TypeScript, @arc-avs/sdk):
import { sealEnvelope, openEnvelope } from "@arc-avs/sdk";
// Seal locally — backend never sees plaintext
const env = sealEnvelope({
plaintext: new TextEncoder().encode(JSON.stringify({ kind: "login" })),
userKemPublicKey: clientKp.publicKey,
appEcdsaPrivateKey, appMlDsaPrivateKey,
appId, className: "User.event", nonceSeq: 1n,
});
// Ship envelope bytes to backend's persist endpoint
await fetch("/api/arc/persist", { method: "POST", body: encodeEnvelope(env) });
// On read, backend returns ciphertext bytes — decrypt locally
const buf = await (await fetch(`/api/arc/envelope/${ref}`)).arrayBuffer();
const env2 = decodeEnvelope(new Uint8Array(buf));
const plaintext = openEnvelope({ envelope: env2, userKemSecretKey: clientKp.secretKey });
purge_user works in either custody mode — it crypto-shreds the wrapped
keys at the adapter level, no plaintext access required. That covers GDPR
Art. 17 even when the runtime never had the secret to begin with.
What's shipped
- Crypto layer — ML-KEM-768, ML-DSA-65, AES-256-GCM, secp256k1 ECDSA, keccak256
- Schema DSL — domain-agnostic, byte-canonical, on-chain hash matches the TS canonicalization
- Runtime · server-custody —
create_user,put_record,read,list,process,purge_user,export_user - Runtime · client-custody (non-custodial) —
register_user,persist_envelope,fetch_envelope,list,purge_user - Adapters —
memory,postgres,mongo,redis,neo4j(graph-RAG / agent memory) - Processors —
openai,anthropic,mistral,kimi,nous - Validator router —
web3.pybased EIP-712 attestation submission
Compatibility
The Python CipherEnvelope serializes to the same byte layout as the TypeScript
SDK. A round-trip test in tests/test_envelope_compat.py proves that an
envelope sealed in TS opens in Python and vice-versa.
| Property | TS | Python |
|---|---|---|
| Schema canonical hash | keccak256(canonicalize_schema(s)) | keccak256(canonicalize_schema(s)) |
bind_aad(app_id, class, seq) |
byte-identical | byte-identical |
bind_digest(...) |
byte-identical | byte-identical |
proof_bind_digest(...) |
byte-identical | byte-identical |
This matters because the on-chain inputHash recorded by PrivacyTaskManager
must agree across language stacks.
Release files for arc-avs-sdk 1.0.0a10
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| arc_avs_sdk-1.0.0a10.tar.gz | 50.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| arc_avs_sdk-1.0.0a10-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 112.2 kB
Release files / arc_avs_sdk-1.0.0a10.tar.gz
| Download URL | arc_avs_sdk-1.0.0a10.tar.gz |
|---|---|
| Size | 50.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b61d52d890d8cfa4927c342443c773a0a66c6fb10c91c3109db1badf4994fcc1
|
|
BLAKE2b-256 checksum How to use checksums |
f122f728730fafea7d57e0532c4744ad9c04b73df445df83c9fb9c41d178681c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|
Release files / arc_avs_sdk-1.0.0a10-py3-none-any.whl
| Download URL | arc_avs_sdk-1.0.0a10-py3-none-any.whl |
|---|---|
| Size | 61.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6e99b608e605ffc7c8297c9535b6c932a1b27658aa2f190b24c6e0fde02e80a9
|
|
BLAKE2b-256 checksum How to use checksums |
8597211c91756e9d75f091f9a42bbe291e3ba324372034b48a5cfb45959ad8f5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.4
|