@synopackageland/cli 0.4.1 → 0.5.3

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 (699) hide show
  1. package/README.md +7 -3
  2. package/dist/authorization-sdk.d.ts +5 -0
  3. package/dist/authorization-sdk.js +5 -0
  4. package/dist/build-spk/delete-app-data.d.ts +27 -7
  5. package/dist/build-spk/delete-app-data.js +35 -34
  6. package/dist/build-spk/dsm-arch.d.ts +6 -1
  7. package/dist/build-spk/dsm-arch.js +25 -1
  8. package/dist/build-spk/dsm-version.d.ts +14 -0
  9. package/dist/build-spk/dsm-version.js +47 -0
  10. package/dist/build-spk/gateway.d.ts +31 -0
  11. package/dist/build-spk/gateway.js +55 -0
  12. package/dist/build-spk/generator.d.ts +5 -0
  13. package/dist/build-spk/generator.js +103 -107
  14. package/dist/build-spk/install-wizard.d.ts +20 -0
  15. package/dist/build-spk/install-wizard.js +76 -0
  16. package/dist/build-spk/native-lifecycle.d.ts +5 -0
  17. package/dist/build-spk/native-lifecycle.js +12 -2
  18. package/dist/build-spk/resource-worker.d.ts +9 -4
  19. package/dist/build-spk/resource-worker.js +15 -6
  20. package/dist/build-spk/share-combobox.d.ts +3 -0
  21. package/dist/build-spk/share-combobox.js +27 -0
  22. package/dist/build-spk/uninstall-wizard.d.ts +14 -0
  23. package/dist/build-spk/uninstall-wizard.js +33 -0
  24. package/dist/build-spk/wizard-i18n.d.ts +18 -0
  25. package/dist/build-spk/wizard-i18n.js +38 -0
  26. package/dist/build-spk/wizard-messages.d.ts +388 -0
  27. package/dist/build-spk/wizard-messages.js +387 -0
  28. package/dist/cli.js +132 -32
  29. package/dist/compose/analyze.d.ts +20 -0
  30. package/dist/compose/analyze.js +75 -11
  31. package/dist/contract/validate.js +33 -1
  32. package/dist/contract/web-launch.d.ts +22 -0
  33. package/dist/contract/web-launch.js +37 -0
  34. package/dist/deploy/deploy.d.ts +3 -0
  35. package/dist/deploy/deploy.js +11 -2
  36. package/dist/error-registry.js +62 -3
  37. package/dist/host/dsm-port-profile.d.ts +1 -1
  38. package/dist/host/dsm-port-profile.js +1 -1
  39. package/dist/host/open-url.d.ts +2 -0
  40. package/dist/host/open-url.js +4 -1
  41. package/dist/images/pin.d.ts +52 -0
  42. package/dist/images/pin.js +249 -0
  43. package/dist/init.d.ts +27 -3
  44. package/dist/init.js +126 -16
  45. package/dist/inspect.d.ts +3 -0
  46. package/dist/inspect.js +15 -3
  47. package/dist/standalone/authorization-window.d.ts +2 -0
  48. package/dist/standalone/authorization-window.js +28 -0
  49. package/dist/standalone/authorization.d.ts +48 -0
  50. package/dist/standalone/authorization.js +116 -0
  51. package/dist/standalone/background.d.ts +21 -0
  52. package/dist/standalone/background.js +52 -0
  53. package/dist/standalone/binary.d.ts +1 -0
  54. package/dist/standalone/binary.js +1 -1
  55. package/dist/standalone/build.d.ts +2 -0
  56. package/dist/standalone/build.js +54 -10
  57. package/dist/standalone/dsm-window.js +10 -3
  58. package/dist/standalone/helper-inventory.d.ts +15 -0
  59. package/dist/standalone/helper-inventory.js +9 -0
  60. package/dist/standalone/helper.d.ts +1 -0
  61. package/dist/standalone/helper.js +29 -11
  62. package/dist/standalone/host-adapter.d.ts +1 -1
  63. package/dist/standalone/host-adapter.js +33 -15
  64. package/dist/standalone/host-file-navigation.d.ts +7 -0
  65. package/dist/standalone/host-file-navigation.js +172 -0
  66. package/dist/standalone/inspect-helper.js +21 -6
  67. package/dist/standalone/inspect-spk.d.ts +1 -1
  68. package/dist/standalone/inspect-spk.js +211 -7
  69. package/dist/standalone/job-diagnostics.d.ts +1 -0
  70. package/dist/standalone/job-diagnostics.js +49 -0
  71. package/dist/standalone/lifecycle-helper.d.ts +1 -1
  72. package/dist/standalone/lifecycle-helper.js +2 -2
  73. package/dist/standalone/lifecycle.d.ts +1 -1
  74. package/dist/standalone/lifecycle.js +14 -4
  75. package/dist/standalone/manifest.d.ts +15 -2
  76. package/dist/standalone/manifest.js +37 -6
  77. package/dist/standalone/native-layout.d.ts +74 -0
  78. package/dist/standalone/native-layout.js +318 -0
  79. package/dist/standalone/resource.d.ts +11 -0
  80. package/dist/standalone/resource.js +13 -0
  81. package/dist/standalone/root-ops.d.ts +2 -0
  82. package/dist/standalone/root-ops.js +10 -0
  83. package/dist/standalone/root-window.d.ts +3 -1
  84. package/dist/standalone/root-window.js +156 -38
  85. package/dist/standalone/shared-folder.d.ts +39 -0
  86. package/dist/standalone/shared-folder.js +141 -0
  87. package/dist/standalone/spk.d.ts +4 -0
  88. package/dist/standalone/spk.js +47 -3
  89. package/dist/standalone/worker-contract-json.d.ts +8 -0
  90. package/dist/standalone/worker-contract-json.js +141 -0
  91. package/dist/standalone/worker-contract.d.ts +189 -0
  92. package/dist/standalone/worker-contract.js +175 -0
  93. package/dist/standalone/worker-registry.d.ts +40 -0
  94. package/dist/standalone/worker-registry.js +167 -0
  95. package/dist/templates/_authorization/main.go +104 -0
  96. package/dist/templates/_authorization/main_test.go +35 -0
  97. package/dist/templates/_daemon/go.mod +2 -0
  98. package/dist/templates/_gateway/auth.go +101 -0
  99. package/dist/templates/_gateway/auth_test.go +216 -0
  100. package/dist/templates/_gateway/cgi.go +133 -0
  101. package/dist/templates/_gateway/cgi_test.go +156 -0
  102. package/dist/templates/_gateway/csrf.go +73 -0
  103. package/dist/templates/_gateway/csrf_test.go +155 -0
  104. package/dist/templates/_gateway/directory.go +108 -0
  105. package/dist/templates/_gateway/directory_test.go +202 -0
  106. package/dist/templates/_gateway/gateway.go +412 -0
  107. package/dist/templates/_gateway/gateway_test.go +676 -0
  108. package/dist/templates/_gateway/go.mod +3 -0
  109. package/dist/templates/_gateway/groups.go +66 -0
  110. package/dist/templates/_gateway/main.go +45 -0
  111. package/dist/templates/binary/synology-app.yaml +1 -1
  112. package/dist/templates/compose-import/compose.yaml +1 -1
  113. package/dist/templates/compose-import/synology-app.yaml +1 -1
  114. package/dist/templates/hello-files/compose.yaml +1 -1
  115. package/dist/templates/hello-files/synology-app.yaml +1 -1
  116. package/dist/templates/native-go/README.md +118 -5
  117. package/dist/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +3 -1
  118. package/dist/templates/native-go/backend/cmd/app/main.go +25 -6
  119. package/dist/templates/native-go/backend/cmd/app/sdk_main.go +62 -0
  120. package/dist/templates/native-go/backend/cmd/background-worker/main.go +38 -0
  121. package/dist/templates/native-go/backend/cmd/helper/main.go +27 -1
  122. package/dist/templates/native-go/backend/cmd/helper/sdk_registry.go +19 -0
  123. package/dist/templates/native-go/backend/go.mod +5 -3
  124. package/dist/templates/native-go/backend/go.sum +4 -4
  125. package/dist/templates/native-go/backend/internal/api/registry.go +17 -6
  126. package/dist/templates/native-go/backend/internal/api/server.go +7 -1
  127. package/dist/templates/native-go/backend/internal/app/authorization_none.go +5 -0
  128. package/dist/templates/native-go/backend/internal/app/background.go +270 -0
  129. package/dist/templates/native-go/backend/internal/app/background_none.go +8 -0
  130. package/dist/templates/native-go/backend/internal/app/background_owner.go +59 -0
  131. package/dist/templates/native-go/backend/internal/app/background_owner_test.go +145 -0
  132. package/dist/templates/native-go/backend/internal/app/background_schedule.go +74 -0
  133. package/dist/templates/native-go/backend/internal/app/background_schedule_test.go +62 -0
  134. package/dist/templates/native-go/backend/internal/app/background_test.go +346 -0
  135. package/dist/templates/native-go/backend/internal/app/integration_state.go +16 -0
  136. package/dist/templates/native-go/backend/internal/app/migrations.go +41 -0
  137. package/dist/templates/native-go/backend/internal/app/migrations_test.go +41 -0
  138. package/dist/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +8 -0
  139. package/dist/templates/native-go/backend/internal/app/routes.go +22 -5
  140. package/dist/templates/native-go/backend/internal/app/routes_test.go +20 -3
  141. package/dist/templates/native-go/backend/internal/app/sdk_jobs.go +70 -0
  142. package/dist/templates/native-go/backend/internal/app/sdk_jobs_test.go +116 -0
  143. package/dist/templates/native-go/backend/internal/app/sdk_routes.go +177 -0
  144. package/dist/templates/native-go/backend/internal/app/session_files.go +15 -0
  145. package/dist/templates/native-go/backend/internal/app/session_files_test.go +26 -0
  146. package/dist/templates/native-go/backend/internal/app/shared_folder.go +144 -0
  147. package/dist/templates/native-go/backend/internal/app/shared_folder_test.go +158 -0
  148. package/dist/templates/native-go/backend/internal/background/access.go +57 -0
  149. package/dist/templates/native-go/backend/internal/background/owner_test.go +126 -0
  150. package/dist/templates/native-go/backend/internal/background/runner.go +185 -0
  151. package/dist/templates/native-go/backend/internal/background/runner_test.go +209 -0
  152. package/dist/templates/native-go/backend/internal/background/schedule.go +300 -0
  153. package/dist/templates/native-go/backend/internal/background/schedule_test.go +335 -0
  154. package/dist/templates/native-go/backend/internal/background/store.go +807 -0
  155. package/dist/templates/native-go/backend/internal/background/store_test.go +407 -0
  156. package/dist/templates/native-go/backend/internal/datamigrate/migrate.go +191 -0
  157. package/dist/templates/native-go/backend/internal/datamigrate/migrate_test.go +177 -0
  158. package/dist/templates/native-go/backend/internal/filestation/browse_test.go +67 -0
  159. package/dist/templates/native-go/backend/internal/filestation/client.go +251 -0
  160. package/dist/templates/native-go/backend/internal/filestation/client_test.go +155 -0
  161. package/dist/templates/native-go/backend/internal/filestation/doc.go +4 -0
  162. package/dist/templates/native-go/backend/internal/filestation/read_file_test.go +90 -0
  163. package/dist/templates/native-go/backend/internal/filestation/repository.go +207 -0
  164. package/dist/templates/native-go/backend/internal/filestation/repository_test.go +104 -0
  165. package/dist/templates/native-go/backend/internal/filestation/sdk_session.go +241 -0
  166. package/dist/templates/native-go/backend/internal/filestation/sdk_session_test.go +183 -0
  167. package/dist/templates/native-go/backend/internal/filestation/service.go +254 -0
  168. package/dist/templates/native-go/backend/internal/filestation/service_test.go +94 -0
  169. package/dist/templates/native-go/backend/internal/filestation/session_semantics_test.go +383 -0
  170. package/dist/templates/native-go/backend/internal/filestation/write.go +72 -0
  171. package/dist/templates/native-go/backend/internal/filestation/write_test.go +123 -0
  172. package/dist/templates/native-go/backend/internal/helper/background_proof.go +163 -0
  173. package/dist/templates/native-go/backend/internal/helper/background_proof_contract.go +46 -0
  174. package/dist/templates/native-go/backend/internal/helper/background_proof_test.go +161 -0
  175. package/dist/templates/native-go/backend/internal/helper/data_contract.go +3 -0
  176. package/dist/templates/native-go/backend/internal/helper/data_protocol.go +3 -0
  177. package/dist/templates/native-go/backend/internal/helper/data_protocol_test.go +1 -1
  178. package/dist/templates/native-go/backend/internal/helper/grant_authority.go +3 -0
  179. package/dist/templates/native-go/backend/internal/helper/grant_authority_test.go +1 -1
  180. package/dist/templates/native-go/backend/internal/helper/grant_repository_linux.go +2 -1
  181. package/dist/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +4 -3
  182. package/dist/templates/native-go/backend/internal/helper/grant_snapshot.go +3 -0
  183. package/dist/templates/native-go/backend/internal/helper/jobcontract/bindings.go +48 -0
  184. package/dist/templates/native-go/backend/internal/helper/jobcontract/contract_test.go +436 -0
  185. package/dist/templates/native-go/backend/internal/helper/jobcontract/decode.go +185 -0
  186. package/dist/templates/native-go/backend/internal/helper/jobcontract/digest.go +55 -0
  187. package/dist/templates/native-go/backend/internal/helper/jobcontract/registry.go +85 -0
  188. package/dist/templates/native-go/backend/internal/helper/jobcontract/registry_test.go +73 -0
  189. package/dist/templates/native-go/backend/internal/helper/jobcontract/result.go +53 -0
  190. package/dist/templates/native-go/backend/internal/helper/jobcontract/stub.go +8 -0
  191. package/dist/templates/native-go/backend/internal/helper/jobcontract/testdata/input-digests.json +127 -0
  192. package/dist/templates/native-go/backend/internal/helper/jobcontract/types.go +234 -0
  193. package/dist/templates/native-go/backend/internal/helper/jobcontract/types_test.go +29 -0
  194. package/dist/templates/native-go/backend/internal/helper/jobcontract/validate.go +462 -0
  195. package/dist/templates/native-go/backend/internal/helper/legacy_authority_schema_linux_test.go +34 -0
  196. package/dist/templates/native-go/backend/internal/helper/legacy_authority_schema_test.go +6 -0
  197. package/dist/templates/native-go/backend/internal/helper/management.go +86 -0
  198. package/dist/templates/native-go/backend/internal/helper/observation.go +42 -2
  199. package/dist/templates/native-go/backend/internal/helper/observation_health_test.go +13 -1
  200. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic.go +56 -10
  201. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +6 -0
  202. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_writer.go +40 -0
  203. package/dist/templates/native-go/backend/internal/helper/process_linux.go +3 -0
  204. package/dist/templates/native-go/backend/internal/helper/purge.go +115 -0
  205. package/dist/templates/native-go/backend/internal/helper/purge_test.go +59 -0
  206. package/dist/templates/native-go/backend/internal/helper/query_deadline_linux_test.go +115 -0
  207. package/dist/templates/native-go/backend/internal/helper/query_pending_diagnostic_test.go +254 -0
  208. package/dist/templates/native-go/backend/internal/helper/relaxed_invalidation.go +3 -0
  209. package/dist/templates/native-go/backend/internal/helper/revoke.go +109 -0
  210. package/dist/templates/native-go/backend/internal/helper/revoke_test.go +121 -0
  211. package/dist/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +23 -4
  212. package/dist/templates/native-go/backend/internal/helper/sdk_assembly_linux.go +51 -0
  213. package/dist/templates/native-go/backend/internal/helper/sdk_attach.go +83 -0
  214. package/dist/templates/native-go/backend/internal/helper/sdk_attach_contract.go +32 -0
  215. package/dist/templates/native-go/backend/internal/helper/sdk_attach_test.go +184 -0
  216. package/dist/templates/native-go/backend/internal/helper/sdk_authority_schema_test.go +6 -0
  217. package/dist/templates/native-go/backend/internal/helper/sdk_background_authority.go +832 -0
  218. package/dist/templates/native-go/backend/internal/helper/sdk_background_authority_test.go +714 -0
  219. package/dist/templates/native-go/backend/internal/helper/sdk_background_invalidation.go +218 -0
  220. package/dist/templates/native-go/backend/internal/helper/sdk_background_lease.go +218 -0
  221. package/dist/templates/native-go/backend/internal/helper/sdk_background_snapshot.go +110 -0
  222. package/dist/templates/native-go/backend/internal/helper/sdk_background_store_linux_test.go +261 -0
  223. package/dist/templates/native-go/backend/internal/helper/sdk_background_store_test.go +58 -0
  224. package/dist/templates/native-go/backend/internal/helper/sdk_bindings.go +60 -0
  225. package/dist/templates/native-go/backend/internal/helper/sdk_data_contract.go +251 -0
  226. package/dist/templates/native-go/backend/internal/helper/sdk_data_protocol.go +424 -0
  227. package/dist/templates/native-go/backend/internal/helper/sdk_dispatch_absence_test.go +51 -0
  228. package/dist/templates/native-go/backend/internal/helper/sdk_display.go +488 -0
  229. package/dist/templates/native-go/backend/internal/helper/sdk_display_contract.go +121 -0
  230. package/dist/templates/native-go/backend/internal/helper/sdk_display_test.go +459 -0
  231. package/dist/templates/native-go/backend/internal/helper/sdk_grant_authority.go +559 -0
  232. package/dist/templates/native-go/backend/internal/helper/sdk_grant_repository_linux.go +417 -0
  233. package/dist/templates/native-go/backend/internal/helper/sdk_grant_snapshot.go +94 -0
  234. package/dist/templates/native-go/backend/internal/helper/sdk_history.go +80 -0
  235. package/dist/templates/native-go/backend/internal/helper/sdk_history_test.go +76 -0
  236. package/dist/templates/native-go/backend/internal/helper/sdk_job.go +697 -0
  237. package/dist/templates/native-go/backend/internal/helper/sdk_job_child_linux.go +309 -0
  238. package/dist/templates/native-go/backend/internal/helper/sdk_job_contract.go +122 -0
  239. package/dist/templates/native-go/backend/internal/helper/sdk_job_linux_test.go +159 -0
  240. package/dist/templates/native-go/backend/internal/helper/sdk_job_process_linux.go +327 -0
  241. package/dist/templates/native-go/backend/internal/helper/sdk_job_test.go +501 -0
  242. package/dist/templates/native-go/backend/internal/helper/sdk_job_vm_linux_test.go +343 -0
  243. package/dist/templates/native-go/backend/internal/helper/sdk_journal.go +77 -0
  244. package/dist/templates/native-go/backend/internal/helper/sdk_journal_linux.go +244 -0
  245. package/dist/templates/native-go/backend/internal/helper/sdk_journal_linux_test.go +295 -0
  246. package/dist/templates/native-go/backend/internal/helper/sdk_journal_test.go +71 -0
  247. package/dist/templates/native-go/backend/internal/helper/sdk_picker_test.go +50 -0
  248. package/dist/templates/native-go/backend/internal/helper/sdk_process_linux.go +184 -0
  249. package/dist/templates/native-go/backend/internal/helper/sdk_public_vm_linux_test.go +129 -0
  250. package/dist/templates/native-go/backend/internal/helper/sdk_relaxed_invalidation.go +242 -0
  251. package/dist/templates/native-go/backend/internal/helper/sdk_rpc.go +299 -0
  252. package/dist/templates/native-go/backend/internal/helper/sdk_rpc_contract.go +70 -0
  253. package/dist/templates/native-go/backend/internal/helper/sdk_rpc_test.go +135 -0
  254. package/dist/templates/native-go/backend/internal/helper/sdk_server_linux.go +161 -0
  255. package/dist/templates/native-go/backend/internal/helper/sdk_session.go +677 -0
  256. package/dist/templates/native-go/backend/internal/helper/sdk_session_contract.go +72 -0
  257. package/dist/templates/native-go/backend/internal/helper/sdk_session_fence_test.go +215 -0
  258. package/dist/templates/native-go/backend/internal/helper/sdk_session_test.go +475 -0
  259. package/dist/templates/native-go/backend/internal/helper/sdk_supervisor_frame.go +78 -0
  260. package/dist/templates/native-go/backend/internal/helper/sdk_supervisor_linux.go +414 -0
  261. package/dist/templates/native-go/backend/internal/helper/sdk_transport.go +79 -0
  262. package/dist/templates/native-go/backend/internal/helper/sdk_transport_linux.go +82 -0
  263. package/dist/templates/native-go/backend/internal/helper/sdk_transport_test.go +64 -0
  264. package/dist/templates/native-go/backend/internal/helper/server_linux.go +14 -2
  265. package/dist/templates/native-go/backend/internal/helper/stale_management_linux_test.go +126 -0
  266. package/dist/templates/native-go/backend/internal/helper/stale_management_test.go +122 -0
  267. package/dist/templates/native-go/backend/internal/helper/startup_diagnostic.go +68 -0
  268. package/dist/templates/native-go/backend/internal/helper/startup_diagnostic_linux_test.go +126 -0
  269. package/dist/templates/native-go/backend/internal/helper/startup_diagnostic_test.go +117 -0
  270. package/dist/templates/native-go/backend/internal/helper/status.go +22 -13
  271. package/dist/templates/native-go/backend/internal/helper/status_test.go +45 -0
  272. package/dist/templates/native-go/backend/internal/helper/supervision.go +1 -1
  273. package/dist/templates/native-go/backend/internal/helper/supervisor_frame.go +3 -0
  274. package/dist/templates/native-go/backend/internal/helper/supervisor_linux.go +6 -2
  275. package/dist/templates/native-go/backend/internal/helper/unit_connection_test.go +22 -4
  276. package/dist/templates/native-go/backend/internal/helper/unit_linux.go +7 -3
  277. package/dist/templates/native-go/backend/internal/helper/unit_query_linux.go +5 -1
  278. package/dist/templates/native-go/backend/internal/helper/write_files_linux.go +7 -4
  279. package/dist/templates/native-go/backend/internal/helper/write_files_linux_test.go +26 -0
  280. package/dist/templates/native-go/dsm-package.yaml +2 -2
  281. package/dist/templates/native-go-authorization/backend/internal/app/authorization.go +298 -0
  282. package/dist/templates/native-go-authorization/backend/internal/app/authorization_test.go +96 -0
  283. package/dist/templates/native-go-authorization/frontend/src/authorization/AuthorizationGate.vue +89 -0
  284. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/de.json +36 -0
  285. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/en.json +36 -0
  286. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/es.json +36 -0
  287. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/fr.json +36 -0
  288. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/index.ts +15 -0
  289. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/it.json +36 -0
  290. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/ja.json +36 -0
  291. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/ko.json +36 -0
  292. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/zh-CN.json +36 -0
  293. package/dist/templates/native-go-authorization/frontend/src/authorization/i18n/zh-TW.json +36 -0
  294. package/dist/templates/native-go-authorization/frontend/test/authorization-preview.html +14 -0
  295. package/dist/templates/native-go-authorization/frontend/test/authorization.test.ts +59 -0
  296. package/dist/templates/native-go-background/BACKGROUND.md +111 -0
  297. package/dist/templates/native-go-background/backend/internal/app/background_on.go +7 -0
  298. package/dist/templates/native-go-background/backend/internal/app/background_routes_test.go +32 -0
  299. package/dist/templates/native-go-background/frontend/src/background/BackgroundPanel.vue +178 -0
  300. package/dist/templates/native-go-background/frontend/src/background/i18n/de.json +83 -0
  301. package/dist/templates/native-go-background/frontend/src/background/i18n/en.json +83 -0
  302. package/dist/templates/native-go-background/frontend/src/background/i18n/es.json +83 -0
  303. package/dist/templates/native-go-background/frontend/src/background/i18n/fr.json +83 -0
  304. package/dist/templates/native-go-background/frontend/src/background/i18n/it.json +83 -0
  305. package/dist/templates/native-go-background/frontend/src/background/i18n/ja.json +83 -0
  306. package/dist/templates/native-go-background/frontend/src/background/i18n/ko.json +83 -0
  307. package/dist/templates/native-go-background/frontend/src/background/i18n/zh-CN.json +83 -0
  308. package/dist/templates/native-go-background/frontend/src/background/i18n/zh-TW.json +83 -0
  309. package/dist/templates/native-go-background/frontend/src/background/i18n.ts +19 -0
  310. package/dist/templates/native-go-background/frontend/src/background/picker-provider.ts +13 -0
  311. package/dist/templates/native-go-background/frontend/test/background.test.ts +179 -0
  312. package/dist/templates/native-go-integration/backend/internal/app/personal.go +2 -2
  313. package/dist/templates/native-go-integration/backend/internal/app/personal_test.go +37 -0
  314. package/dist/templates/native-go-vue/README.md +38 -7
  315. package/dist/templates/native-go-vue/frontend/DESIGN.md +15 -3
  316. package/dist/templates/native-go-vue/frontend/README-JOBS.md +75 -0
  317. package/dist/templates/native-go-vue/frontend/README-M2.md +64 -0
  318. package/dist/templates/native-go-vue/frontend/package-lock.json +5 -4
  319. package/dist/templates/native-go-vue/frontend/package.json +1 -1
  320. package/dist/templates/native-go-vue/frontend/src/App.vue +39 -11
  321. package/dist/templates/native-go-vue/frontend/src/M2App.vue +57 -0
  322. package/dist/templates/native-go-vue/frontend/src/SDKApp.vue +203 -0
  323. package/dist/templates/native-go-vue/frontend/src/context.ts +3 -0
  324. package/dist/templates/native-go-vue/frontend/src/jobs/InteractiveJobForm.vue +70 -0
  325. package/dist/templates/native-go-vue/frontend/src/jobs/JobsAdminPanel.vue +33 -0
  326. package/dist/templates/native-go-vue/frontend/src/jobs/JobsPanel.vue +135 -0
  327. package/dist/templates/native-go-vue/frontend/src/jobs/connected-provider.ts +179 -0
  328. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/de.json +62 -0
  329. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/en.json +62 -0
  330. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/es.json +62 -0
  331. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/fr.json +62 -0
  332. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/it.json +62 -0
  333. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/ja.json +62 -0
  334. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/ko.json +62 -0
  335. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/zh-CN.json +62 -0
  336. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/zh-TW.json +62 -0
  337. package/dist/templates/native-go-vue/frontend/src/jobs/i18n.ts +15 -0
  338. package/dist/templates/native-go-vue/frontend/src/jobs/mock-provider.ts +67 -0
  339. package/dist/templates/native-go-vue/frontend/src/jobs/provider.ts +60 -0
  340. package/dist/templates/native-go-vue/frontend/src/jobs/validate.ts +44 -0
  341. package/dist/templates/native-go-vue/frontend/src/m2-main.ts +21 -0
  342. package/dist/templates/native-go-vue/frontend/src/m2-style.css +7 -0
  343. package/dist/templates/native-go-vue/frontend/src/nas/M2Files.vue +94 -0
  344. package/dist/templates/native-go-vue/frontend/src/nas/M2PathPicker.vue +70 -0
  345. package/dist/templates/native-go-vue/frontend/src/nas/M2Settings.vue +69 -0
  346. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/de.json +56 -0
  347. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/en.json +56 -0
  348. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/es.json +56 -0
  349. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/fr.json +56 -0
  350. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/it.json +56 -0
  351. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/ja.json +56 -0
  352. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/ko.json +56 -0
  353. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-CN.json +56 -0
  354. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-TW.json +56 -0
  355. package/dist/templates/native-go-vue/frontend/src/nas/m2-contract.ts +33 -0
  356. package/dist/templates/native-go-vue/frontend/src/nas/m2-i18n.ts +24 -0
  357. package/dist/templates/native-go-vue/frontend/src/nas/m2-provider.ts +104 -0
  358. package/dist/templates/native-go-vue/frontend/src/nas/use-m2-request.ts +18 -0
  359. package/dist/templates/native-go-vue/frontend/src/sdk-main.ts +39 -0
  360. package/dist/templates/native-go-vue/frontend/src/shell/AppShell.vue +48 -0
  361. package/dist/templates/native-go-vue/frontend/src/shell/i18n/de.json +10 -0
  362. package/dist/templates/native-go-vue/frontend/src/shell/i18n/en.json +10 -0
  363. package/dist/templates/native-go-vue/frontend/src/shell/i18n/es.json +10 -0
  364. package/dist/templates/native-go-vue/frontend/src/shell/i18n/fr.json +10 -0
  365. package/dist/templates/native-go-vue/frontend/src/shell/i18n/it.json +10 -0
  366. package/dist/templates/native-go-vue/frontend/src/shell/i18n/ja.json +10 -0
  367. package/dist/templates/native-go-vue/frontend/src/shell/i18n/ko.json +10 -0
  368. package/dist/templates/native-go-vue/frontend/src/shell/i18n/zh-CN.json +10 -0
  369. package/dist/templates/native-go-vue/frontend/src/shell/i18n/zh-TW.json +10 -0
  370. package/dist/templates/native-go-vue/frontend/src/shell/i18n.ts +17 -0
  371. package/dist/templates/native-go-vue/frontend/src/shell/pages.ts +34 -0
  372. package/dist/templates/native-go-vue/frontend/src/style.css +2 -6
  373. package/dist/templates/native-go-vue/frontend/test/apps.test.ts +21 -0
  374. package/dist/templates/native-go-vue/frontend/test/jobs-connected.test.ts +163 -0
  375. package/dist/templates/native-go-vue/frontend/test/jobs-preview.html +22 -0
  376. package/dist/templates/native-go-vue/frontend/test/jobs.test.ts +176 -0
  377. package/dist/templates/native-go-vue/frontend/test/m2-preview.html +27 -0
  378. package/dist/templates/native-go-vue/frontend/test/m2-provider.test.ts +87 -0
  379. package/dist/templates/native-go-vue/frontend/test/m2-ui.test.ts +209 -0
  380. package/dist/templates/native-go-vue/frontend/test/native-controls.test.ts +27 -0
  381. package/dist/templates/native-go-vue/frontend/test/picker-wire.test.ts +110 -0
  382. package/dist/templates/native-go-vue/frontend/test/shell-preview.html +19 -0
  383. package/dist/templates/native-go-vue/frontend/test/shell-sdk.test.ts +73 -0
  384. package/dist/templates/native-go-vue/frontend/test/shell-ui.test.ts +114 -0
  385. package/dist/templates/native-go-vue/frontend/test/shell.test.ts +45 -0
  386. package/dist/templates/native-go-vue/frontend/vite.config.ts +2 -2
  387. package/dist/types.d.ts +1 -1
  388. package/dist/validate.js +6 -3
  389. package/package.json +5 -2
  390. package/schema/synology-app.schema.json +19 -0
  391. package/skills/reference/create.md +6 -2
  392. package/templates/_authorization/main.go +104 -0
  393. package/templates/_authorization/main_test.go +35 -0
  394. package/templates/_daemon/go.mod +2 -0
  395. package/templates/_gateway/auth.go +101 -0
  396. package/templates/_gateway/auth_test.go +216 -0
  397. package/templates/_gateway/cgi.go +133 -0
  398. package/templates/_gateway/cgi_test.go +156 -0
  399. package/templates/_gateway/csrf.go +73 -0
  400. package/templates/_gateway/csrf_test.go +155 -0
  401. package/templates/_gateway/directory.go +108 -0
  402. package/templates/_gateway/directory_test.go +202 -0
  403. package/templates/_gateway/gateway.go +412 -0
  404. package/templates/_gateway/gateway_test.go +676 -0
  405. package/templates/_gateway/go.mod +3 -0
  406. package/templates/_gateway/groups.go +66 -0
  407. package/templates/_gateway/main.go +45 -0
  408. package/templates/binary/synology-app.yaml +1 -1
  409. package/templates/compose-import/compose.yaml +1 -1
  410. package/templates/compose-import/synology-app.yaml +1 -1
  411. package/templates/hello-files/compose.yaml +1 -1
  412. package/templates/hello-files/synology-app.yaml +1 -1
  413. package/templates/native-go/README.md +118 -5
  414. package/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +3 -1
  415. package/templates/native-go/backend/cmd/app/main.go +25 -6
  416. package/templates/native-go/backend/cmd/app/sdk_main.go +62 -0
  417. package/templates/native-go/backend/cmd/background-worker/main.go +38 -0
  418. package/templates/native-go/backend/cmd/helper/main.go +27 -1
  419. package/templates/native-go/backend/cmd/helper/sdk_registry.go +19 -0
  420. package/templates/native-go/backend/go.mod +5 -3
  421. package/templates/native-go/backend/go.sum +4 -4
  422. package/templates/native-go/backend/internal/api/registry.go +17 -6
  423. package/templates/native-go/backend/internal/api/server.go +7 -1
  424. package/templates/native-go/backend/internal/app/authorization_none.go +5 -0
  425. package/templates/native-go/backend/internal/app/background.go +270 -0
  426. package/templates/native-go/backend/internal/app/background_none.go +8 -0
  427. package/templates/native-go/backend/internal/app/background_owner.go +59 -0
  428. package/templates/native-go/backend/internal/app/background_owner_test.go +145 -0
  429. package/templates/native-go/backend/internal/app/background_schedule.go +74 -0
  430. package/templates/native-go/backend/internal/app/background_schedule_test.go +62 -0
  431. package/templates/native-go/backend/internal/app/background_test.go +346 -0
  432. package/templates/native-go/backend/internal/app/integration_state.go +16 -0
  433. package/templates/native-go/backend/internal/app/migrations.go +41 -0
  434. package/templates/native-go/backend/internal/app/migrations_test.go +41 -0
  435. package/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +8 -0
  436. package/templates/native-go/backend/internal/app/routes.go +22 -5
  437. package/templates/native-go/backend/internal/app/routes_test.go +20 -3
  438. package/templates/native-go/backend/internal/app/sdk_jobs.go +70 -0
  439. package/templates/native-go/backend/internal/app/sdk_jobs_test.go +116 -0
  440. package/templates/native-go/backend/internal/app/sdk_routes.go +177 -0
  441. package/templates/native-go/backend/internal/app/session_files.go +15 -0
  442. package/templates/native-go/backend/internal/app/session_files_test.go +26 -0
  443. package/templates/native-go/backend/internal/app/shared_folder.go +144 -0
  444. package/templates/native-go/backend/internal/app/shared_folder_test.go +158 -0
  445. package/templates/native-go/backend/internal/background/access.go +57 -0
  446. package/templates/native-go/backend/internal/background/owner_test.go +126 -0
  447. package/templates/native-go/backend/internal/background/runner.go +185 -0
  448. package/templates/native-go/backend/internal/background/runner_test.go +209 -0
  449. package/templates/native-go/backend/internal/background/schedule.go +300 -0
  450. package/templates/native-go/backend/internal/background/schedule_test.go +335 -0
  451. package/templates/native-go/backend/internal/background/store.go +807 -0
  452. package/templates/native-go/backend/internal/background/store_test.go +407 -0
  453. package/templates/native-go/backend/internal/datamigrate/migrate.go +191 -0
  454. package/templates/native-go/backend/internal/datamigrate/migrate_test.go +177 -0
  455. package/templates/native-go/backend/internal/filestation/browse_test.go +67 -0
  456. package/templates/native-go/backend/internal/filestation/client.go +251 -0
  457. package/templates/native-go/backend/internal/filestation/client_test.go +155 -0
  458. package/templates/native-go/backend/internal/filestation/doc.go +4 -0
  459. package/templates/native-go/backend/internal/filestation/read_file_test.go +90 -0
  460. package/templates/native-go/backend/internal/filestation/repository.go +207 -0
  461. package/templates/native-go/backend/internal/filestation/repository_test.go +104 -0
  462. package/templates/native-go/backend/internal/filestation/sdk_session.go +241 -0
  463. package/templates/native-go/backend/internal/filestation/sdk_session_test.go +183 -0
  464. package/templates/native-go/backend/internal/filestation/service.go +254 -0
  465. package/templates/native-go/backend/internal/filestation/service_test.go +94 -0
  466. package/templates/native-go/backend/internal/filestation/session_semantics_test.go +383 -0
  467. package/templates/native-go/backend/internal/filestation/write.go +72 -0
  468. package/templates/native-go/backend/internal/filestation/write_test.go +123 -0
  469. package/templates/native-go/backend/internal/helper/background_proof.go +163 -0
  470. package/templates/native-go/backend/internal/helper/background_proof_contract.go +46 -0
  471. package/templates/native-go/backend/internal/helper/background_proof_test.go +161 -0
  472. package/templates/native-go/backend/internal/helper/data_contract.go +3 -0
  473. package/templates/native-go/backend/internal/helper/data_protocol.go +3 -0
  474. package/templates/native-go/backend/internal/helper/data_protocol_test.go +1 -1
  475. package/templates/native-go/backend/internal/helper/grant_authority.go +3 -0
  476. package/templates/native-go/backend/internal/helper/grant_authority_test.go +1 -1
  477. package/templates/native-go/backend/internal/helper/grant_repository_linux.go +2 -1
  478. package/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +4 -3
  479. package/templates/native-go/backend/internal/helper/grant_snapshot.go +3 -0
  480. package/templates/native-go/backend/internal/helper/jobcontract/bindings.go +48 -0
  481. package/templates/native-go/backend/internal/helper/jobcontract/contract_test.go +436 -0
  482. package/templates/native-go/backend/internal/helper/jobcontract/decode.go +185 -0
  483. package/templates/native-go/backend/internal/helper/jobcontract/digest.go +55 -0
  484. package/templates/native-go/backend/internal/helper/jobcontract/registry.go +85 -0
  485. package/templates/native-go/backend/internal/helper/jobcontract/registry_test.go +73 -0
  486. package/templates/native-go/backend/internal/helper/jobcontract/result.go +53 -0
  487. package/templates/native-go/backend/internal/helper/jobcontract/stub.go +8 -0
  488. package/templates/native-go/backend/internal/helper/jobcontract/testdata/input-digests.json +127 -0
  489. package/templates/native-go/backend/internal/helper/jobcontract/types.go +234 -0
  490. package/templates/native-go/backend/internal/helper/jobcontract/types_test.go +29 -0
  491. package/templates/native-go/backend/internal/helper/jobcontract/validate.go +462 -0
  492. package/templates/native-go/backend/internal/helper/legacy_authority_schema_linux_test.go +34 -0
  493. package/templates/native-go/backend/internal/helper/legacy_authority_schema_test.go +6 -0
  494. package/templates/native-go/backend/internal/helper/management.go +86 -0
  495. package/templates/native-go/backend/internal/helper/observation.go +42 -2
  496. package/templates/native-go/backend/internal/helper/observation_health_test.go +13 -1
  497. package/templates/native-go/backend/internal/helper/observer_diagnostic.go +56 -10
  498. package/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +6 -0
  499. package/templates/native-go/backend/internal/helper/observer_diagnostic_writer.go +40 -0
  500. package/templates/native-go/backend/internal/helper/process_linux.go +3 -0
  501. package/templates/native-go/backend/internal/helper/purge.go +115 -0
  502. package/templates/native-go/backend/internal/helper/purge_test.go +59 -0
  503. package/templates/native-go/backend/internal/helper/query_deadline_linux_test.go +115 -0
  504. package/templates/native-go/backend/internal/helper/query_pending_diagnostic_test.go +254 -0
  505. package/templates/native-go/backend/internal/helper/relaxed_invalidation.go +3 -0
  506. package/templates/native-go/backend/internal/helper/revoke.go +109 -0
  507. package/templates/native-go/backend/internal/helper/revoke_test.go +121 -0
  508. package/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +23 -4
  509. package/templates/native-go/backend/internal/helper/sdk_assembly_linux.go +51 -0
  510. package/templates/native-go/backend/internal/helper/sdk_attach.go +83 -0
  511. package/templates/native-go/backend/internal/helper/sdk_attach_contract.go +32 -0
  512. package/templates/native-go/backend/internal/helper/sdk_attach_test.go +184 -0
  513. package/templates/native-go/backend/internal/helper/sdk_authority_schema_test.go +6 -0
  514. package/templates/native-go/backend/internal/helper/sdk_background_authority.go +832 -0
  515. package/templates/native-go/backend/internal/helper/sdk_background_authority_test.go +714 -0
  516. package/templates/native-go/backend/internal/helper/sdk_background_invalidation.go +218 -0
  517. package/templates/native-go/backend/internal/helper/sdk_background_lease.go +218 -0
  518. package/templates/native-go/backend/internal/helper/sdk_background_snapshot.go +110 -0
  519. package/templates/native-go/backend/internal/helper/sdk_background_store_linux_test.go +261 -0
  520. package/templates/native-go/backend/internal/helper/sdk_background_store_test.go +58 -0
  521. package/templates/native-go/backend/internal/helper/sdk_bindings.go +60 -0
  522. package/templates/native-go/backend/internal/helper/sdk_data_contract.go +251 -0
  523. package/templates/native-go/backend/internal/helper/sdk_data_protocol.go +424 -0
  524. package/templates/native-go/backend/internal/helper/sdk_dispatch_absence_test.go +51 -0
  525. package/templates/native-go/backend/internal/helper/sdk_display.go +488 -0
  526. package/templates/native-go/backend/internal/helper/sdk_display_contract.go +121 -0
  527. package/templates/native-go/backend/internal/helper/sdk_display_test.go +459 -0
  528. package/templates/native-go/backend/internal/helper/sdk_grant_authority.go +559 -0
  529. package/templates/native-go/backend/internal/helper/sdk_grant_repository_linux.go +417 -0
  530. package/templates/native-go/backend/internal/helper/sdk_grant_snapshot.go +94 -0
  531. package/templates/native-go/backend/internal/helper/sdk_history.go +80 -0
  532. package/templates/native-go/backend/internal/helper/sdk_history_test.go +76 -0
  533. package/templates/native-go/backend/internal/helper/sdk_job.go +697 -0
  534. package/templates/native-go/backend/internal/helper/sdk_job_child_linux.go +309 -0
  535. package/templates/native-go/backend/internal/helper/sdk_job_contract.go +122 -0
  536. package/templates/native-go/backend/internal/helper/sdk_job_linux_test.go +159 -0
  537. package/templates/native-go/backend/internal/helper/sdk_job_process_linux.go +327 -0
  538. package/templates/native-go/backend/internal/helper/sdk_job_test.go +501 -0
  539. package/templates/native-go/backend/internal/helper/sdk_job_vm_linux_test.go +343 -0
  540. package/templates/native-go/backend/internal/helper/sdk_journal.go +77 -0
  541. package/templates/native-go/backend/internal/helper/sdk_journal_linux.go +244 -0
  542. package/templates/native-go/backend/internal/helper/sdk_journal_linux_test.go +295 -0
  543. package/templates/native-go/backend/internal/helper/sdk_journal_test.go +71 -0
  544. package/templates/native-go/backend/internal/helper/sdk_picker_test.go +50 -0
  545. package/templates/native-go/backend/internal/helper/sdk_process_linux.go +184 -0
  546. package/templates/native-go/backend/internal/helper/sdk_public_vm_linux_test.go +129 -0
  547. package/templates/native-go/backend/internal/helper/sdk_relaxed_invalidation.go +242 -0
  548. package/templates/native-go/backend/internal/helper/sdk_rpc.go +299 -0
  549. package/templates/native-go/backend/internal/helper/sdk_rpc_contract.go +70 -0
  550. package/templates/native-go/backend/internal/helper/sdk_rpc_test.go +135 -0
  551. package/templates/native-go/backend/internal/helper/sdk_server_linux.go +161 -0
  552. package/templates/native-go/backend/internal/helper/sdk_session.go +677 -0
  553. package/templates/native-go/backend/internal/helper/sdk_session_contract.go +72 -0
  554. package/templates/native-go/backend/internal/helper/sdk_session_fence_test.go +215 -0
  555. package/templates/native-go/backend/internal/helper/sdk_session_test.go +475 -0
  556. package/templates/native-go/backend/internal/helper/sdk_supervisor_frame.go +78 -0
  557. package/templates/native-go/backend/internal/helper/sdk_supervisor_linux.go +414 -0
  558. package/templates/native-go/backend/internal/helper/sdk_transport.go +79 -0
  559. package/templates/native-go/backend/internal/helper/sdk_transport_linux.go +82 -0
  560. package/templates/native-go/backend/internal/helper/sdk_transport_test.go +64 -0
  561. package/templates/native-go/backend/internal/helper/server_linux.go +14 -2
  562. package/templates/native-go/backend/internal/helper/stale_management_linux_test.go +126 -0
  563. package/templates/native-go/backend/internal/helper/stale_management_test.go +122 -0
  564. package/templates/native-go/backend/internal/helper/startup_diagnostic.go +68 -0
  565. package/templates/native-go/backend/internal/helper/startup_diagnostic_linux_test.go +126 -0
  566. package/templates/native-go/backend/internal/helper/startup_diagnostic_test.go +117 -0
  567. package/templates/native-go/backend/internal/helper/status.go +22 -13
  568. package/templates/native-go/backend/internal/helper/status_test.go +45 -0
  569. package/templates/native-go/backend/internal/helper/supervision.go +1 -1
  570. package/templates/native-go/backend/internal/helper/supervisor_frame.go +3 -0
  571. package/templates/native-go/backend/internal/helper/supervisor_linux.go +6 -2
  572. package/templates/native-go/backend/internal/helper/unit_connection_test.go +22 -4
  573. package/templates/native-go/backend/internal/helper/unit_linux.go +7 -3
  574. package/templates/native-go/backend/internal/helper/unit_query_linux.go +5 -1
  575. package/templates/native-go/backend/internal/helper/write_files_linux.go +7 -4
  576. package/templates/native-go/backend/internal/helper/write_files_linux_test.go +26 -0
  577. package/templates/native-go/dsm-package.yaml +2 -2
  578. package/templates/native-go-authorization/backend/internal/app/authorization.go +298 -0
  579. package/templates/native-go-authorization/backend/internal/app/authorization_test.go +96 -0
  580. package/templates/native-go-authorization/frontend/src/authorization/AuthorizationGate.vue +89 -0
  581. package/templates/native-go-authorization/frontend/src/authorization/i18n/de.json +36 -0
  582. package/templates/native-go-authorization/frontend/src/authorization/i18n/en.json +36 -0
  583. package/templates/native-go-authorization/frontend/src/authorization/i18n/es.json +36 -0
  584. package/templates/native-go-authorization/frontend/src/authorization/i18n/fr.json +36 -0
  585. package/templates/native-go-authorization/frontend/src/authorization/i18n/index.ts +15 -0
  586. package/templates/native-go-authorization/frontend/src/authorization/i18n/it.json +36 -0
  587. package/templates/native-go-authorization/frontend/src/authorization/i18n/ja.json +36 -0
  588. package/templates/native-go-authorization/frontend/src/authorization/i18n/ko.json +36 -0
  589. package/templates/native-go-authorization/frontend/src/authorization/i18n/zh-CN.json +36 -0
  590. package/templates/native-go-authorization/frontend/src/authorization/i18n/zh-TW.json +36 -0
  591. package/templates/native-go-authorization/frontend/test/authorization-preview.html +14 -0
  592. package/templates/native-go-authorization/frontend/test/authorization.test.ts +59 -0
  593. package/templates/native-go-background/BACKGROUND.md +111 -0
  594. package/templates/native-go-background/backend/internal/app/background_on.go +7 -0
  595. package/templates/native-go-background/backend/internal/app/background_routes_test.go +32 -0
  596. package/templates/native-go-background/frontend/src/background/BackgroundPanel.vue +178 -0
  597. package/templates/native-go-background/frontend/src/background/i18n/de.json +83 -0
  598. package/templates/native-go-background/frontend/src/background/i18n/en.json +83 -0
  599. package/templates/native-go-background/frontend/src/background/i18n/es.json +83 -0
  600. package/templates/native-go-background/frontend/src/background/i18n/fr.json +83 -0
  601. package/templates/native-go-background/frontend/src/background/i18n/it.json +83 -0
  602. package/templates/native-go-background/frontend/src/background/i18n/ja.json +83 -0
  603. package/templates/native-go-background/frontend/src/background/i18n/ko.json +83 -0
  604. package/templates/native-go-background/frontend/src/background/i18n/zh-CN.json +83 -0
  605. package/templates/native-go-background/frontend/src/background/i18n/zh-TW.json +83 -0
  606. package/templates/native-go-background/frontend/src/background/i18n.ts +19 -0
  607. package/templates/native-go-background/frontend/src/background/picker-provider.ts +13 -0
  608. package/templates/native-go-background/frontend/test/background.test.ts +179 -0
  609. package/templates/native-go-integration/backend/internal/app/personal.go +2 -2
  610. package/templates/native-go-integration/backend/internal/app/personal_test.go +37 -0
  611. package/templates/native-go-vue/README.md +38 -7
  612. package/templates/native-go-vue/frontend/DESIGN.md +15 -3
  613. package/templates/native-go-vue/frontend/README-JOBS.md +75 -0
  614. package/templates/native-go-vue/frontend/README-M2.md +64 -0
  615. package/templates/native-go-vue/frontend/package-lock.json +5 -4
  616. package/templates/native-go-vue/frontend/package.json +1 -1
  617. package/templates/native-go-vue/frontend/src/App.vue +39 -11
  618. package/templates/native-go-vue/frontend/src/M2App.vue +57 -0
  619. package/templates/native-go-vue/frontend/src/SDKApp.vue +203 -0
  620. package/templates/native-go-vue/frontend/src/context.ts +3 -0
  621. package/templates/native-go-vue/frontend/src/jobs/InteractiveJobForm.vue +70 -0
  622. package/templates/native-go-vue/frontend/src/jobs/JobsAdminPanel.vue +33 -0
  623. package/templates/native-go-vue/frontend/src/jobs/JobsPanel.vue +135 -0
  624. package/templates/native-go-vue/frontend/src/jobs/connected-provider.ts +179 -0
  625. package/templates/native-go-vue/frontend/src/jobs/i18n/de.json +62 -0
  626. package/templates/native-go-vue/frontend/src/jobs/i18n/en.json +62 -0
  627. package/templates/native-go-vue/frontend/src/jobs/i18n/es.json +62 -0
  628. package/templates/native-go-vue/frontend/src/jobs/i18n/fr.json +62 -0
  629. package/templates/native-go-vue/frontend/src/jobs/i18n/it.json +62 -0
  630. package/templates/native-go-vue/frontend/src/jobs/i18n/ja.json +62 -0
  631. package/templates/native-go-vue/frontend/src/jobs/i18n/ko.json +62 -0
  632. package/templates/native-go-vue/frontend/src/jobs/i18n/zh-CN.json +62 -0
  633. package/templates/native-go-vue/frontend/src/jobs/i18n/zh-TW.json +62 -0
  634. package/templates/native-go-vue/frontend/src/jobs/i18n.ts +15 -0
  635. package/templates/native-go-vue/frontend/src/jobs/mock-provider.ts +67 -0
  636. package/templates/native-go-vue/frontend/src/jobs/provider.ts +60 -0
  637. package/templates/native-go-vue/frontend/src/jobs/validate.ts +44 -0
  638. package/templates/native-go-vue/frontend/src/m2-main.ts +21 -0
  639. package/templates/native-go-vue/frontend/src/m2-style.css +7 -0
  640. package/templates/native-go-vue/frontend/src/nas/M2Files.vue +94 -0
  641. package/templates/native-go-vue/frontend/src/nas/M2PathPicker.vue +70 -0
  642. package/templates/native-go-vue/frontend/src/nas/M2Settings.vue +69 -0
  643. package/templates/native-go-vue/frontend/src/nas/i18n/m2/de.json +56 -0
  644. package/templates/native-go-vue/frontend/src/nas/i18n/m2/en.json +56 -0
  645. package/templates/native-go-vue/frontend/src/nas/i18n/m2/es.json +56 -0
  646. package/templates/native-go-vue/frontend/src/nas/i18n/m2/fr.json +56 -0
  647. package/templates/native-go-vue/frontend/src/nas/i18n/m2/it.json +56 -0
  648. package/templates/native-go-vue/frontend/src/nas/i18n/m2/ja.json +56 -0
  649. package/templates/native-go-vue/frontend/src/nas/i18n/m2/ko.json +56 -0
  650. package/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-CN.json +56 -0
  651. package/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-TW.json +56 -0
  652. package/templates/native-go-vue/frontend/src/nas/m2-contract.ts +33 -0
  653. package/templates/native-go-vue/frontend/src/nas/m2-i18n.ts +24 -0
  654. package/templates/native-go-vue/frontend/src/nas/m2-provider.ts +104 -0
  655. package/templates/native-go-vue/frontend/src/nas/use-m2-request.ts +18 -0
  656. package/templates/native-go-vue/frontend/src/sdk-main.ts +39 -0
  657. package/templates/native-go-vue/frontend/src/shell/AppShell.vue +48 -0
  658. package/templates/native-go-vue/frontend/src/shell/i18n/de.json +10 -0
  659. package/templates/native-go-vue/frontend/src/shell/i18n/en.json +10 -0
  660. package/templates/native-go-vue/frontend/src/shell/i18n/es.json +10 -0
  661. package/templates/native-go-vue/frontend/src/shell/i18n/fr.json +10 -0
  662. package/templates/native-go-vue/frontend/src/shell/i18n/it.json +10 -0
  663. package/templates/native-go-vue/frontend/src/shell/i18n/ja.json +10 -0
  664. package/templates/native-go-vue/frontend/src/shell/i18n/ko.json +10 -0
  665. package/templates/native-go-vue/frontend/src/shell/i18n/zh-CN.json +10 -0
  666. package/templates/native-go-vue/frontend/src/shell/i18n/zh-TW.json +10 -0
  667. package/templates/native-go-vue/frontend/src/shell/i18n.ts +17 -0
  668. package/templates/native-go-vue/frontend/src/shell/pages.ts +34 -0
  669. package/templates/native-go-vue/frontend/src/style.css +2 -6
  670. package/templates/native-go-vue/frontend/test/apps.test.ts +21 -0
  671. package/templates/native-go-vue/frontend/test/jobs-connected.test.ts +163 -0
  672. package/templates/native-go-vue/frontend/test/jobs-preview.html +22 -0
  673. package/templates/native-go-vue/frontend/test/jobs.test.ts +176 -0
  674. package/templates/native-go-vue/frontend/test/m2-preview.html +27 -0
  675. package/templates/native-go-vue/frontend/test/m2-provider.test.ts +87 -0
  676. package/templates/native-go-vue/frontend/test/m2-ui.test.ts +209 -0
  677. package/templates/native-go-vue/frontend/test/native-controls.test.ts +27 -0
  678. package/templates/native-go-vue/frontend/test/picker-wire.test.ts +110 -0
  679. package/templates/native-go-vue/frontend/test/shell-preview.html +19 -0
  680. package/templates/native-go-vue/frontend/test/shell-sdk.test.ts +73 -0
  681. package/templates/native-go-vue/frontend/test/shell-ui.test.ts +114 -0
  682. package/templates/native-go-vue/frontend/test/shell.test.ts +45 -0
  683. package/templates/native-go-vue/frontend/vite.config.ts +2 -2
  684. package/dist/templates/hello-web/compose.yaml +0 -21
  685. package/dist/templates/hello-web/html/app.js +0 -1
  686. package/dist/templates/hello-web/html/index.html +0 -13
  687. package/dist/templates/hello-web/synology-app.yaml +0 -13
  688. package/dist/templates/hello-web-page/compose.yaml +0 -21
  689. package/dist/templates/hello-web-page/html/app.js +0 -1
  690. package/dist/templates/hello-web-page/html/index.html +0 -13
  691. package/dist/templates/hello-web-page/synology-app.yaml +0 -13
  692. package/templates/hello-web/compose.yaml +0 -21
  693. package/templates/hello-web/html/app.js +0 -1
  694. package/templates/hello-web/html/index.html +0 -13
  695. package/templates/hello-web/synology-app.yaml +0 -13
  696. package/templates/hello-web-page/compose.yaml +0 -21
  697. package/templates/hello-web-page/html/app.js +0 -1
  698. package/templates/hello-web-page/html/index.html +0 -13
  699. package/templates/hello-web-page/synology-app.yaml +0 -13
@@ -0,0 +1,407 @@
1
+ package background
2
+
3
+ import (
4
+ "bytes"
5
+ "context"
6
+ "crypto/sha256"
7
+ "encoding/hex"
8
+ "errors"
9
+ "fmt"
10
+ "os"
11
+ "path/filepath"
12
+ "strings"
13
+ "testing"
14
+ "time"
15
+ )
16
+
17
+ var admin = Submitter{User: "admin", UID: "1024"}
18
+
19
+ func newStore(t *testing.T) (*Store, string) {
20
+ t.Helper()
21
+ dir := filepath.Join(t.TempDir(), "background")
22
+ s := NewStore(dir)
23
+ if err := s.SetEnabled(context.Background(), true); err != nil {
24
+ t.Fatal(err)
25
+ }
26
+ return s, dir
27
+ }
28
+
29
+ func submit(t *testing.T, s *Store, key string, data []byte) Job {
30
+ t.Helper()
31
+ job, _, err := s.Submit(context.Background(), SubmitRequest{Key: key, Name: "a.txt", Data: data, Submitter: admin, Admin: true})
32
+ if err != nil {
33
+ t.Fatalf("submit %q: %v", key, err)
34
+ }
35
+ return job
36
+ }
37
+
38
+ func digest(b []byte) string { h := sha256.Sum256(b); return hex.EncodeToString(h[:]) }
39
+
40
+ func TestSubmitIsDisabledByDefault(t *testing.T) {
41
+ s := NewStore(filepath.Join(t.TempDir(), "background"))
42
+ _, _, err := s.Submit(context.Background(), SubmitRequest{Key: "k1", Name: "a", Data: []byte("x"), Submitter: admin, Admin: true})
43
+ if !errors.Is(err, ErrDisabled) {
44
+ t.Fatalf("want ErrDisabled, got %v", err)
45
+ }
46
+ }
47
+
48
+ func TestSubmitWritesDurableQueuedJobBeforeReturningID(t *testing.T) {
49
+ s, dir := newStore(t)
50
+ data := []byte("hello")
51
+ job := submit(t, s, "key-1", data)
52
+ if job.State != StateQueued || len(job.ID) != 32 || job.InputDigest != digest(data) || job.InputBytes != 5 {
53
+ t.Fatalf("unexpected job %+v", job)
54
+ }
55
+ // A second process (fresh Store on the same directory) sees the job.
56
+ got, err := NewStore(dir).Get(context.Background(), job.ID)
57
+ if err != nil || got.State != StateQueued || got.Submitter != admin || got.Worker != WorkerSHA256V1 {
58
+ t.Fatalf("reopen: %+v %v", got, err)
59
+ }
60
+ }
61
+
62
+ func TestSpoolPermissionsArePrivate(t *testing.T) {
63
+ s, dir := newStore(t)
64
+ job := submit(t, s, "key-1", []byte("x"))
65
+ check := func(path string, want os.FileMode) {
66
+ t.Helper()
67
+ info, err := os.Lstat(path)
68
+ if err != nil || info.Mode().Perm() != want {
69
+ t.Fatalf("%s: mode %v err %v, want %v", path, info.Mode().Perm(), err, want)
70
+ }
71
+ }
72
+ check(dir, 0o700)
73
+ check(filepath.Join(dir, "inputs"), 0o700)
74
+ check(filepath.Join(dir, "inputs", job.ID), 0o600)
75
+ check(filepath.Join(dir, "journal.json"), 0o600)
76
+ check(filepath.Join(dir, "lock"), 0o600)
77
+ }
78
+
79
+ func TestSpoolRefusesWidePermissionsAndSymlinks(t *testing.T) {
80
+ root := t.TempDir()
81
+ dir := filepath.Join(root, "background")
82
+ if err := os.Mkdir(dir, 0o755); err != nil {
83
+ t.Fatal(err)
84
+ }
85
+ if err := os.Chmod(dir, 0o755); err != nil {
86
+ t.Fatal(err)
87
+ }
88
+ s := NewStore(dir)
89
+ if err := s.SetEnabled(context.Background(), true); err == nil {
90
+ t.Fatal("a world-readable spool must be refused")
91
+ }
92
+ link := filepath.Join(root, "link")
93
+ if err := os.Symlink(root, link); err != nil {
94
+ t.Fatal(err)
95
+ }
96
+ if err := NewStore(link).SetEnabled(context.Background(), true); err == nil {
97
+ t.Fatal("a symlinked spool must be refused")
98
+ }
99
+ }
100
+
101
+ func TestSubmitIdempotencyKey(t *testing.T) {
102
+ s, _ := newStore(t)
103
+ first := submit(t, s, "same-key", []byte("one"))
104
+ again, dup, err := s.Submit(context.Background(), SubmitRequest{Key: "same-key", Name: "a.txt", Data: []byte("one"), Submitter: admin, Admin: true})
105
+ if err != nil || !dup || again.ID != first.ID {
106
+ t.Fatalf("duplicate: %+v dup=%v err=%v", again, dup, err)
107
+ }
108
+ _, _, err = s.Submit(context.Background(), SubmitRequest{Key: "same-key", Name: "a.txt", Data: []byte("two"), Submitter: admin, Admin: true})
109
+ if !errors.Is(err, ErrKeyConflict) {
110
+ t.Fatalf("different input under the same key: %v", err)
111
+ }
112
+ list, _ := s.List(context.Background())
113
+ if len(list) != 1 {
114
+ t.Fatalf("same key must not queue twice: %d jobs", len(list))
115
+ }
116
+ }
117
+
118
+ func TestSubmitLimits(t *testing.T) {
119
+ s, _ := newStore(t)
120
+ ctx := context.Background()
121
+ if _, _, err := s.Submit(ctx, SubmitRequest{Key: "big", Name: "a", Data: make([]byte, MaxInputBytes+1), Submitter: admin, Admin: true}); !errors.Is(err, ErrTooLarge) {
122
+ t.Fatalf("oversize: %v", err)
123
+ }
124
+ for _, bad := range []SubmitRequest{
125
+ {Key: "", Name: "a", Data: []byte("x")},
126
+ {Key: "has space", Name: "a", Data: []byte("x")},
127
+ {Key: strings.Repeat("k", 65), Name: "a", Data: []byte("x")},
128
+ {Key: "ok", Name: "a", Data: nil},
129
+ {Key: "ok", Name: "bad\nname", Data: []byte("x")},
130
+ {Key: "ok", Name: "", Data: []byte("x")},
131
+ } {
132
+ bad.Submitter = admin
133
+ if _, _, err := s.Submit(ctx, bad); !errors.Is(err, ErrInvalid) {
134
+ t.Fatalf("%+v: want ErrInvalid, got %v", bad, err)
135
+ }
136
+ }
137
+ for i := 0; i < MaxQueued; i++ {
138
+ _, _, err := s.Submit(ctx, SubmitRequest{Key: fmt.Sprint(i), Name: "a", Data: []byte("x"), Admin: true, Submitter: Submitter{User: "admin", UID: fmt.Sprint(2000 + i)}})
139
+ if err != nil {
140
+ t.Fatal(err)
141
+ }
142
+ }
143
+ if _, _, err := s.Submit(ctx, SubmitRequest{Key: "one-more", Name: "a", Data: []byte("x"), Submitter: admin, Admin: true}); !errors.Is(err, ErrQueueFull) {
144
+ t.Fatalf("queue full: %v", err)
145
+ }
146
+ }
147
+
148
+ func TestSubmitTotalQuota(t *testing.T) {
149
+ s, _ := newStore(t)
150
+ s.limits.MaxTotalBytes = 10 + resultReserve
151
+ submit(t, s, "k1", []byte("123456"))
152
+ if _, _, err := s.Submit(context.Background(), SubmitRequest{Key: "k2", Name: "a", Data: []byte("123456"), Submitter: admin, Admin: true}); !errors.Is(err, ErrQuota) {
153
+ t.Fatalf("quota: %v", err)
154
+ }
155
+ }
156
+
157
+ func TestClaimRunsOneJobAtATimeInSubmissionOrder(t *testing.T) {
158
+ s, _ := newStore(t)
159
+ ctx := context.Background()
160
+ a := submit(t, s, "ka", []byte("a"))
161
+ b := submit(t, s, "kb", []byte("b"))
162
+ claimed, err := s.Claim(ctx)
163
+ if err != nil || claimed == nil || claimed.ID != a.ID || claimed.State != StateRunning {
164
+ t.Fatalf("first claim: %+v %v", claimed, err)
165
+ }
166
+ if again, err := s.Claim(ctx); err != nil || again != nil {
167
+ t.Fatalf("a second job must wait while one runs: %+v %v", again, err)
168
+ }
169
+ if err := s.Finish(ctx, a.ID, Outcome{State: StateSucceeded, Result: &Result{SHA256: digest([]byte("a")), Bytes: 1}}); err != nil {
170
+ t.Fatal(err)
171
+ }
172
+ next, err := s.Claim(ctx)
173
+ if err != nil || next == nil || next.ID != b.ID {
174
+ t.Fatalf("next claim: %+v %v", next, err)
175
+ }
176
+ }
177
+
178
+ func TestClaimDoesNothingWhileDisabled(t *testing.T) {
179
+ s, _ := newStore(t)
180
+ submit(t, s, "k", []byte("x"))
181
+ if err := s.SetEnabled(context.Background(), false); err != nil {
182
+ t.Fatal(err)
183
+ }
184
+ if got, err := s.Claim(context.Background()); err != nil || got != nil {
185
+ t.Fatalf("disabled claim: %+v %v", got, err)
186
+ }
187
+ }
188
+
189
+ func TestFinishRecordsResultAndRetainsPrivateCopy(t *testing.T) {
190
+ s, dir := newStore(t)
191
+ ctx := context.Background()
192
+ job := submit(t, s, "k", []byte("abc"))
193
+ if _, err := s.Claim(ctx); err != nil {
194
+ t.Fatal(err)
195
+ }
196
+ want := Result{SHA256: digest([]byte("abc")), Bytes: 3}
197
+ if err := s.Finish(ctx, job.ID, Outcome{State: StateSucceeded, Result: &want}); err != nil {
198
+ t.Fatal(err)
199
+ }
200
+ got, _ := s.Get(ctx, job.ID)
201
+ if got.State != StateSucceeded || got.Result == nil || *got.Result != want || got.FinishedAt.IsZero() {
202
+ t.Fatalf("finished job: %+v", got)
203
+ }
204
+ if b, err := os.ReadFile(filepath.Join(dir, "inputs", job.ID)); err != nil || string(b) != "abc" {
205
+ t.Fatalf("completed private copy must remain available for schedules: %v", err)
206
+ }
207
+ if err := s.Finish(ctx, job.ID, Outcome{State: StateFailed, ErrorCode: "x"}); !errors.Is(err, ErrNotRunning) {
208
+ t.Fatalf("finishing twice: %v", err)
209
+ }
210
+ }
211
+
212
+ func TestCancelQueuedJobIsImmediate(t *testing.T) {
213
+ s, dir := newStore(t)
214
+ job := submit(t, s, "k", []byte("x"))
215
+ got, err := s.Cancel(context.Background(), job.ID)
216
+ if err != nil || got.State != StateCanceled {
217
+ t.Fatalf("cancel: %+v %v", got, err)
218
+ }
219
+ if _, err := os.Stat(filepath.Join(dir, "inputs", job.ID)); !errors.Is(err, os.ErrNotExist) {
220
+ t.Fatalf("canceled input must be removed: %v", err)
221
+ }
222
+ if c, _ := s.Claim(context.Background()); c != nil {
223
+ t.Fatal("a canceled job must never run")
224
+ }
225
+ }
226
+
227
+ func TestCancelRunningJobRequestsStopAndBeatsLaterCompletion(t *testing.T) {
228
+ s, _ := newStore(t)
229
+ ctx := context.Background()
230
+ job := submit(t, s, "k", []byte("x"))
231
+ if _, err := s.Claim(ctx); err != nil {
232
+ t.Fatal(err)
233
+ }
234
+ got, err := s.Cancel(ctx, job.ID)
235
+ if err != nil || got.State != StateRunning || !got.CancelRequested {
236
+ t.Fatalf("cancel running: %+v %v", got, err)
237
+ }
238
+ if err := s.Finish(ctx, job.ID, Outcome{State: StateSucceeded, Result: &Result{Bytes: 1}}); err != nil {
239
+ t.Fatal(err)
240
+ }
241
+ final, _ := s.Get(ctx, job.ID)
242
+ if final.State != StateCanceled || final.Result != nil {
243
+ t.Fatalf("cancel requested first must win: %+v", final)
244
+ }
245
+ }
246
+
247
+ func TestCancelAfterCompletionIsRefused(t *testing.T) {
248
+ s, _ := newStore(t)
249
+ ctx := context.Background()
250
+ job := submit(t, s, "k", []byte("x"))
251
+ _, _ = s.Claim(ctx)
252
+ _ = s.Finish(ctx, job.ID, Outcome{State: StateSucceeded, Result: &Result{Bytes: 1}})
253
+ if _, err := s.Cancel(ctx, job.ID); !errors.Is(err, ErrNotCancelable) {
254
+ t.Fatalf("late cancel: %v", err)
255
+ }
256
+ if got, _ := s.Get(ctx, job.ID); got.State != StateSucceeded {
257
+ t.Fatalf("completion must stand: %+v", got)
258
+ }
259
+ }
260
+
261
+ func TestUnknownJobIsNotFound(t *testing.T) {
262
+ s, _ := newStore(t)
263
+ for _, id := range []string{"nope", strings.Repeat("0", 32), "../journal.json"} {
264
+ if _, err := s.Get(context.Background(), id); !errors.Is(err, ErrNotFound) {
265
+ t.Fatalf("%q: %v", id, err)
266
+ }
267
+ if _, err := s.Cancel(context.Background(), id); !errors.Is(err, ErrNotFound) {
268
+ t.Fatalf("cancel %q: %v", id, err)
269
+ }
270
+ }
271
+ }
272
+
273
+ func TestDisableCancelsQueuedAndRequestsStopOfRunning(t *testing.T) {
274
+ s, _ := newStore(t)
275
+ ctx := context.Background()
276
+ running := submit(t, s, "k1", []byte("1"))
277
+ queued := submit(t, s, "k2", []byte("2"))
278
+ _, _ = s.Claim(ctx)
279
+ if err := s.SetEnabled(ctx, false); err != nil {
280
+ t.Fatal(err)
281
+ }
282
+ if got, _ := s.Get(ctx, queued.ID); got.State != StateCanceled || got.ErrorCode != "disabled" {
283
+ t.Fatalf("queued: %+v", got)
284
+ }
285
+ if got, _ := s.Get(ctx, running.ID); got.State != StateRunning || !got.CancelRequested {
286
+ t.Fatalf("running: %+v", got)
287
+ }
288
+ if _, _, err := s.Submit(ctx, SubmitRequest{Key: "k3", Name: "a", Data: []byte("x"), Submitter: admin, Admin: true}); !errors.Is(err, ErrDisabled) {
289
+ t.Fatalf("submit while disabled: %v", err)
290
+ }
291
+ }
292
+
293
+ func TestRecoverMarksRunningInterruptedWithoutReplay(t *testing.T) {
294
+ s, dir := newStore(t)
295
+ ctx := context.Background()
296
+ running := submit(t, s, "k1", []byte("1"))
297
+ queued := submit(t, s, "k2", []byte("2"))
298
+ _, _ = s.Claim(ctx)
299
+ // The worker was killed: a new process recovers the journal.
300
+ fresh := NewStore(dir)
301
+ if err := fresh.Recover(ctx); err != nil {
302
+ t.Fatal(err)
303
+ }
304
+ if got, _ := fresh.Get(ctx, running.ID); got.State != StateInterrupted || got.ErrorCode != "worker-stopped" {
305
+ t.Fatalf("running: %+v", got)
306
+ }
307
+ if _, err := os.Stat(filepath.Join(dir, "inputs", running.ID)); !errors.Is(err, os.ErrNotExist) {
308
+ t.Fatalf("interrupted input must be removed: %v", err)
309
+ }
310
+ if got, _ := fresh.Get(ctx, queued.ID); got.State != StateQueued {
311
+ t.Fatalf("queued jobs of the same worker revision stay queued: %+v", got)
312
+ }
313
+ }
314
+
315
+ func TestRecoverMarksCancelRequestedRunningAsCanceled(t *testing.T) {
316
+ s, dir := newStore(t)
317
+ ctx := context.Background()
318
+ job := submit(t, s, "k", []byte("x"))
319
+ _, _ = s.Claim(ctx)
320
+ _, _ = s.Cancel(ctx, job.ID)
321
+ if err := NewStore(dir).Recover(ctx); err != nil {
322
+ t.Fatal(err)
323
+ }
324
+ if got, _ := s.Get(ctx, job.ID); got.State != StateCanceled {
325
+ t.Fatalf("%+v", got)
326
+ }
327
+ }
328
+
329
+ func TestRecoverInterruptsQueuedJobsFromAnotherWorkerRevision(t *testing.T) {
330
+ s, dir := newStore(t)
331
+ ctx := context.Background()
332
+ job := submit(t, s, "k", []byte("x"))
333
+ newer := NewStore(dir)
334
+ newer.revision = WorkerRevision + 1
335
+ if err := newer.Recover(ctx); err != nil {
336
+ t.Fatal(err)
337
+ }
338
+ got, _ := s.Get(ctx, job.ID)
339
+ if got.State != StateInterrupted || got.ErrorCode != "worker-changed" {
340
+ t.Fatalf("an upgrade must not silently run old queued work: %+v", got)
341
+ }
342
+ }
343
+
344
+ func TestRecoverRemovesOrphanInputs(t *testing.T) {
345
+ s, dir := newStore(t)
346
+ submit(t, s, "k", []byte("x"))
347
+ orphan := filepath.Join(dir, "inputs", strings.Repeat("a", 32))
348
+ if err := os.WriteFile(orphan, []byte("left by a crash"), 0o600); err != nil {
349
+ t.Fatal(err)
350
+ }
351
+ if err := s.Recover(context.Background()); err != nil {
352
+ t.Fatal(err)
353
+ }
354
+ if _, err := os.Stat(orphan); !errors.Is(err, os.ErrNotExist) {
355
+ t.Fatalf("orphan input must be removed: %v", err)
356
+ }
357
+ }
358
+
359
+ func TestOpenInputReturnsStoredBytesOnlyForRunningJob(t *testing.T) {
360
+ s, _ := newStore(t)
361
+ ctx := context.Background()
362
+ job := submit(t, s, "k", []byte("payload"))
363
+ if _, err := s.OpenInput(job.ID); err == nil {
364
+ t.Fatal("a queued job's input is not handed to a worker")
365
+ }
366
+ _, _ = s.Claim(ctx)
367
+ f, err := s.OpenInput(job.ID)
368
+ if err != nil {
369
+ t.Fatal(err)
370
+ }
371
+ defer f.Close()
372
+ var buf bytes.Buffer
373
+ _, _ = buf.ReadFrom(f)
374
+ if buf.String() != "payload" {
375
+ t.Fatalf("input: %q", buf.String())
376
+ }
377
+ }
378
+
379
+ func TestHistoryIsBounded(t *testing.T) {
380
+ s, _ := newStore(t)
381
+ ctx := context.Background()
382
+ for i := 0; i < MaxHistory+5; i++ {
383
+ job := submit(t, s, "key-"+time.Duration(i).String(), []byte("x"))
384
+ _, _ = s.Claim(ctx)
385
+ _ = s.Finish(ctx, job.ID, Outcome{State: StateSucceeded, Result: &Result{Bytes: 1}})
386
+ }
387
+ list, _ := s.List(ctx)
388
+ if len(list) != MaxHistory {
389
+ t.Fatalf("history: %d jobs", len(list))
390
+ }
391
+ }
392
+
393
+ func TestStatusReportsWorkerHeartbeat(t *testing.T) {
394
+ s, _ := newStore(t)
395
+ ctx := context.Background()
396
+ st, _ := s.Status(ctx)
397
+ if !st.Enabled || st.Worker != nil || st.Revision != WorkerRevision || st.Algorithm != WorkerSHA256V1 {
398
+ t.Fatalf("status: %+v", st)
399
+ }
400
+ if err := s.Heartbeat(ctx, WorkerInfo{PID: 42, UID: 255853, Username: "SynologyApp"}); err != nil {
401
+ t.Fatal(err)
402
+ }
403
+ st, _ = s.Status(ctx)
404
+ if st.Worker == nil || st.Worker.UID != 255853 || st.Worker.PID != 42 || st.Worker.At.IsZero() {
405
+ t.Fatalf("worker: %+v", st.Worker)
406
+ }
407
+ }
@@ -0,0 +1,191 @@
1
+ // Package datamigrate applies ordered, idempotent schema migrations to a
2
+ // package's data directory and records how far they have run.
3
+ //
4
+ // The data directory is the package's `var` folder (/var/packages/<package>/var,
5
+ // @appdata on the volume). DSM keeps it across upgrades and removes `tmp` and
6
+ // `target`, so schema changes belong here.
7
+ //
8
+ // Every run is a no-op once the recorded version covers all migrations. A
9
+ // migration that fails stops the run with the previous version still recorded:
10
+ // the utility never deletes or rewrites data by itself, and the next run
11
+ // resumes from the last successful step. Migrations must therefore be
12
+ // idempotent — a crash between Apply and the version record re-runs one step,
13
+ // and two concurrent CGI requests can both reach a step the first time.
14
+ package datamigrate
15
+
16
+ import (
17
+ "encoding/json"
18
+ "errors"
19
+ "fmt"
20
+ "os"
21
+ "path/filepath"
22
+ "sort"
23
+ )
24
+
25
+ // StateFile is the file, inside the data directory, that records progress.
26
+ const StateFile = "data-version"
27
+
28
+ // State is what StateFile holds.
29
+ type State struct {
30
+ // Schema is the highest migration version applied so far; 0 means none.
31
+ Schema int `json:"schema"`
32
+ // PackageVersion is the package version recorded by the last run. It is the
33
+ // fallback for Context.OldPkgVer when SYNOPKG_OLD_PKGVER is not set.
34
+ PackageVersion string `json:"packageVersion,omitempty"`
35
+ }
36
+
37
+ // Context is the version context and directory a migration runs in.
38
+ type Context struct {
39
+ // DataDir is the package's persistent var directory; DSM keeps it across
40
+ // upgrades.
41
+ DataDir string
42
+ // OldPkgVer is the version being upgraded from: SYNOPKG_OLD_PKGVER when the
43
+ // lifecycle environment provides it, otherwise the version the last
44
+ // successful run recorded. Empty on a first install.
45
+ OldPkgVer string
46
+ // NewPkgVer is the version running now.
47
+ NewPkgVer string
48
+ // Logf, when set, receives one line per applied migration.
49
+ Logf func(format string, args ...any)
50
+ }
51
+
52
+ // Migration is one numbered schema step. The app owns the meaning of Version;
53
+ // versions start at 1, never change meaning and never run twice once recorded.
54
+ type Migration struct {
55
+ Version int
56
+ Name string
57
+ Apply func(Context) error
58
+ }
59
+
60
+ // Info is the version context of one run.
61
+ type Info struct {
62
+ // OldPkgVer comes from SYNOPKG_OLD_PKGVER in a lifecycle script.
63
+ OldPkgVer string
64
+ // NewPkgVer is the package version running now.
65
+ NewPkgVer string
66
+ // Logf, when set, receives one line per applied migration.
67
+ Logf func(format string, args ...any)
68
+ }
69
+
70
+ // Load reads the recorded state. A missing file is the zero state, not an
71
+ // error: that is a package that has never migrated.
72
+ func Load(dataDir string) (State, error) {
73
+ raw, err := os.ReadFile(filepath.Join(dataDir, StateFile))
74
+ if errors.Is(err, os.ErrNotExist) {
75
+ return State{}, nil
76
+ }
77
+ if err != nil {
78
+ return State{}, fmt.Errorf("read %s: %w", StateFile, err)
79
+ }
80
+ var state State
81
+ if err := json.Unmarshal(raw, &state); err != nil {
82
+ return State{}, fmt.Errorf("parse %s: %w", StateFile, err)
83
+ }
84
+ if state.Schema < 0 {
85
+ return State{}, fmt.Errorf("%s: schema %d is negative", StateFile, state.Schema)
86
+ }
87
+ return state, nil
88
+ }
89
+
90
+ // Run validates the migrations, applies every one whose version is greater
91
+ // than the recorded schema version (lowest first) and records the package
92
+ // version. It returns the state after the run. On the first failure it stops
93
+ // and returns the error with the previous state intact.
94
+ func Run(dataDir string, info Info, migrations []Migration) (State, error) {
95
+ if dataDir == "" {
96
+ return State{}, errors.New("datamigrate: data directory is empty")
97
+ }
98
+ ordered, err := order(migrations)
99
+ if err != nil {
100
+ return State{}, err
101
+ }
102
+ current, err := Load(dataDir)
103
+ if err != nil {
104
+ return State{}, err
105
+ }
106
+ oldPkgVer := info.OldPkgVer
107
+ if oldPkgVer == "" {
108
+ oldPkgVer = current.PackageVersion
109
+ }
110
+ for _, migration := range ordered {
111
+ if migration.Version <= current.Schema {
112
+ continue
113
+ }
114
+ ctx := Context{DataDir: dataDir, OldPkgVer: oldPkgVer, NewPkgVer: info.NewPkgVer, Logf: info.Logf}
115
+ if err := migration.Apply(ctx); err != nil {
116
+ return current, fmt.Errorf("schema migration %d (%s) failed: %w", migration.Version, migration.Name, err)
117
+ }
118
+ if info.Logf != nil {
119
+ info.Logf("applied schema migration %d (%s)", migration.Version, migration.Name)
120
+ }
121
+ current.Schema = migration.Version
122
+ if err := save(dataDir, current); err != nil {
123
+ return current, err
124
+ }
125
+ }
126
+ if info.NewPkgVer != "" && current.PackageVersion != info.NewPkgVer {
127
+ current.PackageVersion = info.NewPkgVer
128
+ if err := save(dataDir, current); err != nil {
129
+ return current, err
130
+ }
131
+ }
132
+ return current, nil
133
+ }
134
+
135
+ // order checks the list before anything runs and returns a version-ascending
136
+ // copy, so a bad list never leaves half a migration behind.
137
+ func order(migrations []Migration) ([]Migration, error) {
138
+ ordered := append([]Migration(nil), migrations...)
139
+ sort.Slice(ordered, func(i, j int) bool { return ordered[i].Version < ordered[j].Version })
140
+ seen := make(map[int]bool, len(ordered))
141
+ for _, migration := range ordered {
142
+ if migration.Version < 1 {
143
+ return nil, fmt.Errorf("datamigrate: migration %q has version %d; versions start at 1", migration.Name, migration.Version)
144
+ }
145
+ if migration.Apply == nil {
146
+ return nil, fmt.Errorf("datamigrate: migration %d (%s) has no Apply function", migration.Version, migration.Name)
147
+ }
148
+ if seen[migration.Version] {
149
+ return nil, fmt.Errorf("datamigrate: duplicate migration version %d", migration.Version)
150
+ }
151
+ seen[migration.Version] = true
152
+ }
153
+ return ordered, nil
154
+ }
155
+
156
+ // save writes the state through a temporary file in the same directory and
157
+ // renames it, so a reader never sees a partial file.
158
+ func save(dataDir string, state State) error {
159
+ if err := os.MkdirAll(dataDir, 0o750); err != nil {
160
+ return fmt.Errorf("create data directory: %w", err)
161
+ }
162
+ data, err := json.Marshal(state)
163
+ if err != nil {
164
+ return err
165
+ }
166
+ data = append(data, '\n')
167
+ tmp, err := os.CreateTemp(dataDir, "."+StateFile+"-*")
168
+ if err != nil {
169
+ return fmt.Errorf("create %s: %w", StateFile, err)
170
+ }
171
+ tmpName := tmp.Name()
172
+ defer os.Remove(tmpName)
173
+ if _, err := tmp.Write(data); err != nil {
174
+ tmp.Close()
175
+ return fmt.Errorf("write %s: %w", StateFile, err)
176
+ }
177
+ if err := tmp.Sync(); err != nil {
178
+ tmp.Close()
179
+ return fmt.Errorf("sync %s: %w", StateFile, err)
180
+ }
181
+ if err := tmp.Close(); err != nil {
182
+ return fmt.Errorf("close %s: %w", StateFile, err)
183
+ }
184
+ if err := os.Chmod(tmpName, 0o600); err != nil {
185
+ return err
186
+ }
187
+ if err := os.Rename(tmpName, filepath.Join(dataDir, StateFile)); err != nil {
188
+ return fmt.Errorf("replace %s: %w", StateFile, err)
189
+ }
190
+ return nil
191
+ }