slim-bindings 0.7.1__cp313-cp313-win_amd64.whl
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.
- slim_bindings/__init__.py +47 -0
- slim_bindings/_slim_bindings.cp313-win_amd64.pyd +0 -0
- slim_bindings/_slim_bindings.pyi +651 -0
- slim_bindings/errors.py +52 -0
- slim_bindings/py.typed +0 -0
- slim_bindings/session.py +178 -0
- slim_bindings/slim.py +325 -0
- slim_bindings/version.py +38 -0
- slim_bindings-0.7.1.dist-info/METADATA +367 -0
- slim_bindings-0.7.1.dist-info/RECORD +11 -0
- slim_bindings-0.7.1.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Copyright AGNTCY Contributors (https://github.com/agntcy)
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
from slim_bindings._slim_bindings import (
|
|
5
|
+
Algorithm,
|
|
6
|
+
App,
|
|
7
|
+
CompletionHandle,
|
|
8
|
+
IdentityProvider,
|
|
9
|
+
IdentityVerifier,
|
|
10
|
+
Key,
|
|
11
|
+
KeyData,
|
|
12
|
+
KeyFormat,
|
|
13
|
+
MessageContext,
|
|
14
|
+
Name,
|
|
15
|
+
SessionConfiguration,
|
|
16
|
+
SessionContext,
|
|
17
|
+
SessionType,
|
|
18
|
+
init_tracing,
|
|
19
|
+
)
|
|
20
|
+
from slim_bindings.errors import SLIMTimeoutError
|
|
21
|
+
from slim_bindings.session import Session
|
|
22
|
+
from slim_bindings.slim import Slim
|
|
23
|
+
from slim_bindings.version import get_build_info, get_build_profile, get_version
|
|
24
|
+
|
|
25
|
+
# High-level public API - only expose the main interface and supporting types
|
|
26
|
+
__all__ = [
|
|
27
|
+
"get_build_info",
|
|
28
|
+
"get_build_profile",
|
|
29
|
+
"get_version",
|
|
30
|
+
"init_tracing",
|
|
31
|
+
"App",
|
|
32
|
+
"Algorithm",
|
|
33
|
+
"IdentityProvider",
|
|
34
|
+
"IdentityVerifier",
|
|
35
|
+
"Key",
|
|
36
|
+
"KeyData",
|
|
37
|
+
"KeyFormat",
|
|
38
|
+
"MessageContext",
|
|
39
|
+
"Name",
|
|
40
|
+
"Session",
|
|
41
|
+
"SessionConfiguration",
|
|
42
|
+
"SessionContext",
|
|
43
|
+
"SessionType",
|
|
44
|
+
"CompletionHandle",
|
|
45
|
+
"SLIMTimeoutError",
|
|
46
|
+
"Slim",
|
|
47
|
+
]
|
|
Binary file
|
|
@@ -0,0 +1,651 @@
|
|
|
1
|
+
# This file is automatically generated by pyo3_stub_gen
|
|
2
|
+
# ruff: noqa: E501, F401
|
|
3
|
+
|
|
4
|
+
import builtins
|
|
5
|
+
import collections.abc
|
|
6
|
+
import datetime
|
|
7
|
+
import typing
|
|
8
|
+
from enum import Enum
|
|
9
|
+
|
|
10
|
+
class App:
|
|
11
|
+
@property
|
|
12
|
+
def id(self) -> builtins.int: ...
|
|
13
|
+
@property
|
|
14
|
+
def name(self) -> Name: ...
|
|
15
|
+
def __new__(cls, name:Name, provider:IdentityProvider, verifier:IdentityVerifier, local_service:builtins.bool) -> App: ...
|
|
16
|
+
def create_session(self, destination:Name, config:SessionConfiguration) -> collections.abc.Awaitable[tuple[SessionContext, CompletionHandle]]: ...
|
|
17
|
+
def listen_for_session(self, timeout:typing.Optional[datetime.timedelta]=None) -> collections.abc.Awaitable[SessionContext]: ...
|
|
18
|
+
def run_server(self, config:dict) -> collections.abc.Awaitable: ...
|
|
19
|
+
def stop_server(self, endpoint:builtins.str) -> collections.abc.Awaitable: ...
|
|
20
|
+
def connect(self, config:dict) -> collections.abc.Awaitable: ...
|
|
21
|
+
def disconnect(self, conn:builtins.int) -> collections.abc.Awaitable: ...
|
|
22
|
+
def subscribe(self, name:Name, conn:typing.Optional[builtins.int]=None) -> collections.abc.Awaitable: ...
|
|
23
|
+
def unsubscribe(self, name:Name, conn:typing.Optional[builtins.int]=None) -> collections.abc.Awaitable: ...
|
|
24
|
+
def set_route(self, name:Name, conn:builtins.int) -> collections.abc.Awaitable: ...
|
|
25
|
+
def remove_route(self, name:Name, conn:builtins.int) -> collections.abc.Awaitable: ...
|
|
26
|
+
def delete_session(self, session_context:SessionContext) -> collections.abc.Awaitable[CompletionHandle]: ...
|
|
27
|
+
|
|
28
|
+
class CompletionHandle:
|
|
29
|
+
r"""
|
|
30
|
+
Handle for awaiting completion of asynchronous operations.
|
|
31
|
+
This class wraps a `CompletionHandle` future, allowing Python code
|
|
32
|
+
to await the completion of operations such as:
|
|
33
|
+
- Message delivery (publish)
|
|
34
|
+
- Session initialization (create_session)
|
|
35
|
+
- Participant invitation (invite)
|
|
36
|
+
- Participant removal (remove)
|
|
37
|
+
|
|
38
|
+
# Examples
|
|
39
|
+
````python
|
|
40
|
+
...
|
|
41
|
+
# This will make sure the message is successfully handled to the session
|
|
42
|
+
res_pub = await session_context.publish(msg)
|
|
43
|
+
# This will make sure the message was successfully delivered to the peer(s)
|
|
44
|
+
ack = await res_pub
|
|
45
|
+
print("Operation completed:", ack)
|
|
46
|
+
...
|
|
47
|
+
```
|
|
48
|
+
"""
|
|
49
|
+
def __await__(self) -> collections.abc.Generator: ...
|
|
50
|
+
|
|
51
|
+
class IdentityProvider:
|
|
52
|
+
r"""
|
|
53
|
+
Python-facing identity provider definitions.
|
|
54
|
+
|
|
55
|
+
Variants:
|
|
56
|
+
* StaticJwt { path }: Load a token from a file (cached, static).
|
|
57
|
+
* Jwt { private_key, duration, issuer?, audience?, subject? }:
|
|
58
|
+
Dynamically sign tokens using provided private key with optional
|
|
59
|
+
standard JWT claims (iss, aud, sub) and a token validity duration.
|
|
60
|
+
* SharedSecret { identity, shared_secret }:
|
|
61
|
+
Symmetric token provider using a shared secret. Used mainly for testing.
|
|
62
|
+
* Spire { socket_path=None, target_spiffe_id=None, jwt_audiences=None }:
|
|
63
|
+
SPIRE-based provider retrieving SPIFFE JWT SVIDs (non-Windows only; requires SPIRE agent socket).
|
|
64
|
+
|
|
65
|
+
Examples (Python):
|
|
66
|
+
|
|
67
|
+
Static (pre-issued) JWT token loaded from a file:
|
|
68
|
+
```python
|
|
69
|
+
from slim_bindings import IdentityProvider
|
|
70
|
+
|
|
71
|
+
provider = IdentityProvider.StaticJwt(path="service.token")
|
|
72
|
+
# 'provider.get_token()' (internally) will manage reloading of the file if it changes.
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Dynamically signed JWT using a private key (claims + duration):
|
|
76
|
+
```python
|
|
77
|
+
from slim_bindings import (
|
|
78
|
+
IdentityProvider, Key, Algorithm, KeyFormat, KeyData
|
|
79
|
+
)
|
|
80
|
+
import datetime
|
|
81
|
+
|
|
82
|
+
signing_key = Key(
|
|
83
|
+
algorithm=Algorithm.RS256,
|
|
84
|
+
format=KeyFormat.Pem,
|
|
85
|
+
key=KeyData.File("private_key.pem"),
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
provider = IdentityProvider.Jwt(
|
|
89
|
+
private_key=signing_key,
|
|
90
|
+
duration=datetime.timedelta(minutes=30),
|
|
91
|
+
issuer="my-issuer",
|
|
92
|
+
audience=["downstream-svc"],
|
|
93
|
+
subject="svc-a",
|
|
94
|
+
)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Shared secret token provider for tests / local development:
|
|
98
|
+
```python
|
|
99
|
+
from slim_bindings import IdentityProvider
|
|
100
|
+
|
|
101
|
+
provider = IdentityProvider.SharedSecret(
|
|
102
|
+
identity="svc-a",
|
|
103
|
+
shared_secret="not-for-production",
|
|
104
|
+
)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
End-to-end example pairing with a verifier:
|
|
108
|
+
```python
|
|
109
|
+
# For a simple shared-secret flow:
|
|
110
|
+
from slim_bindings import IdentityProvider, IdentityVerifier
|
|
111
|
+
|
|
112
|
+
provider = IdentityProvider.SharedSecret(identity="svc-a", shared_secret="dev-secret")
|
|
113
|
+
verifier = IdentityVerifier.SharedSecret(identity="svc-a", shared_secret="dev-secret")
|
|
114
|
+
|
|
115
|
+
# Pass both into Slim(local_name, provider, verifier)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Jwt variant quick start (full):
|
|
119
|
+
```python
|
|
120
|
+
import datetime
|
|
121
|
+
from slim_bindings import (
|
|
122
|
+
IdentityProvider, IdentityVerifier,
|
|
123
|
+
Key, Algorithm, KeyFormat, KeyData
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
key = Key(Algorithm.RS256, KeyFormat.Pem, KeyData.File("private_key.pem"))
|
|
127
|
+
provider = IdentityProvider.Jwt(
|
|
128
|
+
private_key=key,
|
|
129
|
+
duration=datetime.timedelta(hours=1),
|
|
130
|
+
issuer="my-issuer",
|
|
131
|
+
audience=["svc-b"],
|
|
132
|
+
subject="svc-a"
|
|
133
|
+
)
|
|
134
|
+
# Verifier would normally use the corresponding public key (IdentityVerifier.Jwt).
|
|
135
|
+
```
|
|
136
|
+
"""
|
|
137
|
+
class StaticJwt(IdentityProvider):
|
|
138
|
+
__match_args__ = ("path",)
|
|
139
|
+
@property
|
|
140
|
+
def path(self) -> builtins.str: ...
|
|
141
|
+
def __new__(cls, path:builtins.str) -> IdentityProvider.StaticJwt: ...
|
|
142
|
+
|
|
143
|
+
class Jwt(IdentityProvider):
|
|
144
|
+
__match_args__ = ("private_key", "duration", "issuer", "audience", "subject",)
|
|
145
|
+
@property
|
|
146
|
+
def private_key(self) -> Key: ...
|
|
147
|
+
@property
|
|
148
|
+
def duration(self) -> datetime.timedelta: ...
|
|
149
|
+
@property
|
|
150
|
+
def issuer(self) -> typing.Optional[builtins.str]: ...
|
|
151
|
+
@property
|
|
152
|
+
def audience(self) -> typing.Optional[builtins.list[builtins.str]]: ...
|
|
153
|
+
@property
|
|
154
|
+
def subject(self) -> typing.Optional[builtins.str]: ...
|
|
155
|
+
def __new__(cls, private_key:Key, duration:datetime.timedelta, issuer:typing.Optional[builtins.str]=None, audience:typing.Optional[typing.Sequence[builtins.str]]=None, subject:typing.Optional[builtins.str]=None) -> IdentityProvider.Jwt: ...
|
|
156
|
+
|
|
157
|
+
class SharedSecret(IdentityProvider):
|
|
158
|
+
__match_args__ = ("identity", "shared_secret",)
|
|
159
|
+
@property
|
|
160
|
+
def identity(self) -> builtins.str: ...
|
|
161
|
+
@property
|
|
162
|
+
def shared_secret(self) -> builtins.str: ...
|
|
163
|
+
def __new__(cls, identity:builtins.str, shared_secret:builtins.str) -> IdentityProvider.SharedSecret: ...
|
|
164
|
+
|
|
165
|
+
class Spire(IdentityProvider):
|
|
166
|
+
__match_args__ = ("socket_path", "target_spiffe_id", "jwt_audiences",)
|
|
167
|
+
@property
|
|
168
|
+
def socket_path(self) -> typing.Optional[builtins.str]: ...
|
|
169
|
+
@property
|
|
170
|
+
def target_spiffe_id(self) -> typing.Optional[builtins.str]: ...
|
|
171
|
+
@property
|
|
172
|
+
def jwt_audiences(self) -> typing.Optional[builtins.list[builtins.str]]: ...
|
|
173
|
+
def __new__(cls, socket_path:typing.Optional[builtins.str]=None, target_spiffe_id:typing.Optional[builtins.str]=None, jwt_audiences:typing.Optional[typing.Sequence[builtins.str]]=None) -> IdentityProvider.Spire: ...
|
|
174
|
+
|
|
175
|
+
...
|
|
176
|
+
|
|
177
|
+
class IdentityVerifier:
|
|
178
|
+
r"""
|
|
179
|
+
Python-facing identity verifier definitions.
|
|
180
|
+
|
|
181
|
+
Variants:
|
|
182
|
+
* Jwt { public_key?, autoresolve, issuer?, audience?, subject?, require_* }:
|
|
183
|
+
Verifies tokens using a public key or via JWKS auto-resolution.
|
|
184
|
+
`require_iss`, `require_aud`, `require_sub` toggle mandatory presence
|
|
185
|
+
of the respective claims. `autoresolve=True` enables JWKS retrieval
|
|
186
|
+
(public_key must be omitted in that case).
|
|
187
|
+
* SharedSecret { identity, shared_secret }:
|
|
188
|
+
Verifies tokens generated with the same shared secret.
|
|
189
|
+
* Spire { socket_path=None, target_spiffe_id=None, jwt_audiences=None }:
|
|
190
|
+
SPIRE-based JWT SVID verifier (non-Windows only). Uses SPIRE Workload API
|
|
191
|
+
bundles to validate SPIFFE JWT SVIDs. Requires an initialized SPIRE
|
|
192
|
+
identity manager. (Underlying AuthVerifier support must exist.)
|
|
193
|
+
|
|
194
|
+
JWKS Auto-Resolve:
|
|
195
|
+
When `autoresolve=True`, the verifier will attempt to resolve keys
|
|
196
|
+
dynamically (e.g. from a JWKS endpoint) if supported by the underlying
|
|
197
|
+
implementation.
|
|
198
|
+
|
|
199
|
+
Safety:
|
|
200
|
+
A direct panic occurs if neither `public_key` nor `autoresolve=True`
|
|
201
|
+
is provided for the Jwt variant (invalid configuration).
|
|
202
|
+
|
|
203
|
+
Autoresolve key selection (concise algorithm):
|
|
204
|
+
1. If a static JWKS was injected, use it directly.
|
|
205
|
+
2. Else if a cached JWKS for the issuer exists and is within TTL, use it.
|
|
206
|
+
3. Else discover JWKS:
|
|
207
|
+
- Try {issuer}/.well-known/openid-configuration for "jwks_uri"
|
|
208
|
+
- Fallback to {issuer}/.well-known/jwks.json
|
|
209
|
+
4. Fetch & cache the JWKS (default TTL ~1h unless overridden).
|
|
210
|
+
5. If JWT header has 'kid', pick the matching key ID; otherwise choose the
|
|
211
|
+
first key whose algorithm matches the token header's alg.
|
|
212
|
+
6. Convert JWK -> DecodingKey and verify signature; then enforce required
|
|
213
|
+
claims (iss/aud/sub) per the require_* flags.
|
|
214
|
+
|
|
215
|
+
# Examples (Python)
|
|
216
|
+
|
|
217
|
+
Basic JWT verification with explicit public key:
|
|
218
|
+
```python
|
|
219
|
+
pub_key = Key(
|
|
220
|
+
Algorithm.RS256,
|
|
221
|
+
KeyFormat.Pem,
|
|
222
|
+
KeyData.File("public_key.pem"),
|
|
223
|
+
)
|
|
224
|
+
verifier = IdentityVerifier.Jwt(
|
|
225
|
+
public_key=pub_key,
|
|
226
|
+
autoresolve=False,
|
|
227
|
+
issuer="my-issuer",
|
|
228
|
+
audience=["service-b"],
|
|
229
|
+
subject="service-a",
|
|
230
|
+
require_iss=True,
|
|
231
|
+
require_aud=True,
|
|
232
|
+
require_sub=True,
|
|
233
|
+
)
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Auto-resolving JWKS (no public key provided):
|
|
237
|
+
```python
|
|
238
|
+
# The underlying implementation must know how / where to resolve JWKS.
|
|
239
|
+
verifier = IdentityVerifier.Jwt(
|
|
240
|
+
public_key=None,
|
|
241
|
+
autoresolve=True,
|
|
242
|
+
issuer="https://auth.example.com",
|
|
243
|
+
audience=["svc-cluster"],
|
|
244
|
+
subject=None,
|
|
245
|
+
require_iss=True,
|
|
246
|
+
require_aud=True,
|
|
247
|
+
require_sub=False,
|
|
248
|
+
)
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Shared secret verifier (symmetric):
|
|
252
|
+
```python
|
|
253
|
+
verifier = IdentityVerifier.SharedSecret(
|
|
254
|
+
identity="service-a",
|
|
255
|
+
shared_secret="super-secret-value",
|
|
256
|
+
)
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Pairing with a provider when constructing Slim:
|
|
260
|
+
```python
|
|
261
|
+
provider = IdentityProvider.SharedSecret(
|
|
262
|
+
identity="service-a",
|
|
263
|
+
shared_secret="super-secret-value",
|
|
264
|
+
)
|
|
265
|
+
slim = Slim(local_name, provider, verifier)
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Enforcing strict claims (reject tokens missing aud/sub):
|
|
269
|
+
```python
|
|
270
|
+
strict_verifier = IdentityVerifier.Jwt(
|
|
271
|
+
public_key=pub_key,
|
|
272
|
+
autoresolve=False,
|
|
273
|
+
issuer="my-issuer",
|
|
274
|
+
audience=["service-a"],
|
|
275
|
+
subject="service-a",
|
|
276
|
+
require_iss=True,
|
|
277
|
+
require_aud=True,
|
|
278
|
+
require_sub=True,
|
|
279
|
+
)
|
|
280
|
+
```
|
|
281
|
+
"""
|
|
282
|
+
class Jwt(IdentityVerifier):
|
|
283
|
+
__match_args__ = ("public_key", "autoresolve", "issuer", "audience", "subject", "require_iss", "require_aud", "require_sub",)
|
|
284
|
+
@property
|
|
285
|
+
def public_key(self) -> typing.Optional[Key]: ...
|
|
286
|
+
@property
|
|
287
|
+
def autoresolve(self) -> builtins.bool: ...
|
|
288
|
+
@property
|
|
289
|
+
def issuer(self) -> typing.Optional[builtins.str]: ...
|
|
290
|
+
@property
|
|
291
|
+
def audience(self) -> typing.Optional[builtins.list[builtins.str]]: ...
|
|
292
|
+
@property
|
|
293
|
+
def subject(self) -> typing.Optional[builtins.str]: ...
|
|
294
|
+
@property
|
|
295
|
+
def require_iss(self) -> builtins.bool: ...
|
|
296
|
+
@property
|
|
297
|
+
def require_aud(self) -> builtins.bool: ...
|
|
298
|
+
@property
|
|
299
|
+
def require_sub(self) -> builtins.bool: ...
|
|
300
|
+
def __new__(cls, public_key:typing.Optional[Key]=None, autoresolve:builtins.bool=False, issuer:typing.Optional[builtins.str]=None, audience:typing.Optional[typing.Sequence[builtins.str]]=None, subject:typing.Optional[builtins.str]=None, require_iss:builtins.bool=False, require_aud:builtins.bool=False, require_sub:builtins.bool=False) -> IdentityVerifier.Jwt: ...
|
|
301
|
+
|
|
302
|
+
class SharedSecret(IdentityVerifier):
|
|
303
|
+
__match_args__ = ("identity", "shared_secret",)
|
|
304
|
+
@property
|
|
305
|
+
def identity(self) -> builtins.str: ...
|
|
306
|
+
@property
|
|
307
|
+
def shared_secret(self) -> builtins.str: ...
|
|
308
|
+
def __new__(cls, identity:builtins.str, shared_secret:builtins.str) -> IdentityVerifier.SharedSecret: ...
|
|
309
|
+
|
|
310
|
+
class Spire(IdentityVerifier):
|
|
311
|
+
__match_args__ = ("socket_path", "target_spiffe_id", "jwt_audiences",)
|
|
312
|
+
@property
|
|
313
|
+
def socket_path(self) -> typing.Optional[builtins.str]: ...
|
|
314
|
+
@property
|
|
315
|
+
def target_spiffe_id(self) -> typing.Optional[builtins.str]: ...
|
|
316
|
+
@property
|
|
317
|
+
def jwt_audiences(self) -> typing.Optional[builtins.list[builtins.str]]: ...
|
|
318
|
+
def __new__(cls, socket_path:typing.Optional[builtins.str]=None, target_spiffe_id:typing.Optional[builtins.str]=None, jwt_audiences:typing.Optional[typing.Sequence[builtins.str]]=None) -> IdentityVerifier.Spire: ...
|
|
319
|
+
|
|
320
|
+
...
|
|
321
|
+
|
|
322
|
+
class Key:
|
|
323
|
+
r"""
|
|
324
|
+
Composite key description used for signing or verification.
|
|
325
|
+
|
|
326
|
+
Fields:
|
|
327
|
+
* algorithm: `Algorithm` to apply
|
|
328
|
+
* format: `KeyFormat` describing encoding
|
|
329
|
+
* key: `KeyData` where the actual bytes originate
|
|
330
|
+
"""
|
|
331
|
+
@property
|
|
332
|
+
def algorithm(self) -> Algorithm: ...
|
|
333
|
+
@algorithm.setter
|
|
334
|
+
def algorithm(self, value: Algorithm) -> None: ...
|
|
335
|
+
@property
|
|
336
|
+
def format(self) -> KeyFormat: ...
|
|
337
|
+
@format.setter
|
|
338
|
+
def format(self, value: KeyFormat) -> None: ...
|
|
339
|
+
@property
|
|
340
|
+
def key(self) -> KeyData: ...
|
|
341
|
+
@key.setter
|
|
342
|
+
def key(self, value: KeyData) -> None: ...
|
|
343
|
+
def __new__(cls, algorithm:Algorithm, format:KeyFormat, key:KeyData) -> Key:
|
|
344
|
+
r"""
|
|
345
|
+
Construct a new `Key`.
|
|
346
|
+
|
|
347
|
+
Args:
|
|
348
|
+
algorithm: Algorithm used for signing / verification.
|
|
349
|
+
format: Representation format (PEM/JWK/JWKS).
|
|
350
|
+
key: Source (file vs inline content).
|
|
351
|
+
"""
|
|
352
|
+
|
|
353
|
+
class KeyData:
|
|
354
|
+
r"""
|
|
355
|
+
Key material origin.
|
|
356
|
+
|
|
357
|
+
Either a path on disk (`File`) or inline string content (`Content`)
|
|
358
|
+
containing the encoded key. The interpretation depends on the
|
|
359
|
+
accompanying `KeyFormat`.
|
|
360
|
+
"""
|
|
361
|
+
class File(KeyData):
|
|
362
|
+
__match_args__ = ("path",)
|
|
363
|
+
@property
|
|
364
|
+
def path(self) -> builtins.str: ...
|
|
365
|
+
def __new__(cls, path:builtins.str) -> KeyData.File: ...
|
|
366
|
+
|
|
367
|
+
class Content(KeyData):
|
|
368
|
+
__match_args__ = ("content",)
|
|
369
|
+
@property
|
|
370
|
+
def content(self) -> builtins.str: ...
|
|
371
|
+
def __new__(cls, content:builtins.str) -> KeyData.Content: ...
|
|
372
|
+
|
|
373
|
+
...
|
|
374
|
+
|
|
375
|
+
class MessageContext:
|
|
376
|
+
r"""
|
|
377
|
+
Python-visible context accompanying every received message.
|
|
378
|
+
|
|
379
|
+
Provides routing and descriptive metadata needed for replying,
|
|
380
|
+
auditing, and instrumentation.
|
|
381
|
+
|
|
382
|
+
This type implements `From<MessageContext>` and `Into<MessageContext>`
|
|
383
|
+
for seamless conversion with the common core message context type.
|
|
384
|
+
|
|
385
|
+
Fields:
|
|
386
|
+
* `source_name`: Fully-qualified sender identity.
|
|
387
|
+
* `destination_name`: Fully-qualified destination identity (may be an empty placeholder
|
|
388
|
+
when not explicitly set, e.g. broadcast/group scenarios).
|
|
389
|
+
* `payload_type`: Logical/semantic type (defaults to "msg" if unspecified).
|
|
390
|
+
* `metadata`: Arbitrary key/value pairs supplied by the sender (e.g. tracing IDs).
|
|
391
|
+
* `input_connection`: Numeric identifier of the inbound connection carrying the message.
|
|
392
|
+
"""
|
|
393
|
+
@property
|
|
394
|
+
def source_name(self) -> Name: ...
|
|
395
|
+
@property
|
|
396
|
+
def destination_name(self) -> Name: ...
|
|
397
|
+
@property
|
|
398
|
+
def payload_type(self) -> builtins.str: ...
|
|
399
|
+
@property
|
|
400
|
+
def metadata(self) -> builtins.dict[builtins.str, builtins.str]: ...
|
|
401
|
+
@property
|
|
402
|
+
def input_connection(self) -> builtins.int: ...
|
|
403
|
+
@property
|
|
404
|
+
def identity(self) -> builtins.str: ...
|
|
405
|
+
def __new__(cls) -> MessageContext:
|
|
406
|
+
r"""
|
|
407
|
+
Prevent direct construction from Python. `MessageContext` instances
|
|
408
|
+
are created internally when messages are received from the service.
|
|
409
|
+
"""
|
|
410
|
+
|
|
411
|
+
class Name:
|
|
412
|
+
r"""
|
|
413
|
+
name class
|
|
414
|
+
"""
|
|
415
|
+
@property
|
|
416
|
+
def id(self) -> builtins.int: ...
|
|
417
|
+
@id.setter
|
|
418
|
+
def id(self, value: builtins.int) -> None: ...
|
|
419
|
+
def __eq__(self, other:builtins.object) -> builtins.bool: ...
|
|
420
|
+
def __str__(self) -> builtins.str: ...
|
|
421
|
+
def __new__(cls, component0:builtins.str, component1:builtins.str, component2:builtins.str, id:typing.Optional[builtins.int]=None) -> Name: ...
|
|
422
|
+
def components(self) -> builtins.list[builtins.int]: ...
|
|
423
|
+
def components_strings(self) -> builtins.list[builtins.str]: ...
|
|
424
|
+
def equal_without_id(self, name:Name) -> builtins.bool: ...
|
|
425
|
+
def __hash__(self) -> builtins.int: ...
|
|
426
|
+
|
|
427
|
+
class SessionConfiguration:
|
|
428
|
+
r"""
|
|
429
|
+
User-facing configuration for establishing and tuning sessions.
|
|
430
|
+
|
|
431
|
+
Each variant maps to a core `SessionConfig` and defines the behavior of session-level
|
|
432
|
+
operations like message publishing, participant management, and message reception.
|
|
433
|
+
|
|
434
|
+
Common fields:
|
|
435
|
+
* `timeout`: How long we wait for an ack before trying again.
|
|
436
|
+
* `max_retries`: Number of attempts to send a message. If we run out, an error is returned.
|
|
437
|
+
* `mls_enabled`: Turn on MLS for end‑to‑end crypto.
|
|
438
|
+
* `metadata`: One-shot string key/value tags sent at session start; the other side can read them for tracing, routing, auth, etc.
|
|
439
|
+
|
|
440
|
+
Variant-specific notes:
|
|
441
|
+
* `PointToPoint`: Direct communication with a specific peer. Session operations target the peer directly.
|
|
442
|
+
* `Group`: Channel-based multicast communication. Session operations affect the entire group.
|
|
443
|
+
|
|
444
|
+
# Examples
|
|
445
|
+
|
|
446
|
+
## Python: Create different session configs
|
|
447
|
+
```python
|
|
448
|
+
from slim_bindings import SessionConfiguration, Name
|
|
449
|
+
|
|
450
|
+
# PointToPoint session - direct peer communication
|
|
451
|
+
p2p_cfg = SessionConfiguration.PointToPoint(
|
|
452
|
+
peer_name=Name("org", "namespace", "service"), # target peer
|
|
453
|
+
timeout=datetime.timedelta(seconds=2), # wait 2 seconds for an ack
|
|
454
|
+
max_retries=5, # retry up to 5 times
|
|
455
|
+
mls_enabled=True, # enable MLS
|
|
456
|
+
metadata={"trace_id": "1234abcd"} # arbitrary (string -> string) key/value pairs to send at session establishment
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
# Group session (channel-based)
|
|
460
|
+
channel = Name("org", "namespace", "channel")
|
|
461
|
+
group_cfg = SessionConfiguration.Group(
|
|
462
|
+
channel_name=channel, # group channel_name
|
|
463
|
+
max_retries=2, # retry up to 2 times
|
|
464
|
+
timeout=datetime.timedelta(seconds=2), # wait 2 seconds for an ack
|
|
465
|
+
mls_enabled=True, # enable MLS
|
|
466
|
+
metadata={"role": "publisher"} # arbitrary (string -> string) key/value pairs to send at session establishment
|
|
467
|
+
)
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
## Python: Using a config when creating a session
|
|
471
|
+
```python
|
|
472
|
+
slim = Slim(local_name, provider, verifier)
|
|
473
|
+
session = await slim.create_session(p2p_cfg)
|
|
474
|
+
print("Session ID:", session.id)
|
|
475
|
+
print("Type:", session.session_type)
|
|
476
|
+
print("Metadata:", session.metadata)
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
## Python: Updating configuration after creation
|
|
480
|
+
```python
|
|
481
|
+
# Adjust retries & metadata dynamically
|
|
482
|
+
new_cfg = SessionConfiguration.PointToPoint(
|
|
483
|
+
peer_name=Name("org", "namespace", "service"),
|
|
484
|
+
timeout=None,
|
|
485
|
+
max_retries=10,
|
|
486
|
+
mls_enabled=True,
|
|
487
|
+
metadata={"trace_id": "1234abcd", "phase": "retrying"}
|
|
488
|
+
)
|
|
489
|
+
session.set_session_config(new_cfg)
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
## Rust (internal conversion flow)
|
|
493
|
+
The enum transparently converts to and from `SessionConfig`:
|
|
494
|
+
```
|
|
495
|
+
// Example conversion (pseudo-code):
|
|
496
|
+
// let core: SessionConfig = py_cfg.clone().into();
|
|
497
|
+
// let roundtrip: SessionConfiguration = core.into();
|
|
498
|
+
// assert_eq!(py_cfg, roundtrip);
|
|
499
|
+
```
|
|
500
|
+
"""
|
|
501
|
+
@property
|
|
502
|
+
def session_type(self) -> SessionType:
|
|
503
|
+
r"""
|
|
504
|
+
Return the session type.
|
|
505
|
+
"""
|
|
506
|
+
@property
|
|
507
|
+
def metadata(self) -> builtins.dict[builtins.str, builtins.str]:
|
|
508
|
+
r"""
|
|
509
|
+
Return the metadata map (cloned).
|
|
510
|
+
"""
|
|
511
|
+
@property
|
|
512
|
+
def mls_enabled(self) -> builtins.bool:
|
|
513
|
+
r"""
|
|
514
|
+
Return whether MLS is enabled.
|
|
515
|
+
"""
|
|
516
|
+
@property
|
|
517
|
+
def timeout(self) -> typing.Optional[datetime.timedelta]:
|
|
518
|
+
r"""
|
|
519
|
+
Return the timeout duration (if any).
|
|
520
|
+
"""
|
|
521
|
+
@property
|
|
522
|
+
def max_retries(self) -> typing.Optional[builtins.int]:
|
|
523
|
+
r"""
|
|
524
|
+
Return the maximum number of retries (if any).
|
|
525
|
+
"""
|
|
526
|
+
@staticmethod
|
|
527
|
+
def PointToPoint(timeout:typing.Optional[datetime.timedelta]=None, max_retries:typing.Optional[builtins.int]=None, mls_enabled:builtins.bool=False, metadata:typing.Optional[typing.Mapping[builtins.str, builtins.str]]=None) -> SessionConfiguration:
|
|
528
|
+
r"""
|
|
529
|
+
Create a PointToPoint session configuration.
|
|
530
|
+
|
|
531
|
+
Args:
|
|
532
|
+
timeout: Optional timeout duration
|
|
533
|
+
max_retries: Optional maximum retry attempts
|
|
534
|
+
mls_enabled: Enable MLS encryption (default: false)
|
|
535
|
+
metadata: Optional metadata dictionary
|
|
536
|
+
"""
|
|
537
|
+
@staticmethod
|
|
538
|
+
def Group(timeout:typing.Optional[datetime.timedelta]=None, max_retries:typing.Optional[builtins.int]=None, mls_enabled:builtins.bool=False, metadata:typing.Optional[typing.Mapping[builtins.str, builtins.str]]=None) -> SessionConfiguration:
|
|
539
|
+
r"""
|
|
540
|
+
Create a Group session configuration.
|
|
541
|
+
|
|
542
|
+
Args:
|
|
543
|
+
timeout: Optional timeout duration
|
|
544
|
+
max_retries: Optional maximum retry attempts
|
|
545
|
+
mls_enabled: Enable MLS encryption (default: false)
|
|
546
|
+
metadata: Optional metadata dictionary
|
|
547
|
+
"""
|
|
548
|
+
|
|
549
|
+
class SessionContext:
|
|
550
|
+
r"""
|
|
551
|
+
Python-exposed session context wrapper.
|
|
552
|
+
|
|
553
|
+
A thin, cloneable handle around the underlying Rust session state that provides
|
|
554
|
+
both session metadata access and session-specific operations. All getters perform
|
|
555
|
+
a safe upgrade of the weak internal session reference, returning a Python exception
|
|
556
|
+
if the session has already been closed.
|
|
557
|
+
|
|
558
|
+
Properties (getters exposed to Python):
|
|
559
|
+
- id -> int: Unique numeric identifier of the session. Raises a Python
|
|
560
|
+
exception if the session has been closed.
|
|
561
|
+
- metadata -> dict[str,str]: Arbitrary key/value metadata copied from the
|
|
562
|
+
current SessionConfig. A cloned map is returned so Python can mutate
|
|
563
|
+
without racing the underlying config.
|
|
564
|
+
- session_type -> SessionType: High-level transport classification
|
|
565
|
+
(PointToPoint, Group), inferred from internal kind + destination.
|
|
566
|
+
- src -> Name: Fully qualified source identity that originated / owns
|
|
567
|
+
the session.
|
|
568
|
+
- dst -> Name: Destination name:
|
|
569
|
+
* Name of the peer for PointToPoint
|
|
570
|
+
* Name of the channel for Group
|
|
571
|
+
- session_config -> SessionConfiguration: Current effective configuration
|
|
572
|
+
converted to the Python-facing enum variant.
|
|
573
|
+
"""
|
|
574
|
+
@property
|
|
575
|
+
def id(self) -> builtins.int: ...
|
|
576
|
+
@property
|
|
577
|
+
def metadata(self) -> builtins.dict[builtins.str, builtins.str]: ...
|
|
578
|
+
@property
|
|
579
|
+
def session_type(self) -> SessionType: ...
|
|
580
|
+
@property
|
|
581
|
+
def src(self) -> Name: ...
|
|
582
|
+
@property
|
|
583
|
+
def dst(self) -> typing.Optional[Name]: ...
|
|
584
|
+
@property
|
|
585
|
+
def session_config(self) -> SessionConfiguration: ...
|
|
586
|
+
def publish(self, fanout:builtins.int, blob:typing.Sequence[builtins.int], message_ctx:typing.Optional[MessageContext]=None, name:typing.Optional[Name]=None, payload_type:typing.Optional[builtins.str]=None, metadata:typing.Optional[typing.Mapping[builtins.str, builtins.str]]=None) -> collections.abc.Awaitable[CompletionHandle]:
|
|
587
|
+
r"""
|
|
588
|
+
Publish a message through the specified session.
|
|
589
|
+
"""
|
|
590
|
+
def publish_to(self, message_ctx:MessageContext, blob:typing.Sequence[builtins.int], payload_type:typing.Optional[builtins.str]=None, metadata:typing.Optional[typing.Mapping[builtins.str, builtins.str]]=None) -> collections.abc.Awaitable[CompletionHandle]:
|
|
591
|
+
r"""
|
|
592
|
+
Publish a message as a reply to a received message through the specified session.
|
|
593
|
+
"""
|
|
594
|
+
def invite(self, name:Name) -> collections.abc.Awaitable[CompletionHandle]:
|
|
595
|
+
r"""
|
|
596
|
+
Invite a participant to the specified session (group only).
|
|
597
|
+
"""
|
|
598
|
+
def remove(self, name:Name) -> collections.abc.Awaitable[CompletionHandle]:
|
|
599
|
+
r"""
|
|
600
|
+
Remove a participant from the specified session (group only).
|
|
601
|
+
"""
|
|
602
|
+
def get_message(self, timeout:typing.Optional[datetime.timedelta]=None) -> collections.abc.Awaitable[tuple[MessageContext, bytes]]:
|
|
603
|
+
r"""
|
|
604
|
+
Get a message from the specified session.
|
|
605
|
+
"""
|
|
606
|
+
|
|
607
|
+
class Algorithm(Enum):
|
|
608
|
+
r"""
|
|
609
|
+
JWT / signature algorithms exposed to Python.
|
|
610
|
+
|
|
611
|
+
Maps 1:1 to `slim_auth::jwt::Algorithm`.
|
|
612
|
+
Provides stable integer values for stub generation / introspection.
|
|
613
|
+
"""
|
|
614
|
+
HS256 = ...
|
|
615
|
+
HS384 = ...
|
|
616
|
+
HS512 = ...
|
|
617
|
+
RS256 = ...
|
|
618
|
+
RS384 = ...
|
|
619
|
+
RS512 = ...
|
|
620
|
+
PS256 = ...
|
|
621
|
+
PS384 = ...
|
|
622
|
+
PS512 = ...
|
|
623
|
+
ES256 = ...
|
|
624
|
+
ES384 = ...
|
|
625
|
+
EdDSA = ...
|
|
626
|
+
|
|
627
|
+
class KeyFormat(Enum):
|
|
628
|
+
r"""
|
|
629
|
+
Supported key encoding formats.
|
|
630
|
+
|
|
631
|
+
Used during parsing / loading of provided key material.
|
|
632
|
+
"""
|
|
633
|
+
Pem = ...
|
|
634
|
+
Jwk = ...
|
|
635
|
+
Jwks = ...
|
|
636
|
+
|
|
637
|
+
class SessionType(Enum):
|
|
638
|
+
r"""
|
|
639
|
+
High-level session classification presented to Python.
|
|
640
|
+
"""
|
|
641
|
+
PointToPoint = ...
|
|
642
|
+
r"""
|
|
643
|
+
Point-to-point with a single, explicit destination name.
|
|
644
|
+
"""
|
|
645
|
+
Group = ...
|
|
646
|
+
r"""
|
|
647
|
+
Many-to-many distribution via a group channel_name.
|
|
648
|
+
"""
|
|
649
|
+
|
|
650
|
+
def init_tracing(config:dict) -> typing.Any: ...
|
|
651
|
+
|