cello-framework 1.2.1__tar.gz → 1.2.3__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 (290) hide show
  1. {cello_framework-1.2.1 → cello_framework-1.2.3}/CLAUDE.md +4 -2
  2. {cello_framework-1.2.1 → cello_framework-1.2.3}/Cargo.lock +1 -1
  3. {cello_framework-1.2.1 → cello_framework-1.2.3}/Cargo.toml +1 -1
  4. {cello_framework-1.2.1 → cello_framework-1.2.3}/PKG-INFO +1 -1
  5. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/core/async.md +1 -2
  6. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/core/blueprints.md +1 -2
  7. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/middleware/overview.md +1 -2
  8. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/security/overview.md +1 -1
  9. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/index.md +11 -10
  10. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/overrides/main.html +2 -2
  11. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/reference/api/app.md +2 -2
  12. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/reference/index.md +4 -5
  13. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/v0.5.0.md +12 -8
  14. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/v0.6.0.md +10 -23
  15. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/v1.2.1.md +58 -0
  16. cello_framework-1.2.3/docs/releases/v1.2.2.md +131 -0
  17. cello_framework-1.2.3/docs/releases/v1.2.3.md +121 -0
  18. {cello_framework-1.2.1 → cello_framework-1.2.3}/mkdocs.yml +2 -0
  19. {cello_framework-1.2.1 → cello_framework-1.2.3}/pyproject.toml +1 -1
  20. {cello_framework-1.2.1 → cello_framework-1.2.3}/python/cello/__init__.py +97 -1
  21. cello_framework-1.2.3/python/cello/middleware.py +166 -0
  22. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/lib.rs +91 -0
  23. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/auth.rs +4 -4
  24. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/csrf.rs +4 -3
  25. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/guards.rs +2 -2
  26. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/mod.rs +13 -0
  27. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/rate_limit.rs +5 -5
  28. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/session.rs +3 -3
  29. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/minijinja_engine.rs +5 -5
  30. {cello_framework-1.2.1 → cello_framework-1.2.3}/tests/test_cello.py +3 -3
  31. {cello_framework-1.2.1 → cello_framework-1.2.3}/tests/test_minijinja.py +1 -1
  32. {cello_framework-1.2.1 → cello_framework-1.2.3}/.github/workflows/ci.yml +0 -0
  33. {cello_framework-1.2.1 → cello_framework-1.2.3}/.github/workflows/docs.yml +0 -0
  34. {cello_framework-1.2.1 → cello_framework-1.2.3}/.github/workflows/publish.yml +0 -0
  35. {cello_framework-1.2.1 → cello_framework-1.2.3}/.gitignore +0 -0
  36. {cello_framework-1.2.1 → cello_framework-1.2.3}/CONTRIBUTING.md +0 -0
  37. {cello_framework-1.2.1 → cello_framework-1.2.3}/ENTERPRISE_ROADMAP.md +0 -0
  38. {cello_framework-1.2.1 → cello_framework-1.2.3}/LICENSE +0 -0
  39. {cello_framework-1.2.1 → cello_framework-1.2.3}/PUBLISHING.md +0 -0
  40. {cello_framework-1.2.1 → cello_framework-1.2.3}/README.md +0 -0
  41. {cello_framework-1.2.1 → cello_framework-1.2.3}/benchmarks/README.md +0 -0
  42. {cello_framework-1.2.1 → cello_framework-1.2.3}/benchmarks/benchmark.py +0 -0
  43. {cello_framework-1.2.1 → cello_framework-1.2.3}/benchmarks/compare/README.md +0 -0
  44. {cello_framework-1.2.1 → cello_framework-1.2.3}/benchmarks/compare/apps/__init__.py +0 -0
  45. {cello_framework-1.2.1 → cello_framework-1.2.3}/benchmarks/compare/apps/blacksheep_app.py +0 -0
  46. {cello_framework-1.2.1 → cello_framework-1.2.3}/benchmarks/compare/apps/cello_app.py +0 -0
  47. {cello_framework-1.2.1 → cello_framework-1.2.3}/benchmarks/compare/apps/fastapi_app.py +0 -0
  48. {cello_framework-1.2.1 → cello_framework-1.2.3}/benchmarks/compare/apps/robyn_app.py +0 -0
  49. {cello_framework-1.2.1 → cello_framework-1.2.3}/benchmarks/compare/requirements.txt +0 -0
  50. {cello_framework-1.2.1 → cello_framework-1.2.3}/benchmarks/compare/run_benchmarks.py +0 -0
  51. {cello_framework-1.2.1 → cello_framework-1.2.3}/benchmarks/quick_bench.py +0 -0
  52. {cello_framework-1.2.1 → cello_framework-1.2.3}/cello.md +0 -0
  53. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/community/code-of-conduct.md +0 -0
  54. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/community/contributing.md +0 -0
  55. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/community/index.md +0 -0
  56. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/community/support.md +0 -0
  57. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/enterprise/deployment/docker.md +0 -0
  58. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/enterprise/deployment/kubernetes.md +0 -0
  59. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/enterprise/deployment/service-mesh.md +0 -0
  60. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/enterprise/index.md +0 -0
  61. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/enterprise/integration/database.md +0 -0
  62. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/enterprise/integration/graphql.md +0 -0
  63. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/enterprise/integration/grpc.md +0 -0
  64. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/enterprise/integration/message-queues.md +0 -0
  65. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/enterprise/observability/health-checks.md +0 -0
  66. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/enterprise/observability/metrics.md +0 -0
  67. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/enterprise/observability/opentelemetry.md +0 -0
  68. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/enterprise/observability/tracing.md +0 -0
  69. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/enterprise/roadmap.md +0 -0
  70. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/advanced/background-tasks.md +0 -0
  71. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/advanced/file-storage.md +0 -0
  72. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/advanced/fullstack.md +0 -0
  73. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/advanced/graphql.md +0 -0
  74. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/advanced/microservices.md +0 -0
  75. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/advanced/realtime-dashboard.md +0 -0
  76. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/advanced/redis-caching.md +0 -0
  77. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/basic/database.md +0 -0
  78. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/basic/forms.md +0 -0
  79. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/basic/hello-world.md +0 -0
  80. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/basic/jwt-auth.md +0 -0
  81. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/basic/query-params.md +0 -0
  82. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/basic/rest-api.md +0 -0
  83. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/enterprise/api-gateway.md +0 -0
  84. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/enterprise/event-sourcing.md +0 -0
  85. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/enterprise/health-checks.md +0 -0
  86. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/enterprise/multi-tenant.md +0 -0
  87. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/enterprise/oauth2.md +0 -0
  88. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/enterprise/rate-limiting.md +0 -0
  89. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/index.md +0 -0
  90. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/adaptive-rate-limiting.md +0 -0
  91. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/advanced-middleware.md +0 -0
  92. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/advanced-patterns.md +0 -0
  93. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/all-features.md +0 -0
  94. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/api-protocols.md +0 -0
  95. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/async-handlers.md +0 -0
  96. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/auto-openapi.md +0 -0
  97. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/blueprints-advanced.md +0 -0
  98. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/circuit-breaker.md +0 -0
  99. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/cluster-demo.md +0 -0
  100. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/complete-showcase.md +0 -0
  101. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/comprehensive-demo.md +0 -0
  102. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/database-demo.md +0 -0
  103. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/dto-validation.md +0 -0
  104. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/enterprise-config.md +0 -0
  105. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/guards.md +0 -0
  106. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/hello-world.md +0 -0
  107. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/lifecycle-hooks.md +0 -0
  108. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/middleware-demo.md +0 -0
  109. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/minijinja-advanced.md +0 -0
  110. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/minijinja-basic.md +0 -0
  111. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/minijinja-blog.md +0 -0
  112. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/minijinja-emails.md +0 -0
  113. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/minijinja-forms.md +0 -0
  114. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/minijinja-macros.md +0 -0
  115. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/security.md +0 -0
  116. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/simple-api.md +0 -0
  117. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/smart-caching.md +0 -0
  118. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/examples/real/streaming-sse.md +0 -0
  119. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/advanced/background-tasks.md +0 -0
  120. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/advanced/dependency-injection.md +0 -0
  121. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/advanced/dto-validation.md +0 -0
  122. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/advanced/file-uploads.md +0 -0
  123. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/advanced/static-files.md +0 -0
  124. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/advanced/templates.md +0 -0
  125. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/core/requests.md +0 -0
  126. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/core/responses.md +0 -0
  127. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/core/routing.md +0 -0
  128. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/index.md +0 -0
  129. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/middleware/caching.md +0 -0
  130. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/middleware/circuit-breaker.md +0 -0
  131. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/middleware/compression.md +0 -0
  132. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/middleware/cors.md +0 -0
  133. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/middleware/logging.md +0 -0
  134. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/middleware/rate-limiting.md +0 -0
  135. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/minijinja-templates.md +0 -0
  136. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/realtime/sse.md +0 -0
  137. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/realtime/websocket.md +0 -0
  138. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/security/authentication.md +0 -0
  139. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/security/csrf.md +0 -0
  140. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/security/guards.md +0 -0
  141. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/security/headers.md +0 -0
  142. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/security/jwt.md +0 -0
  143. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/security/sessions.md +0 -0
  144. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/features/templates.md +0 -0
  145. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/getting-started/configuration.md +0 -0
  146. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/getting-started/first-app.md +0 -0
  147. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/getting-started/index.md +0 -0
  148. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/getting-started/installation.md +0 -0
  149. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/getting-started/project-structure.md +0 -0
  150. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/getting-started/quickstart.md +0 -0
  151. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/includes/abbreviations.md +0 -0
  152. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/javascripts/extra.js +0 -0
  153. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/learn/guides/best-practices.md +0 -0
  154. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/learn/guides/deployment.md +0 -0
  155. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/learn/guides/error-handling.md +0 -0
  156. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/learn/guides/performance.md +0 -0
  157. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/learn/guides/testing.md +0 -0
  158. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/learn/index.md +0 -0
  159. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/learn/patterns/cqrs.md +0 -0
  160. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/learn/patterns/event-driven.md +0 -0
  161. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/learn/patterns/repository.md +0 -0
  162. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/learn/patterns/service-layer.md +0 -0
  163. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/learn/tutorials/auth-system.md +0 -0
  164. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/learn/tutorials/chat-app.md +0 -0
  165. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/learn/tutorials/microservices.md +0 -0
  166. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/learn/tutorials/rest-api.md +0 -0
  167. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/logo-full.png +0 -0
  168. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/logo-icon.svg +0 -0
  169. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/logo.jpg +0 -0
  170. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/logo.svg +0 -0
  171. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/reference/api/blueprint.md +0 -0
  172. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/reference/api/context.md +0 -0
  173. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/reference/api/guards.md +0 -0
  174. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/reference/api/middleware.md +0 -0
  175. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/reference/api/request.md +0 -0
  176. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/reference/api/response.md +0 -0
  177. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/reference/cli.md +0 -0
  178. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/reference/config/middleware.md +0 -0
  179. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/reference/config/security.md +0 -0
  180. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/reference/config/server.md +0 -0
  181. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/reference/errors.md +0 -0
  182. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/changelog.md +0 -0
  183. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/index.md +0 -0
  184. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/migration.md +0 -0
  185. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/v0.10.0.md +0 -0
  186. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/v0.3.0.md +0 -0
  187. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/v0.4.0.md +0 -0
  188. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/v0.7.0.md +0 -0
  189. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/v0.8.0.md +0 -0
  190. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/v0.9.0.md +0 -0
  191. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/v1.0.0.md +0 -0
  192. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/v1.0.1.md +0 -0
  193. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/v1.1.0.md +0 -0
  194. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/releases/v1.2.0.md +0 -0
  195. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/requirements.txt +0 -0
  196. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/stylesheets/extra.css +0 -0
  197. {cello_framework-1.2.1 → cello_framework-1.2.3}/docs/tags.md +0 -0
  198. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/adaptive_rate_limit.py +0 -0
  199. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/advanced.py +0 -0
  200. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/advanced_middleware.py +0 -0
  201. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/advanced_patterns_demo.py +0 -0
  202. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/all_features_demo.py +0 -0
  203. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/api_protocols_demo.py +0 -0
  204. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/async_demo.py +0 -0
  205. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/auto_openapi_demo.py +0 -0
  206. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/circuit_breaker.py +0 -0
  207. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/cluster_demo.py +0 -0
  208. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/complete_showcase.py +0 -0
  209. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/comprehensive_demo.py +0 -0
  210. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/database_demo.py +0 -0
  211. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/dto_validation.py +0 -0
  212. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/enterprise.py +0 -0
  213. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/guards.py +0 -0
  214. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/hello.py +0 -0
  215. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/lifecycle_hooks.py +0 -0
  216. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/middleware_demo.py +0 -0
  217. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/minijinja_advanced.py +0 -0
  218. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/minijinja_basic.py +0 -0
  219. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/minijinja_blog.py +0 -0
  220. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/minijinja_emails.py +0 -0
  221. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/minijinja_forms.py +0 -0
  222. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/minijinja_macros.py +0 -0
  223. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/security.py +0 -0
  224. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/simple_api.py +0 -0
  225. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/smart_caching.py +0 -0
  226. {cello_framework-1.2.1 → cello_framework-1.2.3}/examples/streaming_demo.py +0 -0
  227. {cello_framework-1.2.1 → cello_framework-1.2.3}/python/cello/cqrs.py +0 -0
  228. {cello_framework-1.2.1 → cello_framework-1.2.3}/python/cello/database.py +0 -0
  229. {cello_framework-1.2.1 → cello_framework-1.2.3}/python/cello/eventsourcing.py +0 -0
  230. {cello_framework-1.2.1 → cello_framework-1.2.3}/python/cello/graphql.py +0 -0
  231. {cello_framework-1.2.1 → cello_framework-1.2.3}/python/cello/grpc.py +0 -0
  232. {cello_framework-1.2.1 → cello_framework-1.2.3}/python/cello/guards.py +0 -0
  233. {cello_framework-1.2.1 → cello_framework-1.2.3}/python/cello/messaging.py +0 -0
  234. {cello_framework-1.2.1 → cello_framework-1.2.3}/python/cello/saga.py +0 -0
  235. {cello_framework-1.2.1 → cello_framework-1.2.3}/python/cello/validation.py +0 -0
  236. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/arena.rs +0 -0
  237. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/background.rs +0 -0
  238. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/blueprint.rs +0 -0
  239. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/context.rs +0 -0
  240. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/dependency.rs +0 -0
  241. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/dto.rs +0 -0
  242. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/error.rs +0 -0
  243. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/handler.rs +0 -0
  244. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/http_client.rs +0 -0
  245. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/json.rs +0 -0
  246. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/lifecycle.rs +0 -0
  247. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/body_limit.rs +0 -0
  248. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/cache.rs +0 -0
  249. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/circuit_breaker.rs +0 -0
  250. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/cors.rs +0 -0
  251. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/cqrs.rs +0 -0
  252. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/database.rs +0 -0
  253. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/etag.rs +0 -0
  254. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/eventsourcing.rs +0 -0
  255. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/exception_handler.rs +0 -0
  256. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/graphql.rs +0 -0
  257. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/grpc.rs +0 -0
  258. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/health.rs +0 -0
  259. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/messaging.rs +0 -0
  260. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/prometheus.rs +0 -0
  261. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/redis.rs +0 -0
  262. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/request_id.rs +0 -0
  263. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/saga.rs +0 -0
  264. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/security.rs +0 -0
  265. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/static_files.rs +0 -0
  266. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/middleware/telemetry.rs +0 -0
  267. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/multipart.rs +0 -0
  268. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/openapi.rs +0 -0
  269. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/request/mod.rs +0 -0
  270. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/request/multipart_streaming.rs +0 -0
  271. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/request/parsing.rs +0 -0
  272. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/response/mod.rs +0 -0
  273. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/response/streaming.rs +0 -0
  274. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/response/xml.rs +0 -0
  275. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/router.rs +0 -0
  276. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/routing/constraints.rs +0 -0
  277. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/routing/mod.rs +0 -0
  278. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/server/cluster.rs +0 -0
  279. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/server/mod.rs +0 -0
  280. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/server/protocols.rs +0 -0
  281. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/sse.rs +0 -0
  282. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/template.rs +0 -0
  283. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/timeout.rs +0 -0
  284. {cello_framework-1.2.1 → cello_framework-1.2.3}/src/websocket.rs +0 -0
  285. {cello_framework-1.2.1 → cello_framework-1.2.3}/tests/verify_adaptive.py +0 -0
  286. {cello_framework-1.2.1 → cello_framework-1.2.3}/tests/verify_caching.py +0 -0
  287. {cello_framework-1.2.1 → cello_framework-1.2.3}/tests/verify_circuit_breaker.py +0 -0
  288. {cello_framework-1.2.1 → cello_framework-1.2.3}/tests/verify_dto.py +0 -0
  289. {cello_framework-1.2.1 → cello_framework-1.2.3}/tests/verify_guards_impl.py +0 -0
  290. {cello_framework-1.2.1 → cello_framework-1.2.3}/tests/verify_lifecycle.py +0 -0
@@ -4,7 +4,7 @@
4
4
 
5
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's the successor to frameworks like FastAPI, Robyn, and Litestar, combining their best features with pure Rust implementation for maximum performance.
6
6
 
7
- **Version:** 1.1.0
7
+ **Version:** 1.2.3
8
8
  **License:** MIT
9
9
  **Python Requirement:** 3.12+
10
10
  **Author:** Jagadeesh Katla
@@ -346,7 +346,9 @@ def handle_value_error(request, exc):
346
346
 
347
347
  ## Version History
348
348
 
349
- - **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; doc corrections (`type_uri` not `type_url`)
349
+ - **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
+ - **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
+ - **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`)
350
352
  - **v1.2.0**: Bug fixes (shutdown coroutine never awaited, KeyboardInterrupt in shutdown handler, `request.redis` AttributeError); Redis Lua scripting (`eval`, `evalsha`, `script_load`); Rust-native `AsyncClient` backed by `reqwest + Tokio` — GIL never held during HTTP I/O, HTTP/2, gzip, rustls
351
353
  - **v1.1.0**: MiniJinja Jinja2-compatible template engine (`MiniJinjaEngine`, `App.enable_templates()`, `App.render()`, `App.render_string()`); minijinja 2 Rust crate; HTML auto-escaping; globals; 47 new tests; 6 examples
352
354
  - **v1.0.1**: Cross-platform fixes (Windows multi-worker, signal handling, UNC paths; ARM JSON fallback; Linux-only CPU affinity), async compatibility fixes (handler validation, guards, cache decorator, blueprints), guards and database exports in `__all__`
@@ -341,7 +341,7 @@ dependencies = [
341
341
 
342
342
  [[package]]
343
343
  name = "cello-framework"
344
- version = "1.2.1"
344
+ version = "1.2.3"
345
345
  dependencies = [
346
346
  "async-graphql",
347
347
  "async-graphql-value",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "cello-framework"
3
- version = "1.2.1"
3
+ version = "1.2.3"
4
4
  edition = "2021"
5
5
  description = "Ultra-fast Rust-powered Python async web framework"
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cello-framework
3
- Version: 1.2.1
3
+ Version: 1.2.3
4
4
  Classifier: Development Status :: 5 - Production/Stable
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: MIT License
@@ -254,8 +254,7 @@ All Python-side decorators and wrappers in Cello automatically detect whether a
254
254
  | Pydantic validation | Yes | Validates the request body, then awaits the handler |
255
255
 
256
256
  ```python
257
- from cello import App, cache
258
- from cello.guards import RoleGuard
257
+ from cello import App, cache, RoleGuard
259
258
  from pydantic import BaseModel
260
259
 
261
260
  app = App()
@@ -183,8 +183,7 @@ app.register_blueprint(v2)
183
183
  Apply middleware to all routes within a blueprint. Async handlers work seamlessly with blueprint-level middleware and per-route guards:
184
184
 
185
185
  ```python
186
- from cello import App, Blueprint
187
- from cello.guards import RoleGuard, Authenticated
186
+ from cello import App, Blueprint, RoleGuard, Authenticated
188
187
 
189
188
  # Public blueprint -- no auth required
190
189
  public_bp = Blueprint("/public")
@@ -172,8 +172,7 @@ app.use(ApiKeyAuth(keys={"key1": "service-a"}, header="X-API-Key"))
172
172
  All Python-side middleware wrappers -- including the `@cache` decorator, guard wrappers, and Pydantic validation -- fully support async handlers. Each wrapper uses `inspect.iscoroutinefunction()` to detect async handlers at decoration time and generates the appropriate sync or async wrapper. This means you can freely use `async def` handlers with any combination of caching, guards, and validation without encountering unawaited coroutine issues.
173
173
 
174
174
  ```python
175
- from cello import App, cache
176
- from cello.guards import RoleGuard
175
+ from cello import App, cache, RoleGuard
177
176
  from pydantic import BaseModel
178
177
 
179
178
  class Item(BaseModel):
@@ -261,7 +261,7 @@ app.use(api_auth)
261
261
  Control access with composable guards:
262
262
 
263
263
  ```python
264
- from cello.guards import RoleGuard, PermissionGuard, And, Or
264
+ from cello import RoleGuard, PermissionGuard, And, Or
265
265
 
266
266
  # Simple role check
267
267
  admin_only = RoleGuard(["admin"])
@@ -37,7 +37,7 @@ hide:
37
37
  [:material-package-variant: PyPI](https://pypi.org/project/cello-framework/){ .md-button }
38
38
 
39
39
  <div class="hero-badges">
40
- <code class="badge-version">v1.2.0</code>
40
+ <code class="badge-version">v1.2.3</code>
41
41
  <code class="badge-tests">441 tests passing</code>
42
42
  <code class="badge-license">MIT License</code>
43
43
  <code class="badge-python">Python 3.12+</code>
@@ -178,8 +178,7 @@ hide:
178
178
  === ":material-api: REST API"
179
179
 
180
180
  ```python
181
- from cello import App, Response, Blueprint
182
- from cello.guards import RoleGuard
181
+ from cello import App, Response, Blueprint, RoleGuard
183
182
 
184
183
  app = App()
185
184
  api = Blueprint("api", url_prefix="/api/v1")
@@ -371,21 +370,23 @@ How Cello stacks up against popular Python web frameworks (4 workers, 5 processe
371
370
 
372
371
  <!-- ===== WHAT'S NEW ===== -->
373
372
 
374
- ## :material-creation: What's New in v1.2.0
373
+ ## :material-creation: What's New in v1.2.3
375
374
 
376
375
  <div class="whats-new-box" markdown>
377
376
 
378
- !!! tip "v1.2.0 -- Bug Fixes & Rust-Native AsyncClient"
377
+ !!! tip "v1.2.3 -- Full Middleware Python API & Correct Import Paths"
379
378
 
380
- Cello v1.2.0 ships critical bug fixes and a brand-new Rust-native HTTP client the GIL is never held during HTTP I/O.
379
+ Cello v1.2.3 exposes the complete auth & security middleware suite to Python, and fixes all doc import errors.
381
380
 
382
- - :material-bug-check: **Critical Bug Fixes** -- Shutdown coroutine now properly awaited, `KeyboardInterrupt` handled cleanly in shutdown handler, `request.redis` AttributeError resolved.
381
+ - :material-api: **`app.use(middleware)`** -- New universal dispatcher: `app.use(JwtAuth(...))`, `app.use(BasicAuth(...))`, `app.use(ApiKeyAuth(...))`, `app.use(CsrfConfig())`.
383
382
 
384
- - :material-language-rust: **Rust-Native AsyncClient** -- Backed by `reqwest + Tokio` with HTTP/2, gzip, and rustls. GIL is never held during HTTP I/O — true async performance.
383
+ - :material-package: **`cello.middleware` module** -- `from cello.middleware import JwtAuth, BasicAuth, ApiKeyAuth, CsrfConfig` now works.
385
384
 
386
- - :material-database: **Redis Lua Scripting** -- New `eval`, `evalsha`, and `script_load` methods for atomic server-side operations.
385
+ - :material-language-rust: **6 new Rust-backed methods** -- `enable_jwt()`, `enable_session()`, `enable_security_headers()`, `enable_csrf()`, `enable_basic_auth()`, `enable_api_key()` added to App.
387
386
 
388
- [:material-tag: Full Release Notes](releases/v1.2.0.md){ .md-button .md-button--primary }
387
+ - :material-import: **All import paths corrected** -- `from cello import RoleGuard` (not `from cello.guards`). All 9 affected doc pages fixed.
388
+
389
+ [:material-tag: Full Release Notes](releases/v1.2.3.md){ .md-button .md-button--primary }
389
390
  [:material-book-open-variant: Migration Guide](releases/migration.md){ .md-button }
390
391
 
391
392
  </div>
@@ -2,7 +2,7 @@
2
2
 
3
3
  {% block announce %}
4
4
  <span class="cello-announce">
5
- Cello v1.2.0Redis Lua scripting, Rust-native AsyncClient, critical bug fixes
5
+ Cello v1.2.3Full middleware Python API (JwtAuth, BasicAuth, ApiKeyAuth, app.use())
6
6
  <a href="{{ base_url }}/releases/" class="cello-announce-link">
7
7
  Release notes →
8
8
  </a>
@@ -37,7 +37,7 @@
37
37
  "operatingSystem": "Linux, macOS, Windows",
38
38
  "programmingLanguage": ["Python", "Rust"],
39
39
  "license": "https://opensource.org/licenses/MIT",
40
- "softwareVersion": "1.2.0",
40
+ "softwareVersion": "1.2.3",
41
41
  "author": {
42
42
  "@type": "Person",
43
43
  "name": "Jagadeesh Katla",
@@ -728,9 +728,9 @@ Add a global guard to all routes.
728
728
  > *Since v0.5.0*
729
729
 
730
730
  ```python
731
- from cello.guards import AuthenticatedGuard
731
+ from cello import Authenticated
732
732
 
733
- app.add_guard(AuthenticatedGuard())
733
+ app.add_guard(Authenticated())
734
734
  ```
735
735
 
736
736
  | Parameter | Type | Description |
@@ -78,7 +78,7 @@ The building blocks of every Cello application -- from creating your app to hand
78
78
 
79
79
  Role-based and permission-based access control. Composable guards that protect routes and blueprints.
80
80
 
81
- **Key classes:** `RoleGuard` `PermissionGuard` `CompositeGuard`
81
+ **Key classes:** `RoleGuard` `PermissionGuard` `Authenticated` `And` `Or` `Not`
82
82
 
83
83
  [:octicons-arrow-right-24: Guards Reference](api/guards.md)
84
84
 
@@ -166,8 +166,8 @@ The most commonly used classes and functions at a glance.
166
166
  | [`Response`](api/response.md) | `cello` | HTTP response builder |
167
167
  | [`Blueprint`](api/blueprint.md) | `cello` | Route grouping |
168
168
  | [`Depends`](api/context.md) | `cello` | Dependency injection marker |
169
- | [`RoleGuard`](api/guards.md) | `cello.guards` | Role-based access guard |
170
- | [`PermissionGuard`](api/guards.md) | `cello.guards` | Permission-based access guard |
169
+ | [`RoleGuard`](api/guards.md) | `cello` | Role-based access guard |
170
+ | [`PermissionGuard`](api/guards.md) | `cello` | Permission-based access guard |
171
171
  | [`JwtConfig`](config/security.md) | `cello.middleware` | JWT authentication config |
172
172
  | [`RateLimitConfig`](config/middleware.md) | `cello.middleware` | Rate limiting config |
173
173
  | [`SessionConfig`](config/security.md) | `cello.middleware` | Session management config |
@@ -219,8 +219,7 @@ The most commonly used classes and functions at a glance.
219
219
  === "Guards & Auth"
220
220
 
221
221
  ```python
222
- from cello import App
223
- from cello.guards import RoleGuard, PermissionGuard
222
+ from cello import App, RoleGuard, PermissionGuard
224
223
  from cello.middleware import JwtConfig, JwtAuth
225
224
 
226
225
  app = App()
@@ -65,14 +65,18 @@ def profile(request, user=Depends(get_current_user)):
65
65
 
66
66
  Composable access control guards that run before the handler. Guards inspect the request context and either allow or deny access.
67
67
 
68
+ !!! note "API names updated in v1.x"
69
+ `RoleGuard`, `PermissionGuard`, `AuthenticatedGuard`, `AndGuard`, `OrGuard`, `NotGuard` were the original v0.5.0 names.
70
+ Current names: `RoleGuard` → still `RoleGuard` (from `cello`), `PermissionGuard` → still `PermissionGuard` (from `cello`),
71
+ `AuthenticatedGuard` → `Authenticated`, `AndGuard` → `And`, `OrGuard` → `Or`, `NotGuard` → `Not`.
72
+
68
73
  ```python
69
- from cello import App
70
- from cello.guards import RoleGuard, PermissionGuard, AuthenticatedGuard
74
+ from cello import App, RoleGuard, PermissionGuard, Authenticated
71
75
 
72
76
  app = App()
73
77
 
74
78
  # Require authentication
75
- @app.get("/dashboard", guards=[AuthenticatedGuard()])
79
+ @app.get("/dashboard", guards=[Authenticated()])
76
80
  def dashboard(request):
77
81
  return {"welcome": request.context.get("user_id")}
78
82
 
@@ -90,18 +94,18 @@ def delete_user(request):
90
94
  **Composable logic with And, Or, Not:**
91
95
 
92
96
  ```python
93
- from cello.guards import AndGuard, OrGuard, NotGuard
97
+ from cello import And, Or, Not, RoleGuard, PermissionGuard, Authenticated
94
98
 
95
99
  # Admin OR has special permission
96
- flexible = OrGuard([
100
+ flexible = Or([
97
101
  RoleGuard(["admin"]),
98
102
  PermissionGuard(["elevated:access"]),
99
103
  ])
100
104
 
101
105
  # Authenticated AND not banned
102
- safe = AndGuard([
103
- AuthenticatedGuard(),
104
- NotGuard(RoleGuard(["banned"])),
106
+ safe = And([
107
+ Authenticated(),
108
+ Not(RoleGuard(["banned"])),
105
109
  ])
106
110
 
107
111
  @app.get("/resource", guards=[flexible])
@@ -56,17 +56,10 @@ def create_user(request):
56
56
  Rate limits now adjust based on server health:
57
57
 
58
58
  ```python
59
- from cello.middleware import AdaptiveRateLimitConfig
60
-
61
- config = AdaptiveRateLimitConfig(
62
- base_requests=100,
63
- window=60,
64
- cpu_threshold=0.8, # Reduce limits at 80% CPU
65
- memory_threshold=0.9, # Reduce limits at 90% memory
66
- latency_threshold=100, # Reduce limits if latency > 100ms
67
- min_requests=10 # Never go below 10 req/min
68
- )
59
+ from cello import App, RateLimitConfig
69
60
 
61
+ # Adaptive rate limiting (adjusts based on server load)
62
+ config = RateLimitConfig.adaptive(capacity=100, refill_rate=10)
70
63
  app.enable_rate_limit(config)
71
64
  ```
72
65
 
@@ -109,18 +102,15 @@ Invalid requests return RFC 7807 Problem Details:
109
102
  Protect against cascading failures:
110
103
 
111
104
  ```python
112
- from cello.middleware import CircuitBreaker, CircuitBreakerConfig
105
+ from cello import App
113
106
 
114
- config = CircuitBreakerConfig(
115
- failure_threshold=5, # Open after 5 failures
116
- recovery_timeout=30, # Try again after 30 seconds
117
- half_open_requests=3 # Allow 3 test requests
107
+ app.enable_circuit_breaker(
108
+ failure_threshold=5, # Open after 5 failures
109
+ reset_timeout=30, # Try again after 30 seconds
110
+ half_open_target=3, # Allow 3 test requests in half-open state
118
111
  )
119
112
 
120
- circuit = CircuitBreaker(config)
121
-
122
113
  @app.get("/external-api")
123
- @circuit.protect
124
114
  async def call_external(request):
125
115
  return await external_service.fetch()
126
116
  ```
@@ -130,8 +120,7 @@ async def call_external(request):
130
120
  Guards can now be applied at multiple levels:
131
121
 
132
122
  ```python
133
- from cello import App, Blueprint
134
- from cello.guards import RoleGuard, PermissionGuard
123
+ from cello import App, Blueprint, RoleGuard, PermissionGuard
135
124
 
136
125
  # Controller-level guard
137
126
  admin_bp = Blueprint("/admin", guards=[RoleGuard(["admin"])])
@@ -181,9 +170,7 @@ The cache middleware configuration has changed:
181
170
  app.enable_cache(max_age=300)
182
171
 
183
172
  # After (v0.6.0)
184
- from cello.middleware import CacheConfig
185
- config = CacheConfig(default_ttl=300, max_size=1000)
186
- app.enable_cache(config)
173
+ app.enable_caching(ttl=300)
187
174
  ```
188
175
 
189
176
  ### Rate Limit Response
@@ -100,6 +100,64 @@ admin_or_editor = Or(RoleGuard(["admin"]), RoleGuard(["editor"]))
100
100
 
101
101
  ---
102
102
 
103
+ ### CSRF Cookie Readable by JavaScript (Security)
104
+
105
+ **Symptom:** AJAX/SPA applications using CSRF protection failed all POST/PUT/DELETE requests with 403.
106
+
107
+ **Root cause:** The CSRF double-submit cookie was set with the `HttpOnly` flag. This prevents
108
+ JavaScript from reading the cookie value, making it impossible for the frontend to copy it into
109
+ the `X-CSRF-Token` header — which is the entire point of the double-submit pattern.
110
+
111
+ **Fix:** Removed `HttpOnly` from the CSRF cookie. The CSRF cookie is intentionally readable by
112
+ JavaScript; the session cookie (where sensitive data lives) remains `HttpOnly`.
113
+
114
+ ```javascript
115
+ // Now works — JS can read the CSRF cookie and send it back
116
+ const csrf = document.cookie.match(/_csrf=([^;]+)/)?.[1];
117
+ fetch("/api/data", {
118
+ method: "POST",
119
+ headers: { "X-CSRF-Token": csrf },
120
+ body: JSON.stringify(data),
121
+ });
122
+ ```
123
+
124
+ ---
125
+
126
+ ### Rate Limiter Fixed-Window Counter Reset (Bug)
127
+
128
+ **Symptom:** After the first rate-limit window expired, the fixed-window counter reset to zero
129
+ on every single subsequent request, making rate limiting completely ineffective.
130
+
131
+ **Root cause:** When the time window rolled over, `entry.count` was reset to 0 but
132
+ `entry.window_start` was never updated to the new window. Every request in the new window
133
+ saw `window_start != current_window` and reset the counter again.
134
+
135
+ **Fix:** Update `entry.window_start = current_window` alongside the count reset.
136
+
137
+ ---
138
+
139
+ ### Auth Skip-Path Prefix Bypass (Security)
140
+
141
+ **Symptom:** Calling `skip_path("/health")` to exclude the health endpoint from authentication
142
+ also excluded `/healthz`, `/healthy`, and any other path starting with `/health`.
143
+
144
+ **Root cause:** Path matching used `request.path.starts_with(skip_path)` without checking that
145
+ the following character is `/` or end-of-string.
146
+
147
+ **Fix:** Path is now only skipped when it equals the pattern exactly or starts with
148
+ `{pattern}/`. Affects `JwtAuth`, `BasicAuth`, `ApiKeyAuth`, `RateLimitMiddleware`,
149
+ `SessionMiddleware`, `CsrfMiddleware`, and `GuardsMiddleware`.
150
+
151
+ ```python
152
+ # Before: /healthz would also be skipped (security bypass)
153
+ jwt.skip_path("/health")
154
+
155
+ # After: only /health and /health/* are skipped
156
+ jwt.skip_path("/health")
157
+ ```
158
+
159
+ ---
160
+
103
161
  ## Upgrade
104
162
 
105
163
  ```bash
@@ -0,0 +1,131 @@
1
+ ---
2
+ title: v1.2.2 Release Notes
3
+ description: Cello Framework v1.2.2 — Security & Bug Fixes
4
+ tags:
5
+ - v1.2.2
6
+ - Release Notes
7
+ - Security
8
+ - Bug Fixes
9
+ ---
10
+
11
+ # Cello v1.2.2 — Security & Bug Fixes
12
+
13
+ **Release Date:** June 14, 2026
14
+ **License:** MIT
15
+ **Python:** 3.12+
16
+
17
+ ---
18
+
19
+ ## Overview
20
+
21
+ Cello v1.2.2 is a patch release that fixes one critical security bug, one security
22
+ vulnerability, and two correctness bugs discovered during a thorough code review of v1.2.1.
23
+ All changes are fully backwards-compatible.
24
+
25
+ **Upgrade immediately** if you use CSRF protection or authentication middleware skip-paths.
26
+
27
+ ---
28
+
29
+ ## Security Fixes
30
+
31
+ ### CSRF Double-Submit Cookie Was `HttpOnly` (Critical)
32
+
33
+ **Symptom:** AJAX applications and SPAs using `CsrfMiddleware` received 403 on every
34
+ POST/PUT/DELETE request, even when the CSRF token was correctly set.
35
+
36
+ **Root cause:** The CSRF double-submit cookie was set with `HttpOnly`, which prevents
37
+ JavaScript from reading cookie values. The double-submit pattern *requires* JavaScript
38
+ to read the cookie and copy its value into the `X-CSRF-Token` request header. With
39
+ `HttpOnly` set, this was impossible — every state-changing request failed CSRF validation.
40
+
41
+ **Fix:** Removed `HttpOnly` from the CSRF token cookie. The CSRF cookie is intentionally
42
+ readable by JavaScript (that is the design). Your session cookie, which holds sensitive
43
+ data, remains `HttpOnly`.
44
+
45
+ ```javascript
46
+ // Now works — JavaScript can read the CSRF cookie
47
+ const csrf = document.cookie.match(/_csrf=([^;]+)/)?.[1];
48
+
49
+ fetch("/api/submit", {
50
+ method: "POST",
51
+ headers: { "X-CSRF-Token": csrf, "Content-Type": "application/json" },
52
+ body: JSON.stringify({ name: "Alice" }),
53
+ });
54
+ ```
55
+
56
+ ---
57
+
58
+ ### Auth Middleware `skip_path` Allowed Prefix Bypass (Security)
59
+
60
+ **Symptom:** Calling `jwt.skip_path("/health")` to exclude the health-check endpoint
61
+ from authentication also excluded `/healthz`, `/healthy`, `/health-admin`, and any
62
+ other path whose string representation started with `/health`.
63
+
64
+ **Root cause:** All middleware used `request.path.starts_with(skip_path)` with no
65
+ boundary check. An attacker aware of a skipped path could craft a URL that bypasses
66
+ authentication.
67
+
68
+ **Affected middleware:** `JwtAuth`, `BasicAuth`, `ApiKeyAuth`, `RateLimitMiddleware`,
69
+ `SessionMiddleware`, `CsrfMiddleware`, `GuardsMiddleware`.
70
+
71
+ **Fix:** Paths are now only skipped when:
72
+
73
+ - The path **exactly equals** the pattern, or
74
+ - The path **starts with** `{pattern}/` (sub-path match).
75
+
76
+ ```python
77
+ # Before: /healthz was also skipped — security bypass
78
+ jwt_auth.skip_path("/health")
79
+
80
+ # After: only /health and /health/* are skipped
81
+ jwt_auth.skip_path("/health")
82
+ ```
83
+
84
+ ---
85
+
86
+ ## Bug Fixes
87
+
88
+ ### Rate Limiter Fixed-Window Counter Broke After First Window
89
+
90
+ **Symptom:** After the first time-window expired, the `FixedWindowStore` rate limiter
91
+ stopped enforcing limits entirely — every request was allowed regardless of how many
92
+ had been made.
93
+
94
+ **Root cause:** When the window rolled over, the per-client entry's `count` was reset
95
+ to 0 but `window_start` was never updated to the new window ID. Every subsequent
96
+ request also saw `window_start != current_window` and reset the counter to 0 again,
97
+ making the limiter permanently ineffective after the first window.
98
+
99
+ **Fix:** `window_start` is now updated to `current_window` alongside the count reset.
100
+
101
+ ---
102
+
103
+ ### Unused `mut` Warnings in Template Engine Tests
104
+
105
+ Five test functions in `minijinja_engine.rs` declared `let mut env = Environment::new()`
106
+ where `mut` was not needed (the variable was never mutated after construction). These
107
+ were cleaned up to eliminate Clippy warnings.
108
+
109
+ ---
110
+
111
+ ## Files Changed
112
+
113
+ | File | Change |
114
+ |------|--------|
115
+ | `src/middleware/csrf.rs` | Remove `HttpOnly` from CSRF cookie |
116
+ | `src/middleware/mod.rs` | Add `path_matches_skip()` shared helper |
117
+ | `src/middleware/auth.rs` | Use `path_matches_skip()` in JWT/Basic/ApiKey |
118
+ | `src/middleware/session.rs` | Use `path_matches_skip()` |
119
+ | `src/middleware/rate_limit.rs` | Use `path_matches_skip()`; fix `window_start` reset |
120
+ | `src/middleware/guards.rs` | Use `path_matches_skip()` |
121
+ | `src/minijinja_engine.rs` | Remove unused `mut` from test bindings |
122
+
123
+ ---
124
+
125
+ ## Upgrade
126
+
127
+ ```bash
128
+ pip install --upgrade cello-framework==1.2.2
129
+ ```
130
+
131
+ Drop-in replacement for v1.2.1. No API changes.
@@ -0,0 +1,121 @@
1
+ ---
2
+ title: v1.2.3 Release Notes
3
+ description: Cello Framework v1.2.3 — Full Middleware Python API & Docs Fixes
4
+ tags:
5
+ - v1.2.3
6
+ - Release Notes
7
+ - New Features
8
+ - Bug Fixes
9
+ ---
10
+
11
+ # Cello v1.2.3 — Full Middleware Python API & Docs Fixes
12
+
13
+ **Release Date:** June 14, 2026
14
+ **License:** MIT
15
+ **Python:** 3.12+
16
+
17
+ ---
18
+
19
+ ## Overview
20
+
21
+ Cello v1.2.3 exposes the complete authentication and security middleware suite to
22
+ Python — functionality that existed in Rust since v0.4.0 but had no Python API.
23
+ It also fixes all incorrect import paths across the documentation.
24
+
25
+ Drop-in upgrade from v1.2.2. No breaking changes.
26
+
27
+ ---
28
+
29
+ ## New Features
30
+
31
+ ### Full Middleware Python API
32
+
33
+ All authentication and security middleware is now accessible from Python.
34
+
35
+ #### `app.use(middleware)` — universal middleware dispatcher
36
+
37
+ ```python
38
+ from cello import App, JwtConfig
39
+ from cello.middleware import JwtAuth, BasicAuth, ApiKeyAuth, CsrfConfig
40
+
41
+ app = App()
42
+
43
+ # JWT authentication
44
+ app.use(JwtAuth(JwtConfig(secret="your-32-byte-secret-key!", algorithm="HS256")))
45
+
46
+ # Basic auth with credential dict
47
+ app.use(BasicAuth(credentials={"admin": "s3cr3t"}, realm="My API"))
48
+
49
+ # API key validation
50
+ app.use(ApiKeyAuth(keys={"key-abc": "service-a", "key-xyz": "service-b"}))
51
+
52
+ # CSRF protection
53
+ app.use(CsrfConfig())
54
+ ```
55
+
56
+ #### New `App` enable methods
57
+
58
+ ```python
59
+ app.enable_jwt(JwtConfig(secret="...", algorithm="HS256"), skip_paths=["/health"])
60
+ app.enable_session(SessionConfig(cookie_name="sid", max_age=3600))
61
+ app.enable_security_headers(strict=False)
62
+ app.enable_csrf()
63
+ app.enable_basic_auth(credentials={"admin": "secret"}, realm="Protected")
64
+ app.enable_api_key(keys={"key123": "service-a"}, header="X-API-Key")
65
+ ```
66
+
67
+ ### New `cello.middleware` module
68
+
69
+ ```python
70
+ from cello.middleware import (
71
+ JwtAuth, # JWT auth wrapper for app.use()
72
+ BasicAuth, # Basic auth wrapper for app.use()
73
+ ApiKeyAuth, # API key auth wrapper for app.use()
74
+ CsrfConfig, # CSRF middleware config for app.use()
75
+ AdaptiveRateLimitConfig, # Convenience wrapper for RateLimitConfig.adaptive()
76
+ # Also re-exported from cello for convenience:
77
+ JwtConfig,
78
+ SessionConfig,
79
+ SecurityHeadersConfig,
80
+ RateLimitConfig,
81
+ CSP,
82
+ )
83
+ ```
84
+
85
+ ---
86
+
87
+ ## Docs Fixes
88
+
89
+ All documentation pages now use correct import paths. Previously, several pages
90
+ showed imports that raised `ImportError` at runtime.
91
+
92
+ | Wrong (raised ImportError) | Correct |
93
+ |---------------------------|---------|
94
+ | `from cello.guards import RoleGuard` | `from cello import RoleGuard` |
95
+ | `from cello.guards import PermissionGuard` | `from cello import PermissionGuard` |
96
+ | `from cello.guards import AuthenticatedGuard` | `from cello import Authenticated` |
97
+ | `from cello.guards import AndGuard` | `from cello import And` |
98
+ | `from cello.middleware import CircuitBreaker` | `app.enable_circuit_breaker(...)` |
99
+ | `from cello.middleware import CacheConfig` | `app.enable_caching(ttl=...)` |
100
+
101
+ ---
102
+
103
+ ## Files Changed
104
+
105
+ | File | Change |
106
+ |------|--------|
107
+ | `src/lib.rs` | Add `enable_jwt`, `enable_session`, `enable_security_headers`, `enable_csrf`, `enable_basic_auth`, `enable_api_key` to Rust `Cello` struct |
108
+ | `python/cello/middleware.py` | **New file** — `JwtAuth`, `BasicAuth`, `ApiKeyAuth`, `CsrfConfig`, `AdaptiveRateLimitConfig` |
109
+ | `python/cello/__init__.py` | Add `App.use()` dispatcher and 6 new `enable_*` methods |
110
+ | `docs/` | 9 pages updated with correct import paths |
111
+ | `docs/overrides/main.html` | Announcement bar updated to v1.2.3 |
112
+
113
+ ---
114
+
115
+ ## Upgrade
116
+
117
+ ```bash
118
+ pip install --upgrade cello-framework==1.2.3
119
+ ```
120
+
121
+ Drop-in replacement for v1.2.2. No API changes.
@@ -364,6 +364,8 @@ nav:
364
364
 
365
365
  - Release Notes:
366
366
  - releases/index.md
367
+ - v1.2.3: releases/v1.2.3.md
368
+ - v1.2.2: releases/v1.2.2.md
367
369
  - v1.2.1: releases/v1.2.1.md
368
370
  - v1.2.0: releases/v1.2.0.md
369
371
  - v1.1.0: releases/v1.1.0.md
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "cello-framework"
7
- version = "1.2.1"
7
+ version = "1.2.3"
8
8
  description = "Ultra-fast Rust-powered Python async web framework"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }