nene2-python 1.8.66__tar.gz → 1.8.164__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 (537) hide show
  1. {nene2_python-1.8.66 → nene2_python-1.8.164}/.env.example +5 -0
  2. nene2_python-1.8.164/.github/workflows/ci.yml +128 -0
  3. {nene2_python-1.8.66 → nene2_python-1.8.164}/AGENTS.md +18 -2
  4. {nene2_python-1.8.66 → nene2_python-1.8.164}/CHANGELOG.md +51 -0
  5. {nene2_python-1.8.66 → nene2_python-1.8.164}/CLAUDE.md +25 -12
  6. {nene2_python-1.8.66 → nene2_python-1.8.164}/PKG-INFO +63 -31
  7. {nene2_python-1.8.66 → nene2_python-1.8.164}/README.md +60 -29
  8. nene2_python-1.8.164/docs/explanation/field-trial-methodology.md +106 -0
  9. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-195.md +345 -0
  10. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-196.md +357 -0
  11. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-197.md +205 -0
  12. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-198.md +314 -0
  13. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-199.md +220 -0
  14. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-200.md +300 -0
  15. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-201.md +300 -0
  16. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-202.md +202 -0
  17. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-203.md +213 -0
  18. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-204.md +518 -0
  19. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-205.md +277 -0
  20. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-206.md +240 -0
  21. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-207.md +299 -0
  22. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-208.md +295 -0
  23. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-209.md +272 -0
  24. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-210.md +220 -0
  25. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-211.md +172 -0
  26. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-212.md +189 -0
  27. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-213.md +210 -0
  28. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-214.md +160 -0
  29. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-215.md +151 -0
  30. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-216.md +178 -0
  31. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-217.md +139 -0
  32. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-218.md +138 -0
  33. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-219.md +167 -0
  34. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-220.md +245 -0
  35. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-221.md +162 -0
  36. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-222.md +164 -0
  37. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-223.md +124 -0
  38. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-224.md +0 -0
  39. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-225.md +149 -0
  40. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-226.md +119 -0
  41. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-227.md +128 -0
  42. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-228.md +163 -0
  43. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-229.md +118 -0
  44. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-230.md +121 -0
  45. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-231.md +138 -0
  46. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-232.md +153 -0
  47. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-233.md +121 -0
  48. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-234.md +150 -0
  49. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-235.md +119 -0
  50. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-236.md +155 -0
  51. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-237.md +139 -0
  52. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-238.md +119 -0
  53. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-239.md +119 -0
  54. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-240.md +152 -0
  55. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-241.md +122 -0
  56. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-242.md +121 -0
  57. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-243.md +138 -0
  58. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-244.md +154 -0
  59. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-245.md +117 -0
  60. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-246.md +145 -0
  61. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-247.md +119 -0
  62. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-248.md +155 -0
  63. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-249.md +139 -0
  64. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-250.md +120 -0
  65. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-251.md +119 -0
  66. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-252.md +149 -0
  67. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-253.md +116 -0
  68. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-254.md +120 -0
  69. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-255.md +139 -0
  70. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-256.md +150 -0
  71. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-257.md +118 -0
  72. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-258.md +136 -0
  73. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-259.md +117 -0
  74. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-260.md +153 -0
  75. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-261.md +139 -0
  76. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-262.md +116 -0
  77. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-263.md +116 -0
  78. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-264.md +146 -0
  79. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-265.md +119 -0
  80. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-266.md +114 -0
  81. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-267.md +136 -0
  82. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-268.md +151 -0
  83. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-269.md +117 -0
  84. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-270.md +134 -0
  85. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-271.md +117 -0
  86. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-272.md +148 -0
  87. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-273.md +132 -0
  88. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-274.md +117 -0
  89. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-275.md +118 -0
  90. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-276.md +143 -0
  91. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-277.md +117 -0
  92. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-278.md +118 -0
  93. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-279.md +135 -0
  94. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-280.md +142 -0
  95. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-281.md +121 -0
  96. nene2_python-1.8.164/docs/field-trials/2026-05-field-trial-282.md +136 -0
  97. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/INDEX.md +96 -4
  98. nene2_python-1.8.164/docs/how-to/concurrency-patterns.md +68 -0
  99. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/middleware-stack.md +29 -1
  100. nene2_python-1.8.164/docs/how-to/release-and-publish.md +72 -0
  101. nene2_python-1.8.164/docs/how-to/run-integration-tests.md +51 -0
  102. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/run-tests.md +8 -4
  103. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/index.md +4 -0
  104. nene2_python-1.8.164/docs/ja/explanation/field-trial-methodology.md +104 -0
  105. nene2_python-1.8.164/docs/ja/how-to/release-and-publish.md +68 -0
  106. nene2_python-1.8.164/docs/ja/how-to/run-integration-tests.md +48 -0
  107. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/ja/how-to/run-tests.md +6 -4
  108. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/ja/reference/framework-modules.md +2 -0
  109. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/reference/framework-modules.md +122 -0
  110. nene2_python-1.8.164/docs/review/2026-05-22.md +94 -0
  111. nene2_python-1.8.164/docs/review/2026-05-23.md +83 -0
  112. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/roadmap.md +48 -44
  113. nene2_python-1.8.164/docs/todo/current.md +180 -0
  114. {nene2_python-1.8.66 → nene2_python-1.8.164}/pyproject.toml +7 -3
  115. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/app.py +83 -6
  116. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/comment/handler.py +37 -35
  117. nene2_python-1.8.164/src/example/note/handler.py +97 -0
  118. nene2_python-1.8.164/src/example/tag/handler.py +89 -0
  119. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/auth/__init__.py +17 -0
  120. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/auth/api_key.py +1 -0
  121. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/auth/bearer_token.py +14 -0
  122. nene2_python-1.8.164/src/nene2/auth/composite.py +129 -0
  123. nene2_python-1.8.164/src/nene2/auth/local_bearer_jwt.py +60 -0
  124. nene2_python-1.8.164/src/nene2/auth/local_issuer.py +70 -0
  125. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/database/sqlalchemy_executor.py +24 -4
  126. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/http/__init__.py +11 -1
  127. nene2_python-1.8.164/src/nene2/http/context.py +44 -0
  128. nene2_python-1.8.164/src/nene2/http/etag.py +128 -0
  129. nene2_python-1.8.164/src/nene2/http/query.py +67 -0
  130. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/middleware/__init__.py +3 -1
  131. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/middleware/throttle.py +77 -33
  132. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/example/comment/test_comment_http.py +28 -25
  133. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/example/note/test_list_notes.py +24 -15
  134. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/example/tag/test_tags.py +16 -16
  135. nene2_python-1.8.164/tests/example/test_examples_protected.py +53 -0
  136. nene2_python-1.8.164/tests/example/test_local_throttle_default.py +15 -0
  137. nene2_python-1.8.164/tests/example/test_system_routes.py +33 -0
  138. nene2_python-1.8.164/tests/integration/conftest.py +58 -0
  139. nene2_python-1.8.164/tests/integration/test_repository_real_db.py +65 -0
  140. nene2_python-1.8.164/tests/nene2/auth/test_composite_auth.py +134 -0
  141. nene2_python-1.8.164/tests/nene2/auth/test_local_bearer_jwt.py +60 -0
  142. nene2_python-1.8.164/tests/nene2/auth/test_local_issuer.py +116 -0
  143. nene2_python-1.8.164/tests/nene2/http/test_context.py +68 -0
  144. nene2_python-1.8.164/tests/nene2/http/test_etag.py +173 -0
  145. nene2_python-1.8.164/tests/nene2/http/test_query.py +117 -0
  146. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/middleware/test_throttle.py +28 -9
  147. nene2_python-1.8.164/tests/scripts/__init__.py +0 -0
  148. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/scripts/test_export_openapi.py +2 -1
  149. {nene2_python-1.8.66 → nene2_python-1.8.164}/uv.lock +15 -4
  150. nene2_python-1.8.66/.github/workflows/ci.yml +0 -52
  151. nene2_python-1.8.66/docs/todo/current.md +0 -77
  152. nene2_python-1.8.66/src/example/note/handler.py +0 -89
  153. nene2_python-1.8.66/src/example/tag/handler.py +0 -85
  154. nene2_python-1.8.66/src/nene2/http/etag.py +0 -23
  155. nene2_python-1.8.66/tests/nene2/http/test_etag.py +0 -51
  156. {nene2_python-1.8.66 → nene2_python-1.8.164}/.github/workflows/docs.yml +0 -0
  157. {nene2_python-1.8.66 → nene2_python-1.8.164}/.github/workflows/publish.yml +0 -0
  158. {nene2_python-1.8.66 → nene2_python-1.8.164}/.gitignore +0 -0
  159. {nene2_python-1.8.66 → nene2_python-1.8.164}/.vitepress/config.mts +0 -0
  160. {nene2_python-1.8.66 → nene2_python-1.8.164}/.vitepress/theme/custom.css +0 -0
  161. {nene2_python-1.8.66 → nene2_python-1.8.164}/.vitepress/theme/index.ts +0 -0
  162. {nene2_python-1.8.66 → nene2_python-1.8.164}/Dockerfile +0 -0
  163. {nene2_python-1.8.66 → nene2_python-1.8.164}/LICENSE +0 -0
  164. {nene2_python-1.8.66 → nene2_python-1.8.164}/alembic/README +0 -0
  165. {nene2_python-1.8.66 → nene2_python-1.8.164}/alembic/env.py +0 -0
  166. {nene2_python-1.8.66 → nene2_python-1.8.164}/alembic/script.py.mako +0 -0
  167. {nene2_python-1.8.66 → nene2_python-1.8.164}/alembic/versions/001_create_notes_and_tags_tables.py +0 -0
  168. {nene2_python-1.8.66 → nene2_python-1.8.164}/alembic.ini +0 -0
  169. {nene2_python-1.8.66 → nene2_python-1.8.164}/compose.yaml +0 -0
  170. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/adr/0001-toolchain.md +0 -0
  171. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/adr/0002-clean-architecture.md +0 -0
  172. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/adr/0003-security-first.md +0 -0
  173. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/adr/0004-ai-first-design.md +0 -0
  174. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/adr/0005-logging.md +0 -0
  175. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/adr/0006-rate-limiting.md +0 -0
  176. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/adr/0009-mcp-design.md +0 -0
  177. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/adr/0010-async-use-case.md +0 -0
  178. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/adr/0011-mcp-as-core-dependency.md +0 -0
  179. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/de/index.md +0 -0
  180. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/de/tutorials/getting-started.md +0 -0
  181. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/explanation/architecture.md +0 -0
  182. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/explanation/design-philosophy.md +0 -0
  183. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-1.md +0 -0
  184. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-10.md +0 -0
  185. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-100.md +0 -0
  186. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-101.md +0 -0
  187. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-102.md +0 -0
  188. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-103.md +0 -0
  189. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-104.md +0 -0
  190. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-105.md +0 -0
  191. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-106.md +0 -0
  192. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-107.md +0 -0
  193. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-108.md +0 -0
  194. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-109.md +0 -0
  195. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-11.md +0 -0
  196. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-110.md +0 -0
  197. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-111.md +0 -0
  198. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-112.md +0 -0
  199. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-113.md +0 -0
  200. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-114.md +0 -0
  201. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-115.md +0 -0
  202. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-116.md +0 -0
  203. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-117.md +0 -0
  204. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-118.md +0 -0
  205. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-119.md +0 -0
  206. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-12.md +0 -0
  207. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-120.md +0 -0
  208. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-121.md +0 -0
  209. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-122.md +0 -0
  210. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-123.md +0 -0
  211. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-124.md +0 -0
  212. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-125.md +0 -0
  213. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-126.md +0 -0
  214. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-127.md +0 -0
  215. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-128.md +0 -0
  216. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-129.md +0 -0
  217. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-13.md +0 -0
  218. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-130.md +0 -0
  219. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-131.md +0 -0
  220. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-132.md +0 -0
  221. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-133.md +0 -0
  222. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-134.md +0 -0
  223. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-135.md +0 -0
  224. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-136.md +0 -0
  225. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-137.md +0 -0
  226. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-138.md +0 -0
  227. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-139.md +0 -0
  228. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-14.md +0 -0
  229. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-140.md +0 -0
  230. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-141.md +0 -0
  231. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-142.md +0 -0
  232. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-143.md +0 -0
  233. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-144.md +0 -0
  234. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-145.md +0 -0
  235. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-146.md +0 -0
  236. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-147.md +0 -0
  237. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-148.md +0 -0
  238. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-149.md +0 -0
  239. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-15.md +0 -0
  240. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-150.md +0 -0
  241. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-151.md +0 -0
  242. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-152.md +0 -0
  243. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-153.md +0 -0
  244. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-154.md +0 -0
  245. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-155.md +0 -0
  246. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-156.md +0 -0
  247. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-157.md +0 -0
  248. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-158.md +0 -0
  249. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-159.md +0 -0
  250. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-16.md +0 -0
  251. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-160.md +0 -0
  252. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-161.md +0 -0
  253. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-162.md +0 -0
  254. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-163.md +0 -0
  255. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-164.md +0 -0
  256. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-165.md +0 -0
  257. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-166.md +0 -0
  258. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-167.md +0 -0
  259. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-168.md +0 -0
  260. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-169.md +0 -0
  261. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-17.md +0 -0
  262. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-170.md +0 -0
  263. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-171.md +0 -0
  264. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-172.md +0 -0
  265. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-173.md +0 -0
  266. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-174.md +0 -0
  267. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-175.md +0 -0
  268. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-176.md +0 -0
  269. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-177.md +0 -0
  270. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-178.md +0 -0
  271. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-179.md +0 -0
  272. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-18.md +0 -0
  273. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-180.md +0 -0
  274. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-181.md +0 -0
  275. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-182.md +0 -0
  276. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-183.md +0 -0
  277. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-184.md +0 -0
  278. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-185.md +0 -0
  279. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-186.md +0 -0
  280. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-187.md +0 -0
  281. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-188.md +0 -0
  282. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-189.md +0 -0
  283. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-19.md +0 -0
  284. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-190.md +0 -0
  285. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-191.md +0 -0
  286. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-192.md +0 -0
  287. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-193.md +0 -0
  288. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-194.md +0 -0
  289. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-2.md +0 -0
  290. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-20.md +0 -0
  291. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-21.md +0 -0
  292. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-22.md +0 -0
  293. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-23.md +0 -0
  294. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-24.md +0 -0
  295. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-25.md +0 -0
  296. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-26.md +0 -0
  297. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-27.md +0 -0
  298. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-28.md +0 -0
  299. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-29.md +0 -0
  300. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-3.md +0 -0
  301. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-30.md +0 -0
  302. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-31.md +0 -0
  303. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-32.md +0 -0
  304. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-33.md +0 -0
  305. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-34.md +0 -0
  306. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-35.md +0 -0
  307. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-36.md +0 -0
  308. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-37.md +0 -0
  309. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-38.md +0 -0
  310. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-39.md +0 -0
  311. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-4.md +0 -0
  312. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-40.md +0 -0
  313. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-41.md +0 -0
  314. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-42.md +0 -0
  315. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-43.md +0 -0
  316. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-44.md +0 -0
  317. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-45.md +0 -0
  318. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-46.md +0 -0
  319. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-47.md +0 -0
  320. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-48.md +0 -0
  321. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-49.md +0 -0
  322. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-5.md +0 -0
  323. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-50.md +0 -0
  324. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-51.md +0 -0
  325. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-52.md +0 -0
  326. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-53.md +0 -0
  327. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-54.md +0 -0
  328. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-55.md +0 -0
  329. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-56.md +0 -0
  330. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-57.md +0 -0
  331. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-58.md +0 -0
  332. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-59.md +0 -0
  333. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-6.md +0 -0
  334. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-60.md +0 -0
  335. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-61.md +0 -0
  336. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-62.md +0 -0
  337. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-63.md +0 -0
  338. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-64.md +0 -0
  339. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-65.md +0 -0
  340. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-66.md +0 -0
  341. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-67.md +0 -0
  342. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-68.md +0 -0
  343. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-69.md +0 -0
  344. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-7.md +0 -0
  345. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-70.md +0 -0
  346. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-71.md +0 -0
  347. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-72.md +0 -0
  348. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-73.md +0 -0
  349. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-74.md +0 -0
  350. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-75.md +0 -0
  351. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-76.md +0 -0
  352. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-77.md +0 -0
  353. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-78.md +0 -0
  354. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-79.md +0 -0
  355. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-8.md +0 -0
  356. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-80.md +0 -0
  357. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-81.md +0 -0
  358. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-82.md +0 -0
  359. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-83.md +0 -0
  360. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-84.md +0 -0
  361. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-85.md +0 -0
  362. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-86.md +0 -0
  363. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-87.md +0 -0
  364. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-88.md +0 -0
  365. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-89.md +0 -0
  366. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-9.md +0 -0
  367. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-90.md +0 -0
  368. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-91.md +0 -0
  369. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-92.md +0 -0
  370. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-93.md +0 -0
  371. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-94.md +0 -0
  372. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-95.md +0 -0
  373. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-96.md +0 -0
  374. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-97.md +0 -0
  375. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-98.md +0 -0
  376. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/field-trials/2026-05-field-trial-99.md +0 -0
  377. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/fr/index.md +0 -0
  378. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/fr/tutorials/getting-started.md +0 -0
  379. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/add-new-domain.md +0 -0
  380. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/api-versioning.md +0 -0
  381. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/async-use-case.md +0 -0
  382. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/background-tasks.md +0 -0
  383. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/configure-auth.md +0 -0
  384. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/cors.md +0 -0
  385. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/custom-auth-middleware.md +0 -0
  386. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/decimal-unicode-input.md +0 -0
  387. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/dependency-injection.md +0 -0
  388. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/domain-events.md +0 -0
  389. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/email-address-parsing.md +0 -0
  390. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/file-upload.md +0 -0
  391. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/lifespan-and-app-state.md +0 -0
  392. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/new-project.md +0 -0
  393. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/problem-details.md +0 -0
  394. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/response-patterns.md +0 -0
  395. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/soft-delete.md +0 -0
  396. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/sqlalchemy-repository.md +0 -0
  397. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/streaming.md +0 -0
  398. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/structured-logging.md +0 -0
  399. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/validation.md +0 -0
  400. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/how-to/webhook.md +0 -0
  401. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/howto/mcp-setup.md +0 -0
  402. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/ja/explanation/architecture.md +0 -0
  403. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/ja/explanation/design-philosophy.md +0 -0
  404. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/ja/how-to/add-new-domain.md +0 -0
  405. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/ja/how-to/configure-auth.md +0 -0
  406. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/ja/how-to/new-project.md +0 -0
  407. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/ja/how-to/sqlalchemy-repository.md +0 -0
  408. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/ja/howto/mcp-setup.md +0 -0
  409. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/ja/index.md +0 -0
  410. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/ja/reference/api.md +0 -0
  411. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/ja/reference/configuration.md +0 -0
  412. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/ja/tutorials/first-domain.md +0 -0
  413. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/ja/tutorials/getting-started.md +0 -0
  414. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/pt-br/index.md +0 -0
  415. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/pt-br/tutorials/getting-started.md +0 -0
  416. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/reference/api.md +0 -0
  417. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/reference/configuration.md +0 -0
  418. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/templates/field-trial-report.md +0 -0
  419. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/tutorials/first-domain.md +0 -0
  420. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/tutorials/getting-started.md +0 -0
  421. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/zh/index.md +0 -0
  422. {nene2_python-1.8.66 → nene2_python-1.8.164}/docs/zh/tutorials/getting-started.md +0 -0
  423. {nene2_python-1.8.66 → nene2_python-1.8.164}/package-lock.json +0 -0
  424. {nene2_python-1.8.66 → nene2_python-1.8.164}/package.json +0 -0
  425. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/__init__.py +0 -0
  426. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/__main__.py +0 -0
  427. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/comment/__init__.py +0 -0
  428. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/comment/entity.py +0 -0
  429. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/comment/exceptions.py +0 -0
  430. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/comment/repository.py +0 -0
  431. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/comment/sqlalchemy_repository.py +0 -0
  432. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/comment/use_case.py +0 -0
  433. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/mcp.py +0 -0
  434. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/note/__init__.py +0 -0
  435. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/note/async_use_case.py +0 -0
  436. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/note/entity.py +0 -0
  437. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/note/exceptions.py +0 -0
  438. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/note/repository.py +0 -0
  439. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/note/sqlalchemy_repository.py +0 -0
  440. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/note/use_case.py +0 -0
  441. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/schema.py +0 -0
  442. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/tag/__init__.py +0 -0
  443. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/tag/entity.py +0 -0
  444. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/tag/exceptions.py +0 -0
  445. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/tag/repository.py +0 -0
  446. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/tag/sqlalchemy_repository.py +0 -0
  447. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/example/tag/use_case.py +0 -0
  448. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/__init__.py +0 -0
  449. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/auth/deps.py +0 -0
  450. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/auth/exceptions.py +0 -0
  451. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/auth/interfaces.py +0 -0
  452. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/auth/local_verifier.py +0 -0
  453. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/cache/__init__.py +0 -0
  454. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/cache/ttl.py +0 -0
  455. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/config/__init__.py +0 -0
  456. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/config/settings.py +0 -0
  457. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/database/__init__.py +0 -0
  458. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/database/exceptions.py +0 -0
  459. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/database/health.py +0 -0
  460. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/database/interfaces.py +0 -0
  461. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/database/utils.py +0 -0
  462. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/http/health.py +0 -0
  463. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/http/pagination.py +0 -0
  464. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/http/problem_details.py +0 -0
  465. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/log/__init__.py +0 -0
  466. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/log/setup.py +0 -0
  467. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/mcp/__init__.py +0 -0
  468. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/mcp/http_client.py +0 -0
  469. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/mcp/server.py +0 -0
  470. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/middleware/domain_exception.py +0 -0
  471. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/middleware/error_handler.py +0 -0
  472. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/middleware/request_id.py +0 -0
  473. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/middleware/request_logging.py +0 -0
  474. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/middleware/request_size_limit.py +0 -0
  475. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/middleware/security_headers.py +0 -0
  476. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/middleware/setup.py +0 -0
  477. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/py.typed +0 -0
  478. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/security/__init__.py +0 -0
  479. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/security/webhook.py +0 -0
  480. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/use_case/__init__.py +0 -0
  481. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/use_case/protocols.py +0 -0
  482. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/validation/__init__.py +0 -0
  483. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/nene2/validation/exceptions.py +0 -0
  484. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/scripts/__init__.py +0 -0
  485. {nene2_python-1.8.66 → nene2_python-1.8.164}/src/scripts/export_openapi.py +0 -0
  486. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/__init__.py +0 -0
  487. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/conftest.py +0 -0
  488. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/example/__init__.py +0 -0
  489. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/example/comment/__init__.py +0 -0
  490. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/example/comment/test_comment_repository.py +0 -0
  491. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/example/comment/test_comment_use_case.py +0 -0
  492. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/example/conftest.py +0 -0
  493. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/example/note/__init__.py +0 -0
  494. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/example/note/test_async_note_use_case.py +0 -0
  495. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/example/note/test_note_repository.py +0 -0
  496. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/example/tag/__init__.py +0 -0
  497. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/example/tag/test_tag_repository.py +0 -0
  498. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/example/test_cors.py +0 -0
  499. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/example/test_mcp.py +0 -0
  500. {nene2_python-1.8.66/tests/nene2 → nene2_python-1.8.164/tests/integration}/__init__.py +0 -0
  501. {nene2_python-1.8.66/tests/nene2/auth → nene2_python-1.8.164/tests/nene2}/__init__.py +0 -0
  502. {nene2_python-1.8.66/tests/nene2/cache → nene2_python-1.8.164/tests/nene2/auth}/__init__.py +0 -0
  503. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/auth/test_api_key.py +0 -0
  504. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/auth/test_bearer_token.py +0 -0
  505. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/auth/test_make_require_auth.py +0 -0
  506. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/auth/test_token_issuer.py +0 -0
  507. {nene2_python-1.8.66/tests/nene2/config → nene2_python-1.8.164/tests/nene2/cache}/__init__.py +0 -0
  508. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/cache/test_ttl.py +0 -0
  509. {nene2_python-1.8.66/tests/nene2/database → nene2_python-1.8.164/tests/nene2/config}/__init__.py +0 -0
  510. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/config/test_settings.py +0 -0
  511. {nene2_python-1.8.66/tests/nene2/http → nene2_python-1.8.164/tests/nene2/database}/__init__.py +0 -0
  512. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/database/test_transaction.py +0 -0
  513. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/database/test_utils.py +0 -0
  514. {nene2_python-1.8.66/tests/nene2/log → nene2_python-1.8.164/tests/nene2/http}/__init__.py +0 -0
  515. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/http/test_health.py +0 -0
  516. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/http/test_pagination.py +0 -0
  517. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/http/test_problem_details.py +0 -0
  518. {nene2_python-1.8.66/tests/nene2/mcp → nene2_python-1.8.164/tests/nene2/log}/__init__.py +0 -0
  519. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/log/test_setup.py +0 -0
  520. {nene2_python-1.8.66/tests/nene2/middleware → nene2_python-1.8.164/tests/nene2/mcp}/__init__.py +0 -0
  521. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/mcp/test_http_client.py +0 -0
  522. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/mcp/test_server.py +0 -0
  523. {nene2_python-1.8.66/tests/nene2/security → nene2_python-1.8.164/tests/nene2/middleware}/__init__.py +0 -0
  524. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/middleware/test_error_handler.py +0 -0
  525. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/middleware/test_request_id.py +0 -0
  526. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/middleware/test_request_logging.py +0 -0
  527. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/middleware/test_request_size_limit.py +0 -0
  528. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/middleware/test_security_headers.py +0 -0
  529. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/middleware/test_setup_middlewares.py +0 -0
  530. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/middleware/test_simple_domain_handler.py +0 -0
  531. {nene2_python-1.8.66/tests/nene2/use_case → nene2_python-1.8.164/tests/nene2/security}/__init__.py +0 -0
  532. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/security/test_webhook.py +0 -0
  533. {nene2_python-1.8.66/tests/nene2/validation → nene2_python-1.8.164/tests/nene2/use_case}/__init__.py +0 -0
  534. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/use_case/test_protocols.py +0 -0
  535. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/use_case/test_run_in_threadpool.py +0 -0
  536. {nene2_python-1.8.66/tests/scripts → nene2_python-1.8.164/tests/nene2/validation}/__init__.py +0 -0
  537. {nene2_python-1.8.66 → nene2_python-1.8.164}/tests/nene2/validation/test_exceptions.py +0 -0
@@ -35,6 +35,11 @@ CORS_ORIGINS=[]
35
35
  # DB_USER=nene2
36
36
  # DB_PASSWORD=secret
37
37
 
38
+ # レートリミット(APP_ENV=local では未設定時オフ。有効化する場合のみ)
39
+ # THROTTLE_ENABLED=true
40
+ # THROTTLE_LIMIT=60
41
+ # THROTTLE_WINDOW=60
42
+
38
43
  # デフォルト値
39
44
  DB_ADAPTER=sqlite
40
45
  DB_NAME=:memory:
@@ -0,0 +1,128 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ check:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.12", "3.14"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Install uv
20
+ uses: astral-sh/setup-uv@v5
21
+ with:
22
+ version: "latest"
23
+ enable-cache: true
24
+
25
+ - name: Set up Python ${{ matrix.python-version }}
26
+ run: uv python install ${{ matrix.python-version }}
27
+
28
+ - name: Install dependencies
29
+ run: uv sync --all-extras
30
+
31
+ - name: pytest (with coverage)
32
+ run: uv run pytest
33
+
34
+ - name: coverage gate — domain/use_case layers (90%)
35
+ run: |
36
+ uv run coverage report \
37
+ --include="src/example/*/use_case.py,src/example/*/async_use_case.py,src/example/*/entity.py" \
38
+ --fail-under=90
39
+
40
+ - name: mypy
41
+ run: uv run mypy src/
42
+
43
+ - name: ruff check
44
+ run: uv run ruff check src/ tests/
45
+
46
+ - name: ruff format
47
+ run: uv run ruff format --check src/ tests/
48
+
49
+ - name: pip-audit
50
+ # PYSEC-2025-183: pyjwt weak-key-length — disputed by supplier, no fix version available.
51
+ # Transitive via mcp>=1.0. Re-evaluate when pyjwt releases a fix. (#280)
52
+ run: uv run pip-audit --ignore-vuln PYSEC-2025-183
53
+
54
+ integration-db:
55
+ name: Real-DB integration tests
56
+ runs-on: ubuntu-latest
57
+ # 実 PostgreSQL / MySQL に対してリポジトリ層を検証する(#747)。
58
+ # SQLite だけでは露見しなかった lastrowid 由来の採番バグを CI で恒常的に防ぐ。
59
+ services:
60
+ postgres:
61
+ image: postgres:16-alpine
62
+ env:
63
+ POSTGRES_PASSWORD: nene2
64
+ POSTGRES_DB: nene2_test
65
+ ports:
66
+ - 5432:5432
67
+ options: >-
68
+ --health-cmd "pg_isready -U postgres"
69
+ --health-interval 5s --health-timeout 5s --health-retries 10
70
+ mysql:
71
+ image: mysql:8
72
+ env:
73
+ MYSQL_ROOT_PASSWORD: nene2
74
+ MYSQL_DATABASE: nene2_test
75
+ ports:
76
+ - 3306:3306
77
+ options: >-
78
+ --health-cmd "mysqladmin ping -uroot -pnene2"
79
+ --health-interval 5s --health-timeout 5s --health-retries 20
80
+
81
+ steps:
82
+ - uses: actions/checkout@v4
83
+
84
+ - name: Install uv
85
+ uses: astral-sh/setup-uv@v5
86
+ with:
87
+ version: "latest"
88
+ enable-cache: true
89
+
90
+ - name: Set up Python
91
+ run: uv python install 3.14
92
+
93
+ - name: Install dependencies
94
+ run: uv sync --all-extras
95
+
96
+ - name: integration tests (PostgreSQL + MySQL)
97
+ env:
98
+ NENE2_TEST_POSTGRES_URL: postgresql+psycopg2://postgres:nene2@127.0.0.1:5432/nene2_test
99
+ NENE2_TEST_MYSQL_URL: mysql+pymysql://root:nene2@127.0.0.1:3306/nene2_test
100
+ run: uv run pytest tests/integration/ -v --no-cov
101
+
102
+ package-build:
103
+ name: Package build verification
104
+ runs-on: ubuntu-latest
105
+ steps:
106
+ - uses: actions/checkout@v4
107
+
108
+ - name: Install uv
109
+ uses: astral-sh/setup-uv@v5
110
+ with:
111
+ version: "latest"
112
+
113
+ # publish.yml と同じ uv build を PR ごとに走らせ、配布物の壊れを早期検出する(#541)。
114
+ - name: Build sdist + wheel
115
+ run: uv build
116
+
117
+ - name: Validate distribution metadata (twine check)
118
+ run: uvx twine check dist/*
119
+
120
+ - name: Verify clean install + import (no example/tests leakage)
121
+ run: |
122
+ uv venv /tmp/verify
123
+ uv pip install --python /tmp/verify/bin/python dist/*.whl
124
+ /tmp/verify/bin/python -c "import nene2; from nene2.http import PaginationResponse; print('import OK')"
125
+ # フレームワーク以外(example/tests)が配布物に混入していないことを保証
126
+ if /tmp/verify/bin/python -c "import example" 2>/dev/null; then
127
+ echo "ERROR: example package leaked into wheel"; exit 1
128
+ fi
@@ -10,7 +10,8 @@ NENE2 の設計哲学を Python で実装したリファレンスフレームワ
10
10
  - DTO / バリデーション: Pydantic v2 + `dataclass(frozen=True)`
11
11
  - 型チェック: `mypy --strict`
12
12
  - Lint / Format: `ruff`
13
- - テスト: `pytest` + `httpx`
13
+ - テスト: `pytest` + `httpx`(466 tests、カバレッジ 80% 以上)
14
+ - 現状: **v1.8.97** / FT219 完了 / [Field Trial INDEX](docs/field-trials/INDEX.md)
14
15
 
15
16
  ## 設計原則(PHP 版 NENE2 と共通)
16
17
 
@@ -19,13 +20,28 @@ NENE2 の設計哲学を Python で実装したリファレンスフレームワ
19
20
  3. ハンドラーは薄く: parse → use-case → response
20
21
  4. エラーは RFC 9457 Problem Details(application/problem+json)
21
22
  5. `ValidationException` → 422 自動マッピング
23
+ 6. FastAPI アプリは `APIRouter` + `create_app()` をファイル末尾に配置([CLAUDE.md](CLAUDE.md))
22
24
 
23
25
  ## 全チェックコマンド(CI と同等)
24
26
 
25
27
  ```bash
26
- uv run pytest && uv run mypy src/ && uv run ruff check src/ tests/ && uv run ruff format --check src/ tests/
28
+ uv run pytest && \
29
+ uv run mypy src/ && \
30
+ uv run ruff check src/ tests/ && \
31
+ uv run ruff format --check src/ tests/ && \
32
+ uv run pip-audit --ignore-vuln PYSEC-2025-183
27
33
  ```
28
34
 
35
+ ## ドキュメント入口
36
+
37
+ | 用途 | ファイル |
38
+ |---|---|
39
+ | 設計ポリシー(SSOT) | [CLAUDE.md](CLAUDE.md) |
40
+ | 現状・次タスク | [docs/todo/current.md](docs/todo/current.md) |
41
+ | FT 一覧 | [docs/field-trials/INDEX.md](docs/field-trials/INDEX.md) |
42
+ | API リファレンス | [docs/reference/framework-modules.md](docs/reference/framework-modules.md) |
43
+ | How-to | [docs/how-to/](docs/how-to/) |
44
+
29
45
  ## PHP 版リポジトリとの関係
30
46
 
31
47
  PHP 版 NENE2 の設計決定・ADR・フィールドトライアル記録は `../NENE2/docs/` を参照。
@@ -3,6 +3,57 @@
3
3
  All notable changes to nene2-python are documented here.
4
4
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
+ > 詳細な版ごとの一行サマリーは [`docs/todo/current.md`](docs/todo/current.md) の
7
+ > マイルストーン表を参照。本ファイルにはリリース粒度の集約エントリを記録する。
8
+
9
+ ---
10
+
11
+ ## [1.8.164] — 2026-05-29
12
+
13
+ 実データベース(PostgreSQL / MySQL)統合テストを追加し、マルチDB対応を実測で検証 (#747)。
14
+
15
+ ### Fixed
16
+ - `SqlAlchemyQueryExecutor.write()` / `_BoundQueryExecutor.write()` の INSERT 採番を
17
+ 全方言で正しく返すよう修正。psycopg2 は `lastrowid` 非対応のため、PostgreSQL では
18
+ `lastval()` フォールバックを使う(従来は `rowcount` を返し、`save()` が常に `1` を
19
+ 返す重大バグだった)。SQLite / MySQL は従来どおり `lastrowid`。
20
+
21
+ ### Added
22
+ - 実DB統合テスト `tests/integration/`(PostgreSQL / MySQL)。環境変数
23
+ `NENE2_TEST_POSTGRES_URL` / `NENE2_TEST_MYSQL_URL` 設定時のみ実行、未設定ならスキップ。
24
+ スキーマは SQLAlchemy `Table` から方言非依存に生成。
25
+ - CI に `integration-db` ジョブ(postgres:16 / mysql:8 service container)を追加。
26
+ - how-to [`run-integration-tests.md`](docs/how-to/run-integration-tests.md)(EN/JA)を追加。
27
+ - `pymysql` を dev 依存に追加(`mysql+pymysql://` ドライバが未導入だった)。
28
+
29
+ ### Changed
30
+ - リリース手順 how-to を「公開済み」の現実に合わせて訂正(#541 の事後整合)。
31
+
32
+ ## [1.8.163] — 2026-05-29
33
+
34
+ v1.8.35〜v1.8.163 の集約リリース。フィールドトライアル網羅スイープの完了と、
35
+ 公開準備・ポリシー整合・ハウスキーピングを含む。
36
+
37
+ ### Added
38
+ - フィールドトライアル **FT203〜FT282**(標準ライブラリ検証 + セキュリティ深掘り)。
39
+ セキュリティ診断(`%3==0`)・クラッカーペンテスト(`%4==0`)・6 ペルソナ DX レビューを各 FT で実施。
40
+ 危険プリミティブ回避シリーズ(pickle/marshal/eval、subprocess、SSRF、ReDoS、zip/tar slip、解凍爆弾、SSTI、XXE 等)を含む。
41
+ - FT ループ方法論ドキュメント [`docs/explanation/field-trial-methodology.md`](docs/explanation/field-trial-methodology.md)(EN/JA)— 目的・3 フェーズ・終着点を明文化 (#540)
42
+ - ETag / 条件付きリクエスト、`CompositeAuthMiddleware`、`InMemoryRateLimitStorage`、query ヘルパー、`LocalTokenIssuer`、`RequestScopedContext`
43
+ - リリース手順 how-to [`docs/how-to/release-and-publish.md`](docs/how-to/release-and-publish.md)、CI に配布物ビルド検証ジョブ (#541)
44
+
45
+ ### Changed
46
+ - example の全ハンドラー(Note/Tag/Comment)に `response_model` を付与し OpenAPI にレスポンス型を出力 (#539)
47
+ - starlette 1.0.1 へ更新(PYSEC-2026-161 解消、#611)
48
+
49
+ ### Fixed
50
+ - example の 422 レスポンスで全フィールドのエラーを返すように修正 (#588)
51
+ - `APP_ENV=local` で throttle を既定無効化 (#592)
52
+
53
+ ### Housekeeping
54
+ - FT サンドボックスを 5.1G→79M に整理(`ft-status.sh --clean-sandbox` 追加)、マージ済み orphan ブランチを削除
55
+ - #553(`/examples/ping`・`/examples/notes`)は #578 で実装済みを確認し close
56
+
6
57
  ---
7
58
 
8
59
  ## [1.8.34] — 2026-05-20
@@ -223,7 +223,14 @@ AI エージェント(Claude 等)がこのコードベースを正確に理
223
223
  ## 7. エラーハンドリングポリシー
224
224
 
225
225
  - `ValidationException` → 422 validation-failed Problem Details(自動)
226
- - `ErrorHandlerMiddleware` が全例外をキャッチ
226
+ - `ValidationError` は **`field / message / code` の 3 引数がすべて必須**(省略すると TypeError)
227
+ ```python
228
+ from nene2.validation import ValidationError, ValidationException
229
+ raise ValidationException([
230
+ ValidationError(field="host", message="許可されていません", code="host_not_allowed")
231
+ ])
232
+ ```
233
+ - `ErrorHandlerMiddleware` が全例外をキャッチ(FT サンドボックスでも `add_middleware(ErrorHandlerMiddleware)` を忘れないこと)
227
234
  - `APP_DEBUG=true` 時のみ例外メッセージを detail に含める
228
235
  - **スタックトレース・DB 接続情報を公開レスポンスに含めない**
229
236
  - ログには `logging` モジュールのみ使用(`print()` 禁止)
@@ -319,7 +326,7 @@ uv run pytest && \
319
326
  uv run mypy src/ && \
320
327
  uv run ruff check src/ tests/ && \
321
328
  uv run ruff format --check src/ tests/ && \
322
- uv run pip-audit
329
+ uv run pip-audit --ignore-vuln PYSEC-2025-183
323
330
 
324
331
  # 個別
325
332
  uv run pytest
@@ -329,7 +336,7 @@ uv run mypy src/
329
336
  uv run ruff check src/ tests/
330
337
  uv run ruff check src/ tests/ --fix # 自動修正
331
338
  uv run ruff format src/ tests/
332
- uv run pip-audit # 依存関係の脆弱性スキャン
339
+ uv run pip-audit --ignore-vuln PYSEC-2025-183 # 依存関係の脆弱性スキャン(CI と同じ)
333
340
 
334
341
  # 開発サーバー
335
342
  uv run uvicorn src.example.app:app --reload --port 8080
@@ -345,11 +352,13 @@ docker compose up app
345
352
  ```
346
353
  src/
347
354
  nene2/ フレームワークコア
348
- http/ JSON レスポンス・ページネーション・Problem Details
349
- middleware/ ミドルウェアパイプライン(Error / Security / RequestId / Logging / SizeLimit / Throttle)
355
+ http/ JSON レスポンス・ページネーション・Problem Details・ETag・query ヘルパー
356
+ middleware/ ミドルウェアパイプライン + setup_middlewares()
350
357
  validation/ ValidationException / ValidationError
351
358
  config/ 型付き設定オブジェクト(AppSettings)
352
- auth/ TokenVerifierProtocol / BearerTokenMiddleware / ApiKeyAuthMiddleware
359
+ auth/ Bearer / API Key / CompositeAuth / LocalTokenIssuer
360
+ cache/ TtlCache[V]
361
+ security/ verify_hmac_signature()
353
362
  database/ SqlAlchemyQueryExecutor / SqlAlchemyTransactionManager
354
363
  mcp/ LocalMcpServer / HttpxMcpClient
355
364
  log/ structlog セットアップ
@@ -358,20 +367,24 @@ src/
358
367
  note/ Note ドメイン(entity / repository / use_case / handler / sqlalchemy_repository)
359
368
  tag/ Tag ドメイン(entity / repository / use_case / handler / sqlalchemy_repository)
360
369
  comment/ Comment ドメイン(Note に紐付く nested ドメイン)
361
- app.py アプリケーションファクトリ
370
+ app.py アプリケーションファクトリ(create_app)
362
371
  mcp.py MCP サーバー(Note / Tag / Comment 全 15 ツール)
363
372
 
364
- tests/ pytest テスト(src/ を鏡像)
373
+ tests/ pytest テスト(src/ を鏡像、466 tests)
365
374
  docs/
366
375
  adr/ 設計決定記録(変更理由を残す)
367
- how-to/ How-to ガイド
376
+ how-to/ How-to ガイド(24+ 本)
368
377
  howto/ MCP セットアップガイド
369
- field-trials/ フィールドトライアル記録(FT1〜FT3)
378
+ field-trials/ フィールドトライアル記録(FT1〜FT219+、INDEX.md 参照)
379
+ field-trials/INDEX.md FT 検索索引(テーマ・診断種別・Follow-up Issue)
380
+ todo/current.md 現状サマリー・次タスク
381
+ roadmap.md ロードマップ・PHP 版対応表
382
+ review/ 作業日報
370
383
  tutorials/ チュートリアル
371
384
  explanation/ アーキテクチャ解説
372
385
  reference/ 設定・モジュールリファレンス
373
386
  ja/ 日本語ドキュメント(上記すべての翻訳)
374
- .github/workflows/ CI(GitHub Actions)
387
+ .github/workflows/ CI(GitHub Actions: Python 3.12 / 3.14
375
388
  ```
376
389
 
377
390
  ---
@@ -476,4 +489,4 @@ Python 標準ライブラリ・サードパーティライブラリを nene2-pyt
476
489
  | `JsonResponseFactory` | `fastapi.responses.JSONResponse` |
477
490
  | `PHPStan level 8` | `mypy --strict` |
478
491
  | `PHP-CS-Fixer` | `ruff format` |
479
- | `composer check` | `uv run pytest && mypy && ruff check && ruff format --check && pip-audit` |
492
+ | `composer check` | `uv run pytest && mypy && ruff check && ruff format --check && pip-audit --ignore-vuln PYSEC-2025-183` |
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nene2-python
3
- Version: 1.8.66
3
+ Version: 1.8.164
4
4
  Summary: NENE2 Python — minimal API framework following NENE2's design philosophy
5
5
  Project-URL: Homepage, https://github.com/hideyukiMORI/nene2-python
6
6
  Project-URL: Repository, https://github.com/hideyukiMORI/nene2-python
7
- Project-URL: Documentation, https://github.com/hideyukiMORI/nene2-python/tree/main/docs
7
+ Project-URL: Documentation, https://hideyukimori.github.io/nene2-python/
8
8
  Project-URL: Bug Tracker, https://github.com/hideyukiMORI/nene2-python/issues
9
9
  Author-email: hideyukiMORI <info.xion.cc@gmail.com>
10
10
  License: MIT
@@ -18,6 +18,7 @@ Classifier: Operating System :: OS Independent
18
18
  Classifier: Programming Language :: Python :: 3
19
19
  Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
21
22
  Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
22
23
  Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
23
24
  Classifier: Typing :: Typed
@@ -51,6 +52,8 @@ A Python reference framework implementing the [NENE2](https://github.com/hideyuk
51
52
  [![Python](https://img.shields.io/badge/python-3.12%2B-blue)](https://www.python.org/)
52
53
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
53
54
 
55
+ **Current release**: `v1.8.97` · **466 tests** · CI on Python 3.12 and 3.14
56
+
54
57
  ---
55
58
 
56
59
  ## Features
@@ -60,11 +63,14 @@ A Python reference framework implementing the [NENE2](https://github.com/hideyuk
60
63
  - **`mypy --strict`** — equivalent to PHPStan level 8 type safety
61
64
  - **ruff** — lint and format in one tool (replaces flake8, isort, black, bandit)
62
65
  - **RFC 9457 Problem Details** — uniform error responses across all endpoints
63
- - **Bearer Token / API Key auth** — zero-config `LocalTokenVerifier`
66
+ - **Bearer Token / API Key auth** — `LocalTokenVerifier`, `CompositeAuthMiddleware`, dev JWT helpers
64
67
  - **MCP support** — expose UseCases as AI agent tools via `LocalMcpServer`
65
68
  - **SQLAlchemy Core** — parameterised SQL without ORM overhead
66
- - **Security middleware** — CSP, X-Frame-Options, rate limiting, request size limit, CORS
69
+ - **Security middleware** — CSP, rate limiting, request size limit, CORS via `setup_middlewares()`
70
+ - **ETag / conditional requests** — `generate_etag()`, `check_not_modified()`, `check_precondition()`
71
+ - **TTL cache & webhooks** — `TtlCache[V]`, `verify_hmac_signature()`
67
72
  - **structlog** — structured JSON logging with request ID correlation
73
+ - **219 field trials** — stdlib and framework patterns validated in sandbox apps ([INDEX](docs/field-trials/INDEX.md))
68
74
 
69
75
  ---
70
76
 
@@ -76,31 +82,44 @@ pip install nene2-python
76
82
  uv add nene2-python
77
83
  ```
78
84
 
79
- Requires Python 3.12+.
85
+ Requires Python 3.12+ (CI also tests 3.14).
80
86
 
81
87
  ---
82
88
 
83
89
  ## Quick Start
84
90
 
91
+ Use `APIRouter` + `create_app()` at the **end of the file** (see [CLAUDE.md](CLAUDE.md)). Register middlewares with `setup_middlewares()` so 500 responses still get `X-Request-Id` and security headers.
92
+
85
93
  ```python
86
- from fastapi import FastAPI
94
+ from fastapi import APIRouter, FastAPI
87
95
  from nene2.config import AppSettings
88
- from nene2.middleware import (
89
- ErrorHandlerMiddleware,
90
- RequestIdMiddleware,
91
- SecurityHeadersMiddleware,
92
- ThrottleMiddleware,
93
- )
94
-
95
- cfg = AppSettings()
96
- app = FastAPI()
97
-
98
- app.add_middleware(ErrorHandlerMiddleware, debug=cfg.app_debug)
99
- app.add_middleware(SecurityHeadersMiddleware)
100
- app.add_middleware(RequestIdMiddleware)
101
- app.add_middleware(ThrottleMiddleware, limit=cfg.throttle_limit, window=cfg.throttle_window)
96
+ from nene2.middleware import setup_middlewares
97
+
98
+ router = APIRouter()
99
+
100
+ @router.get("/health")
101
+ def health() -> dict[str, str]:
102
+ return {"status": "ok"}
103
+
104
+ def create_app() -> FastAPI:
105
+ cfg = AppSettings()
106
+ app = FastAPI(title=cfg.app_name)
107
+ setup_middlewares(
108
+ app,
109
+ debug=cfg.app_debug,
110
+ throttle_limit=cfg.throttle_limit if cfg.throttle_enabled else None,
111
+ cors_allowed_origins=cfg.cors_origins if cfg.cors_enabled else None,
112
+ )
113
+ app.include_router(router)
114
+ return app
115
+
116
+ app = create_app()
102
117
  ```
103
118
 
119
+ See the full reference app in [`src/example/`](src/example/) (Note / Tag / Comment CRUD, auth, MCP).
120
+
121
+ ---
122
+
104
123
  ### Define a domain
105
124
 
106
125
  ```python
@@ -137,7 +156,6 @@ class GetNoteUseCase:
137
156
  ```python
138
157
  from fastapi import APIRouter
139
158
  from fastapi.responses import JSONResponse
140
- from nene2.http import problem_details_response
141
159
 
142
160
  router = APIRouter(prefix="/notes", tags=["notes"])
143
161
 
@@ -147,16 +165,14 @@ async def get_note(note_id: int) -> JSONResponse:
147
165
  return JSONResponse({"id": note.id, "title": note.title, "body": note.body})
148
166
  ```
149
167
 
150
- See the full working example in [`src/example/`](src/example/).
151
-
152
168
  ---
153
169
 
154
170
  ## Development Commands
155
171
 
156
172
  ```bash
157
173
  uv sync # install dependencies
158
- uv run pytest # run tests (coverage enforced at 80%)
159
- uv run mypy src/ # type check
174
+ uv run pytest # 466 tests, coverage 80%
175
+ uv run mypy src/ # type check (strict)
160
176
  uv run ruff check src/ tests/ # lint
161
177
  uv run ruff format src/ tests/ # format
162
178
  uv run uvicorn src.example.app:app --reload --port 8080 # dev server
@@ -169,25 +185,39 @@ uv run pytest && \
169
185
  uv run mypy src/ && \
170
186
  uv run ruff check src/ tests/ && \
171
187
  uv run ruff format --check src/ tests/ && \
172
- uv run pip-audit
188
+ uv run pip-audit --ignore-vuln PYSEC-2025-183
173
189
  ```
174
190
 
191
+ CI also runs a **90% coverage gate** on `example/*/use_case.py`, `entity.py`, and `async_use_case.py`.
192
+
175
193
  ---
176
194
 
177
195
  ## Framework Modules
178
196
 
179
197
  | Module | Purpose |
180
198
  |---|---|
181
- | `nene2.http` | `PaginationQueryParser`, `PaginationResponse`, `problem_details_response()` |
182
- | `nene2.middleware` | `ErrorHandlerMiddleware`, `SecurityHeadersMiddleware`, `RequestIdMiddleware`, `RequestLoggingMiddleware`, `RequestSizeLimitMiddleware`, `ThrottleMiddleware` |
183
- | `nene2.auth` | `BearerTokenMiddleware`, `ApiKeyAuthMiddleware`, `LocalTokenVerifier`, `TokenVerifierProtocol` |
199
+ | `nene2.http` | Pagination, Problem Details, health checks, ETag, query helpers, `RequestScopedContext` |
200
+ | `nene2.middleware` | Full pipeline + `setup_middlewares()`, rate-limit storage protocol |
201
+ | `nene2.auth` | Bearer / API Key / composite auth, `LocalTokenIssuer`, `make_require_auth()` |
184
202
  | `nene2.database` | `SqlAlchemyQueryExecutor`, `SqlAlchemyTransactionManager`, `DatabaseHealthCheck` |
185
203
  | `nene2.config` | `AppSettings` (pydantic-settings, reads from env / `.env`) |
186
204
  | `nene2.validation` | `ValidationException`, `ValidationError` |
205
+ | `nene2.cache` | `TtlCache[V]` — thread-safe in-memory TTL cache |
206
+ | `nene2.security` | `verify_hmac_signature()` for webhook verification |
187
207
  | `nene2.mcp` | `LocalMcpServer`, `HttpxMcpClient` |
188
208
  | `nene2.log` | `setup_logging()` (structlog, JSON in production) |
189
209
  | `nene2.use_case` | `UseCaseProtocol[I, O]`, `AsyncUseCaseProtocol[I, O]` |
190
210
 
211
+ Details: [Framework modules reference](docs/reference/framework-modules.md) · [How-to guides](docs/how-to/)
212
+
213
+ ---
214
+
215
+ ## Versioning
216
+
217
+ - **`pyproject.toml` `version`** — bumped with each merged FT or feature PR (currently `1.8.97`).
218
+ - **Git tags** (`v1.8.N`) — created on selected releases; may lag behind `pyproject.toml` during rapid FT loops.
219
+ - See [docs/todo/current.md](docs/todo/current.md) for the latest milestone table.
220
+
191
221
  ---
192
222
 
193
223
  ## PHP NENE2 Correspondence
@@ -197,7 +227,7 @@ uv run pip-audit
197
227
  | `readonly class` | `dataclass(frozen=True, slots=True)` |
198
228
  | `PHPStan level 8` | `mypy --strict` |
199
229
  | `PHP-CS-Fixer` | `ruff format` |
200
- | `composer check` | `uv run pytest && mypy && ruff check && ruff format --check && pip-audit` |
230
+ | `composer check` | `uv run pytest && mypy && ruff check && ruff format --check && pip-audit --ignore-vuln PYSEC-2025-183` |
201
231
  | `ValidationException` | `nene2.validation.ValidationException` |
202
232
  | `PaginationQueryParser` | `nene2.http.PaginationQueryParser` |
203
233
  | `ErrorHandlerMiddleware` | `nene2.middleware.ErrorHandlerMiddleware` |
@@ -208,4 +238,6 @@ uv run pip-audit
208
238
  ## Related
209
239
 
210
240
  - [NENE2 (PHP)](https://github.com/hideyukiMORI/NENE2) — PHP reference implementation
211
- - [Documentation](https://hideyukimori.github.io/nene2-python/) — full docs (Diátaxis structure)
241
+ - [Documentation (GitHub Pages)](https://hideyukimori.github.io/nene2-python/) — tutorials, how-to, reference (Diátaxis)
242
+ - [Field Trial INDEX](docs/field-trials/INDEX.md) — FT1–FT219 searchable index
243
+ - [Roadmap](docs/roadmap.md) — current status and planned work