cello-framework 1.2.3__tar.gz → 1.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cello_framework-1.2.3 → cello_framework-1.3.0}/CLAUDE.md +38 -3
- {cello_framework-1.2.3 → cello_framework-1.3.0}/Cargo.lock +354 -418
- {cello_framework-1.2.3 → cello_framework-1.3.0}/Cargo.toml +21 -5
- {cello_framework-1.2.3 → cello_framework-1.3.0}/ENTERPRISE_ROADMAP.md +59 -104
- {cello_framework-1.2.3 → cello_framework-1.3.0}/PKG-INFO +14 -13
- {cello_framework-1.2.3 → cello_framework-1.3.0}/README.md +13 -12
- {cello_framework-1.2.3 → cello_framework-1.3.0}/benchmarks/README.md +27 -34
- {cello_framework-1.2.3 → cello_framework-1.3.0}/cello.md +14 -15
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/community/index.md +0 -9
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/community/support.md +3 -3
- cello_framework-1.3.0/docs/data-layer.md +203 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/enterprise/roadmap.md +3 -8
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/basic/hello-world.md +3 -3
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/basic/rest-api.md +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/advanced-patterns.md +6 -6
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/all-features.md +9 -9
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/api-protocols.md +3 -3
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/auto-openapi.md +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/blueprints-advanced.md +3 -3
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/cluster-demo.md +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/complete-showcase.md +4 -4
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/comprehensive-demo.md +17 -23
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/database-demo.md +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/enterprise-config.md +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/hello-world.md +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/middleware-demo.md +3 -3
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/security.md +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/streaming-sse.md +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/advanced/dependency-injection.md +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/advanced/dto-validation.md +36 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/core/async.md +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/core/blueprints.md +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/core/responses.md +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/index.md +23 -27
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/getting-started/configuration.md +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/getting-started/first-app.md +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/getting-started/index.md +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/index.md +44 -52
- cello_framework-1.3.0/docs/issue-5-answer.md +162 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/javascripts/extra.js +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/learn/guides/performance.md +2 -3
- cello_framework-1.3.0/docs/middleware.md +125 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/overrides/main.html +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/reference/api/app.md +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/reference/api/blueprint.md +1 -1
- cello_framework-1.3.0/docs/reference/api/plugins.md +199 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/reference/index.md +1 -1
- cello_framework-1.3.0/docs/releases/index.md +317 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/v0.3.0.md +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/v0.5.0.md +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/v1.0.0.md +8 -49
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/v1.0.1.md +8 -49
- cello_framework-1.3.0/docs/releases/v1.2.4.md +107 -0
- cello_framework-1.3.0/docs/releases/v1.3.0.md +258 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/advanced.py +3 -3
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/advanced_middleware.py +6 -7
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/advanced_patterns_demo.py +6 -6
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/all_features_demo.py +9 -9
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/api_protocols_demo.py +3 -3
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/auto_openapi_demo.py +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/cluster_demo.py +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/complete_showcase.py +4 -4
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/comprehensive_demo.py +17 -23
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/database_demo.py +3 -3
- cello_framework-1.3.0/examples/database_orm_demo.py +179 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/enterprise.py +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/hello.py +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/middleware_demo.py +3 -3
- cello_framework-1.3.0/examples/middleware_full_demo.py +74 -0
- cello_framework-1.3.0/examples/plugins_demo.py +93 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/security.py +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/simple_api.py +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/streaming_demo.py +2 -2
- cello_framework-1.3.0/examples/three_pillars_demo.py +69 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/mkdocs.yml +3 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/pyproject.toml +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/python/cello/__init__.py +175 -58
- cello_framework-1.3.0/python/cello/database.py +83 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/python/cello/middleware.py +4 -0
- cello_framework-1.3.0/python/cello/orm.py +639 -0
- cello_framework-1.3.0/python/cello/validation.py +169 -0
- cello_framework-1.3.0/src/async_loop.rs +88 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/background.rs +1 -1
- cello_framework-1.3.0/src/db/mod.rs +13 -0
- cello_framework-1.3.0/src/db/postgres.rs +303 -0
- cello_framework-1.3.0/src/db/redis_client.rs +417 -0
- cello_framework-1.3.0/src/db/value.rs +215 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/dependency.rs +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/dto.rs +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/handler.rs +21 -15
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/http_client.rs +1 -3
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/json.rs +14 -4
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/lib.rs +388 -139
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/lifecycle.rs +3 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/auth.rs +40 -9
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/body_limit.rs +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/cache.rs +49 -8
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/cors.rs +8 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/csrf.rs +67 -18
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/etag.rs +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/exception_handler.rs +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/graphql.rs +6 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/guards.rs +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/health.rs +9 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/mod.rs +90 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/prometheus.rs +20 -3
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/static_files.rs +1 -3
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/telemetry.rs +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/minijinja_engine.rs +10 -12
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/openapi.rs +2 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/request/mod.rs +32 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/response/mod.rs +22 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/response/streaming.rs +8 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/server/cluster.rs +3 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/server/mod.rs +269 -40
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/sse.rs +40 -2
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/template.rs +1 -1
- {cello_framework-1.2.3 → cello_framework-1.3.0}/tests/test_cello.py +45 -403
- cello_framework-1.3.0/tests/test_middleware.py +149 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/tests/test_minijinja.py +1 -1
- cello_framework-1.3.0/tests/test_native_db.py +246 -0
- cello_framework-1.3.0/tests/test_plugins.py +291 -0
- cello_framework-1.3.0/tests/test_upgrades.py +197 -0
- cello_framework-1.3.0/tests/test_v130_fixes.py +269 -0
- cello_framework-1.3.0/tests/verify_async_client.py +250 -0
- cello_framework-1.2.3/docs/releases/index.md +0 -241
- cello_framework-1.2.3/python/cello/database.py +0 -422
- cello_framework-1.2.3/python/cello/validation.py +0 -90
- {cello_framework-1.2.3 → cello_framework-1.3.0}/.github/workflows/ci.yml +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/.github/workflows/docs.yml +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/.github/workflows/publish.yml +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/.gitignore +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/CONTRIBUTING.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/LICENSE +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/PUBLISHING.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/benchmarks/benchmark.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/benchmarks/compare/README.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/benchmarks/compare/apps/__init__.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/benchmarks/compare/apps/blacksheep_app.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/benchmarks/compare/apps/cello_app.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/benchmarks/compare/apps/fastapi_app.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/benchmarks/compare/apps/robyn_app.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/benchmarks/compare/requirements.txt +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/benchmarks/compare/run_benchmarks.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/benchmarks/quick_bench.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/community/code-of-conduct.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/community/contributing.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/enterprise/deployment/docker.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/enterprise/deployment/kubernetes.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/enterprise/deployment/service-mesh.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/enterprise/index.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/enterprise/integration/database.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/enterprise/integration/graphql.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/enterprise/integration/grpc.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/enterprise/integration/message-queues.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/enterprise/observability/health-checks.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/enterprise/observability/metrics.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/enterprise/observability/opentelemetry.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/enterprise/observability/tracing.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/advanced/background-tasks.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/advanced/file-storage.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/advanced/fullstack.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/advanced/graphql.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/advanced/microservices.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/advanced/realtime-dashboard.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/advanced/redis-caching.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/basic/database.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/basic/forms.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/basic/jwt-auth.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/basic/query-params.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/enterprise/api-gateway.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/enterprise/event-sourcing.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/enterprise/health-checks.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/enterprise/multi-tenant.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/enterprise/oauth2.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/enterprise/rate-limiting.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/index.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/adaptive-rate-limiting.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/advanced-middleware.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/async-handlers.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/circuit-breaker.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/dto-validation.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/guards.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/lifecycle-hooks.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/minijinja-advanced.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/minijinja-basic.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/minijinja-blog.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/minijinja-emails.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/minijinja-forms.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/minijinja-macros.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/simple-api.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/examples/real/smart-caching.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/advanced/background-tasks.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/advanced/file-uploads.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/advanced/static-files.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/advanced/templates.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/core/requests.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/core/routing.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/middleware/caching.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/middleware/circuit-breaker.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/middleware/compression.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/middleware/cors.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/middleware/logging.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/middleware/overview.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/middleware/rate-limiting.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/minijinja-templates.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/realtime/sse.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/realtime/websocket.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/security/authentication.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/security/csrf.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/security/guards.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/security/headers.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/security/jwt.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/security/overview.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/security/sessions.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/features/templates.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/getting-started/installation.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/getting-started/project-structure.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/getting-started/quickstart.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/includes/abbreviations.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/learn/guides/best-practices.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/learn/guides/deployment.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/learn/guides/error-handling.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/learn/guides/testing.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/learn/index.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/learn/patterns/cqrs.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/learn/patterns/event-driven.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/learn/patterns/repository.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/learn/patterns/service-layer.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/learn/tutorials/auth-system.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/learn/tutorials/chat-app.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/learn/tutorials/microservices.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/learn/tutorials/rest-api.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/logo-full.png +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/logo-icon.svg +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/logo.jpg +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/logo.svg +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/reference/api/context.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/reference/api/guards.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/reference/api/middleware.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/reference/api/request.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/reference/api/response.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/reference/cli.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/reference/config/middleware.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/reference/config/security.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/reference/config/server.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/reference/errors.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/changelog.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/migration.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/v0.10.0.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/v0.4.0.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/v0.6.0.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/v0.7.0.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/v0.8.0.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/v0.9.0.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/v1.1.0.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/v1.2.0.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/v1.2.1.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/v1.2.2.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/releases/v1.2.3.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/requirements.txt +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/stylesheets/extra.css +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/docs/tags.md +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/adaptive_rate_limit.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/async_demo.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/circuit_breaker.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/dto_validation.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/guards.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/lifecycle_hooks.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/minijinja_advanced.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/minijinja_basic.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/minijinja_blog.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/minijinja_emails.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/minijinja_forms.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/minijinja_macros.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/examples/smart_caching.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/python/cello/cqrs.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/python/cello/eventsourcing.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/python/cello/graphql.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/python/cello/grpc.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/python/cello/guards.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/python/cello/messaging.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/python/cello/saga.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/arena.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/blueprint.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/context.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/error.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/circuit_breaker.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/cqrs.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/database.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/eventsourcing.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/grpc.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/messaging.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/rate_limit.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/redis.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/request_id.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/saga.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/security.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/middleware/session.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/multipart.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/request/multipart_streaming.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/request/parsing.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/response/xml.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/router.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/routing/constraints.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/routing/mod.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/server/protocols.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/timeout.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/src/websocket.rs +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/tests/verify_adaptive.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/tests/verify_caching.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/tests/verify_circuit_breaker.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/tests/verify_dto.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/tests/verify_guards_impl.py +0 -0
- {cello_framework-1.2.3 → cello_framework-1.3.0}/tests/verify_lifecycle.py +0 -0
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## Project Overview
|
|
4
4
|
|
|
5
|
-
**Cello** is an ultra-fast, Rust-powered Python async web framework designed to achieve C-level performance on the hot path while maintaining Python's developer experience. It
|
|
5
|
+
**Cello** is an ultra-fast, Rust-powered Python async web framework designed to achieve C-level performance on the hot path while maintaining Python's developer experience. It combines a modern feature set with a pure Rust implementation for maximum performance.
|
|
6
6
|
|
|
7
|
-
**Version:** 1.
|
|
7
|
+
**Version:** 1.3.0
|
|
8
8
|
**License:** MIT
|
|
9
9
|
**Python Requirement:** 3.12+
|
|
10
10
|
**Author:** Jagadeesh Katla
|
|
@@ -78,7 +78,7 @@ Request → Rust HTTP Engine → Python Handler → Rust Response
|
|
|
78
78
|
│ │ └── redis.rs # Redis integration (v0.8.0)
|
|
79
79
|
│ ├── routing/ # Route constraints
|
|
80
80
|
│ ├── server/ # Server modes (cluster, TLS)
|
|
81
|
-
│ ├── blueprint.rs #
|
|
81
|
+
│ ├── blueprint.rs # Modular route grouping
|
|
82
82
|
│ ├── websocket.rs # WebSocket support
|
|
83
83
|
│ ├── sse.rs # Server-Sent Events
|
|
84
84
|
│ ├── json.rs # SIMD JSON parsing
|
|
@@ -346,6 +346,41 @@ def handle_value_error(request, exc):
|
|
|
346
346
|
|
|
347
347
|
## Version History
|
|
348
348
|
|
|
349
|
+
- **v1.3.0**: The Speed/Simplicity/Security release — async rework (below), native data layer + ORM, a full `enable_*` plugin audit, and three-pillar upgrades. Native data layer + ORM resolves issue #5 ("how do I use the database pool and Redis client?"); the previous DB/Redis layer was **mock scaffolding** (methods returned `[]`/`None`, never connected) and is now real.
|
|
350
|
+
- **Native Postgres pool** (`src/db/postgres.rs`, `PyDatabase`): backed by `deadpool-postgres` + `tokio-postgres`. `request.database` / `app.database` expose `fetch` (→`list[dict]`), `fetchrow` (→`dict|None`), `fetchval`, `execute` (→rows affected), and `transaction()`. Positional `$1` params via a `SqlParam`/`ToSql` bridge (`src/db/value.rs`) that dispatches on the target column type; rows decode common pg types incl. `jsonb`→nested Python.
|
|
351
|
+
- **Native Redis client** (`src/db/redis_client.rs`, `PyRedis`): `redis` crate `aio::ConnectionManager`. `request.redis` / `app.redis` expose get/set/del/expire/incr/hget/hset/lpush/lrange/sadd/publish/eval/evalsha/script_load/ping/… (real, verified against a live server).
|
|
352
|
+
- **Transactions**: `async with request.database.transaction() as tx` (explicit BEGIN/COMMIT/ROLLBACK on a held pooled connection), plus a rewritten `@transactional` decorator (async-only; injects a `tx` argument; auto commit/rollback).
|
|
353
|
+
- **Built-in ORM** (`python/cello/orm.py`): `Model` + typed fields (`AutoField/IntegerField/CharField/TextField/BooleanField/FloatField/JSONField/DateTimeField/ForeignKey`), a chainable async `QuerySet` (`filter/exclude/order_by/limit/offset` with field lookups; `get/first/all/count/exists/values/create/update/delete`), `create_table`/`drop_table`. Intentionally lightweight (no migration diffing, lazy reverse relations, `select_related`, signals/admin) — documented as such.
|
|
354
|
+
- **Async bridge**: all methods return `pyo3_asyncio::tokio::future_into_py` awaitables (same proven pattern as `AsyncClient`); verified to resolve on the persistent asyncio loop.
|
|
355
|
+
- **Wiring**: `lib.rs` `enable_database`/`enable_redis` build real pools; `app.state` namespace added; `request.database`/`request.db`/`request.redis` injected per request. Stub `Database`/`Redis`/`Transaction` in `python/cello/database.py` removed — native classes exported from `cello`.
|
|
356
|
+
- **Deps**: `deadpool-postgres`/`tokio-postgres` made non-optional (with `with-chrono-0_4`/`with-uuid-1`/`with-serde_json-1`); added `redis = 0.25`. `postgres` feature kept as an empty alias.
|
|
357
|
+
- **Tests**: `tests/test_native_db.py` — live-server integration for raw queries/types, transaction commit+rollback, Redis commands, ORM CRUD/filters/FK (auto-skips when PG/Redis unreachable). Obsolete mock-based unit tests removed. Docs: `docs/data-layer.md`, `docs/issue-5-answer.md`, `examples/database_orm_demo.py`.
|
|
358
|
+
- **Middleware verification + Prometheus fix**: verified the 7 core `enable_*` middleware end-to-end (cors, logging, compression, caching, rate_limit, circuit_breaker, prometheus). Six worked; **`enable_prometheus` was broken** — `/metrics` returned 404 because `handle_request` (`src/server/mod.rs`) does "route match FIRST, fast-return 404" before the prometheus middleware runs, and `/metrics` isn't a registered route. Fixed via `PrometheusMiddleware::try_serve(path)` (`src/middleware/prometheus.rs`), called in the routing-miss branch before returning 404. Tests: `tests/test_middleware.py`; docs: `docs/middleware.md`; example: `examples/middleware_full_demo.py`. Known middleware notes (documented): CORS preflight `OPTIONS` to an *unrouted* path still 404s (same fast-404 cause; register an `OPTIONS` route); a cache HIT serves the stored body uncompressed (bypasses compression); rate-limit + circuit-breaker are global.
|
|
359
|
+
- **Full `enable_*` plugin audit (all 27)**: verified every plugin end-to-end over live HTTP (extends the 7-core pass above). Bugs found & fixed:
|
|
360
|
+
- **Health checks & GraphQL returned 404** — identical root cause to the prometheus bug (fast-404 runs before the middleware chain; `/health*` and `/graphql` aren't registered routes). Fixed generally: added a `serves_unrouted(method, path)` hook to the `Middleware`/`AsyncMiddleware` traits (default `false`; overridden in `src/middleware/health.rs` and `graphql.rs`), plus `MiddlewareChain::has_unrouted` / `execute_before_unrouted` / `execute_before_async_unrouted` (`src/middleware/mod.rs`) and a `serve_unrouted()` helper in the router-miss branch (`src/server/mod.rs`). **Only** path-owning middleware run on a miss, so unknown paths under auth still 404 (no 404→401 route-existence leak).
|
|
361
|
+
- **BasicAuth 401 lacked `WWW-Authenticate`** — `before` returned `Err`, so the server short-circuited and the `after` hook that set the header never ran. Fixed by returning `Stop(challenge())` with the header set inline (`src/middleware/auth.rs`).
|
|
362
|
+
- **JWT rejected tokens without `iat`** — a standard `sub`+`exp` token failed with "missing field iat". Fixed with `#[serde(default)]` on `JwtClaims.iat`. `exp` stays required (secure default).
|
|
363
|
+
- **`enable_security_headers` only accepted a `bool`** while docs/examples pass a `SecurityHeadersConfig` (TypeError). Now accepts `None` | `bool` | `SecurityHeadersConfig` via `Option<&PyAny>` + `build_security_headers_mw()` (`src/lib.rs`).
|
|
364
|
+
- **`set_timeouts` panicked** — hyper 1.10 requires `builder.timer(TokioTimer::new())` when `header_read_timeout` is set ("timeout set, but no timer set"); was missing. Fixed in `src/server/mod.rs` (unblocks the 3 timeout/limit tests in `tests/test_v130_fixes.py`).
|
|
365
|
+
- **Announce-only plugins** (documented, not "broken"): `enable_grpc`, `enable_messaging`, `enable_rabbitmq`, `enable_sqs`, `enable_event_sourcing`, `enable_cqrs`, `enable_saga` print config but do not wire runtime behaviour into the HTTP app — real functionality is in `cello.grpc/messaging/cqrs/saga/eventsourcing`.
|
|
366
|
+
- Tests: `tests/test_plugins.py` (20 live-HTTP checks); example: `examples/plugins_demo.py`; docs: `docs/reference/api/plugins.md` (+ mkdocs nav). Full suite: **433 pass** with `pytest --asyncio-mode=auto` (`pytest-asyncio` IS required for `test_cello.py`'s `async def` tests).
|
|
367
|
+
- **Three-pillar upgrades (Speed / Simplicity / Security)**:
|
|
368
|
+
- **Security — full headers**: `SecurityHeadersConfig` now exposes `csp` (a `CSP` builder), `permissions_policy` (`{feature: [origins]}`), and `coep`/`coop`/`corp` (string values); `build_security_headers_mw` in `src/lib.rs` bridges them onto the Rust `SecurityHeadersMiddleware` (which already emitted them). `SecurityHeadersConfig.secure()` now includes cross-origin isolation (`require-corp` / `same-origin`).
|
|
369
|
+
- **Security — Redis TLS**: added rustls features (`tls-rustls`, `tls-rustls-webpki-roots`, `tokio-rustls-comp`) to the `redis` crate; `rediss://` URLs now work (`src/db/redis_client.rs` unchanged — `Client::open` handles the scheme). Resolves the v1.4.0 "TLS for Redis" follow-up.
|
|
370
|
+
- **Speed — compressed cache**: a cache HIT short-circuits the pipeline so the compression middleware never ran on it (was served uncompressed). `CacheMiddleware` now gzips the HIT inline for `Accept-Encoding: gzip` clients (`compress`/`compress_min_size` on `CacheConfig`, default on, min 1 KB), sets `Vary: Accept-Encoding`, and serves identity to non-gzip clients. `enable_caching(..., compress=True)` toggles it. Cache stores identity because async-`after` (store) runs before sync-`after` (compress).
|
|
371
|
+
- **Simplicity — honest stubs**: the 7 announce-only `enable_*` methods (`grpc`, `messaging`, `rabbitmq`, `sqs`, `event_sourcing`, `cqrs`, `saga`) no longer print a misleading "enabled" banner — they emit a clear "records config only — use the `cello.X` module" note (Rust + Python docstrings). No behavior change; just honest.
|
|
372
|
+
- **DX + Security — request validation**: `@app.{get,post,...}(path, body=DTO)` (App + Blueprint) parses/validates the JSON body and returns **400 `{"detail": [...]}`** before the handler runs, injecting the validated instance (`wrap_handler_with_body` in `python/cello/validation.py`). Works with Pydantic, dataclasses, and plain classes. Complements the pre-existing type-hint validation (returns 422).
|
|
373
|
+
- Tests: `tests/test_upgrades.py` (11 checks). Example: `examples/three_pillars_demo.py`. Docs: `docs/reference/api/plugins.md`, `docs/features/advanced/dto-validation.md`. Full suite: **464 pass** (`pytest --asyncio-mode=auto`).
|
|
374
|
+
- **Known follow-up**: `numeric`/`timestamptz` params need an explicit `$1::type` cast; `cargo test --lib` can't link libpython (pre-existing pyo3 `extension-module` limitation) — Python integration tests are the verification path.
|
|
375
|
+
- **Async runtime rework, security hardening & DoS protection** (the async-rework portion of v1.3.0):
|
|
376
|
+
- **Async runtime rework** (`src/async_loop.rs`, `handler.rs`, `lib.rs`): async `def` handlers now run on a single **persistent asyncio loop** (dedicated daemon thread) via `run_coroutine_threadsafe` instead of a fresh `asyncio.run()` per request. Loop-bound resources (aiohttp/asyncpg pools, `asyncio.Lock`/`Queue`) survive across requests, and the GIL is released while a coroutine awaits I/O (async handlers no longer serialize on the GIL). Async startup/shutdown hooks now actually run (previously the `pyo3_asyncio::into_future` path failed silently).
|
|
377
|
+
- **Security**: CSRF Origin/Referer validation rewritten to exact-authority matching (`example.com.evil.com` no longer bypasses); all middleware skip/exclude paths use `path_matches_skip` (no prefix bypass); CORS adds `Vary: Origin` on reflected responses; BasicAuth uses non-short-circuit comparison (no username-timing oracle); SSE `id`/`event` strip CR/LF (no stream injection).
|
|
378
|
+
- **DoS hardening**: `max_body_size` enforced (413, default 100 MB, `Limited`-capped streaming) via `App.set_limits()`; `App.set_timeouts()` wires header/body read timeouts (Slowloris) and a handler timeout (504). Previously `LimitsConfig`/`TimeoutConfig` were inert.
|
|
379
|
+
- **Correctness**: large Python ints (`> i64::MAX`, up to `u64::MAX`) serialize exactly instead of becoming lossy floats; `Range` header no longer underflows on 0-byte files; DELETE/OPTIONS request bodies are read; query `+` decodes to space in keys as well as values.
|
|
380
|
+
- **Python API**: `CsrfConfig` passed to `app.use()` is now honored (`cookie_name`/`header_name`/`allowed_origins`); `options()`/`head()`/`route()` apply the same validation + redis-injection wrapping as other verbs.
|
|
381
|
+
- **Tests**: new Rust `#[cfg(test)]` units (CSRF authority, `path_matches_skip`, Range, SSE) + `tests/test_v130_fixes.py` integration suite.
|
|
382
|
+
- **Known follow-up**: per-process Tokio runtime remains current-thread (multicore via the existing multi-process model); `AsyncClient` still uses `pyo3_asyncio::future_into_py`.
|
|
383
|
+
- **v1.2.4**: Critical fix — async handlers broken since v1.2.1; `pyo3_asyncio::tokio::into_future` failed silently after server startup switched to `py.allow_threads + block_on` (v1.2.1), causing all `async def` handlers to return 500; fixed by driving coroutines via `tokio::task::spawn_blocking + asyncio.run()` (`handler.rs`)
|
|
349
384
|
- **v1.2.3**: Full middleware Python API — `cello.middleware` module with `JwtAuth`, `BasicAuth`, `ApiKeyAuth`, `CsrfConfig`, `AdaptiveRateLimitConfig`; `app.use()` dispatcher; 6 new `enable_*` methods on App (`enable_jwt`, `enable_session`, `enable_security_headers`, `enable_csrf`, `enable_basic_auth`, `enable_api_key`); all docs import paths corrected (`from cello import RoleGuard` not `cello.guards`)
|
|
350
385
|
- **v1.2.2**: Security & bug fixes — CSRF `HttpOnly` on double-submit cookie (critical, broke all AJAX CSRF); all middleware `skip_path` prefix bypass fixed via `path_matches_skip()` helper; `FixedWindowStore` window_start never updated after reset; unused `mut` cleaned in minijinja tests
|
|
351
386
|
- **v1.2.1**: Bug fixes — server port never bound (`pyo3_asyncio` replaced with native `py.allow_threads` + `tokio::block_on`); `ProblemDetails` was missing from Python module export; `And`/`Or` guards now accept both `*args` and list styles; CSRF `HttpOnly` removed from double-submit cookie (JS must read it); `FixedWindowStore` window_start never updated after reset; all middleware `skip_path` used raw `starts_with` allowing prefix bypass; doc corrections (`type_uri` not `type_url`)
|