@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.
- package/LICENSE +21 -0
- package/README.md +37 -0
- package/dist/build-spk/generator.js +3 -0
- package/dist/build-spk/notices.d.ts +5 -0
- package/dist/build-spk/notices.js +60 -0
- package/dist/cli.js +9 -2
- package/dist/error-registry.js +20 -0
- package/dist/init.d.ts +4 -0
- package/dist/init.js +20 -12
- package/dist/standalone/build.js +3 -1
- package/dist/standalone/daemon.d.ts +23 -0
- package/dist/standalone/daemon.js +114 -0
- package/dist/standalone/dsm-window.d.ts +1 -1
- package/dist/standalone/dsm-window.js +50 -10
- package/dist/standalone/helper-inventory.d.ts +16 -0
- package/dist/standalone/helper-inventory.js +2 -0
- package/dist/standalone/helper.d.ts +2 -12
- package/dist/standalone/helper.js +8 -7
- package/dist/standalone/host-adapter.d.ts +5 -0
- package/dist/standalone/host-adapter.js +148 -0
- package/dist/standalone/host-platform.d.ts +13 -0
- package/dist/standalone/host-platform.js +42 -0
- package/dist/standalone/host-types.d.ts +49 -0
- package/dist/standalone/host-types.js +1 -0
- package/dist/standalone/inspect-helper.d.ts +6 -0
- package/dist/standalone/inspect-helper.js +88 -0
- package/dist/standalone/inspect-spk.d.ts +2 -0
- package/dist/standalone/inspect-spk.js +49 -0
- package/dist/standalone/lifecycle-helper.d.ts +2 -0
- package/dist/standalone/lifecycle-helper.js +12 -0
- package/dist/standalone/lifecycle.d.ts +3 -0
- package/dist/standalone/lifecycle.js +53 -0
- package/dist/standalone/manifest.d.ts +2 -0
- package/dist/standalone/manifest.js +4 -1
- package/dist/standalone/reopen-events.d.ts +2 -0
- package/dist/standalone/reopen-events.js +28 -0
- package/dist/standalone/root-messages.js +9 -0
- package/dist/standalone/root-window.d.ts +4 -3
- package/dist/standalone/root-window.js +17 -5
- package/dist/standalone/spk.d.ts +4 -3
- package/dist/standalone/spk.js +20 -33
- package/dist/template-paths.d.ts +2 -0
- package/dist/template-paths.js +9 -0
- package/dist/templates/_daemon/fixture_linux_test.go +15 -0
- package/dist/templates/_daemon/fixture_other_test.go +7 -0
- package/dist/templates/_daemon/go.mod +3 -0
- package/dist/templates/_daemon/main.go +608 -0
- package/dist/templates/_daemon/main_test.go +242 -0
- package/dist/templates/_daemon/process_linux.go +55 -0
- package/dist/templates/_daemon/process_linux_test.go +161 -0
- package/dist/templates/_daemon/process_other.go +14 -0
- package/dist/templates/_daemon/testdata/child.go +41 -0
- package/dist/templates/_shared/GO-LICENSE +27 -0
- package/dist/templates/_shared/GO-PATENTS +22 -0
- package/dist/templates/_shared/LICENSES/TEMPLATE.txt +21 -0
- package/dist/templates/_shared/notice-overrides/index.json +14 -0
- package/dist/templates/_shared/notice-overrides/utils-0.4.2-LICENSE +21 -0
- package/dist/templates/_shared/notice-overrides/utils-0.5.0-LICENSE +21 -0
- package/dist/templates/_shared/third-party-notices.mjs +51 -0
- package/dist/templates/native-go/README.md +57 -1
- package/dist/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +59 -0
- package/dist/templates/native-go/backend/cmd/dsm-readonly-probe/main_linux.go +46 -0
- package/dist/templates/native-go/backend/go.mod +4 -0
- package/dist/templates/native-go/backend/go.sum +4 -0
- package/dist/templates/native-go/backend/internal/api/binary.go +154 -0
- package/dist/templates/native-go/backend/internal/api/binary_test.go +165 -0
- package/dist/templates/native-go/backend/internal/api/registry.go +14 -4
- package/dist/templates/native-go/backend/internal/api/server.go +4 -0
- package/dist/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +121 -0
- package/dist/templates/native-go/backend/internal/app/nas_refusal_test.go +46 -0
- package/dist/templates/native-go/backend/internal/app/routes.go +11 -0
- package/dist/templates/native-go/backend/internal/app/routes_test.go +10 -5
- package/dist/templates/native-go/backend/internal/dsmprobe/collector_linux.go +335 -0
- package/dist/templates/native-go/backend/internal/dsmprobe/collector_linux_test.go +41 -0
- package/dist/templates/native-go/backend/internal/dsmprobe/protocol.go +179 -0
- package/dist/templates/native-go/backend/internal/dsmprobe/protocol_test.go +29 -0
- package/dist/templates/native-go/backend/internal/helper/cohort.go +393 -0
- package/dist/templates/native-go/backend/internal/helper/cohort_publication.go +18 -0
- package/dist/templates/native-go/backend/internal/helper/cohort_publication_test.go +105 -0
- package/dist/templates/native-go/backend/internal/helper/cohort_test.go +372 -0
- package/dist/templates/native-go/backend/internal/helper/control.go +226 -21
- package/dist/templates/native-go/backend/internal/helper/control_test.go +10 -2
- package/dist/templates/native-go/backend/internal/helper/data_contract.go +242 -0
- package/dist/templates/native-go/backend/internal/helper/data_contract_test.go +51 -0
- package/dist/templates/native-go/backend/internal/helper/data_decode.go +184 -0
- package/dist/templates/native-go/backend/internal/helper/data_decode_pointer_test.go +30 -0
- package/dist/templates/native-go/backend/internal/helper/data_protocol.go +416 -0
- package/dist/templates/native-go/backend/internal/helper/data_protocol_test.go +449 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_linux.go +139 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_linux_test.go +121 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux.go +95 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux_test.go +56 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_bridge_linux.go +144 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_bridge_linux_test.go +89 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_home_linux.go +107 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_home_linux_test.go +82 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_probe_transport_linux.go +151 -0
- package/dist/templates/native-go/backend/internal/helper/dsm_probe_transport_linux_test.go +66 -0
- package/dist/templates/native-go/backend/internal/helper/grant_authority.go +516 -0
- package/dist/templates/native-go/backend/internal/helper/grant_authority_contract.go +88 -0
- package/dist/templates/native-go/backend/internal/helper/grant_authority_test.go +510 -0
- package/dist/templates/native-go/backend/internal/helper/grant_cohort.go +389 -0
- package/dist/templates/native-go/backend/internal/helper/grant_cohort_test.go +239 -0
- package/dist/templates/native-go/backend/internal/helper/grant_delivery.go +49 -0
- package/dist/templates/native-go/backend/internal/helper/grant_delivery_methods.go +273 -0
- package/dist/templates/native-go/backend/internal/helper/grant_delivery_test.go +322 -0
- package/dist/templates/native-go/backend/internal/helper/grant_operation_contract.go +47 -0
- package/dist/templates/native-go/backend/internal/helper/grant_readonly_test.go +180 -0
- package/dist/templates/native-go/backend/internal/helper/grant_repository_linux.go +415 -0
- package/dist/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +468 -0
- package/dist/templates/native-go/backend/internal/helper/grant_rpc.go +147 -0
- package/dist/templates/native-go/backend/internal/helper/grant_rpc_test.go +51 -0
- package/dist/templates/native-go/backend/internal/helper/grant_snapshot.go +75 -0
- package/dist/templates/native-go/backend/internal/helper/grant_supervisor_linux.go +134 -0
- package/dist/templates/native-go/backend/internal/helper/grant_supervisor_linux_test.go +254 -0
- package/dist/templates/native-go/backend/internal/helper/lease.go +112 -0
- package/dist/templates/native-go/backend/internal/helper/lease_linux.go +44 -0
- package/dist/templates/native-go/backend/internal/helper/lease_other.go +8 -0
- package/dist/templates/native-go/backend/internal/helper/lifecycle.go +234 -0
- package/dist/templates/native-go/backend/internal/helper/lifecycle_test.go +473 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot.go +284 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot_repository_linux.go +74 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot_repository_linux_test.go +40 -0
- package/dist/templates/native-go/backend/internal/helper/managed_pilot_test.go +210 -0
- package/dist/templates/native-go/backend/internal/helper/nas_shipped_refusal_linux_test.go +97 -0
- package/dist/templates/native-go/backend/internal/helper/native_discovery.go +79 -0
- package/dist/templates/native-go/backend/internal/helper/native_identity.go +89 -0
- package/dist/templates/native-go/backend/internal/helper/native_provider.go +159 -0
- package/dist/templates/native-go/backend/internal/helper/native_provider_test.go +421 -0
- package/dist/templates/native-go/backend/internal/helper/observation.go +204 -0
- package/dist/templates/native-go/backend/internal/helper/observation_health_test.go +115 -0
- package/dist/templates/native-go/backend/internal/helper/observation_reload_budget_test.go +117 -0
- package/dist/templates/native-go/backend/internal/helper/observation_test.go +196 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic.go +109 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_linux.go +76 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +124 -0
- package/dist/templates/native-go/backend/internal/helper/observer_diagnostic_test.go +98 -0
- package/dist/templates/native-go/backend/internal/helper/operation_bootstrap_linux.go +193 -0
- package/dist/templates/native-go/backend/internal/helper/operation_credentials_linux.go +56 -0
- package/dist/templates/native-go/backend/internal/helper/operation_linux.go +480 -0
- package/dist/templates/native-go/backend/internal/helper/operation_linux_test.go +528 -0
- package/dist/templates/native-go/backend/internal/helper/process_linux.go +11 -1
- package/dist/templates/native-go/backend/internal/helper/publication_test.go +178 -0
- package/dist/templates/native-go/backend/internal/helper/read_stream_cohort_linux_test.go +156 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer.go +40 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer_linux.go +109 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer_linux_test.go +118 -0
- package/dist/templates/native-go/backend/internal/helper/read_transfer_test.go +177 -0
- package/dist/templates/native-go/backend/internal/helper/readonly.go +105 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_admission.go +85 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_cohort_linux_test.go +253 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_linux_test.go +378 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_mount_linux.go +65 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_mount_proxy_linux.go +113 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_operations_linux.go +168 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_resolver_linux.go +241 -0
- package/dist/templates/native-go/backend/internal/helper/readonly_test.go +40 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_identity.go +252 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_identity_contract.go +105 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_identity_test.go +406 -0
- package/dist/templates/native-go/backend/internal/helper/relaxed_invalidation.go +200 -0
- package/dist/templates/native-go/backend/internal/helper/repair.go +132 -0
- package/dist/templates/native-go/backend/internal/helper/repair_test.go +271 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_actor_acl_linux_test.go +303 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_actor_fixture_linux_test.go +184 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +231 -0
- package/dist/templates/native-go/backend/internal/helper/s1r_fixture_contract_linux_test.go +18 -0
- package/dist/templates/native-go/backend/internal/helper/server_linux.go +44 -3
- package/dist/templates/native-go/backend/internal/helper/status.go +74 -11
- package/dist/templates/native-go/backend/internal/helper/status_test.go +83 -0
- package/dist/templates/native-go/backend/internal/helper/supervision.go +28 -5
- package/dist/templates/native-go/backend/internal/helper/supervisor_frame.go +76 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_frame_linux_test.go +69 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_frame_test.go +107 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_linux.go +187 -16
- package/dist/templates/native-go/backend/internal/helper/supervisor_linux_test.go +618 -7
- package/dist/templates/native-go/backend/internal/helper/supervisor_socket_eof_test.go +74 -0
- package/dist/templates/native-go/backend/internal/helper/supervisor_socket_test.go +45 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/create.json +23 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/frames.json +67 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/grant-store.json +52 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/intent.json +20 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/list.json +20 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/publish.json +20 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/read.json +22 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/stat.json +22 -0
- package/dist/templates/native-go/backend/internal/helper/testdata/protocol2/write-stream.json +22 -0
- package/dist/templates/native-go/backend/internal/helper/unit_connection.go +75 -0
- package/dist/templates/native-go/backend/internal/helper/unit_connection_linux_test.go +135 -0
- package/dist/templates/native-go/backend/internal/helper/unit_connection_test.go +133 -0
- package/dist/templates/native-go/backend/internal/helper/unit_frame_test.go +32 -0
- package/dist/templates/native-go/backend/internal/helper/unit_linux.go +364 -0
- package/dist/templates/native-go/backend/internal/helper/unit_linux_test.go +46 -0
- package/dist/templates/native-go/backend/internal/helper/unit_mechanisms_linux_test.go +217 -0
- package/dist/templates/native-go/backend/internal/helper/unit_padding_linux_test.go +178 -0
- package/dist/templates/native-go/backend/internal/helper/unit_query_linux.go +111 -0
- package/dist/templates/native-go/backend/internal/helper/unit_reload_linux_test.go +372 -0
- package/dist/templates/native-go/backend/internal/helper/unit_reload_sequence_linux_test.go +232 -0
- package/dist/templates/native-go/backend/internal/helper/write.go +77 -0
- package/dist/templates/native-go/backend/internal/helper/write_admission.go +260 -0
- package/dist/templates/native-go/backend/internal/helper/write_admission_test.go +135 -0
- package/dist/templates/native-go/backend/internal/helper/write_cohort_linux_test.go +218 -0
- package/dist/templates/native-go/backend/internal/helper/write_files_linux.go +202 -0
- package/dist/templates/native-go/backend/internal/helper/write_files_linux_test.go +199 -0
- package/dist/templates/native-go/backend/internal/helper/write_intent_linux.go +116 -0
- package/dist/templates/native-go/backend/internal/helper/write_intent_linux_test.go +74 -0
- package/dist/templates/native-go/backend/internal/helper/write_operation_linux.go +245 -0
- package/dist/templates/native-go/backend/internal/helper/write_test.go +53 -0
- package/dist/templates/native-go/ui/app.js +8 -1
- package/dist/templates/native-go-better-auth/node/build.mjs +2 -0
- package/dist/templates/native-go-vue/README.md +115 -1
- package/dist/templates/native-go-vue/frontend/DESIGN.md +1 -1
- package/dist/templates/native-go-vue/frontend/package-lock.json +132 -229
- package/dist/templates/native-go-vue/frontend/package.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/App.vue +33 -6
- package/dist/templates/native-go-vue/frontend/src/context.ts +41 -2
- package/dist/templates/native-go-vue/frontend/src/main.ts +4 -1
- package/dist/templates/native-go-vue/frontend/src/nas/NasGrantSettings.vue +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/NasPathPicker.vue +106 -0
- package/dist/templates/native-go-vue/frontend/src/nas/NasUnavailable.vue +20 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/de.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/en.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/es.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/fr.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/it.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/ja.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/ko.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/zh-CN.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/zh-TW.json +74 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n.ts +38 -0
- package/dist/templates/native-go-vue/frontend/src/nas/mock-provider.ts +119 -0
- package/dist/templates/native-go-vue/frontend/src/nas/provider.ts +59 -0
- package/dist/templates/native-go-vue/frontend/src/nas/use-request.ts +27 -0
- package/dist/templates/native-go-vue/frontend/src/style.css +17 -0
- package/dist/templates/native-go-vue/frontend/test/apps.test.ts +44 -2
- package/dist/templates/native-go-vue/frontend/test/nas-provider.test.ts +81 -0
- package/dist/templates/native-go-vue/frontend/test/nas-request.test.ts +21 -0
- package/dist/templates/native-go-vue/frontend/test/nas-ui.test.ts +261 -0
- package/dist/templates/native-go-vue/frontend/tsconfig.json +1 -1
- package/dist/templates/native-go-vue/frontend/vite.config.ts +6 -4
- package/package.json +3 -2
- package/templates/_daemon/fixture_linux_test.go +15 -0
- package/templates/_daemon/fixture_other_test.go +7 -0
- package/templates/_daemon/go.mod +3 -0
- package/templates/_daemon/main.go +608 -0
- package/templates/_daemon/main_test.go +242 -0
- package/templates/_daemon/process_linux.go +55 -0
- package/templates/_daemon/process_linux_test.go +161 -0
- package/templates/_daemon/process_other.go +14 -0
- package/templates/_daemon/testdata/child.go +41 -0
- package/templates/_shared/GO-LICENSE +27 -0
- package/templates/_shared/GO-PATENTS +22 -0
- package/templates/_shared/LICENSES/TEMPLATE.txt +21 -0
- package/templates/_shared/notice-overrides/index.json +14 -0
- package/templates/_shared/notice-overrides/utils-0.4.2-LICENSE +21 -0
- package/templates/_shared/notice-overrides/utils-0.5.0-LICENSE +21 -0
- package/templates/_shared/third-party-notices.mjs +51 -0
- package/templates/native-go/README.md +57 -1
- package/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +59 -0
- package/templates/native-go/backend/cmd/dsm-readonly-probe/main_linux.go +46 -0
- package/templates/native-go/backend/go.mod +4 -0
- package/templates/native-go/backend/go.sum +4 -0
- package/templates/native-go/backend/internal/api/binary.go +154 -0
- package/templates/native-go/backend/internal/api/binary_test.go +165 -0
- package/templates/native-go/backend/internal/api/registry.go +14 -4
- package/templates/native-go/backend/internal/api/server.go +4 -0
- package/templates/native-go/backend/internal/app/nas_cgi_artifact_test.go +121 -0
- package/templates/native-go/backend/internal/app/nas_refusal_test.go +46 -0
- package/templates/native-go/backend/internal/app/routes.go +11 -0
- package/templates/native-go/backend/internal/app/routes_test.go +10 -5
- package/templates/native-go/backend/internal/dsmprobe/collector_linux.go +335 -0
- package/templates/native-go/backend/internal/dsmprobe/collector_linux_test.go +41 -0
- package/templates/native-go/backend/internal/dsmprobe/protocol.go +179 -0
- package/templates/native-go/backend/internal/dsmprobe/protocol_test.go +29 -0
- package/templates/native-go/backend/internal/helper/cohort.go +393 -0
- package/templates/native-go/backend/internal/helper/cohort_publication.go +18 -0
- package/templates/native-go/backend/internal/helper/cohort_publication_test.go +105 -0
- package/templates/native-go/backend/internal/helper/cohort_test.go +372 -0
- package/templates/native-go/backend/internal/helper/control.go +226 -21
- package/templates/native-go/backend/internal/helper/control_test.go +10 -2
- package/templates/native-go/backend/internal/helper/data_contract.go +242 -0
- package/templates/native-go/backend/internal/helper/data_contract_test.go +51 -0
- package/templates/native-go/backend/internal/helper/data_decode.go +184 -0
- package/templates/native-go/backend/internal/helper/data_decode_pointer_test.go +30 -0
- package/templates/native-go/backend/internal/helper/data_protocol.go +416 -0
- package/templates/native-go/backend/internal/helper/data_protocol_test.go +449 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_linux.go +139 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_linux_test.go +121 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux.go +95 -0
- package/templates/native-go/backend/internal/helper/dsm_acl_syscall_linux_test.go +56 -0
- package/templates/native-go/backend/internal/helper/dsm_bridge_linux.go +144 -0
- package/templates/native-go/backend/internal/helper/dsm_bridge_linux_test.go +89 -0
- package/templates/native-go/backend/internal/helper/dsm_home_linux.go +107 -0
- package/templates/native-go/backend/internal/helper/dsm_home_linux_test.go +82 -0
- package/templates/native-go/backend/internal/helper/dsm_probe_transport_linux.go +151 -0
- package/templates/native-go/backend/internal/helper/dsm_probe_transport_linux_test.go +66 -0
- package/templates/native-go/backend/internal/helper/grant_authority.go +516 -0
- package/templates/native-go/backend/internal/helper/grant_authority_contract.go +88 -0
- package/templates/native-go/backend/internal/helper/grant_authority_test.go +510 -0
- package/templates/native-go/backend/internal/helper/grant_cohort.go +389 -0
- package/templates/native-go/backend/internal/helper/grant_cohort_test.go +239 -0
- package/templates/native-go/backend/internal/helper/grant_delivery.go +49 -0
- package/templates/native-go/backend/internal/helper/grant_delivery_methods.go +273 -0
- package/templates/native-go/backend/internal/helper/grant_delivery_test.go +322 -0
- package/templates/native-go/backend/internal/helper/grant_operation_contract.go +47 -0
- package/templates/native-go/backend/internal/helper/grant_readonly_test.go +180 -0
- package/templates/native-go/backend/internal/helper/grant_repository_linux.go +415 -0
- package/templates/native-go/backend/internal/helper/grant_repository_linux_test.go +468 -0
- package/templates/native-go/backend/internal/helper/grant_rpc.go +147 -0
- package/templates/native-go/backend/internal/helper/grant_rpc_test.go +51 -0
- package/templates/native-go/backend/internal/helper/grant_snapshot.go +75 -0
- package/templates/native-go/backend/internal/helper/grant_supervisor_linux.go +134 -0
- package/templates/native-go/backend/internal/helper/grant_supervisor_linux_test.go +254 -0
- package/templates/native-go/backend/internal/helper/lease.go +112 -0
- package/templates/native-go/backend/internal/helper/lease_linux.go +44 -0
- package/templates/native-go/backend/internal/helper/lease_other.go +8 -0
- package/templates/native-go/backend/internal/helper/lifecycle.go +234 -0
- package/templates/native-go/backend/internal/helper/lifecycle_test.go +473 -0
- package/templates/native-go/backend/internal/helper/managed_pilot.go +284 -0
- package/templates/native-go/backend/internal/helper/managed_pilot_repository_linux.go +74 -0
- package/templates/native-go/backend/internal/helper/managed_pilot_repository_linux_test.go +40 -0
- package/templates/native-go/backend/internal/helper/managed_pilot_test.go +210 -0
- package/templates/native-go/backend/internal/helper/nas_shipped_refusal_linux_test.go +97 -0
- package/templates/native-go/backend/internal/helper/native_discovery.go +79 -0
- package/templates/native-go/backend/internal/helper/native_identity.go +89 -0
- package/templates/native-go/backend/internal/helper/native_provider.go +159 -0
- package/templates/native-go/backend/internal/helper/native_provider_test.go +421 -0
- package/templates/native-go/backend/internal/helper/observation.go +204 -0
- package/templates/native-go/backend/internal/helper/observation_health_test.go +115 -0
- package/templates/native-go/backend/internal/helper/observation_reload_budget_test.go +117 -0
- package/templates/native-go/backend/internal/helper/observation_test.go +196 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic.go +109 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic_linux.go +76 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic_linux_test.go +124 -0
- package/templates/native-go/backend/internal/helper/observer_diagnostic_test.go +98 -0
- package/templates/native-go/backend/internal/helper/operation_bootstrap_linux.go +193 -0
- package/templates/native-go/backend/internal/helper/operation_credentials_linux.go +56 -0
- package/templates/native-go/backend/internal/helper/operation_linux.go +480 -0
- package/templates/native-go/backend/internal/helper/operation_linux_test.go +528 -0
- package/templates/native-go/backend/internal/helper/process_linux.go +11 -1
- package/templates/native-go/backend/internal/helper/publication_test.go +178 -0
- package/templates/native-go/backend/internal/helper/read_stream_cohort_linux_test.go +156 -0
- package/templates/native-go/backend/internal/helper/read_transfer.go +40 -0
- package/templates/native-go/backend/internal/helper/read_transfer_linux.go +109 -0
- package/templates/native-go/backend/internal/helper/read_transfer_linux_test.go +118 -0
- package/templates/native-go/backend/internal/helper/read_transfer_test.go +177 -0
- package/templates/native-go/backend/internal/helper/readonly.go +105 -0
- package/templates/native-go/backend/internal/helper/readonly_admission.go +85 -0
- package/templates/native-go/backend/internal/helper/readonly_cohort_linux_test.go +253 -0
- package/templates/native-go/backend/internal/helper/readonly_linux_test.go +378 -0
- package/templates/native-go/backend/internal/helper/readonly_mount_linux.go +65 -0
- package/templates/native-go/backend/internal/helper/readonly_mount_proxy_linux.go +113 -0
- package/templates/native-go/backend/internal/helper/readonly_operations_linux.go +168 -0
- package/templates/native-go/backend/internal/helper/readonly_resolver_linux.go +241 -0
- package/templates/native-go/backend/internal/helper/readonly_test.go +40 -0
- package/templates/native-go/backend/internal/helper/relaxed_identity.go +252 -0
- package/templates/native-go/backend/internal/helper/relaxed_identity_contract.go +105 -0
- package/templates/native-go/backend/internal/helper/relaxed_identity_test.go +406 -0
- package/templates/native-go/backend/internal/helper/relaxed_invalidation.go +200 -0
- package/templates/native-go/backend/internal/helper/repair.go +132 -0
- package/templates/native-go/backend/internal/helper/repair_test.go +271 -0
- package/templates/native-go/backend/internal/helper/s1r_actor_acl_linux_test.go +303 -0
- package/templates/native-go/backend/internal/helper/s1r_actor_fixture_linux_test.go +184 -0
- package/templates/native-go/backend/internal/helper/s1r_actor_races_linux_test.go +231 -0
- package/templates/native-go/backend/internal/helper/s1r_fixture_contract_linux_test.go +18 -0
- package/templates/native-go/backend/internal/helper/server_linux.go +44 -3
- package/templates/native-go/backend/internal/helper/status.go +74 -11
- package/templates/native-go/backend/internal/helper/status_test.go +83 -0
- package/templates/native-go/backend/internal/helper/supervision.go +28 -5
- package/templates/native-go/backend/internal/helper/supervisor_frame.go +76 -0
- package/templates/native-go/backend/internal/helper/supervisor_frame_linux_test.go +69 -0
- package/templates/native-go/backend/internal/helper/supervisor_frame_test.go +107 -0
- package/templates/native-go/backend/internal/helper/supervisor_linux.go +187 -16
- package/templates/native-go/backend/internal/helper/supervisor_linux_test.go +618 -7
- package/templates/native-go/backend/internal/helper/supervisor_socket_eof_test.go +74 -0
- package/templates/native-go/backend/internal/helper/supervisor_socket_test.go +45 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/create.json +23 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/frames.json +67 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/grant-store.json +52 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/intent.json +20 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/list.json +20 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/publish.json +20 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/read.json +22 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/stat.json +22 -0
- package/templates/native-go/backend/internal/helper/testdata/protocol2/write-stream.json +22 -0
- package/templates/native-go/backend/internal/helper/unit_connection.go +75 -0
- package/templates/native-go/backend/internal/helper/unit_connection_linux_test.go +135 -0
- package/templates/native-go/backend/internal/helper/unit_connection_test.go +133 -0
- package/templates/native-go/backend/internal/helper/unit_frame_test.go +32 -0
- package/templates/native-go/backend/internal/helper/unit_linux.go +364 -0
- package/templates/native-go/backend/internal/helper/unit_linux_test.go +46 -0
- package/templates/native-go/backend/internal/helper/unit_mechanisms_linux_test.go +217 -0
- package/templates/native-go/backend/internal/helper/unit_padding_linux_test.go +178 -0
- package/templates/native-go/backend/internal/helper/unit_query_linux.go +111 -0
- package/templates/native-go/backend/internal/helper/unit_reload_linux_test.go +372 -0
- package/templates/native-go/backend/internal/helper/unit_reload_sequence_linux_test.go +232 -0
- package/templates/native-go/backend/internal/helper/write.go +77 -0
- package/templates/native-go/backend/internal/helper/write_admission.go +260 -0
- package/templates/native-go/backend/internal/helper/write_admission_test.go +135 -0
- package/templates/native-go/backend/internal/helper/write_cohort_linux_test.go +218 -0
- package/templates/native-go/backend/internal/helper/write_files_linux.go +202 -0
- package/templates/native-go/backend/internal/helper/write_files_linux_test.go +199 -0
- package/templates/native-go/backend/internal/helper/write_intent_linux.go +116 -0
- package/templates/native-go/backend/internal/helper/write_intent_linux_test.go +74 -0
- package/templates/native-go/backend/internal/helper/write_operation_linux.go +245 -0
- package/templates/native-go/backend/internal/helper/write_test.go +53 -0
- package/templates/native-go/ui/app.js +8 -1
- package/templates/native-go-better-auth/node/build.mjs +2 -0
- package/templates/native-go-vue/README.md +115 -1
- package/templates/native-go-vue/frontend/DESIGN.md +1 -1
- package/templates/native-go-vue/frontend/package-lock.json +132 -229
- package/templates/native-go-vue/frontend/package.json +1 -1
- package/templates/native-go-vue/frontend/src/App.vue +33 -6
- package/templates/native-go-vue/frontend/src/context.ts +41 -2
- package/templates/native-go-vue/frontend/src/main.ts +4 -1
- package/templates/native-go-vue/frontend/src/nas/NasGrantSettings.vue +74 -0
- package/templates/native-go-vue/frontend/src/nas/NasPathPicker.vue +106 -0
- package/templates/native-go-vue/frontend/src/nas/NasUnavailable.vue +20 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/de.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/en.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/es.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/fr.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/it.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/ja.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/ko.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/zh-CN.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/zh-TW.json +74 -0
- package/templates/native-go-vue/frontend/src/nas/i18n.ts +38 -0
- package/templates/native-go-vue/frontend/src/nas/mock-provider.ts +119 -0
- package/templates/native-go-vue/frontend/src/nas/provider.ts +59 -0
- package/templates/native-go-vue/frontend/src/nas/use-request.ts +27 -0
- package/templates/native-go-vue/frontend/src/style.css +17 -0
- package/templates/native-go-vue/frontend/test/apps.test.ts +44 -2
- package/templates/native-go-vue/frontend/test/nas-provider.test.ts +81 -0
- package/templates/native-go-vue/frontend/test/nas-request.test.ts +21 -0
- package/templates/native-go-vue/frontend/test/nas-ui.test.ts +261 -0
- package/templates/native-go-vue/frontend/tsconfig.json +1 -1
- 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
|
+
}
|
|
@@ -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 {
|
|
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 {
|
|
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 {
|
|
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
|
|
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))
|