@synopackageland/cli 0.4.0 → 0.4.1

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 (438) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +37 -0
  3. package/dist/build-spk/generator.js +3 -0
  4. package/dist/build-spk/notices.d.ts +5 -0
  5. package/dist/build-spk/notices.js +60 -0
  6. package/dist/cli.js +9 -2
  7. package/dist/error-registry.js +20 -0
  8. package/dist/init.d.ts +4 -0
  9. package/dist/init.js +20 -12
  10. package/dist/standalone/build.js +3 -1
  11. package/dist/standalone/daemon.d.ts +23 -0
  12. package/dist/standalone/daemon.js +114 -0
  13. package/dist/standalone/dsm-window.d.ts +1 -1
  14. package/dist/standalone/dsm-window.js +50 -10
  15. package/dist/standalone/helper-inventory.d.ts +16 -0
  16. package/dist/standalone/helper-inventory.js +2 -0
  17. package/dist/standalone/helper.d.ts +2 -12
  18. package/dist/standalone/helper.js +8 -7
  19. package/dist/standalone/host-adapter.d.ts +5 -0
  20. package/dist/standalone/host-adapter.js +148 -0
  21. package/dist/standalone/host-platform.d.ts +13 -0
  22. package/dist/standalone/host-platform.js +42 -0
  23. package/dist/standalone/host-types.d.ts +49 -0
  24. package/dist/standalone/host-types.js +1 -0
  25. package/dist/standalone/inspect-helper.d.ts +6 -0
  26. package/dist/standalone/inspect-helper.js +88 -0
  27. package/dist/standalone/inspect-spk.d.ts +2 -0
  28. package/dist/standalone/inspect-spk.js +49 -0
  29. package/dist/standalone/lifecycle-helper.d.ts +2 -0
  30. package/dist/standalone/lifecycle-helper.js +12 -0
  31. package/dist/standalone/lifecycle.d.ts +3 -0
  32. package/dist/standalone/lifecycle.js +53 -0
  33. package/dist/standalone/manifest.d.ts +2 -0
  34. package/dist/standalone/manifest.js +4 -1
  35. package/dist/standalone/reopen-events.d.ts +2 -0
  36. package/dist/standalone/reopen-events.js +28 -0
  37. package/dist/standalone/root-messages.js +9 -0
  38. package/dist/standalone/root-window.d.ts +4 -3
  39. package/dist/standalone/root-window.js +17 -5
  40. package/dist/standalone/spk.d.ts +4 -3
  41. package/dist/standalone/spk.js +20 -33
  42. package/dist/template-paths.d.ts +2 -0
  43. package/dist/template-paths.js +9 -0
  44. package/dist/templates/_daemon/fixture_linux_test.go +15 -0
  45. package/dist/templates/_daemon/fixture_other_test.go +7 -0
  46. package/dist/templates/_daemon/go.mod +3 -0
  47. package/dist/templates/_daemon/main.go +608 -0
  48. package/dist/templates/_daemon/main_test.go +242 -0
  49. package/dist/templates/_daemon/process_linux.go +55 -0
  50. package/dist/templates/_daemon/process_linux_test.go +161 -0
  51. package/dist/templates/_daemon/process_other.go +14 -0
  52. package/dist/templates/_daemon/testdata/child.go +41 -0
  53. package/dist/templates/_shared/GO-LICENSE +27 -0
  54. package/dist/templates/_shared/GO-PATENTS +22 -0
  55. package/dist/templates/_shared/LICENSES/TEMPLATE.txt +21 -0
  56. package/dist/templates/_shared/notice-overrides/index.json +14 -0
  57. package/dist/templates/_shared/notice-overrides/utils-0.4.2-LICENSE +21 -0
  58. package/dist/templates/_shared/notice-overrides/utils-0.5.0-LICENSE +21 -0
  59. package/dist/templates/_shared/third-party-notices.mjs +51 -0
  60. package/dist/templates/native-go/README.md +57 -1
  61. package/dist/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +59 -0
  62. package/dist/templates/native-go/backend/cmd/dsm-readonly-probe/main_linux.go +46 -0
  63. package/dist/templates/native-go/backend/go.mod +4 -0
  64. package/dist/templates/native-go/backend/go.sum +4 -0
  65. package/dist/templates/native-go/backend/internal/api/binary.go +154 -0
  66. package/dist/templates/native-go/backend/internal/api/binary_test.go +165 -0
  67. package/dist/templates/native-go/backend/internal/api/registry.go +14 -4
  68. package/dist/templates/native-go/backend/internal/api/server.go +4 -0
  69. package/dist/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +121 -0
  70. package/dist/templates/native-go/backend/internal/app/nas_refusal_test.go +46 -0
  71. package/dist/templates/native-go/backend/internal/app/routes.go +11 -0
  72. package/dist/templates/native-go/backend/internal/app/routes_test.go +10 -5
  73. package/dist/templates/native-go/backend/internal/dsmprobe/collector_linux.go +335 -0
  74. package/dist/templates/native-go/backend/internal/dsmprobe/collector_linux_test.go +41 -0
  75. package/dist/templates/native-go/backend/internal/dsmprobe/protocol.go +179 -0
  76. package/dist/templates/native-go/backend/internal/dsmprobe/protocol_test.go +29 -0
  77. package/dist/templates/native-go/backend/internal/helper/cohort.go +393 -0
  78. package/dist/templates/native-go/backend/internal/helper/cohort_publication.go +18 -0
  79. package/dist/templates/native-go/backend/internal/helper/cohort_publication_test.go +105 -0
  80. package/dist/templates/native-go/backend/internal/helper/cohort_test.go +372 -0
  81. package/dist/templates/native-go/backend/internal/helper/control.go +226 -21
  82. package/dist/templates/native-go/backend/internal/helper/control_test.go +10 -2
  83. package/dist/templates/native-go/backend/internal/helper/data_contract.go +242 -0
  84. package/dist/templates/native-go/backend/internal/helper/data_contract_test.go +51 -0
  85. package/dist/templates/native-go/backend/internal/helper/data_decode.go +184 -0
  86. package/dist/templates/native-go/backend/internal/helper/data_decode_pointer_test.go +30 -0
  87. package/dist/templates/native-go/backend/internal/helper/data_protocol.go +416 -0
  88. package/dist/templates/native-go/backend/internal/helper/data_protocol_test.go +449 -0
  89. package/dist/templates/native-go/backend/internal/helper/dsm_acl_linux.go +139 -0
  90. package/dist/templates/native-go/backend/internal/helper/dsm_acl_linux_test.go +121 -0
  91. package/dist/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux.go +95 -0
  92. package/dist/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux_test.go +56 -0
  93. package/dist/templates/native-go/backend/internal/helper/dsm_bridge_linux.go +144 -0
  94. package/dist/templates/native-go/backend/internal/helper/dsm_bridge_linux_test.go +89 -0
  95. package/dist/templates/native-go/backend/internal/helper/dsm_home_linux.go +107 -0
  96. package/dist/templates/native-go/backend/internal/helper/dsm_home_linux_test.go +82 -0
  97. package/dist/templates/native-go/backend/internal/helper/dsm_probe_transport_linux.go +151 -0
  98. package/dist/templates/native-go/backend/internal/helper/dsm_probe_transport_linux_test.go +66 -0
  99. package/dist/templates/native-go/backend/internal/helper/grant_authority.go +516 -0
  100. package/dist/templates/native-go/backend/internal/helper/grant_authority_contract.go +88 -0
  101. package/dist/templates/native-go/backend/internal/helper/grant_authority_test.go +510 -0
  102. package/dist/templates/native-go/backend/internal/helper/grant_cohort.go +389 -0
  103. package/dist/templates/native-go/backend/internal/helper/grant_cohort_test.go +239 -0
  104. package/dist/templates/native-go/backend/internal/helper/grant_delivery.go +49 -0
  105. package/dist/templates/native-go/backend/internal/helper/grant_delivery_methods.go +273 -0
  106. package/dist/templates/native-go/backend/internal/helper/grant_delivery_test.go +322 -0
  107. package/dist/templates/native-go/backend/internal/helper/grant_operation_contract.go +47 -0
  108. package/dist/templates/native-go/backend/internal/helper/grant_readonly_test.go +180 -0
  109. package/dist/templates/native-go/backend/internal/helper/grant_repository_linux.go +415 -0
  110. package/dist/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +468 -0
  111. package/dist/templates/native-go/backend/internal/helper/grant_rpc.go +147 -0
  112. package/dist/templates/native-go/backend/internal/helper/grant_rpc_test.go +51 -0
  113. package/dist/templates/native-go/backend/internal/helper/grant_snapshot.go +75 -0
  114. package/dist/templates/native-go/backend/internal/helper/grant_supervisor_linux.go +134 -0
  115. package/dist/templates/native-go/backend/internal/helper/grant_supervisor_linux_test.go +254 -0
  116. package/dist/templates/native-go/backend/internal/helper/lease.go +112 -0
  117. package/dist/templates/native-go/backend/internal/helper/lease_linux.go +44 -0
  118. package/dist/templates/native-go/backend/internal/helper/lease_other.go +8 -0
  119. package/dist/templates/native-go/backend/internal/helper/lifecycle.go +234 -0
  120. package/dist/templates/native-go/backend/internal/helper/lifecycle_test.go +473 -0
  121. package/dist/templates/native-go/backend/internal/helper/managed_pilot.go +284 -0
  122. package/dist/templates/native-go/backend/internal/helper/managed_pilot_repository_linux.go +74 -0
  123. package/dist/templates/native-go/backend/internal/helper/managed_pilot_repository_linux_test.go +40 -0
  124. package/dist/templates/native-go/backend/internal/helper/managed_pilot_test.go +210 -0
  125. package/dist/templates/native-go/backend/internal/helper/nas_shipped_refusal_linux_test.go +97 -0
  126. package/dist/templates/native-go/backend/internal/helper/native_discovery.go +79 -0
  127. package/dist/templates/native-go/backend/internal/helper/native_identity.go +89 -0
  128. package/dist/templates/native-go/backend/internal/helper/native_provider.go +159 -0
  129. package/dist/templates/native-go/backend/internal/helper/native_provider_test.go +421 -0
  130. package/dist/templates/native-go/backend/internal/helper/observation.go +204 -0
  131. package/dist/templates/native-go/backend/internal/helper/observation_health_test.go +115 -0
  132. package/dist/templates/native-go/backend/internal/helper/observation_reload_budget_test.go +117 -0
  133. package/dist/templates/native-go/backend/internal/helper/observation_test.go +196 -0
  134. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic.go +109 -0
  135. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_linux.go +76 -0
  136. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +124 -0
  137. package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_test.go +98 -0
  138. package/dist/templates/native-go/backend/internal/helper/operation_bootstrap_linux.go +193 -0
  139. package/dist/templates/native-go/backend/internal/helper/operation_credentials_linux.go +56 -0
  140. package/dist/templates/native-go/backend/internal/helper/operation_linux.go +480 -0
  141. package/dist/templates/native-go/backend/internal/helper/operation_linux_test.go +528 -0
  142. package/dist/templates/native-go/backend/internal/helper/process_linux.go +11 -1
  143. package/dist/templates/native-go/backend/internal/helper/publication_test.go +178 -0
  144. package/dist/templates/native-go/backend/internal/helper/read_stream_cohort_linux_test.go +156 -0
  145. package/dist/templates/native-go/backend/internal/helper/read_transfer.go +40 -0
  146. package/dist/templates/native-go/backend/internal/helper/read_transfer_linux.go +109 -0
  147. package/dist/templates/native-go/backend/internal/helper/read_transfer_linux_test.go +118 -0
  148. package/dist/templates/native-go/backend/internal/helper/read_transfer_test.go +177 -0
  149. package/dist/templates/native-go/backend/internal/helper/readonly.go +105 -0
  150. package/dist/templates/native-go/backend/internal/helper/readonly_admission.go +85 -0
  151. package/dist/templates/native-go/backend/internal/helper/readonly_cohort_linux_test.go +253 -0
  152. package/dist/templates/native-go/backend/internal/helper/readonly_linux_test.go +378 -0
  153. package/dist/templates/native-go/backend/internal/helper/readonly_mount_linux.go +65 -0
  154. package/dist/templates/native-go/backend/internal/helper/readonly_mount_proxy_linux.go +113 -0
  155. package/dist/templates/native-go/backend/internal/helper/readonly_operations_linux.go +168 -0
  156. package/dist/templates/native-go/backend/internal/helper/readonly_resolver_linux.go +241 -0
  157. package/dist/templates/native-go/backend/internal/helper/readonly_test.go +40 -0
  158. package/dist/templates/native-go/backend/internal/helper/relaxed_identity.go +252 -0
  159. package/dist/templates/native-go/backend/internal/helper/relaxed_identity_contract.go +105 -0
  160. package/dist/templates/native-go/backend/internal/helper/relaxed_identity_test.go +406 -0
  161. package/dist/templates/native-go/backend/internal/helper/relaxed_invalidation.go +200 -0
  162. package/dist/templates/native-go/backend/internal/helper/repair.go +132 -0
  163. package/dist/templates/native-go/backend/internal/helper/repair_test.go +271 -0
  164. package/dist/templates/native-go/backend/internal/helper/s1r_actor_acl_linux_test.go +303 -0
  165. package/dist/templates/native-go/backend/internal/helper/s1r_actor_fixture_linux_test.go +184 -0
  166. package/dist/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +231 -0
  167. package/dist/templates/native-go/backend/internal/helper/s1r_fixture_contract_linux_test.go +18 -0
  168. package/dist/templates/native-go/backend/internal/helper/server_linux.go +44 -3
  169. package/dist/templates/native-go/backend/internal/helper/status.go +74 -11
  170. package/dist/templates/native-go/backend/internal/helper/status_test.go +83 -0
  171. package/dist/templates/native-go/backend/internal/helper/supervision.go +28 -5
  172. package/dist/templates/native-go/backend/internal/helper/supervisor_frame.go +76 -0
  173. package/dist/templates/native-go/backend/internal/helper/supervisor_frame_linux_test.go +69 -0
  174. package/dist/templates/native-go/backend/internal/helper/supervisor_frame_test.go +107 -0
  175. package/dist/templates/native-go/backend/internal/helper/supervisor_linux.go +187 -16
  176. package/dist/templates/native-go/backend/internal/helper/supervisor_linux_test.go +618 -7
  177. package/dist/templates/native-go/backend/internal/helper/supervisor_socket_eof_test.go +74 -0
  178. package/dist/templates/native-go/backend/internal/helper/supervisor_socket_test.go +45 -0
  179. package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/create.json +23 -0
  180. package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/frames.json +67 -0
  181. package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/grant-store.json +52 -0
  182. package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/intent.json +20 -0
  183. package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/list.json +20 -0
  184. package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/publish.json +20 -0
  185. package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/read.json +22 -0
  186. package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/stat.json +22 -0
  187. package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/write-stream.json +22 -0
  188. package/dist/templates/native-go/backend/internal/helper/unit_connection.go +75 -0
  189. package/dist/templates/native-go/backend/internal/helper/unit_connection_linux_test.go +135 -0
  190. package/dist/templates/native-go/backend/internal/helper/unit_connection_test.go +133 -0
  191. package/dist/templates/native-go/backend/internal/helper/unit_frame_test.go +32 -0
  192. package/dist/templates/native-go/backend/internal/helper/unit_linux.go +364 -0
  193. package/dist/templates/native-go/backend/internal/helper/unit_linux_test.go +46 -0
  194. package/dist/templates/native-go/backend/internal/helper/unit_mechanisms_linux_test.go +217 -0
  195. package/dist/templates/native-go/backend/internal/helper/unit_padding_linux_test.go +178 -0
  196. package/dist/templates/native-go/backend/internal/helper/unit_query_linux.go +111 -0
  197. package/dist/templates/native-go/backend/internal/helper/unit_reload_linux_test.go +372 -0
  198. package/dist/templates/native-go/backend/internal/helper/unit_reload_sequence_linux_test.go +232 -0
  199. package/dist/templates/native-go/backend/internal/helper/write.go +77 -0
  200. package/dist/templates/native-go/backend/internal/helper/write_admission.go +260 -0
  201. package/dist/templates/native-go/backend/internal/helper/write_admission_test.go +135 -0
  202. package/dist/templates/native-go/backend/internal/helper/write_cohort_linux_test.go +218 -0
  203. package/dist/templates/native-go/backend/internal/helper/write_files_linux.go +202 -0
  204. package/dist/templates/native-go/backend/internal/helper/write_files_linux_test.go +199 -0
  205. package/dist/templates/native-go/backend/internal/helper/write_intent_linux.go +116 -0
  206. package/dist/templates/native-go/backend/internal/helper/write_intent_linux_test.go +74 -0
  207. package/dist/templates/native-go/backend/internal/helper/write_operation_linux.go +245 -0
  208. package/dist/templates/native-go/backend/internal/helper/write_test.go +53 -0
  209. package/dist/templates/native-go/ui/app.js +8 -1
  210. package/dist/templates/native-go-better-auth/node/build.mjs +2 -0
  211. package/dist/templates/native-go-vue/README.md +115 -1
  212. package/dist/templates/native-go-vue/frontend/DESIGN.md +1 -1
  213. package/dist/templates/native-go-vue/frontend/package-lock.json +132 -229
  214. package/dist/templates/native-go-vue/frontend/package.json +1 -1
  215. package/dist/templates/native-go-vue/frontend/src/App.vue +33 -6
  216. package/dist/templates/native-go-vue/frontend/src/context.ts +41 -2
  217. package/dist/templates/native-go-vue/frontend/src/main.ts +4 -1
  218. package/dist/templates/native-go-vue/frontend/src/nas/NasGrantSettings.vue +74 -0
  219. package/dist/templates/native-go-vue/frontend/src/nas/NasPathPicker.vue +106 -0
  220. package/dist/templates/native-go-vue/frontend/src/nas/NasUnavailable.vue +20 -0
  221. package/dist/templates/native-go-vue/frontend/src/nas/i18n/de.json +74 -0
  222. package/dist/templates/native-go-vue/frontend/src/nas/i18n/en.json +74 -0
  223. package/dist/templates/native-go-vue/frontend/src/nas/i18n/es.json +74 -0
  224. package/dist/templates/native-go-vue/frontend/src/nas/i18n/fr.json +74 -0
  225. package/dist/templates/native-go-vue/frontend/src/nas/i18n/it.json +74 -0
  226. package/dist/templates/native-go-vue/frontend/src/nas/i18n/ja.json +74 -0
  227. package/dist/templates/native-go-vue/frontend/src/nas/i18n/ko.json +74 -0
  228. package/dist/templates/native-go-vue/frontend/src/nas/i18n/zh-CN.json +74 -0
  229. package/dist/templates/native-go-vue/frontend/src/nas/i18n/zh-TW.json +74 -0
  230. package/dist/templates/native-go-vue/frontend/src/nas/i18n.ts +38 -0
  231. package/dist/templates/native-go-vue/frontend/src/nas/mock-provider.ts +119 -0
  232. package/dist/templates/native-go-vue/frontend/src/nas/provider.ts +59 -0
  233. package/dist/templates/native-go-vue/frontend/src/nas/use-request.ts +27 -0
  234. package/dist/templates/native-go-vue/frontend/src/style.css +17 -0
  235. package/dist/templates/native-go-vue/frontend/test/apps.test.ts +44 -2
  236. package/dist/templates/native-go-vue/frontend/test/nas-provider.test.ts +81 -0
  237. package/dist/templates/native-go-vue/frontend/test/nas-request.test.ts +21 -0
  238. package/dist/templates/native-go-vue/frontend/test/nas-ui.test.ts +261 -0
  239. package/dist/templates/native-go-vue/frontend/tsconfig.json +1 -1
  240. package/dist/templates/native-go-vue/frontend/vite.config.ts +6 -4
  241. package/package.json +3 -2
  242. package/templates/_daemon/fixture_linux_test.go +15 -0
  243. package/templates/_daemon/fixture_other_test.go +7 -0
  244. package/templates/_daemon/go.mod +3 -0
  245. package/templates/_daemon/main.go +608 -0
  246. package/templates/_daemon/main_test.go +242 -0
  247. package/templates/_daemon/process_linux.go +55 -0
  248. package/templates/_daemon/process_linux_test.go +161 -0
  249. package/templates/_daemon/process_other.go +14 -0
  250. package/templates/_daemon/testdata/child.go +41 -0
  251. package/templates/_shared/GO-LICENSE +27 -0
  252. package/templates/_shared/GO-PATENTS +22 -0
  253. package/templates/_shared/LICENSES/TEMPLATE.txt +21 -0
  254. package/templates/_shared/notice-overrides/index.json +14 -0
  255. package/templates/_shared/notice-overrides/utils-0.4.2-LICENSE +21 -0
  256. package/templates/_shared/notice-overrides/utils-0.5.0-LICENSE +21 -0
  257. package/templates/_shared/third-party-notices.mjs +51 -0
  258. package/templates/native-go/README.md +57 -1
  259. package/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +59 -0
  260. package/templates/native-go/backend/cmd/dsm-readonly-probe/main_linux.go +46 -0
  261. package/templates/native-go/backend/go.mod +4 -0
  262. package/templates/native-go/backend/go.sum +4 -0
  263. package/templates/native-go/backend/internal/api/binary.go +154 -0
  264. package/templates/native-go/backend/internal/api/binary_test.go +165 -0
  265. package/templates/native-go/backend/internal/api/registry.go +14 -4
  266. package/templates/native-go/backend/internal/api/server.go +4 -0
  267. package/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +121 -0
  268. package/templates/native-go/backend/internal/app/nas_refusal_test.go +46 -0
  269. package/templates/native-go/backend/internal/app/routes.go +11 -0
  270. package/templates/native-go/backend/internal/app/routes_test.go +10 -5
  271. package/templates/native-go/backend/internal/dsmprobe/collector_linux.go +335 -0
  272. package/templates/native-go/backend/internal/dsmprobe/collector_linux_test.go +41 -0
  273. package/templates/native-go/backend/internal/dsmprobe/protocol.go +179 -0
  274. package/templates/native-go/backend/internal/dsmprobe/protocol_test.go +29 -0
  275. package/templates/native-go/backend/internal/helper/cohort.go +393 -0
  276. package/templates/native-go/backend/internal/helper/cohort_publication.go +18 -0
  277. package/templates/native-go/backend/internal/helper/cohort_publication_test.go +105 -0
  278. package/templates/native-go/backend/internal/helper/cohort_test.go +372 -0
  279. package/templates/native-go/backend/internal/helper/control.go +226 -21
  280. package/templates/native-go/backend/internal/helper/control_test.go +10 -2
  281. package/templates/native-go/backend/internal/helper/data_contract.go +242 -0
  282. package/templates/native-go/backend/internal/helper/data_contract_test.go +51 -0
  283. package/templates/native-go/backend/internal/helper/data_decode.go +184 -0
  284. package/templates/native-go/backend/internal/helper/data_decode_pointer_test.go +30 -0
  285. package/templates/native-go/backend/internal/helper/data_protocol.go +416 -0
  286. package/templates/native-go/backend/internal/helper/data_protocol_test.go +449 -0
  287. package/templates/native-go/backend/internal/helper/dsm_acl_linux.go +139 -0
  288. package/templates/native-go/backend/internal/helper/dsm_acl_linux_test.go +121 -0
  289. package/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux.go +95 -0
  290. package/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux_test.go +56 -0
  291. package/templates/native-go/backend/internal/helper/dsm_bridge_linux.go +144 -0
  292. package/templates/native-go/backend/internal/helper/dsm_bridge_linux_test.go +89 -0
  293. package/templates/native-go/backend/internal/helper/dsm_home_linux.go +107 -0
  294. package/templates/native-go/backend/internal/helper/dsm_home_linux_test.go +82 -0
  295. package/templates/native-go/backend/internal/helper/dsm_probe_transport_linux.go +151 -0
  296. package/templates/native-go/backend/internal/helper/dsm_probe_transport_linux_test.go +66 -0
  297. package/templates/native-go/backend/internal/helper/grant_authority.go +516 -0
  298. package/templates/native-go/backend/internal/helper/grant_authority_contract.go +88 -0
  299. package/templates/native-go/backend/internal/helper/grant_authority_test.go +510 -0
  300. package/templates/native-go/backend/internal/helper/grant_cohort.go +389 -0
  301. package/templates/native-go/backend/internal/helper/grant_cohort_test.go +239 -0
  302. package/templates/native-go/backend/internal/helper/grant_delivery.go +49 -0
  303. package/templates/native-go/backend/internal/helper/grant_delivery_methods.go +273 -0
  304. package/templates/native-go/backend/internal/helper/grant_delivery_test.go +322 -0
  305. package/templates/native-go/backend/internal/helper/grant_operation_contract.go +47 -0
  306. package/templates/native-go/backend/internal/helper/grant_readonly_test.go +180 -0
  307. package/templates/native-go/backend/internal/helper/grant_repository_linux.go +415 -0
  308. package/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +468 -0
  309. package/templates/native-go/backend/internal/helper/grant_rpc.go +147 -0
  310. package/templates/native-go/backend/internal/helper/grant_rpc_test.go +51 -0
  311. package/templates/native-go/backend/internal/helper/grant_snapshot.go +75 -0
  312. package/templates/native-go/backend/internal/helper/grant_supervisor_linux.go +134 -0
  313. package/templates/native-go/backend/internal/helper/grant_supervisor_linux_test.go +254 -0
  314. package/templates/native-go/backend/internal/helper/lease.go +112 -0
  315. package/templates/native-go/backend/internal/helper/lease_linux.go +44 -0
  316. package/templates/native-go/backend/internal/helper/lease_other.go +8 -0
  317. package/templates/native-go/backend/internal/helper/lifecycle.go +234 -0
  318. package/templates/native-go/backend/internal/helper/lifecycle_test.go +473 -0
  319. package/templates/native-go/backend/internal/helper/managed_pilot.go +284 -0
  320. package/templates/native-go/backend/internal/helper/managed_pilot_repository_linux.go +74 -0
  321. package/templates/native-go/backend/internal/helper/managed_pilot_repository_linux_test.go +40 -0
  322. package/templates/native-go/backend/internal/helper/managed_pilot_test.go +210 -0
  323. package/templates/native-go/backend/internal/helper/nas_shipped_refusal_linux_test.go +97 -0
  324. package/templates/native-go/backend/internal/helper/native_discovery.go +79 -0
  325. package/templates/native-go/backend/internal/helper/native_identity.go +89 -0
  326. package/templates/native-go/backend/internal/helper/native_provider.go +159 -0
  327. package/templates/native-go/backend/internal/helper/native_provider_test.go +421 -0
  328. package/templates/native-go/backend/internal/helper/observation.go +204 -0
  329. package/templates/native-go/backend/internal/helper/observation_health_test.go +115 -0
  330. package/templates/native-go/backend/internal/helper/observation_reload_budget_test.go +117 -0
  331. package/templates/native-go/backend/internal/helper/observation_test.go +196 -0
  332. package/templates/native-go/backend/internal/helper/observer_diagnostic.go +109 -0
  333. package/templates/native-go/backend/internal/helper/observer_diagnostic_linux.go +76 -0
  334. package/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +124 -0
  335. package/templates/native-go/backend/internal/helper/observer_diagnostic_test.go +98 -0
  336. package/templates/native-go/backend/internal/helper/operation_bootstrap_linux.go +193 -0
  337. package/templates/native-go/backend/internal/helper/operation_credentials_linux.go +56 -0
  338. package/templates/native-go/backend/internal/helper/operation_linux.go +480 -0
  339. package/templates/native-go/backend/internal/helper/operation_linux_test.go +528 -0
  340. package/templates/native-go/backend/internal/helper/process_linux.go +11 -1
  341. package/templates/native-go/backend/internal/helper/publication_test.go +178 -0
  342. package/templates/native-go/backend/internal/helper/read_stream_cohort_linux_test.go +156 -0
  343. package/templates/native-go/backend/internal/helper/read_transfer.go +40 -0
  344. package/templates/native-go/backend/internal/helper/read_transfer_linux.go +109 -0
  345. package/templates/native-go/backend/internal/helper/read_transfer_linux_test.go +118 -0
  346. package/templates/native-go/backend/internal/helper/read_transfer_test.go +177 -0
  347. package/templates/native-go/backend/internal/helper/readonly.go +105 -0
  348. package/templates/native-go/backend/internal/helper/readonly_admission.go +85 -0
  349. package/templates/native-go/backend/internal/helper/readonly_cohort_linux_test.go +253 -0
  350. package/templates/native-go/backend/internal/helper/readonly_linux_test.go +378 -0
  351. package/templates/native-go/backend/internal/helper/readonly_mount_linux.go +65 -0
  352. package/templates/native-go/backend/internal/helper/readonly_mount_proxy_linux.go +113 -0
  353. package/templates/native-go/backend/internal/helper/readonly_operations_linux.go +168 -0
  354. package/templates/native-go/backend/internal/helper/readonly_resolver_linux.go +241 -0
  355. package/templates/native-go/backend/internal/helper/readonly_test.go +40 -0
  356. package/templates/native-go/backend/internal/helper/relaxed_identity.go +252 -0
  357. package/templates/native-go/backend/internal/helper/relaxed_identity_contract.go +105 -0
  358. package/templates/native-go/backend/internal/helper/relaxed_identity_test.go +406 -0
  359. package/templates/native-go/backend/internal/helper/relaxed_invalidation.go +200 -0
  360. package/templates/native-go/backend/internal/helper/repair.go +132 -0
  361. package/templates/native-go/backend/internal/helper/repair_test.go +271 -0
  362. package/templates/native-go/backend/internal/helper/s1r_actor_acl_linux_test.go +303 -0
  363. package/templates/native-go/backend/internal/helper/s1r_actor_fixture_linux_test.go +184 -0
  364. package/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +231 -0
  365. package/templates/native-go/backend/internal/helper/s1r_fixture_contract_linux_test.go +18 -0
  366. package/templates/native-go/backend/internal/helper/server_linux.go +44 -3
  367. package/templates/native-go/backend/internal/helper/status.go +74 -11
  368. package/templates/native-go/backend/internal/helper/status_test.go +83 -0
  369. package/templates/native-go/backend/internal/helper/supervision.go +28 -5
  370. package/templates/native-go/backend/internal/helper/supervisor_frame.go +76 -0
  371. package/templates/native-go/backend/internal/helper/supervisor_frame_linux_test.go +69 -0
  372. package/templates/native-go/backend/internal/helper/supervisor_frame_test.go +107 -0
  373. package/templates/native-go/backend/internal/helper/supervisor_linux.go +187 -16
  374. package/templates/native-go/backend/internal/helper/supervisor_linux_test.go +618 -7
  375. package/templates/native-go/backend/internal/helper/supervisor_socket_eof_test.go +74 -0
  376. package/templates/native-go/backend/internal/helper/supervisor_socket_test.go +45 -0
  377. package/templates/native-go/backend/internal/helper/testdata/protocol2/create.json +23 -0
  378. package/templates/native-go/backend/internal/helper/testdata/protocol2/frames.json +67 -0
  379. package/templates/native-go/backend/internal/helper/testdata/protocol2/grant-store.json +52 -0
  380. package/templates/native-go/backend/internal/helper/testdata/protocol2/intent.json +20 -0
  381. package/templates/native-go/backend/internal/helper/testdata/protocol2/list.json +20 -0
  382. package/templates/native-go/backend/internal/helper/testdata/protocol2/publish.json +20 -0
  383. package/templates/native-go/backend/internal/helper/testdata/protocol2/read.json +22 -0
  384. package/templates/native-go/backend/internal/helper/testdata/protocol2/stat.json +22 -0
  385. package/templates/native-go/backend/internal/helper/testdata/protocol2/write-stream.json +22 -0
  386. package/templates/native-go/backend/internal/helper/unit_connection.go +75 -0
  387. package/templates/native-go/backend/internal/helper/unit_connection_linux_test.go +135 -0
  388. package/templates/native-go/backend/internal/helper/unit_connection_test.go +133 -0
  389. package/templates/native-go/backend/internal/helper/unit_frame_test.go +32 -0
  390. package/templates/native-go/backend/internal/helper/unit_linux.go +364 -0
  391. package/templates/native-go/backend/internal/helper/unit_linux_test.go +46 -0
  392. package/templates/native-go/backend/internal/helper/unit_mechanisms_linux_test.go +217 -0
  393. package/templates/native-go/backend/internal/helper/unit_padding_linux_test.go +178 -0
  394. package/templates/native-go/backend/internal/helper/unit_query_linux.go +111 -0
  395. package/templates/native-go/backend/internal/helper/unit_reload_linux_test.go +372 -0
  396. package/templates/native-go/backend/internal/helper/unit_reload_sequence_linux_test.go +232 -0
  397. package/templates/native-go/backend/internal/helper/write.go +77 -0
  398. package/templates/native-go/backend/internal/helper/write_admission.go +260 -0
  399. package/templates/native-go/backend/internal/helper/write_admission_test.go +135 -0
  400. package/templates/native-go/backend/internal/helper/write_cohort_linux_test.go +218 -0
  401. package/templates/native-go/backend/internal/helper/write_files_linux.go +202 -0
  402. package/templates/native-go/backend/internal/helper/write_files_linux_test.go +199 -0
  403. package/templates/native-go/backend/internal/helper/write_intent_linux.go +116 -0
  404. package/templates/native-go/backend/internal/helper/write_intent_linux_test.go +74 -0
  405. package/templates/native-go/backend/internal/helper/write_operation_linux.go +245 -0
  406. package/templates/native-go/backend/internal/helper/write_test.go +53 -0
  407. package/templates/native-go/ui/app.js +8 -1
  408. package/templates/native-go-better-auth/node/build.mjs +2 -0
  409. package/templates/native-go-vue/README.md +115 -1
  410. package/templates/native-go-vue/frontend/DESIGN.md +1 -1
  411. package/templates/native-go-vue/frontend/package-lock.json +132 -229
  412. package/templates/native-go-vue/frontend/package.json +1 -1
  413. package/templates/native-go-vue/frontend/src/App.vue +33 -6
  414. package/templates/native-go-vue/frontend/src/context.ts +41 -2
  415. package/templates/native-go-vue/frontend/src/main.ts +4 -1
  416. package/templates/native-go-vue/frontend/src/nas/NasGrantSettings.vue +74 -0
  417. package/templates/native-go-vue/frontend/src/nas/NasPathPicker.vue +106 -0
  418. package/templates/native-go-vue/frontend/src/nas/NasUnavailable.vue +20 -0
  419. package/templates/native-go-vue/frontend/src/nas/i18n/de.json +74 -0
  420. package/templates/native-go-vue/frontend/src/nas/i18n/en.json +74 -0
  421. package/templates/native-go-vue/frontend/src/nas/i18n/es.json +74 -0
  422. package/templates/native-go-vue/frontend/src/nas/i18n/fr.json +74 -0
  423. package/templates/native-go-vue/frontend/src/nas/i18n/it.json +74 -0
  424. package/templates/native-go-vue/frontend/src/nas/i18n/ja.json +74 -0
  425. package/templates/native-go-vue/frontend/src/nas/i18n/ko.json +74 -0
  426. package/templates/native-go-vue/frontend/src/nas/i18n/zh-CN.json +74 -0
  427. package/templates/native-go-vue/frontend/src/nas/i18n/zh-TW.json +74 -0
  428. package/templates/native-go-vue/frontend/src/nas/i18n.ts +38 -0
  429. package/templates/native-go-vue/frontend/src/nas/mock-provider.ts +119 -0
  430. package/templates/native-go-vue/frontend/src/nas/provider.ts +59 -0
  431. package/templates/native-go-vue/frontend/src/nas/use-request.ts +27 -0
  432. package/templates/native-go-vue/frontend/src/style.css +17 -0
  433. package/templates/native-go-vue/frontend/test/apps.test.ts +44 -2
  434. package/templates/native-go-vue/frontend/test/nas-provider.test.ts +81 -0
  435. package/templates/native-go-vue/frontend/test/nas-request.test.ts +21 -0
  436. package/templates/native-go-vue/frontend/test/nas-ui.test.ts +261 -0
  437. package/templates/native-go-vue/frontend/tsconfig.json +1 -1
  438. package/templates/native-go-vue/frontend/vite.config.ts +6 -4
@@ -0,0 +1,51 @@
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+
4
+ // Conservative inventory of every locked production dependency, including
5
+ // dependencies tree-shaken from the bundle. Build tools marked dev are omitted.
6
+ // Read actual upstream license/notice files, never synthesize license text from
7
+ // SPDX metadata. npm ci must have installed the exact lock before this runs.
8
+ export function writeThirdPartyNotices(root, output, { ui = false } = {}) {
9
+ const lock = JSON.parse(readFileSync(join(root, 'package-lock.json'), 'utf8'));
10
+ if (lock.lockfileVersion < 2 || !lock.packages) throw new Error('Notice generation requires a v2/v3 npm lockfile');
11
+ const inventory = [];
12
+ const sections = [];
13
+ let uiFiles;
14
+ for (const [path, entry] of Object.entries(lock.packages).sort(([a], [b]) => a.localeCompare(b, 'en'))) {
15
+ if (!path || entry.dev) continue;
16
+ if (!/^node_modules\//.test(path) || path.split('/').includes('..') || entry.link) throw new Error(`Unsupported notice package path: ${path}`);
17
+ const dir = join(root, path);
18
+ const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'));
19
+ if (pkg.version !== entry.version) throw new Error(`Notice version mismatch: ${path}; run npm ci`);
20
+ const files = readdirSync(dir, { withFileTypes: true })
21
+ .filter(f => f.isFile() && /^(licen[sc]e|copying|notice|copyright)([.-]|$)/i.test(f.name))
22
+ .map(f => f.name).sort();
23
+ const texts = files.map(file => ({ file, text: readFileSync(join(dir, file), 'utf8') }));
24
+ let source, provenance;
25
+ if (!files.some(f => /^(licen[sc]e|copying)([.-]|$)/i.test(f))) {
26
+ const index = new URL('./notice-overrides/index.json', import.meta.url);
27
+ const overrides = existsSync(index) ? JSON.parse(readFileSync(index, 'utf8')) : {};
28
+ const override = overrides[`${pkg.name}@${pkg.version}`];
29
+ if (!override || !entry.integrity || override.integrity !== entry.integrity) throw new Error(`Missing upstream license text: ${pkg.name}@${pkg.version}`);
30
+ source = override.source;
31
+ provenance = override.provenance;
32
+ texts.push({file: 'LICENSE (pinned upstream source)', text: readFileSync(new URL(`./notice-overrides/${override.file}`, import.meta.url), 'utf8')});
33
+ files.push(override.file);
34
+ }
35
+ // UI ships its own aggregate for fonts, icons and dependencies/assets.
36
+ if (pkg.name === '@synopackageland/ui') {
37
+ uiFiles = {
38
+ 'UI-LICENSE': readFileSync(join(dir, 'LICENSE'), 'utf8'),
39
+ 'UI-THIRD_PARTY.md': readFileSync(join(dir, 'LICENSES/THIRD_PARTY.md'), 'utf8'),
40
+ };
41
+ }
42
+ inventory.push({ name: pkg.name, version: pkg.version, license: pkg.license ?? entry.license ?? 'unknown', integrity: entry.integrity, path, files, ...(source ? {source, provenance} : {}) });
43
+ sections.push(`\n===== ${pkg.name}@${pkg.version} (${pkg.license ?? entry.license ?? 'unknown'}) =====\n` + (source ? `Source: ${source}\n${provenance}\n` : '') + texts.map(({ file, text }) => `\n--- ${file} ---\n${text}\n`).join(''));
44
+ }
45
+ if (ui && !uiFiles) throw new Error('UI dependency is missing from the locked production inventory');
46
+ rmSync(output, { recursive: true, force: true });
47
+ mkdirSync(output, { recursive: true });
48
+ writeFileSync(join(output, 'THIRD_PARTY_NOTICES.txt'), 'Locked production dependency notices (conservative superset of bundled code).\n' + sections.join(''));
49
+ writeFileSync(join(output, 'inventory.json'), JSON.stringify(inventory, null, 2) + '\n');
50
+ for (const [name, text] of Object.entries(uiFiles ?? {})) writeFileSync(join(output, name), text);
51
+ }
@@ -135,9 +135,65 @@ Known limits:
135
135
  `ui/app.js` must register `window.DsmPackageApps[<package>].mount(root, ctx)`
136
136
  (the template shows how, using `document.currentScript.dataset.package`).
137
137
  `ctx.call(method, params)` is the only transport. `ctx.reopen(fn)` runs `fn`
138
- whenever DSM shows the window again. Scope your CSS under your own root class:
138
+ whenever DSM shows the window again and returns an idempotent unsubscribe function. Scope your CSS under your own root class:
139
139
  every DSM app shares one page.
140
140
 
141
+ Plain JS and Vue receive the same `ctx.host` adapter. `ctx.host.platform()`
142
+ returns a fresh frozen snapshot: `web`, `host` (`dsm`, `standalone-web` or
143
+ `unavailable`), `dsmStandalone`, `dsmLanguage`, `appLocale`, `systemVersion`,
144
+ `fullVersion`, and `theme`. Unknown fields are `null`; `theme` stays unknown.
145
+ DSM launch mode is separate from plain-web fallback, and `appLocale` is the
146
+ app's catalog locale, which may differ from DSM's UI language code.
147
+
148
+ ```js
149
+ const platform = ctx.host.platform();
150
+ const result = ctx.host.setTitle('My notes');
151
+ if (result.status !== 'ok') showTitleStatus(result.status);
152
+ ```
153
+
154
+ `setTitle` enables DSM HTML encoding or assigns standalone `document.title`.
155
+ It returns `{status: 'ok', target: 'dsm-window' | 'document'}` on synchronous
156
+ completion, or `unsupported`, `unavailable`, `invalid-input`, `failed` statuses.
157
+ A missing DSM method is unsupported; it never changes the DSM desktop's title.
158
+ Destroy disposes the adapter and clears reopen handlers; retained adapters
159
+ return unavailable. Navigation exposes activateWindow/requestClose/openApp/openURL;
160
+ requests do not acknowledge completion. `ctx.host.subscribe('window-resize', fn)`
161
+ returns `{status: 'subscribed', dispose}` only for a verified DSM window with on/un.
162
+ The callback receives no native arguments. Remove your subscriptions on unmount;
163
+ wrapper destroy also cleans them. `host-theme-change` and `host-language-change`
164
+ return unsupported: no third-party host event is proven. These observations do
165
+ not authorize work.
166
+
167
+ `ctx.host.openFileManager('/example-share/docs')` requests File Station folder
168
+ navigation; `revealFile('/home/report.txt')` requests a file highlight. Both require
169
+ a registered, enabled and launchable File Station and report requested plus action,
170
+ not location completion or ACL success. Use canonical virtual share paths only;
171
+ OS `/volumeN/...`, traversal, repeated/trailing slash, controls and backslash are
172
+ invalid. No path conversion or grant is performed. `openFile`, `showFileDetails`
173
+ and `openAppSetting` return unsupported; private preview/details/settings flows
174
+ have no proven generic contract. DSM runtime remains unknown.
175
+
176
+ For an independent browser shell, use the SPK's generated `ui/host-0001.js`
177
+ (the number follows the manifest build). It has no Ext or npm runtime dependency:
178
+
179
+ ```html
180
+ <script src="./host-0001.js"></script>
181
+ ```
182
+
183
+ ```js
184
+ // shellContext supplies your app's own auth/transport and other context members.
185
+ const ctx = {...shellContext, host: window.DsmPackageHosts.__PACKAGE__({locale: 'en'})};
186
+ const app = window.DsmPackageApps.__PACKAGE__.mount(root, ctx);
187
+ // When your shell unmounts:
188
+ ctx.host.dispose();
189
+ app.unmount();
190
+ ```
191
+
192
+ Serve the generated script with your shell (or reference its same-origin DSM
193
+ static path). `ctx.host` does not create a standalone backend, DSM session,
194
+ cross-origin iframe bridge, or implementations of `ctx.call/t/root/reopen`.
195
+ Standalone title affects the document shared by that shell's mounts.
196
+
141
197
  To build the UI with Vite, Vue or React, point `ui` at the build output and
142
198
  give the build command as an argv list (no shell):
143
199
 
@@ -0,0 +1,59 @@
1
+ DSM integration helper build dependencies
2
+
3
+ github.com/godbus/dbus/v5 v5.2.2 (BSD-2-Clause)
4
+
5
+ Copyright (c) 2013, Georg Reinke (<guelfey at gmail dot com>), Google
6
+ All rights reserved.
7
+
8
+ Redistribution and use in source and binary forms, with or without
9
+ modification, are permitted provided that the following conditions
10
+ are met:
11
+
12
+ 1. Redistributions of source code must retain the above copyright notice,
13
+ this list of conditions and the following disclaimer.
14
+
15
+ 2. Redistributions in binary form must reproduce the above copyright
16
+ notice, this list of conditions and the following disclaimer in the
17
+ documentation and/or other materials provided with the distribution.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
25
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ golang.org/x/sys v0.27.0 (BSD-3-Clause)
32
+
33
+ Copyright 2009 The Go Authors.
34
+
35
+ Redistribution and use in source and binary forms, with or without
36
+ modification, are permitted provided that the following conditions are
37
+ met:
38
+
39
+ * Redistributions of source code must retain the above copyright
40
+ notice, this list of conditions and the following disclaimer.
41
+ * Redistributions in binary form must reproduce the above
42
+ copyright notice, this list of conditions and the following disclaimer
43
+ in the documentation and/or other materials provided with the
44
+ distribution.
45
+ * Neither the name of Google LLC nor the names of its
46
+ contributors may be used to endorse or promote products derived from
47
+ this software without specific prior written permission.
48
+
49
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
50
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
51
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
52
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
53
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
55
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
56
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
57
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
59
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,46 @@
1
+ // A standalone evidence-only static probe. No helper activation or mutation.
2
+ package main
3
+
4
+ import (
5
+ "context"
6
+ "dsmapp/internal/dsmprobe"
7
+ "encoding/json"
8
+ "golang.org/x/sys/unix"
9
+ "io"
10
+ "os"
11
+ "runtime"
12
+ "time"
13
+ )
14
+
15
+ func main() {
16
+ if len(os.Args) != 2 || os.Args[1] != "--wire-v1" {
17
+ os.Exit(2)
18
+ }
19
+ // Watchdog owns this bounded observation; no children or services are created.
20
+ go func() { time.Sleep(8 * time.Second); os.Exit(124) }()
21
+ runtime.LockOSThread()
22
+ if unix.Prctl(unix.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != nil || unix.Prctl(unix.PR_SET_DUMPABLE, 0, 0, 0, 0) != nil {
23
+ os.Exit(3)
24
+ }
25
+ data, e := io.ReadAll(io.LimitReader(os.Stdin, dsmprobe.MaxRequestBytes+1))
26
+ if e != nil {
27
+ os.Exit(2)
28
+ }
29
+ request, e := dsmprobe.DecodeRequest(data)
30
+ if e != nil {
31
+ os.Exit(2)
32
+ }
33
+ ctx, cancel := context.WithTimeout(context.Background(), 7*time.Second)
34
+ defer cancel()
35
+ out, e := dsmprobe.Collect(ctx, request)
36
+ if e != nil {
37
+ out.Status = "unsupported"
38
+ }
39
+ data, e = json.Marshal(out)
40
+ if e != nil || len(data) > dsmprobe.MaxResponseBytes {
41
+ os.Exit(3)
42
+ }
43
+ if _, e = os.Stdout.Write(append(data, '\n')); e != nil {
44
+ os.Exit(3)
45
+ }
46
+ }
@@ -1,3 +1,7 @@
1
1
  module dsmapp
2
2
 
3
3
  go 1.24
4
+
5
+ require github.com/godbus/dbus/v5 v5.2.2
6
+
7
+ require golang.org/x/sys v0.27.0 // indirect
@@ -0,0 +1,4 @@
1
+ github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
2
+ github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
3
+ golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
4
+ golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
@@ -0,0 +1,154 @@
1
+ package api
2
+
3
+ import (
4
+ "bytes"
5
+ "context"
6
+ "encoding/json"
7
+ "io"
8
+ "net/http"
9
+ "regexp"
10
+ "strconv"
11
+ "sync"
12
+ "time"
13
+ )
14
+
15
+ const MaxBinaryReadBytes = 1 << 20
16
+ const BinaryReadTimeout = 10 * time.Second
17
+
18
+ // Control IDs are not bearer authority. The trusted adapter must revalidate
19
+ // the original caller/session, epoch, grant revision and every chunk ticket.
20
+ // The fixed route accepts no path, offset, range, URL, filename or MIME type.
21
+ type BinaryReadRequest struct {
22
+ OperationID string `json:"operationId"`
23
+ Epoch string `json:"epoch"`
24
+ Token string `json:"token"`
25
+ }
26
+
27
+ // Body must implement Close concurrently with Read and unblock it on Close.
28
+ // Close releases/cancels the helper transfer; it is not itself a Q receipt.
29
+ type BinaryRead struct {
30
+ Body io.ReadCloser
31
+ Bytes uint64
32
+ OperationID string
33
+ }
34
+ type BinaryReadHandler func(context.Context, Caller, *http.Request, json.RawMessage) (BinaryRead, error)
35
+
36
+ func BoundedRead(h BinaryReadHandler) Route {
37
+ return Route{method: "nas.files.read.binary", policy: policyUser, binary: h}
38
+ }
39
+
40
+ var binaryReference = regexp.MustCompile(`^[a-f0-9]{64}$`)
41
+
42
+ func serveBoundedRead(w http.ResponseWriter, r *http.Request, c Caller, params json.RawMessage, h BinaryReadHandler) {
43
+ if r.Context().Err() != nil {
44
+ writeError(w, &Error{"canceled", "read canceled"})
45
+ return
46
+ }
47
+ if r.Header.Get("Range") != "" {
48
+ writeError(w, BadRequest("ranges are unsupported"))
49
+ return
50
+ }
51
+ in, ok := decodeBinaryReadControl(params)
52
+ if !ok {
53
+ writeError(w, BadRequest("invalid binary read control"))
54
+ return
55
+ }
56
+ ctx, cancel := context.WithTimeout(r.Context(), BinaryReadTimeout)
57
+ defer cancel()
58
+ result, err := h(ctx, c, r, params)
59
+ if err != nil {
60
+ if result.Body != nil {
61
+ result.Body.Close()
62
+ }
63
+ writeError(w, asError(err))
64
+ return
65
+ }
66
+ if result.Body == nil {
67
+ writeError(w, internalError)
68
+ return
69
+ }
70
+ var once sync.Once
71
+ var closeErr error
72
+ closeBody := func() { once.Do(func() { closeErr = result.Body.Close() }) }
73
+ defer closeBody()
74
+ if result.Bytes > MaxBinaryReadBytes || result.OperationID != in.OperationID {
75
+ writeError(w, BadRequest("invalid bounded read result"))
76
+ return
77
+ }
78
+ stop := make(chan struct{})
79
+ done := make(chan struct{})
80
+ go func() {
81
+ defer close(done)
82
+ select {
83
+ case <-ctx.Done():
84
+ closeBody()
85
+ case <-stop:
86
+ }
87
+ }()
88
+ // Materialize only the bounded response so short/error/overlong transfers
89
+ // cannot become successful binary responses. Helper relay still leases at
90
+ // most one 64KiB chunk. Long CGI streaming remains disabled pending DSM proof.
91
+ body, readErr := io.ReadAll(io.LimitReader(result.Body, int64(result.Bytes)+1))
92
+ closeBody()
93
+ close(stop)
94
+ <-done
95
+ if ctx.Err() != nil {
96
+ writeError(w, &Error{"canceled", "read expired or canceled"})
97
+ return
98
+ }
99
+ if readErr != nil || closeErr != nil || uint64(len(body)) != result.Bytes {
100
+ writeError(w, &Error{"read_failed", "binary read failed"})
101
+ return
102
+ }
103
+ headers := w.Header()
104
+ headers.Set("Content-Type", "application/octet-stream")
105
+ headers.Set("Content-Length", strconv.FormatUint(result.Bytes, 10))
106
+ headers.Set("Cache-Control", "no-store")
107
+ headers.Set("X-Content-Type-Options", "nosniff")
108
+ w.WriteHeader(http.StatusOK)
109
+ // Go CGI may buffer or block stdout. All helper resources have already been
110
+ // released; there is no long-stream readiness claim from this bounded write.
111
+ _, _ = w.Write(body)
112
+ }
113
+
114
+ // Fixed shape with duplicate-key rejection, so two parsers cannot bind a token
115
+ // to different operations. Controls never grow the existing ctx.call envelope.
116
+ func decodeBinaryReadControl(raw json.RawMessage) (BinaryReadRequest, bool) {
117
+ var in BinaryReadRequest
118
+ if len(raw) > 16*1024 {
119
+ return in, false
120
+ }
121
+ d := json.NewDecoder(bytes.NewReader(raw))
122
+ first, e := d.Token()
123
+ if e != nil || first != json.Delim('{') {
124
+ return in, false
125
+ }
126
+ seen := map[string]bool{}
127
+ for d.More() {
128
+ token, e := d.Token()
129
+ key, ok := token.(string)
130
+ if e != nil || !ok || seen[key] {
131
+ return in, false
132
+ }
133
+ seen[key] = true
134
+ var value string
135
+ if d.Decode(&value) != nil {
136
+ return in, false
137
+ }
138
+ switch key {
139
+ case "operationId":
140
+ in.OperationID = value
141
+ case "epoch":
142
+ in.Epoch = value
143
+ case "token":
144
+ in.Token = value
145
+ default:
146
+ return in, false
147
+ }
148
+ }
149
+ end, e := d.Token()
150
+ if e != nil || end != json.Delim('}') || d.Decode(new(any)) != io.EOF {
151
+ return in, false
152
+ }
153
+ return in, binaryReference.MatchString(in.OperationID) && binaryReference.MatchString(in.Epoch) && binaryReference.MatchString(in.Token)
154
+ }
@@ -0,0 +1,165 @@
1
+ package api
2
+
3
+ import (
4
+ "bytes"
5
+ "context"
6
+ "encoding/json"
7
+ "io"
8
+ "net/http"
9
+ "net/http/cgi"
10
+ "net/http/httptest"
11
+ "os"
12
+ "strings"
13
+ "sync"
14
+ "testing"
15
+ "time"
16
+ )
17
+
18
+ type binarySource struct {
19
+ io.Reader
20
+ closed bool
21
+ }
22
+
23
+ func (s *binarySource) Close() error { s.closed = true; return nil }
24
+ func TestBoundedReadBinaryGuardAndBody(t *testing.T) {
25
+ for _, kind := range []string{"valid", "anonymous", "cross-origin", "oversize", "short", "nil", "cancel"} {
26
+ t.Run(kind, func(t *testing.T) {
27
+ auth := &fakeAuth{user: "normal1"}
28
+ if kind == "anonymous" {
29
+ auth.err = ErrNoSession
30
+ }
31
+ src := &binarySource{Reader: bytes.NewReader([]byte{0, 1, 255, 10})}
32
+ called := false
33
+ srv, e := NewServer(auth, BoundedRead(func(ctx context.Context, c Caller, r *http.Request, params json.RawMessage) (BinaryRead, error) {
34
+ called = true
35
+ if !c.Authenticated() || c.User() != "normal1" {
36
+ t.Fatal(c)
37
+ }
38
+ n := uint64(4)
39
+ if kind == "oversize" {
40
+ n = MaxBinaryReadBytes + 1
41
+ }
42
+ if kind == "short" {
43
+ n = 5
44
+ }
45
+ if kind == "nil" {
46
+ return BinaryRead{}, nil
47
+ }
48
+ return BinaryRead{Body: src, Bytes: n, OperationID: strings.Repeat("a", 64)}, nil
49
+ }))
50
+ if e != nil {
51
+ t.Fatal(e)
52
+ }
53
+ r := httptest.NewRequest("POST", "http://nas.local/cgi/api.cgi", strings.NewReader(`{"method":"nas.files.read.binary","params":{"operationId":"`+strings.Repeat("a", 64)+`","epoch":"`+strings.Repeat("b", 64)+`","token":"`+strings.Repeat("c", 64)+`"}}`))
54
+ r.Header.Set("Content-Type", "application/json")
55
+ if kind == "cross-origin" {
56
+ r.Header.Set("Origin", "http://evil.local")
57
+ }
58
+ if kind == "cancel" {
59
+ ctx, cancel := context.WithCancel(r.Context())
60
+ cancel()
61
+ r = r.WithContext(ctx)
62
+ }
63
+ w := httptest.NewRecorder()
64
+ srv.ServeHTTP(w, r)
65
+ if kind == "valid" {
66
+ if w.Header().Get("Content-Type") != "application/octet-stream" || !bytes.Equal(w.Body.Bytes(), []byte{0, 1, 255, 10}) || w.Header().Get("Content-Length") != "4" || !src.closed {
67
+ t.Fatal(w.Body.String(), w.Header())
68
+ }
69
+ } else {
70
+ if w.Header().Get("Content-Type") != "application/json" {
71
+ t.Fatal("invalid binary escaped")
72
+ }
73
+ if (kind == "anonymous" || kind == "cross-origin" || kind == "cancel") && called {
74
+ t.Fatal("handler called before guards")
75
+ }
76
+ if called && kind != "nil" && !src.closed {
77
+ t.Fatal("source not closed")
78
+ }
79
+ }
80
+ })
81
+ }
82
+ }
83
+
84
+ type blockedBinarySource struct {
85
+ done chan struct{}
86
+ once sync.Once
87
+ }
88
+
89
+ func (s *blockedBinarySource) Read([]byte) (int, error) { <-s.done; return 0, io.ErrClosedPipe }
90
+ func (s *blockedBinarySource) Close() error { s.once.Do(func() { close(s.done) }); return nil }
91
+ func TestBoundedBinaryDisconnectCancelsSource(t *testing.T) {
92
+ src := &blockedBinarySource{done: make(chan struct{})}
93
+ started := make(chan struct{})
94
+ srv, e := NewServer(&fakeAuth{user: "normal1"}, BoundedRead(func(context.Context, Caller, *http.Request, json.RawMessage) (BinaryRead, error) {
95
+ close(started)
96
+ return BinaryRead{Body: src, Bytes: 1, OperationID: strings.Repeat("a", 64)}, nil
97
+ }))
98
+ if e != nil {
99
+ t.Fatal(e)
100
+ }
101
+ ctx, cancel := context.WithCancel(context.Background())
102
+ r := httptest.NewRequest("POST", "http://nas.local/cgi/api.cgi", strings.NewReader(`{"method":"nas.files.read.binary","params":{"operationId":"`+strings.Repeat("a", 64)+`","epoch":"`+strings.Repeat("b", 64)+`","token":"`+strings.Repeat("c", 64)+`"}}`)).WithContext(ctx)
103
+ r.Header.Set("Content-Type", "application/json")
104
+ done := make(chan struct{})
105
+ go func() { defer close(done); srv.ServeHTTP(httptest.NewRecorder(), r) }()
106
+ <-started
107
+ cancel()
108
+ select {
109
+ case <-done:
110
+ case <-time.After(time.Second):
111
+ t.Fatal("disconnect did not release bounded source")
112
+ }
113
+ }
114
+ func TestBoundedBinaryRejectsCallerPathsAndTransferSubstitution(t *testing.T) {
115
+ calls := 0
116
+ srv, e := NewServer(&fakeAuth{user: "normal1"}, BoundedRead(func(context.Context, Caller, *http.Request, json.RawMessage) (BinaryRead, error) {
117
+ calls++
118
+ return BinaryRead{}, nil
119
+ }))
120
+ if e != nil {
121
+ t.Fatal(e)
122
+ }
123
+ for _, params := range []string{`{}`, `{"operationId":"x"}`, `{"operationId":"` + strings.Repeat("a", 64) + `","epoch":"` + strings.Repeat("b", 64) + `","token":"` + strings.Repeat("c", 64) + `","path":"/secret"}`} {
124
+ _, env := post(t, srv, `{"method":"nas.files.read.binary","params":`+params+`}`)
125
+ if env.Success || env.Error == nil || env.Error.Code != "bad_request" {
126
+ t.Fatal(env)
127
+ }
128
+ }
129
+ if calls != 0 {
130
+ t.Fatal("invalid control reached adapter")
131
+ }
132
+ }
133
+
134
+ func TestBoundedBinaryRealCGIWire(t *testing.T) {
135
+ requestBody := `{"method":"nas.files.read.binary","params":{"operationId":"` + strings.Repeat("a", 64) + `","epoch":"` + strings.Repeat("b", 64) + `","token":"` + strings.Repeat("c", 64) + `"}}`
136
+ h := &cgi.Handler{Path: os.Args[0], Args: []string{"-test.run=TestBoundedBinaryCGIProcessFixture"}, Env: []string{"S6_CGI_FIXTURE=1"}}
137
+ r := httptest.NewRequest("POST", "http://nas.local/cgi/api.cgi", strings.NewReader(requestBody))
138
+ r.Header.Set("Content-Type", "application/json")
139
+ w := httptest.NewRecorder()
140
+ h.ServeHTTP(w, r)
141
+ if w.Code != http.StatusOK || w.Header().Get("Content-Type") != "application/octet-stream" || w.Header().Get("Content-Length") != "1048576" || !bytes.Equal(w.Body.Bytes(), bytes.Repeat([]byte{0, 255, 10, 13}, MaxBinaryReadBytes/4)) {
142
+ t.Fatal(w.Code, w.Header(), w.Body.Len())
143
+ }
144
+ }
145
+ func TestBoundedBinaryCGIProcessFixture(t *testing.T) {
146
+ if os.Getenv("S6_CGI_FIXTURE") != "1" {
147
+ t.Skip("spawned CGI-only process")
148
+ }
149
+ srv, e := NewServer(&fakeAuth{user: "normal1"}, BoundedRead(func(context.Context, Caller, *http.Request, json.RawMessage) (BinaryRead, error) {
150
+ return BinaryRead{Body: io.NopCloser(bytes.NewReader(bytes.Repeat([]byte{0, 255, 10, 13}, MaxBinaryReadBytes/4))), Bytes: MaxBinaryReadBytes, OperationID: strings.Repeat("a", 64)}, nil
151
+ }))
152
+ if e != nil {
153
+ os.Exit(1)
154
+ }
155
+ if cgi.Serve(srv) != nil {
156
+ os.Exit(1)
157
+ }
158
+ os.Exit(0)
159
+ }
160
+ func TestBinaryControlRejectsDuplicates(t *testing.T) {
161
+ raw := `{"operationId":"` + strings.Repeat("a", 64) + `","epoch":"` + strings.Repeat("b", 64) + `","token":"` + strings.Repeat("c", 64) + `","token":"` + strings.Repeat("d", 64) + `"}`
162
+ if _, ok := decodeBinaryReadControl(json.RawMessage(raw)); ok {
163
+ t.Fatal("duplicate transfer token")
164
+ }
165
+ }
@@ -32,17 +32,24 @@ type Route struct {
32
32
  method string
33
33
  policy policy
34
34
  handler Handler
35
+ binary BinaryReadHandler
35
36
  }
36
37
 
37
38
  // User declares an operation any signed-in DSM user may call.
38
- func User(method string, h Handler) Route { return Route{method, policyUser, h} }
39
+ func User(method string, h Handler) Route {
40
+ return Route{method: method, policy: policyUser, handler: h}
41
+ }
39
42
 
40
43
  // Admin declares an operation only members of DSM's administrators group may call.
41
- func Admin(method string, h Handler) Route { return Route{method, policyAdmin, h} }
44
+ func Admin(method string, h Handler) Route {
45
+ return Route{method: method, policy: policyAdmin, handler: h}
46
+ }
42
47
 
43
48
  // Public declares an operation that runs WITHOUT a DSM session. Use it only for
44
49
  // data that is safe to show anyone who can reach the NAS's DSM port.
45
- func Public(method string, h Handler) Route { return Route{method, policyPublic, h} }
50
+ func Public(method string, h Handler) Route {
51
+ return Route{method: method, policy: policyPublic, handler: h}
52
+ }
46
53
 
47
54
  // Identity is what an Authenticator established about the requester.
48
55
  type Identity struct {
@@ -73,7 +80,10 @@ func buildRegistry(routes []Route) (map[string]Route, error) {
73
80
  if !methodName.MatchString(r.method) {
74
81
  return nil, fmt.Errorf("route %q: method must look like \"area.action\" (lowercase)", r.method)
75
82
  }
76
- if r.handler == nil {
83
+ if r.binary != nil && (r.method != "nas.files.read.binary" || r.policy != policyUser || r.handler != nil) {
84
+ return nil, errors.New("binary read must use the fixed authenticated route")
85
+ }
86
+ if r.handler == nil && r.binary == nil {
77
87
  return nil, fmt.Errorf("route %q has no handler", r.method)
78
88
  }
79
89
  if _, dup := registry[r.method]; dup {
@@ -67,6 +67,10 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
67
67
  writeError(w, apiErr)
68
68
  return
69
69
  }
70
+ if route.binary != nil {
71
+ serveBoundedRead(w, r, caller, req.Params, route.binary)
72
+ return
73
+ }
70
74
  data, err := route.handler(r.Context(), caller, req.Params)
71
75
  if err != nil {
72
76
  writeError(w, asError(err))