create-windy 0.3.2 → 0.3.5

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 (343) hide show
  1. package/README.md +27 -9
  2. package/dist/cli.js +825 -117
  3. package/package.json +1 -1
  4. package/template/.agents/skills/windy-business-module/SKILL.md +16 -3
  5. package/template/.windy-template.json +2 -2
  6. package/template/AGENTS.md +4 -0
  7. package/template/README.md +18 -11
  8. package/template/_gitignore +1 -0
  9. package/template/apps/agent-server/README.md +2 -0
  10. package/template/apps/agent-server/pyproject.toml +8 -0
  11. package/template/apps/agent-server/src/southwind_agent_server/adk_adapter.py +87 -10
  12. package/template/apps/agent-server/src/southwind_agent_server/adk_model.py +18 -3
  13. package/template/apps/agent-server/src/southwind_agent_server/adk_tools.py +78 -11
  14. package/template/apps/agent-server/src/southwind_agent_server/app.py +120 -115
  15. package/template/apps/agent-server/src/southwind_agent_server/artifact_input.py +153 -0
  16. package/template/apps/agent-server/src/southwind_agent_server/config.py +29 -0
  17. package/template/apps/agent-server/src/southwind_agent_server/contracts.py +81 -1
  18. package/template/apps/agent-server/src/southwind_agent_server/deterministic.py +8 -0
  19. package/template/apps/agent-server/src/southwind_agent_server/engine.py +28 -0
  20. package/template/apps/agent-server/src/southwind_agent_server/fingerprint.py +41 -0
  21. package/template/apps/agent-server/src/southwind_agent_server/http_helpers.py +62 -0
  22. package/template/apps/agent-server/src/southwind_agent_server/lease.py +15 -0
  23. package/template/apps/agent-server/src/southwind_agent_server/multimodal.py +76 -0
  24. package/template/apps/agent-server/src/southwind_agent_server/openai_engine.py +112 -20
  25. package/template/apps/agent-server/src/southwind_agent_server/openai_provider.py +14 -1
  26. package/template/apps/agent-server/src/southwind_agent_server/postgres_store.py +329 -0
  27. package/template/apps/agent-server/src/southwind_agent_server/postgres_store_backend.py +332 -0
  28. package/template/apps/agent-server/src/southwind_agent_server/provider_governance.py +64 -3
  29. package/template/apps/agent-server/src/southwind_agent_server/runtime_factory.py +68 -0
  30. package/template/apps/agent-server/src/southwind_agent_server/service.py +218 -56
  31. package/template/apps/agent-server/src/southwind_agent_server/signal_events.py +36 -0
  32. package/template/apps/agent-server/src/southwind_agent_server/sqlite_catalog.py +107 -0
  33. package/template/apps/agent-server/src/southwind_agent_server/sqlite_schema.py +65 -0
  34. package/template/apps/agent-server/src/southwind_agent_server/sqlite_serialization.py +16 -0
  35. package/template/apps/agent-server/src/southwind_agent_server/sqlite_store.py +89 -57
  36. package/template/apps/agent-server/src/southwind_agent_server/store.py +105 -2
  37. package/template/apps/agent-server/src/southwind_agent_server/store_cipher.py +40 -0
  38. package/template/apps/agent-server/src/southwind_agent_server/telemetry.py +89 -0
  39. package/template/apps/agent-server/src/southwind_agent_server/tool_host.py +72 -0
  40. package/template/apps/agent-server/tests/test_adk_adapter.py +6 -2
  41. package/template/apps/agent-server/tests/test_api.py +24 -1
  42. package/template/apps/agent-server/tests/test_artifact_input.py +110 -0
  43. package/template/apps/agent-server/tests/test_config.py +4 -0
  44. package/template/apps/agent-server/tests/test_fingerprint.py +10 -0
  45. package/template/apps/agent-server/tests/test_multimodal.py +51 -0
  46. package/template/apps/agent-server/tests/test_openai_provider.py +6 -2
  47. package/template/apps/agent-server/tests/test_postgres_store.py +131 -0
  48. package/template/apps/agent-server/tests/test_provider_governance.py +61 -0
  49. package/template/apps/agent-server/tests/test_sqlite_store.py +95 -10
  50. package/template/apps/agent-server/tests/test_telemetry.py +25 -0
  51. package/template/apps/agent-server/tests/test_tool_approval.py +28 -0
  52. package/template/apps/agent-server/uv.lock +165 -0
  53. package/template/apps/document-server/Dockerfile +19 -0
  54. package/template/apps/document-server/pyproject.toml +43 -0
  55. package/template/apps/document-server/src/southwind_document_server/__init__.py +1 -0
  56. package/template/apps/document-server/src/southwind_document_server/adapter.py +337 -0
  57. package/template/apps/document-server/src/southwind_document_server/app.py +151 -0
  58. package/template/apps/document-server/src/southwind_document_server/config.py +94 -0
  59. package/template/apps/document-server/src/southwind_document_server/contracts.py +103 -0
  60. package/template/apps/document-server/src/southwind_document_server/service.py +149 -0
  61. package/template/apps/document-server/src/southwind_document_server/store.py +185 -0
  62. package/template/apps/document-server/tests/__init__.py +1 -0
  63. package/template/apps/document-server/tests/test_config.py +42 -0
  64. package/template/apps/document-server/tests/test_service.py +140 -0
  65. package/template/apps/document-server/uv.lock +430 -0
  66. package/template/apps/embedding-server/Dockerfile +17 -0
  67. package/template/apps/embedding-server/pyproject.toml +44 -0
  68. package/template/apps/embedding-server/src/southwind_embedding_server/__init__.py +1 -0
  69. package/template/apps/embedding-server/src/southwind_embedding_server/adapter.py +254 -0
  70. package/template/apps/embedding-server/src/southwind_embedding_server/app.py +119 -0
  71. package/template/apps/embedding-server/src/southwind_embedding_server/config.py +120 -0
  72. package/template/apps/embedding-server/src/southwind_embedding_server/contracts.py +106 -0
  73. package/template/apps/embedding-server/src/southwind_embedding_server/error.py +6 -0
  74. package/template/apps/embedding-server/src/southwind_embedding_server/image_input.py +87 -0
  75. package/template/apps/embedding-server/tests/__init__.py +1 -0
  76. package/template/apps/embedding-server/tests/test_adapter.py +92 -0
  77. package/template/apps/embedding-server/tests/test_config.py +38 -0
  78. package/template/apps/embedding-server/uv.lock +449 -0
  79. package/template/apps/server/src/agent/background-operation-port.ts +37 -0
  80. package/template/apps/server/src/agent/background-operation.test.ts +231 -0
  81. package/template/apps/server/src/agent/background-operation.ts +252 -0
  82. package/template/apps/server/src/agent/drizzle-run-binding-repository.ts +114 -0
  83. package/template/apps/server/src/agent/execution-grants.ts +7 -1
  84. package/template/apps/server/src/agent/fake-runtime.test-support.ts +43 -0
  85. package/template/apps/server/src/agent/idempotency-key.test.ts +28 -0
  86. package/template/apps/server/src/agent/idempotency-key.ts +11 -0
  87. package/template/apps/server/src/agent/remote-runtime.test.ts +115 -1
  88. package/template/apps/server/src/agent/remote-runtime.ts +173 -5
  89. package/template/apps/server/src/agent/run-authorization.test-support.ts +9 -0
  90. package/template/apps/server/src/agent/run-authorization.test.ts +126 -0
  91. package/template/apps/server/src/agent/run-authorization.ts +180 -0
  92. package/template/apps/server/src/agent/run-binding-repository.ts +93 -0
  93. package/template/apps/server/src/agent/run-contracts.ts +88 -1
  94. package/template/apps/server/src/agent/run-definition-support.ts +58 -0
  95. package/template/apps/server/src/agent/run-errors.ts +25 -0
  96. package/template/apps/server/src/agent/run-facade.test.ts +57 -46
  97. package/template/apps/server/src/agent/run-facade.ts +185 -65
  98. package/template/apps/server/src/agent/run-release.ts +78 -0
  99. package/template/apps/server/src/agent/run-route-input.ts +169 -0
  100. package/template/apps/server/src/agent/run-routes.ts +63 -76
  101. package/template/apps/server/src/agent/runtime-bootstrap.ts +169 -13
  102. package/template/apps/server/src/agent/sandbox-client.ts +200 -0
  103. package/template/apps/server/src/agent/sandbox-protocol.ts +76 -0
  104. package/template/apps/server/src/agent/sandbox-registry.ts +205 -0
  105. package/template/apps/server/src/agent/sandbox-runtime.test.ts +137 -0
  106. package/template/apps/server/src/agent/sandbox-worker-server.ts +195 -0
  107. package/template/apps/server/src/agent/sandbox-worker.ts +12 -0
  108. package/template/apps/server/src/agent/tool-approval.test.ts +75 -0
  109. package/template/apps/server/src/agent/tool-approval.ts +115 -0
  110. package/template/apps/server/src/agent/tool-audit.ts +62 -0
  111. package/template/apps/server/src/agent/tool-host.test.ts +39 -11
  112. package/template/apps/server/src/agent/tool-host.ts +184 -17
  113. package/template/apps/server/src/agent/tool-registry.ts +52 -47
  114. package/template/apps/server/src/agent/vision-facade.test.ts +256 -0
  115. package/template/apps/server/src/agent/vision-input.ts +120 -0
  116. package/template/apps/server/src/ai-artifact/codec.test.ts +44 -0
  117. package/template/apps/server/src/ai-artifact/codec.ts +137 -0
  118. package/template/apps/server/src/ai-artifact/routes.ts +37 -0
  119. package/template/apps/server/src/ai-artifact/runtime.ts +205 -0
  120. package/template/apps/server/src/application-services.ts +62 -2
  121. package/template/apps/server/src/auth/reauthentication.test.ts +40 -0
  122. package/template/apps/server/src/auth/reauthentication.ts +19 -0
  123. package/template/apps/server/src/auth/runtime.ts +9 -1
  124. package/template/apps/server/src/data-access/context.ts +6 -4
  125. package/template/apps/server/src/data-access/scope-snapshot.ts +27 -0
  126. package/template/apps/server/src/data-governance/export/approval-port.ts +6 -3
  127. package/template/apps/server/src/data-governance/export/authorization-port.test.ts +23 -4
  128. package/template/apps/server/src/data-governance/export/authorization-port.ts +89 -25
  129. package/template/apps/server/src/data-governance/export/drizzle-repository.integration.test.ts +2 -0
  130. package/template/apps/server/src/data-governance/export/drizzle-repository.ts +1 -0
  131. package/template/apps/server/src/data-governance/export/job-runtime.test.ts +15 -4
  132. package/template/apps/server/src/data-governance/export/job-runtime.ts +68 -15
  133. package/template/apps/server/src/data-governance/export/ndjson-stream.ts +25 -6
  134. package/template/apps/server/src/data-governance/export/postgres-recovery.integration.test.ts +4 -2
  135. package/template/apps/server/src/data-governance/export/renderer-job-runtime.test.ts +235 -0
  136. package/template/apps/server/src/data-governance/export/renderer-runtime.ts +293 -0
  137. package/template/apps/server/src/data-governance/export/renderer-selection.test.ts +67 -0
  138. package/template/apps/server/src/data-governance/export/repository.test.ts +2 -0
  139. package/template/apps/server/src/data-governance/export/request-fingerprint.test.ts +13 -0
  140. package/template/apps/server/src/data-governance/export/request-fingerprint.ts +2 -0
  141. package/template/apps/server/src/data-governance/export/routes.ts +11 -1
  142. package/template/apps/server/src/data-governance/export/scope-snapshot.ts +6 -18
  143. package/template/apps/server/src/data-governance/export/service-support.ts +188 -0
  144. package/template/apps/server/src/data-governance/export/service.ts +90 -113
  145. package/template/apps/server/src/data-governance/export/source.ts +101 -0
  146. package/template/apps/server/src/data-governance/export/types.ts +27 -0
  147. package/template/apps/server/src/document/contracts.ts +76 -0
  148. package/template/apps/server/src/document/facade.ts +339 -0
  149. package/template/apps/server/src/document/remote-runtime.test.ts +96 -0
  150. package/template/apps/server/src/document/remote-runtime.ts +223 -0
  151. package/template/apps/server/src/document/routes.ts +193 -0
  152. package/template/apps/server/src/embedding/contracts.ts +83 -0
  153. package/template/apps/server/src/embedding/error.ts +10 -0
  154. package/template/apps/server/src/embedding/facade.ts +217 -0
  155. package/template/apps/server/src/embedding/input.ts +172 -0
  156. package/template/apps/server/src/embedding/remote-runtime.test.ts +66 -0
  157. package/template/apps/server/src/embedding/remote-runtime.ts +218 -0
  158. package/template/apps/server/src/embedding/routes.ts +152 -0
  159. package/template/apps/server/src/index.ts +40 -43
  160. package/template/apps/server/src/jobs/artifact-service.test.ts +14 -2
  161. package/template/apps/server/src/jobs/artifact-service.ts +10 -0
  162. package/template/apps/server/src/jobs/drizzle-execution-repository.ts +17 -18
  163. package/template/apps/server/src/jobs/drizzle-execution.integration.test.ts +19 -1
  164. package/template/apps/server/src/jobs/drizzle-mappers.ts +4 -1
  165. package/template/apps/server/src/jobs/drizzle-recovery-repository.ts +49 -2
  166. package/template/apps/server/src/jobs/drizzle-repository.ts +1 -0
  167. package/template/apps/server/src/jobs/execution-repository.ts +17 -0
  168. package/template/apps/server/src/jobs/execution.test.ts +34 -0
  169. package/template/apps/server/src/jobs/in-memory-control.ts +135 -0
  170. package/template/apps/server/src/jobs/in-memory-execution.ts +34 -65
  171. package/template/apps/server/src/jobs/legacy-service-runtime.ts +5 -2
  172. package/template/apps/server/src/jobs/repository.ts +3 -0
  173. package/template/apps/server/src/jobs/worker.ts +80 -41
  174. package/template/apps/server/src/module-host/ai-operation-port.ts +170 -0
  175. package/template/apps/server/src/module-host/durable-context.test.ts +312 -0
  176. package/template/apps/server/src/module-host/durable-context.ts +124 -0
  177. package/template/apps/server/src/module-host/durable-handler-registration.ts +72 -0
  178. package/template/apps/server/src/module-host/governed-export-route-support.ts +171 -0
  179. package/template/apps/server/src/module-host/governed-export-routes.test.ts +327 -0
  180. package/template/apps/server/src/module-host/governed-export-routes.ts +238 -0
  181. package/template/apps/server/src/module-host/governed-renderer-registration.test.ts +247 -0
  182. package/template/apps/server/src/module-host/governed-resource-routes.ts +331 -0
  183. package/template/apps/server/src/module-host/governed-resources.test.ts +344 -0
  184. package/template/apps/server/src/module-host/governed-resources.ts +203 -0
  185. package/template/apps/server/src/module-host/http-runtime.ts +95 -0
  186. package/template/apps/server/src/module-host/initialize-contracts.ts +14 -0
  187. package/template/apps/server/src/module-host/initialize.test.ts +49 -1
  188. package/template/apps/server/src/module-host/initialize.ts +39 -16
  189. package/template/apps/server/src/module-host/job-port.test.ts +262 -0
  190. package/template/apps/server/src/module-host/job-port.ts +334 -0
  191. package/template/apps/server/src/module-host/request-context.test.ts +88 -2
  192. package/template/apps/server/src/module-host/request-context.ts +56 -22
  193. package/template/apps/server/src/module-host/route-installer.test.ts +10 -0
  194. package/template/apps/server/src/module-host/route-installer.ts +36 -1
  195. package/template/apps/server/src/module-host/sandbox-tool-registration.ts +42 -0
  196. package/template/apps/server/src/module-host/tool-handlers.ts +67 -31
  197. package/template/apps/server/src/module-host.ts +1 -0
  198. package/template/apps/server/src/module-runtime-validation.ts +7 -3
  199. package/template/apps/server/src/speech/contracts.ts +76 -0
  200. package/template/apps/server/src/speech/facade.ts +316 -0
  201. package/template/apps/server/src/speech/remote-runtime.test.ts +88 -0
  202. package/template/apps/server/src/speech/remote-runtime.ts +227 -0
  203. package/template/apps/server/src/speech/routes.ts +180 -0
  204. package/template/apps/server/src/system/actor.ts +39 -0
  205. package/template/apps/server/src/system/route-helpers.ts +1 -0
  206. package/template/apps/server/src/workflow/service.ts +2 -1
  207. package/template/apps/speech-server/Dockerfile +22 -0
  208. package/template/apps/speech-server/pyproject.toml +43 -0
  209. package/template/apps/speech-server/src/southwind_speech_server/__init__.py +1 -0
  210. package/template/apps/speech-server/src/southwind_speech_server/adapter.py +249 -0
  211. package/template/apps/speech-server/src/southwind_speech_server/app.py +183 -0
  212. package/template/apps/speech-server/src/southwind_speech_server/config.py +100 -0
  213. package/template/apps/speech-server/src/southwind_speech_server/contracts.py +103 -0
  214. package/template/apps/speech-server/src/southwind_speech_server/errors.py +6 -0
  215. package/template/apps/speech-server/src/southwind_speech_server/normalizer.py +108 -0
  216. package/template/apps/speech-server/src/southwind_speech_server/output_validation.py +128 -0
  217. package/template/apps/speech-server/src/southwind_speech_server/service.py +162 -0
  218. package/template/apps/speech-server/src/southwind_speech_server/store.py +209 -0
  219. package/template/apps/speech-server/tests/__init__.py +1 -0
  220. package/template/apps/speech-server/tests/test_config.py +33 -0
  221. package/template/apps/speech-server/tests/test_service.py +154 -0
  222. package/template/apps/speech-server/uv.lock +430 -0
  223. package/template/apps/web/src/app/business-routes.ts +22 -0
  224. package/template/apps/web/src/components/common/AccessSnapshotBoundary.vue +112 -0
  225. package/template/apps/web/src/components/common/AccessSnapshotBoundary.webtest.ts +130 -0
  226. package/template/apps/web/src/components/common/AccessSnapshotNotice.vue +117 -0
  227. package/template/apps/web/src/components/common/FormDialog.vue +6 -0
  228. package/template/apps/web/src/components/common/ModalLayout.webtest.ts +13 -0
  229. package/template/apps/web/src/composables/access-snapshot-change.ts +131 -0
  230. package/template/apps/web/src/composables/access-snapshot-change.webtest.ts +103 -0
  231. package/template/apps/web/src/composables/useAccessSnapshot.ts +48 -2
  232. package/template/apps/web/src/composables/useAccessSnapshot.webtest.ts +54 -0
  233. package/template/apps/web/src/composables/useAccessSnapshotMonitor.ts +42 -0
  234. package/template/apps/web/src/layout/AppShell.vue +28 -25
  235. package/template/apps/web/src/layout/AppShell.webtest.ts +1 -0
  236. package/template/apps/web/src/router/business-routes.ts +68 -0
  237. package/template/apps/web/src/router/business-routes.webtest.ts +85 -0
  238. package/template/apps/web/src/router/index.ts +7 -0
  239. package/template/apps/web/src/router/shared-scaffold-neutrality.webtest.ts +12 -0
  240. package/template/apps/web/src/services/access-api.ts +5 -1
  241. package/template/apps/web/src/services/access-api.webtest.ts +35 -0
  242. package/template/docker-compose.yml +127 -0
  243. package/template/docs/architecture/ai-egress.md +12 -9
  244. package/template/docs/architecture/ai-runtime.md +23 -11
  245. package/template/docs/architecture/durable-jobs.md +25 -3
  246. package/template/docs/architecture/foundation-infrastructure.md +163 -0
  247. package/template/docs/architecture/module-host.md +115 -0
  248. package/template/docs/architecture/server-module-interface.md +39 -0
  249. package/template/docs/architecture/web-access-snapshot-resilience.md +60 -0
  250. package/template/docs/development/business-web-routes.md +66 -0
  251. package/template/docs/development/custom-login-page.md +3 -3
  252. package/template/docs/development/module-lifecycle.md +71 -0
  253. package/template/docs/operations/observability.md +5 -1
  254. package/template/docs/platform/agent-runtime.md +21 -11
  255. package/template/docs/platform/agent-tool-sandbox.md +58 -0
  256. package/template/docs/platform/agent-tools.md +5 -0
  257. package/template/docs/platform/document-ai-runtime.md +204 -0
  258. package/template/docs/platform/governed-export-renderers.md +132 -0
  259. package/template/docs/platform/navigation-registry.md +5 -0
  260. package/template/docs/platform/organization-membership.md +2 -1
  261. package/template/docs/platform/speech-ai-runtime.md +156 -0
  262. package/template/docs/platform/system-crud-api.md +7 -1
  263. package/template/docs/platform/vision-ai-runtime.md +97 -0
  264. package/template/docs/platform/web-system-crud.md +6 -0
  265. package/template/package.json +16 -2
  266. package/template/packages/ai-client/index.ts +4 -0
  267. package/template/packages/ai-client/package.json +5 -2
  268. package/template/packages/ai-client/src/agent/client/artifact.ts +26 -0
  269. package/template/packages/ai-client/src/agent/client/attach.test.ts +124 -0
  270. package/template/packages/ai-client/src/agent/client/client.ts +119 -7
  271. package/template/packages/ai-client/src/agent/client/run.ts +14 -0
  272. package/template/packages/ai-client/src/agent/client/types.ts +18 -0
  273. package/template/packages/ai-client/src/agent/client/vision.test.ts +53 -0
  274. package/template/packages/ai-client/src/agent/contracts/contracts.test.ts +1 -0
  275. package/template/packages/ai-client/src/agent/contracts/events.ts +33 -0
  276. package/template/packages/ai-client/src/agent/contracts/runs.ts +71 -0
  277. package/template/packages/ai-client/src/agent/index.ts +1 -0
  278. package/template/packages/ai-client/src/artifact-ref.ts +8 -0
  279. package/template/packages/ai-client/src/document/client.test.ts +114 -0
  280. package/template/packages/ai-client/src/document/client.ts +134 -0
  281. package/template/packages/ai-client/src/document/contracts.ts +152 -0
  282. package/template/packages/ai-client/src/document/error.ts +43 -0
  283. package/template/packages/ai-client/src/document/index.ts +3 -0
  284. package/template/packages/ai-client/src/document/run.ts +104 -0
  285. package/template/packages/ai-client/src/document/validation.ts +115 -0
  286. package/template/packages/ai-client/src/embedding/client.test.ts +77 -0
  287. package/template/packages/ai-client/src/embedding/client.ts +96 -0
  288. package/template/packages/ai-client/src/embedding/contracts.ts +46 -0
  289. package/template/packages/ai-client/src/embedding/error.ts +61 -0
  290. package/template/packages/ai-client/src/embedding/index.ts +3 -0
  291. package/template/packages/ai-client/src/embedding/validation.ts +117 -0
  292. package/template/packages/ai-client/src/speech/client.test.ts +135 -0
  293. package/template/packages/ai-client/src/speech/client.ts +104 -0
  294. package/template/packages/ai-client/src/speech/contracts.ts +129 -0
  295. package/template/packages/ai-client/src/speech/error.ts +43 -0
  296. package/template/packages/ai-client/src/speech/index.ts +3 -0
  297. package/template/packages/ai-client/src/speech/run.ts +133 -0
  298. package/template/packages/ai-client/src/speech/validation.ts +132 -0
  299. package/template/packages/config/package.json +2 -2
  300. package/template/packages/database/drizzle/0039_early_ezekiel_stane.sql +1 -0
  301. package/template/packages/database/drizzle/0040_colossal_baron_strucker.sql +63 -0
  302. package/template/packages/database/drizzle/0041_yummy_prowler.sql +21 -0
  303. package/template/packages/database/drizzle/0042_puzzling_rumiko_fujikawa.sql +27 -0
  304. package/template/packages/database/drizzle/meta/0039_snapshot.json +7755 -0
  305. package/template/packages/database/drizzle/meta/0040_snapshot.json +8150 -0
  306. package/template/packages/database/drizzle/meta/0041_snapshot.json +8323 -0
  307. package/template/packages/database/drizzle/meta/0042_snapshot.json +8541 -0
  308. package/template/packages/database/drizzle/meta/_journal.json +28 -0
  309. package/template/packages/database/package.json +2 -2
  310. package/template/packages/database/src/agent-runtime-schema.test.ts +54 -0
  311. package/template/packages/database/src/schema/agent-runtime.ts +149 -0
  312. package/template/packages/database/src/schema/common.ts +2 -14
  313. package/template/packages/database/src/schema/durable-jobs.ts +5 -0
  314. package/template/packages/database/src/schema/governed-exports.ts +17 -5
  315. package/template/packages/database/src/schema/index.ts +3 -0
  316. package/template/packages/database/src/schema-durable-recovery.test.ts +31 -0
  317. package/template/packages/database/src/schema-governed-exports.test.ts +21 -1
  318. package/template/packages/database/src/schema.test.ts +6 -23
  319. package/template/packages/jobs/package.json +3 -2
  320. package/template/packages/jobs/src/handlers.test.ts +13 -0
  321. package/template/packages/jobs/src/handlers.ts +7 -1
  322. package/template/packages/jobs/src/types.ts +4 -0
  323. package/template/packages/modules/package.json +2 -2
  324. package/template/packages/modules/src/ai-operation-composition.test-support.ts +165 -0
  325. package/template/packages/modules/src/ai-operation-composition.test.ts +91 -127
  326. package/template/packages/modules/src/ai-operation-composition.ts +59 -1
  327. package/template/packages/modules/src/manifest.ts +25 -1
  328. package/template/packages/modules/src/tool-composition.ts +18 -0
  329. package/template/packages/server-sdk/index.ts +50 -0
  330. package/template/packages/server-sdk/package.json +10 -4
  331. package/template/packages/server-sdk/src/ai-artifact-port.ts +34 -0
  332. package/template/packages/server-sdk/src/ai-operation-port.ts +65 -0
  333. package/template/packages/server-sdk/src/ai-operation-registration.ts +42 -1
  334. package/template/packages/server-sdk/src/background-ai-port.ts +43 -0
  335. package/template/packages/server-sdk/src/data-governance-registration.ts +116 -0
  336. package/template/packages/server-sdk/src/durable-handler.ts +29 -0
  337. package/template/packages/server-sdk/src/jobs-port.ts +69 -0
  338. package/template/packages/server-sdk/src/module-host.ts +16 -2
  339. package/template/packages/server-sdk/src/request-context.ts +6 -2
  340. package/template/packages/server-sdk/src/sandbox-tool.ts +21 -0
  341. package/template/packages/server-sdk/src/tool-registration.ts +2 -0
  342. package/template/packages/shared/package.json +1 -1
  343. package/template/packages/shared/src/rbac.ts +30 -0
@@ -0,0 +1,344 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { featureKey, type PermissionDefinition } from "@southwind-ai/shared";
3
+ import type { ModuleManifest } from "@southwind-ai/modules";
4
+ import type { ModuleGovernedResourceRegistration } from "@southwind-ai/server-sdk";
5
+ import { buildActorScopeContexts } from "../data-access/context.js";
6
+ import type { RequestActor } from "../guards.js";
7
+ import { createServerRuntime } from "../runtime.js";
8
+ import { FakeRouteApp } from "../system/route-test-app.js";
9
+ import { installModuleGovernedResourceRoutes } from "./governed-resource-routes.js";
10
+ import { initializeModuleHosts } from "./initialize.js";
11
+
12
+ describe("业务模块数据治理 Port", () => {
13
+ test("普通读取只返回掩码,明文要求独立权限、理由与再认证", async () => {
14
+ const fixture = await setup();
15
+ const masked = (await fixture.invoke("GET")) as {
16
+ governedFields: {
17
+ phone: { kind: string; classification: string; display: string };
18
+ };
19
+ };
20
+ expect(masked.governedFields.phone).toEqual({
21
+ kind: "masked",
22
+ classification: "sensitive",
23
+ display: "138****8071",
24
+ });
25
+ expect(JSON.stringify(masked)).not.toContain("13812348071");
26
+
27
+ const denied = (await fixture.invoke("POST", {
28
+ reason: "案件复核需要核对联系方式",
29
+ password: "wrong",
30
+ fieldKeys: ["phone"],
31
+ })) as Response;
32
+ expect(denied.status).toBe(403);
33
+ expect(fixture.reads()).toBe(1);
34
+ expect(fixture.runtime.auditSink.list()).toContainEqual(
35
+ expect.objectContaining({
36
+ action: "people.phone.reveal",
37
+ outcome: "denied",
38
+ }),
39
+ );
40
+
41
+ const revealed = (await fixture.invoke("POST", {
42
+ reason: "案件复核需要核对联系方式",
43
+ password: "correct",
44
+ fieldKeys: ["phone"],
45
+ })) as {
46
+ governedFields: {
47
+ phone: { kind: string; value: string; grantId: string };
48
+ };
49
+ };
50
+ expect(revealed.governedFields.phone).toMatchObject({
51
+ kind: "plaintext",
52
+ value: "13812348071",
53
+ grantId: expect.any(String),
54
+ });
55
+ expect(fixture.runtime.auditSink.list()).toContainEqual(
56
+ expect.objectContaining({
57
+ action: "people.phone.reveal",
58
+ outcome: "success",
59
+ metadata: expect.objectContaining({
60
+ reason: "案件复核需要核对联系方式",
61
+ fieldKeys: ["phone"],
62
+ }),
63
+ }),
64
+ );
65
+ });
66
+
67
+ test("对象授权、权限与投影字段漂移均 fail-closed", async () => {
68
+ const unauthorized = await setup({ objectAllowed: false });
69
+ const missing = (await unauthorized.invoke("GET")) as Response;
70
+ expect(missing.status).toBe(404);
71
+ expect(unauthorized.reads()).toBe(0);
72
+
73
+ const noPermission = await setup({ permissionKeys: [] });
74
+ const forbidden = (await noPermission.invoke("GET")) as Response;
75
+ expect(forbidden.status).toBe(403);
76
+ expect(noPermission.authorizations()).toBe(0);
77
+
78
+ const drift = await setup({ projectionDrift: true });
79
+ await expect(drift.invoke("GET")).rejects.toThrow(
80
+ "业务治理投影与 Manifest 不一致",
81
+ );
82
+ });
83
+
84
+ test("注册拒绝未知策略、错误 API 绑定与重复策略", async () => {
85
+ const declared = peopleManifest();
86
+ await expect(
87
+ initializeModuleHosts({
88
+ modules: [declared],
89
+ installations: [
90
+ {
91
+ manifest: declared,
92
+ setup(host) {
93
+ host.registerGovernedResources([
94
+ { ...registration(), policyKey: "people.unknown" },
95
+ ]);
96
+ },
97
+ },
98
+ ],
99
+ }),
100
+ ).rejects.toThrow("业务治理资源未在 Manifest 声明");
101
+
102
+ const wrongRoute = peopleManifest();
103
+ wrongRoute.apiPermissions[1] = {
104
+ ...wrongRoute.apiPermissions[1]!,
105
+ permissionKey: "people.person.read",
106
+ };
107
+ await expect(createHosts(wrongRoute)).rejects.toThrow(
108
+ "业务治理路由与 Manifest 绑定不一致",
109
+ );
110
+
111
+ await expect(
112
+ initializeModuleHosts({
113
+ modules: [declared],
114
+ installations: [
115
+ {
116
+ manifest: declared,
117
+ setup(host) {
118
+ host.registerGovernedResources([registration(), registration()]);
119
+ },
120
+ },
121
+ ],
122
+ }),
123
+ ).rejects.toThrow("业务治理资源重复注册");
124
+ });
125
+
126
+ });
127
+
128
+ interface SetupOptions {
129
+ permissionKeys?: string[];
130
+ objectAllowed?: boolean;
131
+ projectionDrift?: boolean;
132
+ }
133
+
134
+ async function setup(options: SetupOptions = {}) {
135
+ let authorizationCalls = 0;
136
+ let readCalls = 0;
137
+ const registrationValue = registration({
138
+ authorize() {
139
+ authorizationCalls += 1;
140
+ return options.objectAllowed ?? true;
141
+ },
142
+ read() {
143
+ readCalls += 1;
144
+ return {
145
+ id: "person-1",
146
+ publicFields: options.projectionDrift
147
+ ? { name: "张三", phone: "leak" }
148
+ : { name: "张三" },
149
+ governedFields: { phone: "13812348071" },
150
+ };
151
+ },
152
+ });
153
+ const declared = peopleManifest();
154
+ const hosts = await initializeModuleHosts({
155
+ modules: [declared],
156
+ installations: [
157
+ {
158
+ manifest: declared,
159
+ setup(host) {
160
+ host.registerGovernedResources([registrationValue]);
161
+ },
162
+ },
163
+ ],
164
+ });
165
+ const runtime = createServerRuntime(
166
+ {},
167
+ {
168
+ actorResolver: {
169
+ resolve: () => actor(options.permissionKeys),
170
+ },
171
+ featureCatalog: declared.features,
172
+ },
173
+ );
174
+ const app = new FakeRouteApp();
175
+ installModuleGovernedResourceRoutes(hosts, app, {
176
+ runtime,
177
+ features: declared.features,
178
+ reauthenticate: (_actorId, password) =>
179
+ Promise.resolve(password === "correct"),
180
+ });
181
+ const guardContext = await runtime.createGuardContext(
182
+ new Request("http://localhost/api/people/persons/person-1"),
183
+ );
184
+ return {
185
+ runtime,
186
+ authorizations: () => authorizationCalls,
187
+ reads: () => readCalls,
188
+ invoke(method: "GET" | "POST", body?: unknown) {
189
+ const path =
190
+ method === "GET"
191
+ ? "/people/persons/:id"
192
+ : "/people/persons/:id/plaintext";
193
+ return app.invoke(method, path, {
194
+ guardContext,
195
+ params: { id: "person-1" },
196
+ query: {},
197
+ body,
198
+ });
199
+ },
200
+ };
201
+ }
202
+
203
+ function createHosts(manifest: ModuleManifest) {
204
+ return initializeModuleHosts({
205
+ modules: [manifest],
206
+ installations: [
207
+ {
208
+ manifest,
209
+ setup(host) {
210
+ host.registerGovernedResources([registration()]);
211
+ },
212
+ },
213
+ ],
214
+ });
215
+ }
216
+
217
+ function registration(
218
+ overrides: Partial<ModuleGovernedResourceRegistration> = {},
219
+ ): ModuleGovernedResourceRegistration {
220
+ return {
221
+ policyKey: "people.person.fields",
222
+ readPath: "/api/people/persons/:id",
223
+ revealPath: "/api/people/persons/:id/plaintext",
224
+ revealAuditAction: "people.phone.reveal",
225
+ authorize: () => true,
226
+ read: () => ({
227
+ id: "person-1",
228
+ publicFields: { name: "张三" },
229
+ governedFields: { phone: "13812348071" },
230
+ }),
231
+ ...overrides,
232
+ };
233
+ }
234
+
235
+ function peopleManifest(): ModuleManifest {
236
+ const policyFeature = featureKey("people.person");
237
+ return {
238
+ name: "people",
239
+ version: "0.1.0",
240
+ label: "人员",
241
+ description: "人员主档",
242
+ menus: [],
243
+ adminRoutes: [],
244
+ permissions: [
245
+ permission("people.person.read", "read"),
246
+ permission("people.person.reveal", "reveal", "sensitive-disclosure"),
247
+ permission("people.person.export", "export", "governed-export"),
248
+ ],
249
+ apiPermissions: [
250
+ {
251
+ method: "GET",
252
+ path: "/api/people/persons/:id",
253
+ permissionKey: "people.person.read",
254
+ featureKey: policyFeature,
255
+ },
256
+ {
257
+ method: "POST",
258
+ path: "/api/people/persons/:id/plaintext",
259
+ permissionKey: "people.person.reveal",
260
+ featureKey: policyFeature,
261
+ },
262
+ ],
263
+ features: [
264
+ {
265
+ key: policyFeature,
266
+ label: "人员主档",
267
+ module: "people",
268
+ visible: "visible",
269
+ enabled: true,
270
+ stage: "stable",
271
+ },
272
+ ],
273
+ migrations: [],
274
+ schemaExports: [],
275
+ tasks: [],
276
+ tools: [],
277
+ providers: [],
278
+ dataPolicies: [
279
+ {
280
+ key: "people.person.fields",
281
+ resourceType: "people.person",
282
+ version: "1",
283
+ featureKey: policyFeature,
284
+ readPermissionKey: "people.person.read",
285
+ revealPermissionKey: "people.person.reveal",
286
+ exportPermissionKey: "people.person.export",
287
+ display: {
288
+ read: "masked",
289
+ reveal: "plaintext",
290
+ unauthorized: "hidden",
291
+ },
292
+ fields: [
293
+ {
294
+ fieldKey: "phone",
295
+ classification: "sensitive",
296
+ mask: { kind: "partial", prefix: 3, suffix: 4 },
297
+ },
298
+ ],
299
+ },
300
+ ],
301
+ auditActions: ["people.phone.reveal"],
302
+ };
303
+ }
304
+
305
+ function permission(
306
+ key: string,
307
+ action: PermissionDefinition["action"],
308
+ accessRisk?: PermissionDefinition["accessRisk"],
309
+ ): PermissionDefinition {
310
+ return {
311
+ key,
312
+ label: key,
313
+ module: "people",
314
+ moduleLabel: "人员",
315
+ resource: "person",
316
+ resourceLabel: "人员",
317
+ action,
318
+ accessRisk,
319
+ };
320
+ }
321
+
322
+ function actor(
323
+ permissionKeys = [
324
+ "people.person.read",
325
+ "people.person.reveal",
326
+ "people.person.export",
327
+ ],
328
+ ): RequestActor {
329
+ return {
330
+ id: "user-reviewer",
331
+ type: "user",
332
+ name: "复核员",
333
+ roleCodes: ["reviewer"],
334
+ permissionKeys,
335
+ ...buildActorScopeContexts("user-reviewer", "dept-case", [
336
+ {
337
+ id: "role-reviewer",
338
+ code: "reviewer",
339
+ dataScope: "department",
340
+ departmentIds: [],
341
+ },
342
+ ]),
343
+ };
344
+ }
@@ -0,0 +1,203 @@
1
+ import type { ModuleManifest } from "@southwind-ai/modules";
2
+ import {
3
+ requireModuleNamespace,
4
+ type ModuleGovernedResourceRegistration,
5
+ } from "@southwind-ai/server-sdk";
6
+ import type { RegisteredModuleGovernedResource } from "./initialize-contracts.js";
7
+
8
+ export interface GovernedResourceRegistrationState {
9
+ readonly governedResources: RegisteredModuleGovernedResource[];
10
+ readonly governedResourceKeys: Set<string>;
11
+ readonly routeKeys: Set<string>;
12
+ }
13
+
14
+ export function registerGovernedResources(
15
+ manifest: ModuleManifest,
16
+ state: GovernedResourceRegistrationState,
17
+ registrations: readonly ModuleGovernedResourceRegistration[],
18
+ ) {
19
+ for (const registration of registrations) {
20
+ requireModuleNamespace(
21
+ "数据治理策略",
22
+ registration.policyKey,
23
+ manifest.name,
24
+ );
25
+ const policy = manifest.dataPolicies?.find(
26
+ ({ key }) => key === registration.policyKey,
27
+ );
28
+ if (!policy) {
29
+ throw new Error(
30
+ `业务治理资源未在 Manifest 声明:${registration.policyKey}`,
31
+ );
32
+ }
33
+ if (state.governedResourceKeys.has(registration.policyKey)) {
34
+ throw new Error(`业务治理资源重复注册:${registration.policyKey}`);
35
+ }
36
+ validateRoute(
37
+ manifest,
38
+ state,
39
+ "GET",
40
+ registration.readPath,
41
+ policy.readPermissionKey,
42
+ policy.featureKey,
43
+ );
44
+ if (registration.export) {
45
+ validateExportRegistration(manifest, state, registration);
46
+ }
47
+ validateRoute(
48
+ manifest,
49
+ state,
50
+ "POST",
51
+ registration.revealPath,
52
+ policy.revealPermissionKey,
53
+ policy.featureKey,
54
+ );
55
+ const audits = new Set(
56
+ manifest.auditActions.map((action) =>
57
+ typeof action === "string" ? action : action.key,
58
+ ),
59
+ );
60
+ if (!audits.has(registration.revealAuditAction)) {
61
+ throw new Error(
62
+ `业务治理明文审计未在 Manifest 声明:${registration.revealAuditAction}`,
63
+ );
64
+ }
65
+ state.governedResourceKeys.add(registration.policyKey);
66
+ state.governedResources.push({
67
+ moduleName: manifest.name,
68
+ registration,
69
+ });
70
+ }
71
+ }
72
+
73
+ function validateExportRegistration(
74
+ manifest: ModuleManifest,
75
+ state: GovernedResourceRegistrationState,
76
+ registration: ModuleGovernedResourceRegistration,
77
+ ) {
78
+ const policy = manifest.dataPolicies?.find(
79
+ ({ key }) => key === registration.policyKey,
80
+ );
81
+ if (!policy || !registration.export) return;
82
+ const basePath = registration.export.basePath;
83
+ if (
84
+ !basePath.startsWith(`/api/${manifest.name}/`) ||
85
+ basePath.includes(":id") ||
86
+ basePath.endsWith("/")
87
+ ) {
88
+ throw new Error(`业务治理导出基路径无效:${basePath}`);
89
+ }
90
+ if (
91
+ registration.export.retentionSeconds !== undefined &&
92
+ (!Number.isInteger(registration.export.retentionSeconds) ||
93
+ registration.export.retentionSeconds < 60)
94
+ ) {
95
+ throw new Error(`业务治理导出保留时间无效:${registration.policyKey}`);
96
+ }
97
+ validateRenderers(manifest, registration);
98
+ for (const [method, suffix] of [
99
+ ["POST", ""],
100
+ ["GET", "/:id"],
101
+ ["POST", "/:id/cancel"],
102
+ ["GET", "/:id/download"],
103
+ ] as const) {
104
+ validateRoute(
105
+ manifest,
106
+ state,
107
+ method,
108
+ `${basePath}${suffix}`,
109
+ policy.exportPermissionKey,
110
+ policy.featureKey,
111
+ false,
112
+ );
113
+ }
114
+ }
115
+
116
+ function validateRenderers(
117
+ manifest: ModuleManifest,
118
+ registration: ModuleGovernedResourceRegistration,
119
+ ) {
120
+ const renderers = registration.export?.renderers;
121
+ if (!renderers) return;
122
+ if (renderers.length === 0) {
123
+ throw new Error(`业务治理导出 Renderer 列表不能为空:${registration.policyKey}`);
124
+ }
125
+ const formatKeys = new Set<string>();
126
+ const schemas = new Set(
127
+ (manifest.jsonSchemas ?? []).map(({ key }) => key),
128
+ );
129
+ for (const renderer of renderers) {
130
+ if (
131
+ !/^[a-z0-9][a-z0-9._-]{0,79}$/.test(renderer.formatKey) ||
132
+ formatKeys.has(renderer.formatKey)
133
+ ) {
134
+ throw new Error(
135
+ `业务治理导出 formatKey 无效或重复:${renderer.formatKey}`,
136
+ );
137
+ }
138
+ formatKeys.add(renderer.formatKey);
139
+ requireModuleNamespace("治理导出模板", renderer.templateKey, manifest.name);
140
+ if (!schemas.has(renderer.inputSchemaKey)) {
141
+ throw new Error(
142
+ `业务治理导出引用了未注册 JSON Schema:${renderer.inputSchemaKey}`,
143
+ );
144
+ }
145
+ if (
146
+ !renderer.templateVersion.trim() ||
147
+ renderer.templateVersion.length > 80 ||
148
+ !/^[a-z0-9][a-z0-9.+-]{0,79}$/i.test(renderer.templateVersion) ||
149
+ renderer.contentType.length > 120 ||
150
+ !/^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$/i.test(
151
+ renderer.contentType,
152
+ ) ||
153
+ !/^[a-z0-9]{1,16}$/.test(renderer.filenameExtension) ||
154
+ !Number.isInteger(renderer.limits.maxRecords) ||
155
+ renderer.limits.maxRecords < 1 ||
156
+ renderer.limits.maxRecords > 1_000_000 ||
157
+ !Number.isInteger(renderer.limits.maxOutputBytes) ||
158
+ renderer.limits.maxOutputBytes < 1 ||
159
+ renderer.limits.maxOutputBytes > 1024 * 1024 * 1024 ||
160
+ !Number.isInteger(renderer.limits.timeoutSeconds) ||
161
+ renderer.limits.timeoutSeconds < 1 ||
162
+ renderer.limits.timeoutSeconds > 900
163
+ ) {
164
+ throw new Error(
165
+ `业务治理导出 Renderer 元数据或上限无效:${renderer.formatKey}`,
166
+ );
167
+ }
168
+ }
169
+ }
170
+
171
+ function validateRoute(
172
+ manifest: ModuleManifest,
173
+ state: GovernedResourceRegistrationState,
174
+ method: "GET" | "POST",
175
+ path: string,
176
+ permissionKey: string,
177
+ featureKey: string,
178
+ requireResourceId = true,
179
+ ) {
180
+ if (
181
+ !path.startsWith("/api/") ||
182
+ (requireResourceId && !path.includes(":id"))
183
+ ) {
184
+ throw new Error(
185
+ `业务治理路由必须是${requireResourceId ? "含 :id 的 " : ""}/api 路径:${path}`,
186
+ );
187
+ }
188
+ const binding = manifest.apiPermissions.find(
189
+ (item) => item.method === method && item.path === path,
190
+ );
191
+ if (
192
+ !binding ||
193
+ binding.permissionKey !== permissionKey ||
194
+ binding.featureKey !== featureKey
195
+ ) {
196
+ throw new Error(`业务治理路由与 Manifest 绑定不一致:${method} ${path}`);
197
+ }
198
+ const key = `${method} ${path}`;
199
+ if (state.routeKeys.has(key)) {
200
+ throw new Error(`模块路由重复注册:${key}`);
201
+ }
202
+ state.routeKeys.add(key);
203
+ }
@@ -0,0 +1,95 @@
1
+ import type { FeatureFlagDefinition } from "@southwind-ai/shared";
2
+ // @windy-module system.scheduler begin
3
+ import type { DurableJobService } from "../jobs/service.js";
4
+ import type { DurableJobWorker } from "../jobs/worker.js";
5
+ // @windy-module system.scheduler end
6
+ import type { createServerRuntime } from "../runtime.js";
7
+ // @windy-module system.storage begin
8
+ import type { createStorageRuntime } from "../storage/runtime.js";
9
+ // @windy-module system.storage end
10
+ import type { RouteApp } from "../system/route-types.js";
11
+ import type { SystemRepositories } from "../system/seed.js";
12
+ // @windy-module system.agent begin
13
+ import type { RequestGuardContext } from "../guards.js";
14
+ import type { AiArtifactRuntime } from "../ai-artifact/runtime.js";
15
+ import type { ModuleAiOperationPort } from "@southwind-ai/server-sdk";
16
+ // @windy-module system.agent end
17
+ import { installModuleRoutes } from "./route-installer.js";
18
+ import type { InitializedModuleHosts } from "./initialize.js";
19
+ // @windy-module system.data-governance begin
20
+ import type { GovernedExportService } from "../data-governance/export/service.js";
21
+ import { installModuleGovernedExportRoutes } from "./governed-export-routes.js";
22
+ import { installModuleGovernedResourceRoutes } from "./governed-resource-routes.js";
23
+ // @windy-module system.data-governance end
24
+
25
+ type ServerRuntime = ReturnType<typeof createServerRuntime>;
26
+
27
+ export function installModuleHttpRuntime(
28
+ hosts: InitializedModuleHosts,
29
+ app: RouteApp,
30
+ context: {
31
+ runtime: ServerRuntime;
32
+ features: readonly FeatureFlagDefinition[];
33
+ // @windy-module system.scheduler begin
34
+ jobs: DurableJobService;
35
+ jobWorker: DurableJobWorker;
36
+ // @windy-module system.scheduler end
37
+ // @windy-module system.storage begin
38
+ storage: ReturnType<typeof createStorageRuntime>;
39
+ // @windy-module system.storage end
40
+ systemRepositories: SystemRepositories;
41
+ // @windy-module system.agent begin
42
+ aiArtifacts?: AiArtifactRuntime;
43
+ aiOperations?: (
44
+ moduleName: string,
45
+ guardContext: RequestGuardContext,
46
+ signal: AbortSignal,
47
+ ) => ModuleAiOperationPort;
48
+ // @windy-module system.agent end
49
+ // @windy-module system.data-governance begin
50
+ reauthenticate(actorId: string, password: string): Promise<boolean>;
51
+ governedExportService: GovernedExportService;
52
+ // @windy-module system.data-governance end
53
+ },
54
+ ) {
55
+ installModuleRoutes(hosts, app, {
56
+ runtime: context.runtime,
57
+ features: context.features,
58
+ // @windy-module system.scheduler begin
59
+ jobs: context.jobs,
60
+ jobControl: { worker: context.jobWorker },
61
+ // @windy-module system.scheduler end
62
+ // @windy-module system.storage begin
63
+ storage: {
64
+ uploads: context.storage.uploads,
65
+ files: context.storage.files,
66
+ },
67
+ // @windy-module system.storage end
68
+ userDirectory: {
69
+ repositories: context.systemRepositories,
70
+ },
71
+ // @windy-module system.agent begin
72
+ aiArtifacts: context.aiArtifacts
73
+ ? (moduleName, guardContext, signal) =>
74
+ context.aiArtifacts!.createModulePort(
75
+ moduleName,
76
+ guardContext,
77
+ signal,
78
+ )
79
+ : undefined,
80
+ aiOperations: context.aiOperations,
81
+ // @windy-module system.agent end
82
+ });
83
+ // @windy-module system.data-governance begin
84
+ installModuleGovernedResourceRoutes(hosts, app, {
85
+ runtime: context.runtime,
86
+ features: context.features,
87
+ reauthenticate: context.reauthenticate,
88
+ });
89
+ installModuleGovernedExportRoutes(hosts, app, {
90
+ runtime: context.runtime,
91
+ features: context.features,
92
+ service: context.governedExportService,
93
+ });
94
+ // @windy-module system.data-governance end
95
+ }
@@ -4,10 +4,12 @@ import type {
4
4
  InstallableServerModule,
5
5
  ModuleAiOperationHandlerRegistration,
6
6
  ModuleInitializer,
7
+ ModuleGovernedResourceRegistration,
7
8
  ModuleRolePreset,
8
9
  ModuleResourceFileAccessPolicy,
9
10
  ModuleRouteDefinition,
10
11
  ModuleSearchProvider,
12
+ ModuleSandboxToolHandlerRegistration,
11
13
  ModuleTaskHandlerRegistration,
12
14
  ModuleToolHandlerRegistration,
13
15
  ModuleUploadPolicy,
@@ -28,11 +30,21 @@ export interface RegisteredModuleToolHandler {
28
30
  readonly registration: ModuleToolHandlerRegistration;
29
31
  }
30
32
 
33
+ export interface RegisteredModuleSandboxToolHandler {
34
+ readonly moduleName: string;
35
+ readonly registration: ModuleSandboxToolHandlerRegistration;
36
+ }
37
+
31
38
  export interface RegisteredModuleAiOperationHandler {
32
39
  readonly moduleName: string;
33
40
  readonly registration: ModuleAiOperationHandlerRegistration;
34
41
  }
35
42
 
43
+ export interface RegisteredModuleGovernedResource {
44
+ readonly moduleName: string;
45
+ readonly registration: ModuleGovernedResourceRegistration;
46
+ }
47
+
36
48
  export interface RegisteredModuleRolePreset {
37
49
  readonly moduleName: string;
38
50
  readonly preset: ModuleRolePreset;
@@ -59,7 +71,9 @@ export interface InitializedModuleHosts {
59
71
  readonly routes: readonly RegisteredModuleRoute[];
60
72
  readonly taskHandlers: readonly RegisteredModuleTaskHandler[];
61
73
  readonly toolHandlers: readonly RegisteredModuleToolHandler[];
74
+ readonly sandboxToolHandlers: readonly RegisteredModuleSandboxToolHandler[];
62
75
  readonly aiOperationHandlers: readonly RegisteredModuleAiOperationHandler[];
76
+ readonly governedResources: readonly RegisteredModuleGovernedResource[];
63
77
  readonly rolePresets: readonly RegisteredModuleRolePreset[];
64
78
  readonly searchProviders: readonly RegisteredModuleSearchProvider[];
65
79
  manifestOf(moduleName: string): ModuleManifest;