tigrbl-core 0.4.2.dev4__tar.gz → 0.4.3.dev4__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 (68) hide show
  1. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/PKG-INFO +85 -4
  2. tigrbl_core-0.4.3.dev4/README.md +238 -0
  3. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/pyproject.toml +3 -1
  4. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/__init__.py +36 -0
  5. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/app_spec.py +38 -1
  6. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/binding_spec.py +28 -11
  7. tigrbl_core-0.4.3.dev4/tigrbl_core/_spec/exceptions.py +16 -0
  8. tigrbl_core-0.4.3.dev4/tigrbl_core/_spec/exposure_policy.py +112 -0
  9. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/hook_types.py +2 -2
  10. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/op_spec.py +9 -0
  11. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/path_spec.py +17 -1
  12. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/router_spec.py +7 -0
  13. tigrbl_core-0.4.3.dev4/tigrbl_core/_spec/table_profile_bindings.py +466 -0
  14. tigrbl_core-0.4.3.dev4/tigrbl_core/_spec/table_profile_spec.py +536 -0
  15. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/table_spec.py +25 -1
  16. tigrbl_core-0.4.3.dev4/tigrbl_core/_spec/transport_stack.py +120 -0
  17. tigrbl_core-0.4.3.dev4/tigrbl_core/_spec/well_known_spec.py +69 -0
  18. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/config/constants.py +3 -0
  19. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/schema/__init__.py +28 -0
  20. tigrbl_core-0.4.3.dev4/tigrbl_core/schema/provenance.py +191 -0
  21. tigrbl_core-0.4.3.dev4/tigrbl_core/schema/provenance_inventory.py +249 -0
  22. tigrbl_core-0.4.3.dev4/tigrbl_core/schema/spec_json.py +19 -0
  23. tigrbl_core-0.4.3.dev4/tigrbl_core/schema/surface_chains.json +2842 -0
  24. tigrbl_core-0.4.2.dev4/README.md +0 -158
  25. tigrbl_core-0.4.2.dev4/tigrbl_core/schema/spec_json.py +0 -807
  26. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/LICENSE +0 -0
  27. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/NOTICE +0 -0
  28. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/alias_spec.py +0 -0
  29. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/column_spec.py +0 -0
  30. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/datatypes.py +0 -0
  31. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/docs_spec.py +0 -0
  32. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/engine_spec.py +0 -0
  33. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/field_spec.py +0 -0
  34. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/hook_spec.py +0 -0
  35. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/io_spec.py +0 -0
  36. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/middleware_spec.py +0 -0
  37. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/monotone.py +0 -0
  38. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/op_utils.py +0 -0
  39. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/plugins.py +0 -0
  40. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/registry.py +0 -0
  41. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/request_spec.py +0 -0
  42. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/response_resolver.py +0 -0
  43. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/response_spec.py +0 -0
  44. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/response_types.py +0 -0
  45. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/schema_spec.py +0 -0
  46. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/serde.py +0 -0
  47. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/session_spec.py +0 -0
  48. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/storage_spec.py +0 -0
  49. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/_spec/table_registry_spec.py +0 -0
  50. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/canonical_json.py +0 -0
  51. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/config/__init__.py +0 -0
  52. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/config/defaults.py +0 -0
  53. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/config/engine_traversal.py +0 -0
  54. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/config/resolver.py +0 -0
  55. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/core/__init__.py +0 -0
  56. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/op/__init__.py +0 -0
  57. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/op/canonical.py +0 -0
  58. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/op/collect.py +0 -0
  59. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/op/types.py +0 -0
  60. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/schema/builder/__init__.py +0 -0
  61. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/schema/builder/build_schema.py +0 -0
  62. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/schema/builder/cache.py +0 -0
  63. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/schema/builder/extras.py +0 -0
  64. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/schema/builder/helpers.py +0 -0
  65. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/schema/builder/list_params.py +0 -0
  66. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/schema/builder/strip_parent_fields.py +0 -0
  67. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/schema/get_schema.py +0 -0
  68. {tigrbl_core-0.4.2.dev4 → tigrbl_core-0.4.3.dev4}/tigrbl_core/schema/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tigrbl-core
3
- Version: 0.4.2.dev4
3
+ Version: 0.4.3.dev4
4
4
  Summary: Core Tigrbl framework specifications, decorators, schemas, hooks, operations, and primitives for schema-first APIs.
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -228,6 +228,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
228
228
  Requires-Dist: pydantic (>=2.10,<3)
229
229
  Requires-Dist: pyyaml
230
230
  Requires-Dist: tigrbl-typing
231
+ Requires-Dist: tigrbl_spec
231
232
  Requires-Dist: tomli (>=2.0.1) ; python_version < "3.11"
232
233
  Requires-Dist: tomli-w
233
234
  Project-URL: Discord, https://discord.gg/K4YTAPapjR
@@ -246,7 +247,7 @@ Description-Content-Type: text/markdown
246
247
  <a href="https://discord.gg/K4YTAPapjR"><img src="https://img.shields.io/badge/Discord-Join%20chat-5865F2?logo=discord&logoColor=white" alt="Discord community for tigrbl-core"/></a>
247
248
  <a href="https://github.com/tigrbl/tigrbl/blob/master/pkgs/core/tigrbl_core/README.md"><img src="https://hits.sh/github.com/tigrbl/tigrbl/blob/master/pkgs/core/tigrbl_core/README.md.svg?label=hits" alt="Repository hits for tigrbl-core README"/></a>
248
249
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-525252" alt="Apache 2.0 license"/></a>
249
- <a href="pyproject.toml"><img 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" alt="Python versions 3.10 | 3.11 | 3.12 | 3.13 | 3.14 for tigrbl-core"/></a>
250
+ <a href="pyproject.toml"><img src="https://img.shields.io/badge/python-3.10%2C%203.11%2C%203.12%2C%203.13%2C%203.14-3776ab" alt="Python versions 3.10 | 3.11 | 3.12 | 3.13 | 3.14 for tigrbl-core"/></a>
250
251
  <a href="https://github.com/tigrbl/tigrbl/blob/master/docs/README.md"><img src="https://img.shields.io/badge/workspace-core-1f6feb" alt="Workspace group for tigrbl-core"/></a>
251
252
  </div>
252
253
 
@@ -303,7 +304,7 @@ pip install tigrbl-core
303
304
  | Entry points | none declared |
304
305
  | Optional extras | none declared |
305
306
  | Legal files | `LICENSE`, `NOTICE` |
306
- | Supported Python | `3.10 | 3.11 | 3.12 | 3.13 | 3.14` |
307
+ | Supported Python | `3.10, 3.11, 3.12, 3.13, 3.14` |
307
308
 
308
309
  ## What It Owns
309
310
 
@@ -312,6 +313,13 @@ pip install tigrbl-core
312
313
  Implementation orientation:
313
314
  - `tigrbl_core`: _spec/, canonical_json, config/, core/, op/, schema/
314
315
 
316
+ Package catalog:
317
+ - `tigrbl_core/_spec/`: typed, serializable specifications for aliases, apps, bindings, columns, data types, docs, engines, fields, hooks, IO, middleware, operations, paths, requests, responses, routers, schemas, sessions, storage, tables, and table registries.
318
+ - `tigrbl_core/config/`: constants, defaults, resolver logic, and engine traversal helpers used when app, router, table, column, op, and request layers are merged.
319
+ - `tigrbl_core/op/`: canonical operation names, operation collection, and operation typing helpers.
320
+ - `tigrbl_core/schema/`: dynamic schema construction, schema cache helpers, extras handling, list-parameter support, schema JSON helpers, and `get_schema` access.
321
+ - `tigrbl_core/canonical_json.py`: deterministic JSON output used by docs, registry-like payloads, tests, and conformance artifacts.
322
+
315
323
  ## Public API and Import Surface
316
324
 
317
325
  - Import roots: `tigrbl_core`.
@@ -319,6 +327,77 @@ Implementation orientation:
319
327
  - Workspace dependencies: [`tigrbl-typing`](https://pypi.org/project/tigrbl-typing/).
320
328
  - External runtime dependencies: `pydantic>=2.10,<3`, `pyyaml`, `tomli-w`, `tomli>=2.0.1; python_version < '3.11'`.
321
329
 
330
+ ## Specification Model
331
+
332
+ The core package is the contract layer. It defines the vocabulary consumed by base abstractions, concrete adapters, atoms, kernel planning, runtime routing, docs generation, and the public facade. Most application code should not construct these specs manually; application code should normally use facade decorators and shortcuts. Extension packages use the specs when they need deterministic, testable configuration objects.
333
+
334
+ | Spec family | What it describes |
335
+ |---|---|
336
+ | `AppSpec`, `RouterSpec`, `TableSpec` | Container-level framework configuration and inheritance points. |
337
+ | `ColumnSpec`, `FieldSpec`, data type specs | Field semantics, validation, storage, schema projection, and data-type lowering. |
338
+ | `OpSpec` and op utilities | Operation name, alias, arity, binding, handler, schema, hook, response, and runtime intent. |
339
+ | `HookSpec` and hook types | Hook targets, phases, predicates, ordering, and callable registration shape. |
340
+ | `SchemaSpec`, `RequestSpec`, `ResponseSpec`, `IoSpec` | Input/output envelope behavior, request extraction, response shaping, and Pydantic model generation. |
341
+ | `BindingSpec` | REST, JSON-RPC, stream, SSE, WebSocket, WSS, and WebTransport binding metadata. |
342
+ | `EngineSpec`, `SessionSpec`, `StorageSpec` | Engine/provider/session/storage configuration without importing concrete engine implementations. |
343
+ | `DocsSpec`, `PathSpec`, `MiddlewareSpec` | Documentation projection, route paths, and middleware configuration. |
344
+
345
+ ## Operation Semantics
346
+
347
+ `tigrbl_core.op.canonical.DEFAULT_CANON_VERBS` is the default CRUD set:
348
+
349
+ ```text
350
+ create, read, update, replace, delete, list, clear
351
+ ```
352
+
353
+ Tables can change canonical wiring through mode/include/exclude attributes or a `should_wire_canonical(op)` helper. Core only decides whether an operation is part of the desired specification. Concrete packages and operation packs supply the actual handlers and routing behavior.
354
+
355
+ Use this package when you need to inspect or build operation specs before runtime compilation. Use `tigrbl` when you simply want a working app surface.
356
+
357
+ ## Binding and Transport Semantics
358
+
359
+ `BindingSpec` keeps four concerns distinct:
360
+
361
+ - protocol or binding kind, such as HTTP REST, HTTP JSON-RPC, HTTP stream, SSE, WebSocket, WSS, or WebTransport;
362
+ - exchange shape, such as request/response, server stream, bidirectional stream, client stream, server stream, session, or datagram;
363
+ - framing, such as JSON, JSON-RPC, SSE, WebSocket text, stream framing, or WebTransport outer framing;
364
+ - runtime lane metadata, especially for WebTransport session, stream, and datagram behavior.
365
+
366
+ This separation is deliberate. Extension authors should not collapse protocol support into a single string or infer framing from the transport name. Invalid combinations should remain explicit validation failures so runtime behavior is fail-closed.
367
+
368
+ ## Configuration Precedence
369
+
370
+ Core resolvers use this precedence pattern:
371
+
372
+ ```text
373
+ request override > operation spec > column spec > table spec > router spec > app spec > defaults
374
+ ```
375
+
376
+ The most specific layer wins. Keep default policy broad, then narrow behavior by table, column, and operation. Avoid hidden mutation of spec objects after a runtime plan has been compiled; build a fresh spec or invalidate the relevant cache when behavior truly changes.
377
+
378
+ ## Schema Construction
379
+
380
+ Schema helpers build operation-specific request and response models from table metadata, column specs, request/response extras, list-parameter rules, and op-level configuration. `get_schema(...)` is the stable way to retrieve the generated model for a table operation and direction. Prefer it over hand-writing duplicate Pydantic envelopes when data belongs to a Tigrbl operation.
381
+
382
+ Best practices for schema work:
383
+ - Keep storage fields, wire fields, and virtual extras separate.
384
+ - Put reusable schema behavior in table or column specs; reserve op specs for operation-specific differences.
385
+ - Use canonical JSON helpers when writing deterministic docs or evidence artifacts.
386
+ - Treat generated schemas as projections of the specs, not as the source of truth.
387
+
388
+ ## Extension Guidance
389
+
390
+ - Depend on `tigrbl-core` when you need spec classes, op collection, schema generation, or config resolution without concrete app/router/runtime imports.
391
+ - Keep specs serializable and deterministic. Do not attach live database sessions, request objects, or transport handles to core specs.
392
+ - Validate protocol and binding assumptions in core or kernel-facing tests before adding runtime behavior.
393
+ - Keep application-facing convenience APIs in `tigrbl` or `tigrbl-concrete`; keep cross-package contracts here.
394
+
395
+ Authoring BCP for this boundary:
396
+ - Do treat `ColumnSpec`, `FieldSpec`, `OpSpec`, `HookSpec`, `SchemaSpec`, `BindingSpec`, `EngineSpec`, `SessionSpec`, and related specs as the contract vocabulary that other Tigrbl packages consume.
397
+ - Do keep specs independent of FastAPI, Starlette, SQLAlchemy sessions, live request objects, and transport handles.
398
+ - Do not move application route authoring, direct database calls, concrete engine creation, or runtime dispatch side effects into `tigrbl-core`.
399
+ - Avoid duplicating spec fields in helper classes or generated schemas. Specs should remain the source that schema, docs, kernel, runtime, base, concrete, and facade layers project from.
400
+
322
401
  ## Usage Examples
323
402
 
324
403
  ### Verify the installed package
@@ -379,6 +458,8 @@ Choose `tigrbl-core` when the quick-answer table matches your use case. Choose [
379
458
  - [Package layout](https://github.com/tigrbl/tigrbl/blob/master/docs/developer/PACKAGE_LAYOUT.md)
380
459
  - [Current target](https://github.com/tigrbl/tigrbl/blob/master/docs/conformance/CURRENT_TARGET.md)
381
460
  - [Current state](https://github.com/tigrbl/tigrbl/blob/master/docs/conformance/CURRENT_STATE.md)
461
+ - [Next steps](https://github.com/tigrbl/tigrbl/blob/master/docs/conformance/NEXT_STEPS.md)
462
+ - [Documentation pointers](https://github.com/tigrbl/tigrbl/blob/master/docs/governance/DOC_POINTERS.md)
382
463
  - [SSOT registry](https://github.com/tigrbl/tigrbl/blob/master/.ssot/registry.json)
383
464
  - [Release workflow](https://github.com/tigrbl/tigrbl/actions/workflows/publish.yml)
384
465
 
@@ -390,7 +471,7 @@ Choose `tigrbl-core` when the quick-answer table matches your use case. Choose [
390
471
 
391
472
  ## Package-local Boundary
392
473
 
393
- This README is the package-local distribution entry point for `tigrbl-core`. It answers install, usage, API, ownership, and certification-orientation questions for this package. Broader architectural decisions, release status, and cross-package proof chains remain in the repository-level docs and SSOT registry.
474
+ This file is a package-local distribution entry point. This README is the package-local distribution entry point for `tigrbl-core`. It answers install, usage, API, ownership, and certification-orientation questions for this package. Broader architectural decisions, release status, and cross-package proof chains remain in the repository-level docs and SSOT registry.
394
475
 
395
476
  ## License
396
477
 
@@ -0,0 +1,238 @@
1
+ <div align="center">
2
+ <h1>tigrbl-core</h1>
3
+ <img src="https://raw.githubusercontent.com/swarmauri/swarmauri-sdk/master/assets/tigrbl_full_logo.png" alt="Tigrbl logo" width="140"/>
4
+ <p><strong>Core Tigrbl framework specifications, decorators, schemas, hooks, operations, and primitives for schema-first APIs.</strong></p>
5
+ <a href="https://pypi.org/project/tigrbl-core/"><img src="https://img.shields.io/pypi/v/tigrbl-core?label=PyPI" alt="PyPI version for tigrbl-core"/></a>
6
+ <a href="https://pypi.org/project/tigrbl-core/"><img src="https://static.pepy.tech/badge/tigrbl-core" alt="Downloads for tigrbl-core"/></a>
7
+ <a href="https://discord.gg/K4YTAPapjR"><img src="https://img.shields.io/badge/Discord-Join%20chat-5865F2?logo=discord&logoColor=white" alt="Discord community for tigrbl-core"/></a>
8
+ <a href="https://github.com/tigrbl/tigrbl/blob/master/pkgs/core/tigrbl_core/README.md"><img src="https://hits.sh/github.com/tigrbl/tigrbl/blob/master/pkgs/core/tigrbl_core/README.md.svg?label=hits" alt="Repository hits for tigrbl-core README"/></a>
9
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-525252" alt="Apache 2.0 license"/></a>
10
+ <a href="pyproject.toml"><img src="https://img.shields.io/badge/python-3.10%2C%203.11%2C%203.12%2C%203.13%2C%203.14-3776ab" alt="Python versions 3.10 | 3.11 | 3.12 | 3.13 | 3.14 for tigrbl-core"/></a>
11
+ <a href="https://github.com/tigrbl/tigrbl/blob/master/docs/README.md"><img src="https://img.shields.io/badge/workspace-core-1f6feb" alt="Workspace group for tigrbl-core"/></a>
12
+ </div>
13
+
14
+ ## What is tigrbl-core?
15
+
16
+ Core Tigrbl framework specifications, decorators, schemas, hooks, operations, and primitives for schema-first APIs.
17
+
18
+ ## Why use tigrbl-core?
19
+
20
+ Use it when you need this foundational Tigrbl layer directly as a small, focused dependency.
21
+
22
+ ## When should I install tigrbl-core?
23
+
24
+ Install it for extension packages, package-local tests, or internals that need this boundary without the whole facade.
25
+
26
+ ## Who is tigrbl-core for?
27
+
28
+ Framework maintainers, extension authors, and advanced users composing Tigrbl from split packages.
29
+
30
+ ## Where does tigrbl-core fit?
31
+
32
+ `tigrbl-core` lives at `pkgs/core/tigrbl_core` and serves a focused layer in the split Tigrbl framework.
33
+
34
+ ## How does tigrbl-core work?
35
+
36
+ It owns a narrow layer in the split workspace and is consumed by higher-level packages through explicit dependencies.
37
+
38
+ ## Certification Status
39
+
40
+ - Package status: governed package in the `tigrbl/tigrbl` workspace.
41
+ - Governance source: [SSOT registry](https://github.com/tigrbl/tigrbl/blob/master/.ssot/registry.json).
42
+ - Release evidence: [publish workflow](https://github.com/tigrbl/tigrbl/actions/workflows/publish.yml) validates package builds, tests, GitHub release assets, and PyPI publication for managed packages.
43
+ - Local certification guard: `pkgs/core/tigrbl_tests/tests/unit/test_package_badges_and_notices.py` verifies every package README keeps the Discord badge, Apache 2.0 badge, explicit Python-version badge, `LICENSE`, and `NOTICE`.
44
+ - Scope note: this README documents the package boundary. Runtime feature support remains governed by `.ssot/` entities and the conformance docs linked below.
45
+
46
+ ## Install
47
+
48
+ ```bash
49
+ uv add tigrbl-core
50
+ ```
51
+
52
+ ```bash
53
+ pip install tigrbl-core
54
+ ```
55
+
56
+ ## Surface Coverage
57
+
58
+ | Surface | Value |
59
+ |---|---|
60
+ | PyPI package | [`tigrbl-core`](https://pypi.org/project/tigrbl-core/) |
61
+ | Repository path | [`pkgs/core/tigrbl_core`](https://github.com/tigrbl/tigrbl/tree/master/pkgs/core/tigrbl_core) |
62
+ | Python import root | `tigrbl_core` |
63
+ | Console scripts | none declared |
64
+ | Entry points | none declared |
65
+ | Optional extras | none declared |
66
+ | Legal files | `LICENSE`, `NOTICE` |
67
+ | Supported Python | `3.10, 3.11, 3.12, 3.13, 3.14` |
68
+
69
+ ## What It Owns
70
+
71
+ `tigrbl-core` owns the `foundational framework package` boundary. It should be installed when you need this package's focused responsibility without assuming every other Tigrbl workspace package is present.
72
+
73
+ Implementation orientation:
74
+ - `tigrbl_core`: _spec/, canonical_json, config/, core/, op/, schema/
75
+
76
+ Package catalog:
77
+ - `tigrbl_core/_spec/`: typed, serializable specifications for aliases, apps, bindings, columns, data types, docs, engines, fields, hooks, IO, middleware, operations, paths, requests, responses, routers, schemas, sessions, storage, tables, and table registries.
78
+ - `tigrbl_core/config/`: constants, defaults, resolver logic, and engine traversal helpers used when app, router, table, column, op, and request layers are merged.
79
+ - `tigrbl_core/op/`: canonical operation names, operation collection, and operation typing helpers.
80
+ - `tigrbl_core/schema/`: dynamic schema construction, schema cache helpers, extras handling, list-parameter support, schema JSON helpers, and `get_schema` access.
81
+ - `tigrbl_core/canonical_json.py`: deterministic JSON output used by docs, registry-like payloads, tests, and conformance artifacts.
82
+
83
+ ## Public API and Import Surface
84
+
85
+ - Import roots: `tigrbl_core`.
86
+ - Public symbols: public surface is module-oriented; import the package boundary and inspect submodules as needed.
87
+ - Workspace dependencies: [`tigrbl-typing`](https://pypi.org/project/tigrbl-typing/).
88
+ - External runtime dependencies: `pydantic>=2.10,<3`, `pyyaml`, `tomli-w`, `tomli>=2.0.1; python_version < '3.11'`.
89
+
90
+ ## Specification Model
91
+
92
+ The core package is the contract layer. It defines the vocabulary consumed by base abstractions, concrete adapters, atoms, kernel planning, runtime routing, docs generation, and the public facade. Most application code should not construct these specs manually; application code should normally use facade decorators and shortcuts. Extension packages use the specs when they need deterministic, testable configuration objects.
93
+
94
+ | Spec family | What it describes |
95
+ |---|---|
96
+ | `AppSpec`, `RouterSpec`, `TableSpec` | Container-level framework configuration and inheritance points. |
97
+ | `ColumnSpec`, `FieldSpec`, data type specs | Field semantics, validation, storage, schema projection, and data-type lowering. |
98
+ | `OpSpec` and op utilities | Operation name, alias, arity, binding, handler, schema, hook, response, and runtime intent. |
99
+ | `HookSpec` and hook types | Hook targets, phases, predicates, ordering, and callable registration shape. |
100
+ | `SchemaSpec`, `RequestSpec`, `ResponseSpec`, `IoSpec` | Input/output envelope behavior, request extraction, response shaping, and Pydantic model generation. |
101
+ | `BindingSpec` | REST, JSON-RPC, stream, SSE, WebSocket, WSS, and WebTransport binding metadata. |
102
+ | `EngineSpec`, `SessionSpec`, `StorageSpec` | Engine/provider/session/storage configuration without importing concrete engine implementations. |
103
+ | `DocsSpec`, `PathSpec`, `MiddlewareSpec` | Documentation projection, route paths, and middleware configuration. |
104
+
105
+ ## Operation Semantics
106
+
107
+ `tigrbl_core.op.canonical.DEFAULT_CANON_VERBS` is the default CRUD set:
108
+
109
+ ```text
110
+ create, read, update, replace, delete, list, clear
111
+ ```
112
+
113
+ Tables can change canonical wiring through mode/include/exclude attributes or a `should_wire_canonical(op)` helper. Core only decides whether an operation is part of the desired specification. Concrete packages and operation packs supply the actual handlers and routing behavior.
114
+
115
+ Use this package when you need to inspect or build operation specs before runtime compilation. Use `tigrbl` when you simply want a working app surface.
116
+
117
+ ## Binding and Transport Semantics
118
+
119
+ `BindingSpec` keeps four concerns distinct:
120
+
121
+ - protocol or binding kind, such as HTTP REST, HTTP JSON-RPC, HTTP stream, SSE, WebSocket, WSS, or WebTransport;
122
+ - exchange shape, such as request/response, server stream, bidirectional stream, client stream, server stream, session, or datagram;
123
+ - framing, such as JSON, JSON-RPC, SSE, WebSocket text, stream framing, or WebTransport outer framing;
124
+ - runtime lane metadata, especially for WebTransport session, stream, and datagram behavior.
125
+
126
+ This separation is deliberate. Extension authors should not collapse protocol support into a single string or infer framing from the transport name. Invalid combinations should remain explicit validation failures so runtime behavior is fail-closed.
127
+
128
+ ## Configuration Precedence
129
+
130
+ Core resolvers use this precedence pattern:
131
+
132
+ ```text
133
+ request override > operation spec > column spec > table spec > router spec > app spec > defaults
134
+ ```
135
+
136
+ The most specific layer wins. Keep default policy broad, then narrow behavior by table, column, and operation. Avoid hidden mutation of spec objects after a runtime plan has been compiled; build a fresh spec or invalidate the relevant cache when behavior truly changes.
137
+
138
+ ## Schema Construction
139
+
140
+ Schema helpers build operation-specific request and response models from table metadata, column specs, request/response extras, list-parameter rules, and op-level configuration. `get_schema(...)` is the stable way to retrieve the generated model for a table operation and direction. Prefer it over hand-writing duplicate Pydantic envelopes when data belongs to a Tigrbl operation.
141
+
142
+ Best practices for schema work:
143
+ - Keep storage fields, wire fields, and virtual extras separate.
144
+ - Put reusable schema behavior in table or column specs; reserve op specs for operation-specific differences.
145
+ - Use canonical JSON helpers when writing deterministic docs or evidence artifacts.
146
+ - Treat generated schemas as projections of the specs, not as the source of truth.
147
+
148
+ ## Extension Guidance
149
+
150
+ - Depend on `tigrbl-core` when you need spec classes, op collection, schema generation, or config resolution without concrete app/router/runtime imports.
151
+ - Keep specs serializable and deterministic. Do not attach live database sessions, request objects, or transport handles to core specs.
152
+ - Validate protocol and binding assumptions in core or kernel-facing tests before adding runtime behavior.
153
+ - Keep application-facing convenience APIs in `tigrbl` or `tigrbl-concrete`; keep cross-package contracts here.
154
+
155
+ Authoring BCP for this boundary:
156
+ - Do treat `ColumnSpec`, `FieldSpec`, `OpSpec`, `HookSpec`, `SchemaSpec`, `BindingSpec`, `EngineSpec`, `SessionSpec`, and related specs as the contract vocabulary that other Tigrbl packages consume.
157
+ - Do keep specs independent of FastAPI, Starlette, SQLAlchemy sessions, live request objects, and transport handles.
158
+ - Do not move application route authoring, direct database calls, concrete engine creation, or runtime dispatch side effects into `tigrbl-core`.
159
+ - Avoid duplicating spec fields in helper classes or generated schemas. Specs should remain the source that schema, docs, kernel, runtime, base, concrete, and facade layers project from.
160
+
161
+ ## Usage Examples
162
+
163
+ ### Verify the installed package
164
+
165
+ ```bash
166
+ python -m pip show tigrbl-core
167
+ python - <<'PY'
168
+ from importlib.metadata import version
169
+ print(version("tigrbl-core"))
170
+ PY
171
+ ```
172
+
173
+ ### Import the package boundary
174
+
175
+ ```python
176
+ import importlib
177
+
178
+ module = importlib.import_module("tigrbl_core._spec")
179
+ print(module.__name__)
180
+ ```
181
+
182
+ ### Inspect available modules
183
+
184
+ ```python
185
+ import importlib
186
+ import pkgutil
187
+
188
+ module = importlib.import_module("tigrbl_core._spec")
189
+ for info in pkgutil.iter_modules(getattr(module, "__path__", [])):
190
+ print(info.name)
191
+ ```
192
+
193
+ ### Use with the facade when building applications
194
+
195
+ ```bash
196
+ uv add tigrbl tigrbl-core
197
+ python - <<'PY'
198
+ import tigrbl
199
+ print(tigrbl.__name__)
200
+ PY
201
+ ```
202
+
203
+ ## How To Choose This Package
204
+
205
+ Choose `tigrbl-core` when the quick-answer table matches your use case. Choose [`tigrbl`](https://pypi.org/project/tigrbl/) instead when you want the full public facade. Choose a lower-level package such as [`tigrbl-core`](https://pypi.org/project/tigrbl-core/), [`tigrbl-base`](https://pypi.org/project/tigrbl-base/), or [`tigrbl-runtime`](https://pypi.org/project/tigrbl-runtime/) when you are building framework extensions or testing a specific internal boundary.
206
+
207
+ ## Related Packages
208
+
209
+ - [`tigrbl-typing`](https://pypi.org/project/tigrbl-typing/)
210
+ - [`tigrbl`](https://pypi.org/project/tigrbl/)
211
+ - [`tigrbl-base`](https://pypi.org/project/tigrbl-base/)
212
+ - [`tigrbl-runtime`](https://pypi.org/project/tigrbl-runtime/)
213
+
214
+ ## Documentation Links
215
+
216
+ - [Workspace docs](https://github.com/tigrbl/tigrbl/blob/master/docs/README.md)
217
+ - [Package catalog](https://github.com/tigrbl/tigrbl/blob/master/docs/developer/PACKAGE_CATALOG.md)
218
+ - [Package layout](https://github.com/tigrbl/tigrbl/blob/master/docs/developer/PACKAGE_LAYOUT.md)
219
+ - [Current target](https://github.com/tigrbl/tigrbl/blob/master/docs/conformance/CURRENT_TARGET.md)
220
+ - [Current state](https://github.com/tigrbl/tigrbl/blob/master/docs/conformance/CURRENT_STATE.md)
221
+ - [Next steps](https://github.com/tigrbl/tigrbl/blob/master/docs/conformance/NEXT_STEPS.md)
222
+ - [Documentation pointers](https://github.com/tigrbl/tigrbl/blob/master/docs/governance/DOC_POINTERS.md)
223
+ - [SSOT registry](https://github.com/tigrbl/tigrbl/blob/master/.ssot/registry.json)
224
+ - [Release workflow](https://github.com/tigrbl/tigrbl/actions/workflows/publish.yml)
225
+
226
+ ## Support
227
+
228
+ - Community: [Discord](https://discord.gg/K4YTAPapjR).
229
+ - Issues: [GitHub Issues](https://github.com/tigrbl/tigrbl/issues).
230
+ - Repository: [pkgs/core/tigrbl_core](https://github.com/tigrbl/tigrbl/tree/master/pkgs/core/tigrbl_core).
231
+
232
+ ## Package-local Boundary
233
+
234
+ This file is a package-local distribution entry point. This README is the package-local distribution entry point for `tigrbl-core`. It answers install, usage, API, ownership, and certification-orientation questions for this package. Broader architectural decisions, release status, and cross-package proof chains remain in the repository-level docs and SSOT registry.
235
+
236
+ ## License
237
+
238
+ Licensed under the Apache License, Version 2.0. See `LICENSE`, `NOTICE`, and the official [Apache 2.0 license text](https://www.apache.org/licenses/LICENSE-2.0).
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tigrbl-core"
3
- version = "0.4.2.dev4"
3
+ version = "0.4.3.dev4"
4
4
  description = "Core Tigrbl framework specifications, decorators, schemas, hooks, operations, and primitives for schema-first APIs."
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }
@@ -42,6 +42,7 @@ requires-python = ">=3.10,<3.15"
42
42
  authors = [{ name = "Jacob Stewart", email = "jacob@swarmauri.com" }]
43
43
 
44
44
  dependencies = [
45
+ "tigrbl_spec",
45
46
  "tigrbl-typing",
46
47
  "pydantic>=2.10,<3",
47
48
  "pyyaml",
@@ -59,6 +60,7 @@ Issues = "https://github.com/tigrbl/tigrbl/issues"
59
60
 
60
61
  [tool.uv.sources]
61
62
  "tigrbl-typing" = { workspace = true }
63
+ "tigrbl_spec" = { workspace = true }
62
64
 
63
65
  [build-system]
64
66
  requires = ["poetry-core>=1.0.0"]
@@ -29,6 +29,8 @@ _EXPORTS = {
29
29
  "HttpStreamBindingSpec": "binding_spec",
30
30
  "SseBindingSpec": "binding_spec",
31
31
  "WebTransportBindingSpec": "binding_spec",
32
+ "WELL_KNOWN_PREFIX": "well_known_spec",
33
+ "WellKnownResourceSpec": "well_known_spec",
32
34
  "WsBindingSpec": "binding_spec",
33
35
  "resolve_rest_nested_prefix": "binding_spec",
34
36
  "ColumnSpec": "column_spec",
@@ -80,6 +82,8 @@ _EXPORTS = {
80
82
  "validate_app_framing_for_binding": "binding_spec",
81
83
  "validate_binding_profile_exchange": "binding_spec",
82
84
  "validate_path_binding": "path_spec",
85
+ "normalize_well_known_name": "well_known_spec",
86
+ "well_known_path": "well_known_spec",
83
87
  "PHASE": "op_spec",
84
88
  "PHASES": "op_spec",
85
89
  "HookPhase": "hook_spec",
@@ -106,7 +110,39 @@ _EXPORTS = {
106
110
  "TypeAdapter": "datatypes",
107
111
  "TypeRegistry": "datatypes",
108
112
  "TableSpec": "table_spec",
113
+ "BindingToken": "table_profile_bindings",
114
+ "LoweredBinding": "table_profile_bindings",
115
+ "lower_binding_tokens_for_ops": "table_profile_bindings",
116
+ "lower_default_bindings_for_op": "table_profile_bindings",
117
+ "lower_table_profile_bindings": "table_profile_bindings",
118
+ "TableProfileSpec": "table_profile_spec",
119
+ "BuiltinTableProfile": "table_profile_spec",
120
+ "BUILTIN_TABLE_PROFILE_DEFINITIONS": "table_profile_spec",
121
+ "BUILTIN_TABLE_PROFILE_KINDS": "table_profile_spec",
122
+ "TableProfileError": "table_profile_spec",
123
+ "TableProfileBindingFamily": "table_profile_spec",
124
+ "TableProfileRole": "table_profile_spec",
125
+ "PLAIN_TABLE_PROFILE": "table_profile_spec",
126
+ "CRUD_TABLE_PROFILE": "table_profile_spec",
127
+ "REALTIME_TABLE_PROFILE": "table_profile_spec",
128
+ "coerce_table_profile": "table_profile_spec",
129
+ "get_builtin_table_profile_definition": "table_profile_spec",
130
+ "get_table_profile": "table_profile_spec",
131
+ "iter_builtin_table_profile_definitions": "table_profile_spec",
132
+ "make_builtin_table_profile": "table_profile_spec",
133
+ "register_table_profile": "table_profile_spec",
109
134
  "TableRegistrySpec": "table_registry_spec",
135
+ "BINDING_STACK_PROJECTIONS": "transport_stack",
136
+ "BindingStackError": "transport_stack",
137
+ "BindingStackProjection": "transport_stack",
138
+ "binding_stack_maturity": "transport_stack",
139
+ "classify_binding_stack": "transport_stack",
140
+ "compose_h3_binding_projections": "transport_stack",
141
+ "require_binding_stack": "transport_stack",
142
+ "ExposureDecision": "exposure_policy",
143
+ "ExposurePolicyError": "exposure_policy",
144
+ "exposed_surfaces": "exposure_policy",
145
+ "resolve_exposure_policy": "exposure_policy",
110
146
  }
111
147
 
112
148
  __all__ = list(_EXPORTS)
@@ -2,10 +2,12 @@
2
2
  from __future__ import annotations
3
3
  from dataclasses import dataclass, field
4
4
  from typing import Any, Callable, Optional, Sequence
5
+ import warnings
5
6
 
6
7
  from .._spec.engine_spec import EngineCfg, EngineSpec
7
8
  from .._spec.monotone import as_tuple, merge_mro_sequence_attr
8
9
  from .._spec.response_spec import ResponseSpec
10
+ from .._spec.well_known_spec import WellKnownResourceSpec
9
11
  from .serde import SerdeMixin
10
12
 
11
13
 
@@ -45,12 +47,15 @@ def normalize_app_spec(spec: "AppSpec") -> "AppSpec":
45
47
  title=str(spec.title or "Tigrbl"),
46
48
  description=spec.description,
47
49
  version=str(spec.version or "0.1.0"),
48
- execution_backend=str(getattr(spec, "execution_backend", None) or "auto"),
50
+ execution_backend=normalize_execution_backend(
51
+ getattr(spec, "execution_backend", None),
52
+ ),
49
53
  engine=spec.engine,
50
54
  engine_name=spec.engine_name,
51
55
  engines=_seqify(spec.engines),
52
56
  routers=routers,
53
57
  ops=ops,
58
+ well_known=_seqify(spec.well_known),
54
59
  tables=tables,
55
60
  schemas=_seqify(spec.schemas),
56
61
  hooks=_seqify(spec.hooks),
@@ -64,6 +69,23 @@ def normalize_app_spec(spec: "AppSpec") -> "AppSpec":
64
69
  )
65
70
 
66
71
 
72
+ def normalize_execution_backend(value: Any) -> str:
73
+ lowered = str(value or "auto").strip().lower()
74
+ if not lowered:
75
+ return "auto"
76
+ if lowered == "rust":
77
+ warnings.warn(
78
+ "AppSpec.execution_backend='rust' is deprecated; "
79
+ "Tigrbl runtime execution is Python-only.",
80
+ DeprecationWarning,
81
+ stacklevel=2,
82
+ )
83
+ return "python"
84
+ if lowered in {"auto", "python"}:
85
+ return lowered
86
+ raise ValueError(f"unsupported execution backend: {value!r}")
87
+
88
+
67
89
  @dataclass(eq=False)
68
90
  class AppSpec(SerdeMixin):
69
91
  """
@@ -83,6 +105,7 @@ class AppSpec(SerdeMixin):
83
105
 
84
106
  # NEW: orchestration/topology knobs
85
107
  ops: Sequence[Any] = field(default_factory=tuple) # op descriptors or specs
108
+ well_known: Sequence[WellKnownResourceSpec] = field(default_factory=tuple)
86
109
  tables: Sequence[Any] = field(default_factory=tuple) # table refs owned by app
87
110
  schemas: Sequence[Any] = field(default_factory=tuple) # schema classes/defs
88
111
  hooks: Sequence[Callable[..., Any]] = field(default_factory=tuple)
@@ -103,9 +126,11 @@ class AppSpec(SerdeMixin):
103
126
  lifespan: Optional[Callable[..., Any]] = None
104
127
 
105
128
  def __post_init__(self) -> None:
129
+ self.execution_backend = normalize_execution_backend(self.execution_backend)
106
130
  self.engines = _seqify(self.engines)
107
131
  self.routers = _seqify(self.routers)
108
132
  self.ops = _seqify(self.ops)
133
+ self.well_known = _seqify(self.well_known)
109
134
  self.tables = _seqify(self.tables)
110
135
  self.schemas = _seqify(self.schemas)
111
136
  self.hooks = _seqify(self.hooks)
@@ -113,6 +138,14 @@ class AppSpec(SerdeMixin):
113
138
  self.deps = _seqify(self.deps)
114
139
  self.middlewares = _seqify(self.middlewares)
115
140
 
141
+ for resource in self.well_known:
142
+ if isinstance(resource, str):
143
+ raise TypeError("AppSpec.well_known entries must be nested specs, not strings.")
144
+ if not isinstance(resource, WellKnownResourceSpec):
145
+ raise TypeError(
146
+ "AppSpec.well_known entries must be WellKnownResourceSpec; "
147
+ f"got {type(resource).__name__}."
148
+ )
116
149
  validate_engine_inventory(self.engines)
117
150
  validate_engine_name_binding(
118
151
  self.engine_name,
@@ -172,6 +205,8 @@ class AppSpec(SerdeMixin):
172
205
 
173
206
  @classmethod
174
207
  def from_dict(cls, payload: dict[str, Any]) -> "AppSpec":
208
+ if "routes" in payload:
209
+ raise ValueError("AppSpec does not accept 'routes'; use path-owned specs.")
175
210
  return super().from_dict(payload)
176
211
 
177
212
  @classmethod
@@ -255,6 +290,7 @@ class AppSpec(SerdeMixin):
255
290
  or ()
256
291
  ),
257
292
  ops=tuple(merge_seq_attr(app, "OPS") or ()),
293
+ well_known=tuple(merge_seq_attr(app, "WELL_KNOWN") or ()),
258
294
  tables=tuple(merge_seq_attr(app, "TABLES") or ()),
259
295
  schemas=tuple(merge_seq_attr(app, "SCHEMAS") or ()),
260
296
  hooks=tuple(merge_seq_attr(app, "HOOKS") or ()),
@@ -277,6 +313,7 @@ class AppSpec(SerdeMixin):
277
313
  engines=tuple(spec.engines or ()),
278
314
  routers=tuple(spec.routers or ()),
279
315
  ops=tuple(spec.ops or ()),
316
+ well_known=tuple(spec.well_known or ()),
280
317
  tables=tuple(spec.tables or ()),
281
318
  schemas=tuple(spec.schemas or ()),
282
319
  hooks=tuple(spec.hooks or ()),