Skip to content

feat(sdk): add Python SDK — port TypeScript verify.ts to Python (#15)#22

Open
nanookclaw wants to merge 1 commit intoFransDevelopment:mainfrom
nanookclaw:feat/python-sdk
Open

feat(sdk): add Python SDK — port TypeScript verify.ts to Python (#15)#22
nanookclaw wants to merge 1 commit intoFransDevelopment:mainfrom
nanookclaw:feat/python-sdk

Conversation

@nanookclaw
Copy link
Copy Markdown
Contributor

Summary

Implements Issue #15: Python port of the TypeScript SDK for native attestation verification in Python-based Working Group members (APS, AgentID, Agora all use PyCA per the WG thread).

What this adds

sdk/python/
  src/open_agent_trust/
    __init__.py   # public API
    types.py      # dataclass mirrors of TS types
    verify.py     # 14-step verification protocol
  tests/
    test_verify.py  # 20 tests — all passing
  pyproject.toml    # pip install open-agent-trust
  README.md

Usage

from open_agent_trust import verify_attestation, RegistryManifest, RevocationList

manifest = RegistryManifest.from_dict(manifest_json)
revocations = RevocationList.from_dict(revocations_json)

result = verify_attestation(token, manifest, revocations, expected_audience="https://your-api.com")
if result.valid:
    print(result.claims.scope)   # ['read']
    print(result.issuer.issuer_id)

Implementation

  • Ed25519 signature verification via cryptography (PyCA) — matches WG member tooling
  • JWT decode via PyJWT with EdDSA algorithm support
  • All 14 steps from spec/03-verification.md implemented with matching comment references
  • Grace period: 90-day deprecated key window (spec/04-key-rotation.md)
  • Fast-path revocation list check before manifest lookup

Tests (20/20 passing)

Covers all acceptance criteria from Issue #15:

Test Scenario
✅ valid attestation Happy path + claims extraction
✅ valid with nonce Per-session replay prevention
✅ unknown issuer Step 4
✅ revoked issuer (manifest) Step 5
✅ suspended issuer Step 5
✅ unknown key Step 7
✅ revoked key (manifest status) Step 8
✅ revoked key (fast-path list) Pre-manifest fast reject
✅ invalid signature Wrong keypair
✅ tampered token Payload mutation
✅ malformed JWS Garbage input
✅ expired attestation (JWT exp) Step 13
✅ expired registry key (expires_at) Step 10
✅ deprecated key past grace period Step 9b
✅ deprecated key within grace period Step 9c — ACCEPT
✅ audience mismatch Step 13
✅ nonce mismatch Step 13
✅ nonce not required Token has nonce, service doesn't check
✅ claims populated on success sub/aud/scope/constraints/user_pseudonym
✅ from_dict() round-trip RegistryManifest.from_dict()

Dependencies

  • Python ≥ 3.10
  • cryptography >= 41
  • PyJWT >= 2.8

…sDevelopment#15)

Implements the 14-step Verification Protocol from spec/03-verification.md
in Python, matching the TypeScript SDK's API surface for native use in
APS, AgentID, Agora, and other Python-based working group members.

Structure:
  sdk/python/
    src/open_agent_trust/
      __init__.py   — public API surface
      types.py      — dataclass mirrors of TypeScript types (RegistryManifest,
                      RevocationList, IssuerEntry, PublicKey, AttestationClaims,
                      VerificationResult, ...)
      verify.py     — 14-step verifyAttestation() implementation
    tests/
      test_verify.py — 20 tests covering all acceptance criteria
    pyproject.toml   — pip install open-agent-trust
    README.md

Implementation notes:
  - Ed25519 signature via cryptography (PyCA) — same library WG members use
  - JWT decode via PyJWT with EdDSA algorithm support
  - Grace period enforcement: 90 days (spec/04-key-rotation.md)
  - Fast-path revocation list check before manifest lookup
  - All 14 steps mapped to spec/03-verification.md section references

Test coverage (20/20 passing):
  - Valid attestation + nonce check
  - Unknown/revoked/suspended issuer
  - Unknown/revoked key (manifest + fast-path revocations list)
  - Invalid signature / tampered token / malformed JWS
  - Expired JWT token (step 13 exp claim)
  - Expired registry public key (step 10 expires_at)
  - Deprecated key within/past 90-day grace period (step 9)
  - Audience mismatch / nonce mismatch
  - Claims extraction (sub, aud, scope, constraints, user_pseudonym)
  - RegistryManifest.from_dict() round-trip

Closes FransDevelopment#15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant