create-windy 0.2.6 → 0.2.8

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 (361) hide show
  1. package/README.md +14 -3
  2. package/dist/cli.js +191 -87
  3. package/package.json +1 -1
  4. package/template/.windy-template.json +2 -2
  5. package/template/README.md +8 -0
  6. package/template/apps/server/Dockerfile +2 -0
  7. package/template/apps/server/package.json +10 -8
  8. package/template/apps/server/src/access-guards.ts +1 -1
  9. package/template/apps/server/src/admin/routes.test.ts +10 -0
  10. package/template/apps/server/src/admin/routes.ts +4 -2
  11. package/template/apps/server/src/agent/routes.test.ts +1 -1
  12. package/template/apps/server/src/agent/routes.ts +2 -2
  13. package/template/apps/server/src/application-services.ts +3 -0
  14. package/template/apps/server/src/audit/drizzle-log-store.ts +2 -2
  15. package/template/apps/server/src/audit/policy.ts +1 -1
  16. package/template/apps/server/src/audit/recovery-queue.test.ts +1 -1
  17. package/template/apps/server/src/audit/recovery-queue.ts +1 -1
  18. package/template/apps/server/src/audit/redaction.ts +1 -1
  19. package/template/apps/server/src/audit/reliable-writer.test.ts +1 -1
  20. package/template/apps/server/src/audit/reliable-writer.ts +1 -1
  21. package/template/apps/server/src/audit/search-summary.ts +1 -1
  22. package/template/apps/server/src/auth/authentication-provider.test.ts +1 -1
  23. package/template/apps/server/src/auth/credential-service.ts +1 -1
  24. package/template/apps/server/src/auth/drizzle-repository.ts +2 -2
  25. package/template/apps/server/src/auth/drizzle-session-operations.ts +1 -1
  26. package/template/apps/server/src/auth/own-session-routes.test.ts +1 -1
  27. package/template/apps/server/src/auth/password.ts +2 -4
  28. package/template/apps/server/src/auth/repository.ts +1 -1
  29. package/template/apps/server/src/auth/routes.test.ts +1 -1
  30. package/template/apps/server/src/auth/service.ts +1 -1
  31. package/template/apps/server/src/bulk-data/artifact-store.ts +1 -1
  32. package/template/apps/server/src/bulk-data/dictionary-handler.ts +1 -1
  33. package/template/apps/server/src/bulk-data/drizzle-repository.ts +3 -3
  34. package/template/apps/server/src/bulk-data/repository.ts +1 -1
  35. package/template/apps/server/src/bulk-data/routes.test.ts +1 -1
  36. package/template/apps/server/src/bulk-data/routes.ts +1 -1
  37. package/template/apps/server/src/bulk-data/service.test.ts +1 -1
  38. package/template/apps/server/src/bulk-data/service.ts +1 -1
  39. package/template/apps/server/src/bulk-data/types.ts +1 -1
  40. package/template/apps/server/src/configuration/bootstrap.ts +2 -2
  41. package/template/apps/server/src/configuration/definition.ts +2 -2
  42. package/template/apps/server/src/configuration/drizzle-repository.ts +2 -2
  43. package/template/apps/server/src/configuration/repository.ts +1 -1
  44. package/template/apps/server/src/configuration/routes.ts +1 -1
  45. package/template/apps/server/src/configuration/service.ts +1 -1
  46. package/template/apps/server/src/data-access/context.ts +2 -2
  47. package/template/apps/server/src/data-access/query-specification.test.ts +1 -1
  48. package/template/apps/server/src/data-access/scoped-repository.integration.test.ts +1 -1
  49. package/template/apps/server/src/data-access/scoped-repository.ts +1 -1
  50. package/template/apps/server/src/data-access/scoped-resource.test.ts +1 -1
  51. package/template/apps/server/src/data-access/scoped-resource.ts +1 -1
  52. package/template/apps/server/src/data-governance/export/approval-port.ts +1 -1
  53. package/template/apps/server/src/data-governance/export/drizzle-repository.ts +1 -1
  54. package/template/apps/server/src/data-governance/export/job-runtime.test.ts +2 -2
  55. package/template/apps/server/src/data-governance/export/job-runtime.ts +2 -3
  56. package/template/apps/server/src/data-governance/export/postgres-api-fixture.ts +2 -2
  57. package/template/apps/server/src/data-governance/export/postgres-api.integration.test.ts +1 -1
  58. package/template/apps/server/src/data-governance/export/routes-test-fixture.ts +3 -3
  59. package/template/apps/server/src/data-governance/export/routes.ts +1 -1
  60. package/template/apps/server/src/data-governance/export/scope-snapshot.ts +1 -1
  61. package/template/apps/server/src/data-governance/export/service.ts +2 -2
  62. package/template/apps/server/src/data-governance/export/source.ts +1 -1
  63. package/template/apps/server/src/data-governance/export/types.ts +1 -1
  64. package/template/apps/server/src/data-governance/plaintext-access.test.ts +1 -1
  65. package/template/apps/server/src/data-governance/plaintext-access.ts +1 -1
  66. package/template/apps/server/src/data-governance/plaintext-postgres.integration.test.ts +1 -1
  67. package/template/apps/server/src/data-governance/user-plaintext-routes.ts +1 -1
  68. package/template/apps/server/src/data-governance/user-projection.ts +2 -2
  69. package/template/apps/server/src/example-modules.ts +25 -1
  70. package/template/apps/server/src/feature/manifest-feature-repository.test.ts +1 -1
  71. package/template/apps/server/src/feature/manifest-feature-repository.ts +1 -1
  72. package/template/apps/server/src/feature/routes.ts +3 -6
  73. package/template/apps/server/src/foundation-access.test.ts +1 -1
  74. package/template/apps/server/src/foundation-access.ts +1 -1
  75. package/template/apps/server/src/foundation.ts +21 -7
  76. package/template/apps/server/src/guards.test.ts +1 -1
  77. package/template/apps/server/src/guards.ts +3 -3
  78. package/template/apps/server/src/index.ts +27 -3
  79. package/template/{packages/modules → apps/server}/src/installed-business-modules.ts +2 -2
  80. package/template/apps/server/src/jobs/artifact-service.test.ts +1 -1
  81. package/template/apps/server/src/jobs/artifact-service.ts +2 -2
  82. package/template/apps/server/src/jobs/drizzle-artifact.ts +2 -2
  83. package/template/apps/server/src/jobs/drizzle-claim.ts +1 -1
  84. package/template/apps/server/src/jobs/drizzle-execution-repository.ts +2 -2
  85. package/template/apps/server/src/jobs/drizzle-execution.integration.test.ts +1 -1
  86. package/template/apps/server/src/jobs/drizzle-lease.ts +2 -2
  87. package/template/apps/server/src/jobs/drizzle-mappers.ts +3 -3
  88. package/template/apps/server/src/jobs/drizzle-recovery-repository.ts +1 -1
  89. package/template/apps/server/src/jobs/drizzle-repository.integration.test.ts +1 -1
  90. package/template/apps/server/src/jobs/drizzle-repository.ts +3 -3
  91. package/template/apps/server/src/jobs/execution-repository.ts +1 -1
  92. package/template/apps/server/src/jobs/execution.test.ts +2 -2
  93. package/template/apps/server/src/jobs/in-memory-claim.ts +1 -1
  94. package/template/apps/server/src/jobs/in-memory-execution.ts +1 -1
  95. package/template/apps/server/src/jobs/in-memory-lease.ts +1 -1
  96. package/template/apps/server/src/jobs/legacy-adapter.integration.test.ts +1 -1
  97. package/template/apps/server/src/jobs/legacy-adapter.test.ts +1 -1
  98. package/template/apps/server/src/jobs/legacy-adapter.ts +1 -1
  99. package/template/apps/server/src/jobs/legacy-service-runtime.ts +4 -2
  100. package/template/apps/server/src/jobs/repository.ts +2 -2
  101. package/template/apps/server/src/jobs/service.ts +2 -2
  102. package/template/apps/server/src/jobs/worker.ts +3 -2
  103. package/template/apps/server/src/license/legacy-license-resolver.ts +1 -1
  104. package/template/apps/server/src/license/license-resolver.test.ts +1 -1
  105. package/template/apps/server/src/license/license-resolver.ts +3 -3
  106. package/template/apps/server/src/license/routes-offline-code.test.ts +2 -2
  107. package/template/apps/server/src/license/routes.ts +1 -1
  108. package/template/apps/server/src/license/runtime-audit-reliability.test.ts +2 -2
  109. package/template/apps/server/src/license/runtime-reminder.test.ts +2 -2
  110. package/template/apps/server/src/license/runtime-service.test.ts +2 -2
  111. package/template/apps/server/src/license/runtime-service.ts +2 -2
  112. package/template/apps/server/src/module-composition.test.ts +1 -1
  113. package/template/apps/server/src/module-composition.ts +1 -1
  114. package/template/apps/server/src/module-host.test.ts +145 -0
  115. package/template/apps/server/src/module-host.ts +110 -0
  116. package/template/apps/server/src/notification/drizzle-repository.ts +2 -2
  117. package/template/apps/server/src/notification/repository.ts +1 -1
  118. package/template/apps/server/src/notification/routes.ts +1 -1
  119. package/template/apps/server/src/pagination.ts +1 -1
  120. package/template/apps/server/src/persistence.integration.test.ts +1 -1
  121. package/template/apps/server/src/persistence.ts +1 -1
  122. package/template/apps/server/src/profile/routes.ts +1 -1
  123. package/template/apps/server/src/route-guards.test.ts +1 -1
  124. package/template/apps/server/src/route-guards.ts +1 -1
  125. package/template/apps/server/src/runtime-feature.ts +125 -0
  126. package/template/apps/server/src/runtime-license.ts +1 -1
  127. package/template/apps/server/src/runtime.test.ts +48 -1
  128. package/template/apps/server/src/runtime.ts +17 -64
  129. package/template/apps/server/src/scheduler/audit.ts +1 -1
  130. package/template/apps/server/src/scheduler/definitions.test.ts +1 -1
  131. package/template/apps/server/src/scheduler/definitions.ts +2 -2
  132. package/template/apps/server/src/scheduler/drizzle-durable-links.ts +1 -1
  133. package/template/apps/server/src/scheduler/drizzle-mappers.ts +1 -1
  134. package/template/apps/server/src/scheduler/drizzle-repository.ts +1 -1
  135. package/template/apps/server/src/scheduler/execution-recorder.ts +1 -1
  136. package/template/apps/server/src/scheduler/history.ts +1 -1
  137. package/template/apps/server/src/scheduler/overview.ts +1 -1
  138. package/template/apps/server/src/scheduler/recovery-service.test.ts +1 -1
  139. package/template/apps/server/src/scheduler/recovery-service.ts +1 -1
  140. package/template/apps/server/src/scheduler/repository.ts +1 -1
  141. package/template/apps/server/src/scheduler/routes.ts +1 -1
  142. package/template/apps/server/src/scheduler/service-idle.test.ts +1 -1
  143. package/template/apps/server/src/scheduler/service.test.ts +1 -1
  144. package/template/apps/server/src/scheduler/service.ts +1 -1
  145. package/template/apps/server/src/scheduler/types.ts +1 -1
  146. package/template/apps/server/src/search/contracts.ts +2 -2
  147. package/template/apps/server/src/search/host.ts +1 -1
  148. package/template/apps/server/src/search/registry.ts +1 -1
  149. package/template/apps/server/src/search/routes.test.ts +1 -1
  150. package/template/apps/server/src/search/routes.ts +1 -1
  151. package/template/apps/server/src/search/service.ts +2 -2
  152. package/template/apps/server/src/search/test-support.ts +2 -2
  153. package/template/apps/server/src/session/routes.ts +1 -1
  154. package/template/apps/server/src/settings/drizzle-repository.ts +2 -2
  155. package/template/apps/server/src/settings/repository.ts +1 -1
  156. package/template/apps/server/src/settings/routes.test.ts +1 -1
  157. package/template/apps/server/src/settings/routes.ts +1 -1
  158. package/template/apps/server/src/settings/runtime.ts +1 -1
  159. package/template/apps/server/src/storage/blob-reference-registry.test.ts +1 -1
  160. package/template/apps/server/src/storage/blob-reference-registry.ts +1 -1
  161. package/template/apps/server/src/storage/drizzle-upload-repository.integration.test.ts +1 -1
  162. package/template/apps/server/src/storage/drizzle-upload-repository.ts +2 -2
  163. package/template/apps/server/src/storage/route-support.ts +1 -1
  164. package/template/apps/server/src/storage/routes.test.ts +1 -1
  165. package/template/apps/server/src/storage/routes.ts +2 -2
  166. package/template/apps/server/src/storage/runtime.ts +6 -4
  167. package/template/apps/server/src/system/audit-routes.ts +1 -1
  168. package/template/apps/server/src/system/department-routes.ts +1 -1
  169. package/template/apps/server/src/system/drizzle-repository.ts +1 -1
  170. package/template/apps/server/src/system/drizzle-scoped-repository.ts +1 -1
  171. package/template/apps/server/src/system/drizzle-system.ts +1 -1
  172. package/template/apps/server/src/system/entities.ts +1 -1
  173. package/template/apps/server/src/system/identity-route-config.ts +1 -1
  174. package/template/apps/server/src/system/interface-catalog.test.ts +3 -3
  175. package/template/apps/server/src/system/interface-catalog.ts +2 -2
  176. package/template/apps/server/src/system/menu-registry.ts +1 -1
  177. package/template/apps/server/src/system/menu-routes.ts +1 -1
  178. package/template/apps/server/src/system/operations.test.ts +1 -1
  179. package/template/apps/server/src/system/operations.ts +1 -1
  180. package/template/apps/server/src/system/redis-health.ts +1 -1
  181. package/template/apps/server/src/system/repository.ts +1 -1
  182. package/template/apps/server/src/system/resource-route-support.ts +1 -1
  183. package/template/apps/server/src/system/route-helpers.ts +1 -1
  184. package/template/apps/server/src/system/route-types.ts +1 -1
  185. package/template/apps/server/src/system/routes.test.ts +1 -1
  186. package/template/apps/server/src/system/routes.ts +1 -1
  187. package/template/apps/server/src/system/user-projection.ts +1 -1
  188. package/template/apps/server/src/work-order/data-scope.integration.test.ts +1 -1
  189. package/template/apps/server/src/work-order/drizzle-repository.integration.test.ts +1 -1
  190. package/template/apps/server/src/work-order/drizzle-repository.ts +2 -2
  191. package/template/apps/server/src/work-order/foundation-modules.test.ts +15 -5
  192. package/template/apps/server/src/work-order/repository.ts +1 -1
  193. package/template/apps/server/src/work-order/routes.test.ts +2 -2
  194. package/template/apps/server/src/work-order/routes.ts +2 -2
  195. package/template/apps/server/src/work-order/search-api.test.ts +3 -3
  196. package/template/apps/server/src/work-order/search-provider.test.ts +3 -3
  197. package/template/apps/server/src/work-order/service.ts +1 -1
  198. package/template/apps/server/src/work-order/task.test.ts +1 -1
  199. package/template/apps/server/src/work-order/task.ts +2 -2
  200. package/template/apps/server/src/workflow/drizzle-repository.integration.test.ts +2 -2
  201. package/template/apps/server/src/workflow/drizzle-repository.ts +3 -3
  202. package/template/apps/server/src/workflow/effects.test.ts +1 -1
  203. package/template/apps/server/src/workflow/effects.ts +1 -1
  204. package/template/apps/server/src/workflow/repository.ts +2 -2
  205. package/template/apps/server/src/workflow/routes.ts +3 -3
  206. package/template/apps/server/src/workflow/service.ts +1 -1
  207. package/template/apps/server/src/workflow/timeout-runtime.test.ts +1 -1
  208. package/template/apps/server/src/workflow/timeout-runtime.ts +2 -2
  209. package/template/apps/web/Dockerfile +2 -0
  210. package/template/apps/web/package.json +4 -4
  211. package/template/apps/web/runtime-server.ts +1 -1
  212. package/template/apps/web/src/app/layouts/AppLayout.vue +6 -0
  213. package/template/apps/web/src/components/auth/PasswordChangeForm.vue +52 -7
  214. package/template/apps/web/src/components/auth/PasswordChangeForm.webtest.ts +43 -0
  215. package/template/apps/web/src/components/common/DataPagination.vue +1 -1
  216. package/template/apps/web/src/components/license/LicenseActivationCodeForm.vue +1 -1
  217. package/template/apps/web/src/components/license/LicenseFlow.webtest.ts +2 -2
  218. package/template/apps/web/src/composables/useModuleConfigurations.ts +1 -1
  219. package/template/apps/web/src/composables/useWatermarkSettings.ts +1 -0
  220. package/template/apps/web/src/composables/watermark-settings.ts +6 -0
  221. package/template/apps/web/src/composables/watermark-settings.webtest.ts +27 -1
  222. package/template/apps/web/src/layout/AppSidebar.vue +12 -3
  223. package/template/apps/web/src/layout/AppSidebar.webtest.ts +11 -0
  224. package/template/apps/web/src/layout/GlobalWatermark.vue +25 -8
  225. package/template/apps/web/src/layout/GlobalWatermark.webtest.ts +109 -0
  226. package/template/apps/web/src/layout/NavigationSearchDialog.vue +1 -1
  227. package/template/apps/web/src/layout/NotificationMenu.vue +1 -1
  228. package/template/apps/web/src/layout/navigation.ts +5 -1
  229. package/template/apps/web/src/layout/navigation.webtest.ts +1 -1
  230. package/template/apps/web/src/pages/configuration/components/ModuleConfigRollbackDialog.vue +1 -1
  231. package/template/apps/web/src/pages/configuration/components/ModuleConfigVersionList.vue +1 -1
  232. package/template/apps/web/src/pages/configuration/components/ModuleConfigurationEditor.vue +1 -1
  233. package/template/apps/web/src/pages/configuration/components/ModuleConfigurationEditor.webtest.ts +1 -1
  234. package/template/apps/web/src/pages/configuration/components/ModuleConfigurationWorkbench.vue +1 -1
  235. package/template/apps/web/src/pages/dashboard/dashboard-presenter.webtest.ts +1 -1
  236. package/template/apps/web/src/pages/settings/WatermarkSettingsSection.vue +21 -0
  237. package/template/apps/web/src/pages/system/SystemNotificationsPage.vue +2 -2
  238. package/template/apps/web/src/pages/system/components/AuditActionCell.vue +7 -2
  239. package/template/apps/web/src/pages/system/components/AuditLogFilters.vue +7 -2
  240. package/template/apps/web/src/pages/system/components/NotificationPublishForm.vue +1 -1
  241. package/template/apps/web/src/pages/system/components/SchedulerOperationsPanel.vue +1 -1
  242. package/template/apps/web/src/pages/system/components/SchedulerOperationsPanel.webtest.ts +1 -1
  243. package/template/apps/web/src/pages/system/components/SchedulerRunTable.vue +1 -1
  244. package/template/apps/web/src/pages/system/components/SchedulerRunTable.webtest.ts +1 -1
  245. package/template/apps/web/src/pages/system/components/SchedulerStaleRecoveryForm.vue +1 -1
  246. package/template/apps/web/src/pages/system/components/SchedulerStaleRecoveryForm.webtest.ts +1 -1
  247. package/template/apps/web/src/pages/system/components/SystemResourcePage.vue +1 -1
  248. package/template/apps/web/src/pages/system/components/SystemResourceTable.vue +10 -3
  249. package/template/apps/web/src/pages/system/components/role-policy/RolePermissionTree.vue +1 -1
  250. package/template/apps/web/src/pages/system/components/role-policy/RolePermissionTree.webtest.ts +1 -1
  251. package/template/apps/web/src/pages/system/components/role-policy/RolePolicyForm.vue +1 -1
  252. package/template/apps/web/src/pages/system/components/role-policy/permission-tree.ts +1 -1
  253. package/template/apps/web/src/pages/system/components/role-policy/permission-tree.webtest.ts +1 -1
  254. package/template/apps/web/src/pages/system/composables/useSchedulerOperations.ts +2 -2
  255. package/template/apps/web/src/pages/system/composables/useSchedulerOperations.webtest.ts +1 -1
  256. package/template/apps/web/src/pages/system/composables/useSystemResource.ts +1 -1
  257. package/template/apps/web/src/router/manifest-routes.ts +1 -1
  258. package/template/apps/web/src/router/manifest-routes.webtest.ts +1 -1
  259. package/template/apps/web/src/services/access-api.ts +10 -1
  260. package/template/apps/web/src/services/configuration-api.ts +1 -1
  261. package/template/apps/web/src/services/license-api.ts +1 -1
  262. package/template/apps/web/src/services/notification-api.ts +2 -2
  263. package/template/apps/web/src/services/operations-api.ts +1 -1
  264. package/template/apps/web/src/services/platform-settings-api.ts +2 -2
  265. package/template/apps/web/src/services/profile-api.ts +2 -2
  266. package/template/docs/architecture/durable-jobs.md +5 -0
  267. package/template/docs/architecture/module-manifest-composition.md +14 -7
  268. package/template/docs/architecture/object-storage.md +1 -1
  269. package/template/docs/development/crud-generator.md +4 -1
  270. package/template/docs/platform/audit-reliability.md +1 -1
  271. package/template/package.json +2 -1
  272. package/template/packages/config/package.json +15 -4
  273. package/template/packages/config/src/platform.ts +1 -1
  274. package/template/packages/crud-generator/package.json +1 -1
  275. package/template/packages/crud-generator/src/generator.test.ts +16 -0
  276. package/template/packages/crud-generator/src/templates/domain.ts +1 -1
  277. package/template/packages/crud-generator/src/templates/manifest.ts +2 -2
  278. package/template/packages/crud-generator/src/templates/project.ts +3 -3
  279. package/template/packages/crud-generator/src/templates/repository.ts +1 -1
  280. package/template/packages/crud-generator/src/templates/routes.ts +2 -2
  281. package/template/packages/crud-generator/src/validation.ts +22 -1
  282. package/template/packages/database/package.json +15 -5
  283. package/template/packages/database/src/bundle-validation.ts +218 -0
  284. package/template/packages/database/src/dialects.ts +1 -1
  285. package/template/packages/database/src/runner.test.ts +160 -13
  286. package/template/packages/database/src/runner.ts +95 -77
  287. package/template/packages/database/src/schema/governed-exports.ts +1 -1
  288. package/template/packages/database/src/schema/identity.ts +1 -1
  289. package/template/packages/database/src/schema/license-v1.ts +1 -1
  290. package/template/packages/database/src/schema/notifications.ts +1 -1
  291. package/template/packages/database/src/schema/platform-settings.ts +1 -1
  292. package/template/packages/database/src/schema/workflow.ts +1 -1
  293. package/template/packages/database/src/sql-store.ts +1 -1
  294. package/template/packages/database/src/store.ts +1 -1
  295. package/template/packages/example-work-order/index.ts +1 -0
  296. package/template/packages/example-work-order/package.json +4 -3
  297. package/template/packages/example-work-order/src/contract.ts +1 -1
  298. package/template/packages/example-work-order/src/manifest.ts +8 -3
  299. package/template/packages/example-work-order/src/migration-bundle.test.ts +43 -0
  300. package/template/packages/example-work-order/src/migration-bundle.ts +64 -0
  301. package/template/packages/jobs/index.ts +2 -0
  302. package/template/packages/jobs/package.json +29 -0
  303. package/template/packages/jobs/src/handlers.test.ts +72 -0
  304. package/template/{apps/server/src/jobs/handler-registry.ts → packages/jobs/src/handlers.ts} +4 -4
  305. package/template/{apps/server/src/jobs → packages/jobs/src}/types.ts +7 -1
  306. package/template/packages/{license-sdk → jobs}/tsconfig.json +0 -1
  307. package/template/packages/modules/index.ts +1 -1
  308. package/template/packages/modules/package.json +15 -5
  309. package/template/packages/modules/src/catalog-validation.ts +123 -0
  310. package/template/packages/modules/src/composition.test.ts +75 -2
  311. package/template/packages/modules/src/composition.ts +4 -2
  312. package/template/packages/modules/src/manifest.ts +7 -12
  313. package/template/packages/modules/src/menu-composition.ts +1 -1
  314. package/template/packages/modules/src/system-api-binding.ts +1 -1
  315. package/template/packages/modules/src/system-api-data-governance.ts +1 -1
  316. package/template/packages/modules/src/system-api-permissions.ts +1 -1
  317. package/template/packages/modules/src/system-data-governance.ts +1 -1
  318. package/template/packages/modules/src/system-features.ts +1 -1
  319. package/template/packages/modules/src/system-governed-export-bindings.ts +1 -1
  320. package/template/packages/modules/src/system-module-catalog.ts +1 -1
  321. package/template/packages/server-sdk/index.ts +5 -0
  322. package/template/packages/server-sdk/package.json +25 -0
  323. package/template/packages/server-sdk/src/module-host.ts +29 -0
  324. package/template/packages/server-sdk/tsconfig.json +16 -0
  325. package/template/packages/shared/index.ts +3 -0
  326. package/template/packages/shared/package.json +14 -3
  327. package/template/packages/shared/src/audit.ts +22 -1
  328. package/template/packages/shared/src/license-catalog.test.ts +17 -0
  329. package/template/packages/shared/src/license-catalog.ts +33 -0
  330. package/template/packages/shared/src/migration.ts +39 -0
  331. package/template/packages/shared/src/password.ts +4 -0
  332. package/template/packages/storage/package.json +14 -3
  333. package/template/packages/license-sdk/index.ts +0 -13
  334. package/template/packages/license-sdk/package.json +0 -18
  335. package/template/packages/license-sdk/src/bounded-json-body.test.ts +0 -65
  336. package/template/packages/license-sdk/src/bounded-json-body.ts +0 -135
  337. package/template/packages/license-sdk/src/canonical-json.test.ts +0 -28
  338. package/template/packages/license-sdk/src/canonical-json.ts +0 -104
  339. package/template/packages/license-sdk/src/client.test.ts +0 -82
  340. package/template/packages/license-sdk/src/client.ts +0 -86
  341. package/template/packages/license-sdk/src/device.ts +0 -46
  342. package/template/packages/license-sdk/src/file-storage.test.ts +0 -80
  343. package/template/packages/license-sdk/src/file-storage.ts +0 -77
  344. package/template/packages/license-sdk/src/installation.test.ts +0 -241
  345. package/template/packages/license-sdk/src/installation.ts +0 -150
  346. package/template/packages/license-sdk/src/license-parser.ts +0 -56
  347. package/template/packages/license-sdk/src/offline-code-base32.ts +0 -57
  348. package/template/packages/license-sdk/src/offline-code-decompression.ts +0 -55
  349. package/template/packages/license-sdk/src/offline-code-limits.ts +0 -10
  350. package/template/packages/license-sdk/src/offline-code-wire.ts +0 -72
  351. package/template/packages/license-sdk/src/offline-code.test.ts +0 -172
  352. package/template/packages/license-sdk/src/offline-code.ts +0 -319
  353. package/template/packages/license-sdk/src/payload.test.ts +0 -72
  354. package/template/packages/license-sdk/src/payload.ts +0 -201
  355. package/template/packages/license-sdk/src/storage.ts +0 -64
  356. package/template/packages/license-sdk/src/test-fixtures.ts +0 -59
  357. package/template/packages/license-sdk/src/v1-test-vector.ts +0 -49
  358. package/template/packages/license-sdk/src/validation.test.ts +0 -62
  359. package/template/packages/license-sdk/src/validation.ts +0 -143
  360. package/template/packages/license-sdk/src/verification.test.ts +0 -97
  361. package/template/packages/license-sdk/src/verification.ts +0 -199
@@ -1,104 +0,0 @@
1
- export type CanonicalJsonPrimitive = string | number | boolean | null;
2
- export type CanonicalJsonValue =
3
- | CanonicalJsonPrimitive
4
- | CanonicalJsonValue[]
5
- | { [key: string]: CanonicalJsonValue };
6
-
7
- export type CanonicalJsonErrorCode =
8
- | "CANONICAL_JSON_INVALID_TYPE"
9
- | "CANONICAL_JSON_INVALID_NUMBER"
10
- | "CANONICAL_JSON_INVALID_UNICODE"
11
- | "CANONICAL_JSON_CYCLE";
12
-
13
- export class CanonicalJsonError extends Error {
14
- constructor(
15
- readonly code: CanonicalJsonErrorCode,
16
- message: string,
17
- ) {
18
- super(message);
19
- this.name = "CanonicalJsonError";
20
- }
21
- }
22
-
23
- /**
24
- * RFC 8785 JSON Canonicalization Scheme (JCS) serializer.
25
- *
26
- * V1 intentionally accepts JSON values only: no undefined, BigInt, custom
27
- * toJSON conversion, non-finite numbers, or unpaired UTF-16 surrogates.
28
- */
29
- export function canonicalizeJson(value: unknown): string {
30
- return serialize(value, new Set<object>());
31
- }
32
-
33
- function serialize(value: unknown, ancestors: Set<object>): string {
34
- if (value === null) return "null";
35
- if (typeof value === "boolean") return value ? "true" : "false";
36
- if (typeof value === "string") return serializeString(value);
37
- if (typeof value === "number") return serializeNumber(value);
38
- if (typeof value !== "object") {
39
- throw new CanonicalJsonError(
40
- "CANONICAL_JSON_INVALID_TYPE",
41
- `JCS 不支持 ${typeof value} 值`,
42
- );
43
- }
44
- if (ancestors.has(value)) {
45
- throw new CanonicalJsonError("CANONICAL_JSON_CYCLE", "JCS 不支持循环引用");
46
- }
47
-
48
- ancestors.add(value);
49
- try {
50
- if (Array.isArray(value)) {
51
- return `[${value.map((item) => serialize(item, ancestors)).join(",")}]`;
52
- }
53
- const object = value as Record<string, unknown>;
54
- const members = Object.keys(object)
55
- .sort(compareUtf16)
56
- .map(
57
- (key) => `${serializeString(key)}:${serialize(object[key], ancestors)}`,
58
- );
59
- return `{${members.join(",")}}`;
60
- } finally {
61
- ancestors.delete(value);
62
- }
63
- }
64
-
65
- function serializeNumber(value: number): string {
66
- if (!Number.isFinite(value)) {
67
- throw new CanonicalJsonError(
68
- "CANONICAL_JSON_INVALID_NUMBER",
69
- "JCS 不支持 NaN 或无穷大",
70
- );
71
- }
72
- return JSON.stringify(value);
73
- }
74
-
75
- function serializeString(value: string): string {
76
- assertUnicodeScalarSequence(value);
77
- return JSON.stringify(value);
78
- }
79
-
80
- function assertUnicodeScalarSequence(value: string): void {
81
- for (let index = 0; index < value.length; index += 1) {
82
- const code = value.charCodeAt(index);
83
- if (code >= 0xd800 && code <= 0xdbff) {
84
- const next = value.charCodeAt(index + 1);
85
- if (!Number.isFinite(next) || next < 0xdc00 || next > 0xdfff) {
86
- invalidUnicode();
87
- }
88
- index += 1;
89
- } else if (code >= 0xdc00 && code <= 0xdfff) {
90
- invalidUnicode();
91
- }
92
- }
93
- }
94
-
95
- function invalidUnicode(): never {
96
- throw new CanonicalJsonError(
97
- "CANONICAL_JSON_INVALID_UNICODE",
98
- "JCS 不支持未配对的 UTF-16 surrogate",
99
- );
100
- }
101
-
102
- function compareUtf16(left: string, right: string): number {
103
- return left < right ? -1 : left > right ? 1 : 0;
104
- }
@@ -1,82 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
- import { WindyLicenseClient } from "./client.js";
3
- import { MemoryAtomicLicenseStore, MemoryLicenseStorage } from "./storage.js";
4
- import { LICENSE_V1_TEST_VECTOR } from "./v1-test-vector.js";
5
-
6
- const vectorLicense = JSON.stringify({
7
- formatVersion: 1,
8
- algorithm: "ED25519",
9
- publicKeyId: LICENSE_V1_TEST_VECTOR.keyId,
10
- claims: LICENSE_V1_TEST_VECTOR.claims,
11
- signature: LICENSE_V1_TEST_VECTOR.signature,
12
- });
13
-
14
- describe("WindyLicenseClient", () => {
15
- test("使用固定向量和多公钥环打开 V1 License", async () => {
16
- const client = new WindyLicenseClient({
17
- licenseSource: new MemoryAtomicLicenseStore(vectorLicense),
18
- stateStorage: new MemoryLicenseStorage(),
19
- productCode: "windy-platform",
20
- machineCode: "machine-vector-001",
21
- publicKeys: {
22
- unrelated: LICENSE_V1_TEST_VECTOR.publicKeyPem,
23
- [LICENSE_V1_TEST_VECTOR.keyId]: LICENSE_V1_TEST_VECTOR.publicKeyPem,
24
- },
25
- now: () => new Date("2026-07-10T10:00:00.000Z"),
26
- });
27
-
28
- const result = await client.recordOpen();
29
-
30
- expect(result.valid).toBe(true);
31
- expect(result.failures).toEqual([]);
32
- expect(result.license?.claims.licenseId).toBe("license_vector_v1");
33
- });
34
-
35
- test("未知 publicKeyId 时拒绝运行", async () => {
36
- const client = new WindyLicenseClient({
37
- licenseSource: new MemoryAtomicLicenseStore(vectorLicense),
38
- stateStorage: new MemoryLicenseStorage(),
39
- productCode: "windy-platform",
40
- machineCode: "machine-vector-001",
41
- publicKeys: {},
42
- now: () => new Date("2026-07-10T10:00:00.000Z"),
43
- });
44
-
45
- const result = await client.recordOpen();
46
-
47
- expect(result.valid).toBe(false);
48
- expect(result.failures).toEqual(["unknown-public-key"]);
49
- });
50
-
51
- test("明显回拨持续暂停,小幅 NTP 偏差不误判且时间恢复后自动恢复", async () => {
52
- let now = new Date("2026-07-10T10:00:00.000Z");
53
- const state = new MemoryLicenseStorage();
54
- const client = new WindyLicenseClient({
55
- licenseSource: new MemoryAtomicLicenseStore(vectorLicense),
56
- stateStorage: state,
57
- productCode: "windy-platform",
58
- machineCode: "machine-vector-001",
59
- publicKeys: {
60
- [LICENSE_V1_TEST_VECTOR.keyId]: LICENSE_V1_TEST_VECTOR.publicKeyPem,
61
- },
62
- clockToleranceMs: 5 * 60 * 1000,
63
- now: () => now,
64
- });
65
-
66
- expect((await client.recordOpen()).valid).toBe(true);
67
- now = new Date("2026-07-10T09:54:00.000Z");
68
- expect((await client.recordOpen()).failures).toContain("clock-rollback");
69
- expect(await state.read("last-trusted-at")).toBe(
70
- "2026-07-10T10:00:00.000Z",
71
- );
72
- expect((await client.recordOpen()).failures).toContain("clock-rollback");
73
-
74
- now = new Date("2026-07-10T09:58:00.000Z");
75
- const recovered = await client.recordOpen();
76
- expect(recovered.valid).toBe(true);
77
- expect(recovered.failures).not.toContain("clock-rollback");
78
- expect(await state.read("last-trusted-at")).toBe(
79
- "2026-07-10T10:00:00.000Z",
80
- );
81
- });
82
- });
@@ -1,86 +0,0 @@
1
- import type {
2
- LicenseFailureReason,
3
- LicenseUsageRecord,
4
- SignedLicense,
5
- } from "@windy/shared";
6
- import type { LicenseSource, LicenseStorage } from "./storage.js";
7
- import type { LicensePublicKeySource } from "./verification.js";
8
- import { parseSignedLicense, validateLicenseDocument } from "./validation.js";
9
-
10
- export interface LicenseClientOptions {
11
- licenseSource: LicenseSource;
12
- stateStorage: LicenseStorage;
13
- productCode: string;
14
- machineCode: string;
15
- publicKeys: LicensePublicKeySource;
16
- now?: () => Date;
17
- clockToleranceMs?: number;
18
- }
19
-
20
- export interface LicenseOpenResult {
21
- valid: boolean;
22
- license?: SignedLicense;
23
- usage: LicenseUsageRecord;
24
- failures: LicenseFailureReason[];
25
- }
26
-
27
- const LAST_TRUSTED_AT_KEY = "last-trusted-at";
28
-
29
- export class WindyLicenseClient {
30
- private readonly now: () => Date;
31
-
32
- constructor(private readonly options: LicenseClientOptions) {
33
- this.now = options.now ?? (() => new Date());
34
- }
35
-
36
- async readLicense(): Promise<SignedLicense | undefined> {
37
- const rawLicense = await this.options.licenseSource.readCurrent();
38
- return rawLicense ? parseSignedLicense(rawLicense) : undefined;
39
- }
40
-
41
- async recordOpen(): Promise<LicenseOpenResult> {
42
- const openedAt = this.now();
43
- const rawLicense = await this.options.licenseSource.readCurrent();
44
- const previousOpenedAt =
45
- await this.options.stateStorage.read(LAST_TRUSTED_AT_KEY);
46
-
47
- if (!rawLicense) {
48
- return {
49
- valid: false,
50
- failures: ["invalid-format"],
51
- usage: {
52
- machineCode: this.options.machineCode,
53
- openedAt: openedAt.toISOString(),
54
- previousOpenedAt,
55
- status: "invalid",
56
- reason: "invalid-format",
57
- },
58
- };
59
- }
60
-
61
- const result = await validateLicenseDocument(rawLicense, {
62
- productCode: this.options.productCode,
63
- machineCode: this.options.machineCode,
64
- publicKeys: this.options.publicKeys,
65
- now: openedAt,
66
- lastTrustedAt: previousOpenedAt,
67
- clockToleranceMs: this.options.clockToleranceMs,
68
- });
69
- if (
70
- !result.failures.includes("clock-rollback") &&
71
- result.nextTrustedAt &&
72
- result.nextTrustedAt !== previousOpenedAt
73
- ) {
74
- await this.options.stateStorage.write(
75
- LAST_TRUSTED_AT_KEY,
76
- result.nextTrustedAt,
77
- );
78
- }
79
- return {
80
- valid: result.valid,
81
- license: result.license,
82
- failures: result.failures,
83
- usage: result.usage,
84
- };
85
- }
86
- }
@@ -1,46 +0,0 @@
1
- export interface DeviceCodeParts {
2
- hostname?: string;
3
- platform?: string;
4
- arch?: string;
5
- tenant?: string;
6
- }
7
-
8
- export function createDeviceCode(parts: DeviceCodeParts): string {
9
- const stableParts = [
10
- parts.hostname || "unknown-host",
11
- parts.platform || "unknown-platform",
12
- parts.arch || "unknown-arch",
13
- parts.tenant || "default",
14
- ];
15
-
16
- return btoaSafe(stableParts.join("|"));
17
- }
18
-
19
- export function createDeviceQrPayload(machineCode: string): string {
20
- return JSON.stringify({
21
- type: "windy-device-code",
22
- version: 1,
23
- machineCode,
24
- });
25
- }
26
-
27
- export function readDeviceCodeFromQrPayload(
28
- payload: string,
29
- ): string | undefined {
30
- try {
31
- const parsed = JSON.parse(payload) as { machineCode?: unknown };
32
- return typeof parsed.machineCode === "string"
33
- ? parsed.machineCode
34
- : undefined;
35
- } catch {
36
- return payload.trim() || undefined;
37
- }
38
- }
39
-
40
- function btoaSafe(value: string): string {
41
- if (typeof btoa === "function") {
42
- return btoa(value);
43
- }
44
-
45
- return Buffer.from(value, "utf8").toString("base64");
46
- }
@@ -1,80 +0,0 @@
1
- import { afterEach, describe, expect, test } from "bun:test";
2
- import { mkdtemp, readdir, rm, writeFile } from "node:fs/promises";
3
- import { join } from "node:path";
4
- import { tmpdir } from "node:os";
5
- import { WindyLicenseClient } from "./client.js";
6
- import {
7
- FileSystemAtomicLicenseStore,
8
- FixedPathLicenseSource,
9
- } from "./file-storage.js";
10
- import { MemoryLicenseStorage } from "./storage.js";
11
- import { LICENSE_V1_TEST_VECTOR } from "./v1-test-vector.js";
12
-
13
- const temporaryDirectories: string[] = [];
14
-
15
- afterEach(async () => {
16
- await Promise.all(
17
- temporaryDirectories
18
- .splice(0)
19
- .map((directory) => rm(directory, { force: true, recursive: true })),
20
- );
21
- });
22
-
23
- describe("filesystem License adapters", () => {
24
- test("固定路径挂载复用统一 V1 校验器", async () => {
25
- const directory = await temporaryDirectory();
26
- const path = join(directory, "runtime", "current.license.json");
27
- const store = new FileSystemAtomicLicenseStore(path);
28
- await store.replaceCurrentAtomically(
29
- JSON.stringify({
30
- formatVersion: 1,
31
- algorithm: "ED25519",
32
- publicKeyId: LICENSE_V1_TEST_VECTOR.keyId,
33
- claims: LICENSE_V1_TEST_VECTOR.claims,
34
- signature: LICENSE_V1_TEST_VECTOR.signature,
35
- }),
36
- );
37
-
38
- const client = new WindyLicenseClient({
39
- licenseSource: new FixedPathLicenseSource(path),
40
- stateStorage: new MemoryLicenseStorage(),
41
- productCode: "windy-platform",
42
- machineCode: "machine-vector-001",
43
- publicKeys: {
44
- [LICENSE_V1_TEST_VECTOR.keyId]: LICENSE_V1_TEST_VECTOR.publicKeyPem,
45
- },
46
- now: () => new Date("2026-07-10T10:00:00.000Z"),
47
- });
48
-
49
- await expect(client.recordOpen()).resolves.toMatchObject({
50
- valid: true,
51
- failures: [],
52
- });
53
- });
54
-
55
- test("模拟原子提交前崩溃时旧文件保持完整且临时文件被清理", async () => {
56
- const directory = await temporaryDirectory();
57
- const path = join(directory, "current.license.json");
58
- await writeFile(path, '{"license":"old"}', "utf8");
59
- const store = new CrashBeforeCommitStore(path);
60
-
61
- await expect(
62
- store.replaceCurrentAtomically('{"license":"new"}'),
63
- ).rejects.toThrow("模拟进程崩溃");
64
-
65
- await expect(store.readCurrent()).resolves.toBe('{"license":"old"}');
66
- expect(await readdir(directory)).toEqual(["current.license.json"]);
67
- });
68
- });
69
-
70
- class CrashBeforeCommitStore extends FileSystemAtomicLicenseStore {
71
- protected override async beforeCommit(): Promise<void> {
72
- throw new Error("模拟进程崩溃");
73
- }
74
- }
75
-
76
- async function temporaryDirectory(): Promise<string> {
77
- const directory = await mkdtemp(join(tmpdir(), "windy-license-sdk-"));
78
- temporaryDirectories.push(directory);
79
- return directory;
80
- }
@@ -1,77 +0,0 @@
1
- import { randomUUID } from "node:crypto";
2
- import { basename, dirname, join } from "node:path";
3
- import { mkdir, open, readFile, rename, unlink } from "node:fs/promises";
4
- import type { AtomicLicenseStore, LicenseSource } from "./storage.js";
5
-
6
- export class FixedPathLicenseSource implements LicenseSource {
7
- constructor(protected readonly licensePath: string) {}
8
-
9
- async readCurrent(): Promise<string | undefined> {
10
- try {
11
- return await readFile(this.licensePath, "utf8");
12
- } catch (error) {
13
- if (isMissingFile(error)) return undefined;
14
- throw error;
15
- }
16
- }
17
- }
18
-
19
- /**
20
- * Atomic filesystem adapter. Temporary data is synced before the same-directory
21
- * rename; the directory is synced afterwards so a crash cannot expose a partial file.
22
- */
23
- export class FileSystemAtomicLicenseStore
24
- extends FixedPathLicenseSource
25
- implements AtomicLicenseStore
26
- {
27
- constructor(
28
- licensePath: string,
29
- private readonly fileMode = 0o600,
30
- ) {
31
- super(licensePath);
32
- }
33
-
34
- async replaceCurrentAtomically(value: string): Promise<void> {
35
- const directory = dirname(this.licensePath);
36
- const temporaryPath = join(
37
- directory,
38
- `.${basename(this.licensePath)}.${process.pid}.${randomUUID()}.tmp`,
39
- );
40
- await mkdir(directory, { recursive: true });
41
-
42
- let temporaryFile: Awaited<ReturnType<typeof open>> | undefined;
43
- try {
44
- temporaryFile = await open(temporaryPath, "wx", this.fileMode);
45
- await temporaryFile.writeFile(value, "utf8");
46
- await temporaryFile.sync();
47
- await temporaryFile.close();
48
- temporaryFile = undefined;
49
- await this.beforeCommit();
50
- await rename(temporaryPath, this.licensePath);
51
- await syncDirectory(directory);
52
- } finally {
53
- await temporaryFile?.close().catch(() => undefined);
54
- await unlink(temporaryPath).catch(() => undefined);
55
- }
56
- }
57
-
58
- /** Test seam for simulating a process failure before the atomic commit. */
59
- protected async beforeCommit(): Promise<void> {}
60
- }
61
-
62
- async function syncDirectory(directory: string): Promise<void> {
63
- const handle = await open(directory, "r");
64
- try {
65
- await handle.sync();
66
- } finally {
67
- await handle.close();
68
- }
69
- }
70
-
71
- function isMissingFile(error: unknown): boolean {
72
- return (
73
- error instanceof Error &&
74
- "code" in error &&
75
- (error as NodeJS.ErrnoException).code === "ENOENT"
76
- );
77
- }