cloudoll 4.2.1__tar.gz → 4.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. cloudoll-4.4.0/CHANGELOG.md +220 -0
  2. {cloudoll-4.2.1 → cloudoll-4.4.0}/PKG-INFO +8 -7
  3. {cloudoll-4.2.1 → cloudoll-4.4.0}/README.md +7 -6
  4. {cloudoll-4.2.1 → cloudoll-4.4.0}/README.zh-CN.md +11 -11
  5. cloudoll-4.4.0/cloudoll/__init__.py +1 -0
  6. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/AGENTS.md +4 -0
  7. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/ai.md +2 -0
  8. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/changelog.md +65 -3
  9. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/config.md +14 -2
  10. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/cookie-and-session.md +6 -1
  11. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/database.md +255 -23
  12. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/jwt.md +9 -2
  13. cloudoll-4.4.0/cloudoll/ai/docs/mail.md +74 -0
  14. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/start.md +7 -5
  15. cloudoll-4.4.0/cloudoll/ai/docs/utils.md +74 -0
  16. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/view.md +3 -1
  17. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/manifest.json +19 -9
  18. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/skills/cloudoll/SKILL.md +11 -1
  19. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/cli.py +7 -1
  20. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/clitool/cli_main.py +67 -26
  21. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/clitool/watch.py +37 -2
  22. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/mail/smtp.py +39 -53
  23. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/__init__.py +18 -1
  24. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/aws_engine.py +3 -0
  25. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/compiler.py +167 -10
  26. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/engine.py +17 -3
  27. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/field.py +3 -0
  28. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/model.py +20 -0
  29. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/protocols.py +1 -0
  30. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/query.py +237 -9
  31. cloudoll-4.4.0/cloudoll/orm/relation.py +79 -0
  32. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/savepoints.py +4 -0
  33. cloudoll-4.4.0/cloudoll/orm/subquery.py +15 -0
  34. cloudoll-4.4.0/cloudoll/template/.gitignore +82 -0
  35. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/template/README.md +11 -1
  36. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/template/config/conf.local.yaml +10 -2
  37. cloudoll-4.4.0/cloudoll/template/middlewares/auth.py +38 -0
  38. cloudoll-4.4.0/cloudoll/template/requirements.txt +1 -0
  39. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/configuration.py +12 -0
  40. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/core.py +45 -9
  41. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/sessions.py +15 -20
  42. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll.egg-info/PKG-INFO +8 -7
  43. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll.egg-info/SOURCES.txt +9 -0
  44. {cloudoll-4.2.1 → cloudoll-4.4.0}/docs/maintenance.md +2 -0
  45. {cloudoll-4.2.1 → cloudoll-4.4.0}/pyproject.toml +1 -0
  46. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/check_wheel.py +5 -0
  47. cloudoll-4.4.0/tests/integration/test_databases.py +576 -0
  48. cloudoll-4.4.0/tests/test_cli_create.py +192 -0
  49. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_datasources.py +28 -0
  50. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_dev_lifecycle.py +203 -3
  51. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_field_types.py +11 -0
  52. cloudoll-4.4.0/tests/test_mail_client.py +183 -0
  53. cloudoll-4.4.0/tests/test_password_and_id_utils.py +151 -0
  54. cloudoll-4.4.0/tests/test_query_capabilities.py +225 -0
  55. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_regressions.py +46 -7
  56. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_request_contract.py +152 -1
  57. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_transactions.py +60 -0
  58. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/typing/query_contract.py +14 -1
  59. cloudoll-4.2.1/CHANGELOG.md +0 -106
  60. cloudoll-4.2.1/cloudoll/__init__.py +0 -1
  61. cloudoll-4.2.1/cloudoll/template/middlewares/auth.py +0 -31
  62. cloudoll-4.2.1/cloudoll/template/requirements.txt +0 -1
  63. cloudoll-4.2.1/tests/integration/test_databases.py +0 -294
  64. {cloudoll-4.2.1 → cloudoll-4.4.0}/AGENTS.md +0 -0
  65. {cloudoll-4.2.1 → cloudoll-4.4.0}/AI.md +0 -0
  66. {cloudoll-4.2.1 → cloudoll-4.4.0}/LICENSE +0 -0
  67. {cloudoll-4.2.1 → cloudoll-4.4.0}/MANIFEST.in +0 -0
  68. {cloudoll-4.2.1 → cloudoll-4.4.0}/SECURITY.md +0 -0
  69. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/__main__.py +0 -0
  70. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/__init__.py +0 -0
  71. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/commands.py +0 -0
  72. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/app-start.md +0 -0
  73. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/deployment.md +0 -0
  74. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/event-source.md +0 -0
  75. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/exception.md +0 -0
  76. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/file-uploads.md +0 -0
  77. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/http-client.md +0 -0
  78. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/logs.md +0 -0
  79. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/middleware.md +0 -0
  80. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/migration.md +0 -0
  81. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/router.md +0 -0
  82. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/structure.md +0 -0
  83. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/validation.md +0 -0
  84. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/ai/docs/websockets.md +0 -0
  85. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/clitool/__init__.py +0 -0
  86. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/clitool/m2d.py +0 -0
  87. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/clitool/process.py +0 -0
  88. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/clitool/schema.py +0 -0
  89. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/clitool/spinner.py +0 -0
  90. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/logging/__init__.py +0 -0
  91. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/mail/__init__.py +0 -0
  92. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/observability.py +0 -0
  93. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/awsmysql.py +0 -0
  94. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/awspostgres.py +0 -0
  95. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/base.py +0 -0
  96. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/datasources.py +0 -0
  97. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/dialects.py +0 -0
  98. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/mysql.py +0 -0
  99. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/parse.py +0 -0
  100. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/postgres.py +0 -0
  101. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/streaming.py +0 -0
  102. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/test_sql.py +0 -0
  103. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/orm/values.py +0 -0
  104. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/py.typed +0 -0
  105. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/template/__init__.py +0 -0
  106. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/template/controllers/admin/test.py +0 -0
  107. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/template/controllers/api/index.py +0 -0
  108. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/template/controllers/es/es.py +0 -0
  109. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/template/controllers/home/index.py +0 -0
  110. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/template/controllers/upload/upload.py +0 -0
  111. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/template/controllers/ws/ws.py +0 -0
  112. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/template/static/css/index.css +0 -0
  113. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/template/static/img/cat.avif +0 -0
  114. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/template/static/js/index.js +0 -0
  115. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/template/templates/index.html +0 -0
  116. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/utils/__init__.py +0 -0
  117. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/utils/async_tools.py +0 -0
  118. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/utils/common.py +0 -0
  119. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/utils/password.py +0 -0
  120. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/utils/snowflake.py +0 -0
  121. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/__init__.py +0 -0
  122. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/context.py +0 -0
  123. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/exception.py +0 -0
  124. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/html.py +0 -0
  125. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/jwt.py +0 -0
  126. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/lifecycle.py +0 -0
  127. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/request_data.py +0 -0
  128. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/requests.py +0 -0
  129. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/resources.py +0 -0
  130. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/routing.py +0 -0
  131. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/settings.py +0 -0
  132. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/types.py +0 -0
  133. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll/web/validation.py +0 -0
  134. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll.egg-info/dependency_links.txt +0 -0
  135. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll.egg-info/entry_points.txt +0 -0
  136. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll.egg-info/requires.txt +0 -0
  137. {cloudoll-4.2.1 → cloudoll-4.4.0}/cloudoll.egg-info/top_level.txt +0 -0
  138. {cloudoll-4.2.1 → cloudoll-4.4.0}/docs/architecture.md +0 -0
  139. {cloudoll-4.2.1 → cloudoll-4.4.0}/docs/aurora.md +0 -0
  140. {cloudoll-4.2.1 → cloudoll-4.4.0}/docs/production.md +0 -0
  141. {cloudoll-4.2.1 → cloudoll-4.4.0}/docs/reliability.md +0 -0
  142. {cloudoll-4.2.1 → cloudoll-4.4.0}/docs/schema-generation.md +0 -0
  143. {cloudoll-4.2.1 → cloudoll-4.4.0}/docs/streaming-and-types.md +0 -0
  144. {cloudoll-4.2.1 → cloudoll-4.4.0}/scripts/sync_ai_docs.py +0 -0
  145. {cloudoll-4.2.1 → cloudoll-4.4.0}/setup.cfg +0 -0
  146. {cloudoll-4.2.1 → cloudoll-4.4.0}/setup.py +0 -0
  147. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/audit_dependencies.py +0 -0
  148. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/check_release.py +0 -0
  149. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/conftest.py +0 -0
  150. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/integration/test_aws_failover.py +0 -0
  151. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/integration/test_savepoints.py +0 -0
  152. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/integration/test_schema.py +0 -0
  153. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/integration/test_streaming.py +0 -0
  154. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/run_local_databases.py +0 -0
  155. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_ai.py +0 -0
  156. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_architecture.py +0 -0
  157. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_production_contracts.py +0 -0
  158. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_release_workflow.py +0 -0
  159. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_retry_and_query_regressions.py +0 -0
  160. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_review_fixes.py +0 -0
  161. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_save_snapshots_and_cleanup.py +0 -0
  162. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_savepoint_unit.py +0 -0
  163. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_schema_generation.py +0 -0
  164. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_sql_echo.py +0 -0
  165. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_startup_logging.py +0 -0
  166. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_streaming_unit.py +0 -0
  167. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_typing_regressions.py +0 -0
  168. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/test_validation.py +0 -0
  169. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/typing/engine_contract.py +0 -0
  170. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/typing/field_contract.py +0 -0
  171. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/typing/middleware_contract.py +0 -0
  172. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/typing/production_contract.py +0 -0
  173. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/typing/request_contract.py +0 -0
  174. {cloudoll-4.2.1 → cloudoll-4.4.0}/tests/typing/web_contract.py +0 -0
@@ -0,0 +1,220 @@
1
+ # Changelog
2
+
3
+ 简体中文见 [CHANGELOG.zh-CN.md](CHANGELOG.zh-CN.md)。
4
+
5
+ ## 4.4.0
6
+
7
+ Defect-fix release; backward compatible. Python 3.9+ remains supported.
8
+
9
+ ### Database
10
+
11
+ - `for_update()` row locks now require your own transaction. Outside one, the lock
12
+ was released by the commit that `for_update()` issued itself and protected
13
+ nothing; such a call now raises instead of silently doing nothing.
14
+ - A transaction cancelled or timed out while waiting for a connection gives that
15
+ connection back to the pool, so long-running services stop losing connections.
16
+ - Model fields are hashable again: columns can go into sets and serve as dict
17
+ keys (deduplicating columns, excluding groups of fields).
18
+ - `SUM(DISTINCT column)` and similar aggregate deduplication now happens inside
19
+ the aggregate, so values are deduplicated before being combined, and a literal
20
+ inside an aggregate is no longer bound twice.
21
+ - URL query parameters in an AWS datasource string are no longer handed to the
22
+ driver as unknown connection options.
23
+
24
+ ### Web and templates
25
+
26
+ - A response that has already started streaming keeps its body when an error
27
+ occurs; the JSON error handler no longer rewrites it. Streaming and SSE
28
+ endpoints stay intact.
29
+ - Page responses no longer repeat `charset` in `Content-Type`.
30
+ - `session` options (`key`, `max_age`, `httponly`, `secure`, `domain`, `path`,
31
+ `samesite`) apply to encrypted cookie, Redis and Memcached storage alike.
32
+ - `render_view()` keywords are `Response` options only, and the template context
33
+ is the positional mapping. A stray keyword now raises `TypeError` instead of
34
+ being silently merged into the context.
35
+ - Development servers bind to 127.0.0.1 by default and no longer occupy
36
+ `port + 1`.
37
+ - `server.ignore_dirs` is honoured for directories such as `logs`, so writing logs
38
+ no longer triggers a reload.
39
+ - The scaffolded authorization middleware now matches its documentation: it is an
40
+ async decorator, lets static paths through, and lets downstream failures reach
41
+ the error layer instead of being flattened into a 500 that echoes the exception
42
+ text.
43
+
44
+ ### Command line and new projects
45
+
46
+ - `cloudoll create` no longer copies `__pycache__` and `.pyc` files into the new
47
+ project.
48
+ - The last component of a project name must be letters, digits, underscore, dot
49
+ or dash; names with spaces or shell characters are refused, as is an existing
50
+ target directory.
51
+ - A failed creation exits with a non-zero status and removes the half-written
52
+ project instead of leaving it behind.
53
+ - New projects write independent JWT and session keys to `.env`, which
54
+ `.gitignore` keeps out of version control. Local starts no longer warn about a
55
+ random process-local session key, and logins survive a restart or an added
56
+ worker.
57
+
58
+ ### Mail and utilities
59
+
60
+ - Building a `cloudoll.mail.smtp.Client` no longer reaches the network, and one
61
+ client stays usable across sends and server idle timeouts: each `send()` opens
62
+ its own connection, carries one copy of the body, and closes the connection even
63
+ when the send fails.
64
+ - Missing credentials and an empty recipient address now raise a readable error
65
+ before anything is sent.
66
+ - `cloudoll.utils` - reversible encryption, keyed digests, random strings and the
67
+ distributed ID generator - is now official API with a
68
+ [utilities](https://cloudoll.chuchur.com/utils) page and regression tests. None
69
+ of them is a password hash; store user passwords with bcrypt or argon2.
70
+ - New [mail](https://cloudoll.chuchur.com/mail) page documents sending limits
71
+ (SMTPS 465 only, no STARTTLS, no retry or queue). The dead POP3 draft under
72
+ `cloudoll/mail` is gone - Cloudoll does not receive mail.
73
+
74
+ ### Upgrade notes
75
+
76
+ - `for_update()` outside a transaction and unexpected `render_view()` keywords now
77
+ raise rather than misbehaving quietly; audit those two call shapes before
78
+ upgrading.
79
+ - `cloudoll create` rejects names it used to accept, such as `my shop`, because
80
+ they reached a shell unsafely.
81
+ - Projects created before this release keep an old `config/conf.local.yaml`
82
+ without a session key; add `session.secret_key` (or set
83
+ `CLOUDOLL_SESSION_SECRET`) so sessions survive restarts and multiple workers.
84
+ - Existing `.env` files need the new `CLOUDOLL_SESSION_SECRET` entry; `.env` has
85
+ always been ignored by the project's `.gitignore`.
86
+
87
+ ### Documentation
88
+
89
+ - JWT middleware examples use `web.RequestKey` instead of a plain string key, so
90
+ aiohttp stops warning about it.
91
+ - The quick start and session pages describe how a new project injects its keys.
92
+
93
+ ## 4.3.0
94
+
95
+ ### ORM queries and writes
96
+
97
+ - Add explicit LEFT/INNER/RIGHT JOIN kinds, query-level DISTINCT, `one_dict()`
98
+ for projected/aggregate rows, and non-consuming `exists()` checks.
99
+ - Add parameterized scalar/IN and EXISTS/NOT EXISTS subqueries with snapshot
100
+ semantics and datasource/dialect compatibility checks.
101
+ - Add read-only table aliases for self-joins, non-recursive CTEs, and
102
+ UNION/UNION ALL with branch-local and outer pagination semantics.
103
+ - Add atomic expression-valued updates and transaction-owned `for_update()`
104
+ row locks, including mutually exclusive NOWAIT and SKIP LOCKED options.
105
+ - Add single-statement `upsert()` with explicit update fields; PostgreSQL
106
+ supports conflict targets, while MySQL explicitly rejects that option.
107
+ - Export `Relation` and `Subquery` types. Reject writes against aliases,
108
+ CTE/UNION sources and joined queries rather than silently ignoring sources.
109
+
110
+ ### Documentation and verification
111
+
112
+ - Expand grouping/HAVING, aggregates, default datasource usage and query
113
+ result contracts. Normal application CRUD defaults to entity APIs without
114
+ unnecessary `.use(db)` or handwritten SQL.
115
+ - Update bundled AI guidance and version-matched examples, including locking,
116
+ unique constraints, snapshots and unsupported advanced combinations.
117
+ - Add MySQL 8.4/PostgreSQL 16 integration coverage for query sources, upserts,
118
+ concurrency, rollback and row-lock contention. Aurora remains unverified.
119
+
120
+ ## 4.2.1
121
+
122
+ - Correct the AI initialization regression test to compare the original bytes
123
+ rather than assume LF newlines on Windows. Keep preservation and idempotence
124
+ assertions enabled on every platform.
125
+ - Normalize the generated full documentation's trailing newline.
126
+ - Include all 4.2.0 features. The 4.2.0 tag was blocked by Windows CI and was
127
+ not published to PyPI; 4.2.1 is the replacement release.
128
+
129
+ ## 4.2.0
130
+
131
+ Backward-compatible AI-assisted development release. Python 3.9+ remains supported.
132
+
133
+ - Add offline `cloudoll ai list`, `read`, and `search` commands for bundled official
134
+ documentation, with source URLs, version metadata and content integrity checks.
135
+ - Add `cloudoll ai init` for existing projects. New scaffolds automatically include
136
+ an AGENTS.md entry and a project-local Cloudoll skill covering documented project
137
+ structure, validation, ORM, resource lifecycle, security and verification.
138
+ - Preserve existing project instructions and refuse to overwrite customized skills
139
+ or write through symbolic links. Initialization is repeatable.
140
+ - Add documentation synchronization tooling and website LLM discovery assets.
141
+ Test both instruction initialization and AI resources in the built wheel.
142
+
143
+ ## 4.1.0
144
+
145
+ Backward-compatible feature release. Pydantic 2 (`>=2.0,<3`) is now a core
146
+ runtime dependency. Existing handlers and explicit ORM engine bindings remain
147
+ supported. Python 3.9+ remains supported by the CI matrix.
148
+
149
+ - Correct lifecycle callback and JWT payload type declarations for strict
150
+ checking with current dependency annotations.
151
+ - Include HTTP method and actual request path in exception logs; emit 4xx access
152
+ logs at WARNING and 5xx at ERROR so failed requests remain visible above INFO.
153
+
154
+ - Add Pydantic 2 request validation with typed `Body`, `Query`, `Form`, and
155
+ `Path` bindings, repeated collection parameters and structured HTTP 400 errors.
156
+ Preserve legacy request and streaming multipart handlers.
157
+
158
+ - Add application-local named ORM datasources via `orm.default` and model
159
+ `__datasource__`, independent class-level queries, `Model.query()` and
160
+ `Model.transaction()`. Reuse existing task-owned engine transactions.
161
+ - Add `datasource_context` for scoped standalone/test engine bindings. Keep
162
+ explicit `.use(engine)`, offline SQL compilation and bound records compatible.
163
+
164
+ ## 4.0.0
165
+
166
+ This release contains breaking changes to configuration, security, ORM and the
167
+ application lifecycle. Read the migration guide before upgrading.
168
+
169
+ ### Breaking changes and migration
170
+
171
+ - Python 3.9+ is required; database/cache drivers are optional extras.
172
+ - Configuration values no longer execute Python expressions. Supply literal
173
+ numeric values and inject required environment variables explicitly.
174
+ - `Model.use()` returns an independent Query. Records use UNSET and dirty-field
175
+ snapshots; successful outer commits update the saved baseline. Database errors
176
+ propagate instead of appearing as empty results.
177
+ - PostgreSQL ORM inserts use RETURNING. Raw inserts without RETURNING and batch
178
+ inserts do not manufacture a primary key.
179
+ - Sessions require a private, stable key for multi-worker/restart persistence;
180
+ discard cookies created with old publicly derivable keys.
181
+ - Middleware uses the direct async decorator contract. Application creation is
182
+ instance-local and may only be performed once per instance.
183
+ - CLI service identity includes process creation time and command line. Unknown
184
+ legacy PID identities are not killed automatically; stop old services safely
185
+ before upgrading. Production mode remains foreground, not a process supervisor.
186
+
187
+ ### ORM and developer experience
188
+
189
+ - Added native MySQL/PostgreSQL transactions, nested savepoints, scoped streaming,
190
+ generic Query/Field typing and dialect-specific schema generation.
191
+ - Added opt-in SQL/parameter echo, connection/query/cleanup timeouts, and safe
192
+ cancellation. Writes and uncertain commits are never automatically replayed.
193
+ - Added isolated route/module discovery and explicit application components.
194
+ - Development children and reloads create a fresh Application at the explicit
195
+ project root instead of inheriting a parent's cached app/context through fork.
196
+ - Scaffold dependencies now target Cloudoll 4.0.0; scaffold business code remains
197
+ illustrative, not a complete application authorization system.
198
+
199
+ ### Core production hardening
200
+
201
+ - Explicitly selected missing configuration files now raise `FileNotFoundError`.
202
+ Use `Application.create(env=None)` or `config={}` for intentional no-config mode.
203
+ - Library-owned configuration types/ranges are validated before startup and after
204
+ `on_create`. Custom business/plugin keys remain supported.
205
+ - JWT verification requires `exp` by default and supports issuer, audience,
206
+ leeway and required claims. Invalid tokens return `None`; configuration errors
207
+ raise. Explicit `require=()` is the legacy-token escape hatch.
208
+ - Native pool close and application resource cleanup have finite deadlines.
209
+ - Added JSON logging, structured-data masking, string-redaction extension,
210
+ trace correlation and value-free HTTP/native query observation events.
211
+ - Added native deadlock/commit-cancellation regression tests and dependency audit CI.
212
+
213
+ ### Migration
214
+
215
+ See [reliability](docs/reliability.md) for the existing transaction, savepoint,
216
+ UNSET/dirty-field, CLI/PID, SQL echo and request parsing changes. See
217
+ [production contracts](docs/production.md) for the new configuration and APIs.
218
+
219
+ Aurora transactions and connection reuse are implemented but remain untested.
220
+ Native driver validation must not be presented as Aurora failover validation.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloudoll
3
- Version: 4.2.1
3
+ Version: 4.4.0
4
4
  Summary: Assist in quickly creating distributable microservices based on aiohttp, with a focus on simplicity and ease of use.
5
5
  Author-email: Qiu <smallerqiu@gmail.com>
6
6
  License-Expression: MIT
@@ -54,7 +54,7 @@ Dynamic: license-file
54
54
 
55
55
  English | [简体中文](README.zh-CN.md)
56
56
 
57
- Cloudoll 4.2.1 is an aiohttp-based Python library for routing, middleware,
57
+ Cloudoll 4.4.0 is an aiohttp-based Python library for routing, middleware,
58
58
  templates, sessions, JWT, database access and application scaffolding.
59
59
 
60
60
  ## AI-assisted development
@@ -71,8 +71,8 @@ does not have `cloudoll ai --help`, consult its matching README and source first
71
71
  Python 3.9+ is required. Install only the optional drivers you use:
72
72
 
73
73
  ```sh
74
- python -m pip install 'cloudoll==4.2.1'
75
- python -m pip install 'cloudoll[mysql,postgres,cache]==4.2.1'
74
+ python -m pip install 'cloudoll==4.4.0'
75
+ python -m pip install 'cloudoll[mysql,postgres,cache]==4.4.0'
76
76
  ```
77
77
 
78
78
  The AWS extra requires Python 3.10+. Aurora remains untested; see
@@ -87,7 +87,8 @@ python -m pip install -r requirements.txt
87
87
  cloudoll start -n myapp
88
88
  ```
89
89
 
90
- The generated project targets 4.2.1 and receives a random JWT secret. Controllers
90
+ The generated project targets 4.4.0 and receives random JWT and session secrets
91
+ in `.env`. Controllers
91
92
  and authentication middleware are examples: replace demo credentials and supply
92
93
  your own authorization and upload policies before deployment.
93
94
 
@@ -172,8 +173,8 @@ python -m ruff check cloudoll tests
172
173
  python -m mypy
173
174
  python -m pytest -q -m 'not integration' -k 'not aws'
174
175
  python -m build
175
- python tests/check_wheel.py dist/cloudoll-4.2.1-py3-none-any.whl
176
- python tests/check_release.py dist/cloudoll-4.2.1-py3-none-any.whl
176
+ python tests/check_wheel.py dist/cloudoll-4.4.0-py3-none-any.whl
177
+ python tests/check_release.py dist/cloudoll-4.4.0-py3-none-any.whl
177
178
  ```
178
179
 
179
180
  Native integration tests require explicitly configured disposable databases.
@@ -2,7 +2,7 @@
2
2
 
3
3
  English | [简体中文](README.zh-CN.md)
4
4
 
5
- Cloudoll 4.2.1 is an aiohttp-based Python library for routing, middleware,
5
+ Cloudoll 4.4.0 is an aiohttp-based Python library for routing, middleware,
6
6
  templates, sessions, JWT, database access and application scaffolding.
7
7
 
8
8
  ## AI-assisted development
@@ -19,8 +19,8 @@ does not have `cloudoll ai --help`, consult its matching README and source first
19
19
  Python 3.9+ is required. Install only the optional drivers you use:
20
20
 
21
21
  ```sh
22
- python -m pip install 'cloudoll==4.2.1'
23
- python -m pip install 'cloudoll[mysql,postgres,cache]==4.2.1'
22
+ python -m pip install 'cloudoll==4.4.0'
23
+ python -m pip install 'cloudoll[mysql,postgres,cache]==4.4.0'
24
24
  ```
25
25
 
26
26
  The AWS extra requires Python 3.10+. Aurora remains untested; see
@@ -35,7 +35,8 @@ python -m pip install -r requirements.txt
35
35
  cloudoll start -n myapp
36
36
  ```
37
37
 
38
- The generated project targets 4.2.1 and receives a random JWT secret. Controllers
38
+ The generated project targets 4.4.0 and receives random JWT and session secrets
39
+ in `.env`. Controllers
39
40
  and authentication middleware are examples: replace demo credentials and supply
40
41
  your own authorization and upload policies before deployment.
41
42
 
@@ -120,8 +121,8 @@ python -m ruff check cloudoll tests
120
121
  python -m mypy
121
122
  python -m pytest -q -m 'not integration' -k 'not aws'
122
123
  python -m build
123
- python tests/check_wheel.py dist/cloudoll-4.2.1-py3-none-any.whl
124
- python tests/check_release.py dist/cloudoll-4.2.1-py3-none-any.whl
124
+ python tests/check_wheel.py dist/cloudoll-4.4.0-py3-none-any.whl
125
+ python tests/check_release.py dist/cloudoll-4.4.0-py3-none-any.whl
125
126
  ```
126
127
 
127
128
  Native integration tests require explicitly configured disposable databases.
@@ -2,11 +2,11 @@
2
2
 
3
3
  [English](README.md) | 简体中文
4
4
 
5
- 生产配置、资源关闭期限、JWT 验证、JSON 日志与监控接入见 [生产运行契约](docs/production.md);版本兼容及发布检查见 [维护政策](docs/maintenance.md),安全问题报告见 [SECURITY.md](SECURITY.md)。
5
+ 生产配置、资源关闭期限、JWT 验证、JSON 日志与监控接入见 [生产运行契约](docs/production.md);版本兼容及发布检查见 [维护政策](docs/maintenance.md);各版本变化见 [更新日志](CHANGELOG.zh-CN.md),安全问题报告见 [SECURITY.md](SECURITY.md)。
6
6
 
7
7
  Cloudoll 是一个基于 aiohttp 的 Python Web 开发库,提供路由自动注册、中间件、模板渲染、会话管理、JWT、数据库访问及命令行脚手架,帮助快速构建 Web 应用和微服务。
8
8
 
9
- 本文适用于 Cloudoll 4.2.1。从 3.x 升级前请阅读下方迁移说明。
9
+ 本文适用于 Cloudoll 4.4.0。从 3.x 升级前请阅读下方迁移说明。
10
10
 
11
11
  ## AI 辅助开发
12
12
 
@@ -25,10 +25,10 @@ Cloudoll 是一个基于 aiohttp 的 Python Web 开发库,提供路由自动
25
25
 
26
26
  ## 安装
27
27
 
28
- 安装 4.2.1:
28
+ 安装 4.4.0:
29
29
 
30
30
  ```sh
31
- python -m pip install 'cloudoll==4.2.1'
31
+ python -m pip install 'cloudoll==4.4.0'
32
32
  ```
33
33
 
34
34
  在当前仓库目录安装源码:
@@ -41,16 +41,16 @@ python -m pip install -e .
41
41
 
42
42
  ```sh
43
43
  # MySQL
44
- python -m pip install 'cloudoll[mysql]==4.2.1'
44
+ python -m pip install 'cloudoll[mysql]==4.4.0'
45
45
 
46
46
  # PostgreSQL
47
- python -m pip install 'cloudoll[postgres]==4.2.1'
47
+ python -m pip install 'cloudoll[postgres]==4.4.0'
48
48
 
49
49
  # AWS 数据库驱动
50
- python -m pip install 'cloudoll[aws]==4.2.1'
50
+ python -m pip install 'cloudoll[aws]==4.4.0'
51
51
 
52
52
  # Redis / Memcached 会话或 Redis 数据库
53
- python -m pip install 'cloudoll[cache]==4.2.1'
53
+ python -m pip install 'cloudoll[cache]==4.4.0'
54
54
  ```
55
55
 
56
56
  源码开发时可用 `python -m pip install -e '.[mysql,postgres,cache,dev]'` 安装。
@@ -89,7 +89,7 @@ myapp/
89
89
  └── templates/
90
90
  ```
91
91
 
92
- 脚手架中的鉴权中间件和登录接口用于演示。正式使用前,应替换示例账号、密码和业务鉴权逻辑。新建项目会获得独立的 JWT 密钥。
92
+ 脚手架中的鉴权中间件和登录接口用于演示。正式使用前,应替换示例账号、密码和业务鉴权逻辑。新建项目会在 `.env` 里获得相互独立的 JWT 与 Session 密钥。
93
93
 
94
94
  ### 手动创建应用
95
95
 
@@ -546,8 +546,8 @@ cloudoll restart -n myapp
546
546
  python -m pip install -e '.[mysql,postgres,cache,dev]'
547
547
  python -m pytest -q -m 'not integration' -k 'not aws'
548
548
  python -m build
549
- python tests/check_wheel.py dist/cloudoll-4.2.1-py3-none-any.whl
550
- python tests/check_release.py dist/cloudoll-4.2.1-py3-none-any.whl
549
+ python tests/check_wheel.py dist/cloudoll-4.4.0-py3-none-any.whl
550
+ python tests/check_release.py dist/cloudoll-4.4.0-py3-none-any.whl
551
551
  ```
552
552
 
553
553
  最后一条命令用于验证构建出的 wheel,版本号变化后请调整文件名。测试使用模拟数据库连接及本机 HTTP 服务;真实数据库连接和 AWS 故障切换需要单独的集成环境。
@@ -0,0 +1 @@
1
+ __version__ = "4.4.0"
@@ -5,3 +5,7 @@ Before building or changing a Cloudoll application, read `.agents/skills/cloudol
5
5
  Official documentation is bundled with the installed library: `python -m cloudoll.cli ai list`, `ai read <topic>`, and `ai search <query>`. These commands work offline without MCP. Read `structure`, `config`, `router`, and `validation` before designing an application; read `database` before database work. Consult the installed source when resolving a signature discrepancy; report the discrepancy rather than inventing an API.
6
6
 
7
7
  Prefer the documented scaffold, auto-discovered controllers/middlewares, YAML configuration, framework-owned database lifecycle, typed request validation, and ORM for ordinary CRUD. Low-level alternatives require a task-specific reason. Never silently replace Cloudoll's architecture with patterns from another framework.
8
+
9
+ Ordinary CRUD, joins, filters, aliases, counts and pagination use entity/Query APIs. With initialized application datasources and `orm.default`, omit `.use(db)` in routes and services; explicit binding is for intentional overrides or context-free scripts/tests. Before using raw SQL, verify and state the specific ORM capability gap, not merely that the query contains JOIN or COUNT.
10
+
11
+ Grouping, HAVING and aggregate expressions are also supported. Consult the installed database topic for the full capability inventory; 4.3.0 additions must not be assumed available in an older installed release.
@@ -49,6 +49,8 @@ python -m cloudoll.cli ai search transaction
49
49
  .agents/skills/cloudoll/SKILL.md,再通过 cloudoll ai read 查阅相关文档。
50
50
  新项目遵循自动发现的 controllers/middlewares、YAML 配置、框架管理的
51
51
  数据库生命周期、类型化参数校验和 ORM。若需要偏离默认方案,先说明理由。
52
+ 普通 CRUD、联表、筛选、计数和分页用实体 API;配置 orm.default 后,
53
+ 应用代码默认省略 .use(db)。原始 SQL 须先确认并说明当前 ORM 的具体能力缺口。
52
54
  完成后说明查阅的主题、测试结果和未验证的部分。
53
55
  ```
54
56
 
@@ -6,10 +6,74 @@ icon: logs
6
6
 
7
7
  # 更新日志
8
8
 
9
- 按版本倒序记录 Cloudoll 的主要变化。当前使用方法请以本站 4.2.1 文档为准,历史功能不代表当前仍保留相同 API。
9
+ 按版本倒序记录 Cloudoll 的主要变化。当前使用方法请以本站 4.4.0 文档为准,历史功能不代表当前仍保留相同 API。
10
10
 
11
11
  历史版本日期为对应源码提交日期。各版本源码可通过表格中的链接查看。
12
12
 
13
+ ## 4.4.0
14
+
15
+ 缺陷修复版本,向后兼容;Python 3.9+ 仍然支持。
16
+
17
+ ### 数据库
18
+
19
+ - `for_update()` 行锁必须在调用方自己的事务里使用。以前脱离事务的写法会临时开一个事务,锁随提交立刻释放,实际什么都没锁住;现在这样的调用直接报错。
20
+ - 开启事务时获取连接超时或被取消,已借到的连接会归还连接池,服务跑久了不再慢慢耗光连接。
21
+ - 模型字段恢复可哈希,可以放进 `set` 或作为字典键(列去重、批量排除字段)。
22
+ - `SUM(DISTINCT column)` 等聚合去重编译到聚合函数内部,去重发生在求和之前;聚合里的字面量不再被重复绑定参数。
23
+ - AWS 数据源串里的 URL 查询参数不再作为未知参数传给驱动。
24
+
25
+ ### Web 与模板
26
+
27
+ - 已经开始输出的响应不再被 JSON 错误处理改写坏,流式与 SSE 接口出错时保留原响应。
28
+ - 页面响应的 `Content-Type` 不再出现两个 `charset`。
29
+ - `session` 的 `key`、`max_age`、`httponly`、`secure`、`domain`、`path`、`samesite` 在加密 Cookie、Redis、Memcached 三种存储下都生效。
30
+ - `render_view()` 的关键字参数只归一处:模板上下文按位置传字典,关键字参数一律是 `Response` 选项,传错直接抛 `TypeError`,不再被当成上下文吞掉。
31
+ - 默认监听 127.0.0.1,开发模式不再额外占用配置端口 +1。
32
+ - `server.ignore_dirs` 对 `logs` 等目录生效,写日志不再触发热重载。
33
+ - 脚手架的鉴权中间件示例与文档一致:async 装饰器写法,放行静态资源,不再把后续处理器的异常吞成带错误文本的 500。
34
+
35
+ ### 命令行与新建项目
36
+
37
+ - `cloudoll create` 不再把 `__pycache__`、`.pyc` 复制进新项目。
38
+ - 项目名最后一段只能是字母、数字、下划线、点、短横线;带空格或 shell 元字符的名字被拒绝,已存在的目标目录也会报错。
39
+ - 创建失败时退出码非 0,并回收只写了一半的目录,不会留下半个项目。
40
+ - 新项目在 `.env` 里同时生成 JWT 与 Session 两把独立密钥,配置读取环境变量,`.gitignore` 忽略 `.env`。本地启动不再出现“使用随机进程本地密钥”的告警,重启和多 worker 之间登录状态不再丢失。
41
+
42
+ ### 邮件与工具函数
43
+
44
+ - 邮件客户端构造时不再立刻联网,发送过一次或服务器空闲断开后仍能继续使用:每次 `send()` 自建连接、只带一份正文,失败时也会关闭连接。
45
+ - 缺少账号或授权码、收件人为空时立即给出可读错误,不再留给服务器报认证失败。
46
+ - `cloudoll.utils` 的可逆加密、单向摘要、随机字符串、分布式 ID 成为正式 API,见[工具函数](/utils)。存用户密码请改用 bcrypt/argon2,这些工具都不是口令哈希。
47
+ - 新增[发送邮件](/mail)页;`cloudoll/mail` 下从未生效的 POP3 草稿文件被移除,库本身不提供收信能力。
48
+
49
+ ### 升级提示
50
+
51
+ - 在事务外调用 `for_update()`、给 `render_view()` 传多余关键字,以前是静默出错,现在会抛异常;升级前先检查这两类调用。
52
+ - `cloudoll create` 开始拒绝带空格和 shell 元字符的项目名。
53
+ - 老项目请自行补上 `session.secret_key` 或 `CLOUDOLL_SESSION_SECRET`,否则重启、多 worker 之间仍会丢登录状态。
54
+
55
+ ### 文档
56
+
57
+ - JWT 中间件示例改用 `web.RequestKey`,避免 aiohttp 的字符串键告警。
58
+ - [快速开始](/)与 [Cookie 与 Session](/session-cookie)说明新项目的密钥注入方式。
59
+
60
+ ## 4.3.0
61
+
62
+ ### ORM 查询与写入
63
+
64
+ - JOIN 新增显式 LEFT/INNER/RIGHT 类型,默认保持 LEFT;增加查询级 `distinct()`、保留聚合与别名列的 `one_dict()`、不消费查询的 `exists()`。
65
+ - 新增参数化 IN、标量、EXISTS/NOT EXISTS 子查询,创建时快照 SQL 与参数,并校验数据源和方言。
66
+ - 新增 `Model.alias()` 表别名和自连接、非递归 CTE、UNION/UNION ALL;区分分支分页与合并结果分页,保留正确计数语义。
67
+ - 新增表达式原子更新和 `for_update()` 行锁,支持 NOWAIT、SKIP LOCKED;事务由调用方管理,不自动重试。
68
+ - 新增单条原子 `upsert()`,显式指定更新列;PostgreSQL 支持冲突目标,MySQL 明确拒绝不能实现的冲突目标选项。
69
+ - 导出 `Relation`、`Subquery` 类型;明确拒绝别名、CTE、UNION 和 JOIN 查询的直接写入,避免静默忽略查询源。
70
+
71
+ ### 文档与验证
72
+
73
+ - 补齐 GROUP BY、HAVING、聚合、返回类型和默认数据源示例;普通应用 CRUD 优先实体 API,不必重复 `.use(db)`。
74
+ - 同步 AI 指引与随包文档,说明行锁、唯一约束、版本适用范围和高级查询限制。
75
+ - 增加 MySQL 8.4 / PostgreSQL 16 真实数据库测试,覆盖并发 upsert、回滚、锁竞争、CTE 和 UNION。Aurora 仍未经过真实环境验证。
76
+
13
77
  ## 4.2.1
14
78
 
15
79
  - 修正 AI 初始化测试对 Windows CRLF 换行的错误假设,继续验证原有内容保留和重复初始化不变。
@@ -26,8 +90,6 @@ icon: logs
26
90
 
27
91
  ## 4.1.0
28
92
 
29
- 本节对应 4.1.0 源码变更;实际发布状态以 PyPI 为准。
30
-
31
93
  - [默认数据源](/database#默认数据源与模型绑定):orm.default、模型 __datasource__、独立类级查询、query() 与 transaction(),保留显式 use(engine)。
32
94
  - datasource_context 为独立任务和测试提供作用域绑定;事务复用现有引擎机制,应用与并发任务保持隔离。
33
95
  - [请求参数校验](/validation):Pydantic 2 支持 Body、Query、Form、Path,重复数组参数和结构化 HTTP 400,兼容旧接口与流式上传。
@@ -14,9 +14,21 @@ CLI 默认读取项目根目录的 `config/conf.local.yaml`。选择生产配置
14
14
  cloudoll start -n myapp -env prod -m production
15
15
  ```
16
16
 
17
- `-env prod` 选择文件,`-m production` 选择运行模式,两者不是同一个开关。通过 `--host` / `--port` 可覆盖监听地址;未传入时使用配置。入口参数 `-e app` 是模块名,不是 `app.py`。
17
+ `-env prod` 选择文件,`-m production` 选择运行模式,两者不是同一个开关。通过 `--host` / `--port` 可覆盖监听地址;未传入时使用配置。配置也缺省时,监听地址为本机回环 `127.0.0.1`、端口 `9001`;需要对外提供服务时显式写入 `server.host: 0.0.0.0` 或使用 `--host 0.0.0.0`。开发模式只有工作进程监听业务端口,监督进程不占用其他端口。入口参数 `-e app` 是模块名,不是 `app.py`。
18
18
 
19
- 配置必须是 YAML 映射;加载时使用安全 YAML 解析和严格环境变量展开。缺少环境变量会报错。Cloudoll 没有自动加载项目 `.env` 文件的逻辑,应由 shell、容器或进程管理器注入变量。
19
+ 配置必须是 YAML 映射;加载时使用安全 YAML 解析,并通过 EnvYAML 严格展开环境变量。默认情况下,缺少引用的环境变量会报错。
20
+
21
+ ### `.env` 文件
22
+
23
+ EnvYAML 会自动读取当前工作目录下的 `.env`。从项目根目录启动时,可将配置中引用的变量放在根目录的 `.env` 中,也可以由 shell、容器或进程管理器注入。
24
+
25
+ - 可通过进程环境变量 `ENV_FILE` 指定其他文件;从不同目录启动时,建议使用绝对路径。
26
+ - 默认 `.env` 路径相对于当前工作目录,不是 YAML 所在目录;`get_config(..., root=...)` 只指定 YAML 配置的根目录,不改变 `.env` 的查找位置。
27
+ - 当前 EnvYAML 实现中,文件中的变量会覆盖同名进程环境变量,再用于 YAML 占位符展开。生产环境应避免残留本地 `.env` 覆盖部署配置。
28
+ - 文件变量仅进入 EnvYAML 配置,不会写入 `os.environ`;直接使用 `os.getenv()` 或 `os.environ` 的业务代码不能因此读到这些变量。
29
+ - `-env prod` 选择 `config/conf.prod.yaml`,不会自动切换为 `.env.prod`;需要时通过 `ENV_FILE` 指定。
30
+
31
+ 不要提交包含密码或密钥的 `.env`;可提交仅包含变量名和占位值的 `.env.example`。
20
32
 
21
33
  显式指定的配置文件不存在会抛 FileNotFoundError,不再返回空配置继续启动。核心配置节、端口/请求大小、布尔开关、资源关闭期限和 JWT 策略会在应用创建时校验,on_create 修改后再次校验。业务自定义键仍可使用;数据库驱动参数由相应引擎校验。
22
34
 
@@ -78,9 +78,14 @@ session:
78
78
  max_age: 86400
79
79
  httponly: true
80
80
  secure: false
81
+ domain: .example.com
82
+ path: /
83
+ samesite: Lax
81
84
  ```
82
85
 
83
- 也可只在进程环境设置 CLOUDOLL_SESSION_SECRET。未配置时生成应用进程本地随机密钥,重启会使旧 Session 失效,多进程间也不能共享;生产必须使用一致的随机密钥。更换密钥会使原 Cookie 失效。
86
+ `domain`、`path`、`samesite` 属于 Session Cookie 本身,Cookie、Redis、Memcached 三种存储都读取同一份配置;Redis 存储下不要把这三个键写进 `redis` 子配置。`samesite` 只接受 `Strict`、`Lax`、`None`;`None` 表示不下发该属性,使用浏览器默认策略。`path` 决定浏览器在哪些路径回传 Session Cookie,改成子路径后原路径下的请求将不再带会话。HTTPS 生产环境使用 `secure: true`,此时 `samesite: None` 还要求浏览器允许跨站发送,仅在确有跨站回调时使用。
87
+
88
+ `cloudoll create` 生成的项目已在 `config/conf.local.yaml` 写好 `session.secret_key: $CLOUDOLL_SESSION_SECRET`,并把随机密钥连同 JWT 密钥一起写入项目根目录的 `.env`,开箱即用、重启不掉线;`.env` 已被 `.gitignore` 忽略,生产环境改用环境变量注入同名变量。也可只在进程环境设置 CLOUDOLL_SESSION_SECRET。两处都没有时框架生成应用进程本地随机密钥并记录一次告警,重启会使旧 Session 失效,多进程间也不能共享;生产必须使用一致的随机密钥。更换密钥会使原 Cookie 失效。
84
89
 
85
90
  Cookie 容量有限,不要保存大对象、密码或完整业务数据。客户端加密 Cookie 模式无法仅靠退出操作撤销其他地方留存的旧 Cookie;需要集中撤销时使用服务端存储及业务级会话控制。
86
91