create-windy 0.5.1 → 0.6.0

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 (570) hide show
  1. package/dist/cli.js +486 -156
  2. package/package.json +2 -1
  3. package/template/.windy-template.json +2 -2
  4. package/template/apps/agent-server/README.md +25 -6
  5. package/template/apps/agent-server/src/southwind_agent_server/adk_adapter.py +15 -2
  6. package/template/apps/agent-server/src/southwind_agent_server/app.py +13 -34
  7. package/template/apps/agent-server/src/southwind_agent_server/config.py +49 -0
  8. package/template/apps/agent-server/src/southwind_agent_server/contracts.py +13 -0
  9. package/template/apps/agent-server/src/southwind_agent_server/engine_capacity.py +31 -0
  10. package/template/apps/agent-server/src/southwind_agent_server/fingerprint.py +5 -0
  11. package/template/apps/agent-server/src/southwind_agent_server/health_routes.py +50 -0
  12. package/template/apps/agent-server/src/southwind_agent_server/openai_engine.py +11 -2
  13. package/template/apps/agent-server/src/southwind_agent_server/openai_provider.py +3 -9
  14. package/template/apps/agent-server/src/southwind_agent_server/postgres_store.py +5 -0
  15. package/template/apps/agent-server/src/southwind_agent_server/readiness_pin.py +37 -0
  16. package/template/apps/agent-server/src/southwind_agent_server/run_admission.py +64 -0
  17. package/template/apps/agent-server/src/southwind_agent_server/run_capacity.py +59 -0
  18. package/template/apps/agent-server/src/southwind_agent_server/service.py +42 -43
  19. package/template/apps/agent-server/src/southwind_agent_server/service_errors.py +4 -0
  20. package/template/apps/agent-server/src/southwind_agent_server/service_execution.py +31 -0
  21. package/template/apps/agent-server/src/southwind_agent_server/service_tasks.py +34 -0
  22. package/template/apps/agent-server/src/southwind_agent_server/sqlite_catalog.py +11 -0
  23. package/template/apps/agent-server/src/southwind_agent_server/store.py +6 -0
  24. package/template/apps/agent-server/src/southwind_agent_server/vision_probe.py +87 -0
  25. package/template/apps/agent-server/src/southwind_agent_server/vision_requirement.py +28 -0
  26. package/template/apps/agent-server/src/southwind_agent_server/vlm_readiness.py +247 -0
  27. package/template/apps/agent-server/tests/test_api.py +16 -3
  28. package/template/apps/agent-server/tests/test_openai_provider.py +21 -4
  29. package/template/apps/agent-server/tests/test_postgres_store.py +3 -0
  30. package/template/apps/agent-server/tests/test_run_capacity.py +110 -0
  31. package/template/apps/agent-server/tests/test_runtime_factory_readiness.py +37 -0
  32. package/template/apps/agent-server/tests/test_sqlite_store.py +3 -0
  33. package/template/apps/agent-server/tests/test_vision_readiness_enforcement.py +72 -0
  34. package/template/apps/agent-server/tests/test_vlm_readiness.py +106 -0
  35. package/template/apps/document-server/src/southwind_document_server/adapter.py +117 -205
  36. package/template/apps/document-server/src/southwind_document_server/adapter_errors.py +13 -0
  37. package/template/apps/document-server/src/southwind_document_server/app.py +62 -14
  38. package/template/apps/document-server/src/southwind_document_server/artifacts.py +27 -0
  39. package/template/apps/document-server/src/southwind_document_server/config.py +96 -2
  40. package/template/apps/document-server/src/southwind_document_server/contracts.py +168 -13
  41. package/template/apps/document-server/src/southwind_document_server/fingerprint.py +128 -0
  42. package/template/apps/document-server/src/southwind_document_server/grants.py +81 -0
  43. package/template/apps/document-server/src/southwind_document_server/multipart_output.py +265 -0
  44. package/template/apps/document-server/src/southwind_document_server/output_validation.py +202 -0
  45. package/template/apps/document-server/src/southwind_document_server/progress.py +27 -0
  46. package/template/apps/document-server/src/southwind_document_server/readiness.py +280 -0
  47. package/template/apps/document-server/src/southwind_document_server/readiness_contracts.py +280 -0
  48. package/template/apps/document-server/src/southwind_document_server/readiness_http.py +87 -0
  49. package/template/apps/document-server/src/southwind_document_server/readiness_support.py +120 -0
  50. package/template/apps/document-server/src/southwind_document_server/request_validation.py +48 -0
  51. package/template/apps/document-server/src/southwind_document_server/service.py +297 -96
  52. package/template/apps/document-server/src/southwind_document_server/service_recovery.py +183 -0
  53. package/template/apps/document-server/src/southwind_document_server/sink.py +316 -0
  54. package/template/apps/document-server/src/southwind_document_server/store.py +301 -141
  55. package/template/apps/document-server/src/southwind_document_server/store_events.py +40 -0
  56. package/template/apps/document-server/src/southwind_document_server/store_models.py +62 -0
  57. package/template/apps/document-server/src/southwind_document_server/store_recovery.py +247 -0
  58. package/template/apps/document-server/src/southwind_document_server/store_schema.py +50 -0
  59. package/template/apps/document-server/tests/recovery_support.py +230 -0
  60. package/template/apps/document-server/tests/support.py +210 -0
  61. package/template/apps/document-server/tests/test_adapter.py +251 -0
  62. package/template/apps/document-server/tests/test_config.py +43 -0
  63. package/template/apps/document-server/tests/test_contracts.py +80 -0
  64. package/template/apps/document-server/tests/test_fingerprint.py +125 -0
  65. package/template/apps/document-server/tests/test_grants.py +46 -0
  66. package/template/apps/document-server/tests/test_handshake.py +154 -0
  67. package/template/apps/document-server/tests/test_integration.py +192 -0
  68. package/template/apps/document-server/tests/test_multipart_security.py +259 -0
  69. package/template/apps/document-server/tests/test_readiness.py +311 -0
  70. package/template/apps/document-server/tests/test_readiness_contracts.py +131 -0
  71. package/template/apps/document-server/tests/test_recovery.py +222 -0
  72. package/template/apps/document-server/tests/test_recovery_faults.py +101 -0
  73. package/template/apps/document-server/tests/test_recovery_races.py +283 -0
  74. package/template/apps/document-server/tests/test_service.py +16 -13
  75. package/template/apps/document-server/tests/test_service_artifacts.py +296 -0
  76. package/template/apps/document-server/tests/test_sink.py +253 -0
  77. package/template/apps/document-server/tests/test_store.py +199 -0
  78. package/template/apps/embedding-server/pyproject.toml +5 -0
  79. package/template/apps/embedding-server/src/southwind_embedding_server/adapter.py +38 -2
  80. package/template/apps/embedding-server/src/southwind_embedding_server/app.py +111 -3
  81. package/template/apps/embedding-server/src/southwind_embedding_server/config.py +27 -0
  82. package/template/apps/embedding-server/src/southwind_embedding_server/image_input.py +16 -5
  83. package/template/apps/embedding-server/src/southwind_embedding_server/run_cipher.py +31 -0
  84. package/template/apps/embedding-server/src/southwind_embedding_server/run_service.py +130 -0
  85. package/template/apps/embedding-server/src/southwind_embedding_server/run_store.py +250 -0
  86. package/template/apps/embedding-server/tests/test_adapter.py +25 -0
  87. package/template/apps/embedding-server/tests/test_run_http.py +185 -0
  88. package/template/apps/embedding-server/tests/test_run_service.py +200 -0
  89. package/template/apps/embedding-server/uv.lock +71 -0
  90. package/template/apps/server/Dockerfile +13 -0
  91. package/template/apps/server/package.json +1 -0
  92. package/template/apps/server/src/agent/drizzle-screenshot-intake-repository.integration.test.ts +283 -0
  93. package/template/apps/server/src/agent/drizzle-screenshot-intake-repository.ts +175 -0
  94. package/template/apps/server/src/agent/persistent-screenshot-intake-producer.ts +320 -0
  95. package/template/apps/server/src/agent/remote-runtime.ts +8 -1
  96. package/template/apps/server/src/agent/required-environment.ts +5 -0
  97. package/template/apps/server/src/agent/run-attach.ts +41 -0
  98. package/template/apps/server/src/agent/run-audit.ts +49 -0
  99. package/template/apps/server/src/agent/run-contracts.ts +6 -1
  100. package/template/apps/server/src/agent/run-facade.ts +66 -68
  101. package/template/apps/server/src/agent/run-route-input.ts +26 -1
  102. package/template/apps/server/src/agent/run-routes.ts +1 -0
  103. package/template/apps/server/src/agent/runtime-bootstrap-report.test.ts +1 -1
  104. package/template/apps/server/src/agent/runtime-bootstrap.ts +110 -60
  105. package/template/apps/server/src/agent/runtime-readiness-sources.test.ts +27 -0
  106. package/template/apps/server/src/agent/runtime-readiness-sources.ts +31 -0
  107. package/template/apps/server/src/agent/runtime-reporting-bootstrap.ts +40 -0
  108. package/template/apps/server/src/agent/screenshot-intake-authorization.ts +29 -0
  109. package/template/apps/server/src/agent/screenshot-intake-bootstrap.ts +61 -0
  110. package/template/apps/server/src/agent/screenshot-intake-durable.ts +53 -0
  111. package/template/apps/server/src/agent/screenshot-intake-errors.ts +9 -0
  112. package/template/apps/server/src/agent/screenshot-intake-producer.ts +41 -0
  113. package/template/apps/server/src/agent/screenshot-intake-record.ts +44 -0
  114. package/template/apps/server/src/agent/screenshot-intake-recovery.ts +106 -0
  115. package/template/apps/server/src/agent/screenshot-intake-repository.ts +64 -0
  116. package/template/apps/server/src/agent/screenshot-intake-reservation.ts +24 -0
  117. package/template/apps/server/src/agent/screenshot-intake-routes.ts +171 -0
  118. package/template/apps/server/src/agent/screenshot-intake-runtime-types.ts +6 -0
  119. package/template/apps/server/src/agent/screenshot-intake-sweep.ts +26 -0
  120. package/template/apps/server/src/agent/screenshot-intake-test-support.ts +87 -0
  121. package/template/apps/server/src/agent/screenshot-intake-v2-validation.ts +152 -0
  122. package/template/apps/server/src/agent/screenshot-intake-v2.test.ts +338 -0
  123. package/template/apps/server/src/agent/screenshot-intake-v2.ts +350 -0
  124. package/template/apps/server/src/agent/screenshot-png.ts +15 -0
  125. package/template/apps/server/src/agent/screenshot-run-binding.ts +34 -0
  126. package/template/apps/server/src/agent/unavailable-routes.ts +9 -0
  127. package/template/apps/server/src/agent/vision-facade.test.ts +98 -8
  128. package/template/apps/server/src/agent/vision-input.ts +5 -2
  129. package/template/apps/server/src/agent/vision-readiness-pin.ts +74 -0
  130. package/template/apps/server/src/agent/vision-readiness.ts +58 -0
  131. package/template/apps/server/src/ai-artifact/runtime-reference.test.ts +135 -0
  132. package/template/apps/server/src/ai-artifact/runtime.ts +134 -5
  133. package/template/apps/server/src/ai-output-artifact/cleanup.ts +214 -0
  134. package/template/apps/server/src/ai-output-artifact/contracts.ts +152 -0
  135. package/template/apps/server/src/ai-output-artifact/drizzle-cleanup.ts +37 -0
  136. package/template/apps/server/src/ai-output-artifact/drizzle-complete.ts +71 -0
  137. package/template/apps/server/src/ai-output-artifact/drizzle-grant-cleanup.ts +45 -0
  138. package/template/apps/server/src/ai-output-artifact/drizzle-grants.ts +109 -0
  139. package/template/apps/server/src/ai-output-artifact/drizzle-mapping.ts +77 -0
  140. package/template/apps/server/src/ai-output-artifact/drizzle-readiness.ts +46 -0
  141. package/template/apps/server/src/ai-output-artifact/drizzle-repository.ts +350 -0
  142. package/template/apps/server/src/ai-output-artifact/drizzle-seal.ts +64 -0
  143. package/template/apps/server/src/ai-output-artifact/grant.ts +30 -0
  144. package/template/apps/server/src/ai-output-artifact/host-registry.ts +53 -0
  145. package/template/apps/server/src/ai-output-artifact/memory-cleanup.ts +47 -0
  146. package/template/apps/server/src/ai-output-artifact/memory-grants.ts +98 -0
  147. package/template/apps/server/src/ai-output-artifact/memory-readiness.ts +26 -0
  148. package/template/apps/server/src/ai-output-artifact/memory-repository.ts +348 -0
  149. package/template/apps/server/src/ai-output-artifact/policy.test.ts +67 -0
  150. package/template/apps/server/src/ai-output-artifact/policy.ts +125 -0
  151. package/template/apps/server/src/ai-output-artifact/postgres-test-support.ts +147 -0
  152. package/template/apps/server/src/ai-output-artifact/postgres.integration.test.ts +349 -0
  153. package/template/apps/server/src/ai-output-artifact/reference-codec.ts +128 -0
  154. package/template/apps/server/src/ai-output-artifact/repository-grant-invariants.test-support.ts +165 -0
  155. package/template/apps/server/src/ai-output-artifact/repository-invariants.test-support.ts +239 -0
  156. package/template/apps/server/src/ai-output-artifact/repository-invariants.test.ts +18 -0
  157. package/template/apps/server/src/ai-output-artifact/repository.ts +107 -0
  158. package/template/apps/server/src/ai-output-artifact/route-input.ts +173 -0
  159. package/template/apps/server/src/ai-output-artifact/routes-delete.test.ts +287 -0
  160. package/template/apps/server/src/ai-output-artifact/routes-grant.test.ts +116 -0
  161. package/template/apps/server/src/ai-output-artifact/routes-nonblocking-body.test.ts +136 -0
  162. package/template/apps/server/src/ai-output-artifact/routes-security.test.ts +176 -0
  163. package/template/apps/server/src/ai-output-artifact/routes-storage-error.test.ts +105 -0
  164. package/template/apps/server/src/ai-output-artifact/routes.test-support.ts +84 -0
  165. package/template/apps/server/src/ai-output-artifact/routes.test.ts +198 -0
  166. package/template/apps/server/src/ai-output-artifact/routes.ts +280 -0
  167. package/template/apps/server/src/ai-output-artifact/service-completion.ts +60 -0
  168. package/template/apps/server/src/ai-output-artifact/service-grants.test.ts +169 -0
  169. package/template/apps/server/src/ai-output-artifact/service-grants.ts +217 -0
  170. package/template/apps/server/src/ai-output-artifact/service-input.ts +175 -0
  171. package/template/apps/server/src/ai-output-artifact/service-read.ts +89 -0
  172. package/template/apps/server/src/ai-output-artifact/service-recovery.test.ts +238 -0
  173. package/template/apps/server/src/ai-output-artifact/service-support.ts +240 -0
  174. package/template/apps/server/src/ai-output-artifact/service.test.ts +283 -0
  175. package/template/apps/server/src/ai-output-artifact/service.ts +334 -0
  176. package/template/apps/server/src/ai-output-artifact/storage-recovery.ts +33 -0
  177. package/template/apps/server/src/ai-output-artifact/storage-writer.ts +103 -0
  178. package/template/apps/server/src/ai-output-artifact/test-support.ts +161 -0
  179. package/template/apps/server/src/ai-runtime-readiness/health-response.ts +92 -0
  180. package/template/apps/server/src/ai-runtime-readiness/operation-port-trust.test.ts +66 -0
  181. package/template/apps/server/src/ai-runtime-readiness/operation-port.test-support.ts +143 -0
  182. package/template/apps/server/src/ai-runtime-readiness/operation-port.test.ts +193 -0
  183. package/template/apps/server/src/ai-runtime-readiness/operation-port.ts +172 -0
  184. package/template/apps/server/src/ai-runtime-readiness/trust-store.ts +61 -0
  185. package/template/apps/server/src/app/ai-screenshot-intake-binding.ts +22 -0
  186. package/template/apps/server/src/app/document-output-artifact-bindings.ts +5 -0
  187. package/template/apps/server/src/app/speech-output-artifact-bindings.ts +5 -0
  188. package/template/apps/server/src/application-services.ts +9 -3
  189. package/template/apps/server/src/audit/redaction.ts +1 -0
  190. package/template/apps/server/src/audit/reliable-writer.test.ts +8 -0
  191. package/template/apps/server/src/auth/password-change-license-restriction.test.ts +156 -0
  192. package/template/apps/server/src/document/cancel-response.ts +33 -0
  193. package/template/apps/server/src/document/contracts.ts +6 -0
  194. package/template/apps/server/src/document/errors.ts +11 -0
  195. package/template/apps/server/src/document/facade-cancel.test.ts +226 -0
  196. package/template/apps/server/src/document/facade-cancel.ts +110 -0
  197. package/template/apps/server/src/document/facade-grant-handoff.test.ts +113 -0
  198. package/template/apps/server/src/document/facade-idempotency.test.ts +195 -0
  199. package/template/apps/server/src/document/facade-invocation.ts +46 -0
  200. package/template/apps/server/src/document/facade-output-artifact.test.ts +310 -0
  201. package/template/apps/server/src/document/facade-read-response.ts +116 -0
  202. package/template/apps/server/src/document/facade-readiness.test.ts +95 -0
  203. package/template/apps/server/src/document/facade-support.ts +297 -0
  204. package/template/apps/server/src/document/facade.ts +164 -173
  205. package/template/apps/server/src/document/output-artifact-composition.test.ts +64 -0
  206. package/template/apps/server/src/document/output-artifact-composition.ts +78 -0
  207. package/template/apps/server/src/document/output-artifact-fingerprint.contract.test.ts +110 -0
  208. package/template/apps/server/src/document/output-artifact-fingerprint.ts +150 -0
  209. package/template/apps/server/src/document/output-artifact-host-registry.ts +44 -0
  210. package/template/apps/server/src/document/output-artifact-host.test.ts +332 -0
  211. package/template/apps/server/src/document/output-artifact-host.ts +331 -0
  212. package/template/apps/server/src/document/output-artifact-manifest.test-support.ts +71 -0
  213. package/template/apps/server/src/document/output-artifact-publish.test-support.ts +48 -0
  214. package/template/apps/server/src/document/output-artifact-readiness-probe.ts +347 -0
  215. package/template/apps/server/src/document/output-artifact-readiness-timeout.ts +30 -0
  216. package/template/apps/server/src/document/output-artifact-readiness.test.ts +264 -0
  217. package/template/apps/server/src/document/output-artifact-readiness.ts +87 -0
  218. package/template/apps/server/src/document/output-artifact-route-composition.test.ts +27 -0
  219. package/template/apps/server/src/document/output-artifact-route-composition.ts +14 -0
  220. package/template/apps/server/src/document/output-artifact-runtime.test-support.ts +8 -0
  221. package/template/apps/server/src/document/output-artifact-runtime.test.ts +124 -0
  222. package/template/apps/server/src/document/output-artifact-runtime.ts +275 -0
  223. package/template/apps/server/src/document/output-artifact.test-support.ts +350 -0
  224. package/template/apps/server/src/document/remote-response.ts +162 -0
  225. package/template/apps/server/src/document/remote-runtime.test.ts +100 -4
  226. package/template/apps/server/src/document/remote-runtime.ts +37 -85
  227. package/template/apps/server/src/document/routes-read-response.test.ts +267 -0
  228. package/template/apps/server/src/document/routes.test.ts +109 -0
  229. package/template/apps/server/src/document/routes.ts +23 -14
  230. package/template/apps/server/src/embedding/audit.ts +46 -0
  231. package/template/apps/server/src/embedding/contracts.ts +13 -0
  232. package/template/apps/server/src/embedding/drizzle-run-binding-repository.integration.test.ts +100 -0
  233. package/template/apps/server/src/embedding/drizzle-run-binding-repository.ts +102 -0
  234. package/template/apps/server/src/embedding/facade-types.ts +18 -0
  235. package/template/apps/server/src/embedding/facade.ts +242 -111
  236. package/template/apps/server/src/embedding/operation-authorization.ts +23 -0
  237. package/template/apps/server/src/embedding/remote-runtime.test.ts +18 -0
  238. package/template/apps/server/src/embedding/remote-runtime.ts +77 -0
  239. package/template/apps/server/src/embedding/routes.test.ts +118 -0
  240. package/template/apps/server/src/embedding/routes.ts +98 -0
  241. package/template/apps/server/src/embedding/run-artifact.ts +18 -0
  242. package/template/apps/server/src/embedding/run-authorization.test.ts +133 -0
  243. package/template/apps/server/src/embedding/run-authorization.ts +91 -0
  244. package/template/apps/server/src/embedding/run-binding-repository.ts +75 -0
  245. package/template/apps/server/src/embedding/run-fingerprint.test.ts +52 -0
  246. package/template/apps/server/src/embedding/run-fingerprint.ts +39 -0
  247. package/template/apps/server/src/embedding/terminal-observer.test.ts +26 -0
  248. package/template/apps/server/src/embedding/terminal-observer.ts +44 -0
  249. package/template/apps/server/src/index.ts +38 -31
  250. package/template/apps/server/src/module-host/ai-operation-port.ts +3 -3
  251. package/template/apps/server/src/module-host/durable-context.ts +194 -16
  252. package/template/apps/server/src/module-host/durable-handler-registration.ts +1 -0
  253. package/template/apps/server/src/module-host/durable-storage-filesystem-restart.test.ts +265 -0
  254. package/template/apps/server/src/module-host/durable-storage-write.test.ts +345 -0
  255. package/template/apps/server/src/module-host/http-runtime.ts +25 -0
  256. package/template/apps/server/src/module-host/initialize-contracts.ts +18 -1
  257. package/template/apps/server/src/module-host/initialize.test.ts +18 -0
  258. package/template/apps/server/src/module-host/initialize.ts +42 -2
  259. package/template/apps/server/src/module-host/module-secret-audit-version.test.ts +73 -0
  260. package/template/apps/server/src/module-host/module-secret-binding-resolution.ts +60 -0
  261. package/template/apps/server/src/module-host/module-secret-durable.test.ts +206 -0
  262. package/template/apps/server/src/module-host/module-secret-port.test-support.ts +125 -0
  263. package/template/apps/server/src/module-host/module-secret-port.test.ts +161 -0
  264. package/template/apps/server/src/module-host/module-secret-port.ts +249 -0
  265. package/template/apps/server/src/module-host/module-secret-result.test.ts +324 -0
  266. package/template/apps/server/src/module-host/module-secret-result.ts +274 -0
  267. package/template/apps/server/src/module-host/module-secret-tool-boundary.test.ts +143 -0
  268. package/template/apps/server/src/module-host/project-composition.ts +1 -0
  269. package/template/apps/server/src/module-host/report-staging-port.ts +55 -0
  270. package/template/apps/server/src/module-host/report-staging-registration.test.ts +104 -0
  271. package/template/apps/server/src/module-host/request-context.ts +58 -1
  272. package/template/apps/server/src/module-host/route-declaration.ts +11 -4
  273. package/template/apps/server/src/module-host/route-installer.test-fixture.ts +246 -0
  274. package/template/apps/server/src/module-host/route-installer.test.ts +47 -211
  275. package/template/apps/server/src/module-host/route-installer.ts +192 -21
  276. package/template/apps/server/src/module-host/route-registration.test.ts +44 -4
  277. package/template/apps/server/src/module-host/runtime-composition.ts +2 -0
  278. package/template/apps/server/src/module-host/scoped-host.ts +84 -0
  279. package/template/apps/server/src/module-host/screenshot-artifact-ref.ts +91 -0
  280. package/template/apps/server/src/module-host/screenshot-intake-composition.test.ts +292 -0
  281. package/template/apps/server/src/module-host/screenshot-intake-deadline.ts +38 -0
  282. package/template/apps/server/src/module-host/screenshot-intake-plan.ts +75 -0
  283. package/template/apps/server/src/module-host/screenshot-intake-port.ts +297 -0
  284. package/template/apps/server/src/module-host/screenshot-intake-security.test.ts +311 -0
  285. package/template/apps/server/src/module-host/screenshot-intake-store.ts +76 -0
  286. package/template/apps/server/src/module-host/screenshot-intake-test-support.ts +68 -0
  287. package/template/apps/server/src/module-host/secret-bindings.test.ts +167 -0
  288. package/template/apps/server/src/module-host/secret-bindings.ts +184 -0
  289. package/template/apps/server/src/module-host/storage-authorization-binding.test.ts +242 -0
  290. package/template/apps/server/src/module-host/storage-port.test.ts +8 -1
  291. package/template/apps/server/src/module-host/storage-port.ts +84 -8
  292. package/template/apps/server/src/module-host/storage-restart-fixture.test-support.ts +242 -0
  293. package/template/apps/server/src/module-host/storage-restart-postgres.integration.test.ts +280 -0
  294. package/template/apps/server/src/module-host/storage-scope-drift-http.test.ts +68 -0
  295. package/template/apps/server/src/module-host/storage-scope.ts +52 -1
  296. package/template/apps/server/src/module-host/storage-stream-route.test.ts +282 -0
  297. package/template/apps/server/src/module-host/storage-write-error.test.ts +174 -0
  298. package/template/apps/server/src/module-host/storage-write-error.ts +62 -0
  299. package/template/apps/server/src/module-host/storage-write-port.test.ts +323 -0
  300. package/template/apps/server/src/module-host/storage-write-port.ts +320 -0
  301. package/template/apps/server/src/module-host/storage-write-unavailable.ts +21 -0
  302. package/template/apps/server/src/module-host/storage-writer-retention.test.ts +109 -0
  303. package/template/apps/server/src/module-host/user-directory-composition.test.ts +1 -0
  304. package/template/apps/server/src/module-preflight-secret.test.ts +79 -0
  305. package/template/apps/server/src/module-preflight.ts +5 -0
  306. package/template/apps/server/src/platform-http-runtime.ts +16 -4
  307. package/template/apps/server/src/report-staging/archive-frame-stream.test.ts +209 -0
  308. package/template/apps/server/src/report-staging/archive-frame-stream.ts +341 -0
  309. package/template/apps/server/src/report-staging/archive-process.test.ts +302 -0
  310. package/template/apps/server/src/report-staging/archive-process.ts +257 -0
  311. package/template/apps/server/src/report-staging/archive-volumes.ts +30 -0
  312. package/template/apps/server/src/report-staging/cancellation.ts +13 -0
  313. package/template/apps/server/src/report-staging/contracts.ts +94 -0
  314. package/template/apps/server/src/report-staging/drizzle-lifecycle.ts +278 -0
  315. package/template/apps/server/src/report-staging/drizzle-mapping.ts +140 -0
  316. package/template/apps/server/src/report-staging/drizzle-repository.integration.test.ts +346 -0
  317. package/template/apps/server/src/report-staging/drizzle-repository.ts +255 -0
  318. package/template/apps/server/src/report-staging/drizzle-seal.integration.test.ts +267 -0
  319. package/template/apps/server/src/report-staging/drizzle-seal.ts +177 -0
  320. package/template/apps/server/src/report-staging/filesystem-cleanup.test.ts +68 -0
  321. package/template/apps/server/src/report-staging/filesystem-cleanup.ts +102 -0
  322. package/template/apps/server/src/report-staging/filesystem-errors.ts +15 -0
  323. package/template/apps/server/src/report-staging/filesystem-identifiers.ts +19 -0
  324. package/template/apps/server/src/report-staging/filesystem-io.test.ts +85 -0
  325. package/template/apps/server/src/report-staging/filesystem-io.ts +206 -0
  326. package/template/apps/server/src/report-staging/filesystem-scan.ts +85 -0
  327. package/template/apps/server/src/report-staging/filesystem-store.ts +346 -0
  328. package/template/apps/server/src/report-staging/heartbeat.test.ts +47 -0
  329. package/template/apps/server/src/report-staging/heartbeat.ts +53 -0
  330. package/template/apps/server/src/report-staging/manifest-stream.ts +46 -0
  331. package/template/apps/server/src/report-staging/memory-repository.ts +256 -0
  332. package/template/apps/server/src/report-staging/metadata-catalog.ts +89 -0
  333. package/template/apps/server/src/report-staging/metadata-spool-paths.ts +195 -0
  334. package/template/apps/server/src/report-staging/metadata-spool-schema.ts +54 -0
  335. package/template/apps/server/src/report-staging/metadata-spool.test.ts +214 -0
  336. package/template/apps/server/src/report-staging/metadata-spool.ts +305 -0
  337. package/template/apps/server/src/report-staging/native/archive-frame-helper.c +309 -0
  338. package/template/apps/server/src/report-staging/path-policy.test.ts +127 -0
  339. package/template/apps/server/src/report-staging/path-policy.ts +263 -0
  340. package/template/apps/server/src/report-staging/repository-fence.test.ts +114 -0
  341. package/template/apps/server/src/report-staging/repository.ts +75 -0
  342. package/template/apps/server/src/report-staging/runtime.ts +31 -0
  343. package/template/apps/server/src/report-staging/sealed-file.test.ts +34 -0
  344. package/template/apps/server/src/report-staging/sealed-file.ts +137 -0
  345. package/template/apps/server/src/report-staging/service-input-limits.test.ts +62 -0
  346. package/template/apps/server/src/report-staging/service-input.ts +204 -0
  347. package/template/apps/server/src/report-staging/service-lifecycle.test.ts +132 -0
  348. package/template/apps/server/src/report-staging/service-read-fence.test.ts +37 -0
  349. package/template/apps/server/src/report-staging/service-read.ts +172 -0
  350. package/template/apps/server/src/report-staging/service-support.ts +149 -0
  351. package/template/apps/server/src/report-staging/service.test-fixture.ts +226 -0
  352. package/template/apps/server/src/report-staging/service.test.ts +314 -0
  353. package/template/apps/server/src/report-staging/service.ts +255 -0
  354. package/template/apps/server/src/report-staging/supervised-process.ts +194 -0
  355. package/template/apps/server/src/speech/contracts.ts +8 -0
  356. package/template/apps/server/src/speech/errors.ts +10 -0
  357. package/template/apps/server/src/speech/facade-contract.ts +49 -0
  358. package/template/apps/server/src/speech/facade-output.test.ts +299 -0
  359. package/template/apps/server/src/speech/facade-output.ts +298 -0
  360. package/template/apps/server/src/speech/facade-validation.ts +127 -0
  361. package/template/apps/server/src/speech/facade.ts +185 -151
  362. package/template/apps/server/src/speech/fingerprint.test.ts +42 -0
  363. package/template/apps/server/src/speech/fingerprint.ts +28 -0
  364. package/template/apps/server/src/speech/output-artifact-binding.test.ts +11 -0
  365. package/template/apps/server/src/speech/output-artifact-binding.ts +30 -0
  366. package/template/apps/server/src/speech/output-artifact-error.ts +9 -0
  367. package/template/apps/server/src/speech/output-artifact-host.test-support.ts +73 -0
  368. package/template/apps/server/src/speech/output-artifact-host.test.ts +302 -0
  369. package/template/apps/server/src/speech/output-artifact-host.ts +279 -0
  370. package/template/apps/server/src/speech/output-artifact-policy.ts +114 -0
  371. package/template/apps/server/src/speech/output-artifact-replay.ts +91 -0
  372. package/template/apps/server/src/speech/remote-response.ts +158 -0
  373. package/template/apps/server/src/speech/remote-runtime.test.ts +90 -0
  374. package/template/apps/server/src/speech/remote-runtime.ts +36 -78
  375. package/template/apps/server/src/speech/routes.ts +60 -16
  376. package/template/apps/server/src/startup-finalization.ts +52 -0
  377. package/template/apps/server/src/startup-preflight.ts +2 -0
  378. package/template/apps/server/src/startup-shutdown.test.ts +69 -0
  379. package/template/apps/server/src/startup-shutdown.ts +61 -0
  380. package/template/apps/server/src/storage/drizzle-upload-purge.ts +61 -0
  381. package/template/apps/server/src/storage/drizzle-upload-references.ts +23 -0
  382. package/template/apps/server/src/storage/drizzle-upload-repository.integration.test.ts +103 -0
  383. package/template/apps/server/src/storage/drizzle-upload-repository.ts +109 -14
  384. package/template/apps/server/src/storage/host-runtime.ts +15 -0
  385. package/template/apps/server/src/storage/routes-stream-cancellation.test.ts +154 -0
  386. package/template/apps/server/src/storage/routes.test.ts +13 -2
  387. package/template/apps/server/src/storage/routes.ts +57 -18
  388. package/template/apps/server/src/storage/runtime.ts +17 -4
  389. package/template/apps/server/src/system/route-types.ts +5 -1
  390. package/template/apps/server/src/system/system-resource-monitoring.test.ts +47 -0
  391. package/template/apps/server/src/system/system-resource-monitoring.ts +60 -10
  392. package/template/apps/server/src/work-order/routes.test.ts +1 -0
  393. package/template/apps/speech-server/src/southwind_speech_server/adapter.py +58 -17
  394. package/template/apps/speech-server/src/southwind_speech_server/app.py +24 -17
  395. package/template/apps/speech-server/src/southwind_speech_server/bounded_json.py +60 -0
  396. package/template/apps/speech-server/src/southwind_speech_server/config.py +122 -2
  397. package/template/apps/speech-server/src/southwind_speech_server/contracts.py +58 -0
  398. package/template/apps/speech-server/src/southwind_speech_server/errors.py +8 -0
  399. package/template/apps/speech-server/src/southwind_speech_server/normalizer.py +14 -0
  400. package/template/apps/speech-server/src/southwind_speech_server/output_artifact.py +190 -0
  401. package/template/apps/speech-server/src/southwind_speech_server/output_validation.py +54 -0
  402. package/template/apps/speech-server/src/southwind_speech_server/pin_cli.py +83 -0
  403. package/template/apps/speech-server/src/southwind_speech_server/readiness.py +266 -0
  404. package/template/apps/speech-server/src/southwind_speech_server/readiness_contracts.py +268 -0
  405. package/template/apps/speech-server/src/southwind_speech_server/readiness_http.py +91 -0
  406. package/template/apps/speech-server/src/southwind_speech_server/readiness_local.py +161 -0
  407. package/template/apps/speech-server/src/southwind_speech_server/readiness_support.py +106 -0
  408. package/template/apps/speech-server/src/southwind_speech_server/service.py +118 -13
  409. package/template/apps/speech-server/src/southwind_speech_server/store.py +7 -0
  410. package/template/apps/speech-server/tests/test_bounded_json.py +55 -0
  411. package/template/apps/speech-server/tests/test_config.py +22 -0
  412. package/template/apps/speech-server/tests/test_output_artifact.py +60 -0
  413. package/template/apps/speech-server/tests/test_output_validation.py +44 -0
  414. package/template/apps/speech-server/tests/test_readiness.py +315 -0
  415. package/template/apps/speech-server/tests/test_readiness_http.py +48 -0
  416. package/template/apps/speech-server/tests/test_readiness_local.py +43 -0
  417. package/template/apps/speech-server/tests/test_service.py +211 -36
  418. package/template/apps/web/src/pages/system/components/OperationGpuMonitor.vue +23 -3
  419. package/template/apps/web/src/pages/system/components/OperationGpuMonitor.webtest.ts +29 -0
  420. package/template/apps/web/src/pages/system/components/OperationServiceMonitor.vue +2 -1
  421. package/template/apps/web/src/pages/system/components/OperationServiceMonitor.webtest.ts +4 -1
  422. package/template/docker-compose.yml +38 -1
  423. package/template/docs/architecture/ai-runtime-readiness.md +498 -0
  424. package/template/docs/architecture/ai-runtime.md +20 -4
  425. package/template/docs/architecture/durable-jobs.md +54 -5
  426. package/template/docs/architecture/module-host.md +72 -9
  427. package/template/docs/architecture/module-manifest-composition.md +5 -2
  428. package/template/docs/architecture/module-secret-resolution.md +250 -0
  429. package/template/docs/architecture/object-storage.md +144 -3
  430. package/template/docs/architecture/report-staging.md +158 -0
  431. package/template/docs/architecture/server-module-interface.md +29 -0
  432. package/template/docs/architecture/speech-variants.md +45 -0
  433. package/template/docs/platform/agent-tools.md +16 -0
  434. package/template/docs/platform/document-ai-runtime.md +199 -17
  435. package/template/docs/platform/module-configuration.md +5 -0
  436. package/template/docs/platform/speech-ai-runtime.md +34 -5
  437. package/template/docs/platform/vision-ai-runtime.md +24 -0
  438. package/template/package.json +4 -1
  439. package/template/packages/ai-client/package.json +1 -1
  440. package/template/packages/ai-client/src/agent/client/client.ts +3 -0
  441. package/template/packages/ai-client/src/agent/client/index.ts +1 -0
  442. package/template/packages/ai-client/src/agent/client/screenshot.test.ts +40 -0
  443. package/template/packages/ai-client/src/agent/client/screenshot.ts +146 -0
  444. package/template/packages/ai-client/src/agent/client/types.ts +2 -0
  445. package/template/packages/ai-client/src/agent/contracts/runs.ts +1 -0
  446. package/template/packages/ai-client/src/embedding/client.test.ts +52 -0
  447. package/template/packages/ai-client/src/embedding/client.ts +69 -0
  448. package/template/packages/ai-client/src/embedding/contracts.ts +47 -0
  449. package/template/packages/ai-client/src/embedding/index.ts +1 -0
  450. package/template/packages/ai-client/src/embedding/run.ts +130 -0
  451. package/template/packages/ai-client/src/speech/client.test.ts +26 -0
  452. package/template/packages/ai-client/src/speech/client.ts +25 -1
  453. package/template/packages/ai-client/src/speech/contracts.ts +19 -0
  454. package/template/packages/config/package.json +1 -1
  455. package/template/packages/database/drizzle/0048_illegal_magneto.sql +11 -0
  456. package/template/packages/database/drizzle/0049_right_lenny_balinger.sql +79 -0
  457. package/template/packages/database/drizzle/0050_greedy_sister_grimm.sql +92 -0
  458. package/template/packages/database/drizzle/0051_lame_shockwave.sql +19 -0
  459. package/template/packages/database/drizzle/0052_tiresome_komodo.sql +1 -0
  460. package/template/packages/database/drizzle/0053_calm_victor_mancha.sql +1 -0
  461. package/template/packages/database/drizzle/0054_tough_thanos.sql +29 -0
  462. package/template/packages/database/drizzle/meta/0048_snapshot.json +8852 -0
  463. package/template/packages/database/drizzle/meta/0049_snapshot.json +9410 -0
  464. package/template/packages/database/drizzle/meta/0050_snapshot.json +10115 -0
  465. package/template/packages/database/drizzle/meta/0051_snapshot.json +10257 -0
  466. package/template/packages/database/drizzle/meta/0052_snapshot.json +10263 -0
  467. package/template/packages/database/drizzle/meta/0053_snapshot.json +10270 -0
  468. package/template/packages/database/drizzle/meta/0054_snapshot.json +10468 -0
  469. package/template/packages/database/drizzle/meta/_journal.json +49 -0
  470. package/template/packages/database/package.json +1 -1
  471. package/template/packages/database/src/agent-runtime-schema.test.ts +15 -0
  472. package/template/packages/database/src/ai-output-artifacts.test.ts +57 -0
  473. package/template/packages/database/src/schema/agent-runtime.ts +43 -0
  474. package/template/packages/database/src/schema/ai-output-artifacts.ts +182 -0
  475. package/template/packages/database/src/schema/embedding-runtime.ts +62 -0
  476. package/template/packages/database/src/schema/file-storage.ts +18 -0
  477. package/template/packages/database/src/schema/index.ts +3 -0
  478. package/template/packages/database/src/schema/report-staging.ts +212 -0
  479. package/template/packages/database/src/schema.test.ts +19 -0
  480. package/template/packages/jobs/package.json +1 -1
  481. package/template/packages/modules/index.ts +1 -0
  482. package/template/packages/modules/package.json +1 -1
  483. package/template/packages/modules/src/ai-operation-composition.test.ts +37 -0
  484. package/template/packages/modules/src/ai-operation-composition.ts +2 -0
  485. package/template/packages/modules/src/ai-operation-readiness-contract.test.ts +38 -0
  486. package/template/packages/modules/src/ai-operation-readiness-contract.ts +34 -0
  487. package/template/packages/modules/src/capability-audit-validation.ts +20 -0
  488. package/template/packages/modules/src/capability-guard-validation.ts +41 -0
  489. package/template/packages/modules/src/composition.ts +11 -0
  490. package/template/packages/modules/src/manifest.ts +40 -0
  491. package/template/packages/modules/src/secret-composition.test.ts +308 -0
  492. package/template/packages/modules/src/secret-composition.ts +176 -0
  493. package/template/packages/modules/src/system-api-control-plane.ts +17 -1
  494. package/template/packages/modules/src/system-module-catalog.test.ts +52 -0
  495. package/template/packages/modules/src/system-module-catalog.ts +1 -1
  496. package/template/packages/server-sdk/contracts/ai-runtime-readiness/v1/document-python-parity.json +12 -0
  497. package/template/packages/server-sdk/contracts/ai-runtime-readiness/v1/document.json +70 -0
  498. package/template/packages/server-sdk/contracts/ai-runtime-readiness/v1/embedding.json +68 -0
  499. package/template/packages/server-sdk/contracts/ai-runtime-readiness/v1/speech.json +80 -0
  500. package/template/packages/server-sdk/contracts/ai-runtime-readiness/v1/vlm.json +70 -0
  501. package/template/packages/server-sdk/contracts/document-runtime/v1/fingerprint-fixture.json +101 -0
  502. package/template/packages/server-sdk/index.ts +109 -0
  503. package/template/packages/server-sdk/package.json +22 -3
  504. package/template/packages/server-sdk/src/ai-runtime-readiness-capture.ts +168 -0
  505. package/template/packages/server-sdk/src/ai-runtime-readiness-digest.ts +49 -0
  506. package/template/packages/server-sdk/src/ai-runtime-readiness-identity.ts +16 -0
  507. package/template/packages/server-sdk/src/ai-runtime-readiness-keys.ts +23 -0
  508. package/template/packages/server-sdk/src/ai-runtime-readiness-limits.ts +141 -0
  509. package/template/packages/server-sdk/src/ai-runtime-readiness-projection.ts +326 -0
  510. package/template/packages/server-sdk/src/ai-runtime-readiness-requirement.ts +31 -0
  511. package/template/packages/server-sdk/src/ai-runtime-readiness-time.ts +16 -0
  512. package/template/packages/server-sdk/src/ai-runtime-readiness-trust.ts +84 -0
  513. package/template/packages/server-sdk/src/ai-runtime-readiness-validation-values.ts +147 -0
  514. package/template/packages/server-sdk/src/ai-runtime-readiness-validation.ts +299 -0
  515. package/template/packages/server-sdk/src/ai-runtime-readiness-values.ts +42 -0
  516. package/template/packages/server-sdk/src/ai-runtime-readiness.adversarial-input.contract.test.ts +146 -0
  517. package/template/packages/server-sdk/src/ai-runtime-readiness.contract-support.ts +139 -0
  518. package/template/packages/server-sdk/src/ai-runtime-readiness.contract.test.ts +314 -0
  519. package/template/packages/server-sdk/src/ai-runtime-readiness.digest-safety.contract.test.ts +131 -0
  520. package/template/packages/server-sdk/src/ai-runtime-readiness.fail-closed.contract.test.ts +215 -0
  521. package/template/packages/server-sdk/src/ai-runtime-readiness.identity.contract.test.ts +138 -0
  522. package/template/packages/server-sdk/src/ai-runtime-readiness.input-safety.contract.test.ts +314 -0
  523. package/template/packages/server-sdk/src/ai-runtime-readiness.public-api.test.ts +18 -0
  524. package/template/packages/server-sdk/src/ai-runtime-readiness.python-parity.contract.test.ts +160 -0
  525. package/template/packages/server-sdk/src/ai-runtime-readiness.trust.contract.test.ts +135 -0
  526. package/template/packages/server-sdk/src/ai-runtime-readiness.ts +198 -0
  527. package/template/packages/server-sdk/src/ai-screenshot-intake-port.ts +58 -0
  528. package/template/packages/server-sdk/src/data-governance-registration.ts +1 -3
  529. package/template/packages/server-sdk/src/durable-handler.ts +12 -0
  530. package/template/packages/server-sdk/src/module-adapter.test.ts +10 -0
  531. package/template/packages/server-sdk/src/module-adapter.ts +3 -0
  532. package/template/packages/server-sdk/src/module-host.ts +8 -0
  533. package/template/packages/server-sdk/src/report-staging-context-compatibility.test.ts +25 -0
  534. package/template/packages/server-sdk/src/report-staging-port.ts +190 -0
  535. package/template/packages/server-sdk/src/request-context.ts +27 -1
  536. package/template/packages/server-sdk/src/route-definition.ts +6 -0
  537. package/template/packages/server-sdk/src/secret-binding.test.ts +66 -0
  538. package/template/packages/server-sdk/src/secret-binding.ts +54 -0
  539. package/template/packages/server-sdk/src/secret-context-compatibility.test.ts +77 -0
  540. package/template/packages/server-sdk/src/secret-port.ts +80 -0
  541. package/template/packages/server-sdk/src/storage-port.ts +129 -9
  542. package/template/packages/server-sdk/src/storage-v052-source-compatibility.test.ts +61 -0
  543. package/template/packages/shared/index.ts +2 -0
  544. package/template/packages/shared/package.json +4 -1
  545. package/template/packages/shared/src/ai-operation-readiness.test.ts +75 -0
  546. package/template/packages/shared/src/ai-operation-readiness.ts +170 -0
  547. package/template/packages/shared/src/license-catalog.ts +14 -9
  548. package/template/packages/shared/src/stable-key.ts +26 -0
  549. package/template/packages/shared/tsconfig.json +16 -0
  550. package/template/packages/storage/index.ts +2 -0
  551. package/template/packages/storage/package.json +1 -1
  552. package/template/packages/storage/src/in-memory-upload-repository.ts +105 -2
  553. package/template/packages/storage/src/local-file-blob-store.test.ts +58 -0
  554. package/template/packages/storage/src/local-file-blob-store.ts +5 -71
  555. package/template/packages/storage/src/local-file-blob-writer.ts +96 -0
  556. package/template/packages/storage/src/upload-abort-recovery.test.ts +234 -0
  557. package/template/packages/storage/src/upload-abort.ts +130 -0
  558. package/template/packages/storage/src/upload-cleanup-race.test.ts +207 -0
  559. package/template/packages/storage/src/upload-cleanup.ts +85 -0
  560. package/template/packages/storage/src/upload-completion.ts +52 -0
  561. package/template/packages/storage/src/upload-purge.test.ts +163 -0
  562. package/template/packages/storage/src/upload-purge.ts +261 -0
  563. package/template/packages/storage/src/upload-repository-v052-compatibility.test.ts +31 -0
  564. package/template/packages/storage/src/upload-repository.ts +61 -0
  565. package/template/packages/storage/src/upload-service-recovery.test.ts +296 -0
  566. package/template/packages/storage/src/upload-service.ts +138 -150
  567. package/template/packages/storage/src/upload-streams.ts +126 -30
  568. package/template/packages/storage/src/upload-types.ts +13 -0
  569. package/template/packages/storage/src/upload-validation.ts +127 -0
  570. package/template/scripts/provision-speech-readiness.ts +147 -0
@@ -6,7 +6,11 @@
6
6
 
7
7
  初始化器在 Storage 和 Durable Job Worker 创建前顺序执行,只允许登记定义,不启动监听、Worker 或后台循环。Host 扩展点:
8
8
 
9
- - `registerRoutes()`:注册 Guarded API 路由;`method + path` 与权限必须与 Manifest `apiPermissions` 声明一致,Guard(权限 / Feature / License)与 `security.denied` 审计由 `evaluateRouteGuards` 统一执行。声明 `auditAction` 时宿主在 Handler 成功后自动写审计;
9
+ - `registerRoutes()`:注册 Guarded API 路由;`method + path` 与权限必须与 Manifest
10
+ `apiPermissions` 声明一致,Guard(权限 / Feature / License)与 `security.denied`
11
+ 审计由 `evaluateRouteGuards` 统一执行。声明 `auditAction` 时宿主在 Handler 成功后
12
+ 自动写审计;流式请求体必须显式声明 `bodyMode: "stream"`,由 Host 下发
13
+ `bodyStream` 与同请求 `signal`;
10
14
  - `registerTaskHandlers()`:为 Manifest `tasks` 已声明的定时任务注册执行体,调度元数据一律以 Manifest 为准;
11
15
  - `registerToolHandlers()`:为 Manifest `tools` 已声明的 Agent Tool 注册类型化 JSON 执行体,输入输出 Schema、`scopeMode` 与 Handler 均接入双向校验;
12
16
  - `registerRolePresets()`:注册角色预设,`permissionKeys` 必须属于本模块 Manifest 权限声明;预设并入内置角色同步(不存在则创建、漂移则非破坏性合并),不改变 4 个内置角色语义;
@@ -18,8 +22,17 @@
18
22
  - `registerResourceFileAccessPolicies()`:注册本模块业务资源到平台文件的受限读取
19
23
  Resolver;purpose 必须来自当前模块或 Manifest 显式依赖模块,resourceType、
20
24
  Feature、Permission 和 Audit Action 必须来自当前消费者模块;
25
+
26
+ <!-- @windy-module system.storage begin -->
27
+
28
+ - `registerReportStagingPolicy()`:注册本模块命名空间内的大报告暂存用途、允许的
29
+ Resource File purpose、保留期及 Host 资源上限;
30
+
31
+ <!-- @windy-module system.storage end -->
32
+
21
33
  - `registerDurableHandler()`:注册强类型 payload parser 与模块 Durable Handler;执行时
22
- 由宿主重建当前 Actor 与提交时授权范围,并只额外提供受限资源文件读取 Port。
34
+ 由宿主重建当前 Actor 与提交时授权范围,并提供模块作用域 Storage Writer 与受限资源
35
+ 文件读取 Port。
23
36
  - `registerGovernedResources()`:为 Manifest `dataPolicies` 注册对象授权 Resolver、
24
37
  去除治理字段后的普通投影、受控字段值读取、可选 cursor 分页导出 Source,以及
25
38
  可选服务端 Renderer 和 Manifest 已声明的 masked/reveal/export Route;宿主负责
@@ -37,10 +50,23 @@
37
50
  - `jobs`:受限 Durable Job 控制 Port。提交只能使用本模块命名空间 Handler,Queue 与
38
51
  Actor 由宿主固定;读取、取消和人工恢复只返回最小投影,并在每次操作时重新执行当前
39
52
  路由的 Feature、Permission、License 与 Scope Guard;
53
+ - `secrets`:只按本模块 Manifest 已声明的 handle/connection/purpose 短暂解析 Secret,
54
+ 每次调用重做 License、Feature、Permission 与审计;不接受 locator,详见
55
+ [模块 Secret 解析 Port](./module-secret-resolution.md);
56
+
57
+ SDK 为旧 Context object literal 保留 optional `secrets` 字段;Windy Host 实际请求始终
58
+ 注入 Port,需要该能力的模块调用 `requireModuleSecretPort()`,缺失时稳定 fail closed。
40
59
 
41
60
  <!-- @windy-module system.storage begin -->
42
61
 
43
- - `storage`:受限 Upload/BlobRead Port(详见[对象存储](./object-storage.md));宿主未挂载时任何访问都以明确错误失败。
62
+ - `storage`:保持 0.5.2 的 `ModuleStoragePort` create/read 契约;
63
+ - `storageWriter?`:版本化 `ModuleStorageWritePortV1` additive seam,提供 `createUploadSession`、
64
+ `getUploadSession`、`appendUploadPart`、`completeUpload`、`abortUpload`,Owner、
65
+ Actor 和 Scope 均由 Host 固定;宿主未挂载时任何访问都以明确错误失败。完整生命周期
66
+ 见[对象存储](./object-storage.md)。
67
+ - `reportStaging?`:版本化 `ModuleReportStagingPortV1` additive seam;Host 负责
68
+ 多卷源读取、真实 RAR5 能力探测、解压前预检、完整索引、read lease、逐次授权和
69
+ TTL purge,详见[受治理的大报告暂存](./report-staging.md)。
44
70
 
45
71
  <!-- @windy-module system.storage end -->
46
72
 
@@ -48,16 +74,49 @@
48
74
  启用用户只读最小投影;不暴露 Admin Repository,详见
49
75
  [业务模块只读用户目录](../platform/business-user-directory.md)。
50
76
 
51
- Agent Tool 也获得同一个 `storage` Interface,但 Port 在每次 Tool Invocation 内根据
52
- 当前 Execution Grant 恢复的 Actor 与服务端 ScopeContext 重新构造;不会复用 Run
53
- 创建时的权限快照。`scopeMode: "request"`、Tool 自身 Feature/Permission Guard、资源
54
- 策略 Feature/Permission Guard 与业务 Resolver 必须全部通过。
77
+ Agent Tool 保持既有 create/read `storage` Interface,不自动获得
78
+ `ModuleStorageWritePortV1`。该既有 Port 在每次 Tool Invocation 内根据当前 Execution
79
+ Grant 恢复的 Actor 与服务端 ScopeContext 重新构造;不会复用 Run 创建时的权限快照。
80
+ `scopeMode: "request"`、Tool 自身 Feature/Permission Guard、资源策略
81
+ Feature/Permission Guard 与业务 Resolver 必须全部通过。这样新增 Request / Durable
82
+ Writer 不会把 append/complete/abort 或原始字节流扩散到 Agent 与 MCP。
83
+
84
+ Agent Tool 不获得 `secrets` Interface。声明并绑定模块 Secret 不会把原始值下发给普通
85
+ Tool 或 Sandbox Tool。
55
86
 
56
87
  Module Durable Handler 获得独立的 `ModuleDurableHandlerContext`。它不复用提交 HTTP
57
88
  请求对象,也不保存进程内闭包:宿主从持久化 Job 读取 `requestedBy` 与提交 Scope,
58
89
  每次执行重新解析当前用户与授权,Scope 漂移即拒绝。其 `storage` 只包含
59
90
  `openResourceFile()`,因此后台 Parser 可以按稳定业务资源绑定读取同案其他上传者的原件,
60
- 但不能创建上传、按 Owner 任意读取或接触平台存储实现。
91
+ 但不能创建上传、按 Owner 任意读取或接触平台存储实现。可选 `storageWriter` 独立提供
92
+ `ModuleStorageWritePortV1`,让后台 Handler 用 Host Actor 和当前模块 purpose 流式写入
93
+ 派生产物,不改变既有 `storage` Interface。
94
+ 其 `secrets` 每个 attempt 重新构造,每次 resolve 再读取当前 binding;轮换、停用和
95
+ Guard 变化不会复用上一次 attempt 的解析结果。
96
+
97
+ <!-- @windy-module system.storage begin -->
98
+
99
+ 可选 `reportStaging` 同样在每次 manifest、分页和 entry 读取前重新解析 Actor、提交时
100
+ Scope 快照与 Durable Handler Guard;Solid RAR 重试从首卷重新扫描,不复用 attempt
101
+ 留下的部分解压目录。
102
+
103
+ <!-- @windy-module system.storage end -->
104
+
105
+ Writer 会话本身持久化在平台 Upload Repository。Durable Handler 必须把 opaque session
106
+ ID 写入 payload 所引用的业务持久事实,或在提交 Job 前把它放入 payload;不能只保存在
107
+ attempt 闭包。每次 attempt 先按当前 License、Feature、Permission 和 nominal Scope
108
+ 重建 Context,再允许 `getUploadSession/appendUploadPart/completeUpload/abortUpload`。
109
+ Host 在创建时把 module 与 canonical Scope hash 作为不可伪造 binding 写入会话;当前
110
+ Actor、Scope、module 或 Host 注册 purpose 与该 creation-time binding 不再匹配时
111
+ fail closed,历史或无 binding 的 session ID 不能恢复旧授权。重复 `completeUpload`
112
+ 返回同一已发布文件,不产生第二份 Blob。
113
+
114
+ HTTP `bodyMode: "stream"` Route 的 `ModuleRequestContext` 同时提供 `bodyStream` 与
115
+ `signal`。`bodyStream` 不经过 JSON 解析或完整缓冲,Writer 等待底层当前写入后才继续
116
+ 拉取,形成端到端背压;请求取消会取消当前尚未提交的临时 Blob,但保留已提交分片供
117
+ 后续请求恢复。Durable attempt 的 `signal` 遵循相同语义。只有显式 `abortUpload` 或
118
+ 平台 session TTL 才终结整个未完成会话;orphan grace period 负责回收未被元数据引用的
119
+ Blob。
61
120
 
62
121
  `ModuleRequestContext.jobs` 提供 `submit/get/cancel/recover`,但不下发 Repository、
63
122
  Worker 或 Queue 选择权。控制操作同时要求任务 Queue/Handler 属于当前模块、任务提交人
@@ -105,7 +164,11 @@ MIME、扩展名和 records/bytes/timeout 上限;请求固化选择,恢复
105
164
 
106
165
  - Host Interface 只承载跨模块稳定能力,不暴露数据库连接或业务 Repository。
107
166
  - 初始化器不得跨模块注册 key,也不得依赖注册顺序读取另一个模块的私有状态。
108
- - 上传授权仍由 Server Route Guard 和文件 Owner/RBAC 负责;注册策略不等于获得上传权限。
167
+ - 上传授权仍由 Server Route / Durable Handler Guard、Host Owner、当前注册 purpose
168
+ 以及持久化的 module/Scope binding 共同负责;注册策略不等于获得上传权限,session ID
169
+ 也不能代替当前授权。
170
+ - Storage Writer DTO 不接受 tenant、Actor、Owner、Scope、Permission、ArtifactRef 或
171
+ 物理 locator;这些字段即使由调用方伪造也不能进入底层调用或审计 metadata。
109
172
  - 跨上传者资源读取只允许通过资源策略:Resolver 只返回授权判定,必须回查业务关联,
110
173
  不能返回或下发 Repository;直接 fileId、文件名或不可猜引用都不能代替资源授权。
111
174
 
@@ -13,7 +13,7 @@ Manifest 当前覆盖:
13
13
 
14
14
  - Feature、Permission、API Route、Admin Route 与菜单 Surface;
15
15
  - Migration 与 Schema Export 证据;
16
- - Scheduled Task、Agent Tool、Provider 与 Audit Action;
16
+ - Scheduled Task、Agent Tool、Provider、模块 Secret 与 Audit Action;
17
17
  - Feature 依赖与可用 License 版本;
18
18
  - 模块依赖及版本元数据。
19
19
 
@@ -22,7 +22,7 @@ Manifest 当前覆盖:
22
22
  组合校验在运行时业务逻辑前执行,并拒绝:
23
23
 
24
24
  1. 缺失依赖、依赖循环及同类能力重复 Key;
25
- 2. Menu、Admin Route、API、Task、Tool、Provider 对未知 Permission 或 Feature 的引用;
25
+ 2. Menu、Admin Route、API、Task、Tool、Provider、Secret 对未知 Permission 或 Feature 的引用;
26
26
  3. 未定义或重复的业务 Audit Action,以及 Tool 对未知 Audit Action 的引用;
27
27
  4. Feature 的未知依赖、自依赖、循环依赖和未知 License 版本;
28
28
  5. Menu 与 Admin Route 路径或 Guard 漂移;
@@ -87,6 +87,9 @@ Migration、Worker 与监听。不存在“构建通过、启动时才第一次
87
87
  监听前验证。Durable Handler 还必须绑定 Manifest 中同一能力的 Feature、Permission
88
88
  与 Audit Action;Host 冻结该绑定,并在每次首次执行、重试和恢复领取时按当前
89
89
  Actor、License、Feature 与 RBAC 状态重新 Guard。
90
+ - 模块 Secret 只在 Manifest 声明稳定 handle/connection/purpose 与治理绑定,物理
91
+ `SecretRef` 由 project-owned Composition 提供;locator、跨模块 binding 和未知引用
92
+ 在监听前 fail closed。运行边界见[模块 Secret 解析 Port](./module-secret-resolution.md)。
90
93
  - 业务模块可在 `auditActions` 中直接注册包含 Key、名称和说明的动作定义;组合后的
91
94
  Audit Action Catalog 与 License Catalog 会通过 Foundation / Admin Bootstrap 契约开放,
92
95
  管理端筛选与展示不维护第二份静态业务 Key。
@@ -0,0 +1,250 @@
1
+ # 模块 Secret 解析 Port
2
+
3
+ ## 目标与边界
4
+
5
+ 业务模块连接 SMB、SFTP 等外部系统时,需要在服务端最后时刻取得凭据,但不能获得任意
6
+ 环境变量名、文件路径或平台 Secret Registry。Windy 将声明、物理绑定和运行时使用拆成
7
+ 三层:
8
+
9
+ 1. 业务 Module Manifest 只声明稳定的 `handle + connection + purpose` 逻辑三元组,
10
+ 以及 Feature、Permission、License 映射和 Audit Action;
11
+ 2. project-owned Server Composition 使用宿主持有的 `SecretRef` / `SecretResolver`
12
+ 提供物理 binding,动态业务 package 不能自行注入 env/file locator;
13
+ 3. Request 或 Durable Handler 通过 `ModuleSecretPort.resolve()` 的短生命周期回调使用
14
+ 原始值,Host 在每次调用时重新 Guard、解析和审计。
15
+
16
+ 该 Port 不取代类型化平台配置。Endpoint、Host、端口、超时和非敏感连接选项仍进入模块
17
+ 自己的严格配置;Secret Port 只负责凭据值。Manifest、API body、Job payload、Tool 参数
18
+ 和业务表都不保存 `SecretRef`、locator 或明文。
19
+
20
+ ## Manifest 契约
21
+
22
+ 示例模块 `archive` 声明 SMB 只读密码:
23
+
24
+ ```ts
25
+ {
26
+ handle: "archive.smb.password",
27
+ connection: "archive.smb.primary",
28
+ purpose: "archive.smb.read",
29
+ featureKey: "archive.external-storage",
30
+ permissionKey: "archive.external-storage.read",
31
+ auditAction: "archive.secret.resolve",
32
+ }
33
+ ```
34
+
35
+ `handle`、`connection` 和 `purpose` 都必须是最多 128 字符的小写稳定 Key,并位于当前
36
+ 模块命名空间;换行、NUL、路径、env 风格大写下划线和前后空白均不合法。每个 handle
37
+ 全局唯一;声明只能包含这三个逻辑字段和治理字段,出现 `provider`、`locator`、env key、
38
+ 文件路径或其它未知字段时,Module Composition 在 Server 监听前失败。
39
+
40
+ Secret 声明与其它能力执行同一门禁:
41
+
42
+ - Permission、Feature 与 Audit Action 必须由拥有该 Secret 的同一 Manifest 注册,
43
+ 只在其它模块或全局 Catalog 中存在仍视为未注册;
44
+ - Permission 必须存在同基础 Key Feature;
45
+ - Feature 可用 `allowedLicenseVersions` 声明商业版本;
46
+ - Audit Action 必须在 Manifest `auditActions` 注册;
47
+ - 未知 Feature、Permission、Audit、重复 handle 和命名空间漂移全部 fail closed。
48
+
49
+ ## project-owned 物理绑定
50
+
51
+ 物理 locator 只出现在客户拥有的 `apps/server/src/app/server-composition.ts`。Host 提供
52
+ 由发布包 `@southwind-ai/server-sdk` 根导出的 `createModuleSecretBinding()`,把既有
53
+ `SecretRef` / `SecretResolver` 适配为 Composition binding。项目不得导入
54
+ `apps/server/src/module-host/**` 私有实现:
55
+
56
+ ```ts
57
+ import { EnvironmentSecretResolver, SecretRef } from "@southwind-ai/config";
58
+ import {
59
+ createModuleSecretBinding,
60
+ defineWindyServerComposition,
61
+ } from "@southwind-ai/server-sdk";
62
+
63
+ const environmentSecrets = new EnvironmentSecretResolver(process.env);
64
+
65
+ export const serverCompositionDeclaration = defineWindyServerComposition({
66
+ assembly: moduleAssembly,
67
+ adapters: projectAdapters,
68
+ attachments: projectAttachments,
69
+ secretBindings: [
70
+ createModuleSecretBinding({
71
+ moduleName: "archive",
72
+ handle: "archive.smb.password",
73
+ connection: "archive.smb.primary",
74
+ purpose: "archive.smb.read",
75
+ reference: new SecretRef("env", "ARCHIVE_SMB_PASSWORD"),
76
+ resolver: environmentSecrets,
77
+ enabled: () => process.env.ARCHIVE_SMB_ENABLED === "true",
78
+ }),
79
+ ],
80
+ });
81
+ ```
82
+
83
+ 示例使用 env 说明接线,不表示生产必须使用 env。生产可以注入受保护文件、Vault 或其它
84
+ 实现相同 `SecretResolver` 契约的宿主 Adapter。业务 package 看不到 binding、Resolver
85
+ 或 `SecretRef`。Host 会拒绝未安装模块、跨模块命名空间、Manifest 未声明和重复 binding。
86
+
87
+ `enabled()` 是宿主状态,不由模块或客户端提交。停用后解析返回稳定
88
+ `MODULE_SECRET_DISABLED`;缺少值、binding 或 Resolver 故障返回
89
+ `MODULE_SECRET_UNAVAILABLE`,错误不包含底层异常、locator 或值。
90
+
91
+ ## Request 与 Durable 使用
92
+
93
+ 业务代码必须把三元组定义为服务端常量,不能从 body、Tool 参数或 Job payload 接受:
94
+
95
+ Request Handler 使用兼容旧 Context 的 helper;缺少 Port 时会抛出稳定 unavailable,
96
+ 不会静默跳过连接:
97
+
98
+ ```ts
99
+ import {
100
+ requireModuleSecretPort,
101
+ type ModuleRequestContext,
102
+ } from "@southwind-ai/server-sdk";
103
+
104
+ declare function connectSmb(input: {
105
+ readonly connectionKey: string;
106
+ readonly password: string;
107
+ }): Promise<{
108
+ listNames(cursor?: string): Promise<readonly string[]>;
109
+ close(): Promise<void>;
110
+ }>;
111
+
112
+ const smbSecret = {
113
+ handle: "archive.smb.password",
114
+ connection: "archive.smb.primary",
115
+ purpose: "archive.smb.read",
116
+ } as const;
117
+
118
+ async function listArchive(
119
+ context: ModuleRequestContext,
120
+ input: { readonly cursor?: string },
121
+ ): Promise<{ readonly names: readonly string[] }> {
122
+ const secrets = requireModuleSecretPort(context);
123
+ return secrets.resolve(smbSecret, async (password) => {
124
+ const client = await connectSmb({
125
+ connectionKey: smbSecret.connection,
126
+ password,
127
+ });
128
+ try {
129
+ return { names: await client.listNames(input.cursor) };
130
+ } finally {
131
+ await client.close();
132
+ }
133
+ });
134
+ }
135
+ ```
136
+
137
+ Durable Handler 每个 attempt 同样必须通过 helper 获取 Port:
138
+
139
+ ```ts
140
+ import {
141
+ requireModuleSecretPort,
142
+ type ModuleDurableHandlerContext,
143
+ } from "@southwind-ai/server-sdk";
144
+
145
+ declare function connectSmb(input: {
146
+ readonly connectionKey: string;
147
+ readonly password: string;
148
+ }): Promise<{
149
+ sync(): Promise<void>;
150
+ close(): Promise<void>;
151
+ }>;
152
+
153
+ const smbSecret = {
154
+ handle: "archive.smb.password",
155
+ connection: "archive.smb.primary",
156
+ purpose: "archive.smb.read",
157
+ } as const;
158
+
159
+ async function syncArchive(
160
+ context: ModuleDurableHandlerContext,
161
+ ): Promise<void> {
162
+ const secrets = requireModuleSecretPort(context);
163
+ await secrets.resolve(smbSecret, async (password) => {
164
+ const client = await connectSmb({
165
+ connectionKey: smbSecret.connection,
166
+ password,
167
+ });
168
+ try {
169
+ await client.sync();
170
+ } finally {
171
+ await client.close();
172
+ }
173
+ });
174
+ }
175
+ ```
176
+
177
+ 原始值只在回调内短暂可见。Host 不信任 TypeScript 返回类型,而是把结果 canonicalize
178
+ 为新的深冻结 JSON snapshot:只接受 `null`、boolean、有限 number、string、稠密 array
179
+ 和 plain object;拒绝 accessor、Proxy、symbol、危险 key、非普通 prototype、循环、
180
+ 非 JSON 值以及过深、过宽、过大的结果。Key 和 string value 都会检查当前原始 Secret。
181
+ 验证、反射或快照异常统一返回 `MODULE_SECRET_EXPOSURE_BLOCKED`,回调或底层 Resolver
182
+ 异常则替换为其它稳定脱敏错误;原 live object 不会返回给调用方。
183
+
184
+ 公开 Context 中 `secrets` 为兼容旧 SDK object literal 的 optional 字段。Windy Host 在
185
+ Request 和每个 Durable attempt 都始终注入受治理 Port;模块通过
186
+ `requireModuleSecretPort(context)` 显式取得它。旧测试桩或 Adapter 缺字段时 helper
187
+ 直接抛稳定 `MODULE_SECRET_UNAVAILABLE`,不会回退到 env、文件或全局 Registry。
188
+
189
+ Durable Worker 每次首次执行、自动重试和恢复都会重建 Actor、重新执行 Handler Guard,
190
+ 并创建新的 Secret Port。Port 调用时再次按 Secret 声明执行 License、Feature 和
191
+ Permission Guard,然后调用当前 binding;不缓存此前 attempt 的值或解析结果。因此受
192
+ 保护文件或动态 Resolver 的轮换在下一次 resolve 生效,`enabled()` 停用也立即阻断下一次
193
+ 调用。
194
+
195
+ ## Agent Tool 暴露边界
196
+
197
+ `ModuleToolContext` 和 Sandbox Tool Context 都没有 `secrets` 字段。即使模块 Manifest
198
+ 声明并由项目绑定 Secret,普通 Agent Tool 也不能通过 Host Port 取得原始值,binding 的
199
+ Resolver 不会被调用。
200
+
201
+ 需要外部连接的 Agent 能力应把凭据使用封装在可信的服务端业务操作中,并只向 Tool
202
+ 返回脱敏业务结果;当前契约不提供 Tool 原始 Secret opt-in。纯计算 Sandbox Tool 继续
203
+ 保持无 Secret、无 Repository、无网络。若未来确需 Tool 直连外部系统,必须另行设计不
204
+ 暴露原始凭据的 Host Adapter,而不是给 `ModuleToolContext` 增加字符串 Secret。
205
+
206
+ ## 审计与失败语义
207
+
208
+ 每次已声明 resolve 都记录声明的 Audit Action:
209
+
210
+ - `success`:只记录 handle target、逻辑 connection/purpose 和 `resolved` 语义;
211
+ - `denied`:记录稳定的 Guard 原因或 `disabled`;
212
+ - `failure`:记录 `binding-unavailable`、`resolver-failed`、
213
+ `operation-failed` 或 `exposure-blocked`。
214
+
215
+ 未声明或跨模块三元组使用同形 `MODULE_SECRET_NOT_DECLARED`,并写不包含调用方输入的
216
+ `security.denied`。Provider 的 version 属于敏感、不可信输入,既不原样记录,也不做可
217
+ 离线字典确认的无密钥摘要;轮换由每个 attempt 重新解析和新的 `resolved` 事件表达,
218
+ 当前不提供跨事件 provider version 相关性。
219
+
220
+ 业务模块仍是可信 Server 代码:Host 能阻止当前 Secret 经平台返回值、错误与事件的意外
221
+ 泄漏,但不能识别回调返回的其它未知凭据,也不能把故意通过网络或其它副作用发送凭据的
222
+ 恶意模块变成安全代码。这些边界必须继续通过代码审查、模块来源治理和网络策略控制。
223
+
224
+ ## 利剑 SMB / SFTP 接入
225
+
226
+ 利剑升级到包含该契约的 Windy 版本后,按以下方式接入,不需要修改 Windy 的配置
227
+ Registry 或 Agent Tool Runtime:
228
+
229
+ 1. 在拥有 SMB/SFTP 同步能力的利剑 Module Manifest 分别声明 password/private-key
230
+ handle、稳定 connection/purpose,以及同基础 Key Feature、Permission 和审计动作;
231
+ 2. 在利剑 project-owned `server-composition.ts` 为每个声明添加
232
+ SDK 根导出的 `createModuleSecretBinding()`,生产 Resolver 指向客户批准的 Secret
233
+ Store;
234
+ 3. Route/Service 在一次连接操作内使用
235
+ `requireModuleSecretPort(context).resolve()`,及时关闭 SMB/SFTP client,只返回文件
236
+ 业务元数据或导入结果;
237
+ 4. 后台同步同样使用 `requireModuleSecretPort(context)`,不要把凭据、locator 或
238
+ provider version 写进 payload;重试和恢复自然取得当前轮换值;
239
+ 5. Agent Tool 只查询已落库或由可信业务服务投影的结果,不把 password、private key、
240
+ endpoint query 或底层连接异常返回给模型。
241
+
242
+ SMB password 与 SFTP password/private key 应使用不同 handle,读、写、导入等 purpose
243
+ 也应分开声明;不要用一个“万能连接 Secret”跨协议、跨动作或跨模块复用。
244
+
245
+ ## 验证范围
246
+
247
+ 定向测试覆盖 Manifest locator 拒绝、物理 binding 双向匹配、跨模块/未声明三元组、
248
+ Permission/Feature/License 拒绝、动态停用、轮换、Durable attempt 重新解析、
249
+ Agent Tool 无 Port、审计成功/拒绝/失败和结果/错误/provider version 脱敏。完整合并与发布矩阵仍由
250
+ 合并候选和发版候选门禁统一执行。
@@ -5,7 +5,8 @@
5
5
  `@southwind-ai/storage` 是平台文件能力的唯一底层模块。`BlobStore` 只供平台 Storage
6
6
  实现使用:流式写入、流式打开和删除;文件名、MIME、上传会话、Owner、权限与审计不
7
7
  进入这个底层接口,由上层上传模块统一处理。可安装业务模块只学习
8
- `@southwind-ai/server-sdk` 的 `ModuleStoragePort`。
8
+ `@southwind-ai/server-sdk` 的既有 create/read Port,以及只向 Request / Durable
9
+ Context 开放的模块作用域 Storage Writer。
9
10
 
10
11
  `ArtifactRef` 使用 `blob_` 加 128 位随机值,不包含目录、租户或内容摘要,不能由业务主键推算。`ContentHash` 当前固定为 SHA-256。调用方可以声明大小和摘要,本地 Adapter 会在写入过程中验证;任何不一致都不会发布 Blob。
11
12
 
@@ -34,7 +35,13 @@
34
35
 
35
36
  PostgreSQL 通过 `file_upload_sessions`、`file_upload_parts` 和 `file_metadata` 持久化会话进度及最终文件。分片提交使用 `received_byte_size + next_part_number` compare-and-set;最终 Blob 与 FileMetadata 只有数据库状态切换成功后才发布为完成状态。
36
37
 
37
- 清理任务先删除已过期会话的分片和已过期文件,再将数据库仍引用的 `ArtifactRef` 集合交给 `LocalFileBlobMaintenance`。本地维护器只删除超过 grace period 的临时文件或未引用 Blob,避免与正在提交的上传竞争。生产应由 Scheduler 周期调用清理入口;grace period 默认一小时。
38
+ 清理任务先以持久化 CAS 把已过期、未完成会话 claim 为 `expired`,再删除已 claim
39
+ 会话及其分片行;只有数据库删除成功后才删除捕获的 Blob 引用。完成先提交时 claim
40
+ 失败,清理不能删除;清理先 claim 时 append/complete CAS 失败,不能发布。claim 或
41
+ 数据库删除失败时不删除 Blob;数据库删除后退出留下的孤儿由引用集合和 grace period
42
+ 收口。随后清理已过期文件,并将数据库仍引用的 `ArtifactRef` 集合交给
43
+ `LocalFileBlobMaintenance`。生产应由 Scheduler 周期调用清理入口;grace period
44
+ 默认一小时。
38
45
 
39
46
  ## 授权下载与业务接入
40
47
 
@@ -52,6 +59,12 @@ Logo 使用 `branding-logo` 上传策略。匿名 `/api/platform/files/:id` 只
52
59
 
53
60
  - `WINDY_BLOB_DRIVER`:当前生产 Adapter 为 `local`;配置未知驱动时启动失败,不静默回退。
54
61
  - `WINDY_STORAGE_ROOT`:本地持久目录,默认 `.data/storage`。Compose 使用独立 named volume 挂载 `/app/data/storage`。
62
+
63
+ 大体积归档或已展开报告的随机读取不由业务模块直接落盘;它通过
64
+ [受治理的大报告暂存](./report-staging.md) 复用 Resource File 授权,并默认使用
65
+ `WINDY_STORAGE_ROOT/report-staging`。需要独立 volume 时可设置
66
+ `WINDY_REPORT_STAGING_ROOT`。
67
+
55
68
  - S3-compatible 支持保留在 `BlobStore` seam;当前不强制安装云 SDK。未来 Adapter 必须保持流式读写、服务端摘要验证、不可猜引用、明确删除与损坏语义,不能让业务模块学习 bucket/key。
56
69
 
57
70
  ## 故障语义
@@ -61,7 +74,7 @@ Logo 使用 `branding-logo` 上传策略。匿名 `/api/platform/files/:id` 只
61
74
  - 删除为幂等操作;第一次存在时返回 `true`,重复删除返回 `false`。
62
75
  - 进程在 Blob 发布与元数据发布之间退出时可能产生孤儿内容;上传生命周期模块基于过期时间、引用集合与 grace period 清理。
63
76
 
64
- ## 模块受限 Upload/BlobRead Port
77
+ ## 模块既有 create/read Port
65
78
 
66
79
  业务模块不直接使用 `UploadService` / `FileService`,而是经
67
80
  `ModuleRequestContext.storage` 或 `ModuleToolContext.storage` 获得
@@ -87,6 +100,132 @@ Logo 使用 `branding-logo` 上传策略。匿名 `/api/platform/files/:id` 只
87
100
  读取。Feature、Permission、Audit Action 和 resourceType 仍必须属于当前消费者模块,
88
101
  任一未知或越界都会在监听前失败。
89
102
 
103
+ ## 模块作用域流式写入
104
+
105
+ `ModuleStorageWritePortV1` 只把既有 `UploadService` 的会话状态机收窄为五个生命周期
106
+ 方法,不创建第二套上传引擎。为保持 0.5.2 C1 源码兼容,
107
+ `ModuleRequestContext.storage` 与 `ModuleDurableHandlerContext.storage` 保持原
108
+ create/read 及 `openResourceFile()` 契约;Writer 通过可选 `storageWriter` 独立注入。
109
+ 业务用 `requireModuleStorageWritePortV1(context)` fail closed 获取:
110
+
111
+ | 方法 | 语义 |
112
+ | --------------------- | ---------------------------------------------- |
113
+ | `createUploadSession` | 以当前 Host Actor 和已注册 purpose 创建会话 |
114
+ | `getUploadSession` | 读取当前会话的服务端续传位置和终态最小投影 |
115
+ | `appendUploadPart` | 向服务端给出的下一分片号和偏移流式写入一个分片 |
116
+ | `completeUpload` | 校验总大小和 SHA-256,并发布最终文件 |
117
+ | `abortUpload` | 显式终止未完成会话并删除其已提交分片 |
118
+
119
+ SDK Writer DTO 只包含业务上传需要的文件名、MIME、声明大小、可选 SHA-256、purpose、opaque
120
+ session ID、分片流及最小进度/文件结果。输入和输出都不得包含 `tenantId`、`actorId`、
121
+ `ownerId`、Permission/Scope 快照、`ArtifactRef`、bucket/key、主机路径、URL 或其它物理
122
+ locator。业务可以持久化 opaque session ID 以续传,但不能解析或据此扩权。
123
+ Writer 创建输入也不接受绝对 `fileExpiresAt`;Host 从 purpose 对应 Upload Policy 的
124
+ `fileRetentionMs` 派生过期时间,缺失、非安全整数、小于一分钟或大于 365 天均 fail
125
+ closed。旧 `ModuleStoragePort.createUploadSession` 的绝对过期时间行为只为 0.5.2
126
+ 兼容保留,不能被 Writer V1 复用。
127
+ Writer 失败统一投影为 `ModuleStorageError` 的稳定 code;可修正的大小、SHA、顺序、
128
+ 过期、取消和并发状态保持可判定,未知 Blob/文件系统异常只返回
129
+ `STORAGE_WRITE_FAILED`,不透传主机路径或底层异常正文。
130
+
131
+ Host 使用当前请求或 Durable attempt 重建的 Actor 填充 Owner;创建时校验 Host 注册的
132
+ purpose,其余四个 Writer 方法每次调用都回读服务端会话,确认 Owner 与当前模块已注册
133
+ purpose 仍然匹配。模块 Writer 创建会话时还会把 Host 生成的模块名与 creation-time
134
+ canonical Scope hash 持久化到 Upload Repository;后续每次 get/append/complete/abort
135
+ 都必须与当前 Host binding 完全一致。session ID、客户端声明的 purpose 或历史成功结果
136
+ 都不是授权事实。跨模块用途、平台基础用途、当前注册已移除、历史无 binding 会话以及
137
+ Actor/Scope 漂移均 fail closed;底层不存在、越权和不匹配不会泄漏 Owner、文件或存储
138
+ 实现细节。
139
+
140
+ ### HTTP 流与背压
141
+
142
+ 模块 HTTP Route 仅可在 `POST` / `PUT` 上显式声明 `bodyMode: "stream"`;声明后,
143
+ Context 才通过 `bodyStream` 接收未解析的请求体流。Host 把同一 Context 的 `signal`
144
+ 与 Writer 绑定。`appendUploadPart` 直接把 `ReadableStream` 交给既有
145
+ `UploadService.appendPart()`,不会先转为字符串、`ArrayBuffer` 或完整 Buffer。底层
146
+ Blob Adapter 每写完当前块才拉取下一块,因此客户端发送速度会自然受存储写入速度背压。
147
+ 普通 JSON Route 保持原有 `body` 解析契约,不能借 body 字段伪造流、Actor 或 scope。
148
+ Route Guard 拒绝时 Host 会立即取消未消费的请求流,不让无权限请求继续占用上传带宽。
149
+
150
+ 分片的声明大小和 SHA-256 由 Blob Adapter 在流经存储时校验;完成时再次校验会话声明的
151
+ 总大小和总 SHA-256。`getUploadSession` 返回的 `nextPartNumber` 与
152
+ `receivedByteSize` 是服务端接收事实;调用方按这两个值回传分片号与偏移,不能通过旧
153
+ 偏移或并发请求覆盖已提交进度。
154
+
155
+ ### 完成、取消与清理
156
+
157
+ `completeUpload` 是终态幂等操作:同一 Owner、模块和 purpose 对已完成会话重放时返回
158
+ 首次发布的同一文件最小投影,不创建第二个 FileMetadata 或 Blob。并发完成仍由上传
159
+ Repository 的 CAS 决定唯一胜者;失败方回读终态后得到同一结果。Owner、purpose 或当前
160
+ 授权不匹配时,即使会话已经完成也不得返回结果。
161
+
162
+ 请求或 Durable attempt 被取消,或者当前分片写入/完整性校验失败时,Writer 停止当前流,
163
+ 并只清理由本次尚未提交的临时 Blob。此前已通过 CAS 提交的分片和 `uploading` 会话继续
164
+ 保留,使调用方可以在下一次请求或 attempt 中调用 `getUploadSession` 后恢复;取消不能
165
+ 伪装成已经 `abortUpload`。业务确认放弃时显式调用 `abortUpload`,由既有上传服务删除
166
+ 全部已提交分片。进程在来不及 abort 时退出,则由 `system.storage.cleanup` 按 session
167
+ TTL 清理;Blob 先发布但元数据未提交产生的孤儿仍由引用集合和 orphan grace period
168
+ 收口,不能为模块另建清理循环。
169
+
170
+ 在 abort intent CAS 前已观察到取消的旧 Request/attempt 会以 `UPLOAD_CANCELLED`
171
+ fail closed,不改变会话;业务随后确认放弃时,必须在新的、重新通过 Guard 的
172
+ Request/attempt 中调用 `abortUpload`。若 `aborting` CAS 已先提交,取消只停止后续清理,
173
+ 会话不再恢复为 uploading,由下一次重放或 TTL 完成终止。这是 Storage CAS 与进程内
174
+ AbortSignal 之间的明确竞态边界,不把信号描述成数据库 lease fence。完成提交后的分片
175
+ 清理为 best effort:重复 `completeUpload` 会继续收口残留行;已完成/已终止会话的分片
176
+ Blob 不再计入活跃引用集合,因此物理删除失败仍可由 orphan cleanup 回收。
177
+
178
+ 显式终止使用可重放状态机 `uploading -> aborting -> aborted`。进入 `aborting` 后先按仍
179
+ 持久化的 part 引用幂等删除 Blob,再删除 part 行;只有 Repository 确认分片行为空后才
180
+ 提交 `aborted`。Blob 删除、行删除、取消或进程退出都只会留下可恢复的 `aborting`,
181
+ 下一次 `abortUpload` 从持久事实继续。兼容升级前可能存在的 `aborted + part` 残留时,
182
+ 重放也必须继续清理,不能把终态本身当作清理完成证明。`aborting` 分片仍属于活跃引用,
183
+ 避免 orphan maintenance 与恢复竞争;会话超过 TTL 后仍由统一 cleanup 删除。
184
+
185
+ `0048_illegal_magneto.sql` 为 `file_upload_sessions` 增加 nullable 的
186
+ `module_name/authorization_scope_hash` 成对约束。平台原生上传保持两列都为空;历史模块
187
+ 会话无法安全回填 creation-time Scope,因此 Module Writer 对无 binding 会话 fail closed,
188
+ 由调用方新建会话或等待 TTL 清理,不能猜测回填。
189
+
190
+ ### 审计白名单
191
+
192
+ Host 统一写入四类内置普通审计,模块不能改写动作 Key;每类记录只从以下 metadata
193
+ 白名单中按实际结果取值:
194
+
195
+ - `file.upload.create`:purpose、声明总大小、声明 SHA-256;
196
+ - `file.upload.part.write`:purpose、part number、offset、分片大小与 SHA-256;
197
+ - `file.upload.complete`:purpose、总大小、SHA-256,以及是否为幂等重放;
198
+ - `file.upload.abort`:purpose,以及适用时的幂等重放标记。
199
+
200
+ 失败事件额外记录稳定 `errorCode`;Durable 事件由 Host 加入 `jobId` 与
201
+ `attemptNumber`。这些字段都来自平台执行事实,模块和 payload 不能覆盖。
202
+ Module、Actor、Request ID 和时间由平台审计上下文补齐;target 使用当前 session 或
203
+ 最终 file 的不透明 ID。审计 metadata 不记录文件内容、文件名、客户端身份/Scope 字段、
204
+ `ArtifactRef`、路径、URL、bucket/key 或底层异常正文。Route / Durable Guard 拒绝继续
205
+ 使用统一 `security.denied`,Writer 自身的 purpose/Owner 拒绝也只返回稳定错误,不把
206
+ 物理事实变成探测面。
207
+ `getUploadSession` 的 Owner/purpose 同形拒绝额外记录稳定 `security.denied`,不会把
208
+ 会话存在性、Owner 或底层错误写入审计。
209
+
210
+ ### 下游接入
211
+
212
+ 1. 在业务模块 `setup(host)` 注册命名空间内 Upload Policy,并在 Manifest Route 或
213
+ Durable Handler 上绑定真实 Feature、Permission 与审计能力。
214
+ 2. HTTP 上传 Route 声明 `bodyMode: "stream"`;后台写入把 opaque session ID 保存到
215
+ Durable payload 所引用的业务持久事实中,不能只保存在闭包或进程内变量。
216
+ 3. 首次调用 `createUploadSession`;重试或恢复先调用 `getUploadSession`,再按服务端
217
+ 位置顺序调用 `appendUploadPart`。
218
+ 4. 全部字节写入后调用 `completeUpload`,只持久化返回的 file ID;明确放弃时调用
219
+ `abortUpload`。
220
+ 5. Agent Tool 不自动获得该 Writer;需要模型发起写操作时,仍须另行完成审批、幂等和
221
+ 可追踪结果契约,不能从 JSON Tool 参数绕过 HTTP / Durable 边界。
222
+
223
+ 真实重启集成只在显式提供 `STORAGE_TEST_DATABASE_URL` 时运行,并使用生产
224
+ `DrizzleUploadRepository + LocalFileBlobStore` 重新构造 HTTP Server 与 Durable
225
+ Context。未提供 URL 时该 PostgreSQL 证据明确为 skipped;独立的 filesystem
226
+ checkpoint 测试只证明 Host/Durable/Blob 对象不复用时仍可恢复,不替代生产数据库持久性
227
+ 验收。
228
+
90
229
  ## 当前切片
91
230
 
92
231
  - F1:Blob 端口、SHA-256、随机引用和本地流式 Adapter 已完成。
@@ -95,3 +234,5 @@ Logo 使用 `branding-logo` 上传策略。匿名 `/api/platform/files/:id` 只
95
234
  - F4:模块受限 Upload/BlobRead Port 已完成,业务模块经 Host 注册用途并受命名空间约束。
96
235
  - F5:Route 与 Tool 共用资源绑定读取 Port,支持受审计、受数据范围约束的跨上传者
97
236
  业务文件流读取,不扩散 Storage/Admin Repository。
237
+ - F6:Request 与 Durable Context 共用模块作用域 Storage Writer,复用既有上传会话、
238
+ 背压、完整性校验和清理状态机,并保持 Tool 写入边界关闭。