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,367 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: slim-bindings
|
|
3
|
+
Version: 0.7.1
|
|
4
|
+
Classifier: Development Status :: 3 - Alpha
|
|
5
|
+
Classifier: Intended Audience :: Developers
|
|
6
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
7
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Summary: SLIM Rust bindings for Python
|
|
12
|
+
License-Expression: Apache-2.0
|
|
13
|
+
Requires-Python: >=3.10, <4.0
|
|
14
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
15
|
+
Project-URL: Repository, https://github.com/agntcy/slim
|
|
16
|
+
Project-URL: Issues, https://github.com/agntcy/slim/issues
|
|
17
|
+
Project-URL: Changelog, https://github.com/agntcy/slim/blob/main/data-plane/python/bindings/CHANGELOG.md
|
|
18
|
+
|
|
19
|
+
# SLIM Python Bindings
|
|
20
|
+
|
|
21
|
+
High-level asynchronous Python bindings for the SLIM data‑plane service (Rust core).
|
|
22
|
+
They let you embed SLIM directly into your Python application to:
|
|
23
|
+
|
|
24
|
+
- Instantiate a local SLIM service
|
|
25
|
+
- Run a server listener (start / stop a SLIM endpoint)
|
|
26
|
+
- Establish outbound client connections (`connect` / `disconnect`)
|
|
27
|
+
- Create, accept, configure, and delete sessions (Point2Point / Group)
|
|
28
|
+
- Publish / receive messages (point‑to‑point or group (channel) based)
|
|
29
|
+
- Manage routing and subscriptions (add / remove routes, subscribe / unsubscribe)
|
|
30
|
+
- Configure identity & trust (shared secret, static JWT, dynamic signing JWT, JWKS auto‑resolve, Spire)
|
|
31
|
+
- Integrate tracing / OpenTelemetry
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Supported Session Types
|
|
36
|
+
|
|
37
|
+
| Type | Description | Sticky Peer | Metadata | MLS (group security) |
|
|
38
|
+
|-------------|------------------------------------------------------------------------------------------|-------------|----------|----------------------|
|
|
39
|
+
| Point2Point | Point-to-point with a fixed destination | Yes | Yes | Yes |
|
|
40
|
+
| Group | Many-to-many via channel/topic name (channel moderator can invite/remove participants) | N/A | Yes | Yes |
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Identity & Authentication
|
|
45
|
+
|
|
46
|
+
SLIM supports pluggable identity strategies for both the provider (how a local identity token/credential is produced) and the verifier (how inbound peer credentials are validated).
|
|
47
|
+
|
|
48
|
+
### Provider Variants
|
|
49
|
+
|
|
50
|
+
| Variant | Use Case / Scenario | Notes |
|
|
51
|
+
|------------------------------------|-----------------------------------------------|-------|
|
|
52
|
+
| `IdentityProvider.SharedSecret` | HMAC-based token (shared symmetric key) | Full HMAC (nonce+timestamp, optional replay cache); validity window & clock skew; rotate by replacing secret |
|
|
53
|
+
| `IdentityProvider.StaticJwt` | Pre-issued token from file (ops managed) | Simple; no signing key in process; rotate by replacing file |
|
|
54
|
+
| `IdentityProvider.Jwt` | Dynamically signed JWT | Supports `exp`, optional `iss`, `aud[]`, `sub`; controllable `duration` |
|
|
55
|
+
| `IdentityProvider.Spire` | SPIRE / SPIFFE based workload identity | Obtains SVID/JWT via SPIRE Workload API; offloads trust & rotation |
|
|
56
|
+
|
|
57
|
+
### Verifier Variants
|
|
58
|
+
|
|
59
|
+
| Variant | Use Case / Scenario | Notes |
|
|
60
|
+
|------------------------------------|----------------------------------------------------|-------|
|
|
61
|
+
| `IdentityVerifier.SharedSecret` | HMAC verification of shared-secret tokens | Verifies MAC, nonce, timestamp; optional replay cache; supports custom claims (no iss/aud/sub) |
|
|
62
|
+
| `IdentityVerifier.Jwt` | Standard JWT / OIDC verification | Public key OR JWKS auto-resolve; optional strict claim requirements |
|
|
63
|
+
| `IdentityVerifier.Spire` | Verify SPIRE-issued identities / tokens | Uses SPIRE Workload API; matches SPIFFE IDs and audiences |
|
|
64
|
+
|
|
65
|
+
### JWT Algorithms
|
|
66
|
+
|
|
67
|
+
Supported signing / verification algorithms:
|
|
68
|
+
|
|
69
|
+
| Symmetric | RSA | PS (RSA-PSS) | EC | Other |
|
|
70
|
+
|-----------|----------|--------------|---------|--------|
|
|
71
|
+
| HS256 | RS256 | PS256 | ES256 | EdDSA |
|
|
72
|
+
| HS384 | RS384 | PS384 | ES384 | |
|
|
73
|
+
| HS512 | RS512 | PS512 | | |
|
|
74
|
+
|
|
75
|
+
(Select via `Algorithm.<Variant>` when constructing a `Key`.)
|
|
76
|
+
|
|
77
|
+
### Key Formats
|
|
78
|
+
|
|
79
|
+
| Format | Description |
|
|
80
|
+
|---------|----------------------------------------------|
|
|
81
|
+
| `KeyFormat.Pem` | PEM encoded key material (file or string) |
|
|
82
|
+
| `KeyFormat.Jwk` | Single JSON Web Key |
|
|
83
|
+
| `KeyFormat.Jwks` | JWKS (set of keys) |
|
|
84
|
+
|
|
85
|
+
Key data can be provided either by file path (`KeyData.File(path="path.pem")`) or in-memory content (`KeyData.Content(content=pem_string)`).
|
|
86
|
+
|
|
87
|
+
### Provider Examples
|
|
88
|
+
|
|
89
|
+
Dynamic signing JWT:
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
import datetime
|
|
93
|
+
from slim_bindings import IdentityProvider, Key, Algorithm, KeyFormat, KeyData
|
|
94
|
+
|
|
95
|
+
private_key = Key(Algorithm.RS256, KeyFormat.Pem, KeyData.File(path="private_key.pem"))
|
|
96
|
+
provider = IdentityProvider.Jwt(
|
|
97
|
+
private_key=private_key,
|
|
98
|
+
duration=datetime.timedelta(minutes=30),
|
|
99
|
+
issuer="my-issuer",
|
|
100
|
+
audience=["peer-service"],
|
|
101
|
+
subject="local-service",
|
|
102
|
+
)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Static pre-issued token (already on disk):
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
from slim_bindings import IdentityProvider
|
|
109
|
+
provider = IdentityProvider.StaticJwt(path="issued.jwt")
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
SPIRE provider (automatic SVID / JWT retrieval):
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
from slim_bindings import IdentityProvider
|
|
116
|
+
provider = IdentityProvider.Spire(
|
|
117
|
+
socket_path="/tmp/spire-agent/public/api.sock", # optional; default search paths if None
|
|
118
|
+
target_spiffe_id="spiffe://example.org/my-service", # optional filter
|
|
119
|
+
jwt_audiences=["peer-service"] # optional requested audiences
|
|
120
|
+
)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Verifier Examples
|
|
124
|
+
|
|
125
|
+
Strict JWT verification (public key):
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
from slim_bindings import IdentityVerifier, Key, Algorithm, KeyFormat, KeyData
|
|
129
|
+
|
|
130
|
+
pub_key = Key(Algorithm.RS256, KeyFormat.Pem, KeyData.File(path="public_key.pem"))
|
|
131
|
+
verifier = IdentityVerifier.Jwt(
|
|
132
|
+
public_key=pub_key,
|
|
133
|
+
autoresolve=False,
|
|
134
|
+
issuer="my-issuer",
|
|
135
|
+
audience=["peer-service"],
|
|
136
|
+
subject="local-service",
|
|
137
|
+
require_iss=True,
|
|
138
|
+
require_aud=True,
|
|
139
|
+
require_sub=True,
|
|
140
|
+
)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
JWKS auto‑resolve (no static key needed — discovery used):
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
verifier = IdentityVerifier.Jwt(
|
|
147
|
+
public_key=None, # trigger auto-resolution
|
|
148
|
+
autoresolve=True,
|
|
149
|
+
issuer="https://issuer.example.com",
|
|
150
|
+
audience=["peer-service"],
|
|
151
|
+
require_iss=True,
|
|
152
|
+
require_aud=True,
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
SPIRE verifier:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
verifier = IdentityVerifier.Spire(
|
|
160
|
+
socket_path="/tmp/spire-agent/public/api.sock",
|
|
161
|
+
target_spiffe_id="spiffe://example.org/peer-service",
|
|
162
|
+
jwt_audiences=["peer-service"]
|
|
163
|
+
)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### JWKS Auto‑Resolution Workflow
|
|
167
|
+
|
|
168
|
+
When `IdentityVerifier.Jwt` is created with `autoresolve=True` and no explicit `public_key`:
|
|
169
|
+
|
|
170
|
+
1. Perform OpenID Provider Discovery (`/.well-known/openid-configuration`) to find `jwks_uri`.
|
|
171
|
+
2. If discovery fails, attempt `/.well-known/jwks.json` directly.
|
|
172
|
+
3. Fetch & cache key set (with TTL); prefer matching `kid`, else fall back to compatible algorithm.
|
|
173
|
+
4. Periodically refresh before expiry (background).
|
|
174
|
+
|
|
175
|
+
### Choosing a Strategy
|
|
176
|
+
|
|
177
|
+
| Environment | Recommended Provider / Verifier Pair |
|
|
178
|
+
|--------------------|---------------------------------------------------------------|
|
|
179
|
+
| Local Dev / Tests | SharedSecret / SharedSecret |
|
|
180
|
+
| Simple Staging | StaticJwt / Jwt (public key) |
|
|
181
|
+
| Production | Jwt (dynamic signing) / Jwt (public key or JWKS) |
|
|
182
|
+
| Zero-Trust / SPIFFE| Spire / Spire |
|
|
183
|
+
|
|
184
|
+
Use strict claim requirements (`require_*`) in production to avoid accepting tokens missing critical identity attributes.
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Quick Start
|
|
190
|
+
|
|
191
|
+
### 1. Install
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
pip install slim-bindings
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### 2. Minimal Receiver Example
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
import asyncio
|
|
201
|
+
import slim_bindings
|
|
202
|
+
|
|
203
|
+
async def main():
|
|
204
|
+
# 1. Create identity
|
|
205
|
+
provider = slim_bindings.IdentityProvider.SharedSecret(identity="demo", shared_secret="secret")
|
|
206
|
+
verifier = slim_bindings.IdentityVerifier.SharedSecret(identity="demo", shared_secret="secret")
|
|
207
|
+
|
|
208
|
+
local_name = slim_bindings.Name("org", "namespace", "demo")
|
|
209
|
+
slim = slim_bindings.Slim(local_name, provider, verifier)
|
|
210
|
+
|
|
211
|
+
# 2. (Optionally) connect as a client to a remote endpoint
|
|
212
|
+
# await slim.connect({"endpoint": "http://127.0.0.1:50000", "tls": {"insecure": True}})
|
|
213
|
+
|
|
214
|
+
# 4. Wait for inbound session
|
|
215
|
+
print("Waiting for an inbound session...")
|
|
216
|
+
session = await slim.listen_for_session()
|
|
217
|
+
|
|
218
|
+
# Wait for messages and reply
|
|
219
|
+
try:
|
|
220
|
+
while True:
|
|
221
|
+
msg_ctx, payload = await session.get_message()
|
|
222
|
+
print("Received:", payload)
|
|
223
|
+
handle = await session.publish(b"echo:" + payload)
|
|
224
|
+
|
|
225
|
+
# Wait for message to be delivered end-to-end
|
|
226
|
+
await handle
|
|
227
|
+
except Exception as e:
|
|
228
|
+
print("Error:", e)
|
|
229
|
+
pass
|
|
230
|
+
|
|
231
|
+
asyncio.run(main())
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### 3. Outbound Session (PointToPoint)
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
remote = slim_bindings.Name("org", "namespace", "peer")
|
|
238
|
+
await slim.set_route(remote)
|
|
239
|
+
session = await slim.create_session(
|
|
240
|
+
dest_name=remote,
|
|
241
|
+
session_config=slim_bindings.SessionConfiguration.PointToPoint(
|
|
242
|
+
max_retries=5,
|
|
243
|
+
timeout=datetime.timedelta(seconds=5),
|
|
244
|
+
mls_enabled=True,
|
|
245
|
+
metadata={"trace_id": "abc123"},
|
|
246
|
+
)
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
handle = await session.publish(b"hello")
|
|
250
|
+
await handle
|
|
251
|
+
|
|
252
|
+
ctx, reply = await session.get_message()
|
|
253
|
+
print("Reply:", reply)
|
|
254
|
+
|
|
255
|
+
# Delete session when done. This will also end the session at the remote peer.
|
|
256
|
+
handle = await slim.delete_session(session)
|
|
257
|
+
await handle
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Tracing / Observability
|
|
263
|
+
|
|
264
|
+
Initialize tracing (optionally enabling OpenTelemetry export):
|
|
265
|
+
|
|
266
|
+
```python
|
|
267
|
+
await slim_bindings.init_tracing({
|
|
268
|
+
"log_level": "info",
|
|
269
|
+
"opentelemetry": {
|
|
270
|
+
"enabled": True,
|
|
271
|
+
"grpc": {"endpoint": "http://localhost:4317"}
|
|
272
|
+
}
|
|
273
|
+
})
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Installation
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
pip install slim-bindings
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Include as Dependency
|
|
287
|
+
|
|
288
|
+
### With `pyproject.toml`
|
|
289
|
+
|
|
290
|
+
```toml
|
|
291
|
+
[project]
|
|
292
|
+
name = "slim-example"
|
|
293
|
+
version = "0.1.0"
|
|
294
|
+
description = "Python program using SLIM"
|
|
295
|
+
requires-python = ">=3.10"
|
|
296
|
+
dependencies = [
|
|
297
|
+
"slim-bindings>=0.7.0"
|
|
298
|
+
]
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### With Poetry
|
|
302
|
+
|
|
303
|
+
```toml
|
|
304
|
+
[tool.poetry]
|
|
305
|
+
name = "slim-example"
|
|
306
|
+
version = "0.1.0"
|
|
307
|
+
description = "Python program using SLIM"
|
|
308
|
+
|
|
309
|
+
[tool.poetry.dependencies]
|
|
310
|
+
python = ">=3.10,<3.13"
|
|
311
|
+
slim-bindings = ">=0.5.0"
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## Feature Highlights
|
|
317
|
+
|
|
318
|
+
| Area | Capability |
|
|
319
|
+
|-----------------|------------|
|
|
320
|
+
| Server | `run_server`, `stop_server` |
|
|
321
|
+
| Client | `connect`, `disconnect`, automatic subscribe to local name |
|
|
322
|
+
| Routing | `set_route`, `remove_route` |
|
|
323
|
+
| Subscriptions | `subscribe`, `unsubscribe` |
|
|
324
|
+
| Sessions | `create_session`, `listen_for_session`, `delete_session`, `set_session_config` |
|
|
325
|
+
| Messaging | `publish`, `publish_to`, `get_message` |
|
|
326
|
+
| Identity | Shared secret, static JWT, dynamic JWT signing, JWT verification (public key / JWKS) |
|
|
327
|
+
| Tracing | Structured logs & optional OpenTelemetry export |
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Example Programs
|
|
332
|
+
|
|
333
|
+
Complete runnable examples (point2point, group, server) live in the repository:
|
|
334
|
+
|
|
335
|
+
https://github.com/agntcy/slim/tree/slim-v0.7.0/data-plane/python/bindings/examples
|
|
336
|
+
|
|
337
|
+
You can install and invoke them (after building) via:
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
slim-bindings-examples point2point ...
|
|
341
|
+
slim-bindings-examples group ...
|
|
342
|
+
slim-bindings-examples slim ...
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## When to Use Each Session Type
|
|
348
|
+
|
|
349
|
+
| Use Case | Recommended Type |
|
|
350
|
+
|----------------------------------|-------------------|
|
|
351
|
+
| Stable peer workflow / stateful | Point2Point |
|
|
352
|
+
| Group chat / fan-out | Group |
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## Security Notes
|
|
357
|
+
|
|
358
|
+
- Prefer asymmetric JWT-based identity in production.
|
|
359
|
+
- Rotate keys periodically and enable `require_iss`, `require_aud`, `require_sub`.
|
|
360
|
+
- Shared secret is only suitable for local tests and prototypes.
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## License
|
|
365
|
+
|
|
366
|
+
Apache-2.0 (see repository for full license text).
|
|
367
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
slim_bindings-0.7.1.dist-info/METADATA,sha256=nhIiMpdQoSTGOIHU-s62UVdYxXs8nJpDhELY_K48XZ8,12590
|
|
2
|
+
slim_bindings-0.7.1.dist-info/WHEEL,sha256=TJQY77QRLvXq32tEs9ATmwKO6NAOtuKOAw50eyiSmWU,96
|
|
3
|
+
slim_bindings/__init__.py,sha256=kgUxH0lTNdZXfXyh0M75vlfqprSlacSasZEY_W0Nwvs,1114
|
|
4
|
+
slim_bindings/_slim_bindings.cp313-win_amd64.pyd,sha256=ysHHo7WrpbiOIDfRTNMVx3wQYtovl6L16bwgKDxEGa4,22553600
|
|
5
|
+
slim_bindings/_slim_bindings.pyi,sha256=cGr0LkHBIymVVySwMxe5OUYWrMr8DNHTPDZ5d7NGOc0,26031
|
|
6
|
+
slim_bindings/errors.py,sha256=4yRY7t4fEsWdtuuyQmpHZwEjxMMJAwCAAs5pT1qOe3Q,2159
|
|
7
|
+
slim_bindings/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
slim_bindings/session.py,sha256=ErTKWuujqFC7iuQjJTZwLUyORbCSvXCdbciVntUNzG0,5779
|
|
9
|
+
slim_bindings/slim.py,sha256=JgtBCClkkaK-fcsgDSY7-KytMhKMcAan6TdHMK5yPLA,10431
|
|
10
|
+
slim_bindings/version.py,sha256=5szIAMwvRLLSKdH_9dXlH-W_fXT_BVM5bKy1Il_seHU,795
|
|
11
|
+
slim_bindings-0.7.1.dist-info/RECORD,,
|