@synopackageland/cli 0.6.0 → 0.7.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 (585) hide show
  1. package/CHANGELOG.md +613 -0
  2. package/README.md +81 -78
  3. package/dist/add.js +39 -16
  4. package/dist/authorization-sdk.d.ts +7 -0
  5. package/dist/authorization-sdk.js +7 -0
  6. package/dist/build-spk/delegate-scope.d.ts +6 -0
  7. package/dist/build-spk/delegate-scope.js +34 -0
  8. package/dist/build-spk/dsm-arch.d.ts +7 -1
  9. package/dist/build-spk/dsm-arch.js +24 -28
  10. package/dist/build-spk/dsm-platforms.json +39 -0
  11. package/dist/build-spk/dsm-version.d.ts +11 -0
  12. package/dist/build-spk/dsm-version.js +17 -0
  13. package/dist/build-spk/gateway.d.ts +1 -1
  14. package/dist/build-spk/gateway.js +2 -2
  15. package/dist/build-spk/generator.js +30 -5
  16. package/dist/build-spk/notices.js +4 -1
  17. package/dist/build-spk/resource-worker.js +3 -0
  18. package/dist/build-spk/wizard-messages.d.ts +66 -0
  19. package/dist/build-spk/wizard-messages.js +75 -9
  20. package/dist/cli.js +30 -18
  21. package/dist/contract/schema-validate.js +8 -0
  22. package/dist/contract/validate.js +30 -0
  23. package/dist/deploy/deploy.d.ts +1 -1
  24. package/dist/deploy/deploy.js +8 -0
  25. package/dist/deploy/plan.js +1 -1
  26. package/dist/deploy/spk-version.js +1 -1
  27. package/dist/error-registry.js +46 -13
  28. package/dist/host/dsm-client.d.ts +8 -4
  29. package/dist/host/dsm-client.js +10 -4
  30. package/dist/host/types.d.ts +2 -1
  31. package/dist/info.js +18 -2
  32. package/dist/init.d.ts +3 -0
  33. package/dist/init.js +49 -18
  34. package/dist/package-metadata.d.ts +21 -0
  35. package/dist/package-metadata.js +101 -0
  36. package/dist/portal/alias.d.ts +25 -0
  37. package/dist/portal/alias.js +48 -0
  38. package/dist/portal/package.d.ts +33 -0
  39. package/dist/portal/package.js +116 -0
  40. package/dist/runtime/delegate-contract.d.ts +79 -0
  41. package/dist/runtime/delegate-contract.js +27 -0
  42. package/dist/runtime/executor-build.d.ts +1 -1
  43. package/dist/runtime/executor-build.js +5 -4
  44. package/dist/runtime/executor-inspect.d.ts +3 -0
  45. package/dist/runtime/executor-inspect.js +11 -5
  46. package/dist/runtime/executor-policy.d.ts +12 -0
  47. package/dist/runtime/executor-policy.js +43 -3
  48. package/dist/runtime/executor-scope-task.d.ts +4 -0
  49. package/dist/runtime/executor-scope-task.js +21 -0
  50. package/dist/runtime/executor-tasks.d.ts +2 -1
  51. package/dist/runtime/executor-tasks.js +4 -4
  52. package/dist/skill.js +1 -0
  53. package/dist/standalone/api-permissions.d.ts +10 -0
  54. package/dist/standalone/api-permissions.js +19 -2
  55. package/dist/standalone/background.d.ts +16 -0
  56. package/dist/standalone/background.js +69 -2
  57. package/dist/standalone/binary.d.ts +1 -1
  58. package/dist/standalone/binary.js +22 -8
  59. package/dist/standalone/build.d.ts +1 -1
  60. package/dist/standalone/build.js +38 -8
  61. package/dist/standalone/daemon.d.ts +1 -1
  62. package/dist/standalone/daemon.js +2 -1
  63. package/dist/standalone/dsm-window.d.ts +3 -1
  64. package/dist/standalone/dsm-window.js +72 -15
  65. package/dist/standalone/inspect-spk.d.ts +9 -1
  66. package/dist/standalone/inspect-spk.js +119 -26
  67. package/dist/standalone/lifecycle.js +86 -8
  68. package/dist/standalone/manifest.d.ts +13 -0
  69. package/dist/standalone/manifest.js +57 -8
  70. package/dist/standalone/native-authorization-window.d.ts +2 -0
  71. package/dist/standalone/native-authorization-window.js +30 -0
  72. package/dist/standalone/native-layout.d.ts +82 -0
  73. package/dist/standalone/native-layout.js +377 -0
  74. package/dist/standalone/native-root-window.d.ts +26 -0
  75. package/dist/standalone/native-root-window.js +282 -0
  76. package/dist/standalone/portal-window.d.ts +21 -0
  77. package/dist/standalone/portal-window.js +155 -0
  78. package/dist/standalone/portal.d.ts +4 -0
  79. package/dist/standalone/portal.js +4 -0
  80. package/dist/standalone/resource.d.ts +5 -3
  81. package/dist/standalone/resource.js +6 -3
  82. package/dist/standalone/root-window.js +62 -15
  83. package/dist/standalone/spk.d.ts +1 -1
  84. package/dist/standalone/spk.js +25 -7
  85. package/dist/templates/_daemon/main_test.go +61 -8
  86. package/dist/templates/_executor/README.md +127 -16
  87. package/dist/templates/_executor/anchor.go +146 -0
  88. package/dist/templates/_executor/anchor_test.go +126 -0
  89. package/dist/templates/_executor/apppriv_review_test.go +1 -1
  90. package/dist/templates/_executor/cancel_contract_test.go +236 -0
  91. package/dist/templates/_executor/copy.go +64 -0
  92. package/dist/templates/_executor/copy_test.go +88 -0
  93. package/dist/templates/_executor/dsm.go +23 -10
  94. package/dist/templates/_executor/dsm_test.go +95 -1
  95. package/dist/templates/_executor/executor.go +260 -49
  96. package/dist/templates/_executor/executor_test.go +36 -6
  97. package/dist/templates/_executor/identity.go +27 -1
  98. package/dist/templates/_executor/identity_kernel_linux_test.go +60 -0
  99. package/dist/templates/_executor/identity_linux.go +82 -0
  100. package/dist/templates/_executor/identity_security_test.go +43 -0
  101. package/dist/templates/_executor/internal/lifecycle/lifecycle.go +5 -0
  102. package/dist/templates/_executor/internal/lifecycle/lifecycle_test.go +61 -3
  103. package/dist/templates/_executor/internal/taskscript/boot.sh +9 -9
  104. package/dist/templates/_executor/internal/taskscript/cmd/main.go +2 -2
  105. package/dist/templates/_executor/internal/taskscript/control.sh +15 -10
  106. package/dist/templates/_executor/internal/taskscript/tasks.go +5 -3
  107. package/dist/templates/_executor/lifecycle_test.go +11 -0
  108. package/dist/templates/_executor/link_linux.go +28 -0
  109. package/dist/templates/_executor/long_running_test.go +530 -0
  110. package/dist/templates/_executor/main.go +72 -20
  111. package/dist/templates/_executor/move_linux.go +490 -0
  112. package/dist/templates/_executor/move_linux_test.go +460 -0
  113. package/dist/templates/_executor/move_validation.go +46 -0
  114. package/dist/templates/_executor/move_validation_test.go +187 -0
  115. package/dist/templates/_executor/operations.go +926 -0
  116. package/dist/templates/_executor/platform_linux.go +24 -173
  117. package/dist/templates/_executor/platform_linux_test.go +9 -65
  118. package/dist/templates/_executor/platform_other.go +30 -4
  119. package/dist/templates/_executor/process.go +3 -0
  120. package/dist/templates/_executor/records.go +242 -0
  121. package/dist/templates/_executor/scope_cancel_contract_test.go +91 -0
  122. package/dist/templates/_executor/scope_client.go +37 -0
  123. package/dist/templates/_executor/scope_contract.go +12 -0
  124. package/dist/templates/_executor/selected_scope.go +146 -0
  125. package/dist/templates/_executor/selected_scope_test.go +186 -0
  126. package/dist/templates/_executor/status_disabled_test.go +33 -0
  127. package/dist/templates/_executor/store.go +4 -3
  128. package/dist/templates/_executor/supervise.go +109 -0
  129. package/dist/templates/_executor/supervise_test.go +130 -0
  130. package/dist/templates/_executor/task_race_review_test.go +1 -1
  131. package/dist/templates/_executor/tasks.go +7 -8
  132. package/dist/templates/_executor/tasks_review_test.go +1 -1
  133. package/dist/templates/_executor/tasks_test.go +4 -4
  134. package/dist/templates/_executor/watch.go +8 -0
  135. package/dist/templates/_executor/watch_test.go +23 -2
  136. package/dist/templates/_executor/write_review_linux_test.go +4 -12
  137. package/dist/templates/_shared/AGENTS.md +129 -0
  138. package/dist/templates/binary/dsm-package.yaml +24 -0
  139. package/dist/templates/binary/i18n/messages/de.json +4 -0
  140. package/dist/templates/binary/i18n/messages/en.json +4 -0
  141. package/dist/templates/binary/i18n/messages/es.json +4 -0
  142. package/dist/templates/binary/i18n/messages/fr.json +4 -0
  143. package/dist/templates/binary/i18n/messages/it.json +4 -0
  144. package/dist/templates/binary/i18n/messages/ja.json +4 -0
  145. package/dist/templates/binary/i18n/messages/ko.json +4 -0
  146. package/dist/templates/binary/i18n/messages/zh-CN.json +4 -0
  147. package/dist/templates/binary/i18n/messages/zh-TW.json +4 -0
  148. package/dist/templates/binary/ui/app.js +19 -4
  149. package/dist/templates/native-authorization/AuthorizationGate.vue +91 -0
  150. package/dist/templates/native-authorization/i18n/de.json +37 -0
  151. package/dist/templates/native-authorization/i18n/en.json +37 -0
  152. package/dist/templates/native-authorization/i18n/es.json +37 -0
  153. package/dist/templates/native-authorization/i18n/fr.json +37 -0
  154. package/dist/templates/native-authorization/i18n/index.ts +15 -0
  155. package/dist/templates/native-authorization/i18n/it.json +37 -0
  156. package/dist/templates/native-authorization/i18n/ja.json +37 -0
  157. package/dist/templates/native-authorization/i18n/ko.json +37 -0
  158. package/dist/templates/native-authorization/i18n/zh-CN.json +37 -0
  159. package/dist/templates/native-authorization/i18n/zh-TW.json +37 -0
  160. package/dist/templates/native-go/README.md +43 -10
  161. package/dist/templates/native-go/backend/cmd/app/main.go +27 -7
  162. package/dist/templates/native-go/backend/internal/api/entry_test.go +47 -0
  163. package/dist/templates/native-go/backend/internal/api/permissions_test.go +3 -3
  164. package/dist/templates/native-go/backend/internal/api/registry.go +11 -0
  165. package/dist/templates/native-go/backend/internal/api/sdk-permissions.json +14 -1
  166. package/dist/templates/native-go/backend/internal/api/server.go +18 -5
  167. package/dist/templates/native-go/backend/internal/app/delegate_config.go +57 -0
  168. package/dist/templates/native-go/backend/internal/app/delegate_config_test.go +28 -0
  169. package/dist/templates/native-go/backend/internal/app/portal.go +30 -0
  170. package/dist/templates/native-go/backend/internal/app/portal_test.go +55 -0
  171. package/dist/templates/native-go/backend/internal/app/routes.go +8 -2
  172. package/dist/templates/native-go/backend/internal/background/runner.go +1 -1
  173. package/dist/templates/native-go/backend/internal/background/store.go +16 -14
  174. package/dist/templates/native-go/backend/internal/dsm/admin.go +8 -2
  175. package/dist/templates/native-go/backend/internal/dsm/admin_linux.go +43 -13
  176. package/dist/templates/native-go/backend/internal/dsm/admin_linux_test.go +56 -0
  177. package/dist/templates/native-go/backend/internal/dsm/admin_other.go +4 -1
  178. package/dist/templates/native-go/backend/internal/dsm/apppriv.go +30 -0
  179. package/dist/templates/native-go/backend/internal/dsm/bridge_file.go +75 -0
  180. package/dist/templates/native-go/backend/internal/dsm/bridge_file_test.go +57 -0
  181. package/dist/templates/native-go/backend/internal/dsm/entry.go +177 -0
  182. package/dist/templates/native-go/backend/internal/dsm/entry_test.go +315 -0
  183. package/dist/templates/native-go/backend/internal/dsm/native/admin-armv7.elf +0 -0
  184. package/dist/templates/native-go/backend/internal/dsm/native/apppriv-aarch64.elf +0 -0
  185. package/dist/templates/native-go/backend/internal/dsm/native/apppriv-armv7.elf +0 -0
  186. package/dist/templates/native-go/backend/internal/dsm/native/apppriv-x86_64.elf +0 -0
  187. package/dist/templates/native-go/backend/internal/dsm/native/apppriv_check.c +33 -0
  188. package/dist/templates/native-go/backend/internal/dsm/native/build.sh +13 -4
  189. package/dist/templates/native-go/backend/internal/dsm/native/provenance.json +9 -3
  190. package/dist/templates/native-go/backend/internal/filestation/check_permission.go +71 -0
  191. package/dist/templates/native-go/backend/internal/filestation/check_permission_test.go +77 -0
  192. package/dist/templates/native-go/backend/internal/filestation/sdk_policy_test.go +39 -0
  193. package/dist/templates/native-go/backend/internal/filestation/service.go +1 -1
  194. package/dist/templates/native-go/backend/internal/portal/portal.go +138 -0
  195. package/dist/templates/native-go/backend/internal/portal/portal_test.go +89 -0
  196. package/dist/templates/native-go/dsm-package.yaml +20 -1
  197. package/dist/templates/native-go/i18n/glossary.json +2 -1
  198. package/dist/templates/native-go/i18n/messages/de.json +1 -0
  199. package/dist/templates/native-go/i18n/messages/en.json +1 -0
  200. package/dist/templates/native-go/i18n/messages/es.json +1 -0
  201. package/dist/templates/native-go/i18n/messages/fr.json +1 -0
  202. package/dist/templates/native-go/i18n/messages/it.json +1 -0
  203. package/dist/templates/native-go/i18n/messages/ja.json +1 -0
  204. package/dist/templates/native-go/i18n/messages/ko.json +1 -0
  205. package/dist/templates/native-go/i18n/messages/zh-CN.json +1 -0
  206. package/dist/templates/native-go/i18n/messages/zh-TW.json +1 -0
  207. package/dist/templates/native-go/ui/app.css +10 -0
  208. package/dist/templates/native-go/ui/app.js +11 -1
  209. package/dist/templates/native-go-delegate/DELEGATE.md +126 -5
  210. package/dist/templates/native-go-delegate/backend/cmd/background-worker/main.go +7 -0
  211. package/dist/templates/native-go-delegate/backend/internal/app/delegate.go +11 -1
  212. package/dist/templates/native-go-delegate/backend/internal/app/delegate_routes_test.go +14 -0
  213. package/dist/templates/native-go-delegate/backend/internal/background/delegated_moves.go +270 -0
  214. package/dist/templates/native-go-delegate/backend/internal/delegate/admission_recovery_test.go +410 -0
  215. package/dist/templates/native-go-delegate/backend/internal/delegate/cancel_contract_test.go +95 -0
  216. package/dist/templates/native-go-delegate/backend/internal/delegate/client.go +8 -0
  217. package/dist/templates/native-go-delegate/backend/internal/delegate/destination.go +110 -0
  218. package/dist/templates/native-go-delegate/backend/internal/delegate/destination_state.go +117 -0
  219. package/dist/templates/native-go-delegate/backend/internal/delegate/destination_state_test.go +60 -0
  220. package/dist/templates/native-go-delegate/backend/internal/delegate/destination_test.go +116 -0
  221. package/dist/templates/native-go-delegate/backend/internal/delegate/example.go +81 -0
  222. package/dist/templates/native-go-delegate/backend/internal/delegate/example_test.go +91 -0
  223. package/dist/templates/native-go-delegate/backend/internal/delegate/executor_contract_test.go +511 -0
  224. package/dist/templates/native-go-delegate/backend/internal/delegate/files.go +1 -1
  225. package/dist/templates/native-go-delegate/backend/internal/delegate/long_running_routes.go +92 -0
  226. package/dist/templates/native-go-delegate/backend/internal/delegate/long_running_routes_test.go +99 -0
  227. package/dist/templates/native-go-delegate/backend/internal/delegate/move.go +348 -0
  228. package/dist/templates/native-go-delegate/backend/internal/delegate/move_test.go +351 -0
  229. package/dist/templates/native-go-delegate/backend/internal/delegate/operations_list.go +65 -0
  230. package/dist/templates/native-go-delegate/backend/internal/delegate/operations_list_test.go +114 -0
  231. package/dist/templates/native-go-delegate/backend/internal/delegate/retry_test.go +1 -1
  232. package/dist/templates/native-go-delegate/backend/internal/delegate/service.go +58 -17
  233. package/dist/templates/native-go-delegate/backend/internal/delegate/staging.go +121 -0
  234. package/dist/templates/native-go-delegate/backend/internal/delegate/status_disabled_test.go +51 -0
  235. package/dist/templates/native-go-delegate/backend/internal/delegate/testdata/executor_contract.txt +112 -0
  236. package/dist/templates/native-go-delegate/backend/internal/delegate/transient_contract_test.go +137 -0
  237. package/dist/templates/native-go-delegate/backend/internal/filestation/files.go +1 -31
  238. package/dist/templates/native-go-delegate/frontend/src/CapabilityPanels.vue +30 -3
  239. package/dist/templates/native-go-delegate/frontend/src/delegate/BackgroundSavePanel.vue +113 -0
  240. package/dist/templates/native-go-delegate/frontend/src/delegate/copy.ts +5 -6
  241. package/dist/templates/native-go-delegate/frontend/test/background-save.test.ts +121 -0
  242. package/dist/templates/native-go-delegate/frontend/test/scope-settings.test.ts +49 -0
  243. package/dist/templates/native-go-delegate/test.sh +1 -0
  244. package/dist/templates/native-go-jobs/frontend/src/background/i18n/de.json +2 -2
  245. package/dist/templates/native-go-jobs/frontend/src/background/i18n/en.json +2 -2
  246. package/dist/templates/native-go-jobs/frontend/src/background/i18n/es.json +12 -12
  247. package/dist/templates/native-go-jobs/frontend/src/background/i18n/fr.json +4 -4
  248. package/dist/templates/native-go-jobs/frontend/src/background/i18n/it.json +17 -17
  249. package/dist/templates/native-go-jobs/frontend/src/background/i18n/ja.json +7 -7
  250. package/dist/templates/native-go-jobs/frontend/src/background/i18n/ko.json +15 -15
  251. package/dist/templates/native-go-jobs/frontend/src/background/i18n/zh-CN.json +3 -3
  252. package/dist/templates/native-go-jobs/frontend/src/background/i18n/zh-TW.json +2 -2
  253. package/dist/templates/native-go-jobs/frontend/test/background.test.ts +25 -28
  254. package/dist/templates/native-go-vue/README.md +4 -0
  255. package/dist/templates/native-go-vue/frontend/package-lock.json +4 -4
  256. package/dist/templates/native-go-vue/frontend/package.json +1 -1
  257. package/dist/templates/native-go-vue/frontend/src/App.vue +18 -13
  258. package/dist/templates/native-go-vue/frontend/src/context.ts +31 -0
  259. package/dist/templates/native-go-vue/frontend/src/delegate/ExecutorSettings.vue +52 -8
  260. package/dist/templates/native-go-vue/frontend/src/delegate/catalogs.ts +11 -0
  261. package/dist/templates/native-go-vue/frontend/src/delegate/copy.test.ts +12 -0
  262. package/dist/templates/native-go-vue/frontend/src/delegate/copy.ts +4 -4
  263. package/dist/templates/native-go-vue/frontend/src/delegate/executor-setup.ts +4 -2
  264. package/dist/templates/native-go-vue/frontend/src/delegate/facade.test.ts +100 -0
  265. package/dist/templates/native-go-vue/frontend/src/delegate/facade.ts +85 -0
  266. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/de.json +46 -0
  267. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/en.json +12 -2
  268. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/es.json +46 -0
  269. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/fr.json +46 -0
  270. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/it.json +46 -0
  271. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/ja.json +46 -0
  272. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/ko.json +46 -0
  273. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/de.json +42 -0
  274. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/en.json +42 -0
  275. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/es.json +42 -0
  276. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/fr.json +42 -0
  277. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/it.json +42 -0
  278. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/ja.json +42 -0
  279. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/ko.json +42 -0
  280. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-CN.json +42 -0
  281. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-TW.json +42 -0
  282. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/zh-CN.json +46 -0
  283. package/dist/templates/native-go-vue/frontend/src/delegate/i18n/zh-TW.json +15 -5
  284. package/dist/templates/native-go-vue/frontend/src/delegate/long-running.ts +57 -0
  285. package/dist/templates/native-go-vue/frontend/src/delegate/save-copy.test.ts +12 -0
  286. package/dist/templates/native-go-vue/frontend/src/delegate/save-copy.ts +24 -0
  287. package/dist/templates/native-go-vue/frontend/src/delegate/scoped-picker.test.ts +12 -0
  288. package/dist/templates/native-go-vue/frontend/src/delegate/scoped-picker.ts +21 -0
  289. package/dist/templates/native-go-vue/frontend/src/files/files.test.ts +7 -0
  290. package/dist/templates/native-go-vue/frontend/src/i18n/de.json +20 -0
  291. package/dist/templates/native-go-vue/frontend/src/i18n/en.json +20 -0
  292. package/dist/templates/native-go-vue/frontend/src/i18n/es.json +20 -0
  293. package/dist/templates/native-go-vue/frontend/src/i18n/fr.json +20 -0
  294. package/dist/templates/native-go-vue/frontend/src/i18n/it.json +20 -0
  295. package/dist/templates/native-go-vue/frontend/src/i18n/ja.json +20 -0
  296. package/dist/templates/native-go-vue/frontend/src/i18n/ko.json +20 -0
  297. package/dist/templates/native-go-vue/frontend/src/i18n/zh-CN.json +20 -0
  298. package/dist/templates/native-go-vue/frontend/src/i18n/zh-TW.json +20 -0
  299. package/dist/templates/native-go-vue/frontend/src/i18n.ts +13 -0
  300. package/dist/templates/native-go-vue/frontend/src/identity/LoginPage.vue +16 -14
  301. package/dist/templates/native-go-vue/frontend/src/identity/i18n/de.json +27 -0
  302. package/dist/templates/native-go-vue/frontend/src/identity/i18n/en.json +27 -0
  303. package/dist/templates/native-go-vue/frontend/src/identity/i18n/es.json +27 -0
  304. package/dist/templates/native-go-vue/frontend/src/identity/i18n/fr.json +27 -0
  305. package/dist/templates/native-go-vue/frontend/src/identity/i18n/it.json +27 -0
  306. package/dist/templates/native-go-vue/frontend/src/identity/i18n/ja.json +27 -0
  307. package/dist/templates/native-go-vue/frontend/src/identity/i18n/ko.json +27 -0
  308. package/dist/templates/native-go-vue/frontend/src/identity/i18n/zh-CN.json +27 -0
  309. package/dist/templates/native-go-vue/frontend/src/identity/i18n/zh-TW.json +27 -0
  310. package/dist/templates/native-go-vue/frontend/src/identity/i18n.ts +14 -0
  311. package/dist/templates/native-go-vue/frontend/src/identity/session.test.ts +4 -0
  312. package/dist/templates/native-go-vue/frontend/src/identity/session.ts +9 -8
  313. package/dist/templates/native-go-vue/frontend/src/nas/NasPicker.vue +31 -12
  314. package/dist/templates/native-go-vue/frontend/src/nas/destination.test.ts +48 -0
  315. package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/de.json +1 -1
  316. package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/en.json +1 -1
  317. package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/es.json +10 -10
  318. package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/fr.json +1 -1
  319. package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/it.json +12 -12
  320. package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/ja.json +15 -15
  321. package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/ko.json +12 -12
  322. package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/zh-CN.json +1 -1
  323. package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/zh-TW.json +1 -1
  324. package/dist/templates/native-go-vue/frontend/src/portal/PortalSettings.vue +39 -0
  325. package/dist/templates/native-go-vue/frontend/src/shell/i18n/fr.json +1 -1
  326. package/dist/templates/native-go-vue/frontend/src/shell/i18n/ja.json +1 -1
  327. package/dist/templates/native-go-vue/frontend/test/apps.test.ts +14 -0
  328. package/dist/templates/native-go-vue/frontend/test/portal-settings.test.ts +71 -0
  329. package/dist/templates/native-go-vue/frontend/test/shell-i18n.test.ts +50 -0
  330. package/dist/validate.js +2 -1
  331. package/package.json +12 -2
  332. package/schema/package-metadata.schema.json +101 -0
  333. package/schema/synology-app.schema.json +112 -0
  334. package/skills/SKILL.md +109 -3
  335. package/skills/reference/create.md +101 -2
  336. package/skills/reference/deploy.md +2 -2
  337. package/skills/reference/files.md +113 -2
  338. package/skills/reference/identity.md +70 -1
  339. package/skills/reference/portal.md +17 -0
  340. package/skills/reference/ui-vue.md +12 -0
  341. package/templates/_daemon/main_test.go +61 -8
  342. package/templates/_executor/README.md +127 -16
  343. package/templates/_executor/anchor.go +146 -0
  344. package/templates/_executor/anchor_test.go +126 -0
  345. package/templates/_executor/apppriv_review_test.go +1 -1
  346. package/templates/_executor/cancel_contract_test.go +236 -0
  347. package/templates/_executor/copy.go +64 -0
  348. package/templates/_executor/copy_test.go +88 -0
  349. package/templates/_executor/dsm.go +23 -10
  350. package/templates/_executor/dsm_test.go +95 -1
  351. package/templates/_executor/executor.go +260 -49
  352. package/templates/_executor/executor_test.go +36 -6
  353. package/templates/_executor/identity.go +27 -1
  354. package/templates/_executor/identity_kernel_linux_test.go +60 -0
  355. package/templates/_executor/identity_linux.go +82 -0
  356. package/templates/_executor/identity_security_test.go +43 -0
  357. package/templates/_executor/internal/lifecycle/lifecycle.go +5 -0
  358. package/templates/_executor/internal/lifecycle/lifecycle_test.go +61 -3
  359. package/templates/_executor/internal/taskscript/boot.sh +9 -9
  360. package/templates/_executor/internal/taskscript/cmd/main.go +2 -2
  361. package/templates/_executor/internal/taskscript/control.sh +15 -10
  362. package/templates/_executor/internal/taskscript/tasks.go +5 -3
  363. package/templates/_executor/lifecycle_test.go +11 -0
  364. package/templates/_executor/link_linux.go +28 -0
  365. package/templates/_executor/long_running_test.go +530 -0
  366. package/templates/_executor/main.go +72 -20
  367. package/templates/_executor/move_linux.go +490 -0
  368. package/templates/_executor/move_linux_test.go +460 -0
  369. package/templates/_executor/move_validation.go +46 -0
  370. package/templates/_executor/move_validation_test.go +187 -0
  371. package/templates/_executor/operations.go +926 -0
  372. package/templates/_executor/platform_linux.go +24 -173
  373. package/templates/_executor/platform_linux_test.go +9 -65
  374. package/templates/_executor/platform_other.go +30 -4
  375. package/templates/_executor/process.go +3 -0
  376. package/templates/_executor/records.go +242 -0
  377. package/templates/_executor/scope_cancel_contract_test.go +91 -0
  378. package/templates/_executor/scope_client.go +37 -0
  379. package/templates/_executor/scope_contract.go +12 -0
  380. package/templates/_executor/selected_scope.go +146 -0
  381. package/templates/_executor/selected_scope_test.go +186 -0
  382. package/templates/_executor/status_disabled_test.go +33 -0
  383. package/templates/_executor/store.go +4 -3
  384. package/templates/_executor/supervise.go +109 -0
  385. package/templates/_executor/supervise_test.go +130 -0
  386. package/templates/_executor/task_race_review_test.go +1 -1
  387. package/templates/_executor/tasks.go +7 -8
  388. package/templates/_executor/tasks_review_test.go +1 -1
  389. package/templates/_executor/tasks_test.go +4 -4
  390. package/templates/_executor/watch.go +8 -0
  391. package/templates/_executor/watch_test.go +23 -2
  392. package/templates/_executor/write_review_linux_test.go +4 -12
  393. package/templates/_shared/AGENTS.md +129 -0
  394. package/templates/binary/dsm-package.yaml +24 -0
  395. package/templates/binary/i18n/messages/de.json +4 -0
  396. package/templates/binary/i18n/messages/en.json +4 -0
  397. package/templates/binary/i18n/messages/es.json +4 -0
  398. package/templates/binary/i18n/messages/fr.json +4 -0
  399. package/templates/binary/i18n/messages/it.json +4 -0
  400. package/templates/binary/i18n/messages/ja.json +4 -0
  401. package/templates/binary/i18n/messages/ko.json +4 -0
  402. package/templates/binary/i18n/messages/zh-CN.json +4 -0
  403. package/templates/binary/i18n/messages/zh-TW.json +4 -0
  404. package/templates/binary/ui/app.js +19 -4
  405. package/templates/native-authorization/AuthorizationGate.vue +91 -0
  406. package/templates/native-authorization/i18n/de.json +37 -0
  407. package/templates/native-authorization/i18n/en.json +37 -0
  408. package/templates/native-authorization/i18n/es.json +37 -0
  409. package/templates/native-authorization/i18n/fr.json +37 -0
  410. package/templates/native-authorization/i18n/index.ts +15 -0
  411. package/templates/native-authorization/i18n/it.json +37 -0
  412. package/templates/native-authorization/i18n/ja.json +37 -0
  413. package/templates/native-authorization/i18n/ko.json +37 -0
  414. package/templates/native-authorization/i18n/zh-CN.json +37 -0
  415. package/templates/native-authorization/i18n/zh-TW.json +37 -0
  416. package/templates/native-go/README.md +43 -10
  417. package/templates/native-go/backend/cmd/app/main.go +27 -7
  418. package/templates/native-go/backend/internal/api/entry_test.go +47 -0
  419. package/templates/native-go/backend/internal/api/permissions_test.go +3 -3
  420. package/templates/native-go/backend/internal/api/registry.go +11 -0
  421. package/templates/native-go/backend/internal/api/sdk-permissions.json +14 -1
  422. package/templates/native-go/backend/internal/api/server.go +18 -5
  423. package/templates/native-go/backend/internal/app/delegate_config.go +57 -0
  424. package/templates/native-go/backend/internal/app/delegate_config_test.go +28 -0
  425. package/templates/native-go/backend/internal/app/portal.go +30 -0
  426. package/templates/native-go/backend/internal/app/portal_test.go +55 -0
  427. package/templates/native-go/backend/internal/app/routes.go +8 -2
  428. package/templates/native-go/backend/internal/background/runner.go +1 -1
  429. package/templates/native-go/backend/internal/background/store.go +16 -14
  430. package/templates/native-go/backend/internal/dsm/admin.go +8 -2
  431. package/templates/native-go/backend/internal/dsm/admin_linux.go +43 -13
  432. package/templates/native-go/backend/internal/dsm/admin_linux_test.go +56 -0
  433. package/templates/native-go/backend/internal/dsm/admin_other.go +4 -1
  434. package/templates/native-go/backend/internal/dsm/apppriv.go +30 -0
  435. package/templates/native-go/backend/internal/dsm/bridge_file.go +75 -0
  436. package/templates/native-go/backend/internal/dsm/bridge_file_test.go +57 -0
  437. package/templates/native-go/backend/internal/dsm/entry.go +177 -0
  438. package/templates/native-go/backend/internal/dsm/entry_test.go +315 -0
  439. package/templates/native-go/backend/internal/dsm/native/admin-armv7.elf +0 -0
  440. package/templates/native-go/backend/internal/dsm/native/apppriv-aarch64.elf +0 -0
  441. package/templates/native-go/backend/internal/dsm/native/apppriv-armv7.elf +0 -0
  442. package/templates/native-go/backend/internal/dsm/native/apppriv-x86_64.elf +0 -0
  443. package/templates/native-go/backend/internal/dsm/native/apppriv_check.c +33 -0
  444. package/templates/native-go/backend/internal/dsm/native/build.sh +13 -4
  445. package/templates/native-go/backend/internal/dsm/native/provenance.json +9 -3
  446. package/templates/native-go/backend/internal/filestation/check_permission.go +71 -0
  447. package/templates/native-go/backend/internal/filestation/check_permission_test.go +77 -0
  448. package/templates/native-go/backend/internal/filestation/sdk_policy_test.go +39 -0
  449. package/templates/native-go/backend/internal/filestation/service.go +1 -1
  450. package/templates/native-go/backend/internal/portal/portal.go +138 -0
  451. package/templates/native-go/backend/internal/portal/portal_test.go +89 -0
  452. package/templates/native-go/dsm-package.yaml +20 -1
  453. package/templates/native-go/i18n/glossary.json +2 -1
  454. package/templates/native-go/i18n/messages/de.json +1 -0
  455. package/templates/native-go/i18n/messages/en.json +1 -0
  456. package/templates/native-go/i18n/messages/es.json +1 -0
  457. package/templates/native-go/i18n/messages/fr.json +1 -0
  458. package/templates/native-go/i18n/messages/it.json +1 -0
  459. package/templates/native-go/i18n/messages/ja.json +1 -0
  460. package/templates/native-go/i18n/messages/ko.json +1 -0
  461. package/templates/native-go/i18n/messages/zh-CN.json +1 -0
  462. package/templates/native-go/i18n/messages/zh-TW.json +1 -0
  463. package/templates/native-go/ui/app.css +10 -0
  464. package/templates/native-go/ui/app.js +11 -1
  465. package/templates/native-go-delegate/DELEGATE.md +126 -5
  466. package/templates/native-go-delegate/backend/cmd/background-worker/main.go +7 -0
  467. package/templates/native-go-delegate/backend/internal/app/delegate.go +11 -1
  468. package/templates/native-go-delegate/backend/internal/app/delegate_routes_test.go +14 -0
  469. package/templates/native-go-delegate/backend/internal/background/delegated_moves.go +270 -0
  470. package/templates/native-go-delegate/backend/internal/delegate/admission_recovery_test.go +410 -0
  471. package/templates/native-go-delegate/backend/internal/delegate/cancel_contract_test.go +95 -0
  472. package/templates/native-go-delegate/backend/internal/delegate/client.go +8 -0
  473. package/templates/native-go-delegate/backend/internal/delegate/destination.go +110 -0
  474. package/templates/native-go-delegate/backend/internal/delegate/destination_state.go +117 -0
  475. package/templates/native-go-delegate/backend/internal/delegate/destination_state_test.go +60 -0
  476. package/templates/native-go-delegate/backend/internal/delegate/destination_test.go +116 -0
  477. package/templates/native-go-delegate/backend/internal/delegate/example.go +81 -0
  478. package/templates/native-go-delegate/backend/internal/delegate/example_test.go +91 -0
  479. package/templates/native-go-delegate/backend/internal/delegate/executor_contract_test.go +511 -0
  480. package/templates/native-go-delegate/backend/internal/delegate/files.go +1 -1
  481. package/templates/native-go-delegate/backend/internal/delegate/long_running_routes.go +92 -0
  482. package/templates/native-go-delegate/backend/internal/delegate/long_running_routes_test.go +99 -0
  483. package/templates/native-go-delegate/backend/internal/delegate/move.go +348 -0
  484. package/templates/native-go-delegate/backend/internal/delegate/move_test.go +351 -0
  485. package/templates/native-go-delegate/backend/internal/delegate/operations_list.go +65 -0
  486. package/templates/native-go-delegate/backend/internal/delegate/operations_list_test.go +114 -0
  487. package/templates/native-go-delegate/backend/internal/delegate/retry_test.go +1 -1
  488. package/templates/native-go-delegate/backend/internal/delegate/service.go +58 -17
  489. package/templates/native-go-delegate/backend/internal/delegate/staging.go +121 -0
  490. package/templates/native-go-delegate/backend/internal/delegate/status_disabled_test.go +51 -0
  491. package/templates/native-go-delegate/backend/internal/delegate/testdata/executor_contract.txt +112 -0
  492. package/templates/native-go-delegate/backend/internal/delegate/transient_contract_test.go +137 -0
  493. package/templates/native-go-delegate/backend/internal/filestation/files.go +1 -31
  494. package/templates/native-go-delegate/frontend/src/CapabilityPanels.vue +30 -3
  495. package/templates/native-go-delegate/frontend/src/delegate/BackgroundSavePanel.vue +113 -0
  496. package/templates/native-go-delegate/frontend/src/delegate/copy.ts +5 -6
  497. package/templates/native-go-delegate/frontend/test/background-save.test.ts +121 -0
  498. package/templates/native-go-delegate/frontend/test/scope-settings.test.ts +49 -0
  499. package/templates/native-go-delegate/test.sh +1 -0
  500. package/templates/native-go-jobs/frontend/src/background/i18n/de.json +2 -2
  501. package/templates/native-go-jobs/frontend/src/background/i18n/en.json +2 -2
  502. package/templates/native-go-jobs/frontend/src/background/i18n/es.json +12 -12
  503. package/templates/native-go-jobs/frontend/src/background/i18n/fr.json +4 -4
  504. package/templates/native-go-jobs/frontend/src/background/i18n/it.json +17 -17
  505. package/templates/native-go-jobs/frontend/src/background/i18n/ja.json +7 -7
  506. package/templates/native-go-jobs/frontend/src/background/i18n/ko.json +15 -15
  507. package/templates/native-go-jobs/frontend/src/background/i18n/zh-CN.json +3 -3
  508. package/templates/native-go-jobs/frontend/src/background/i18n/zh-TW.json +2 -2
  509. package/templates/native-go-jobs/frontend/test/background.test.ts +25 -28
  510. package/templates/native-go-vue/README.md +4 -0
  511. package/templates/native-go-vue/frontend/package-lock.json +4 -4
  512. package/templates/native-go-vue/frontend/package.json +1 -1
  513. package/templates/native-go-vue/frontend/src/App.vue +18 -13
  514. package/templates/native-go-vue/frontend/src/context.ts +31 -0
  515. package/templates/native-go-vue/frontend/src/delegate/ExecutorSettings.vue +52 -8
  516. package/templates/native-go-vue/frontend/src/delegate/catalogs.ts +11 -0
  517. package/templates/native-go-vue/frontend/src/delegate/copy.test.ts +12 -0
  518. package/templates/native-go-vue/frontend/src/delegate/copy.ts +4 -4
  519. package/templates/native-go-vue/frontend/src/delegate/executor-setup.ts +4 -2
  520. package/templates/native-go-vue/frontend/src/delegate/facade.test.ts +100 -0
  521. package/templates/native-go-vue/frontend/src/delegate/facade.ts +85 -0
  522. package/templates/native-go-vue/frontend/src/delegate/i18n/de.json +46 -0
  523. package/templates/native-go-vue/frontend/src/delegate/i18n/en.json +12 -2
  524. package/templates/native-go-vue/frontend/src/delegate/i18n/es.json +46 -0
  525. package/templates/native-go-vue/frontend/src/delegate/i18n/fr.json +46 -0
  526. package/templates/native-go-vue/frontend/src/delegate/i18n/it.json +46 -0
  527. package/templates/native-go-vue/frontend/src/delegate/i18n/ja.json +46 -0
  528. package/templates/native-go-vue/frontend/src/delegate/i18n/ko.json +46 -0
  529. package/templates/native-go-vue/frontend/src/delegate/i18n/save/de.json +42 -0
  530. package/templates/native-go-vue/frontend/src/delegate/i18n/save/en.json +42 -0
  531. package/templates/native-go-vue/frontend/src/delegate/i18n/save/es.json +42 -0
  532. package/templates/native-go-vue/frontend/src/delegate/i18n/save/fr.json +42 -0
  533. package/templates/native-go-vue/frontend/src/delegate/i18n/save/it.json +42 -0
  534. package/templates/native-go-vue/frontend/src/delegate/i18n/save/ja.json +42 -0
  535. package/templates/native-go-vue/frontend/src/delegate/i18n/save/ko.json +42 -0
  536. package/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-CN.json +42 -0
  537. package/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-TW.json +42 -0
  538. package/templates/native-go-vue/frontend/src/delegate/i18n/zh-CN.json +46 -0
  539. package/templates/native-go-vue/frontend/src/delegate/i18n/zh-TW.json +15 -5
  540. package/templates/native-go-vue/frontend/src/delegate/long-running.ts +57 -0
  541. package/templates/native-go-vue/frontend/src/delegate/save-copy.test.ts +12 -0
  542. package/templates/native-go-vue/frontend/src/delegate/save-copy.ts +24 -0
  543. package/templates/native-go-vue/frontend/src/delegate/scoped-picker.test.ts +12 -0
  544. package/templates/native-go-vue/frontend/src/delegate/scoped-picker.ts +21 -0
  545. package/templates/native-go-vue/frontend/src/files/files.test.ts +7 -0
  546. package/templates/native-go-vue/frontend/src/i18n/de.json +20 -0
  547. package/templates/native-go-vue/frontend/src/i18n/en.json +20 -0
  548. package/templates/native-go-vue/frontend/src/i18n/es.json +20 -0
  549. package/templates/native-go-vue/frontend/src/i18n/fr.json +20 -0
  550. package/templates/native-go-vue/frontend/src/i18n/it.json +20 -0
  551. package/templates/native-go-vue/frontend/src/i18n/ja.json +20 -0
  552. package/templates/native-go-vue/frontend/src/i18n/ko.json +20 -0
  553. package/templates/native-go-vue/frontend/src/i18n/zh-CN.json +20 -0
  554. package/templates/native-go-vue/frontend/src/i18n/zh-TW.json +20 -0
  555. package/templates/native-go-vue/frontend/src/i18n.ts +13 -0
  556. package/templates/native-go-vue/frontend/src/identity/LoginPage.vue +16 -14
  557. package/templates/native-go-vue/frontend/src/identity/i18n/de.json +27 -0
  558. package/templates/native-go-vue/frontend/src/identity/i18n/en.json +27 -0
  559. package/templates/native-go-vue/frontend/src/identity/i18n/es.json +27 -0
  560. package/templates/native-go-vue/frontend/src/identity/i18n/fr.json +27 -0
  561. package/templates/native-go-vue/frontend/src/identity/i18n/it.json +27 -0
  562. package/templates/native-go-vue/frontend/src/identity/i18n/ja.json +27 -0
  563. package/templates/native-go-vue/frontend/src/identity/i18n/ko.json +27 -0
  564. package/templates/native-go-vue/frontend/src/identity/i18n/zh-CN.json +27 -0
  565. package/templates/native-go-vue/frontend/src/identity/i18n/zh-TW.json +27 -0
  566. package/templates/native-go-vue/frontend/src/identity/i18n.ts +14 -0
  567. package/templates/native-go-vue/frontend/src/identity/session.test.ts +4 -0
  568. package/templates/native-go-vue/frontend/src/identity/session.ts +9 -8
  569. package/templates/native-go-vue/frontend/src/nas/NasPicker.vue +31 -12
  570. package/templates/native-go-vue/frontend/src/nas/destination.test.ts +48 -0
  571. package/templates/native-go-vue/frontend/src/nas/i18n/files/de.json +1 -1
  572. package/templates/native-go-vue/frontend/src/nas/i18n/files/en.json +1 -1
  573. package/templates/native-go-vue/frontend/src/nas/i18n/files/es.json +10 -10
  574. package/templates/native-go-vue/frontend/src/nas/i18n/files/fr.json +1 -1
  575. package/templates/native-go-vue/frontend/src/nas/i18n/files/it.json +12 -12
  576. package/templates/native-go-vue/frontend/src/nas/i18n/files/ja.json +15 -15
  577. package/templates/native-go-vue/frontend/src/nas/i18n/files/ko.json +12 -12
  578. package/templates/native-go-vue/frontend/src/nas/i18n/files/zh-CN.json +1 -1
  579. package/templates/native-go-vue/frontend/src/nas/i18n/files/zh-TW.json +1 -1
  580. package/templates/native-go-vue/frontend/src/portal/PortalSettings.vue +39 -0
  581. package/templates/native-go-vue/frontend/src/shell/i18n/fr.json +1 -1
  582. package/templates/native-go-vue/frontend/src/shell/i18n/ja.json +1 -1
  583. package/templates/native-go-vue/frontend/test/apps.test.ts +14 -0
  584. package/templates/native-go-vue/frontend/test/portal-settings.test.ts +71 -0
  585. package/templates/native-go-vue/frontend/test/shell-i18n.test.ts +50 -0
@@ -20,15 +20,22 @@ import (
20
20
 
21
21
  // Set by `synopkgland build-spk` through -ldflags -X; never read from a request.
22
22
  var (
23
- delegateScope = ""
24
- executorDigest = ""
25
- policyDigest = ""
26
- packageID = "dev"
27
- version = "0.0.0"
23
+ delegateScope = ""
24
+ delegateOperationsJSON = ""
25
+ delegateDestinationsJSON = ""
26
+ delegateLifetime = ""
27
+ executorDigest = ""
28
+ policyDigest = ""
29
+ packageID = "dev"
30
+ version = "0.0.0"
28
31
  // "session" when the project opted into the interactive File Station adapter.
29
32
  fileStation = ""
30
33
  // "standalone" enables the SDK identity adapter; the runtime owns authentication.
31
34
  identity = ""
35
+ // dsm-package.yaml entry: "admin-only" or "app-privilege"; empty keeps the route policy alone.
36
+ entry = ""
37
+ // "on" when dsm-package.yaml declares portal: serves portal.status.
38
+ portal = ""
32
39
  )
33
40
 
34
41
  func main() {
@@ -39,15 +46,24 @@ func main() {
39
46
  os.Exit(2)
40
47
  }
41
48
  cfg := app.Config{
42
- DelegateScope: delegateScope,
43
- ExecutorDigest: executorDigest, PolicyDigest: policyDigest,
49
+ DelegateScope: delegateScope,
50
+ DelegateOperationsJSON: delegateOperationsJSON,
51
+ DelegateDestinationsJSON: delegateDestinationsJSON,
52
+ DelegateLifetime: delegateLifetime,
53
+ ExecutorDigest: executorDigest, PolicyDigest: policyDigest,
44
54
  PackageID: packageID,
45
55
  Version: version,
46
56
  DataDir: "/var/packages/" + packageID + "/var",
57
+ Portal: portal == "on",
58
+ }
59
+ if _, err := app.ParseDelegateConfig(cfg); err != nil {
60
+ log.Fatal(err)
47
61
  }
48
62
  if app.SessionFilesEnabled(fileStation) {
49
63
  cfg.SessionFiles = filestation.Local(cfg.DataDir)
50
64
  }
65
+ // Kernels without memfd_create stage DSM's bridges in the package's own temp.
66
+ dsm.SetBridgeFallbackDir("/var/packages/" + packageID + "/tmp")
51
67
  var auth api.Authenticator = dsm.NewAuthenticator()
52
68
  var standalone *standaloneidentity.Service
53
69
  if identity == "standalone" {
@@ -58,6 +74,10 @@ func main() {
58
74
  }
59
75
  auth = standalone
60
76
  }
77
+ auth, err := dsm.NewEntryGate(auth, entry, packageID, cfg.DataDir)
78
+ if err != nil {
79
+ log.Fatal(err)
80
+ }
61
81
  srv, err := api.NewServer(auth, app.Routes(cfg)...)
62
82
  if err != nil {
63
83
  log.Fatal(err)
@@ -0,0 +1,47 @@
1
+ package api
2
+
3
+ import (
4
+ "context"
5
+ "encoding/json"
6
+ "errors"
7
+ "testing"
8
+ )
9
+
10
+ func TestEntryRefusalsReachTheBrowserAsStableCodes(t *testing.T) {
11
+ raw := []byte(`{"schema":1,"default":"administrators","methods":{"demo.user":"authenticated"}}`)
12
+ for _, tc := range []struct {
13
+ err error
14
+ code string
15
+ }{
16
+ {ErrAdminRequired, "admin_required"},
17
+ {ErrAppPrivilegeDenied, "app_privilege_denied"},
18
+ {errors.New("bridge exited 2"), "auth_unavailable"},
19
+ } {
20
+ executed := 0
21
+ srv, err := NewServerWithPermissions(&fakeAuth{err: tc.err}, raw, Handle("demo.user", func(context.Context, Caller, json.RawMessage) (any, error) {
22
+ executed++
23
+ return nil, nil
24
+ }))
25
+ if err != nil {
26
+ t.Fatal(err)
27
+ }
28
+ for _, method := range []string{"demo.user", "future.unknown"} {
29
+ _, env := post(t, srv, `{"method":"`+method+`"}`)
30
+ if env.Error == nil || env.Error.Code != tc.code || executed != 0 {
31
+ t.Fatalf("%v %s: %+v executed=%d", tc.err, method, env.Error, executed)
32
+ }
33
+ }
34
+ }
35
+ }
36
+
37
+ func TestRequireAdminLetsHandlersReserveGlobalSettings(t *testing.T) {
38
+ if err := RequireAdmin(Caller{identity: Identity{User: "alice", Admin: true}, authenticated: true}); err != nil {
39
+ t.Fatal(err)
40
+ }
41
+ for _, c := range []Caller{{identity: Identity{User: "bob"}, authenticated: true}, {identity: Identity{User: "alice", Admin: true}}, {}} {
42
+ var apiErr *Error
43
+ if err := RequireAdmin(c); !errors.As(err, &apiErr) || apiErr.Code != "admin_required" {
44
+ t.Fatalf("%+v: %v", c, err)
45
+ }
46
+ }
47
+ }
@@ -9,7 +9,7 @@ import (
9
9
 
10
10
  func TestDefaultPermissionsRequireAdministratorGroup(t *testing.T) {
11
11
  for _, makeRoute := range []func(string, Handler) Route{User, Public, Admin} {
12
- for _, method := range []string{"future.read", "future.unknown"} {
12
+ for method, code := range map[string]string{"future.read": "admin_required", "future.unknown": "unknown_method"} {
13
13
  executed := 0
14
14
  auth := &fakeAuth{user: "admin"} // Name alone confers no group membership.
15
15
  srv, err := NewServer(auth, makeRoute("future.read", func(context.Context, Caller, json.RawMessage) (any, error) {
@@ -20,7 +20,7 @@ func TestDefaultPermissionsRequireAdministratorGroup(t *testing.T) {
20
20
  t.Fatal(err)
21
21
  }
22
22
  _, env := post(t, srv, `{"method":"`+method+`","params":{"admin":true,"groups":["administrators"]}}`)
23
- if env.Error == nil || env.Error.Code != "admin_required" || executed != 0 || auth.calls != 1 {
23
+ if env.Error == nil || env.Error.Code != code || executed != 0 || auth.calls != 1 {
24
24
  t.Fatalf("method=%s error=%+v executed=%d auth=%d", method, env.Error, executed, auth.calls)
25
25
  }
26
26
  }
@@ -39,7 +39,7 @@ func TestCentralPermissionsAreTheOnlyAccessDecision(t *testing.T) {
39
39
  t.Fatal(err)
40
40
  }
41
41
  for _, tc := range []struct{ method, code string }{
42
- {"demo.user", ""}, {"demo.ping", ""}, {"demo.private", "admin_required"}, {"future.unknown", "admin_required"},
42
+ {"demo.user", ""}, {"demo.ping", ""}, {"demo.private", "admin_required"}, {"future.unknown", "unknown_method"},
43
43
  } {
44
44
  _, env := post(t, srv, `{"method":"`+tc.method+`"}`)
45
45
  if tc.code == "" {
@@ -102,6 +102,17 @@ func (c Caller) Authenticated() bool { return c.authenticated }
102
102
  func (c Caller) User() string { return c.identity.User }
103
103
  func (c Caller) Admin() bool { return c.authenticated && c.identity.Admin }
104
104
 
105
+ var adminRequired = &Error{"admin_required", "this action needs the DSM administrators group"}
106
+
107
+ // RequireAdmin reserves part of a shared route, such as global settings, for
108
+ // DSM administrators. Whole routes are reserved in permissions.json instead.
109
+ func RequireAdmin(c Caller) error {
110
+ if !c.Admin() {
111
+ return adminRequired
112
+ }
113
+ return nil
114
+ }
115
+
105
116
  var methodName = regexp.MustCompile(`^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$`)
106
117
 
107
118
  func buildRegistry(routes []Route) (map[string]Route, error) {
@@ -23,6 +23,9 @@
23
23
  "bg.jobs.purge": "administrators",
24
24
  "bg.schedules.enable": "administrators"
25
25
  },
26
+ "portal": {
27
+ "portal.status": "authenticated"
28
+ },
26
29
  "identity": {
27
30
  "identity.status": "public",
28
31
  "identity.login": "public",
@@ -35,12 +38,22 @@
35
38
  "root.run": "administrators"
36
39
  },
37
40
  "delegate": {
41
+ "delegate.destination": "authenticated",
38
42
  "delegate.status": "authenticated",
39
43
  "delegate.create": "authenticated",
40
44
  "delegate.list": "authenticated",
41
45
  "delegate.revoke": "authenticated",
42
46
  "delegate.jobs.submit": "authenticated",
43
47
  "delegate.jobs.list": "authenticated",
44
- "delegate.jobs.cancel": "authenticated"
48
+ "delegate.jobs.cancel": "authenticated",
49
+ "delegate.select_destination": "authenticated",
50
+ "delegate.move_from_staging": "authenticated",
51
+ "delegate.operations.get": "authenticated",
52
+ "delegate.operations.list": "authenticated",
53
+ "delegate.operations.cancel": "authenticated",
54
+ "delegate.disable": "administrators",
55
+ "delegate.enable": "administrators",
56
+ "delegate.audit": "authenticated",
57
+ "delegate.example.export": "authenticated"
45
58
  }
46
59
  }
@@ -40,6 +40,13 @@ func WithRequestDeadline(next http.Handler) http.Handler {
40
40
  // ErrNoSession means the request carries no valid DSM session.
41
41
  var ErrNoSession = errors.New("no valid DSM session")
42
42
 
43
+ // ErrAdminRequired is an entry refusal: the app admits only administrators.
44
+ var ErrAdminRequired = errors.New("app entry requires an administrator")
45
+
46
+ // ErrAppPrivilegeDenied is an entry refusal: DSM Application Privileges do not
47
+ // allow this account to use the app from this address.
48
+ var ErrAppPrivilegeDenied = errors.New("DSM Application Privileges deny this app")
49
+
43
50
  // Authenticator verifies the DSM session behind a request.
44
51
  type Authenticator interface {
45
52
  Authenticate(r *http.Request) (Identity, error)
@@ -212,18 +219,24 @@ func (s *Server) authorize(r *http.Request, method string) (Caller, Route, *Erro
212
219
  if errors.Is(err, ErrNoSession) {
213
220
  return Caller{}, Route{}, &Error{"session_required", "sign in to DSM again"}
214
221
  }
222
+ if errors.Is(err, ErrAdminRequired) {
223
+ return Caller{}, Route{}, adminRequired
224
+ }
225
+ if errors.Is(err, ErrAppPrivilegeDenied) {
226
+ return Caller{}, Route{}, &Error{"app_privilege_denied", "DSM Application Privileges do not allow this account to use this app"}
227
+ }
215
228
  if err != nil {
216
229
  log.Printf("authentication unavailable: %v", err)
217
230
  return Caller{}, Route{}, &Error{"auth_unavailable", "DSM authentication is unavailable"}
218
231
  }
219
- // Unknown methods inherit the fixed administrators default before revealing
220
- // whether a handler exists. Route constructors never grant permission.
221
- if (!known || route.policy == policyAdmin) && !identity.Admin {
222
- return Caller{}, Route{}, &Error{"admin_required", "this action needs the DSM administrators group"}
223
- }
232
+ // Signed-in callers learn that a method is unregistered; method names
233
+ // already ship in the app's UI. Route constructors never grant permission.
224
234
  if !known {
225
235
  return Caller{}, Route{}, &Error{"unknown_method", "unknown method"}
226
236
  }
237
+ if route.policy == policyAdmin && !identity.Admin {
238
+ return Caller{}, Route{}, adminRequired
239
+ }
227
240
  caller := Caller{identity: identity, authenticated: true}
228
241
  return caller, route, nil
229
242
  }
@@ -0,0 +1,57 @@
1
+ package app
2
+
3
+ import (
4
+ "encoding/json"
5
+ "errors"
6
+ "regexp"
7
+ )
8
+
9
+ type DelegateSettings struct {
10
+ Scope string
11
+ Operations, Destinations []string
12
+ Lifetime string
13
+ }
14
+
15
+ var destinationKey = regexp.MustCompile(`^[a-z][a-z0-9_-]{0,63}$`)
16
+
17
+ // ParseDelegateConfig consumes only build/startup settings. Legacy declarations
18
+ // retain their TTL/job branch; absent extension fields never imply permanence.
19
+ func ParseDelegateConfig(cfg Config) (DelegateSettings, error) {
20
+ out := DelegateSettings{Scope: cfg.DelegateScope, Lifetime: cfg.DelegateLifetime}
21
+ invalid := errors.New("invalid delegate build configuration")
22
+ if cfg.DelegateOperationsJSON != "" && json.Unmarshal([]byte(cfg.DelegateOperationsJSON), &out.Operations) != nil {
23
+ return DelegateSettings{}, invalid
24
+ }
25
+ if cfg.DelegateDestinationsJSON != "" && json.Unmarshal([]byte(cfg.DelegateDestinationsJSON), &out.Destinations) != nil {
26
+ return DelegateSettings{}, invalid
27
+ }
28
+ if out.Lifetime == "" {
29
+ if len(out.Destinations) != 0 {
30
+ return DelegateSettings{}, invalid
31
+ }
32
+ seen := map[string]bool{}
33
+ for _, op := range out.Operations {
34
+ switch op {
35
+ case "files.list", "files.info", "files.createFolder", "files.checkPermission", "files.write":
36
+ default:
37
+ return DelegateSettings{}, invalid
38
+ }
39
+ if seen[op] {
40
+ return DelegateSettings{}, invalid
41
+ }
42
+ seen[op] = true
43
+ }
44
+ return out, nil
45
+ }
46
+ if out.Lifetime != "until-revoked" || out.Scope == "" || len(out.Operations) != 1 || out.Operations[0] != "files.moveFromStaging" || len(out.Destinations) == 0 || len(out.Destinations) > 64 {
47
+ return DelegateSettings{}, invalid
48
+ }
49
+ seen := map[string]bool{}
50
+ for _, key := range out.Destinations {
51
+ if !destinationKey.MatchString(key) || seen[key] {
52
+ return DelegateSettings{}, invalid
53
+ }
54
+ seen[key] = true
55
+ }
56
+ return out, nil
57
+ }
@@ -0,0 +1,28 @@
1
+ package app
2
+
3
+ import "testing"
4
+
5
+ func TestDelegateBuildConfigStrictlySeparatesLegacyAndPermanent(t *testing.T) {
6
+ valid := Config{DelegateScope: "home", DelegateOperationsJSON: `["files.moveFromStaging"]`, DelegateDestinationsJSON: `["save"]`, DelegateLifetime: "until-revoked"}
7
+ settings, err := ParseDelegateConfig(valid)
8
+ if err != nil || settings.Lifetime != "until-revoked" || len(settings.Destinations) != 1 {
9
+ t.Fatal(settings, err)
10
+ }
11
+ for _, cfg := range []Config{{}, {DelegateScope: "home"}, {DelegateScope: "home", DelegateOperationsJSON: `["files.write"]`}} {
12
+ settings, err = ParseDelegateConfig(cfg)
13
+ if err != nil || settings.Lifetime != "" || len(settings.Destinations) != 0 {
14
+ t.Fatal("legacy changed", settings, err)
15
+ }
16
+ }
17
+ for _, mutate := range []func(*Config){
18
+ func(c *Config) { c.DelegateLifetime = "" }, func(c *Config) { c.DelegateScope = "" }, func(c *Config) { c.DelegateOperationsJSON = `["files.write"]` },
19
+ func(c *Config) { c.DelegateDestinationsJSON = `["save","save"]` }, func(c *Config) { c.DelegateDestinationsJSON = `["Save"]` }, func(c *Config) { c.DelegateDestinationsJSON = `[]` }, func(c *Config) { c.DelegateDestinationsJSON = `null` },
20
+ func(c *Config) { c.DelegateDestinationsJSON = `["save"] {}` },
21
+ } {
22
+ cfg := valid
23
+ mutate(&cfg)
24
+ if _, err = ParseDelegateConfig(cfg); err == nil {
25
+ t.Fatal("invalid trusted config accepted", cfg)
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,30 @@
1
+ package app
2
+
3
+ import (
4
+ "context"
5
+ "encoding/json"
6
+
7
+ "dsmapp/internal/api"
8
+ "dsmapp/internal/portal"
9
+ )
10
+
11
+ // portalRoutes serves portal.status when dsm-package.yaml declares `portal`.
12
+ // An administrator sets the alias with DSM's own AppPortal API from the UI;
13
+ // the package only reads DSM's saved setting.
14
+ func (cfg Config) portalRoutes() []api.Route {
15
+ if !cfg.Portal {
16
+ return nil
17
+ }
18
+ return []api.Route{api.Handle("portal.status", cfg.portalStatus)}
19
+ }
20
+
21
+ func (cfg Config) portalStatus(_ context.Context, _ api.Caller, params json.RawMessage) (any, error) {
22
+ if err := decodeParams(params, &struct{}{}); err != nil {
23
+ return nil, err
24
+ }
25
+ path := cfg.PortalConfig
26
+ if path == "" {
27
+ path = portal.ConfigPath(cfg.PackageID)
28
+ }
29
+ return portal.Read(path, "SYNO.SDS."+cfg.PackageID+".Instance"), nil
30
+ }
@@ -0,0 +1,55 @@
1
+ package app
2
+
3
+ import (
4
+ "os"
5
+ "path/filepath"
6
+ "testing"
7
+ )
8
+
9
+ func portalConfig(t *testing.T, saved string) Config {
10
+ cfg := testConfig(t)
11
+ cfg.Portal = true
12
+ cfg.PortalConfig = filepath.Join(t.TempDir(), "AppPortal.json")
13
+ if saved != "" {
14
+ if err := os.WriteFile(cfg.PortalConfig, []byte(saved), 0o644); err != nil {
15
+ t.Fatal(err)
16
+ }
17
+ }
18
+ return cfg
19
+ }
20
+
21
+ func TestPortalStatusTellsEverySignedInUserTheAlias(t *testing.T) {
22
+ cfg := portalConfig(t, `{"alias":"hello-go","id":"SYNO.SDS.HelloGo.Instance","version":3}`)
23
+ code, out := call(t, cfg, bob, "portal.status", `{}`)
24
+ if code != "" {
25
+ t.Fatalf("%q %v", code, out)
26
+ }
27
+ data := out["data"].(map[string]any)
28
+ if data["state"] != "active" || data["alias"] != "hello-go" {
29
+ t.Fatalf("%v", data)
30
+ }
31
+ if code, _ := call(t, cfg, nobody, "portal.status", `{}`); code != "session_required" {
32
+ t.Fatalf("anonymous: %q", code)
33
+ }
34
+ if code, _ := call(t, cfg, bob, "portal.status", `{"alias":"x"}`); code != "bad_request" {
35
+ t.Fatalf("params: %q", code)
36
+ }
37
+ }
38
+
39
+ func TestPortalStatusFailsClosedOnAnotherAppsSetting(t *testing.T) {
40
+ cfg := portalConfig(t, `{"alias":"hello-go","id":"SYNO.SDS.Other.Instance"}`)
41
+ _, out := call(t, cfg, bob, "portal.status", `{}`)
42
+ if data := out["data"].(map[string]any); data["state"] != "unavailable" || data["alias"] != nil {
43
+ t.Fatalf("%v", data)
44
+ }
45
+ _, out = call(t, portalConfig(t, ""), bob, "portal.status", `{}`)
46
+ if data := out["data"].(map[string]any); data["state"] != "inactive" {
47
+ t.Fatalf("%v", data)
48
+ }
49
+ }
50
+
51
+ func TestPortalStatusExistsOnlyForAPortalBuild(t *testing.T) {
52
+ if code, _ := call(t, testConfig(t), alice, "portal.status", `{}`); code != "unknown_method" {
53
+ t.Fatalf("%q", code)
54
+ }
55
+ }
@@ -24,8 +24,9 @@ import (
24
24
 
25
25
  // Config is fixed at build time and startup, never taken from a request.
26
26
  type Config struct {
27
- DelegateScope string
28
- ExecutorDigest, PolicyDigest string
27
+ DelegateScope string
28
+ DelegateOperationsJSON, DelegateDestinationsJSON, DelegateLifetime string
29
+ ExecutorDigest, PolicyDigest string
29
30
 
30
31
  // SessionFiles is the interactive File Station adapter; nil keeps legacy refusal.
31
32
  SessionFiles *filestation.Service
@@ -36,6 +37,10 @@ type Config struct {
36
37
  DataDir string
37
38
  // VolumeRoot is where /volumeN lives; empty means "/". Tests set it.
38
39
  VolumeRoot string
40
+ // Portal serves portal.status; PortalConfig overrides DSM's saved
41
+ // AppPortal.json path in tests.
42
+ Portal bool
43
+ PortalConfig string
39
44
  }
40
45
 
41
46
  func Routes(cfg Config) []api.Route {
@@ -47,6 +52,7 @@ func Routes(cfg Config) []api.Route {
47
52
  }...)
48
53
  routes = append(routes, cfg.SessionFiles.Routes()...)
49
54
  routes = append(routes, cfg.backgroundRoutes()...)
55
+ routes = append(routes, cfg.portalRoutes()...)
50
56
  return append(routes, cfg.rootRoutes()...)
51
57
  }
52
58
 
@@ -14,7 +14,7 @@ import (
14
14
  // Work is one fixed worker algorithm. It receives only the job's input bytes.
15
15
  type Work func(ctx context.Context, in io.Reader) (Result, error)
16
16
 
17
- // SHA256V1 is the only worker in this version: it hashes the imported copy.
17
+ // SHA256V1 hashes the imported private copy; delegate assembly adds a separate fixed worker.
18
18
  func SHA256V1(ctx context.Context, in io.Reader) (Result, error) {
19
19
  h := sha256.New()
20
20
  buf := make([]byte, 32*1024)
@@ -61,18 +61,20 @@ const (
61
61
  func (s State) terminal() bool { return s != StateQueued && s != StateRunning }
62
62
 
63
63
  var (
64
- ErrBusy = errors.New("background journal is busy; retry later")
65
- ErrOwnerQueueFull = errors.New("owner pending quota reached")
66
- ErrOwnerQuota = errors.New("owner storage quota reached")
67
- ErrInvalid = errors.New("invalid background request")
68
- ErrTooLarge = errors.New("input is larger than the per-file limit")
69
- ErrQueueFull = errors.New("background queue is full")
70
- ErrQuota = errors.New("background spool quota reached")
71
- ErrKeyConflict = errors.New("idempotency key already used for another input")
72
- ErrNotFound = errors.New("job not found")
73
- ErrNotCancelable = errors.New("job already finished")
74
- ErrNotRunning = errors.New("job is not running")
75
- ErrUnsafeSpool = errors.New("background spool is not private to the package account")
64
+ ErrBusy = errors.New("background journal is busy; retry later")
65
+ ErrOwnerQueueFull = errors.New("owner pending quota reached")
66
+ ErrOwnerQuota = errors.New("owner storage quota reached")
67
+ ErrInvalid = errors.New("invalid background request")
68
+ ErrTooLarge = errors.New("input is larger than the per-file limit")
69
+ ErrQueueFull = errors.New("background queue is full")
70
+ ErrQuota = errors.New("background spool quota reached")
71
+ ErrKeyConflict = errors.New("idempotency key already used for another input")
72
+ ErrNotFound = errors.New("job not found")
73
+ ErrNotCancelable = errors.New("job already finished")
74
+ ErrNotRunning = errors.New("job is not running")
75
+ ErrUnsafeSpool = errors.New("background spool is not private to the package account")
76
+ ErrJournalUnreadable = errors.New("background journal unreadable")
77
+ ErrJournalSchema = errors.New("background journal has an unsupported schema")
76
78
  )
77
79
 
78
80
  // Submitter binds visibility to a fresh DSM username and UID. It never grants
@@ -336,10 +338,10 @@ func (s *Store) readJournal(root *os.Root) (journal, error) {
336
338
  }
337
339
  b, err := io.ReadAll(io.LimitReader(f, maxJournal+1))
338
340
  if err != nil || len(b) > maxJournal {
339
- return j, errors.New("background journal unreadable")
341
+ return j, ErrJournalUnreadable
340
342
  }
341
343
  if err := json.Unmarshal(b, &j); err != nil || j.Schema != schemaVersion {
342
- return journal{}, errors.New("background journal has an unsupported schema")
344
+ return journal{}, ErrJournalSchema
343
345
  }
344
346
  return j, nil
345
347
  }
@@ -56,8 +56,14 @@ func runCGI(ctx context.Context, path string, env []string) ([]byte, error) {
56
56
  }
57
57
 
58
58
  func parseNativeRole(out []byte, err error) (bool, error) {
59
+ return parseNativeBit(out, err, errNativeRole)
60
+ }
61
+
62
+ // parseNativeBit accepts only a bridge's exact "1\n" or "0\n"; anything else,
63
+ // including a failed run, is the caller's unavailable error.
64
+ func parseNativeBit(out []byte, err, unavailable error) (bool, error) {
59
65
  if err != nil {
60
- return false, errNativeRole
66
+ return false, unavailable
61
67
  }
62
68
  switch string(out) {
63
69
  case "1\n":
@@ -65,6 +71,6 @@ func parseNativeRole(out []byte, err error) (bool, error) {
65
71
  case "0\n":
66
72
  return false, nil
67
73
  default:
68
- return false, errNativeRole
74
+ return false, unavailable
69
75
  }
70
76
  }
@@ -23,31 +23,61 @@ var adminAMD64 []byte
23
23
  //go:embed native/admin-aarch64.elf
24
24
  var adminARM64 []byte
25
25
 
26
+ //go:embed native/apppriv-x86_64.elf
27
+ var appPrivAMD64 []byte
28
+
29
+ //go:embed native/apppriv-aarch64.elf
30
+ var appPrivARM64 []byte
31
+
32
+ //go:embed native/admin-armv7.elf
33
+ var adminARMv7 []byte
34
+
35
+ //go:embed native/apppriv-armv7.elf
36
+ var appPrivARMv7 []byte
37
+
38
+ // Bridges per runtime.GOARCH; an architecture without one is refused.
39
+ var (
40
+ adminBridges = map[string][]byte{"amd64": adminAMD64, "arm64": adminARM64, "arm": adminARMv7}
41
+ appPrivBridges = map[string][]byte{"amd64": appPrivAMD64, "arm64": appPrivARM64, "arm": appPrivARMv7}
42
+ )
43
+
26
44
  func nativeAdministrator(ctx context.Context, principal string) (bool, error) {
27
- var payload []byte
28
- switch runtime.GOARCH {
29
- case "amd64":
30
- payload = adminAMD64
31
- case "arm64":
32
- payload = adminARM64
33
- default:
34
- return false, errNativeRole
45
+ out, err := runBridge(ctx, adminBridges, principal)
46
+ return parseNativeRole(out, err)
47
+ }
48
+
49
+ func nativeAppPrivilege(ctx context.Context, principal, app, addr string) (bool, error) {
50
+ out, err := runBridge(ctx, appPrivBridges, principal, app, addr)
51
+ return parseNativeBit(out, err, errNativeAppPriv)
52
+ }
53
+
54
+ // runBridge executes the sealed bridge for this architecture with fixed
55
+ // arguments and a minimal environment, returning at most 16 bytes of output.
56
+ func runBridge(ctx context.Context, bridges map[string][]byte, args ...string) ([]byte, error) {
57
+ payload, ok := bridges[runtime.GOARCH]
58
+ if !ok {
59
+ return nil, errors.New("unsupported architecture")
35
60
  }
36
61
  file, err := sealedBridge(payload)
37
62
  if err != nil {
38
- return false, errNativeRole
63
+ return nil, err
39
64
  }
40
65
  defer file.Close()
41
- cmd := exec.CommandContext(ctx, "/proc/self/fd/3", principal)
66
+ cmd := exec.CommandContext(ctx, "/proc/self/fd/3", args...)
42
67
  cmd.ExtraFiles = []*os.File{file}
43
68
  // In particular, never inherit LD_PRELOAD/LD_LIBRARY_PATH or credentials.
44
69
  cmd.Env = []string{"LANG=C", "LC_ALL=C"}
45
- out, err := commandOutput(cmd, 16)
46
- return parseNativeRole(out, err)
70
+ return commandOutput(cmd, 16)
47
71
  }
48
72
 
73
+ // memfdCreate is the sealing primitive; tests replace it to model old kernels.
74
+ var memfdCreate = unix.MemfdCreate
75
+
49
76
  func sealedBridge(payload []byte) (*os.File, error) {
50
- fd, err := unix.MemfdCreate("synopkgland-admin", unix.MFD_CLOEXEC|unix.MFD_ALLOW_SEALING)
77
+ fd, err := memfdCreate("synopkgland-admin", unix.MFD_CLOEXEC|unix.MFD_ALLOW_SEALING)
78
+ if errors.Is(err, unix.ENOSYS) {
79
+ return unlinkedBridge(bridgeFallbackDir, payload)
80
+ }
51
81
  if err != nil {
52
82
  return nil, err
53
83
  }