@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
@@ -0,0 +1,83 @@
1
+ {
2
+ "title": "背景工作",
3
+ "help": "將選取的一個檔案複製到套件內,由套件帳號計算 SHA-256。登出後工作仍會繼續。副本與結果由套件保存,來源權限變動不會收回;再次登入即可查看自己的結果。",
4
+ "unsupported": "你的帳號無法使用背景工作。請管理員允許一般使用者。",
5
+ "modeOn": "背景模式已開啟",
6
+ "modeOff": "背景模式已關閉",
7
+ "enable": "開啟",
8
+ "disable": "關閉",
9
+ "worker": "Worker",
10
+ "workerRunning": "Worker 正以 {user} 執行",
11
+ "workerStopped": "Worker 未執行",
12
+ "chooseFile": "選擇檔案",
13
+ "chosen": "已選擇的檔案:{path}",
14
+ "pickerTitle": "選擇要匯入的檔案",
15
+ "pickerConsent": "選取的檔案會用你目前的 DSM 登入讀取一次並交給背景工作,不會保存授權。",
16
+ "submit": "匯入並送出",
17
+ "refresh": "重新整理",
18
+ "cancel": "取消",
19
+ "result": "結果",
20
+ "download": "下載結果",
21
+ "noJobs": "尚無工作",
22
+ "state_queued": "排隊中",
23
+ "state_running": "執行中",
24
+ "state_succeeded": "成功",
25
+ "state_failed": "失敗",
26
+ "state_canceled": "已取消",
27
+ "state_interrupted": "已中斷",
28
+ "limits": "每個檔案最多 {size} KiB、佇列 {queue} 個工作、每個工作 {seconds} 秒。",
29
+ "errors": {
30
+ "failed": "無法完成要求。請重新整理後再試。",
31
+ "unsupported": "你的帳號無法使用背景工作。請管理員允許一般使用者。",
32
+ "disabled": "背景模式已關閉。",
33
+ "limit-exceeded": "檔案超過上限。",
34
+ "queue-full": "佇列已滿。",
35
+ "quota-exceeded": "背景儲存空間已滿。",
36
+ "conflict": "工作狀態已變更,請重新整理。",
37
+ "not_found": "找不到。",
38
+ "denied": "存取被拒絕。",
39
+ "session_required": "DSM 工作階段已過期,請重新登入。",
40
+ "owner-queue-full": "你的待處理工作已達上限。請等待完成或取消一個工作。",
41
+ "owner-quota-exceeded": "你的背景儲存已達上限。請管理員清除舊工作。",
42
+ "identity_unavailable": "無法確認你的 DSM 使用者 UID。請重新登入或洽管理員。",
43
+ "schedule-full": "已達 8 個排程上限。請刪除排程。",
44
+ "input-unavailable": "私有副本不存在或已變更。請重新匯入。"
45
+ },
46
+ "ownerScope": "你只能檢視、取消及下載自己的工作。",
47
+ "adminScope": "管理員可檢視及取消所有使用者的工作。",
48
+ "ownerLimits": "每人上限:{jobs} 個待處理工作、{size} KiB 輸入與預留結果儲存。",
49
+ "allowUsers": "允許一般使用者",
50
+ "blockUsers": "停用一般使用者",
51
+ "usersOn": "已允許一般使用者",
52
+ "usersOff": "已停用一般使用者",
53
+ "owner": "擁有者:{user}(UID {uid})",
54
+ "purgeOwner": "清除擁有者的工作",
55
+ "purgeConfirm": "清除 {user}(UID {uid})的所有工作?執行中的工作會取消並等待結束;已儲存的結果會移除。",
56
+ "confirmPurge": "確認清除",
57
+ "keepJobs": "保留工作",
58
+ "schedulesTitle": "排程",
59
+ "scheduleHelp": "由套件帳號每小時、每日或每週重算固定私有副本。最多 8 個排程;錯過的執行只記錄,不補跑。",
60
+ "scheduleCopy": "排程重跑副本",
61
+ "scheduleSource": "私有副本:{name}",
62
+ "interval": "重複間隔",
63
+ "hourly": "每小時",
64
+ "daily": "每日",
65
+ "weekly": "每週",
66
+ "scheduleConsent": "我同意保留此固定副本,並由套件帳號重算。不讀取新來源檔案或個人 ACL。",
67
+ "createSchedule": "建立排程",
68
+ "noSchedules": "尚無排程",
69
+ "scheduleOn": "已啟用",
70
+ "scheduleOff": "已停用",
71
+ "nextRun": "下次執行:{time}",
72
+ "missedRuns": "錯過執行:{count} 次",
73
+ "disableSchedule": "停用排程",
74
+ "deleteSchedule": "刪除排程",
75
+ "deleteScheduleConsent": "刪除 {name} 的排程?排隊工作會取消,執行中工作會停止並完成收尾。已完成結果保留。",
76
+ "confirmDeleteSchedule": "確認刪除",
77
+ "enableSchedule": "啟用排程",
78
+ "enableScheduleConsent": "使用目前 worker revision 啟用 {name} 的排程?我同意重算此固定副本。不重播過去的執行。",
79
+ "confirmEnableSchedule": "確認啟用",
80
+ "revisionChanged": "Worker revision 已變更。管理員須審閱並明確啟用此排程。",
81
+ "scheduledJob": "排程執行",
82
+ "unknownTime": "未知"
83
+ }
@@ -0,0 +1,19 @@
1
+ import en from './i18n/en.json'
2
+ import zhTW from './i18n/zh-TW.json'
3
+ import zhCN from './i18n/zh-CN.json'
4
+ import ja from './i18n/ja.json'
5
+ import ko from './i18n/ko.json'
6
+ import de from './i18n/de.json'
7
+ import fr from './i18n/fr.json'
8
+ import es from './i18n/es.json'
9
+ import it from './i18n/it.json'
10
+ export type BackgroundCopy=typeof en
11
+ export const backgroundCatalogs:Record<string,BackgroundCopy>={en,'zh-TW':zhTW,'zh-CN':zhCN,ja,ko,de,fr,es,it}
12
+ export function backgroundCopy(locale:string):BackgroundCopy{
13
+ const aliases:Record<string,string>={enu:'en',cht:'zh-TW',chs:'zh-CN',jpn:'ja',krn:'ko',ger:'de',fre:'fr',spn:'es',ita:'it'}
14
+ const key=locale.replaceAll('_','-');return backgroundCatalogs[aliases[key]??key]??backgroundCatalogs[key.split('-')[0]]??en
15
+ }
16
+ export function backgroundErrorCopy(e:unknown,copy:BackgroundCopy):string{
17
+ const code=(e as {code?:string})?.code??''
18
+ return (copy.errors as Record<string,string>)[code]??copy.errors.failed
19
+ }
@@ -0,0 +1,13 @@
1
+ import type {Context} from '../context'
2
+ import {createM2Provider} from '../nas/m2-provider'
3
+ import type {M2Provider} from '../nas/m2-contract'
4
+
5
+ // The shared File Station picker browses through bg.browse, the caller's
6
+ // own session, so a package built without --file-station still has a picker.
7
+ // Confirming a pick stores nothing and grants nothing: submit re-reads the file
8
+ // through the same session. Only the listing and the confirm step are real; the
9
+ // grant and file operations of the full provider are never reached from here.
10
+ export function createBackgroundPickerProvider(ctx:Pick<Context,'call'>):M2Provider{
11
+ const provider=createM2Provider({call:(method,params)=>ctx.call(method==='nas.discovery'?'bg.browse':method,params)})
12
+ return {...provider,async confirm(folder,writable){return {grantId:'',folder,writable}}}
13
+ }
@@ -0,0 +1,179 @@
1
+ // @vitest-environment jsdom
2
+ import {readFileSync} from 'node:fs'
3
+ import {join} from 'node:path'
4
+ import {test,expect} from 'vitest'
5
+ import {createApp,h,nextTick} from 'vue'
6
+ import {AppRoot} from '@synopackageland/ui'
7
+ import BackgroundPanel from '../src/background/BackgroundPanel.vue'
8
+ import {backgroundCatalogs,backgroundCopy} from '../src/background/i18n'
9
+ import {m2Copy} from '../src/nas/m2-i18n'
10
+ // The UI Select is a Reka combobox: drive it by keyboard (the UI README helper), which also proves it is keyboard operable.
11
+ // Attrs such as data-schedule-interval land on the focusable combobox itself.
12
+ async function choose(root:HTMLElement,marker:string,label:string){
13
+ const trigger=root.querySelector<HTMLElement>(`[${marker}][role=combobox]`)!;expect(trigger,marker).toBeTruthy()
14
+ expect(trigger.id,marker).toBeTruthy();expect(root.querySelector(`label[for="${trigger.id}"]`),marker).toBeTruthy()
15
+ trigger.dispatchEvent(new KeyboardEvent('keydown',{key:'ArrowDown',bubbles:true,cancelable:true}));await settle()
16
+ const option=[...document.querySelectorAll<HTMLElement>('[role=option]')].find(o=>o.textContent?.trim()===label)
17
+ if(!option||option.getAttribute('aria-disabled')==='true')throw new Error(`No enabled option: ${label}`)
18
+ option.focus();option.dispatchEvent(new KeyboardEvent('keydown',{key:'Enter',bubbles:true,cancelable:true}));await settle()
19
+ expect(trigger.textContent).toContain(label)
20
+ }
21
+ async function settle(){for(let i=0;i<20;i++){await Promise.resolve();await nextTick()}}
22
+ type Call=(method:string,params?:Record<string,unknown>)=>Promise<any>
23
+ function mount(call:Call,locale='en'){
24
+ const root=document.createElement('div');document.body.append(root)
25
+ const app=createApp({render:()=>h(AppRoot,{},()=>h(BackgroundPanel,{ctx:{call,locale}}))})
26
+ app.config.idPrefix=`bg-${Math.random()}`;app.mount(root)
27
+ return {root,close(){app.unmount();root.remove()}}
28
+ }
29
+ const click=(root:HTMLElement,text:string)=>{const b=[...root.querySelectorAll('button')].find(b=>b.textContent?.trim()===text)!;expect(b).toBeTruthy();b.click()}
30
+ const status=(enabled:boolean)=>({supported:true,enabled,admin:true,allowOrdinaryUsers:false,revision:1,queued:0,running:0,worker:{username:'SynoPkg',alive:true},limits:{maxInputBytes:524288,maxQueued:16,maxOwnerPending:2,maxOwnerBytes:1048576,maxTotalBytes:16777216,jobTimeoutSeconds:60}})
31
+
32
+ test('non-administrators see unsupported and no action',async()=>{
33
+ const f=mount(async()=>{throw {code:'unsupported'}});await settle()
34
+ expect(f.root.textContent).toContain(backgroundCopy('en').unsupported);expect(f.root.querySelector('button')).toBeNull();f.close()
35
+ })
36
+ const browse=(args?:Record<string,unknown>)=>args?.folder
37
+ ?{files:[{name:'fixture.bin',path:`${args.folder}/fixture.bin`,isdir:false,additional:{size:3}}],total:1,offset:0}
38
+ :{shares:[{name:'share',path:'/share',isdir:true}],total:1,offset:0}
39
+ test('enable, pick a file, submit, cancel and result use only bg.* routes',async()=>{
40
+ const calls:Array<[string,Record<string,unknown>|undefined]>=[];let enabled=false,jobs:any[]=[]
41
+ const f=mount(async(m,p)=>{
42
+ calls.push([m,p])
43
+ switch(m){
44
+ case 'bg.status':return status(enabled)
45
+ case 'bg.jobs.list':return {jobs}
46
+ case 'bg.browse':return browse(p)
47
+ case 'bg.mode.set':enabled=true;return {enabled}
48
+ case 'bg.jobs.submit':jobs=[{id:'j1',name:'fixture.bin',state:'queued'}];return {job:jobs[0],duplicate:false}
49
+ case 'bg.jobs.cancel':jobs=[{...jobs[0],state:'canceled'}];return {job:jobs[0]}
50
+ case 'bg.jobs.result':return {result:{sha256:'x'}}
51
+ }
52
+ });await settle()
53
+ const copy=backgroundCopy('en'),pick=m2Copy('en')
54
+ click(f.root,copy.enable);await settle()
55
+ expect(f.root.querySelector('[data-bg-folder]')).toBeNull();expect(f.root.querySelector('[data-bg-file]')).toBeNull()
56
+ const submitButton=()=>[...f.root.querySelectorAll('button')].find(b=>b.textContent?.trim()===copy.submit)!
57
+ expect(submitButton().disabled).toBe(true)
58
+ click(f.root,copy.chooseFile);await settle()
59
+ click(f.root,'Open share');await settle()
60
+ click(f.root,'Select fixture.bin');await settle();click(f.root,pick.confirm);await settle()
61
+ expect(f.root.textContent).toContain('/share/fixture.bin')
62
+ expect(submitButton().disabled).toBe(false)
63
+ click(f.root,copy.submit);await settle()
64
+ const submit=calls.find(c=>c[0]==='bg.jobs.submit')![1]!
65
+ expect(submit.folder).toBe('/share');expect(submit.relative).toBe('fixture.bin');expect(typeof submit.key).toBe('string')
66
+ expect(f.root.querySelector('[data-job-state=queued]')).not.toBeNull()
67
+ click(f.root,copy.cancel);await settle()
68
+ expect(f.root.querySelector('[data-job-state=canceled]')).not.toBeNull()
69
+ expect(calls.filter(c=>c[0]==='bg.browse').length).toBeGreaterThan(0)
70
+ expect(calls.every(c=>/^bg\./.test(c[0]))).toBe(true)
71
+ f.close()
72
+ })
73
+ test('a denied listing shows a localized error and cannot submit',async()=>{
74
+ const f=mount(async(m)=>{
75
+ if(m==='bg.status')return status(true)
76
+ if(m==='bg.jobs.list')return {jobs:[]}
77
+ if(m==='bg.browse')throw {code:'denied',message:'Cookie=CANARY'}
78
+ });await settle()
79
+ click(f.root,backgroundCopy('en').chooseFile);await settle()
80
+ expect(f.root.textContent).toContain(m2Copy('en').errorDenied);expect(f.root.textContent).not.toContain('CANARY')
81
+ expect([...f.root.querySelectorAll('button')].find(b=>b.textContent?.trim()===backgroundCopy('en').submit)!.disabled).toBe(true)
82
+ f.close()
83
+ })
84
+ test('nine locales have identical keys and placeholders',()=>{
85
+ const en=backgroundCatalogs.en,flat=(o:any,p=''):Record<string,string>=>Object.fromEntries(Object.entries(o).flatMap(([k,v])=>typeof v==='string'?[[p+k,v]]:Object.entries(flat(v,`${p}${k}.`))))
86
+ const base=flat(en)
87
+ expect(Object.keys(backgroundCatalogs).sort()).toEqual(['de','en','es','fr','it','ja','ko','zh-CN','zh-TW'])
88
+ for(const catalog of Object.values(backgroundCatalogs)){
89
+ const map=flat(catalog);expect(Object.keys(map).sort()).toEqual(Object.keys(base).sort())
90
+ for(const [k,v] of Object.entries(map)){expect(v.length).toBeGreaterThan(0);expect(v.match(/\{\w+\}/g)??[]).toEqual(base[k].match(/\{\w+\}/g)??[])}
91
+ }
92
+ })
93
+
94
+ test('a null job list from the worker renders as no jobs',async()=>{
95
+ const f=mount(async m=>m==='bg.status'?status(true):m==='bg.jobs.list'?{jobs:null}:{});await settle()
96
+ expect(f.root.textContent).toContain(backgroundCopy('en').noJobs);f.close()
97
+ })
98
+
99
+ test('the picker dialog explains the one-time read, not the M2 saved-selection consent',async()=>{
100
+ for(const locale of Object.keys(backgroundCatalogs)){
101
+ const f=mount(async(m,p)=>m==='bg.status'?status(true):m==='bg.jobs.list'?{jobs:[]}:browse(p),locale);await settle()
102
+ const copy=backgroundCopy(locale)
103
+ click(f.root,copy.chooseFile);await settle()
104
+ const dialog=f.root.querySelector('[role=dialog]')!.textContent!
105
+ expect(dialog).toContain(copy.pickerConsent);expect(dialog).not.toContain(m2Copy(locale).consent)
106
+ f.close()
107
+ }
108
+ })
109
+
110
+ test('ordinary owner can submit but has no administrator controls',async()=>{
111
+ const calls:string[]=[]
112
+ const f=mount(async(m,p)=>{calls.push(m);if(m==='bg.status')return {...status(true),admin:false,allowOrdinaryUsers:true};if(m==='bg.jobs.list')return {jobs:[{id:'owned',name:'owned.bin',state:'queued',submitter:{user:'bob',uid:'1025'}}]};if(m==='bg.browse')return browse(p);return {}});await settle()
113
+ const c=backgroundCopy('en')
114
+ expect(f.root.textContent).toContain(c.ownerScope)
115
+ expect(f.root.textContent).not.toContain(c.disable)
116
+ expect(f.root.textContent).not.toContain(c.allowUsers)
117
+ expect(f.root.textContent).not.toContain(c.purgeOwner)
118
+ expect([...f.root.querySelectorAll('button')].some(b=>b.textContent?.trim()===c.chooseFile)).toBe(true)
119
+ click(f.root,c.cancel);await settle();expect(calls).toContain('bg.jobs.cancel');f.close()
120
+ })
121
+ test('admin ordinary-user switch and exact owner purge require explicit confirmation',async()=>{
122
+ const calls:Array<[string,Record<string,unknown>|undefined]>=[]
123
+ const f=mount(async(m,p)=>{calls.push([m,p]);if(m==='bg.status')return {...status(true),admin:true,allowOrdinaryUsers:false};if(m==='bg.jobs.list')return {jobs:[{id:'one',name:'a',state:'succeeded',submitter:{user:'bob',uid:'1025'}}]};return {}});await settle()
124
+ const c=backgroundCopy('en');click(f.root,c.allowUsers);await settle()
125
+ expect(calls.find(([m])=>m==='bg.users.set')?.[1]).toEqual({allowOrdinaryUsers:true})
126
+ click(f.root,c.purgeOwner);await settle();expect(calls.some(([m])=>m==='bg.jobs.purge')).toBe(false)
127
+ click(f.root,c.confirmPurge);await settle()
128
+ expect(calls.find(([m])=>m==='bg.jobs.purge')?.[1]).toEqual({owner:{user:'bob',uid:'1025'}});f.close()
129
+ })
130
+ test('malformed status cannot render action controls or crash the panel',async()=>{
131
+ const f=mount(async()=>({state:'not-enabled'}));await settle()
132
+ expect(f.root.textContent).toContain(backgroundCopy('en').errors.failed)
133
+ expect(f.root.querySelector('button')).toBeNull();f.close()
134
+ })
135
+
136
+ test('schedule creation requires copy consent; owner controls disable and delete exact schedule',async()=>{
137
+ const calls:Array<[string,Record<string,unknown>|undefined]>=[];let schedules:any[]=[]
138
+ const f=mount(async(m,p)=>{calls.push([m,p]);switch(m){
139
+ case 'bg.status':return {...status(true),owner:{user:'bob',uid:'1025'},admin:false,allowOrdinaryUsers:true}
140
+ case 'bg.jobs.list':return {jobs:[{id:'import',name:'copy.bin',state:'succeeded',copyRetained:true,submitter:{user:'bob',uid:'1025'}}]}
141
+ case 'bg.schedules.list':return {schedules}
142
+ case 'bg.schedules.create':schedules=[{id:'schedule',name:'copy.bin',owner:{user:'bob',uid:'1025'},enabled:true,intervalSeconds:3600,nextAt:'2026-10-05T01:00:00Z',missed:0,workerRevision:1}];return {schedule:schedules[0]}
143
+ case 'bg.schedules.disable':schedules=[{...schedules[0],enabled:false}];return {schedule:schedules[0]}
144
+ case 'bg.schedules.delete':schedules=[];return {deleted:true}
145
+ default:return {}
146
+ }});await settle();const c=backgroundCopy('en')
147
+ click(f.root,c.scheduleCopy);await settle()
148
+ expect(calls.some(([m])=>m==='bg.schedules.create')).toBe(false)
149
+ const create=[...f.root.querySelectorAll('button')].find(b=>b.textContent?.trim()===c.createSchedule)!
150
+ expect(create.disabled).toBe(true)
151
+ await choose(f.root,'data-schedule-interval',c.weekly)
152
+ const consent=f.root.querySelector<HTMLElement>('[data-schedule-consent] [role=checkbox], [role=checkbox][data-schedule-consent]')!;consent.click();await settle()
153
+ click(f.root,c.createSchedule);await settle()
154
+ expect(calls.find(([m])=>m==='bg.schedules.create')?.[1]).toMatchObject({jobId:'import',intervalSeconds:604800,consent:true})
155
+ expect(f.root.querySelector('[data-schedule-id=schedule]')?.textContent).toContain(c.nextRun.replace('{time}','').trim().split(':')[0])
156
+ click(f.root,c.disableSchedule);await settle();expect(calls.find(([m])=>m==='bg.schedules.disable')?.[1]).toEqual({id:'schedule'})
157
+ click(f.root,c.deleteSchedule);await settle();expect(calls.some(([m])=>m==='bg.schedules.delete')).toBe(false)
158
+ click(f.root,c.confirmDeleteSchedule);await settle();expect(calls.find(([m])=>m==='bg.schedules.delete')?.[1]).toEqual({id:'schedule'});f.close()
159
+ })
160
+
161
+ test('administrator sees the exact selected copy before enabling a schedule',async()=>{
162
+ const calls:Array<[string,Record<string,unknown>|undefined]>=[]
163
+ const name='private-'.padEnd(128,'x')
164
+ const f=mount(async(m,p)=>{calls.push([m,p]);if(m==='bg.status')return status(true);if(m==='bg.jobs.list')return {jobs:[]};if(m==='bg.schedules.list')return {schedules:[{id:'disabled',name,owner:{user:'normal1',uid:'1025'},enabled:false,nextAt:'2026-10-05T01:00:00Z',missed:0}]};return {}});await settle()
165
+ const c=backgroundCopy('en');click(f.root,c.enableSchedule);await settle()
166
+ const expected=c.enableScheduleConsent.replace('{name}',name)
167
+ expect(expected).toContain(name);expect(f.root.textContent).toContain(expected)
168
+ expect(calls.some(([m])=>m==='bg.schedules.enable')).toBe(false)
169
+ click(f.root,c.confirmEnableSchedule);await settle()
170
+ expect(calls.find(([m])=>m==='bg.schedules.enable')?.[1]).toEqual({id:'disabled',consent:true});f.close()
171
+ })
172
+
173
+ // Same rule as the base template (test/native-controls.test.ts): UI components only, and the
174
+ // UI's own Form auto layout and FormItem id binding instead of per-app workarounds.
175
+ test('the background panel uses only UI components and the UI form binding',()=>{
176
+ const template=readFileSync(join(__dirname,'../src/background/BackgroundPanel.vue'),'utf8').replace(/<script[\s\S]*?<\/script>/g,'').replace(/<style[\s\S]*?<\/style>/g,'')
177
+ expect(template.match(/<(?:a|input|select|textarea|label)[\s>/]/g)).toBeNull()
178
+ expect(template).not.toMatch(/direction="vertical"|field\.controlId|role="group"/)
179
+ })
@@ -22,11 +22,11 @@ import (
22
22
  // The client may send an opaque ID, never a user name, UID or filesystem path.
23
23
  var personalLookup = user.Lookup
24
24
  var integrationHealth = func(ctx context.Context, cfg Config) helper.State {
25
- return helper.NewClient(cfg.HelperInventory).Status(ctx)
25
+ return cfg.integrationState(ctx)
26
26
  }
27
27
 
28
28
  func (cfg Config) integrationRoutes() []api.Route {
29
- if cfg.HelperInventory.Protocol != 1 {
29
+ if !cfg.PackageIntegration && cfg.HelperInventory.Protocol != 1 {
30
30
  return nil
31
31
  }
32
32
  return append([]api.Route{api.User("personal.list", cfg.personalList), api.User("personal.read", cfg.personalRead), api.User("personal.write", cfg.personalWrite)}, cfg.identityRoutes()...)
@@ -68,6 +68,43 @@ func TestPersonalUsersReadWriteAndMutuallyRefuse(t *testing.T) {
68
68
  t.Fatal(code)
69
69
  }
70
70
  }
71
+ // Package-only integration has no helper: the sample stays package-owned data
72
+ // and never waits for a helper health check.
73
+ func TestPackageOnlyPersonalDataNeedsNoHelper(t *testing.T) {
74
+ oldLookup := personalLookup
75
+ personalLookup = func(name string) (*user.User, error) {
76
+ return &user.User{Username: name, Uid: map[string]string{"normal1": "1001", "normal2": "1002"}[name], Gid: "100"}, nil
77
+ }
78
+ t.Cleanup(func() { personalLookup = oldLookup })
79
+ cfg := testConfig(t)
80
+ cfg.PackageIntegration = true
81
+ if cfg.HelperInventory != (helper.Inventory{}) {
82
+ t.Fatal("fixture must have no helper inventory")
83
+ }
84
+ first, second := personalHandle(t, cfg, "normal1"), personalHandle(t, cfg, "normal2")
85
+ if first == second {
86
+ t.Fatal("handles must bind caller")
87
+ }
88
+ if code, out := personalCall(t, cfg, "normal1", "personal.write", `{"id":"`+first+`","text":"mine"}`); code != "" {
89
+ t.Fatal(code, out)
90
+ }
91
+ if code, out := personalCall(t, cfg, "normal1", "personal.read", `{"id":"`+first+`"}`); code != "" || out["data"].(map[string]any)["text"] != "mine" {
92
+ t.Fatal(code, out)
93
+ }
94
+ if code, _ := personalCall(t, cfg, "normal2", "personal.read", `{"id":"`+first+`"}`); code != "access_denied" {
95
+ t.Fatal(code)
96
+ }
97
+ }
98
+
99
+ // Without package-only mode and without an approved helper nothing is served:
100
+ // a helper build whose inventory failed to load stays closed.
101
+ func TestHelperlessConfigWithoutPackageModeServesNoPersonalRoutes(t *testing.T) {
102
+ cfg := testConfig(t)
103
+ if routes := cfg.integrationRoutes(); len(routes) != 0 {
104
+ t.Fatalf("%d routes", len(routes))
105
+ }
106
+ }
107
+
71
108
  func TestPersonalRejectsForgedIdentityAndPaths(t *testing.T) {
72
109
  cfg := personalFixture(t)
73
110
  id := personalHandle(t, cfg, "normal1")
@@ -1,6 +1,6 @@
1
1
  # __DISPLAY_NAME__ — Vue DSM package
2
2
 
3
- This is the existing native-go template with the shared UI **0.4.0**. It uses
3
+ This is the existing native-go template with the shared UI **0.5.7**. It uses
4
4
  AppRoot, the DSM embedded theme, Dialog, SettingsSection, Callout and existing
5
5
  controls. The generated `dsm-package.yaml` remains the only package manifest.
6
6
 
@@ -14,7 +14,7 @@ synopkgland build-spk
14
14
  synopkgland inspect --spk dist/__PACKAGE__-0.1.0-0001-x86_64.spk
15
15
  ```
16
16
 
17
- The pinned `@synopackageland/ui@0.4.0` dependency is public on
17
+ The pinned `@synopackageland/ui@0.5.7` dependency is public on
18
18
  `https://registry.npmjs.org`, selected by `frontend/.npmrc`. No registry account
19
19
  or credentials are required. Dependencies are installed and UI bundled on the
20
20
  build machine; the NAS never downloads npm packages. Commit your lockfiles.
@@ -37,8 +37,12 @@ first, verify the helper is no longer ready, then Stop the package. V1 found
37
37
  this on a real NAS; the M1e investigation is ongoing.
38
38
 
39
39
  Generate with `synopkgland init -t native-go --ui vue --integration go <dir>`.
40
- This automatically chooses root privilege and adds only the existing M1a
41
- `integration: {protocol: 1, workers: {}}` contract. The native-go baseline without
40
+ This keeps `privilege: none`: the private note and status screen run as the
41
+ package account, with no helper, scheduler task or precheck hook, and
42
+ `integration.status` reports `ready / package-only`. Add `--privilege root` to
43
+ get the privileged helper described below (the existing M1a
44
+ `integration: {protocol: 1, workers: {}}` contract). The helper brings only its
45
+ five `helper_*` tasks, not the `whoami` demo. The native-go baseline without
42
46
  these options remains unchanged. Vue alone keeps the original Go 1.24 module;
43
47
  integration uses Go **1.25+** for fd-rooted atomic storage updates.
44
48
 
@@ -67,7 +71,7 @@ version history or general filesystem permission is implied.
67
71
  ## NAS picker and grants (S4 mock preview)
68
72
 
69
73
  The Vue template includes `NasPathPicker` and `NasGrantSettings`, built from UI
70
- 0.4.0's Dialog, TreeView, DataGrid, Button and SettingsSection. The existing
74
+ 0.5.7's Dialog, TreeView, DataGrid, Button and SettingsSection. The existing
71
75
  browser `FilePicker` still represents local `File[]`; NAS selections return
72
76
  opaque directory grant handles. The new UI has catalogs for en, zh-TW, zh-CN,
73
77
  ja, ko, de, fr, es and it, selected from `ctx.locale` with English fallback.
@@ -142,7 +146,7 @@ clears instance/session state and stale reopen callbacks become no-ops.
142
146
  IDs, overlay roots, reopen/unmount, errors and empty data with jsdom. Real
143
147
  unsigned artifact tests additionally cross-compile Go and bundle UI/Node.
144
148
 
145
- UI **0.4.0** enables `<AppRoot modal-scope="app">`. Each mount assigns a
149
+ UI **0.5.7** enables `<AppRoot modal-scope="app">`. Each mount assigns a
146
150
  package-prefixed, instance-unique Vue `idPrefix` before mounting. The sizing
147
151
  class on the mount element fills the existing bounded DSM fit-layout body;
148
152
  AppRoot fills that element and owns the background scroll container and local
@@ -189,7 +193,7 @@ isolated Linux systemd VM evidence; DSM 4.4 acceptance is still unknown.
189
193
  ## M2 S1R build policy and unavailable delivery
190
194
 
191
195
  The S8 source candidate also accepts `--integration-protocol 2` with
192
- `--integration go` or `better-auth`. The default stays protocol 1. The manifest,
196
+ `--integration go` or `better-auth`, and only together with `--privilege root`. The default stays protocol 1. The manifest,
193
197
  compiled helper/CGI inventory, payload/worker digests, inspector and lifecycle
194
198
  approval pin the same protocol. A change requires exact new approval, never
195
199
  protocol 1 data fallback.
@@ -222,3 +226,30 @@ Anonymous/expired DSM sessions return `session_required`; authentication failure
222
226
  returns `auth_unavailable`. Relogin restores only the ordinary app session.
223
227
  Positive NAS functionality, ACL and final DSM SPK acceptance remain blocked /
224
228
  unknown; local refusal and QEMU fixtures do not certify them.
229
+
230
+
231
+ ## Interactive jobs after an observer pause
232
+
233
+ The opt-in workers session API refuses requests with `revalidating` while the
234
+ existing bounded reload/query observer checks are pending. Admission stays
235
+ closed, running jobs are conservatively canceled, and no attach lease is
236
+ extended. Sticky fences still return `fenced`. After a valid session-mode status
237
+ reply confirms recovery, new submissions can proceed; canceled jobs never resume.
238
+
239
+ JobsPanel keeps the revalidation message until recovery is confirmed and explains
240
+ `canceled` jobs with `safeReason: "fenced"` in all nine locales. Resubmit is an
241
+ explicit user action: the connected provider uses a mount-local plan snapshot
242
+ and calls fresh prepare/submit for a new intent and job ID, rechecking permissions.
243
+ There is no automatic resubmission. A lost submit reply locks further submission
244
+ and offers lookup of the new intent. Reopening the view loses the local plan;
245
+ select inputs again instead of inferring them from history. Existing initial
246
+ picker/submission form wiring remains outside this template.
247
+
248
+ See `docs/m3-adapt-simple-session-jobs.md` in the SDK repository for the full
249
+ contract and the distinction between local evidence and DSM acceptance.
250
+
251
+ ## Interactive NAS picker and job submission
252
+
253
+ For the opt-in SDK-workers entry, see [frontend/README-JOBS.md](frontend/README-JOBS.md).
254
+ It connects the existing File Station folder/file picker, session selection and
255
+ fixed read plan to prepare/submit, progress, cancel and explicit fenced resubmission.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: Native DSM Vue integration template
3
- description: Existing package settings UI using Syno Package Land UI 0.4.0.
3
+ description: Existing package settings UI using Syno Package Land UI 0.5.7.
4
4
  typography:
5
5
  body:
6
6
  fontFamily: "var(--ui-font-sans)"
@@ -24,7 +24,7 @@ spacing:
24
24
 
25
25
  This records the built template, not a new visual identity. The settings surface operates inside a DSM package window: users inspect integration health, administrators approve maintenance operations, and each account edits its own synthetic sample note. Its usage mode is **Operate**; preserve the compact, readable hierarchy and existing native component behavior.
26
26
 
27
- Visual authority is `@synopackageland/ui` **0.4.0**, its public exports and `themes/dsm7-embedded.css`, plus the application styles in `src/style.css`. `AppRoot` scopes the component world. Local synthetic browser screenshots (`ui-desktop.png`, `ui-minimum.png`, `ui-user-failed.png`) support this description; they do not establish DSM runtime acceptance.
27
+ Visual authority is `@synopackageland/ui` **0.5.7**, its public exports and `themes/dsm7-embedded.css`, plus the application styles in `src/style.css`. `AppRoot` scopes the component world. Local synthetic browser screenshots (`ui-desktop.png`, `ui-minimum.png`, `ui-user-failed.png`) support this description; they do not establish DSM runtime acceptance.
28
28
 
29
29
  ## Colors
30
30
 
@@ -56,7 +56,7 @@ The application adds no shadows or elevation system. Surface, overlay and dialog
56
56
  - **Loading, empty and mutation states:** Refresh and mutations disable competing controls; the main region exposes `aria-busy` and textual status. Failed status loading offers Refresh. A ready integration with no note ID shows the “No sample data” Callout. A labeled Textarea and Save button appear when a note exists. Completion notices use `role=status`; error copy uses `role=alert` and identifies a recovery action. Optional app identity appears only when its route reports `better-auth`.
57
57
  - **Dialog:** Disable opens the library confirmation dialog, explains refusal of new requests and retention of existing data/output, and presents Cancel plus danger Confirm disable. No application modal replacement is provided.
58
58
 
59
- **App-local modality:** consume UI 0.4.0's `AppRoot modal-scope="app"`.
59
+ **App-local modality:** consume UI 0.5.7's `AppRoot modal-scope="app"`.
60
60
  Each independent mount sets a package-prefixed, unique Vue `idPrefix` before
61
61
  mounting. The mount sizing class and AppRoot use `height: 100%` inside the
62
62
  existing bounded DSM fit-layout body. AppRoot owns background scrolling and
@@ -70,9 +70,21 @@ custom out-of-root portals. Other UI versions/modal libraries, Safari/iOS and
70
70
  manual screen-reader acceptance remain unvalidated. Test the generated final
71
71
  SPK on DSM separately from local jsdom/Chromium evidence.
72
72
 
73
+ ### Opt-in background schedules (S1-a)
74
+
75
+ The `native-go-background` overlay extends this **Operate** surface within the inherited `AppRoot`, embedded theme, `SettingsSection`, Button and Callout system. It introduces no new palette or global tokens.
76
+
77
+ - **Private-copy consent:** “Schedule this copy” is available for the signed-in owner's retained, successful, unscheduled job copy. “Private copy: {name}” identifies the input; “Repeat every” offers “Hour”, “Day” and “Week”. “Create schedule” stays disabled until the user checks “I agree to keep and reprocess this fixed copy as the package user. No new source files or personal ACLs are read.” The help explains the eight-schedule limit and that missed runs are recorded, never replayed.
78
+ - **Ownership and recovery:** preserve user-and-UID owner isolation. Administrator rows expose “Owner: {user} (UID {uid})”. A worker change shows “The worker revision changed. An administrator must review and explicitly enable this schedule.” Only administrators, while background mode is on, see “Enable schedule”. Its confirmation names the exact private copy: “Enable the schedule for {name} with the current worker revision? I agree to reprocess this fixed copy. Past runs will not be replayed.” Actions are “Confirm enable” and “Cancel”.
79
+ - **Layout:** schedule name/state, owner, next run, missed runs and warnings stack above a grouped, wrapping action row. Long names and copy wrap within the available width. Keep the inherited vertical scrolling at the minimum window size; do not squeeze schedules into one viewport. The labeled select and consent checkbox retain visible keyboard focus using existing theme tokens.
80
+ - **Errors and cleanup:** danger alerts map known error codes to localized safe copy, with a localized fallback rather than raw server text. The catalogs cover nine locales. Preserve per-mount disposal: stop polling, dispose the picker, revoke result download URLs and prevent pending responses from restoring disposed state. Deletion confirmation explains that queued jobs cancel, running jobs drain and finished results remain.
81
+
82
+ Evidence: `.herdr-project/syno-package-land-sdk-t-0129/library/ui-desktop.png` and `ui-minimum.png` are local component-fixture captures. The finish review disposition is **ship**, with all three material findings resolved. A fresh `normal1` NAS browser readback passed before the final UI adjustments; these captures validate the final adjustments locally and do not establish final DSM visual acceptance.
83
+
73
84
  ## Do's and Don'ts
74
85
 
75
86
  - Do use existing public UI components, embedded theme tokens and state/recovery copy.
76
87
  - Do retain permission gating, readable loading/empty/error states and per-instance cleanup.
88
+ - Do use the library's `Select`, `Checkbox`, `Input`, `Textarea`, `Form`, `FormItem`, `FilePicker` (`variant="compact"`, in the app locale) and `Link` for controls; there is no native `<input>` or `<a>`. Leave `Form` on its automatic direction (labels stack below 520px of container width) and let a `FormItem` bind its control, with no `direction="vertical"`, `role="group"` or `field.controlId`.
77
89
  - Don't claim trusted helper readiness from scheduler values or treat app identity as native session/filesystem authorization.
78
90
  - Don't introduce a separate palette, component system or modal workaround around the library contract.
@@ -0,0 +1,75 @@
1
+ # Interactive NAS picker → job (experimental)
2
+
3
+ Use the existing `native-go --ui vue --integration go` project, then opt in to
4
+ protocol 2, relaxed File Station session access and a fixed SDK read worker:
5
+
6
+ ```yaml
7
+ integration:
8
+ protocol: 2
9
+ dataAccess: relaxed
10
+ workers: {}
11
+ sdkWorkers:
12
+ scan:
13
+ kind: sdk-read-plan
14
+ workerRevision: 1
15
+ actions: [nas.files.list, nas.files.stat, nas.files.read]
16
+ modes: [interactive]
17
+ ```
18
+
19
+ Install frontend dependencies and run `synopkgland build-spk` as usual. The
20
+ builder sets `SYNOPKGLAND_SDK_WORKERS=1` from the manifest and chooses
21
+ `src/sdk-main.ts`. Leave `SYNOPKGLAND_M2_SIMPLE` unset: that flag deliberately
22
+ selects the separate session-only file-operation entry without job controls.
23
+ For a standalone frontend check use `SYNOPKGLAND_SDK_WORKERS=1 npm run build`.
24
+
25
+ An administrator uses the existing exact-payload approval and activation flow.
26
+ The session SDK surface hides the native personal-note sample, whose routes
27
+ are absent from this protocol-2 build.
28
+ Each user opens the package in their own DSM session. The jobs panel enables
29
+ the source picker only after a fresh `jobs.status` reports session availability.
30
+ Choose a file or folder, confirm selection, select the worker and operation,
31
+ set its bound where required, then submit once. Progress refreshes every 2.5 s
32
+ while this page contains active jobs; errors stop polling and require Refresh.
33
+ Cancel uses the existing owner/revision checks. Closing the window requests
34
+ cancellation and stops renewal. Observer revalidation pauses submission;
35
+ fenced jobs stay canceled and require an explicit fresh submission after
36
+ recovery. Nothing resumes or retries automatically.
37
+
38
+ `jobs.status.workers` projects only interactive workers with session-supported
39
+ list/stat/read actions, exact registry revision and the smaller of the worker's
40
+ bounded/total byte limits and 512 KiB. It contains no compiled bindings or
41
+ credentials. This is display metadata: prepare still verifies the registry,
42
+ selection, session and current permissions. Missing metadata in an older owner
43
+ leaves the form disabled. The form submits one step; list is 1–100 entries,
44
+ read is 1–the projected byte limit, and stat has no byte/entry argument.
45
+ This read-only worker requires no destination and discards content, returning
46
+ only counters. Background jobs remain unsupported even if the manifest lists
47
+ background mode. Writes and custom executables are not part of this form.
48
+
49
+ `M2PathPicker` extends the existing Dialog/TreeView/DataGrid composition with
50
+ `select-files` and `read-only` props and a `source` event (`M2JobSource`). Folder
51
+ picks return an empty segment list. File picks call the existing
52
+ `nas.grants.confirm` for the containing folder with `writable:false`, then use
53
+ one relative filename in `jobs.prepare.input`. The `folder` grant therefore
54
+ records consent for that containing folder, not a file-only authority. Existing
55
+ folder-only consumers and their `selected` event are unchanged. These selections
56
+ remain path based; they do not pin inodes or confine symlink/rename races.
57
+
58
+ The SDK mount provides both `M2ProviderKey` and `JobsProviderKey` per window.
59
+ `JobsProvider.interactive` exposes `workers`, `prepareInteractive` and
60
+ `submitInteractive`; applications can reuse this interface with their own form.
61
+ Transport stays in the existing `ctx.call`, which carries the current DSM
62
+ session and CSRF token. Never put credentials in form fields, persistent
63
+ storage, logs or an administrator-session fallback.
64
+
65
+ A missing submit reply freezes the form with its original intent. **Check
66
+ original job** calls `jobs.lookup`; it never submits or acquires a replacement
67
+ lease. If the job is found, status shows its actual outcome. Without the lost
68
+ attach receipt it may expire after 6 s. Unmount or an account/package change
69
+ clears selection and pending input, disconnects the provider, and discards late
70
+ responses. Refreshing cannot certify remote rollback or completed cleanup.
71
+ The attach contract remains 2 s renewal / 6 s TTL.
72
+
73
+ Nine catalogs cover en, zh-TW, zh-CN, ja, ko, de, fr, es and it via `ctx.locale`.
74
+ Unit and browser fixtures are synthetic; DSM compatibility must be established
75
+ on the final generated SPK with each user's session and File Station permissions.