@synopackageland/cli 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (631) hide show
  1. package/README.md +7 -3
  2. package/dist/build-spk/delete-app-data.d.ts +27 -7
  3. package/dist/build-spk/delete-app-data.js +35 -34
  4. package/dist/build-spk/dsm-arch.d.ts +6 -1
  5. package/dist/build-spk/dsm-arch.js +25 -1
  6. package/dist/build-spk/dsm-version.d.ts +14 -0
  7. package/dist/build-spk/dsm-version.js +47 -0
  8. package/dist/build-spk/gateway.d.ts +31 -0
  9. package/dist/build-spk/gateway.js +55 -0
  10. package/dist/build-spk/generator.d.ts +5 -0
  11. package/dist/build-spk/generator.js +103 -107
  12. package/dist/build-spk/install-wizard.d.ts +20 -0
  13. package/dist/build-spk/install-wizard.js +76 -0
  14. package/dist/build-spk/native-lifecycle.d.ts +5 -0
  15. package/dist/build-spk/native-lifecycle.js +12 -2
  16. package/dist/build-spk/resource-worker.d.ts +9 -4
  17. package/dist/build-spk/resource-worker.js +15 -6
  18. package/dist/build-spk/share-combobox.d.ts +3 -0
  19. package/dist/build-spk/share-combobox.js +27 -0
  20. package/dist/build-spk/uninstall-wizard.d.ts +14 -0
  21. package/dist/build-spk/uninstall-wizard.js +33 -0
  22. package/dist/build-spk/wizard-i18n.d.ts +18 -0
  23. package/dist/build-spk/wizard-i18n.js +38 -0
  24. package/dist/build-spk/wizard-messages.d.ts +388 -0
  25. package/dist/build-spk/wizard-messages.js +387 -0
  26. package/dist/cli.js +130 -30
  27. package/dist/compose/analyze.d.ts +20 -0
  28. package/dist/compose/analyze.js +75 -11
  29. package/dist/contract/validate.js +33 -1
  30. package/dist/contract/web-launch.d.ts +22 -0
  31. package/dist/contract/web-launch.js +37 -0
  32. package/dist/deploy/deploy.d.ts +3 -0
  33. package/dist/deploy/deploy.js +11 -2
  34. package/dist/error-registry.js +60 -1
  35. package/dist/host/open-url.d.ts +2 -0
  36. package/dist/host/open-url.js +4 -1
  37. package/dist/images/pin.d.ts +52 -0
  38. package/dist/images/pin.js +249 -0
  39. package/dist/init.d.ts +27 -3
  40. package/dist/init.js +104 -15
  41. package/dist/inspect.d.ts +3 -0
  42. package/dist/inspect.js +15 -3
  43. package/dist/standalone/background.d.ts +21 -0
  44. package/dist/standalone/background.js +52 -0
  45. package/dist/standalone/binary.d.ts +1 -0
  46. package/dist/standalone/binary.js +1 -1
  47. package/dist/standalone/build.d.ts +2 -0
  48. package/dist/standalone/build.js +38 -6
  49. package/dist/standalone/dsm-window.js +2 -2
  50. package/dist/standalone/helper-inventory.d.ts +15 -0
  51. package/dist/standalone/helper-inventory.js +9 -0
  52. package/dist/standalone/helper.d.ts +1 -0
  53. package/dist/standalone/helper.js +28 -10
  54. package/dist/standalone/host-adapter.d.ts +1 -1
  55. package/dist/standalone/host-adapter.js +33 -15
  56. package/dist/standalone/host-file-navigation.d.ts +7 -0
  57. package/dist/standalone/host-file-navigation.js +172 -0
  58. package/dist/standalone/inspect-helper.js +9 -4
  59. package/dist/standalone/inspect-spk.d.ts +1 -1
  60. package/dist/standalone/inspect-spk.js +200 -7
  61. package/dist/standalone/job-diagnostics.d.ts +1 -0
  62. package/dist/standalone/job-diagnostics.js +49 -0
  63. package/dist/standalone/lifecycle.js +12 -2
  64. package/dist/standalone/manifest.d.ts +15 -2
  65. package/dist/standalone/manifest.js +37 -6
  66. package/dist/standalone/native-layout.d.ts +74 -0
  67. package/dist/standalone/native-layout.js +318 -0
  68. package/dist/standalone/resource.d.ts +11 -0
  69. package/dist/standalone/resource.js +13 -0
  70. package/dist/standalone/root-window.d.ts +3 -1
  71. package/dist/standalone/root-window.js +156 -38
  72. package/dist/standalone/shared-folder.d.ts +39 -0
  73. package/dist/standalone/shared-folder.js +141 -0
  74. package/dist/standalone/spk.d.ts +2 -0
  75. package/dist/standalone/spk.js +33 -3
  76. package/dist/standalone/worker-contract-json.d.ts +8 -0
  77. package/dist/standalone/worker-contract-json.js +141 -0
  78. package/dist/standalone/worker-contract.d.ts +189 -0
  79. package/dist/standalone/worker-contract.js +175 -0
  80. package/dist/standalone/worker-registry.d.ts +40 -0
  81. package/dist/standalone/worker-registry.js +167 -0
  82. package/dist/templates/_daemon/go.mod +2 -0
  83. package/dist/templates/_gateway/auth.go +101 -0
  84. package/dist/templates/_gateway/auth_test.go +216 -0
  85. package/dist/templates/_gateway/cgi.go +133 -0
  86. package/dist/templates/_gateway/cgi_test.go +156 -0
  87. package/dist/templates/_gateway/csrf.go +73 -0
  88. package/dist/templates/_gateway/csrf_test.go +155 -0
  89. package/dist/templates/_gateway/directory.go +108 -0
  90. package/dist/templates/_gateway/directory_test.go +202 -0
  91. package/dist/templates/_gateway/gateway.go +412 -0
  92. package/dist/templates/_gateway/gateway_test.go +676 -0
  93. package/dist/templates/_gateway/go.mod +3 -0
  94. package/dist/templates/_gateway/groups.go +66 -0
  95. package/dist/templates/_gateway/main.go +45 -0
  96. package/dist/templates/binary/synology-app.yaml +1 -1
  97. package/dist/templates/compose-import/compose.yaml +1 -1
  98. package/dist/templates/compose-import/synology-app.yaml +1 -1
  99. package/dist/templates/hello-files/compose.yaml +1 -1
  100. package/dist/templates/hello-files/synology-app.yaml +1 -1
  101. package/dist/templates/hello-web/compose.yaml +5 -2
  102. package/dist/templates/hello-web/synology-app.yaml +4 -1
  103. package/dist/templates/hello-web-page/compose.yaml +5 -2
  104. package/dist/templates/hello-web-page/synology-app.yaml +4 -1
  105. package/dist/templates/native-go/README.md +93 -4
  106. package/dist/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +3 -1
  107. package/dist/templates/native-go/backend/cmd/app/main.go +17 -0
  108. package/dist/templates/native-go/backend/cmd/app/sdk_main.go +60 -0
  109. package/dist/templates/native-go/backend/cmd/background-worker/main.go +38 -0
  110. package/dist/templates/native-go/backend/cmd/helper/main.go +10 -1
  111. package/dist/templates/native-go/backend/cmd/helper/sdk_registry.go +19 -0
  112. package/dist/templates/native-go/backend/go.mod +5 -3
  113. package/dist/templates/native-go/backend/go.sum +4 -4
  114. package/dist/templates/native-go/backend/internal/api/registry.go +17 -6
  115. package/dist/templates/native-go/backend/internal/api/server.go +7 -1
  116. package/dist/templates/native-go/backend/internal/app/background.go +270 -0
  117. package/dist/templates/native-go/backend/internal/app/background_none.go +8 -0
  118. package/dist/templates/native-go/backend/internal/app/background_owner.go +59 -0
  119. package/dist/templates/native-go/backend/internal/app/background_owner_test.go +145 -0
  120. package/dist/templates/native-go/backend/internal/app/background_schedule.go +74 -0
  121. package/dist/templates/native-go/backend/internal/app/background_schedule_test.go +62 -0
  122. package/dist/templates/native-go/backend/internal/app/background_test.go +346 -0
  123. package/dist/templates/native-go/backend/internal/app/integration_state.go +16 -0
  124. package/dist/templates/native-go/backend/internal/app/migrations.go +41 -0
  125. package/dist/templates/native-go/backend/internal/app/migrations_test.go +41 -0
  126. package/dist/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +8 -0
  127. package/dist/templates/native-go/backend/internal/app/routes.go +17 -3
  128. package/dist/templates/native-go/backend/internal/app/routes_test.go +20 -3
  129. package/dist/templates/native-go/backend/internal/app/sdk_jobs.go +70 -0
  130. package/dist/templates/native-go/backend/internal/app/sdk_jobs_test.go +116 -0
  131. package/dist/templates/native-go/backend/internal/app/sdk_routes.go +174 -0
  132. package/dist/templates/native-go/backend/internal/app/session_files.go +15 -0
  133. package/dist/templates/native-go/backend/internal/app/session_files_test.go +26 -0
  134. package/dist/templates/native-go/backend/internal/app/shared_folder.go +144 -0
  135. package/dist/templates/native-go/backend/internal/app/shared_folder_test.go +158 -0
  136. package/dist/templates/native-go/backend/internal/background/access.go +57 -0
  137. package/dist/templates/native-go/backend/internal/background/owner_test.go +126 -0
  138. package/dist/templates/native-go/backend/internal/background/runner.go +185 -0
  139. package/dist/templates/native-go/backend/internal/background/runner_test.go +209 -0
  140. package/dist/templates/native-go/backend/internal/background/schedule.go +300 -0
  141. package/dist/templates/native-go/backend/internal/background/schedule_test.go +335 -0
  142. package/dist/templates/native-go/backend/internal/background/store.go +807 -0
  143. package/dist/templates/native-go/backend/internal/background/store_test.go +407 -0
  144. package/dist/templates/native-go/backend/internal/datamigrate/migrate.go +191 -0
  145. package/dist/templates/native-go/backend/internal/datamigrate/migrate_test.go +177 -0
  146. package/dist/templates/native-go/backend/internal/filestation/browse_test.go +67 -0
  147. package/dist/templates/native-go/backend/internal/filestation/client.go +251 -0
  148. package/dist/templates/native-go/backend/internal/filestation/client_test.go +155 -0
  149. package/dist/templates/native-go/backend/internal/filestation/doc.go +4 -0
  150. package/dist/templates/native-go/backend/internal/filestation/read_file_test.go +90 -0
  151. package/dist/templates/native-go/backend/internal/filestation/repository.go +207 -0
  152. package/dist/templates/native-go/backend/internal/filestation/repository_test.go +104 -0
  153. package/dist/templates/native-go/backend/internal/filestation/sdk_session.go +241 -0
  154. package/dist/templates/native-go/backend/internal/filestation/sdk_session_test.go +183 -0
  155. package/dist/templates/native-go/backend/internal/filestation/service.go +254 -0
  156. package/dist/templates/native-go/backend/internal/filestation/service_test.go +94 -0
  157. package/dist/templates/native-go/backend/internal/filestation/session_semantics_test.go +383 -0
  158. package/dist/templates/native-go/backend/internal/filestation/write.go +72 -0
  159. package/dist/templates/native-go/backend/internal/filestation/write_test.go +123 -0
  160. package/dist/templates/native-go/backend/internal/helper/background_proof.go +163 -0
  161. package/dist/templates/native-go/backend/internal/helper/background_proof_contract.go +46 -0
  162. package/dist/templates/native-go/backend/internal/helper/background_proof_test.go +161 -0
  163. package/dist/templates/native-go/backend/internal/helper/data_contract.go +3 -0
  164. package/dist/templates/native-go/backend/internal/helper/data_protocol.go +3 -0
  165. package/dist/templates/native-go/backend/internal/helper/data_protocol_test.go +1 -1
  166. package/dist/templates/native-go/backend/internal/helper/grant_authority.go +3 -0
  167. package/dist/templates/native-go/backend/internal/helper/grant_authority_test.go +1 -1
  168. package/dist/templates/native-go/backend/internal/helper/grant_repository_linux.go +2 -1
  169. package/dist/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +4 -3
  170. package/dist/templates/native-go/backend/internal/helper/grant_snapshot.go +3 -0
  171. package/dist/templates/native-go/backend/internal/helper/jobcontract/bindings.go +48 -0
  172. package/dist/templates/native-go/backend/internal/helper/jobcontract/contract_test.go +436 -0
  173. package/dist/templates/native-go/backend/internal/helper/jobcontract/decode.go +185 -0
  174. package/dist/templates/native-go/backend/internal/helper/jobcontract/digest.go +55 -0
  175. package/dist/templates/native-go/backend/internal/helper/jobcontract/registry.go +85 -0
  176. package/dist/templates/native-go/backend/internal/helper/jobcontract/registry_test.go +73 -0
  177. package/dist/templates/native-go/backend/internal/helper/jobcontract/result.go +53 -0
  178. package/dist/templates/native-go/backend/internal/helper/jobcontract/stub.go +8 -0
  179. package/dist/templates/native-go/backend/internal/helper/jobcontract/testdata/input-digests.json +127 -0
  180. package/dist/templates/native-go/backend/internal/helper/jobcontract/types.go +234 -0
  181. package/dist/templates/native-go/backend/internal/helper/jobcontract/types_test.go +29 -0
  182. package/dist/templates/native-go/backend/internal/helper/jobcontract/validate.go +462 -0
  183. package/dist/templates/native-go/backend/internal/helper/legacy_authority_schema_linux_test.go +34 -0
  184. package/dist/templates/native-go/backend/internal/helper/legacy_authority_schema_test.go +6 -0
  185. package/dist/templates/native-go/backend/internal/helper/management.go +79 -0
  186. package/dist/templates/native-go/backend/internal/helper/observation.go +42 -2
  187. package/dist/templates/native-go/backend/internal/helper/observation_health_test.go +13 -1
  188. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic.go +56 -10
  189. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +6 -0
  190. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_writer.go +40 -0
  191. package/dist/templates/native-go/backend/internal/helper/process_linux.go +3 -0
  192. package/dist/templates/native-go/backend/internal/helper/query_deadline_linux_test.go +115 -0
  193. package/dist/templates/native-go/backend/internal/helper/query_pending_diagnostic_test.go +254 -0
  194. package/dist/templates/native-go/backend/internal/helper/relaxed_invalidation.go +3 -0
  195. package/dist/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +23 -4
  196. package/dist/templates/native-go/backend/internal/helper/sdk_assembly_linux.go +51 -0
  197. package/dist/templates/native-go/backend/internal/helper/sdk_attach.go +83 -0
  198. package/dist/templates/native-go/backend/internal/helper/sdk_attach_contract.go +32 -0
  199. package/dist/templates/native-go/backend/internal/helper/sdk_attach_test.go +184 -0
  200. package/dist/templates/native-go/backend/internal/helper/sdk_authority_schema_test.go +6 -0
  201. package/dist/templates/native-go/backend/internal/helper/sdk_background_authority.go +832 -0
  202. package/dist/templates/native-go/backend/internal/helper/sdk_background_authority_test.go +714 -0
  203. package/dist/templates/native-go/backend/internal/helper/sdk_background_invalidation.go +218 -0
  204. package/dist/templates/native-go/backend/internal/helper/sdk_background_lease.go +218 -0
  205. package/dist/templates/native-go/backend/internal/helper/sdk_background_snapshot.go +110 -0
  206. package/dist/templates/native-go/backend/internal/helper/sdk_background_store_linux_test.go +261 -0
  207. package/dist/templates/native-go/backend/internal/helper/sdk_background_store_test.go +58 -0
  208. package/dist/templates/native-go/backend/internal/helper/sdk_bindings.go +60 -0
  209. package/dist/templates/native-go/backend/internal/helper/sdk_data_contract.go +251 -0
  210. package/dist/templates/native-go/backend/internal/helper/sdk_data_protocol.go +424 -0
  211. package/dist/templates/native-go/backend/internal/helper/sdk_dispatch_absence_test.go +51 -0
  212. package/dist/templates/native-go/backend/internal/helper/sdk_display.go +488 -0
  213. package/dist/templates/native-go/backend/internal/helper/sdk_display_contract.go +121 -0
  214. package/dist/templates/native-go/backend/internal/helper/sdk_display_test.go +459 -0
  215. package/dist/templates/native-go/backend/internal/helper/sdk_grant_authority.go +559 -0
  216. package/dist/templates/native-go/backend/internal/helper/sdk_grant_repository_linux.go +417 -0
  217. package/dist/templates/native-go/backend/internal/helper/sdk_grant_snapshot.go +94 -0
  218. package/dist/templates/native-go/backend/internal/helper/sdk_history.go +80 -0
  219. package/dist/templates/native-go/backend/internal/helper/sdk_history_test.go +76 -0
  220. package/dist/templates/native-go/backend/internal/helper/sdk_job.go +697 -0
  221. package/dist/templates/native-go/backend/internal/helper/sdk_job_child_linux.go +309 -0
  222. package/dist/templates/native-go/backend/internal/helper/sdk_job_contract.go +122 -0
  223. package/dist/templates/native-go/backend/internal/helper/sdk_job_linux_test.go +159 -0
  224. package/dist/templates/native-go/backend/internal/helper/sdk_job_process_linux.go +327 -0
  225. package/dist/templates/native-go/backend/internal/helper/sdk_job_test.go +501 -0
  226. package/dist/templates/native-go/backend/internal/helper/sdk_job_vm_linux_test.go +343 -0
  227. package/dist/templates/native-go/backend/internal/helper/sdk_journal.go +77 -0
  228. package/dist/templates/native-go/backend/internal/helper/sdk_journal_linux.go +244 -0
  229. package/dist/templates/native-go/backend/internal/helper/sdk_journal_linux_test.go +295 -0
  230. package/dist/templates/native-go/backend/internal/helper/sdk_journal_test.go +71 -0
  231. package/dist/templates/native-go/backend/internal/helper/sdk_picker_test.go +50 -0
  232. package/dist/templates/native-go/backend/internal/helper/sdk_process_linux.go +184 -0
  233. package/dist/templates/native-go/backend/internal/helper/sdk_public_vm_linux_test.go +129 -0
  234. package/dist/templates/native-go/backend/internal/helper/sdk_relaxed_invalidation.go +242 -0
  235. package/dist/templates/native-go/backend/internal/helper/sdk_rpc.go +299 -0
  236. package/dist/templates/native-go/backend/internal/helper/sdk_rpc_contract.go +70 -0
  237. package/dist/templates/native-go/backend/internal/helper/sdk_rpc_test.go +135 -0
  238. package/dist/templates/native-go/backend/internal/helper/sdk_server_linux.go +152 -0
  239. package/dist/templates/native-go/backend/internal/helper/sdk_session.go +677 -0
  240. package/dist/templates/native-go/backend/internal/helper/sdk_session_contract.go +72 -0
  241. package/dist/templates/native-go/backend/internal/helper/sdk_session_fence_test.go +215 -0
  242. package/dist/templates/native-go/backend/internal/helper/sdk_session_test.go +475 -0
  243. package/dist/templates/native-go/backend/internal/helper/sdk_supervisor_frame.go +78 -0
  244. package/dist/templates/native-go/backend/internal/helper/sdk_supervisor_linux.go +414 -0
  245. package/dist/templates/native-go/backend/internal/helper/sdk_transport.go +79 -0
  246. package/dist/templates/native-go/backend/internal/helper/sdk_transport_linux.go +82 -0
  247. package/dist/templates/native-go/backend/internal/helper/sdk_transport_test.go +64 -0
  248. package/dist/templates/native-go/backend/internal/helper/server_linux.go +3 -0
  249. package/dist/templates/native-go/backend/internal/helper/stale_management_linux_test.go +126 -0
  250. package/dist/templates/native-go/backend/internal/helper/stale_management_test.go +122 -0
  251. package/dist/templates/native-go/backend/internal/helper/startup_diagnostic.go +68 -0
  252. package/dist/templates/native-go/backend/internal/helper/startup_diagnostic_linux_test.go +126 -0
  253. package/dist/templates/native-go/backend/internal/helper/startup_diagnostic_test.go +117 -0
  254. package/dist/templates/native-go/backend/internal/helper/status.go +22 -13
  255. package/dist/templates/native-go/backend/internal/helper/status_test.go +45 -0
  256. package/dist/templates/native-go/backend/internal/helper/supervision.go +1 -1
  257. package/dist/templates/native-go/backend/internal/helper/supervisor_frame.go +3 -0
  258. package/dist/templates/native-go/backend/internal/helper/supervisor_linux.go +6 -2
  259. package/dist/templates/native-go/backend/internal/helper/unit_connection_test.go +22 -4
  260. package/dist/templates/native-go/backend/internal/helper/unit_linux.go +7 -3
  261. package/dist/templates/native-go/backend/internal/helper/unit_query_linux.go +5 -1
  262. package/dist/templates/native-go/backend/internal/helper/write_files_linux.go +7 -4
  263. package/dist/templates/native-go/backend/internal/helper/write_files_linux_test.go +26 -0
  264. package/dist/templates/native-go/dsm-package.yaml +1 -1
  265. package/dist/templates/native-go-background/BACKGROUND.md +111 -0
  266. package/dist/templates/native-go-background/backend/internal/app/background_on.go +7 -0
  267. package/dist/templates/native-go-background/backend/internal/app/background_routes_test.go +32 -0
  268. package/dist/templates/native-go-background/frontend/src/background/BackgroundPanel.vue +178 -0
  269. package/dist/templates/native-go-background/frontend/src/background/i18n/de.json +83 -0
  270. package/dist/templates/native-go-background/frontend/src/background/i18n/en.json +83 -0
  271. package/dist/templates/native-go-background/frontend/src/background/i18n/es.json +83 -0
  272. package/dist/templates/native-go-background/frontend/src/background/i18n/fr.json +83 -0
  273. package/dist/templates/native-go-background/frontend/src/background/i18n/it.json +83 -0
  274. package/dist/templates/native-go-background/frontend/src/background/i18n/ja.json +83 -0
  275. package/dist/templates/native-go-background/frontend/src/background/i18n/ko.json +83 -0
  276. package/dist/templates/native-go-background/frontend/src/background/i18n/zh-CN.json +83 -0
  277. package/dist/templates/native-go-background/frontend/src/background/i18n/zh-TW.json +83 -0
  278. package/dist/templates/native-go-background/frontend/src/background/i18n.ts +19 -0
  279. package/dist/templates/native-go-background/frontend/src/background/picker-provider.ts +13 -0
  280. package/dist/templates/native-go-background/frontend/test/background.test.ts +179 -0
  281. package/dist/templates/native-go-integration/backend/internal/app/personal.go +2 -2
  282. package/dist/templates/native-go-integration/backend/internal/app/personal_test.go +37 -0
  283. package/dist/templates/native-go-vue/README.md +38 -7
  284. package/dist/templates/native-go-vue/frontend/DESIGN.md +15 -3
  285. package/dist/templates/native-go-vue/frontend/README-JOBS.md +75 -0
  286. package/dist/templates/native-go-vue/frontend/README-M2.md +64 -0
  287. package/dist/templates/native-go-vue/frontend/package-lock.json +5 -4
  288. package/dist/templates/native-go-vue/frontend/package.json +1 -1
  289. package/dist/templates/native-go-vue/frontend/src/App.vue +39 -11
  290. package/dist/templates/native-go-vue/frontend/src/M2App.vue +57 -0
  291. package/dist/templates/native-go-vue/frontend/src/SDKApp.vue +203 -0
  292. package/dist/templates/native-go-vue/frontend/src/jobs/InteractiveJobForm.vue +70 -0
  293. package/dist/templates/native-go-vue/frontend/src/jobs/JobsAdminPanel.vue +33 -0
  294. package/dist/templates/native-go-vue/frontend/src/jobs/JobsPanel.vue +135 -0
  295. package/dist/templates/native-go-vue/frontend/src/jobs/connected-provider.ts +179 -0
  296. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/de.json +62 -0
  297. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/en.json +62 -0
  298. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/es.json +62 -0
  299. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/fr.json +62 -0
  300. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/it.json +62 -0
  301. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/ja.json +62 -0
  302. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/ko.json +62 -0
  303. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/zh-CN.json +62 -0
  304. package/dist/templates/native-go-vue/frontend/src/jobs/i18n/zh-TW.json +62 -0
  305. package/dist/templates/native-go-vue/frontend/src/jobs/i18n.ts +15 -0
  306. package/dist/templates/native-go-vue/frontend/src/jobs/mock-provider.ts +67 -0
  307. package/dist/templates/native-go-vue/frontend/src/jobs/provider.ts +60 -0
  308. package/dist/templates/native-go-vue/frontend/src/jobs/validate.ts +44 -0
  309. package/dist/templates/native-go-vue/frontend/src/m2-main.ts +21 -0
  310. package/dist/templates/native-go-vue/frontend/src/m2-style.css +7 -0
  311. package/dist/templates/native-go-vue/frontend/src/nas/M2Files.vue +94 -0
  312. package/dist/templates/native-go-vue/frontend/src/nas/M2PathPicker.vue +70 -0
  313. package/dist/templates/native-go-vue/frontend/src/nas/M2Settings.vue +69 -0
  314. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/de.json +56 -0
  315. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/en.json +56 -0
  316. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/es.json +56 -0
  317. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/fr.json +56 -0
  318. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/it.json +56 -0
  319. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/ja.json +56 -0
  320. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/ko.json +56 -0
  321. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-CN.json +56 -0
  322. package/dist/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-TW.json +56 -0
  323. package/dist/templates/native-go-vue/frontend/src/nas/m2-contract.ts +33 -0
  324. package/dist/templates/native-go-vue/frontend/src/nas/m2-i18n.ts +24 -0
  325. package/dist/templates/native-go-vue/frontend/src/nas/m2-provider.ts +104 -0
  326. package/dist/templates/native-go-vue/frontend/src/nas/use-m2-request.ts +18 -0
  327. package/dist/templates/native-go-vue/frontend/src/sdk-main.ts +39 -0
  328. package/dist/templates/native-go-vue/frontend/src/shell/AppShell.vue +48 -0
  329. package/dist/templates/native-go-vue/frontend/src/shell/i18n/de.json +10 -0
  330. package/dist/templates/native-go-vue/frontend/src/shell/i18n/en.json +10 -0
  331. package/dist/templates/native-go-vue/frontend/src/shell/i18n/es.json +10 -0
  332. package/dist/templates/native-go-vue/frontend/src/shell/i18n/fr.json +10 -0
  333. package/dist/templates/native-go-vue/frontend/src/shell/i18n/it.json +10 -0
  334. package/dist/templates/native-go-vue/frontend/src/shell/i18n/ja.json +10 -0
  335. package/dist/templates/native-go-vue/frontend/src/shell/i18n/ko.json +10 -0
  336. package/dist/templates/native-go-vue/frontend/src/shell/i18n/zh-CN.json +10 -0
  337. package/dist/templates/native-go-vue/frontend/src/shell/i18n/zh-TW.json +10 -0
  338. package/dist/templates/native-go-vue/frontend/src/shell/i18n.ts +17 -0
  339. package/dist/templates/native-go-vue/frontend/src/shell/pages.ts +34 -0
  340. package/dist/templates/native-go-vue/frontend/src/style.css +2 -6
  341. package/dist/templates/native-go-vue/frontend/test/apps.test.ts +21 -0
  342. package/dist/templates/native-go-vue/frontend/test/jobs-connected.test.ts +163 -0
  343. package/dist/templates/native-go-vue/frontend/test/jobs-preview.html +22 -0
  344. package/dist/templates/native-go-vue/frontend/test/jobs.test.ts +176 -0
  345. package/dist/templates/native-go-vue/frontend/test/m2-preview.html +27 -0
  346. package/dist/templates/native-go-vue/frontend/test/m2-provider.test.ts +87 -0
  347. package/dist/templates/native-go-vue/frontend/test/m2-ui.test.ts +209 -0
  348. package/dist/templates/native-go-vue/frontend/test/native-controls.test.ts +27 -0
  349. package/dist/templates/native-go-vue/frontend/test/picker-wire.test.ts +110 -0
  350. package/dist/templates/native-go-vue/frontend/test/shell-preview.html +19 -0
  351. package/dist/templates/native-go-vue/frontend/test/shell-sdk.test.ts +73 -0
  352. package/dist/templates/native-go-vue/frontend/test/shell-ui.test.ts +114 -0
  353. package/dist/templates/native-go-vue/frontend/test/shell.test.ts +45 -0
  354. package/dist/templates/native-go-vue/frontend/vite.config.ts +2 -2
  355. package/dist/validate.js +6 -3
  356. package/package.json +1 -1
  357. package/schema/synology-app.schema.json +19 -0
  358. package/skills/reference/create.md +4 -0
  359. package/templates/_daemon/go.mod +2 -0
  360. package/templates/_gateway/auth.go +101 -0
  361. package/templates/_gateway/auth_test.go +216 -0
  362. package/templates/_gateway/cgi.go +133 -0
  363. package/templates/_gateway/cgi_test.go +156 -0
  364. package/templates/_gateway/csrf.go +73 -0
  365. package/templates/_gateway/csrf_test.go +155 -0
  366. package/templates/_gateway/directory.go +108 -0
  367. package/templates/_gateway/directory_test.go +202 -0
  368. package/templates/_gateway/gateway.go +412 -0
  369. package/templates/_gateway/gateway_test.go +676 -0
  370. package/templates/_gateway/go.mod +3 -0
  371. package/templates/_gateway/groups.go +66 -0
  372. package/templates/_gateway/main.go +45 -0
  373. package/templates/binary/synology-app.yaml +1 -1
  374. package/templates/compose-import/compose.yaml +1 -1
  375. package/templates/compose-import/synology-app.yaml +1 -1
  376. package/templates/hello-files/compose.yaml +1 -1
  377. package/templates/hello-files/synology-app.yaml +1 -1
  378. package/templates/hello-web/compose.yaml +5 -2
  379. package/templates/hello-web/synology-app.yaml +4 -1
  380. package/templates/hello-web-page/compose.yaml +5 -2
  381. package/templates/hello-web-page/synology-app.yaml +4 -1
  382. package/templates/native-go/README.md +93 -4
  383. package/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +3 -1
  384. package/templates/native-go/backend/cmd/app/main.go +17 -0
  385. package/templates/native-go/backend/cmd/app/sdk_main.go +60 -0
  386. package/templates/native-go/backend/cmd/background-worker/main.go +38 -0
  387. package/templates/native-go/backend/cmd/helper/main.go +10 -1
  388. package/templates/native-go/backend/cmd/helper/sdk_registry.go +19 -0
  389. package/templates/native-go/backend/go.mod +5 -3
  390. package/templates/native-go/backend/go.sum +4 -4
  391. package/templates/native-go/backend/internal/api/registry.go +17 -6
  392. package/templates/native-go/backend/internal/api/server.go +7 -1
  393. package/templates/native-go/backend/internal/app/background.go +270 -0
  394. package/templates/native-go/backend/internal/app/background_none.go +8 -0
  395. package/templates/native-go/backend/internal/app/background_owner.go +59 -0
  396. package/templates/native-go/backend/internal/app/background_owner_test.go +145 -0
  397. package/templates/native-go/backend/internal/app/background_schedule.go +74 -0
  398. package/templates/native-go/backend/internal/app/background_schedule_test.go +62 -0
  399. package/templates/native-go/backend/internal/app/background_test.go +346 -0
  400. package/templates/native-go/backend/internal/app/integration_state.go +16 -0
  401. package/templates/native-go/backend/internal/app/migrations.go +41 -0
  402. package/templates/native-go/backend/internal/app/migrations_test.go +41 -0
  403. package/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +8 -0
  404. package/templates/native-go/backend/internal/app/routes.go +17 -3
  405. package/templates/native-go/backend/internal/app/routes_test.go +20 -3
  406. package/templates/native-go/backend/internal/app/sdk_jobs.go +70 -0
  407. package/templates/native-go/backend/internal/app/sdk_jobs_test.go +116 -0
  408. package/templates/native-go/backend/internal/app/sdk_routes.go +174 -0
  409. package/templates/native-go/backend/internal/app/session_files.go +15 -0
  410. package/templates/native-go/backend/internal/app/session_files_test.go +26 -0
  411. package/templates/native-go/backend/internal/app/shared_folder.go +144 -0
  412. package/templates/native-go/backend/internal/app/shared_folder_test.go +158 -0
  413. package/templates/native-go/backend/internal/background/access.go +57 -0
  414. package/templates/native-go/backend/internal/background/owner_test.go +126 -0
  415. package/templates/native-go/backend/internal/background/runner.go +185 -0
  416. package/templates/native-go/backend/internal/background/runner_test.go +209 -0
  417. package/templates/native-go/backend/internal/background/schedule.go +300 -0
  418. package/templates/native-go/backend/internal/background/schedule_test.go +335 -0
  419. package/templates/native-go/backend/internal/background/store.go +807 -0
  420. package/templates/native-go/backend/internal/background/store_test.go +407 -0
  421. package/templates/native-go/backend/internal/datamigrate/migrate.go +191 -0
  422. package/templates/native-go/backend/internal/datamigrate/migrate_test.go +177 -0
  423. package/templates/native-go/backend/internal/filestation/browse_test.go +67 -0
  424. package/templates/native-go/backend/internal/filestation/client.go +251 -0
  425. package/templates/native-go/backend/internal/filestation/client_test.go +155 -0
  426. package/templates/native-go/backend/internal/filestation/doc.go +4 -0
  427. package/templates/native-go/backend/internal/filestation/read_file_test.go +90 -0
  428. package/templates/native-go/backend/internal/filestation/repository.go +207 -0
  429. package/templates/native-go/backend/internal/filestation/repository_test.go +104 -0
  430. package/templates/native-go/backend/internal/filestation/sdk_session.go +241 -0
  431. package/templates/native-go/backend/internal/filestation/sdk_session_test.go +183 -0
  432. package/templates/native-go/backend/internal/filestation/service.go +254 -0
  433. package/templates/native-go/backend/internal/filestation/service_test.go +94 -0
  434. package/templates/native-go/backend/internal/filestation/session_semantics_test.go +383 -0
  435. package/templates/native-go/backend/internal/filestation/write.go +72 -0
  436. package/templates/native-go/backend/internal/filestation/write_test.go +123 -0
  437. package/templates/native-go/backend/internal/helper/background_proof.go +163 -0
  438. package/templates/native-go/backend/internal/helper/background_proof_contract.go +46 -0
  439. package/templates/native-go/backend/internal/helper/background_proof_test.go +161 -0
  440. package/templates/native-go/backend/internal/helper/data_contract.go +3 -0
  441. package/templates/native-go/backend/internal/helper/data_protocol.go +3 -0
  442. package/templates/native-go/backend/internal/helper/data_protocol_test.go +1 -1
  443. package/templates/native-go/backend/internal/helper/grant_authority.go +3 -0
  444. package/templates/native-go/backend/internal/helper/grant_authority_test.go +1 -1
  445. package/templates/native-go/backend/internal/helper/grant_repository_linux.go +2 -1
  446. package/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +4 -3
  447. package/templates/native-go/backend/internal/helper/grant_snapshot.go +3 -0
  448. package/templates/native-go/backend/internal/helper/jobcontract/bindings.go +48 -0
  449. package/templates/native-go/backend/internal/helper/jobcontract/contract_test.go +436 -0
  450. package/templates/native-go/backend/internal/helper/jobcontract/decode.go +185 -0
  451. package/templates/native-go/backend/internal/helper/jobcontract/digest.go +55 -0
  452. package/templates/native-go/backend/internal/helper/jobcontract/registry.go +85 -0
  453. package/templates/native-go/backend/internal/helper/jobcontract/registry_test.go +73 -0
  454. package/templates/native-go/backend/internal/helper/jobcontract/result.go +53 -0
  455. package/templates/native-go/backend/internal/helper/jobcontract/stub.go +8 -0
  456. package/templates/native-go/backend/internal/helper/jobcontract/testdata/input-digests.json +127 -0
  457. package/templates/native-go/backend/internal/helper/jobcontract/types.go +234 -0
  458. package/templates/native-go/backend/internal/helper/jobcontract/types_test.go +29 -0
  459. package/templates/native-go/backend/internal/helper/jobcontract/validate.go +462 -0
  460. package/templates/native-go/backend/internal/helper/legacy_authority_schema_linux_test.go +34 -0
  461. package/templates/native-go/backend/internal/helper/legacy_authority_schema_test.go +6 -0
  462. package/templates/native-go/backend/internal/helper/management.go +79 -0
  463. package/templates/native-go/backend/internal/helper/observation.go +42 -2
  464. package/templates/native-go/backend/internal/helper/observation_health_test.go +13 -1
  465. package/templates/native-go/backend/internal/helper/observer_diagnostic.go +56 -10
  466. package/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +6 -0
  467. package/templates/native-go/backend/internal/helper/observer_diagnostic_writer.go +40 -0
  468. package/templates/native-go/backend/internal/helper/process_linux.go +3 -0
  469. package/templates/native-go/backend/internal/helper/query_deadline_linux_test.go +115 -0
  470. package/templates/native-go/backend/internal/helper/query_pending_diagnostic_test.go +254 -0
  471. package/templates/native-go/backend/internal/helper/relaxed_invalidation.go +3 -0
  472. package/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +23 -4
  473. package/templates/native-go/backend/internal/helper/sdk_assembly_linux.go +51 -0
  474. package/templates/native-go/backend/internal/helper/sdk_attach.go +83 -0
  475. package/templates/native-go/backend/internal/helper/sdk_attach_contract.go +32 -0
  476. package/templates/native-go/backend/internal/helper/sdk_attach_test.go +184 -0
  477. package/templates/native-go/backend/internal/helper/sdk_authority_schema_test.go +6 -0
  478. package/templates/native-go/backend/internal/helper/sdk_background_authority.go +832 -0
  479. package/templates/native-go/backend/internal/helper/sdk_background_authority_test.go +714 -0
  480. package/templates/native-go/backend/internal/helper/sdk_background_invalidation.go +218 -0
  481. package/templates/native-go/backend/internal/helper/sdk_background_lease.go +218 -0
  482. package/templates/native-go/backend/internal/helper/sdk_background_snapshot.go +110 -0
  483. package/templates/native-go/backend/internal/helper/sdk_background_store_linux_test.go +261 -0
  484. package/templates/native-go/backend/internal/helper/sdk_background_store_test.go +58 -0
  485. package/templates/native-go/backend/internal/helper/sdk_bindings.go +60 -0
  486. package/templates/native-go/backend/internal/helper/sdk_data_contract.go +251 -0
  487. package/templates/native-go/backend/internal/helper/sdk_data_protocol.go +424 -0
  488. package/templates/native-go/backend/internal/helper/sdk_dispatch_absence_test.go +51 -0
  489. package/templates/native-go/backend/internal/helper/sdk_display.go +488 -0
  490. package/templates/native-go/backend/internal/helper/sdk_display_contract.go +121 -0
  491. package/templates/native-go/backend/internal/helper/sdk_display_test.go +459 -0
  492. package/templates/native-go/backend/internal/helper/sdk_grant_authority.go +559 -0
  493. package/templates/native-go/backend/internal/helper/sdk_grant_repository_linux.go +417 -0
  494. package/templates/native-go/backend/internal/helper/sdk_grant_snapshot.go +94 -0
  495. package/templates/native-go/backend/internal/helper/sdk_history.go +80 -0
  496. package/templates/native-go/backend/internal/helper/sdk_history_test.go +76 -0
  497. package/templates/native-go/backend/internal/helper/sdk_job.go +697 -0
  498. package/templates/native-go/backend/internal/helper/sdk_job_child_linux.go +309 -0
  499. package/templates/native-go/backend/internal/helper/sdk_job_contract.go +122 -0
  500. package/templates/native-go/backend/internal/helper/sdk_job_linux_test.go +159 -0
  501. package/templates/native-go/backend/internal/helper/sdk_job_process_linux.go +327 -0
  502. package/templates/native-go/backend/internal/helper/sdk_job_test.go +501 -0
  503. package/templates/native-go/backend/internal/helper/sdk_job_vm_linux_test.go +343 -0
  504. package/templates/native-go/backend/internal/helper/sdk_journal.go +77 -0
  505. package/templates/native-go/backend/internal/helper/sdk_journal_linux.go +244 -0
  506. package/templates/native-go/backend/internal/helper/sdk_journal_linux_test.go +295 -0
  507. package/templates/native-go/backend/internal/helper/sdk_journal_test.go +71 -0
  508. package/templates/native-go/backend/internal/helper/sdk_picker_test.go +50 -0
  509. package/templates/native-go/backend/internal/helper/sdk_process_linux.go +184 -0
  510. package/templates/native-go/backend/internal/helper/sdk_public_vm_linux_test.go +129 -0
  511. package/templates/native-go/backend/internal/helper/sdk_relaxed_invalidation.go +242 -0
  512. package/templates/native-go/backend/internal/helper/sdk_rpc.go +299 -0
  513. package/templates/native-go/backend/internal/helper/sdk_rpc_contract.go +70 -0
  514. package/templates/native-go/backend/internal/helper/sdk_rpc_test.go +135 -0
  515. package/templates/native-go/backend/internal/helper/sdk_server_linux.go +152 -0
  516. package/templates/native-go/backend/internal/helper/sdk_session.go +677 -0
  517. package/templates/native-go/backend/internal/helper/sdk_session_contract.go +72 -0
  518. package/templates/native-go/backend/internal/helper/sdk_session_fence_test.go +215 -0
  519. package/templates/native-go/backend/internal/helper/sdk_session_test.go +475 -0
  520. package/templates/native-go/backend/internal/helper/sdk_supervisor_frame.go +78 -0
  521. package/templates/native-go/backend/internal/helper/sdk_supervisor_linux.go +414 -0
  522. package/templates/native-go/backend/internal/helper/sdk_transport.go +79 -0
  523. package/templates/native-go/backend/internal/helper/sdk_transport_linux.go +82 -0
  524. package/templates/native-go/backend/internal/helper/sdk_transport_test.go +64 -0
  525. package/templates/native-go/backend/internal/helper/server_linux.go +3 -0
  526. package/templates/native-go/backend/internal/helper/stale_management_linux_test.go +126 -0
  527. package/templates/native-go/backend/internal/helper/stale_management_test.go +122 -0
  528. package/templates/native-go/backend/internal/helper/startup_diagnostic.go +68 -0
  529. package/templates/native-go/backend/internal/helper/startup_diagnostic_linux_test.go +126 -0
  530. package/templates/native-go/backend/internal/helper/startup_diagnostic_test.go +117 -0
  531. package/templates/native-go/backend/internal/helper/status.go +22 -13
  532. package/templates/native-go/backend/internal/helper/status_test.go +45 -0
  533. package/templates/native-go/backend/internal/helper/supervision.go +1 -1
  534. package/templates/native-go/backend/internal/helper/supervisor_frame.go +3 -0
  535. package/templates/native-go/backend/internal/helper/supervisor_linux.go +6 -2
  536. package/templates/native-go/backend/internal/helper/unit_connection_test.go +22 -4
  537. package/templates/native-go/backend/internal/helper/unit_linux.go +7 -3
  538. package/templates/native-go/backend/internal/helper/unit_query_linux.go +5 -1
  539. package/templates/native-go/backend/internal/helper/write_files_linux.go +7 -4
  540. package/templates/native-go/backend/internal/helper/write_files_linux_test.go +26 -0
  541. package/templates/native-go/dsm-package.yaml +1 -1
  542. package/templates/native-go-background/BACKGROUND.md +111 -0
  543. package/templates/native-go-background/backend/internal/app/background_on.go +7 -0
  544. package/templates/native-go-background/backend/internal/app/background_routes_test.go +32 -0
  545. package/templates/native-go-background/frontend/src/background/BackgroundPanel.vue +178 -0
  546. package/templates/native-go-background/frontend/src/background/i18n/de.json +83 -0
  547. package/templates/native-go-background/frontend/src/background/i18n/en.json +83 -0
  548. package/templates/native-go-background/frontend/src/background/i18n/es.json +83 -0
  549. package/templates/native-go-background/frontend/src/background/i18n/fr.json +83 -0
  550. package/templates/native-go-background/frontend/src/background/i18n/it.json +83 -0
  551. package/templates/native-go-background/frontend/src/background/i18n/ja.json +83 -0
  552. package/templates/native-go-background/frontend/src/background/i18n/ko.json +83 -0
  553. package/templates/native-go-background/frontend/src/background/i18n/zh-CN.json +83 -0
  554. package/templates/native-go-background/frontend/src/background/i18n/zh-TW.json +83 -0
  555. package/templates/native-go-background/frontend/src/background/i18n.ts +19 -0
  556. package/templates/native-go-background/frontend/src/background/picker-provider.ts +13 -0
  557. package/templates/native-go-background/frontend/test/background.test.ts +179 -0
  558. package/templates/native-go-integration/backend/internal/app/personal.go +2 -2
  559. package/templates/native-go-integration/backend/internal/app/personal_test.go +37 -0
  560. package/templates/native-go-vue/README.md +38 -7
  561. package/templates/native-go-vue/frontend/DESIGN.md +15 -3
  562. package/templates/native-go-vue/frontend/README-JOBS.md +75 -0
  563. package/templates/native-go-vue/frontend/README-M2.md +64 -0
  564. package/templates/native-go-vue/frontend/package-lock.json +5 -4
  565. package/templates/native-go-vue/frontend/package.json +1 -1
  566. package/templates/native-go-vue/frontend/src/App.vue +39 -11
  567. package/templates/native-go-vue/frontend/src/M2App.vue +57 -0
  568. package/templates/native-go-vue/frontend/src/SDKApp.vue +203 -0
  569. package/templates/native-go-vue/frontend/src/jobs/InteractiveJobForm.vue +70 -0
  570. package/templates/native-go-vue/frontend/src/jobs/JobsAdminPanel.vue +33 -0
  571. package/templates/native-go-vue/frontend/src/jobs/JobsPanel.vue +135 -0
  572. package/templates/native-go-vue/frontend/src/jobs/connected-provider.ts +179 -0
  573. package/templates/native-go-vue/frontend/src/jobs/i18n/de.json +62 -0
  574. package/templates/native-go-vue/frontend/src/jobs/i18n/en.json +62 -0
  575. package/templates/native-go-vue/frontend/src/jobs/i18n/es.json +62 -0
  576. package/templates/native-go-vue/frontend/src/jobs/i18n/fr.json +62 -0
  577. package/templates/native-go-vue/frontend/src/jobs/i18n/it.json +62 -0
  578. package/templates/native-go-vue/frontend/src/jobs/i18n/ja.json +62 -0
  579. package/templates/native-go-vue/frontend/src/jobs/i18n/ko.json +62 -0
  580. package/templates/native-go-vue/frontend/src/jobs/i18n/zh-CN.json +62 -0
  581. package/templates/native-go-vue/frontend/src/jobs/i18n/zh-TW.json +62 -0
  582. package/templates/native-go-vue/frontend/src/jobs/i18n.ts +15 -0
  583. package/templates/native-go-vue/frontend/src/jobs/mock-provider.ts +67 -0
  584. package/templates/native-go-vue/frontend/src/jobs/provider.ts +60 -0
  585. package/templates/native-go-vue/frontend/src/jobs/validate.ts +44 -0
  586. package/templates/native-go-vue/frontend/src/m2-main.ts +21 -0
  587. package/templates/native-go-vue/frontend/src/m2-style.css +7 -0
  588. package/templates/native-go-vue/frontend/src/nas/M2Files.vue +94 -0
  589. package/templates/native-go-vue/frontend/src/nas/M2PathPicker.vue +70 -0
  590. package/templates/native-go-vue/frontend/src/nas/M2Settings.vue +69 -0
  591. package/templates/native-go-vue/frontend/src/nas/i18n/m2/de.json +56 -0
  592. package/templates/native-go-vue/frontend/src/nas/i18n/m2/en.json +56 -0
  593. package/templates/native-go-vue/frontend/src/nas/i18n/m2/es.json +56 -0
  594. package/templates/native-go-vue/frontend/src/nas/i18n/m2/fr.json +56 -0
  595. package/templates/native-go-vue/frontend/src/nas/i18n/m2/it.json +56 -0
  596. package/templates/native-go-vue/frontend/src/nas/i18n/m2/ja.json +56 -0
  597. package/templates/native-go-vue/frontend/src/nas/i18n/m2/ko.json +56 -0
  598. package/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-CN.json +56 -0
  599. package/templates/native-go-vue/frontend/src/nas/i18n/m2/zh-TW.json +56 -0
  600. package/templates/native-go-vue/frontend/src/nas/m2-contract.ts +33 -0
  601. package/templates/native-go-vue/frontend/src/nas/m2-i18n.ts +24 -0
  602. package/templates/native-go-vue/frontend/src/nas/m2-provider.ts +104 -0
  603. package/templates/native-go-vue/frontend/src/nas/use-m2-request.ts +18 -0
  604. package/templates/native-go-vue/frontend/src/sdk-main.ts +39 -0
  605. package/templates/native-go-vue/frontend/src/shell/AppShell.vue +48 -0
  606. package/templates/native-go-vue/frontend/src/shell/i18n/de.json +10 -0
  607. package/templates/native-go-vue/frontend/src/shell/i18n/en.json +10 -0
  608. package/templates/native-go-vue/frontend/src/shell/i18n/es.json +10 -0
  609. package/templates/native-go-vue/frontend/src/shell/i18n/fr.json +10 -0
  610. package/templates/native-go-vue/frontend/src/shell/i18n/it.json +10 -0
  611. package/templates/native-go-vue/frontend/src/shell/i18n/ja.json +10 -0
  612. package/templates/native-go-vue/frontend/src/shell/i18n/ko.json +10 -0
  613. package/templates/native-go-vue/frontend/src/shell/i18n/zh-CN.json +10 -0
  614. package/templates/native-go-vue/frontend/src/shell/i18n/zh-TW.json +10 -0
  615. package/templates/native-go-vue/frontend/src/shell/i18n.ts +17 -0
  616. package/templates/native-go-vue/frontend/src/shell/pages.ts +34 -0
  617. package/templates/native-go-vue/frontend/src/style.css +2 -6
  618. package/templates/native-go-vue/frontend/test/apps.test.ts +21 -0
  619. package/templates/native-go-vue/frontend/test/jobs-connected.test.ts +163 -0
  620. package/templates/native-go-vue/frontend/test/jobs-preview.html +22 -0
  621. package/templates/native-go-vue/frontend/test/jobs.test.ts +176 -0
  622. package/templates/native-go-vue/frontend/test/m2-preview.html +27 -0
  623. package/templates/native-go-vue/frontend/test/m2-provider.test.ts +87 -0
  624. package/templates/native-go-vue/frontend/test/m2-ui.test.ts +209 -0
  625. package/templates/native-go-vue/frontend/test/native-controls.test.ts +27 -0
  626. package/templates/native-go-vue/frontend/test/picker-wire.test.ts +110 -0
  627. package/templates/native-go-vue/frontend/test/shell-preview.html +19 -0
  628. package/templates/native-go-vue/frontend/test/shell-sdk.test.ts +73 -0
  629. package/templates/native-go-vue/frontend/test/shell-ui.test.ts +114 -0
  630. package/templates/native-go-vue/frontend/test/shell.test.ts +45 -0
  631. package/templates/native-go-vue/frontend/vite.config.ts +2 -2
@@ -1,3 +1,6 @@
1
+ //go:build !synopkgland_sdk_workers
2
+
3
+ //line dsmapp/internal/helper/supervisor_linux.go:1
1
4
  package helper
2
5
 
3
6
  import (
@@ -88,7 +91,8 @@ func superviseLinux(c Client, binary string) error {
88
91
  defer cancelWatcher()
89
92
  go o.watch(watcher)
90
93
  epoch := r.Lifecycle.Epoch
91
- defer persistObserverDiagnostic(c, epoch, o.gate)
94
+ stopDiagnostics := startObserverDiagnostics(c, epoch, o.gate)
95
+ defer stopDiagnostics()
92
96
  identity, err := inspectSupervisor(os.Getpid(), c.Expected)
93
97
  if err != nil {
94
98
  return err
@@ -147,7 +151,7 @@ func superviseLinux(c Client, binary string) error {
147
151
  var code Code
148
152
  grants, grantRepo, code = openSupervisorGrants(c, binary, cohort)
149
153
  if code != "" {
150
- o.gate.fence("grant-authority-unavailable")
154
+ o.gate.fenceStartup("grants-open", code)
151
155
  }
152
156
  }
153
157
  fenceRetryExhausted := false
@@ -7,6 +7,8 @@ import (
7
7
  "io"
8
8
  "net"
9
9
  "testing"
10
+
11
+ "github.com/godbus/dbus/v5"
10
12
  )
11
13
 
12
14
  type observerClosedReader struct{ *bytes.Reader }
@@ -33,18 +35,34 @@ func (s *observerTestStream) Write(p []byte) (int, error) {
33
35
  }
34
36
  func (s *observerTestStream) Close() error { return nil }
35
37
 
36
- func TestObserverDBusFrameCloseReturnsError(t *testing.T) {
38
+ // Cover the dependency directly as well as the production recovery boundary.
39
+ // Canonical frames avoid EncodeTo's map-order-dependent header alignment.
40
+ func TestDBusClosedHeaderPaddingReturnsErrorWithoutPanic(t *testing.T) {
37
41
  for _, order := range []binary.ByteOrder{binary.LittleEndian, binary.BigEndian} {
38
42
  t.Run(order.String(), func(t *testing.T) {
39
43
  packet, header := observerPaddedFrame(t, order)
44
+ defer func() {
45
+ if failure := recover(); failure != nil {
46
+ t.Fatalf("closed socket during header alignment panicked: %v", failure)
47
+ }
48
+ }()
49
+ msg, err := dbus.DecodeMessage(observerClosedReader{bytes.NewReader(packet[:header])})
50
+ if msg != nil || !errors.Is(err, net.ErrClosed) {
51
+ t.Fatalf("partial frame accepted or close error lost: %+v %v", msg, err)
52
+ }
53
+ })
54
+ }
55
+ }
56
+
57
+ func TestObserverDBusFrameCloseReturnsError(t *testing.T) {
58
+ for _, order := range []binary.ByteOrder{binary.LittleEndian, binary.BigEndian} {
59
+ t.Run(order.String(), func(t *testing.T) {
60
+ packet, _ := observerPaddedFrame(t, order)
40
61
  for end := 0; end < len(packet); end++ {
41
62
  frame, err := readObserverDBusFrame(observerClosedReader{bytes.NewReader(packet[:end])})
42
63
  if frame != nil || !errors.Is(err, net.ErrClosed) {
43
64
  t.Fatalf("close at byte %d: partial frame %x error %v", end, frame, err)
44
65
  }
45
- if end == header && !errors.Is(err, errObserverDBusDecode) {
46
- t.Fatal("fixture did not exercise upstream padding panic recovery")
47
- }
48
66
  }
49
67
  })
50
68
  }
@@ -17,6 +17,9 @@ import (
17
17
  "github.com/godbus/dbus/v5"
18
18
  )
19
19
 
20
+ const unitQueryTimeout = 500 * time.Millisecond
21
+ const unitProbeInterval = 250 * time.Millisecond
22
+
20
23
  const systemdName = "org.freedesktop.systemd1"
21
24
  const managerInterface = systemdName + ".Manager"
22
25
  const unitInterface = systemdName + ".Unit"
@@ -222,7 +225,7 @@ func jobID(v dbus.Variant) (uint32, bool) {
222
225
  }
223
226
 
224
227
  func openUnitObserver(parent context.Context, i Inventory) (*unitObserver, error) {
225
- ctx, cancel := context.WithTimeout(parent, 500*time.Millisecond)
228
+ ctx, cancel := context.WithTimeout(parent, unitQueryTimeout)
226
229
  defer cancel()
227
230
  binding, err := installedBinding(i)
228
231
  if err != nil {
@@ -309,7 +312,7 @@ func openUnitObserver(parent context.Context, i Inventory) (*unitObserver, error
309
312
  }
310
313
 
311
314
  func (o *unitObserver) watch(ctx context.Context) {
312
- ticker := time.NewTicker(250 * time.Millisecond)
315
+ ticker := time.NewTimer(unitProbeInterval)
313
316
  defer ticker.Stop()
314
317
  for {
315
318
  select {
@@ -320,12 +323,13 @@ func (o *unitObserver) watch(ctx context.Context) {
320
323
  o.gate.fenceObserver("observation-unavailable", observerEvent{Detail: "bus-context-done", ErrorClass: observerErrorClass(o.conn.Context().Err())})
321
324
  return
322
325
  case <-ticker.C:
323
- probe, cancel := context.WithTimeout(ctx, 500*time.Millisecond)
326
+ probe, cancel := context.WithTimeout(ctx, unitQueryTimeout)
324
327
  err := o.reconcile(probe)
325
328
  cancel()
326
329
  if err != nil {
327
330
  return
328
331
  }
332
+ ticker.Reset(unitProbeInterval)
329
333
  }
330
334
  }
331
335
  }
@@ -54,7 +54,8 @@ func (o *unitObserver) reconcile(ctx context.Context) error {
54
54
  return o.reconcileSnapshot(ctx, o.snapshot)
55
55
  }
56
56
  func (o *unitObserver) reconcileSnapshot(ctx context.Context, query func(context.Context) (Binding, map[string]dbus.Variant, error)) error {
57
- serial, ready := o.gate.unitProbe(time.Now())
57
+ started := time.Now()
58
+ serial, ready := o.gate.unitProbe(started)
58
59
  // Initial observation has no freshness baseline yet.
59
60
  if !ready {
60
61
  return nil
@@ -73,6 +74,9 @@ func (o *unitObserver) reconcileSnapshot(ctx context.Context, query func(context
73
74
  }
74
75
  }
75
76
  o.gate.recordObserver(e)
77
+ if !definitive && errors.Is(err, context.DeadlineExceeded) && (e.Phase == "get-owner" || e.Phase == "get-unit" || e.Phase == "get-all") && o.gate.deferUnitDeadline(serial, started, time.Now(), e) {
78
+ return nil
79
+ }
76
80
  if o.gate.failUnitProbe(serial, reason, definitive, time.Now(), e) {
77
81
  return err
78
82
  }
@@ -173,10 +173,7 @@ func (x *actorFileWriter) Commit(ctx context.Context) (MutationReceipt, Code) {
173
173
  // the destination is ever performed, including failure/foreign replacement.
174
174
  e := unix.Linkat(unix.AT_FDCWD, "/proc/self/fd/"+strconv.Itoa(int(x.file.Fd())), int(x.parent.data.Fd()), x.work.Segments[len(x.work.Segments)-1], unix.AT_SYMLINK_FOLLOW)
175
175
  if e != nil {
176
- if errors.Is(e, unix.EEXIST) {
177
- return x.receipt, ErrDenied
178
- }
179
- return x.receipt, ErrUnsupported
176
+ return x.receipt, publishLinkError(e)
180
177
  }
181
178
  }
182
179
  x.receipt.Published = true
@@ -192,6 +189,12 @@ func (x *actorFileWriter) Commit(ctx context.Context) (MutationReceipt, Code) {
192
189
  x.receipt.Committed = true
193
190
  return x.receipt, ""
194
191
  }
192
+ func publishLinkError(err error) Code {
193
+ if errors.Is(err, unix.EEXIST) || errors.Is(err, unix.EACCES) {
194
+ return ErrDenied
195
+ }
196
+ return ErrUnsupported
197
+ }
195
198
  func (x *actorFileWriter) Close() {
196
199
  if x.closed {
197
200
  return
@@ -8,6 +8,32 @@ import (
8
8
  "testing"
9
9
  )
10
10
 
11
+ func TestPublishLinkError(t *testing.T) {
12
+ for _, tc := range []struct {
13
+ err error
14
+ want Code
15
+ }{
16
+ {unix.EACCES, ErrDenied},
17
+ {unix.EEXIST, ErrDenied},
18
+ {unix.EPERM, ErrUnsupported},
19
+ {unix.ENOSYS, ErrUnsupported},
20
+ {unix.EOPNOTSUPP, ErrUnsupported},
21
+ {unix.EINVAL, ErrUnsupported},
22
+ {unix.ENOENT, ErrUnsupported},
23
+ {unix.EXDEV, ErrUnsupported},
24
+ {unix.EROFS, ErrUnsupported},
25
+ {unix.EIO, ErrUnsupported},
26
+ } {
27
+ t.Run(tc.err.Error(), func(t *testing.T) {
28
+ for _, err := range []error{tc.err, &os.LinkError{Op: "linkat", Old: "fixed-fd", New: "destination", Err: tc.err}} {
29
+ if got := publishLinkError(err); got != tc.want {
30
+ t.Errorf("publishLinkError(%v) = %s, want %s", err, got, tc.want)
31
+ }
32
+ }
33
+ })
34
+ }
35
+ }
36
+
11
37
  func TestWriteExclusivePartialAndNoForeignUnlink(t *testing.T) {
12
38
  pin, root := readOnlyFixture(t)
13
39
  w := writeWork{RootPath: root, Action: ActionCreate, Segments: []string{"new"}, MaxBytes: 10}
@@ -11,7 +11,7 @@ build: 1
11
11
  displayname: __DISPLAY_NAME__
12
12
  description: A native DSM package with a Go backend and a DSM window UI.
13
13
  maintainer: Your Name
14
- os_min_ver: "7.2-64570"
14
+ os_min_ver: "7.1-42661"
15
15
 
16
16
  # One SPK per architecture. Supported: x86_64, aarch64.
17
17
  arches: [x86_64, aarch64]
@@ -0,0 +1,111 @@
1
+ # Background jobs
2
+
3
+ This package opted in with `synopkgland init --background`. `dsm-package.yaml` has
4
+ `background: {worker: sha256-v1}`. The build adds a package-user worker that DSM
5
+ runs as a systemd user unit. Nothing runs as root, and the CGI never starts a
6
+ process in the background.
7
+
8
+ ## What runs
9
+
10
+ - `conf/resource` is `{"systemd-user-unit":{}}` and `conf/systemd/pkguser-<Package>-background.service`
11
+ starts `target/background/worker`. `start-stop-status` only calls `synosystemctl`.
12
+ - The worker is fixed: `sha256-v1` reads one imported file and writes its SHA-256.
13
+ Replace it by editing `backend/internal/background/runner.go` and bump `WorkerRevision`
14
+ (queued jobs of an older revision become `interrupted`, never replayed).
15
+ - The spool is `/var/packages/<Package>/var/background` (dirs `0700`, files `0600`).
16
+ Limits: 1 job at a time, 16 queued, 512 KiB per file, 16 MiB total, 60 s per job.
17
+ - Job states: `queued → running → succeeded | failed | canceled | interrupted`.
18
+ After a crash or forced stop a running job becomes `interrupted` and is not run again.
19
+
20
+ ## API and ownership
21
+
22
+ `bg.status`, `bg.mode.set {enabled}`, `bg.users.set {allowOrdinaryUsers}`, `bg.jobs.purge {owner: {user, uid}}`, `bg.browse {folder?, offset?}`, `bg.jobs.submit {key, folder, relative}`,
23
+ `bg.jobs.list`, `bg.jobs.get {id}`, `bg.jobs.cancel {id}`, `bg.jobs.result {id}`.
24
+
25
+ The panel's **Choose a file** button opens the shared File Station picker, which lists shares and folders
26
+ with `bg.browse`: read-only metadata from the signed-in caller's own DSM session. A pick stores no
27
+ grant and adds no permission; `submit` still re-reads the file through the same session.
28
+
29
+ `submit` copies `relative` below the shared `folder` through the caller's File Station session, so the signed-in
30
+ administrator's own DSM permissions decide what can be imported. The job ID is returned
31
+ only after the journal is durable, and `key` makes a retry return the same job.
32
+ No cookie, SynoToken or password is stored. Closing the window or signing out does not
33
+ cancel a job; sign in as the same owner again to read, download or cancel it.
34
+
35
+ ## Access
36
+
37
+ Background mode is off until an administrator turns it on. Ordinary-user access
38
+ has its own administrator switch.
39
+
40
+ ## Ordinary users (U1)
41
+
42
+ Background mode and `allowOrdinaryUsers` are independent administrator switches,
43
+ initially off. With ordinary users allowed, signed-in users can browse through
44
+ **their own live File Station session**, import a copy, and list/get/cancel/download
45
+ only their own jobs. `bg.mode.set`, `bg.users.set` and `bg.jobs.purge` remain admin-only.
46
+ Administrators can see and cancel all jobs. Turning ordinary access off returns
47
+ `unsupported` on owner routes; it does not delete or cancel previously admitted jobs.
48
+ Turning background mode off cancels queued work and drains running work as before.
49
+
50
+ Owners are matched by both authenticated username and freshly resolved numeric UID.
51
+ An unknown UID refuses owner access and submission with `identity_unavailable`.
52
+ Legacy jobs with an unknown UID remain admin-only. Recreated same-name accounts
53
+ with different UIDs cannot access old jobs. This does not detect reuse of the same
54
+ username **and** UID. Account disablement is enforced by DSM session authentication;
55
+ this feature does not provide a separate account-lifecycle directory service.
56
+
57
+ Idempotency keys are scoped to that owner. Cross-owner and missing IDs both return
58
+ `not_found`. Queue/running counts for ordinary users include only their own jobs.
59
+ Per-owner limits (including administrators): 2 queued/running jobs, 1 MiB of pending
60
+ and retained imported inputs, schedule copies, plus 512 bytes reserved for each pending or retained result. The 16-job/16-MiB
61
+ global bounds and 64 finished-job history remain. Two full 512-KiB inputs exceed the
62
+ owner byte limit because of their result reservations. `owner-queue-full` and
63
+ `owner-quota-exceeded` are distinct from global `queue-full`/`quota-exceeded`.
64
+
65
+ An administrator may explicitly clear an exact owner `{user, uid}` (including
66
+ unknown legacy UIDs). This removes saved results and queued inputs, requests cancel
67
+ for running jobs, and hides those jobs until Finish/Recover drains them. A bounded
68
+ 64-entry audit stores actor, exact owner, time and counts in the durable journal;
69
+ it contains no credentials or input contents. Uninstall retains data by default;
70
+ the existing explicit delete-data wizard remains available.
71
+
72
+ The package copy/result is not recalled when source-file permissions change.
73
+ Offline access under a user's ACL, AD/LDAP UID stability and DSM reboot recovery
74
+ are not claimed. No user credentials are stored.
75
+
76
+ ## Private-copy schedules (S1-a)
77
+
78
+ Import a file and wait for its success, then choose **Schedule this copy** and
79
+ explicitly consent. The package pins a separate copy and digest, without accessing
80
+ File Station offline. `bg.schedules.create {key, jobId, intervalSeconds, consent:true}`
81
+ accepts only 3600, 86400 or 604800 seconds; up to 8 schedules per package.
82
+ `key` is scoped to username/UID and retries the exact definition.
83
+ `bg.schedules.list`, `bg.schedules.disable {id}`, `bg.schedules.delete {id}` are
84
+ owner-scoped; administrators see and can disable/delete all. Only an administrator
85
+ can call `bg.schedules.enable {id, consent:true}` after reviewing the current revision.
86
+ An administrator cannot create a schedule from another owner's imported copy.
87
+
88
+ Successful manual inputs are retained with the bounded 64-job history. Old U1
89
+ results whose input was deleted cannot be scheduled: import again. Copies and
90
+ schedule pins count toward the 1-MiB owner/16-MiB global storage limits; a full
91
+ 512-KiB source plus its pinned copy exceeds the owner limit, so use smaller inputs.
92
+ A scheduled run also needs input/result quota and shares the 2-pending-owner limit.
93
+ At least 4 global queue positions remain available for manual jobs.
94
+
95
+ The package-user worker ticks its journal; no root task, crontab or global service
96
+ is created. `nextAt` and the run's `scheduleId`/`scheduledAt` commit atomically.
97
+ Completed jobs never replay. Each start records overdue ticks as `missed` and
98
+ advances to the next future period. Delays over 5 seconds, a full quota/queue, and
99
+ multi-period gaps are also missed; no catch-up. The latest missed time/reason and
100
+ aggregate missed count are retained, not an unbounded event log. This is neither
101
+ an exact-time nor exactly-once guarantee.
102
+
103
+ Disabling/deleting cancels queued runs and requests running cancellation/drain;
104
+ finished results remain. Background mode off also disables every schedule, and
105
+ turning it on does not revive them. Blocking ordinary access hides owner routes,
106
+ but admitted private-copy schedules continue, like admitted U1 jobs. Clearing an
107
+ owner also deletes that owner's schedules/pins and drains running jobs. A worker
108
+ revision mismatch disables the schedule (`worker-changed`) and requires explicit
109
+ administrator re-enable; a package build +1 with the same worker revision preserves
110
+ compatible definitions/results. Changed or missing pinned bytes disable the schedule.
111
+ No S1-b share authorization or offline personal ACL reading is provided.
@@ -0,0 +1,7 @@
1
+ package app
2
+
3
+ import "dsmapp/internal/api"
4
+
5
+ // backgroundRoutes serves the owner-scoped background job API. Jobs run
6
+ // in the package-user worker unit (conf/systemd), never as root.
7
+ func (cfg Config) backgroundRoutes() []api.Route { return BackgroundRoutes(cfg.DataDir) }
@@ -0,0 +1,32 @@
1
+ package app
2
+
3
+ func init() {
4
+ // The generic route tests need valid params for every background route.
5
+ // Background mode is off in a fresh data dir, so submit is refused before
6
+ // any file is read and the id routes find nothing.
7
+ const id = `{"id":"missing"}`
8
+ sampleParams["bg.users.set"] = `{"allowOrdinaryUsers":true}`
9
+ sampleParams["bg.jobs.purge"] = `{"owner":{"user":"missing","uid":"9999"}}`
10
+ sampleParams["bg.schedules.list"] = `{}`
11
+ sampleParams["bg.schedules.create"] = `{"key":"schedule","jobId":"missing","intervalSeconds":3600,"consent":true}`
12
+ sampleParams["bg.schedules.disable"] = id
13
+ sampleParams["bg.schedules.delete"] = id
14
+ sampleParams["bg.schedules.enable"] = `{"id":"missing","consent":true}`
15
+ sampleOutcome["bg.schedules.create"] = "disabled"
16
+ sampleOutcome["bg.schedules.disable"] = "not_found"
17
+ sampleOutcome["bg.schedules.delete"] = "not_found"
18
+ sampleOutcome["bg.schedules.enable"] = "not_found"
19
+ sampleParams["bg.status"] = `{}`
20
+ sampleParams["bg.mode.set"] = `{"enabled":true}`
21
+ sampleParams["bg.browse"] = `{}`
22
+ sampleParams["bg.jobs.submit"] = `{"key":"k1","folder":"/share","relative":"a.bin"}`
23
+ sampleParams["bg.jobs.list"] = `{}`
24
+ sampleParams["bg.jobs.get"] = id
25
+ sampleParams["bg.jobs.cancel"] = id
26
+ sampleParams["bg.jobs.result"] = id
27
+ sampleOutcome["bg.browse"] = "session_required"
28
+ sampleOutcome["bg.jobs.submit"] = "disabled"
29
+ sampleOutcome["bg.jobs.get"] = "not_found"
30
+ sampleOutcome["bg.jobs.cancel"] = "not_found"
31
+ sampleOutcome["bg.jobs.result"] = "not_found"
32
+ }
@@ -0,0 +1,178 @@
1
+ <script setup lang="ts">
2
+ import {computed,onBeforeUnmount,onMounted,provide,ref} from 'vue'
3
+ import {Button,Callout,Checkbox,Form,FormActions,FormItem,Link,Select,SettingsSection} from '@synopackageland/ui'
4
+ import type {Context} from '../context'
5
+ import M2PathPicker from '../nas/M2PathPicker.vue'
6
+ import {M2ProviderKey,type M2JobSource} from '../nas/m2-contract'
7
+ import {backgroundCopy,backgroundErrorCopy} from './i18n'
8
+ import {createBackgroundPickerProvider} from './picker-provider'
9
+ interface Status{owner?:Owner;enabled:boolean;admin:boolean;allowOrdinaryUsers:boolean;revision:number;worker:{username:string;alive:boolean}|null;limits:{maxInputBytes:number;maxQueued:number;maxOwnerPending:number;maxOwnerBytes:number;jobTimeoutSeconds:number}}
10
+ interface Owner{user:string;uid:string}
11
+ interface Job{copyRetained?:boolean;scheduleId?:string;submitter:Owner;id:string;name:string;state:'queued'|'running'|'succeeded'|'failed'|'canceled'|'interrupted'}
12
+ interface Schedule{id:string;name:string;owner:Owner;enabled:boolean;nextAt:string;intervalSeconds:number;workerRevision:number;missed:number;reason?:string}
13
+ const props=defineProps<{ctx:Pick<Context,'call'|'locale'>}>()
14
+ const copy=computed(()=>backgroundCopy(props.ctx.locale))
15
+ const fill=(text:string,values:Record<string,string|number>)=>text.replace(/\{(\w+)\}/g,(_,k)=>String(values[k]??''))
16
+ const status=ref<Status>(),jobs=ref<Job[]>([]),error=ref<unknown>(),unsupported=ref(false),busy=ref(false)
17
+ const schedules=ref<Schedule[]>([]),scheduleSource=ref<Job>(),scheduleConsent=ref(false),scheduleInterval=ref('3600'),scheduleDelete=ref<Schedule>(),scheduleEnable=ref<Schedule>()
18
+ const purgeOwner=ref<Owner>(),refreshing=ref(false)
19
+ const picking=ref(false),picked=ref<{folder:string;relative:string}>(),download=ref(''),downloadName=ref('')
20
+ const picker=createBackgroundPickerProvider(props.ctx);provide(M2ProviderKey,picker)
21
+ let timer:ReturnType<typeof setInterval>|undefined,disposed=false
22
+ const settled=(j:Job)=>!['queued','running'].includes(j.state)
23
+ async function call<T>(method:string,params?:Record<string,unknown>):Promise<T|undefined>{
24
+ try{return await props.ctx.call<T>(method,params)}
25
+ catch(e){
26
+ if(disposed)return undefined
27
+ if((e as {code?:string})?.code==='unsupported'){unsupported.value=true;jobs.value=[];schedules.value=[];scheduleSource.value=undefined;scheduleDelete.value=undefined;scheduleEnable.value=undefined;status.value=undefined;purgeOwner.value=undefined;picked.value=undefined;if(download.value)URL.revokeObjectURL(download.value);download.value=''}
28
+ else if(!disposed)error.value=e
29
+ return undefined
30
+ }
31
+ }
32
+ async function refresh(){
33
+ if(disposed||refreshing.value)return
34
+ refreshing.value=true
35
+ try{
36
+ const s=await call<Status>('bg.status')
37
+ if(!s||disposed)return
38
+ if(!s.limits||typeof s.enabled!=='boolean'||typeof s.admin!=='boolean'){error.value={code:'unavailable'};return}
39
+ unsupported.value=false;status.value=s
40
+ const list=await call<{jobs:Job[]}>('bg.jobs.list')
41
+ if(list&&!disposed)jobs.value=list.jobs??[]
42
+ const scheduleList=await call<{schedules:Schedule[]}>('bg.schedules.list')
43
+ if(scheduleList&&!disposed)schedules.value=scheduleList.schedules??[]
44
+ if(!disposed&&!status.value?.enabled&&jobs.value.every(settled)&&timer){clearInterval(timer);timer=undefined}
45
+ }finally{refreshing.value=false}
46
+ }
47
+ function poll(){if(!timer)timer=setInterval(()=>void refresh(),3000)}
48
+ async function guarded(work:()=>Promise<unknown>){
49
+ if(busy.value)return
50
+ busy.value=true;error.value=undefined
51
+ try{await work();await refresh();if(status.value?.enabled||jobs.value.some(j=>!settled(j)))poll()}finally{if(!disposed)busy.value=false}
52
+ }
53
+ const setMode=(enabled:boolean)=>guarded(()=>call('bg.mode.set',{enabled}))
54
+ const setUsers=(allowOrdinaryUsers:boolean)=>guarded(()=>call('bg.users.set',{allowOrdinaryUsers}))
55
+ const purge=()=>guarded(async()=>{if(!purgeOwner.value)return;const out=await call('bg.jobs.purge',{owner:purgeOwner.value});if(out)purgeOwner.value=undefined})
56
+ const intervalOptions=computed(()=>[{value:'3600',label:copy.value.hourly},{value:'86400',label:copy.value.daily},{value:'604800',label:copy.value.weekly}])
57
+ const selectSchedule=(job:Job)=>{scheduleSource.value=job;scheduleConsent.value=false;scheduleInterval.value='3600'}
58
+ const createSchedule=()=>guarded(async()=>{if(!scheduleSource.value||!scheduleConsent.value)return;const out=await call('bg.schedules.create',{key:crypto.randomUUID(),jobId:scheduleSource.value.id,intervalSeconds:Number(scheduleInterval.value),consent:true});if(out)scheduleSource.value=undefined})
59
+ const disableSchedule=(id:string)=>guarded(()=>call('bg.schedules.disable',{id}))
60
+ const deleteSchedule=()=>guarded(async()=>{if(!scheduleDelete.value)return;const out=await call('bg.schedules.delete',{id:scheduleDelete.value.id});if(out)scheduleDelete.value=undefined})
61
+ const enableSchedule=()=>guarded(async()=>{if(!scheduleEnable.value)return;const out=await call('bg.schedules.enable',{id:scheduleEnable.value.id,consent:true});if(out)scheduleEnable.value=undefined})
62
+ const formatTime=(value:string)=>{const date=new Date(value);return Number.isFinite(date.getTime())?date.toLocaleString():copy.value.unknownTime}
63
+ const ownCopy=(job:Job)=>job.copyRetained&&job.state==='succeeded'&&!job.scheduleId&&job.submitter?.user===status.value?.owner?.user&&job.submitter?.uid===status.value?.owner?.uid
64
+ const cancel=(id:string)=>guarded(()=>call('bg.jobs.cancel',{id}))
65
+ const pick=(value:M2JobSource)=>{picked.value={folder:value.selection.folder,relative:value.segments.join('/')}}
66
+ // The signed-in caller's own File Station session decides whether the
67
+ // file can be read; the submit itself is the consent to copy that one file.
68
+ const submit=()=>guarded(async()=>{
69
+ if(!picked.value)return
70
+ const sent=await call('bg.jobs.submit',{key:crypto.randomUUID(),...picked.value})
71
+ if(sent)picked.value=undefined
72
+ })
73
+ async function fetchResult(job:Job){
74
+ const value=await call<{result:unknown}>('bg.jobs.result',{id:job.id})
75
+ if(!value||disposed)return
76
+ if(download.value)URL.revokeObjectURL(download.value)
77
+ download.value=URL.createObjectURL(new Blob([JSON.stringify(value.result,null,2)],{type:'application/json'}))
78
+ downloadName.value=`${job.name||job.id}.sha256.json`
79
+ }
80
+ onMounted(()=>void refresh().then(()=>{if(status.value?.enabled||jobs.value.some(j=>!settled(j)))poll()}))
81
+ onBeforeUnmount(()=>{disposed=true;picker.dispose();if(timer)clearInterval(timer);if(download.value)URL.revokeObjectURL(download.value)})
82
+ </script>
83
+ <template>
84
+ <SettingsSection :aria-busy="busy||refreshing" :title="copy.title" :collapsible="false" data-background-panel>
85
+ <Callout v-if="unsupported" tone="warning">{{ copy.unsupported }}</Callout>
86
+ <template v-else>
87
+ <p class="integration-help">{{ copy.help }}</p>
88
+ <Callout v-if="error" tone="danger" role="alert">{{ backgroundErrorCopy(error,copy) }}</Callout>
89
+ <template v-if="status">
90
+ <p role="status">{{ status.enabled ? copy.modeOn : copy.modeOff }} · {{ status.worker?.alive ? fill(copy.workerRunning,{user:status.worker.username}) : copy.workerStopped }}</p>
91
+ <p class="integration-help">{{ fill(copy.limits,{size:status.limits.maxInputBytes/1024,queue:status.limits.maxQueued,seconds:status.limits.jobTimeoutSeconds}) }}</p>
92
+ <p class="integration-help">{{ status.admin ? copy.adminScope : copy.ownerScope }}</p>
93
+ <p class="integration-help">{{ fill(copy.ownerLimits,{jobs:status.limits.maxOwnerPending,size:status.limits.maxOwnerBytes/1024}) }}</p>
94
+ <div class="integration-actions">
95
+ <Button v-if="status.admin&&!status.enabled" variant="primary" :disabled="busy" @click="setMode(true)">{{ copy.enable }}</Button>
96
+ <Button v-else-if="status.admin" variant="secondary" :disabled="busy" @click="setMode(false)">{{ copy.disable }}</Button>
97
+ <Button variant="secondary" :disabled="busy" @click="refresh">{{ copy.refresh }}</Button>
98
+ </div>
99
+ <div v-if="status.admin" class="integration-actions">
100
+ <Button variant="secondary" :disabled="busy" @click="setUsers(!status.allowOrdinaryUsers)">{{ status.allowOrdinaryUsers ? copy.blockUsers : copy.allowUsers }}</Button>
101
+ <span role="status">{{ status.allowOrdinaryUsers ? copy.usersOn : copy.usersOff }}</span>
102
+ </div>
103
+ <template v-if="status.enabled">
104
+ <div class="integration-actions">
105
+ <Button variant="secondary" :disabled="busy" @click="picking=true">{{ copy.chooseFile }}</Button>
106
+ <Button variant="primary" :disabled="busy||!picked" @click="submit">{{ copy.submit }}</Button>
107
+ </div>
108
+ <p v-if="picked" role="status" data-bg-picked>{{ fill(copy.chosen,{path:`${picked.folder}/${picked.relative}`}) }}</p>
109
+ <M2PathPicker v-model:open="picking" :locale="ctx.locale" select-files read-only :title="copy.pickerTitle" :consent="copy.pickerConsent" @source="pick" />
110
+ </template>
111
+ <Callout v-if="purgeOwner&&status.admin" tone="warning">
112
+ <p>{{ fill(copy.purgeConfirm,{user:purgeOwner.user,uid:purgeOwner.uid}) }}</p>
113
+ <div class="integration-actions">
114
+ <Button variant="secondary" :disabled="busy" @click="purge">{{ copy.confirmPurge }}</Button>
115
+ <Button variant="secondary" :disabled="busy" @click="purgeOwner=undefined">{{ copy.keepJobs }}</Button>
116
+ </div>
117
+ </Callout>
118
+ <p v-if="!jobs.length">{{ copy.noJobs }}</p>
119
+ <ul v-else class="integration-jobs">
120
+ <li v-for="job in jobs" :key="job.id" :data-job-state="job.state" :data-job-id="job.id">
121
+ <span class="nas-folder-name">{{ job.name }} — {{ copy[`state_${job.state}`] }}</span>
122
+ <span v-if="status.admin&&job.submitter" class="integration-help">{{ fill(copy.owner,{user:job.submitter.user,uid:job.submitter.uid}) }}</span>
123
+ <Button v-if="status.admin&&job.submitter" variant="secondary" :disabled="busy" @click="purgeOwner=job.submitter">{{ copy.purgeOwner }}</Button>
124
+ <Button v-if="!settled(job)" variant="secondary" :disabled="busy" @click="cancel(job.id)">{{ copy.cancel }}</Button>
125
+ <Button v-if="status.enabled&&ownCopy(job)" variant="secondary" :disabled="busy" @click="selectSchedule(job)">{{ copy.scheduleCopy }}</Button>
126
+ <span v-if="job.scheduleId" class="integration-help">{{ copy.scheduledJob }}</span>
127
+ <Button v-if="job.state==='succeeded'" variant="secondary" :disabled="busy" @click="fetchResult(job)">{{ copy.result }}</Button>
128
+ </li>
129
+ </ul>
130
+ <section data-bg-schedules class="bg-schedules" :aria-label="copy.schedulesTitle">
131
+ <h3>{{ copy.schedulesTitle }}</h3>
132
+ <p class="integration-help">{{ copy.scheduleHelp }}</p>
133
+ <Form v-if="scheduleSource&&status.enabled" class="bg-schedule-form" @submit.prevent="createSchedule">
134
+ <p>{{ fill(copy.scheduleSource,{name:scheduleSource.name}) }}</p>
135
+ <FormItem :label="copy.interval"><Select v-model="scheduleInterval" data-schedule-interval :options="intervalOptions" :disabled="busy" /></FormItem>
136
+ <Checkbox v-model="scheduleConsent" data-schedule-consent :disabled="busy" :label="copy.scheduleConsent" />
137
+ <FormActions><Button type="submit" variant="primary" :disabled="busy||!scheduleConsent">{{ copy.createSchedule }}</Button><Button type="button" variant="secondary" :disabled="busy" @click="scheduleSource=undefined">{{ copy.cancel }}</Button></FormActions>
138
+ </Form>
139
+ <p v-if="!schedules.length">{{ copy.noSchedules }}</p>
140
+ <ul v-else class="integration-jobs">
141
+ <li v-for="schedule in schedules" :key="schedule.id" :data-schedule-id="schedule.id">
142
+ <span class="nas-folder-name">{{ schedule.name }} — {{ schedule.enabled ? copy.scheduleOn : copy.scheduleOff }}</span>
143
+ <span v-if="status.admin" class="integration-help">{{ fill(copy.owner,{user:schedule.owner.user,uid:schedule.owner.uid}) }}</span>
144
+ <span v-if="schedule.enabled" class="integration-help">{{ fill(copy.nextRun,{time:formatTime(schedule.nextAt)}) }}</span>
145
+ <span class="integration-help">{{ fill(copy.missedRuns,{count:schedule.missed}) }}</span>
146
+ <Callout v-if="schedule.reason==='worker-changed'" tone="warning">{{ copy.revisionChanged }}</Callout>
147
+ <Callout v-else-if="schedule.reason==='input-unavailable'" tone="warning">{{ copy.errors['input-unavailable'] }}</Callout>
148
+ <div class="integration-actions">
149
+ <Button v-if="schedule.enabled" variant="secondary" :disabled="busy" @click="disableSchedule(schedule.id)">{{ copy.disableSchedule }}</Button>
150
+ <Button v-else-if="status.admin&&status.enabled" variant="secondary" :disabled="busy" @click="scheduleEnable=schedule">{{ copy.enableSchedule }}</Button>
151
+ <Button variant="secondary" :disabled="busy" @click="scheduleDelete=schedule">{{ copy.deleteSchedule }}</Button>
152
+ </div>
153
+ </li>
154
+ </ul>
155
+ <Callout v-if="scheduleDelete" tone="warning">
156
+ <p>{{ fill(copy.deleteScheduleConsent,{name:scheduleDelete.name}) }}</p>
157
+ <div class="integration-actions"><Button variant="danger" :disabled="busy" @click="deleteSchedule">{{ copy.confirmDeleteSchedule }}</Button><Button variant="secondary" :disabled="busy" @click="scheduleDelete=undefined">{{ copy.cancel }}</Button></div>
158
+ </Callout>
159
+ <Callout v-if="scheduleEnable" tone="warning">
160
+ <p>{{ fill(copy.enableScheduleConsent,{name:scheduleEnable.name}) }}</p>
161
+ <div class="integration-actions"><Button variant="primary" :disabled="busy" @click="enableSchedule">{{ copy.confirmEnableSchedule }}</Button><Button variant="secondary" :disabled="busy" @click="scheduleEnable=undefined">{{ copy.cancel }}</Button></div>
162
+ </Callout>
163
+ </section>
164
+ <Link v-if="download" :href="download" :download="downloadName">{{ copy.download }}</Link>
165
+ </template>
166
+ </template>
167
+ </SettingsSection>
168
+ </template>
169
+
170
+ <style scoped>
171
+ .integration-jobs { overflow-wrap:anywhere; min-width:0; }
172
+ .bg-schedules { margin-block-start: var(--ui-space-6,24px); min-width:0; overflow-wrap:anywhere; }
173
+ .bg-schedules .integration-jobs { display:grid; gap:var(--ui-space-4,16px); padding-inline-start:var(--ui-space-5,20px); }
174
+ .bg-schedules .integration-jobs li { display:flex; flex-direction:column; align-items:flex-start; gap:var(--ui-space-2,8px); min-width:0; }
175
+ .bg-schedules p, .bg-schedules li > span { min-width:0; max-width:100%; }
176
+ .bg-schedules h3 { font-size:15px; font-weight:600; }
177
+ .bg-schedule-form { margin-block:var(--ui-space-4,16px); }
178
+ </style>
@@ -0,0 +1,83 @@
1
+ {
2
+ "title": "Hintergrundaufträge",
3
+ "help": "Kopiert eine ausgewählte Datei ins Paket und berechnet ihren SHA-256 als Paketbenutzer. Aufträge laufen nach der Abmeldung weiter. Kopie und Ergebnis bleiben im Paket; geänderte Quellberechtigungen rufen sie nicht zurück. Melden Sie sich erneut an, um Ihr Ergebnis zu sehen.",
4
+ "unsupported": "Hintergrundaufträge sind für Ihr Konto nicht verfügbar. Bitten Sie einen Administrator, normale Benutzer zuzulassen.",
5
+ "modeOn": "Hintergrundmodus ist an",
6
+ "modeOff": "Hintergrundmodus ist aus",
7
+ "enable": "Einschalten",
8
+ "disable": "Ausschalten",
9
+ "worker": "Worker",
10
+ "workerRunning": "Worker läuft als {user}",
11
+ "workerStopped": "Worker läuft nicht",
12
+ "chooseFile": "Datei auswählen",
13
+ "chosen": "Ausgewählte Datei: {path}",
14
+ "pickerTitle": "Datei zum Importieren auswählen",
15
+ "pickerConsent": "Die ausgewählte Datei wird einmalig mit Ihrer aktuellen DSM-Anmeldung gelesen und an den Hintergrundjob übergeben. Es wird keine Berechtigung gespeichert.",
16
+ "submit": "Importieren und senden",
17
+ "refresh": "Aktualisieren",
18
+ "cancel": "Abbrechen",
19
+ "result": "Ergebnis",
20
+ "download": "Ergebnis herunterladen",
21
+ "noJobs": "Noch keine Aufträge",
22
+ "state_queued": "In Warteschlange",
23
+ "state_running": "Läuft",
24
+ "state_succeeded": "Erfolgreich",
25
+ "state_failed": "Fehlgeschlagen",
26
+ "state_canceled": "Abgebrochen",
27
+ "state_interrupted": "Unterbrochen",
28
+ "limits": "Bis zu {size} KiB pro Datei, {queue} Aufträge in der Warteschlange, {seconds} Sekunden pro Auftrag.",
29
+ "errors": {
30
+ "failed": "Die Anfrage konnte nicht abgeschlossen werden. Aktualisieren und erneut versuchen.",
31
+ "unsupported": "Hintergrundaufträge sind für Ihr Konto nicht verfügbar. Bitten Sie einen Administrator, normale Benutzer zuzulassen.",
32
+ "disabled": "Der Hintergrundmodus ist aus.",
33
+ "limit-exceeded": "Die Datei überschreitet das Limit.",
34
+ "queue-full": "Die Warteschlange ist voll.",
35
+ "quota-exceeded": "Der Hintergrundspeicher ist voll.",
36
+ "conflict": "Der Auftragsstatus hat sich geändert. Aktualisieren.",
37
+ "not_found": "Nicht gefunden.",
38
+ "denied": "Zugriff verweigert.",
39
+ "session_required": "Ihre DSM-Sitzung ist abgelaufen. Melden Sie sich erneut an.",
40
+ "owner-queue-full": "Ihr Limit für offene Aufträge ist erreicht. Warten Sie auf einen Abschluss oder brechen Sie einen Auftrag ab.",
41
+ "owner-quota-exceeded": "Ihr Speicherlimit ist erreicht. Bitten Sie einen Administrator, alte Aufträge zu löschen.",
42
+ "identity_unavailable": "Ihre DSM-Benutzer-UID konnte nicht geprüft werden. Melden Sie sich erneut an oder fragen Sie einen Administrator.",
43
+ "schedule-full": "Maximal 8 Zeitpläne. Löschen Sie einen Zeitplan.",
44
+ "input-unavailable": "Die private Kopie fehlt oder wurde geändert. Importieren Sie sie erneut."
45
+ },
46
+ "ownerScope": "Sie können nur eigene Aufträge sehen, abbrechen und herunterladen.",
47
+ "adminScope": "Administratoren können Aufträge aller Benutzer sehen und abbrechen.",
48
+ "ownerLimits": "Pro Benutzer: {jobs} offene Aufträge und {size} KiB für Eingaben und reservierte Ergebnisse.",
49
+ "allowUsers": "Normale Benutzer zulassen",
50
+ "blockUsers": "Normale Benutzer sperren",
51
+ "usersOn": "Normale Benutzer zugelassen",
52
+ "usersOff": "Normale Benutzer gesperrt",
53
+ "owner": "Besitzer: {user} (UID {uid})",
54
+ "purgeOwner": "Aufträge des Besitzers löschen",
55
+ "purgeConfirm": "Alle Aufträge von {user} (UID {uid}) löschen? Laufende Aufträge werden abgebrochen und beendet; gespeicherte Ergebnisse werden entfernt.",
56
+ "confirmPurge": "Löschen bestätigen",
57
+ "keepJobs": "Aufträge behalten",
58
+ "schedulesTitle": "Zeitpläne",
59
+ "scheduleHelp": "Die feste private Kopie wird als Paketbenutzer stündlich, täglich oder wöchentlich neu berechnet. Bis zu 8 Zeitpläne. Verpasste Läufe werden protokolliert, nicht nachgeholt.",
60
+ "scheduleCopy": "Diese Kopie planen",
61
+ "scheduleSource": "Private Kopie: {name}",
62
+ "interval": "Wiederholungsintervall",
63
+ "hourly": "Stündlich",
64
+ "daily": "Täglich",
65
+ "weekly": "Wöchentlich",
66
+ "scheduleConsent": "Ich stimme zu, diese feste Kopie zu speichern und als Paketbenutzer neu zu berechnen. Neue Quelldateien und persönliche ACLs werden nicht gelesen.",
67
+ "createSchedule": "Zeitplan erstellen",
68
+ "noSchedules": "Noch keine Zeitpläne",
69
+ "scheduleOn": "Aktiviert",
70
+ "scheduleOff": "Deaktiviert",
71
+ "nextRun": "Nächster Lauf: {time}",
72
+ "missedRuns": "Verpasste Läufe: {count}",
73
+ "disableSchedule": "Zeitplan deaktivieren",
74
+ "deleteSchedule": "Zeitplan löschen",
75
+ "deleteScheduleConsent": "Zeitplan für {name} löschen? Wartende Jobs werden abgebrochen, laufende Jobs werden gestoppt und abgeschlossen. Fertige Ergebnisse bleiben erhalten.",
76
+ "confirmDeleteSchedule": "Löschen bestätigen",
77
+ "enableSchedule": "Zeitplan aktivieren",
78
+ "enableScheduleConsent": "Zeitplan für {name} mit der aktuellen Worker-Revision aktivieren? Ich stimme der Neuberechnung dieser festen Kopie zu. Frühere Läufe werden nicht wiederholt.",
79
+ "confirmEnableSchedule": "Aktivierung bestätigen",
80
+ "revisionChanged": "Die Worker-Revision hat sich geändert. Ein Administrator muss diesen Zeitplan prüfen und ausdrücklich aktivieren.",
81
+ "scheduledJob": "Geplanter Lauf",
82
+ "unknownTime": "Unbekannt"
83
+ }