aitp-sdk 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. aitp_sdk-0.2.0/Cargo.toml +112 -0
  2. aitp_sdk-0.2.0/PKG-INFO +12 -0
  3. aitp_sdk-0.2.0/aitp.pyi +221 -0
  4. aitp_sdk-0.2.0/bindings/aitp-py/Cargo.lock +1984 -0
  5. aitp_sdk-0.2.0/bindings/aitp-py/Cargo.toml +76 -0
  6. aitp_sdk-0.2.0/bindings/aitp-py/README.md +143 -0
  7. aitp_sdk-0.2.0/bindings/aitp-py/aitp.pyi +221 -0
  8. aitp_sdk-0.2.0/bindings/aitp-py/src/agent.rs +424 -0
  9. aitp_sdk-0.2.0/bindings/aitp-py/src/bundle.rs +199 -0
  10. aitp_sdk-0.2.0/bindings/aitp-py/src/delegation.rs +224 -0
  11. aitp_sdk-0.2.0/bindings/aitp-py/src/helpers.rs +48 -0
  12. aitp_sdk-0.2.0/bindings/aitp-py/src/lib.rs +64 -0
  13. aitp_sdk-0.2.0/bindings/aitp-py/src/manifest.rs +26 -0
  14. aitp_sdk-0.2.0/bindings/aitp-py/src/oidc.rs +204 -0
  15. aitp_sdk-0.2.0/bindings/aitp-py/src/pinning.rs +76 -0
  16. aitp_sdk-0.2.0/bindings/aitp-py/src/renewal.rs +57 -0
  17. aitp_sdk-0.2.0/bindings/aitp-py/src/revocation.rs +90 -0
  18. aitp_sdk-0.2.0/bindings/aitp-py/src/session.rs +375 -0
  19. aitp_sdk-0.2.0/bindings/aitp-py/src/tct.rs +238 -0
  20. aitp_sdk-0.2.0/bindings/aitp-py/tests/test_delegation.py +122 -0
  21. aitp_sdk-0.2.0/bindings/aitp-py/tests/test_handshake.py +122 -0
  22. aitp_sdk-0.2.0/bindings/aitp-py/tests/test_manifest_verify.py +34 -0
  23. aitp_sdk-0.2.0/bindings/aitp-py/tests/test_oidc_identity.py +189 -0
  24. aitp_sdk-0.2.0/bindings/aitp-py/tests/test_p256_suite.py +57 -0
  25. aitp_sdk-0.2.0/bindings/aitp-py/tests/test_pinning.py +75 -0
  26. aitp_sdk-0.2.0/bindings/aitp-py/tests/test_renewal.py +82 -0
  27. aitp_sdk-0.2.0/bindings/aitp-py/tests/test_revocation.py +77 -0
  28. aitp_sdk-0.2.0/bindings/aitp-py/tests/test_session_bundle.py +118 -0
  29. aitp_sdk-0.2.0/bindings/aitp-py/tests/test_tct_cache.py +114 -0
  30. aitp_sdk-0.2.0/crates/aitp-core/Cargo.toml +27 -0
  31. aitp_sdk-0.2.0/crates/aitp-core/src/aid.rs +434 -0
  32. aitp_sdk-0.2.0/crates/aitp-core/src/base64url.rs +89 -0
  33. aitp_sdk-0.2.0/crates/aitp-core/src/envelope.rs +288 -0
  34. aitp_sdk-0.2.0/crates/aitp-core/src/error.rs +314 -0
  35. aitp_sdk-0.2.0/crates/aitp-core/src/extensions.rs +108 -0
  36. aitp_sdk-0.2.0/crates/aitp-core/src/jcs.rs +87 -0
  37. aitp_sdk-0.2.0/crates/aitp-core/src/lib.rs +48 -0
  38. aitp_sdk-0.2.0/crates/aitp-core/src/raw_url.rs +120 -0
  39. aitp_sdk-0.2.0/crates/aitp-core/src/time.rs +114 -0
  40. aitp_sdk-0.2.0/crates/aitp-core/tests/jcs_properties.proptest-regressions +7 -0
  41. aitp_sdk-0.2.0/crates/aitp-core/tests/jcs_properties.rs +98 -0
  42. aitp_sdk-0.2.0/crates/aitp-core/tests/jcs_standard_vectors.rs +190 -0
  43. aitp_sdk-0.2.0/crates/aitp-core/tests/kat.rs +96 -0
  44. aitp_sdk-0.2.0/crates/aitp-crypto/Cargo.toml +24 -0
  45. aitp_sdk-0.2.0/crates/aitp-crypto/src/error.rs +22 -0
  46. aitp_sdk-0.2.0/crates/aitp-crypto/src/keys.rs +740 -0
  47. aitp_sdk-0.2.0/crates/aitp-crypto/src/lib.rs +15 -0
  48. aitp_sdk-0.2.0/crates/aitp-crypto/src/thumbprint.rs +120 -0
  49. aitp_sdk-0.2.0/crates/aitp-crypto/tests/integration.rs +121 -0
  50. aitp_sdk-0.2.0/crates/aitp-crypto/tests/kat.rs +143 -0
  51. aitp_sdk-0.2.0/crates/aitp-delegation/Cargo.toml +24 -0
  52. aitp_sdk-0.2.0/crates/aitp-delegation/src/builder.rs +190 -0
  53. aitp_sdk-0.2.0/crates/aitp-delegation/src/error.rs +64 -0
  54. aitp_sdk-0.2.0/crates/aitp-delegation/src/lib.rs +22 -0
  55. aitp_sdk-0.2.0/crates/aitp-delegation/src/types.rs +180 -0
  56. aitp_sdk-0.2.0/crates/aitp-delegation/src/verifier.rs +501 -0
  57. aitp_sdk-0.2.0/crates/aitp-delegation/tests/multihop.rs +383 -0
  58. aitp_sdk-0.2.0/crates/aitp-delegation/tests/round_trip.rs +276 -0
  59. aitp_sdk-0.2.0/crates/aitp-delegation/tests/schema.rs +71 -0
  60. aitp_sdk-0.2.0/crates/aitp-envelope/Cargo.toml +17 -0
  61. aitp_sdk-0.2.0/crates/aitp-envelope/src/lib.rs +83 -0
  62. aitp_sdk-0.2.0/crates/aitp-handshake/Cargo.toml +31 -0
  63. aitp_sdk-0.2.0/crates/aitp-handshake/src/error.rs +56 -0
  64. aitp_sdk-0.2.0/crates/aitp-handshake/src/identity.rs +103 -0
  65. aitp_sdk-0.2.0/crates/aitp-handshake/src/identity_oidc.rs +216 -0
  66. aitp_sdk-0.2.0/crates/aitp-handshake/src/identity_pinned.rs +418 -0
  67. aitp_sdk-0.2.0/crates/aitp-handshake/src/lib.rs +28 -0
  68. aitp_sdk-0.2.0/crates/aitp-handshake/src/payloads.rs +189 -0
  69. aitp_sdk-0.2.0/crates/aitp-handshake/src/state_machine.rs +1199 -0
  70. aitp_sdk-0.2.0/crates/aitp-handshake/tests/fixtures/mock_oidc.rs +150 -0
  71. aitp_sdk-0.2.0/crates/aitp-handshake/tests/fixtures/mod.rs +3 -0
  72. aitp_sdk-0.2.0/crates/aitp-handshake/tests/full_handshake.rs +645 -0
  73. aitp_sdk-0.2.0/crates/aitp-handshake/tests/oidc_handshake.rs +425 -0
  74. aitp_sdk-0.2.0/crates/aitp-handshake/tests/p1_p8_regressions.rs +401 -0
  75. aitp_sdk-0.2.0/crates/aitp-handshake/tests/responder_identity.rs +220 -0
  76. aitp_sdk-0.2.0/crates/aitp-handshake/tests/revocation_hook.rs +447 -0
  77. aitp_sdk-0.2.0/crates/aitp-handshake/tests/schema.rs +219 -0
  78. aitp_sdk-0.2.0/crates/aitp-manifest/Cargo.toml +25 -0
  79. aitp_sdk-0.2.0/crates/aitp-manifest/src/builder.rs +336 -0
  80. aitp_sdk-0.2.0/crates/aitp-manifest/src/error.rs +45 -0
  81. aitp_sdk-0.2.0/crates/aitp-manifest/src/lib.rs +23 -0
  82. aitp_sdk-0.2.0/crates/aitp-manifest/src/types.rs +249 -0
  83. aitp_sdk-0.2.0/crates/aitp-manifest/src/verifier.rs +184 -0
  84. aitp_sdk-0.2.0/crates/aitp-manifest/tests/identity_type_compat.rs +93 -0
  85. aitp_sdk-0.2.0/crates/aitp-manifest/tests/pop_kat.rs +167 -0
  86. aitp_sdk-0.2.0/crates/aitp-manifest/tests/round_trip.rs +213 -0
  87. aitp_sdk-0.2.0/crates/aitp-manifest/tests/schema.rs +124 -0
  88. aitp_sdk-0.2.0/crates/aitp-session-bundle/Cargo.toml +21 -0
  89. aitp_sdk-0.2.0/crates/aitp-session-bundle/src/builder.rs +122 -0
  90. aitp_sdk-0.2.0/crates/aitp-session-bundle/src/error.rs +49 -0
  91. aitp_sdk-0.2.0/crates/aitp-session-bundle/src/lib.rs +46 -0
  92. aitp_sdk-0.2.0/crates/aitp-session-bundle/src/types.rs +73 -0
  93. aitp_sdk-0.2.0/crates/aitp-session-bundle/src/verifier.rs +168 -0
  94. aitp_sdk-0.2.0/crates/aitp-session-bundle/tests/round_trip.rs +202 -0
  95. aitp_sdk-0.2.0/crates/aitp-tct/Cargo.toml +34 -0
  96. aitp_sdk-0.2.0/crates/aitp-tct/src/builder.rs +180 -0
  97. aitp_sdk-0.2.0/crates/aitp-tct/src/error.rs +71 -0
  98. aitp_sdk-0.2.0/crates/aitp-tct/src/lib.rs +36 -0
  99. aitp_sdk-0.2.0/crates/aitp-tct/src/pop.rs +109 -0
  100. aitp_sdk-0.2.0/crates/aitp-tct/src/renewal.rs +242 -0
  101. aitp_sdk-0.2.0/crates/aitp-tct/src/revocation.rs +272 -0
  102. aitp_sdk-0.2.0/crates/aitp-tct/src/types.rs +168 -0
  103. aitp_sdk-0.2.0/crates/aitp-tct/src/verifier.rs +145 -0
  104. aitp_sdk-0.2.0/crates/aitp-tct/tests/manifest_expiry_bound.rs +98 -0
  105. aitp_sdk-0.2.0/crates/aitp-tct/tests/round_trip.rs +402 -0
  106. aitp_sdk-0.2.0/crates/aitp-tct/tests/schema.rs +125 -0
  107. aitp_sdk-0.2.0/pyproject.toml +31 -0
@@ -0,0 +1,112 @@
1
+ [workspace]
2
+ resolver = "2"
3
+ # Exclude `fuzz/` — cargo-fuzz uses its own profile and nightly-only
4
+ # features. Run via `cargo +nightly fuzz run <target>` from the
5
+ # `fuzz/` directory.
6
+ #
7
+ # `bindings/*` are excluded: the PyO3 / NAPI-rs crates are `cdylib`s
8
+ # built by maturin / napi-cli against an external Python / Node
9
+ # toolchain, so they must not be pulled into `cargo test --workspace`.
10
+ #
11
+ # `tests/e2e-llm` is excluded: it talks to live LLM provider APIs
12
+ # (OpenAI / Anthropic) gated on `AITP_RUN_LLM_TESTS=1`, and must not
13
+ # run under `cargo test --workspace` so CI never burns API credits.
14
+ # Run it explicitly from `tests/e2e-llm/`.
15
+ exclude = ["fuzz", "bindings/aitp-py", "bindings/aitp-node", "tests/e2e-llm"]
16
+ members = [
17
+ "crates/aitp-core",
18
+ "crates/aitp-crypto",
19
+ "crates/aitp-envelope",
20
+ "crates/aitp-manifest",
21
+ "crates/aitp-handshake",
22
+ "crates/aitp-tct",
23
+ "crates/aitp-delegation",
24
+ "crates/aitp-session-bundle",
25
+ "crates/aitp-transport-http",
26
+ "crates/aitp",
27
+ "crates/aitp-conformance",
28
+ "crates/aitp-rs-adapter",
29
+ "examples/two-agents",
30
+ "tools/mint-signed-examples",
31
+ "tools/mint-conformance-fixtures",
32
+ ]
33
+
34
+ [workspace.package]
35
+ version = "0.2.0"
36
+ edition = "2021"
37
+ rust-version = "1.88"
38
+ license = "MIT OR Apache-2.0"
39
+ repository = "https://github.com/agentidentitytrustprotocol/aitp-rs"
40
+ homepage = "https://github.com/agentidentitytrustprotocol/aitp-rs"
41
+ authors = ["AITP contributors"]
42
+ keywords = ["aitp", "agent", "trust", "identity", "ed25519"]
43
+ categories = ["cryptography", "authentication"]
44
+
45
+ [workspace.dependencies]
46
+ # Pinned core deps. Every crate references these via { workspace = true }
47
+ # so the workspace has exactly one version of each.
48
+ serde = { version = "1.0", features = ["derive"] }
49
+ serde_json = { version = "1.0", features = ["preserve_order"] }
50
+ serde_jcs = "0.2"
51
+ thiserror = "1.0"
52
+ ed25519-dalek = { version = "2.1", features = ["rand_core"] }
53
+ # P-256 ECDSA — RFC-AITP-0001 §5.4.3 / §5.5.2 wire format for the
54
+ # `p256` algorithm tag. `ecdsa` enables both verifying and signing
55
+ # (the latter is used by `AitpSigningKey::P256` once an agent picks
56
+ # the P-256 suite). `arithmetic` is required to derive the public
57
+ # point from a freshly-generated scalar.
58
+ p256 = { version = "0.13", default-features = false, features = ["ecdsa", "std", "arithmetic"] }
59
+ base64ct = { version = "1.6", features = ["std"] }
60
+ secrecy = "0.8"
61
+ uuid = { version = "1.7", features = ["v4", "serde"] }
62
+ sha2 = "0.10"
63
+ url = { version = "2.5", features = ["serde"] }
64
+ chrono = { version = "0.4", default-features = false, features = ["std", "serde", "clock"] }
65
+ rand = "0.8"
66
+
67
+ # HTTP transport (feature-gated, only used by aitp-transport-http)
68
+ reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
69
+ axum = "0.7"
70
+ tokio = { version = "1.36", features = ["rt-multi-thread", "macros"] }
71
+ tower = { version = "0.5", default-features = false }
72
+
73
+ # TLS — used by aitp-transport-http for SPKI cert pinning. The `ring`
74
+ # feature gives access to `rustls::crypto::ring::default_provider()` as a
75
+ # fallback when no CryptoProvider has been installed yet (e.g. callers
76
+ # building a pinned client config before any reqwest call has had a
77
+ # chance to install one). reqwest's rustls-tls feature installs a
78
+ # provider on first use; the fallback only fires before that.
79
+ rustls = { version = "0.23", default-features = false, features = ["std", "ring"] }
80
+ rustls-pki-types = "1.10"
81
+ # X.509 parser for extracting SubjectPublicKeyInfo bytes when pinning.
82
+ x509-parser = "0.17"
83
+
84
+ # OIDC (used by aitp-handshake and aitp-transport-http)
85
+ jsonwebtoken = "9.2"
86
+
87
+ # Non-poisoning Mutex for HTTP server state. parking_lot::Mutex never enters
88
+ # a poisoned state on a panic in a locked section — std::sync::Mutex would,
89
+ # and an unwrap on the resulting PoisonError hangs every subsequent request.
90
+ parking_lot = "0.12"
91
+
92
+ # Structured logging. Library crates emit spans + events; binaries (or
93
+ # downstream applications) install a subscriber. Default-features-off keeps
94
+ # the dep lean for library consumers that don't subscribe.
95
+ tracing = { version = "0.1", default-features = false, features = ["std", "attributes"] }
96
+ tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt", "env-filter"] }
97
+
98
+ # CLI (used by aitp-conformance)
99
+ clap = { version = "4.5", features = ["derive"] }
100
+
101
+ # Test deps
102
+ proptest = "1.4"
103
+ insta = { version = "1.36", features = ["json"] }
104
+ hex = "0.4"
105
+ # JSON Schema validator — used in tests/schema.rs to catch wire-type drift
106
+ # from the AITP JSON Schemas. Test-only; do NOT take a runtime dependency.
107
+ boon = "0.6"
108
+
109
+ [profile.release]
110
+ lto = "thin"
111
+ codegen-units = 1
112
+ strip = true
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.4
2
+ Name: aitp-sdk
3
+ Version: 0.2.0
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: Implementation :: CPython
6
+ Requires-Dist: pytest ; extra == 'dev'
7
+ Requires-Dist: httpx ; extra == 'dev'
8
+ Requires-Dist: pyjwt[crypto]>=2.8 ; extra == 'dev'
9
+ Requires-Dist: cryptography>=41 ; extra == 'dev'
10
+ Provides-Extra: dev
11
+ Summary: Agent Identity Trust Protocol — Python SDK
12
+ Requires-Python: >=3.9
@@ -0,0 +1,221 @@
1
+ # Type stubs for the `aitp` Python SDK (`bindings/aitp-py`).
2
+ #
3
+ # Hand-maintained because the underlying extension is built by PyO3 / maturin
4
+ # and does not auto-generate stubs. Edit when the binding's public surface
5
+ # changes; the symmetry oracle is the auto-generated `bindings/aitp-node/
6
+ # index.d.ts` — every type here SHOULD have a camelCase counterpart there
7
+ # (and vice versa), per CLAUDE.md's binding-symmetry rule.
8
+
9
+ from typing import Callable, Literal, Optional
10
+
11
+ # ── Core handshake surface ──────────────────────────────────────────────
12
+
13
+ class TctIdentity:
14
+ """Verified peer identity carried by a TCT."""
15
+
16
+ peer_aid: str
17
+ grants: list[str]
18
+ expires_at: int # unix seconds
19
+ jti: str # UUID string
20
+
21
+ class TctStore:
22
+ """Bounded in-memory cache of successful TCT verifications, keyed by the
23
+ SHA-256 of the exact TCT envelope bytes. Lets a high-throughput verifier
24
+ skip the signature check when it re-sees a byte-identical, still-valid TCT.
25
+ Cheap policy checks (expiry, audience, grant) still run on every hit."""
26
+
27
+ def __init__(self, max_entries: int) -> None: ...
28
+ def len(self) -> int: ...
29
+ def clear(self) -> None: ...
30
+
31
+ class DelegationVerified:
32
+ """Verified delegation token (RFC-AITP-0006)."""
33
+
34
+ delegator: str
35
+ delegatee: str
36
+ issued_by: str
37
+ grants: list[str]
38
+ expires_at: int
39
+ cnf: str # base64url Ed25519 / P-256 pubkey
40
+
41
+ class InitiatorSession:
42
+ """Outbound handshake session. Construct via `AitpAgent.new_session`."""
43
+
44
+ def build_hello(
45
+ self,
46
+ peer_manifest_json: str,
47
+ requested_grants: list[str],
48
+ oidc_mint_jwt: Optional[Callable[[str], str]] = ...,
49
+ ) -> str: ...
50
+ def process_hello_ack(self, hello_ack_json: str, session_id: str) -> str: ...
51
+ def complete(self, commit_ack_json: str) -> str: ...
52
+
53
+ class ResponderSession:
54
+ """Inbound handshake session. Construct via `AitpAgent.new_responder`."""
55
+
56
+ def process_hello(
57
+ self,
58
+ hello_json: str,
59
+ oidc_mint_jwt: Optional[Callable[[str], str]] = ...,
60
+ ) -> tuple[str, str]: ...
61
+ def process_commit(self, commit_json: str) -> tuple[str, str]: ...
62
+
63
+ # ── OIDC identity (RFC-AITP-0002) ───────────────────────────────────────
64
+
65
+ class JwksProvider:
66
+ """In-memory issuer URL → list of JWK dicts. The SDK does no HTTP;
67
+ callers fetch the JWKS themselves and hand the parsed dicts in."""
68
+
69
+ def __init__(self, keys: Optional[dict[str, list[dict]]] = ...) -> None: ...
70
+ def upsert(self, issuer: str, keys: list[dict]) -> None: ...
71
+ def remove(self, issuer: str) -> None: ...
72
+ def issuers(self) -> list[str]: ...
73
+
74
+ # ── Agent ───────────────────────────────────────────────────────────────
75
+
76
+ class AitpAgent:
77
+ """An AITP agent: a signing key + (once built) its published Manifest."""
78
+
79
+ @property
80
+ def aid(self) -> str: ...
81
+ @staticmethod
82
+ def generate(suite: Literal["ed25519", "p256"] = "ed25519") -> "AitpAgent": ...
83
+ @staticmethod
84
+ def from_seed(
85
+ seed: bytes, suite: Literal["ed25519", "p256"] = "ed25519"
86
+ ) -> "AitpAgent": ...
87
+ def build_manifest(
88
+ self,
89
+ display_name: str,
90
+ handshake_endpoint: str,
91
+ offered_caps: list[str],
92
+ required_caps: Optional[list[str]] = ...,
93
+ ttl_secs: Optional[int] = ...,
94
+ identity_type: Literal["pinned_key", "oidc"] = "pinned_key",
95
+ oidc_issuer: Optional[str] = ...,
96
+ oidc_subject: Optional[str] = ...,
97
+ accepted_trust_anchors: Optional[list[str]] = ...,
98
+ ) -> str: ...
99
+ def new_session(
100
+ self,
101
+ jwks: Optional[JwksProvider] = ...,
102
+ trust_anchors: Optional[list[str]] = ...,
103
+ ) -> InitiatorSession: ...
104
+ def new_responder(
105
+ self,
106
+ jwks: Optional[JwksProvider] = ...,
107
+ trust_anchors: Optional[list[str]] = ...,
108
+ ) -> ResponderSession: ...
109
+ def verify_tct(
110
+ self,
111
+ tct_json: str,
112
+ required_grant: str,
113
+ expected_audience: Optional[str] = ...,
114
+ ) -> TctIdentity: ...
115
+ def verify_tct_cached(
116
+ self,
117
+ tct_json: str,
118
+ required_grant: str,
119
+ store: TctStore,
120
+ expected_audience: Optional[str] = ...,
121
+ ) -> TctIdentity: ...
122
+ def build_delegation(
123
+ self,
124
+ held_tct_envelope_json: str,
125
+ delegatee_aid: str,
126
+ delegatee_pubkey_b64u: str,
127
+ scope: list[str],
128
+ ttl_secs: Optional[int] = ...,
129
+ ) -> str: ...
130
+ def issue_tct_for_delegatee(
131
+ self,
132
+ verified: DelegationVerified,
133
+ ttl_secs: Optional[int] = ...,
134
+ ) -> str: ...
135
+ def sign_revocation_list(
136
+ self,
137
+ entries: list[dict],
138
+ expires_in_secs: Optional[int] = ...,
139
+ ) -> str: ...
140
+ # ── experimental-renewal (Cargo feature) ────────────────────────────
141
+ def build_renewal_request(self, current_tct_envelope_json: str) -> str:
142
+ """Holder side. Gated by `experimental-renewal` Cargo feature —
143
+ absent when the wheel is built without it."""
144
+ ...
145
+ def process_renewal_request(
146
+ self,
147
+ request_payload_json: str,
148
+ manifest_exp_unix_secs: int,
149
+ new_ttl_secs: int,
150
+ ) -> str:
151
+ """Issuer side. Gated by `experimental-renewal`."""
152
+ ...
153
+
154
+ # ── Free functions ──────────────────────────────────────────────────────
155
+
156
+ def verify_delegation(
157
+ envelope_json: str, verifier_aid: str
158
+ ) -> DelegationVerified:
159
+ """Verify a delegation envelope under strict AITP v0.1 (RFC-AITP-0006
160
+ single-hop). A token carrying a non-empty `chain` (draft RFC-AITP-0011
161
+ multi-hop) is rejected with `DELEGATION_MULTIHOP_NOT_SUPPORTED`. To opt
162
+ into multi-hop, build with the `experimental-multihop-delegation`
163
+ feature and use `verify_delegation_experimental_multihop`."""
164
+ ...
165
+
166
+ def verify_delegation_experimental_multihop(
167
+ envelope_json: str, verifier_aid: str, max_hops: int = 3
168
+ ) -> DelegationVerified:
169
+ """Verify a delegation envelope allowing draft RFC-AITP-0011 multi-hop
170
+ chains up to `max_hops` total hops (`chain.len() + 1`). NOT part of AITP
171
+ v0.1; only present when built with the `experimental-multihop-delegation`
172
+ Cargo feature. `max_hops=0` reverts to strict v0.1."""
173
+ ...
174
+ def verify_manifest_json(manifest_envelope_json: str) -> None:
175
+ """Verify a `ManifestEnvelope` JSON. Raises on failure."""
176
+ ...
177
+
178
+ def compute_aid_jkt(aid: str) -> str:
179
+ """RFC 7638 JWK thumbprint of the pubkey embedded in an AID — the
180
+ value to place in an OIDC JWT's `cnf.jkt` claim (RFC-AITP-0002
181
+ §2.2.1). Supports both Ed25519 and P-256 AIDs."""
182
+ ...
183
+
184
+ # ── experimental-bundle (Cargo feature) ─────────────────────────────────
185
+
186
+ class SessionBundleBuilder:
187
+ """RFC-AITP-0010 Session Trust Bundle builder. Gated by the
188
+ `experimental-bundle` Cargo feature."""
189
+
190
+ def __init__(self, coordinator: AitpAgent) -> None: ...
191
+ def session_id(self, uuid_str: str) -> "SessionBundleBuilder": ...
192
+ def issued_at(self, unix_secs: int) -> "SessionBundleBuilder": ...
193
+ def participant(
194
+ self, aid: str, tct_envelope_json: str
195
+ ) -> "SessionBundleBuilder": ...
196
+ def build(self) -> str: ...
197
+
198
+ def verify_session_bundle(
199
+ bundle_envelope_json: str,
200
+ verifier_aid: str,
201
+ now_unix_secs: Optional[int] = ...,
202
+ revocation_check: Optional[Callable[[str], bool]] = ...,
203
+ ) -> dict:
204
+ """Returns `{"kind": "clear"|"degraded", "active_aids": [...],
205
+ "dropped_aids": [...]}`. Gated by `experimental-bundle`."""
206
+ ...
207
+
208
+ # ── experimental-pinning (Cargo feature) ────────────────────────────────
209
+
210
+ def compute_spki_hash(cert_der: bytes) -> bytes:
211
+ """SHA-256 over the leaf cert's SubjectPublicKeyInfo. Returns 32 bytes.
212
+ Gated by `experimental-pinning`."""
213
+ ...
214
+
215
+ class SpkiPinVerifier:
216
+ """Holds a list of 32-byte SPKI pins. Gated by `experimental-pinning`."""
217
+
218
+ def __init__(self, pins: list[bytes]) -> None: ...
219
+ def is_pinned(self, cert_der: bytes) -> bool: ...
220
+ @property
221
+ def len(self) -> int: ...