tigrcorn-contract 0.3.16.dev5__tar.gz → 0.3.16.dev13__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 (22) hide show
  1. {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev13}/PKG-INFO +74 -17
  2. tigrcorn_contract-0.3.16.dev13/README.md +101 -0
  3. {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev13}/pyproject.toml +6 -4
  4. {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev13}/src/tigrcorn_contract/__init__.py +40 -0
  5. tigrcorn_contract-0.3.16.dev13/src/tigrcorn_contract/classification.py +209 -0
  6. {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev13}/src/tigrcorn_contract/events.py +215 -20
  7. tigrcorn_contract-0.3.16.dev13/src/tigrcorn_contract/metadata.py +347 -0
  8. tigrcorn_contract-0.3.16.dev13/src/tigrcorn_contract/projection.py +283 -0
  9. {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev13}/src/tigrcorn_contract/scopes.py +8 -0
  10. {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev13}/src/tigrcorn_contract.egg-info/PKG-INFO +74 -17
  11. {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev13}/src/tigrcorn_contract.egg-info/SOURCES.txt +1 -0
  12. tigrcorn_contract-0.3.16.dev13/src/tigrcorn_contract.egg-info/requires.txt +3 -0
  13. tigrcorn_contract-0.3.16.dev5/README.md +0 -46
  14. tigrcorn_contract-0.3.16.dev5/src/tigrcorn_contract/classification.py +0 -104
  15. tigrcorn_contract-0.3.16.dev5/src/tigrcorn_contract/metadata.py +0 -206
  16. tigrcorn_contract-0.3.16.dev5/src/tigrcorn_contract.egg-info/requires.txt +0 -3
  17. {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev13}/LICENSE +0 -0
  18. {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev13}/setup.cfg +0 -0
  19. {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev13}/src/tigrcorn_contract/compat.py +0 -0
  20. {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev13}/src/tigrcorn_contract/py.typed +0 -0
  21. {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev13}/src/tigrcorn_contract.egg-info/dependency_links.txt +0 -0
  22. {tigrcorn_contract-0.3.16.dev5 → tigrcorn_contract-0.3.16.dev13}/src/tigrcorn_contract.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tigrcorn-contract
3
- Version: 0.3.16.dev5
3
+ Version: 0.3.16.dev13
4
4
  Summary: tigr-asgi-contract adapters and runtime-boundary classification for Tigrcorn ASGI3, WebSocket, and WebTransport surfaces.
5
5
  Author-email: Jacob Stewart <jacob@swarmauri.com>
6
6
  License: Apache License
@@ -175,40 +175,52 @@ Classifier: License :: OSI Approved :: Apache Software License
175
175
  Classifier: Operating System :: OS Independent
176
176
  Classifier: Programming Language :: Python :: 3
177
177
  Classifier: Programming Language :: Python :: 3 :: Only
178
+ Classifier: Programming Language :: Python :: 3.10
178
179
  Classifier: Programming Language :: Python :: 3.11
179
180
  Classifier: Programming Language :: Python :: 3.12
180
181
  Classifier: Programming Language :: Python :: 3.13
182
+ Classifier: Programming Language :: Python :: 3.14
181
183
  Classifier: Topic :: Internet :: WWW/HTTP
182
184
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
183
185
  Classifier: Typing :: Typed
184
- Requires-Python: >=3.11
186
+ Requires-Python: <3.15,>=3.10
185
187
  Description-Content-Type: text/markdown
186
188
  License-File: LICENSE
187
- Requires-Dist: tigrcorn-core==0.3.16.dev5
188
- Requires-Dist: tigrcorn-asgi==0.3.16.dev5
189
+ Requires-Dist: tigrcorn-core==0.3.16.dev13
190
+ Requires-Dist: tigrcorn-asgi==0.3.16.dev13
189
191
  Requires-Dist: tigr-asgi-contract>=0.3.2
190
192
  Dynamic: license-file
191
193
 
192
194
  <div align="center">
193
195
  <h1>tigrcorn-contract</h1>
196
+ <img
197
+ src="https://raw.githubusercontent.com/Tigrbl/tigrcorn/master/assets/tigrcorn_logo.png"
198
+ alt="Tigrcorn tiger-unicorn logo"
199
+ width="140"
200
+ />
194
201
 
195
202
  <p><strong>tigr-asgi-contract adapters and runtime-boundary classification for Tigrcorn ASGI3, WebSocket, and WebTransport surfaces.</strong></p>
196
203
 
197
204
  <a href="https://pypi.org/project/tigrcorn-contract/"><img alt="PyPI version for tigrcorn-contract" src="https://img.shields.io/pypi/v/tigrcorn-contract?label=PyPI"></a>
198
205
  <a href="https://pypi.org/project/tigrcorn-contract/"><img alt="tigrcorn-contract package on PyPI" src="https://img.shields.io/badge/package-PyPI-blue"></a>
206
+ <a href="https://pepy.tech/project/tigrcorn-contract"><img alt="Downloads for tigrcorn-contract" src="https://static.pepy.tech/badge/tigrcorn-contract"></a>
207
+ <a href="https://github.com/tigrbl/tigrcorn/blob/master/pkgs/tigrcorn-contract/README.md"><img alt="Hits for tigrcorn-contract README" src="https://hits.sh/github.com/tigrbl/tigrcorn/blob/master/pkgs/tigrcorn-contract/README.md.svg?label=hits"></a>
199
208
  <a href="LICENSE"><img alt="Apache 2.0 license" src="https://img.shields.io/badge/license-Apache%202.0-525252"></a>
200
- <a href="pyproject.toml"><img alt="Python 3.11 supported" src="https://img.shields.io/badge/python-3.11-3776ab"></a>
201
- <a href="pyproject.toml"><img alt="Python 3.12 supported" src="https://img.shields.io/badge/python-3.12-3776ab"></a>
202
- <a href="pyproject.toml"><img alt="Python 3.13 supported" src="https://img.shields.io/badge/python-3.13-3776ab"></a>
203
- <a href="src/tigrcorn_contract/py.typed"><img alt="typed package" src="https://img.shields.io/badge/typed-py.typed-2f7ed8"></a>
209
+ <a href="pyproject.toml"><img alt="Python 3.10 | 3.11 | 3.12 | 3.13 | 3.14 supported" src="https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-3776ab"></a>
204
210
  <a href="https://pypi.org/project/tigrcorn-contract/"><img alt="contract role package" src="https://img.shields.io/badge/role-contract-0a7f5a"></a>
205
211
  </div>
206
212
 
213
+ <p align="center"><a href="https://github.com/Tigrbl/tigrcorn/blob/master/.ssot/registry.json"><img alt="SSOT governed" src="https://img.shields.io/badge/SSOT-governed-2f6f4e.svg"></a> <a href="https://discord.gg/jzvrbEtTtt"><img alt="Discord" src="https://img.shields.io/badge/Discord-Join%20chat-5865F2?logo=discord&amp;logoColor=white"></a></p>
214
+
207
215
  ## Install
208
216
 
209
- ~~~bash
217
+ ```bash
218
+ uv add tigrcorn-contract
219
+ ```
220
+
221
+ ```bash
210
222
  pip install tigrcorn-contract
211
- ~~~
223
+ ```
212
224
 
213
225
  Use the aggregate [tigrcorn](https://pypi.org/project/tigrcorn/) distribution when you want the full ASGI3 Python web server stack. Install <code>tigrcorn-contract</code> directly when you want only this package boundary and its declared dependencies.
214
226
 
@@ -216,22 +228,67 @@ Use the aggregate [tigrcorn](https://pypi.org/project/tigrcorn/) distribution wh
216
228
 
217
229
  <code>tigrcorn-contract</code> owns native contract app markers, contract scope validation, contract event validation, and boundary classification. Its import package is <code>tigrcorn_contract</code>, and its declared package dependencies are: tigrcorn-core, tigrcorn-asgi, tigr-asgi-contract.
218
230
 
219
- This package page is written for developers searching for Tigrcorn ASGI3 server components, Python web server packages, HTTP/3 and QUIC support, WebSocket and WebTransport runtime surfaces, typed package boundaries, and Apache 2.0 licensed infrastructure.
231
+ This package page is written for developers searching for Tigrcorn ASGI3 server components, Python web server packages, HTTP/3 and QUIC support, WebSocket and WebTransport-adjacent surfaces, and Apache 2.0 licensed infrastructure.
232
+
233
+ ## Why Use This?
234
+
235
+ Use <code>tigrcorn-contract</code> when you want the contract layer as a direct install target instead of the full server bundle. It lets application, operator, or certification workflows depend on this boundary explicitly while keeping the broader Tigrcorn runtime assembled from smaller repo-owned package surfaces.
236
+
237
+ ## FAQ
238
+
239
+ ### What does this package export?
240
+
241
+ The package exports through the <code>tigrcorn_contract</code> namespace and keeps the root <code>tigrcorn</code> package as the compatibility umbrella.
242
+
243
+ ### Which boundary does this package own?
244
+
245
+ It is the package boundary for native contract app markers, contract scope validation, contract event validation, and boundary classification in the Tigrcorn package graph.
246
+
247
+ ### What does the contract layer validate?
248
+
249
+ It validates contract scopes, event ordering, endpoint metadata, runtime classification, and WebSocket or WebTransport boundary semantics against the tigr-asgi-contract surface.
250
+
251
+ ## Features
252
+
253
+ - Owns native contract app markers, contract scope validation, contract event validation, and boundary classification inside the Tigrcorn split-package architecture.
254
+ - Publishes the <code>tigrcorn_contract</code> import surface for named public helpers and entrypoints.
255
+ - Declared runtime dependencies: tigrcorn-core, tigrcorn-asgi, tigr-asgi-contract.
256
+ - Optional dependency surface: none.
257
+ - Supports Python 3.10, 3.11, 3.12, 3.13, and 3.14.
220
258
 
221
259
  ## Use It When
222
260
 
223
- Use <code>tigrcorn-contract</code> when you need the governed contract bridge between Tigrcorn runtime surfaces and tigr-asgi-contract semantics. It is part of Tigrcorn's split-package architecture, so it can be installed independently while remaining linked to the rest of the Tigrcorn package family on PyPI.
261
+ Use <code>tigrcorn-contract</code> when you need contract-level behavior without pulling the entire server stack into the import surface. It is part of Tigrcorn's split-package architecture, so it can be installed independently while remaining linked to the rest of the Tigrcorn package family on PyPI.
224
262
 
225
263
  ## Import Surface
226
264
 
227
- ~~~python
228
- import tigrcorn_contract
265
+ ```python
266
+ from tigrcorn_contract import contract_scope, validate_scope
229
267
 
230
- print(tigrcorn_contract.__name__)
231
- ~~~
268
+ scope = contract_scope("http", path="/")
269
+ print(validate_scope(scope))
270
+ ```
271
+
272
+ Namespace discovery starts with `import tigrcorn_contract`.
232
273
 
233
274
  The package exposes its supported public surface through the <code>tigrcorn_contract</code> namespace. The root [tigrcorn](https://pypi.org/project/tigrcorn/) package keeps compatibility shims for users who install the full server distribution.
234
275
 
276
+ ## Related Packages
277
+
278
+ - [tigrcorn-core](https://pypi.org/project/tigrcorn-core/)
279
+ - [tigrcorn-asgi](https://pypi.org/project/tigrcorn-asgi/)
280
+ - [tigrcorn](https://pypi.org/project/tigrcorn/)
281
+
235
282
  ## Package Graph
236
283
 
237
- [tigrcorn](https://pypi.org/project/tigrcorn/) | [tigrcorn-core](https://pypi.org/project/tigrcorn-core/) | [tigrcorn-config](https://pypi.org/project/tigrcorn-config/) | [tigrcorn-asgi](https://pypi.org/project/tigrcorn-asgi/) | [tigrcorn-contract](https://pypi.org/project/tigrcorn-contract/) | [tigrcorn-transports](https://pypi.org/project/tigrcorn-transports/) | [tigrcorn-protocols](https://pypi.org/project/tigrcorn-protocols/) | [tigrcorn-http](https://pypi.org/project/tigrcorn-http/) | [tigrcorn-security](https://pypi.org/project/tigrcorn-security/) | [tigrcorn-runtime](https://pypi.org/project/tigrcorn-runtime/) | [tigrcorn-static](https://pypi.org/project/tigrcorn-static/) | [tigrcorn-observability](https://pypi.org/project/tigrcorn-observability/) | [tigrcorn-compat](https://pypi.org/project/tigrcorn-compat/) | [tigrcorn-certification](https://pypi.org/project/tigrcorn-certification/)
284
+ [tigrcorn-core](https://pypi.org/project/tigrcorn-core/) | [tigrcorn-config](https://pypi.org/project/tigrcorn-config/) | [tigrcorn-http](https://pypi.org/project/tigrcorn-http/) | [tigrcorn-asgi](https://pypi.org/project/tigrcorn-asgi/) | [tigrcorn-contract](https://pypi.org/project/tigrcorn-contract/) | [tigrcorn-transports](https://pypi.org/project/tigrcorn-transports/) | [tigrcorn-security](https://pypi.org/project/tigrcorn-security/) | [tigrcorn-protocols](https://pypi.org/project/tigrcorn-protocols/) | [tigrcorn-static](https://pypi.org/project/tigrcorn-static/) | [tigrcorn-observability](https://pypi.org/project/tigrcorn-observability/) | [tigrcorn-runtime](https://pypi.org/project/tigrcorn-runtime/) | [tigrcorn-compat](https://pypi.org/project/tigrcorn-compat/) | [tigrcorn-certification](https://pypi.org/project/tigrcorn-certification/)
285
+
286
+ ## Best Practices
287
+
288
+ - Use this package when you need contract validation or classification rather than embedding that logic in protocol handlers.
289
+ - Keep new WebSocket, WebTransport, and endpoint-metadata semantics grounded in the contract surface here.
290
+ - Update runtime-boundary classification together with any new contract-facing feature rows.
291
+
292
+ ## License
293
+
294
+ Apache-2.0
@@ -0,0 +1,101 @@
1
+ <div align="center">
2
+ <h1>tigrcorn-contract</h1>
3
+ <img
4
+ src="https://raw.githubusercontent.com/Tigrbl/tigrcorn/master/assets/tigrcorn_logo.png"
5
+ alt="Tigrcorn tiger-unicorn logo"
6
+ width="140"
7
+ />
8
+
9
+ <p><strong>tigr-asgi-contract adapters and runtime-boundary classification for Tigrcorn ASGI3, WebSocket, and WebTransport surfaces.</strong></p>
10
+
11
+ <a href="https://pypi.org/project/tigrcorn-contract/"><img alt="PyPI version for tigrcorn-contract" src="https://img.shields.io/pypi/v/tigrcorn-contract?label=PyPI"></a>
12
+ <a href="https://pypi.org/project/tigrcorn-contract/"><img alt="tigrcorn-contract package on PyPI" src="https://img.shields.io/badge/package-PyPI-blue"></a>
13
+ <a href="https://pepy.tech/project/tigrcorn-contract"><img alt="Downloads for tigrcorn-contract" src="https://static.pepy.tech/badge/tigrcorn-contract"></a>
14
+ <a href="https://github.com/tigrbl/tigrcorn/blob/master/pkgs/tigrcorn-contract/README.md"><img alt="Hits for tigrcorn-contract README" src="https://hits.sh/github.com/tigrbl/tigrcorn/blob/master/pkgs/tigrcorn-contract/README.md.svg?label=hits"></a>
15
+ <a href="LICENSE"><img alt="Apache 2.0 license" src="https://img.shields.io/badge/license-Apache%202.0-525252"></a>
16
+ <a href="pyproject.toml"><img alt="Python 3.10 | 3.11 | 3.12 | 3.13 | 3.14 supported" src="https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13%20%7C%203.14-3776ab"></a>
17
+ <a href="https://pypi.org/project/tigrcorn-contract/"><img alt="contract role package" src="https://img.shields.io/badge/role-contract-0a7f5a"></a>
18
+ </div>
19
+
20
+ <p align="center"><a href="https://github.com/Tigrbl/tigrcorn/blob/master/.ssot/registry.json"><img alt="SSOT governed" src="https://img.shields.io/badge/SSOT-governed-2f6f4e.svg"></a> <a href="https://discord.gg/jzvrbEtTtt"><img alt="Discord" src="https://img.shields.io/badge/Discord-Join%20chat-5865F2?logo=discord&amp;logoColor=white"></a></p>
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ uv add tigrcorn-contract
26
+ ```
27
+
28
+ ```bash
29
+ pip install tigrcorn-contract
30
+ ```
31
+
32
+ Use the aggregate [tigrcorn](https://pypi.org/project/tigrcorn/) distribution when you want the full ASGI3 Python web server stack. Install <code>tigrcorn-contract</code> directly when you want only this package boundary and its declared dependencies.
33
+
34
+ ## What It Owns
35
+
36
+ <code>tigrcorn-contract</code> owns native contract app markers, contract scope validation, contract event validation, and boundary classification. Its import package is <code>tigrcorn_contract</code>, and its declared package dependencies are: tigrcorn-core, tigrcorn-asgi, tigr-asgi-contract.
37
+
38
+ This package page is written for developers searching for Tigrcorn ASGI3 server components, Python web server packages, HTTP/3 and QUIC support, WebSocket and WebTransport-adjacent surfaces, and Apache 2.0 licensed infrastructure.
39
+
40
+ ## Why Use This?
41
+
42
+ Use <code>tigrcorn-contract</code> when you want the contract layer as a direct install target instead of the full server bundle. It lets application, operator, or certification workflows depend on this boundary explicitly while keeping the broader Tigrcorn runtime assembled from smaller repo-owned package surfaces.
43
+
44
+ ## FAQ
45
+
46
+ ### What does this package export?
47
+
48
+ The package exports through the <code>tigrcorn_contract</code> namespace and keeps the root <code>tigrcorn</code> package as the compatibility umbrella.
49
+
50
+ ### Which boundary does this package own?
51
+
52
+ It is the package boundary for native contract app markers, contract scope validation, contract event validation, and boundary classification in the Tigrcorn package graph.
53
+
54
+ ### What does the contract layer validate?
55
+
56
+ It validates contract scopes, event ordering, endpoint metadata, runtime classification, and WebSocket or WebTransport boundary semantics against the tigr-asgi-contract surface.
57
+
58
+ ## Features
59
+
60
+ - Owns native contract app markers, contract scope validation, contract event validation, and boundary classification inside the Tigrcorn split-package architecture.
61
+ - Publishes the <code>tigrcorn_contract</code> import surface for named public helpers and entrypoints.
62
+ - Declared runtime dependencies: tigrcorn-core, tigrcorn-asgi, tigr-asgi-contract.
63
+ - Optional dependency surface: none.
64
+ - Supports Python 3.10, 3.11, 3.12, 3.13, and 3.14.
65
+
66
+ ## Use It When
67
+
68
+ Use <code>tigrcorn-contract</code> when you need contract-level behavior without pulling the entire server stack into the import surface. It is part of Tigrcorn's split-package architecture, so it can be installed independently while remaining linked to the rest of the Tigrcorn package family on PyPI.
69
+
70
+ ## Import Surface
71
+
72
+ ```python
73
+ from tigrcorn_contract import contract_scope, validate_scope
74
+
75
+ scope = contract_scope("http", path="/")
76
+ print(validate_scope(scope))
77
+ ```
78
+
79
+ Namespace discovery starts with `import tigrcorn_contract`.
80
+
81
+ The package exposes its supported public surface through the <code>tigrcorn_contract</code> namespace. The root [tigrcorn](https://pypi.org/project/tigrcorn/) package keeps compatibility shims for users who install the full server distribution.
82
+
83
+ ## Related Packages
84
+
85
+ - [tigrcorn-core](https://pypi.org/project/tigrcorn-core/)
86
+ - [tigrcorn-asgi](https://pypi.org/project/tigrcorn-asgi/)
87
+ - [tigrcorn](https://pypi.org/project/tigrcorn/)
88
+
89
+ ## Package Graph
90
+
91
+ [tigrcorn-core](https://pypi.org/project/tigrcorn-core/) | [tigrcorn-config](https://pypi.org/project/tigrcorn-config/) | [tigrcorn-http](https://pypi.org/project/tigrcorn-http/) | [tigrcorn-asgi](https://pypi.org/project/tigrcorn-asgi/) | [tigrcorn-contract](https://pypi.org/project/tigrcorn-contract/) | [tigrcorn-transports](https://pypi.org/project/tigrcorn-transports/) | [tigrcorn-security](https://pypi.org/project/tigrcorn-security/) | [tigrcorn-protocols](https://pypi.org/project/tigrcorn-protocols/) | [tigrcorn-static](https://pypi.org/project/tigrcorn-static/) | [tigrcorn-observability](https://pypi.org/project/tigrcorn-observability/) | [tigrcorn-runtime](https://pypi.org/project/tigrcorn-runtime/) | [tigrcorn-compat](https://pypi.org/project/tigrcorn-compat/) | [tigrcorn-certification](https://pypi.org/project/tigrcorn-certification/)
92
+
93
+ ## Best Practices
94
+
95
+ - Use this package when you need contract validation or classification rather than embedding that logic in protocol handlers.
96
+ - Keep new WebSocket, WebTransport, and endpoint-metadata semantics grounded in the contract surface here.
97
+ - Update runtime-boundary classification together with any new contract-facing feature rows.
98
+
99
+ ## License
100
+
101
+ Apache-2.0
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tigrcorn-contract"
7
- version = "0.3.16.dev5"
7
+ version = "0.3.16.dev13"
8
8
  description = "tigr-asgi-contract adapters and runtime-boundary classification for Tigrcorn ASGI3, WebSocket, and WebTransport surfaces."
9
9
  readme = "README.md"
10
- requires-python = ">=3.11"
10
+ requires-python = ">=3.10,<3.15"
11
11
  license = {file = "LICENSE"}
12
12
  authors = [{name = "Jacob Stewart", email = "jacob@swarmauri.com"}]
13
13
  keywords = ["tigrcorn", "tigr-asgi-contract", "asgi-contract", "runtime-contract", "webtransport", "asgi3"]
@@ -19,16 +19,18 @@ classifiers = [
19
19
  "Operating System :: OS Independent",
20
20
  "Programming Language :: Python :: 3",
21
21
  "Programming Language :: Python :: 3 :: Only",
22
+ "Programming Language :: Python :: 3.10",
22
23
  "Programming Language :: Python :: 3.11",
23
24
  "Programming Language :: Python :: 3.12",
24
25
  "Programming Language :: Python :: 3.13",
26
+ "Programming Language :: Python :: 3.14",
25
27
  "Topic :: Internet :: WWW/HTTP",
26
28
  "Topic :: Software Development :: Libraries :: Python Modules",
27
29
  "Typing :: Typed",
28
30
  ]
29
31
  dependencies = [
30
- "tigrcorn-core==0.3.16.dev5",
31
- "tigrcorn-asgi==0.3.16.dev5",
32
+ "tigrcorn-core==0.3.16.dev13",
33
+ "tigrcorn-asgi==0.3.16.dev13",
32
34
  "tigr-asgi-contract>=0.3.2",
33
35
  ]
34
36
 
@@ -3,8 +3,13 @@ from __future__ import annotations
3
3
  from .classification import (
4
4
  BindingClassification,
5
5
  FamilyCapability,
6
+ ProductSurfaceStatus,
6
7
  classify_binding,
7
8
  family_capability,
9
+ product_surface_excluded,
10
+ product_surface_status,
11
+ require_product_boundary_exclusion,
12
+ require_product_runtime_available,
8
13
  runtime_interface_available,
9
14
  validate_binding_legality,
10
15
  )
@@ -26,6 +31,8 @@ from .compat import (
26
31
  from .events import (
27
32
  CompletionLevel,
28
33
  CompletionStatus,
34
+ GenericDatagramRuntime,
35
+ GenericStreamRuntime,
29
36
  datagram_receive,
30
37
  datagram_send,
31
38
  emit_complete,
@@ -43,7 +50,9 @@ from .events import (
43
50
  map_contract_event,
44
51
  stream_receive,
45
52
  stream_send,
53
+ validate_datagram_event,
46
54
  validate_event_order,
55
+ validate_stream_event,
47
56
  websocket_accept,
48
57
  websocket_close,
49
58
  websocket_connect,
@@ -73,7 +82,19 @@ from .metadata import (
73
82
  stream_identity,
74
83
  transport_identity,
75
84
  unit_identity,
85
+ validate_connection_identity,
76
86
  validate_endpoint_metadata,
87
+ validate_security_metadata,
88
+ validate_stream_identity,
89
+ )
90
+ from .projection import (
91
+ EventProjection,
92
+ ScopeProjection,
93
+ project_event_classification,
94
+ project_receive_event,
95
+ project_scope_classification,
96
+ project_send_event,
97
+ validate_projected_event,
77
98
  )
78
99
  from .scopes import SUPPORTED_SCOPE_TYPES, contract_scope, validate_scope
79
100
 
@@ -84,10 +105,15 @@ __all__ = [
84
105
  "ConnectionIdentity",
85
106
  "EndpointMetadata",
86
107
  "FamilyCapability",
108
+ "GenericDatagramRuntime",
109
+ "GenericStreamRuntime",
110
+ "ProductSurfaceStatus",
87
111
  "CompatibilityParityRow",
88
112
  "HTTPFeatureContractMap",
89
113
  "SUPPORTED_SCOPE_TYPES",
90
114
  "SecurityMetadata",
115
+ "EventProjection",
116
+ "ScopeProjection",
91
117
  "StreamIdentity",
92
118
  "UnitIdentity",
93
119
  "alt_svc_contract_map",
@@ -120,7 +146,15 @@ __all__ = [
120
146
  "map_contract_event",
121
147
  "observability_contract_metadata",
122
148
  "proxy_normalization_contract_map",
149
+ "product_surface_status",
150
+ "product_surface_excluded",
151
+ "project_event_classification",
152
+ "project_receive_event",
153
+ "project_scope_classification",
154
+ "project_send_event",
123
155
  "require_lossless_metadata",
156
+ "require_product_boundary_exclusion",
157
+ "require_product_runtime_available",
124
158
  "runtime_interface_available",
125
159
  "security_metadata",
126
160
  "static_delivery_contract_map",
@@ -131,9 +165,15 @@ __all__ = [
131
165
  "trailers_contract_map",
132
166
  "unit_identity",
133
167
  "validate_binding_legality",
168
+ "validate_connection_identity",
169
+ "validate_datagram_event",
134
170
  "validate_endpoint_metadata",
135
171
  "validate_event_order",
172
+ "validate_projected_event",
173
+ "validate_security_metadata",
136
174
  "validate_scope",
175
+ "validate_stream_event",
176
+ "validate_stream_identity",
137
177
  "websocket_accept",
138
178
  "websocket_close",
139
179
  "websocket_connect",
@@ -0,0 +1,209 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Literal
5
+
6
+ from tigrcorn_core.errors import ConfigError
7
+
8
+ BindingKind = Literal["http", "http.stream", "websocket", "lifespan", "webtransport", "stream", "datagram", "rest", "jsonrpc", "sse"]
9
+ ProductSurfaceKind = Literal[
10
+ "auto",
11
+ "tigr-asgi-contract",
12
+ "asgi3",
13
+ "asgi2",
14
+ "wsgi",
15
+ "rsgi",
16
+ "rest",
17
+ "jsonrpc",
18
+ ]
19
+
20
+ _SERVER_OWNED_RUNTIMES = {"http", "http.stream", "websocket", "lifespan", "webtransport", "stream", "datagram"}
21
+ _CLASSIFICATION_ONLY = {"rest", "jsonrpc", "sse"}
22
+ _SUPPORTED_APP_INTERFACES = {"auto", "tigr-asgi-contract", "asgi3"}
23
+ _UNSUPPORTED_COMPAT_INTERFACES = {"asgi2", "wsgi", "rsgi"}
24
+ _RUNTIME_EXCLUDED_CLASSIFICATIONS = {"rest", "jsonrpc"}
25
+
26
+
27
+ @dataclass(frozen=True, slots=True)
28
+ class BindingClassification:
29
+ kind: BindingKind
30
+ runtime_owned: bool
31
+ classification_only: bool
32
+ dispatch_runtime: str
33
+ scope_type: str
34
+ family: str
35
+ exchange: str
36
+ framing: str | None = None
37
+ allowed_framings: tuple[str, ...] = ()
38
+
39
+
40
+ @dataclass(frozen=True, slots=True)
41
+ class FamilyCapability:
42
+ family: str
43
+ bindings: tuple[str, ...]
44
+ subevents: tuple[str, ...]
45
+ exchanges: tuple[str, ...]
46
+
47
+
48
+ @dataclass(frozen=True, slots=True)
49
+ class ProductSurfaceStatus:
50
+ kind: ProductSurfaceKind
51
+ runtime_available: bool
52
+ classification_only: bool
53
+ compatibility_exclusion: bool
54
+ reason: str
55
+
56
+
57
+ _FAMILY_CAPABILITIES = {
58
+ "request": FamilyCapability(
59
+ family="request",
60
+ bindings=("http", "http.stream", "rest", "jsonrpc"),
61
+ subevents=("request.open", "request.body_in", "request.chunk_in", "request.close", "request.disconnect"),
62
+ exchanges=("unary", "server_stream"),
63
+ ),
64
+ "session": FamilyCapability(
65
+ family="session",
66
+ bindings=("websocket", "webtransport", "lifespan"),
67
+ subevents=("session.open", "session.accept", "session.ready", "session.heartbeat", "session.close", "session.disconnect"),
68
+ exchanges=("duplex",),
69
+ ),
70
+ "message": FamilyCapability(
71
+ family="message",
72
+ bindings=("websocket",),
73
+ subevents=("message.in", "message.decode", "message.handle", "message.out", "message.ack", "message.nack"),
74
+ exchanges=("duplex",),
75
+ ),
76
+ "stream": FamilyCapability(
77
+ family="stream",
78
+ bindings=("http.stream", "webtransport", "stream", "sse"),
79
+ subevents=("stream.open", "stream.chunk_in", "stream.chunk_out", "stream.flush", "stream.finalize", "stream.abort", "stream.close"),
80
+ exchanges=("server_stream", "duplex"),
81
+ ),
82
+ "datagram": FamilyCapability(
83
+ family="datagram",
84
+ bindings=("webtransport", "datagram"),
85
+ subevents=("datagram.in", "datagram.handle", "datagram.out", "datagram.ack", "datagram.close"),
86
+ exchanges=("duplex",),
87
+ ),
88
+ }
89
+
90
+ _BINDING_SHAPES: dict[str, tuple[str, str, str, str | None, tuple[str, ...]]] = {
91
+ "http": ("http", "request", "unary", None, ()),
92
+ "http.stream": ("http", "stream", "server_stream", None, ()),
93
+ "websocket": ("websocket", "message", "duplex", None, ()),
94
+ "lifespan": ("lifespan", "session", "duplex", None, ()),
95
+ "webtransport": ("webtransport", "session", "duplex", None, ()),
96
+ "stream": ("tigrcorn.stream", "stream", "duplex", None, ()),
97
+ "datagram": ("tigrcorn.datagram", "datagram", "duplex", None, ()),
98
+ "rest": ("http", "request", "unary", "json", ("json",)),
99
+ "jsonrpc": ("http", "request", "unary", "jsonrpc", ("jsonrpc",)),
100
+ "sse": ("http", "stream", "server_stream", "sse", ("sse",)),
101
+ }
102
+
103
+
104
+ def classify_binding(kind: str) -> BindingClassification:
105
+ normalized = kind.strip().lower().replace("_", "-")
106
+ if normalized == "json-rpc":
107
+ normalized = "jsonrpc"
108
+ if normalized not in _SERVER_OWNED_RUNTIMES | _CLASSIFICATION_ONLY:
109
+ raise ConfigError(f"unsupported binding classification: {kind!r}")
110
+ scope_type, family, exchange, framing, allowed_framings = _BINDING_SHAPES[normalized]
111
+ return BindingClassification(
112
+ kind=normalized, # type: ignore[arg-type]
113
+ runtime_owned=normalized in _SERVER_OWNED_RUNTIMES,
114
+ classification_only=normalized in _CLASSIFICATION_ONLY,
115
+ dispatch_runtime="application" if normalized in _CLASSIFICATION_ONLY else "tigrcorn",
116
+ scope_type=scope_type,
117
+ family=family,
118
+ exchange=exchange,
119
+ framing=framing,
120
+ allowed_framings=allowed_framings,
121
+ )
122
+
123
+
124
+ def runtime_interface_available(interface: str) -> bool:
125
+ return product_surface_status(interface).runtime_available
126
+
127
+
128
+ def _normalize_product_surface(value: str) -> ProductSurfaceKind:
129
+ try:
130
+ normalized = value.strip().lower().replace("_", "-")
131
+ except AttributeError as exc:
132
+ raise ConfigError(f"unsupported product surface: {value!r}") from exc
133
+ if normalized == "json-rpc":
134
+ normalized = "jsonrpc"
135
+ if normalized not in _SUPPORTED_APP_INTERFACES | _UNSUPPORTED_COMPAT_INTERFACES | _RUNTIME_EXCLUDED_CLASSIFICATIONS:
136
+ raise ConfigError(f"unsupported product surface: {value!r}")
137
+ return normalized # type: ignore[return-value]
138
+
139
+
140
+ def product_surface_status(surface: str) -> ProductSurfaceStatus:
141
+ normalized = _normalize_product_surface(surface)
142
+ if normalized in _SUPPORTED_APP_INTERFACES:
143
+ return ProductSurfaceStatus(
144
+ kind=normalized,
145
+ runtime_available=True,
146
+ classification_only=False,
147
+ compatibility_exclusion=False,
148
+ reason="supported app interface",
149
+ )
150
+ if normalized in _RUNTIME_EXCLUDED_CLASSIFICATIONS:
151
+ return ProductSurfaceStatus(
152
+ kind=normalized,
153
+ runtime_available=False,
154
+ classification_only=True,
155
+ compatibility_exclusion=False,
156
+ reason="classification-only binding; runtime belongs to the application layer",
157
+ )
158
+ return ProductSurfaceStatus(
159
+ kind=normalized,
160
+ runtime_available=False,
161
+ classification_only=False,
162
+ compatibility_exclusion=True,
163
+ reason="unsupported compatibility interface",
164
+ )
165
+
166
+
167
+ def require_product_runtime_available(surface: str) -> ProductSurfaceStatus:
168
+ status = product_surface_status(surface)
169
+ if not status.runtime_available:
170
+ raise ConfigError(f"unsupported runtime product surface: {surface!r} ({status.reason})")
171
+ return status
172
+
173
+
174
+ def product_surface_excluded(surface: str) -> bool:
175
+ return not product_surface_status(surface).runtime_available
176
+
177
+
178
+ def require_product_boundary_exclusion(surface: str) -> ProductSurfaceStatus:
179
+ status = product_surface_status(surface)
180
+ if status.runtime_available:
181
+ raise ConfigError(f"product surface is supported, not excluded: {surface!r}")
182
+ return status
183
+
184
+
185
+ def family_capability(family: str) -> FamilyCapability:
186
+ normalized = family.strip().lower()
187
+ try:
188
+ return _FAMILY_CAPABILITIES[normalized]
189
+ except KeyError as exc:
190
+ raise ConfigError(f"unsupported contract family: {family!r}") from exc
191
+
192
+
193
+ def validate_binding_legality(*, binding: str, family: str, subevent: str | None = None, exchange: str | None = None) -> None:
194
+ normalized_binding = binding.strip().lower().replace("_", "-")
195
+ if normalized_binding == "json-rpc":
196
+ normalized_binding = "jsonrpc"
197
+ classification = classify_binding(normalized_binding)
198
+ normalized_family = family.strip().lower()
199
+ if classification.classification_only and normalized_family != classification.family:
200
+ raise ConfigError(f"binding {binding!r} is illegal for family {family!r}")
201
+ capability = family_capability(family)
202
+ if normalized_binding not in capability.bindings:
203
+ raise ConfigError(f"binding {binding!r} is illegal for family {family!r}")
204
+ if subevent is not None and subevent not in capability.subevents and not subevent.endswith(".emit_complete"):
205
+ raise ConfigError(f"subevent {subevent!r} is illegal for family {family!r}")
206
+ if classification.classification_only and exchange is not None and exchange != classification.exchange:
207
+ raise ConfigError(f"exchange {exchange!r} is illegal for binding {binding!r}")
208
+ if exchange is not None and exchange not in capability.exchanges:
209
+ raise ConfigError(f"exchange {exchange!r} is illegal for family {family!r}")