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