@synopackageland/cli 0.6.1 → 0.7.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/CHANGELOG.md +846 -0
- package/README.md +81 -89
- package/dist/add.d.ts +4 -1
- package/dist/add.js +45 -17
- package/dist/build-spk/delegate-scope.d.ts +6 -0
- package/dist/build-spk/delegate-scope.js +34 -0
- package/dist/build-spk/dsm-arch.d.ts +7 -1
- package/dist/build-spk/dsm-arch.js +24 -28
- package/dist/build-spk/dsm-platforms.json +42 -0
- package/dist/build-spk/dsm-version.d.ts +11 -0
- package/dist/build-spk/dsm-version.js +17 -0
- package/dist/build-spk/gateway.js +8 -4
- package/dist/build-spk/generator.js +30 -5
- package/dist/build-spk/go-toolchain.d.ts +20 -0
- package/dist/build-spk/go-toolchain.js +44 -0
- package/dist/build-spk/notices.js +4 -1
- package/dist/build-spk/resource-worker.js +3 -0
- package/dist/build-spk/wizard-messages.d.ts +66 -0
- package/dist/build-spk/wizard-messages.js +75 -9
- package/dist/cli.js +28 -14
- package/dist/contract/schema-validate.js +8 -0
- package/dist/contract/validate.js +30 -0
- package/dist/deploy/deploy.d.ts +1 -1
- package/dist/deploy/deploy.js +8 -0
- package/dist/deploy/native-install-values.d.ts +17 -0
- package/dist/deploy/native-install-values.js +32 -0
- package/dist/deploy/plan.d.ts +6 -2
- package/dist/deploy/plan.js +58 -7
- package/dist/deploy/spk-version.js +1 -1
- package/dist/error-registry.js +54 -20
- package/dist/host/dsm-client.d.ts +8 -4
- package/dist/host/dsm-client.js +63 -21
- package/dist/host/dsm-http.js +24 -2
- package/dist/host/types.d.ts +3 -1
- package/dist/info.js +45 -10
- package/dist/init.d.ts +3 -0
- package/dist/init.js +50 -19
- package/dist/package-metadata.d.ts +21 -0
- package/dist/package-metadata.js +101 -0
- package/dist/portal/alias.d.ts +25 -0
- package/dist/portal/alias.js +48 -0
- package/dist/portal/package.d.ts +33 -0
- package/dist/portal/package.js +116 -0
- package/dist/runtime/delegate-contract.d.ts +79 -0
- package/dist/runtime/delegate-contract.js +27 -0
- package/dist/runtime/dsm-version.d.ts +6 -0
- package/dist/runtime/dsm-version.js +8 -0
- package/dist/runtime/executor-build.js +10 -6
- package/dist/runtime/executor-inspect.d.ts +3 -0
- package/dist/runtime/executor-inspect.js +11 -5
- package/dist/runtime/executor-policy.d.ts +12 -0
- package/dist/runtime/executor-policy.js +43 -3
- package/dist/runtime/executor-scope-task.d.ts +4 -0
- package/dist/runtime/executor-scope-task.js +21 -0
- package/dist/runtime/executor-tasks.d.ts +2 -1
- package/dist/runtime/executor-tasks.js +4 -4
- package/dist/skill.js +1 -0
- package/dist/standalone/api-permissions.d.ts +10 -0
- package/dist/standalone/api-permissions.js +19 -2
- package/dist/standalone/background.d.ts +16 -0
- package/dist/standalone/background.js +69 -2
- package/dist/standalone/binary.d.ts +1 -1
- package/dist/standalone/binary.js +22 -8
- package/dist/standalone/build.d.ts +1 -1
- package/dist/standalone/build.js +38 -8
- package/dist/standalone/daemon.d.ts +1 -0
- package/dist/standalone/daemon.js +10 -5
- package/dist/standalone/dsm-window.d.ts +3 -1
- package/dist/standalone/dsm-window.js +78 -49
- package/dist/standalone/inspect-spk.d.ts +8 -0
- package/dist/standalone/inspect-spk.js +110 -27
- package/dist/standalone/lifecycle.js +86 -8
- package/dist/standalone/manifest.d.ts +13 -0
- package/dist/standalone/manifest.js +57 -8
- package/dist/standalone/native-authorization-window.d.ts +1 -1
- package/dist/standalone/native-authorization-window.js +9 -1
- package/dist/standalone/native-layout.d.ts +3 -0
- package/dist/standalone/native-layout.js +37 -5
- package/dist/standalone/native-root-window.d.ts +4 -2
- package/dist/standalone/native-root-window.js +33 -18
- package/dist/standalone/portal-window.d.ts +21 -0
- package/dist/standalone/portal-window.js +155 -0
- package/dist/standalone/portal.d.ts +4 -0
- package/dist/standalone/portal.js +4 -0
- package/dist/standalone/resource.d.ts +5 -3
- package/dist/standalone/resource.js +6 -3
- package/dist/standalone/root-window.d.ts +4 -1
- package/dist/standalone/root-window.js +193 -36
- package/dist/standalone/spk.d.ts +1 -1
- package/dist/standalone/spk.js +25 -7
- package/dist/templates/_daemon/go.mod +1 -1
- package/dist/templates/_daemon/main.go +6 -3
- package/dist/templates/_daemon/main_test.go +82 -9
- package/dist/templates/_daemon/testdata/child.go +3 -0
- package/dist/templates/_executor/README.md +130 -16
- package/dist/templates/_executor/anchor.go +156 -0
- package/dist/templates/_executor/anchor_test.go +161 -0
- package/dist/templates/_executor/apppriv_review_test.go +1 -1
- package/dist/templates/_executor/cancel_contract_test.go +236 -0
- package/dist/templates/_executor/copy.go +64 -0
- package/dist/templates/_executor/copy_test.go +88 -0
- package/dist/templates/_executor/digest_review_test.go +2 -2
- package/dist/templates/_executor/dsm.go +63 -13
- package/dist/templates/_executor/dsm_test.go +95 -1
- package/dist/templates/_executor/executor.go +260 -49
- package/dist/templates/_executor/executor_test.go +36 -6
- package/dist/templates/_executor/go.mod +2 -0
- package/dist/templates/_executor/identity.go +27 -1
- package/dist/templates/_executor/identity_kernel_linux_test.go +60 -0
- package/dist/templates/_executor/identity_linux.go +82 -0
- package/dist/templates/_executor/identity_security_test.go +43 -0
- package/dist/templates/_executor/internal/lifecycle/lifecycle.go +5 -0
- package/dist/templates/_executor/internal/lifecycle/lifecycle_test.go +61 -3
- package/dist/templates/_executor/internal/taskscript/boot.sh +9 -9
- package/dist/templates/_executor/internal/taskscript/cmd/main.go +2 -2
- package/dist/templates/_executor/internal/taskscript/control.sh +15 -10
- package/dist/templates/_executor/internal/taskscript/tasks.go +5 -3
- package/dist/templates/_executor/lifecycle_test.go +11 -0
- package/dist/templates/_executor/link_linux.go +28 -0
- package/dist/templates/_executor/long_running_test.go +530 -0
- package/dist/templates/_executor/main.go +83 -25
- package/dist/templates/_executor/managed.go +3 -3
- package/dist/templates/_executor/managed_test.go +3 -3
- package/dist/templates/_executor/move_linux.go +490 -0
- package/dist/templates/_executor/move_linux_test.go +460 -0
- package/dist/templates/_executor/move_validation.go +46 -0
- package/dist/templates/_executor/move_validation_test.go +187 -0
- package/dist/templates/_executor/operations.go +926 -0
- package/dist/templates/_executor/path_test.go +18 -0
- package/dist/templates/_executor/pid.go +37 -0
- package/dist/templates/_executor/pid_test.go +113 -0
- package/dist/templates/_executor/platform_linux.go +24 -173
- package/dist/templates/_executor/platform_linux_test.go +9 -65
- package/dist/templates/_executor/platform_other.go +38 -4
- package/dist/templates/_executor/process.go +3 -0
- package/dist/templates/_executor/purge_log.go +18 -0
- package/dist/templates/_executor/records.go +242 -0
- package/dist/templates/_executor/scope_cancel_contract_test.go +91 -0
- package/dist/templates/_executor/scope_client.go +37 -0
- package/dist/templates/_executor/scope_contract.go +12 -0
- package/dist/templates/_executor/selected_scope.go +146 -0
- package/dist/templates/_executor/selected_scope_test.go +186 -0
- package/dist/templates/_executor/status_disabled_test.go +33 -0
- package/dist/templates/_executor/store.go +4 -3
- package/dist/templates/_executor/supervise.go +109 -0
- package/dist/templates/_executor/supervise_test.go +130 -0
- package/dist/templates/_executor/task_race_review_test.go +1 -1
- package/dist/templates/_executor/tasks.go +52 -15
- package/dist/templates/_executor/tasks_dsm71_test.go +114 -0
- package/dist/templates/_executor/tasks_review_test.go +1 -1
- package/dist/templates/_executor/tasks_test.go +62 -5
- package/dist/templates/_executor/upgrade_watch_test.go +13 -5
- package/dist/templates/_executor/watch.go +8 -0
- package/dist/templates/_executor/watch_test.go +23 -2
- package/dist/templates/_executor/write_review_linux_test.go +4 -12
- package/dist/templates/_gateway/go.mod +2 -0
- package/dist/templates/_shared/AGENTS.md +129 -0
- package/dist/templates/binary/dsm-package.yaml +24 -0
- package/dist/templates/binary/i18n/messages/de.json +4 -0
- package/dist/templates/binary/i18n/messages/en.json +4 -0
- package/dist/templates/binary/i18n/messages/es.json +4 -0
- package/dist/templates/binary/i18n/messages/fr.json +4 -0
- package/dist/templates/binary/i18n/messages/it.json +4 -0
- package/dist/templates/binary/i18n/messages/ja.json +4 -0
- package/dist/templates/binary/i18n/messages/ko.json +4 -0
- package/dist/templates/binary/i18n/messages/zh-CN.json +4 -0
- package/dist/templates/binary/i18n/messages/zh-TW.json +4 -0
- package/dist/templates/binary/ui/app.js +19 -4
- package/dist/templates/native-authorization/AuthorizationGate.vue +5 -3
- package/dist/templates/native-authorization/i18n/de.json +1 -0
- package/dist/templates/native-authorization/i18n/en.json +1 -0
- package/dist/templates/native-authorization/i18n/es.json +2 -1
- package/dist/templates/native-authorization/i18n/fr.json +1 -0
- package/dist/templates/native-authorization/i18n/it.json +11 -10
- package/dist/templates/native-authorization/i18n/ja.json +1 -0
- package/dist/templates/native-authorization/i18n/ko.json +10 -9
- package/dist/templates/native-authorization/i18n/zh-CN.json +6 -5
- package/dist/templates/native-authorization/i18n/zh-TW.json +6 -5
- package/dist/templates/native-go/README.md +43 -10
- package/dist/templates/native-go/backend/cmd/app/main.go +27 -7
- package/dist/templates/native-go/backend/go.mod +1 -1
- package/dist/templates/native-go/backend/internal/api/entry_test.go +47 -0
- package/dist/templates/native-go/backend/internal/api/permissions_test.go +3 -3
- package/dist/templates/native-go/backend/internal/api/registry.go +11 -0
- package/dist/templates/native-go/backend/internal/api/sdk-permissions.json +14 -1
- package/dist/templates/native-go/backend/internal/api/server.go +18 -5
- package/dist/templates/native-go/backend/internal/app/delegate_config.go +57 -0
- package/dist/templates/native-go/backend/internal/app/delegate_config_test.go +28 -0
- package/dist/templates/native-go/backend/internal/app/portal.go +30 -0
- package/dist/templates/native-go/backend/internal/app/portal_test.go +55 -0
- package/dist/templates/native-go/backend/internal/app/routes.go +8 -2
- package/dist/templates/native-go/backend/internal/background/runner.go +1 -1
- package/dist/templates/native-go/backend/internal/background/store.go +16 -14
- package/dist/templates/native-go/backend/internal/dsm/admin.go +8 -2
- package/dist/templates/native-go/backend/internal/dsm/admin_linux.go +43 -13
- package/dist/templates/native-go/backend/internal/dsm/admin_linux_test.go +56 -0
- package/dist/templates/native-go/backend/internal/dsm/admin_other.go +4 -1
- package/dist/templates/native-go/backend/internal/dsm/apppriv.go +30 -0
- package/dist/templates/native-go/backend/internal/dsm/bridge_file.go +75 -0
- package/dist/templates/native-go/backend/internal/dsm/bridge_file_test.go +57 -0
- package/dist/templates/native-go/backend/internal/dsm/entry.go +177 -0
- package/dist/templates/native-go/backend/internal/dsm/entry_test.go +315 -0
- package/dist/templates/native-go/backend/internal/dsm/native/admin-armv7.elf +0 -0
- package/dist/templates/native-go/backend/internal/dsm/native/apppriv-aarch64.elf +0 -0
- package/dist/templates/native-go/backend/internal/dsm/native/apppriv-armv7.elf +0 -0
- package/dist/templates/native-go/backend/internal/dsm/native/apppriv-x86_64.elf +0 -0
- package/dist/templates/native-go/backend/internal/dsm/native/apppriv_check.c +33 -0
- package/dist/templates/native-go/backend/internal/dsm/native/build.sh +13 -4
- package/dist/templates/native-go/backend/internal/dsm/native/provenance.json +9 -3
- package/dist/templates/native-go/backend/internal/filestation/check_permission.go +71 -0
- package/dist/templates/native-go/backend/internal/filestation/check_permission_test.go +77 -0
- package/dist/templates/native-go/backend/internal/filestation/client.go +39 -3
- package/dist/templates/native-go/backend/internal/filestation/download_dsm71_test.go +82 -0
- package/dist/templates/native-go/backend/internal/filestation/sdk_policy_test.go +39 -0
- package/dist/templates/native-go/backend/internal/filestation/service.go +1 -1
- package/dist/templates/native-go/backend/internal/identity/README.md +5 -1
- package/dist/templates/native-go/backend/internal/identity/dsm.go +24 -5
- package/dist/templates/native-go/backend/internal/identity/http.go +1 -1
- package/dist/templates/native-go/backend/internal/identity/identity_test.go +48 -1
- package/dist/templates/native-go/backend/internal/identity/service.go +1 -1
- package/dist/templates/native-go/backend/internal/portal/portal.go +138 -0
- package/dist/templates/native-go/backend/internal/portal/portal_test.go +89 -0
- package/dist/templates/native-go/dsm-package.yaml +20 -1
- package/dist/templates/native-go/i18n/glossary.json +2 -1
- package/dist/templates/native-go/i18n/messages/de.json +1 -0
- package/dist/templates/native-go/i18n/messages/en.json +1 -0
- package/dist/templates/native-go/i18n/messages/es.json +1 -0
- package/dist/templates/native-go/i18n/messages/fr.json +1 -0
- package/dist/templates/native-go/i18n/messages/it.json +1 -0
- package/dist/templates/native-go/i18n/messages/ja.json +1 -0
- package/dist/templates/native-go/i18n/messages/ko.json +1 -0
- package/dist/templates/native-go/i18n/messages/zh-CN.json +1 -0
- package/dist/templates/native-go/i18n/messages/zh-TW.json +1 -0
- package/dist/templates/native-go/ui/app.css +10 -0
- package/dist/templates/native-go/ui/app.js +11 -1
- package/dist/templates/native-go-delegate/DELEGATE.md +126 -5
- package/dist/templates/native-go-delegate/backend/cmd/background-worker/main.go +7 -0
- package/dist/templates/native-go-delegate/backend/internal/app/delegate.go +11 -1
- package/dist/templates/native-go-delegate/backend/internal/app/delegate_routes_test.go +14 -0
- package/dist/templates/native-go-delegate/backend/internal/background/delegated_moves.go +270 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/admission_recovery_test.go +410 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/cancel_contract_test.go +95 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/client.go +8 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/destination.go +110 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/destination_state.go +117 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/destination_state_test.go +60 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/destination_test.go +116 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/example.go +81 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/example_test.go +91 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/executor_contract_test.go +511 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/files.go +1 -1
- package/dist/templates/native-go-delegate/backend/internal/delegate/long_running_routes.go +92 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/long_running_routes_test.go +99 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/move.go +348 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/move_test.go +351 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/operations_list.go +65 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/operations_list_test.go +114 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/retry_test.go +1 -1
- package/dist/templates/native-go-delegate/backend/internal/delegate/service.go +58 -17
- package/dist/templates/native-go-delegate/backend/internal/delegate/staging.go +121 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/status_disabled_test.go +51 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/testdata/executor_contract.txt +112 -0
- package/dist/templates/native-go-delegate/backend/internal/delegate/transient_contract_test.go +137 -0
- package/dist/templates/native-go-delegate/backend/internal/filestation/files.go +1 -31
- package/dist/templates/native-go-delegate/frontend/src/CapabilityPanels.vue +30 -3
- package/dist/templates/native-go-delegate/frontend/src/delegate/BackgroundSavePanel.vue +113 -0
- package/dist/templates/native-go-delegate/frontend/src/delegate/copy.ts +5 -6
- package/dist/templates/native-go-delegate/frontend/test/background-save.test.ts +121 -0
- package/dist/templates/native-go-delegate/frontend/test/delegate.test.ts +15 -0
- package/dist/templates/native-go-delegate/frontend/test/scope-settings.test.ts +49 -0
- package/dist/templates/native-go-delegate/test.sh +1 -0
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/de.json +2 -2
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/en.json +2 -2
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/es.json +12 -12
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/fr.json +4 -4
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/it.json +17 -17
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/ja.json +7 -7
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/ko.json +15 -15
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/zh-CN.json +3 -3
- package/dist/templates/native-go-jobs/frontend/src/background/i18n/zh-TW.json +2 -2
- package/dist/templates/native-go-jobs/frontend/test/background.test.ts +25 -28
- package/dist/templates/native-go-root-ops/backend/internal/app/executor.go +30 -2
- package/dist/templates/native-go-root-ops/backend/internal/app/executor_test.go +64 -0
- package/dist/templates/native-go-vue/README.md +4 -0
- package/dist/templates/native-go-vue/frontend/package-lock.json +4 -4
- package/dist/templates/native-go-vue/frontend/package.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/App.vue +18 -13
- package/dist/templates/native-go-vue/frontend/src/context.ts +31 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/ExecutorSettings.vue +54 -9
- package/dist/templates/native-go-vue/frontend/src/delegate/catalogs.ts +11 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/copy.test.ts +12 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/copy.ts +4 -4
- package/dist/templates/native-go-vue/frontend/src/delegate/executor-settings.test.ts +23 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/executor-setup.ts +8 -2
- package/dist/templates/native-go-vue/frontend/src/delegate/facade.test.ts +100 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/facade.ts +85 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/de.json +47 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/en.json +13 -2
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/es.json +47 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/fr.json +47 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/it.json +47 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/ja.json +47 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/ko.json +47 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/de.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/en.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/es.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/fr.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/it.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/ja.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/ko.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-CN.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-TW.json +42 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/zh-CN.json +47 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/i18n/zh-TW.json +16 -5
- package/dist/templates/native-go-vue/frontend/src/delegate/long-running.ts +57 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/save-copy.test.ts +12 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/save-copy.ts +24 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/scoped-picker.test.ts +12 -0
- package/dist/templates/native-go-vue/frontend/src/delegate/scoped-picker.ts +21 -0
- package/dist/templates/native-go-vue/frontend/src/files/files.test.ts +7 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/de.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/en.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/es.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/fr.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/it.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/ja.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/ko.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/zh-CN.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n/zh-TW.json +20 -0
- package/dist/templates/native-go-vue/frontend/src/i18n.ts +13 -0
- package/dist/templates/native-go-vue/frontend/src/identity/LoginPage.vue +16 -14
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/de.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/en.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/es.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/fr.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/it.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/ja.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/ko.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/zh-CN.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n/zh-TW.json +27 -0
- package/dist/templates/native-go-vue/frontend/src/identity/i18n.ts +14 -0
- package/dist/templates/native-go-vue/frontend/src/identity/session.test.ts +4 -0
- package/dist/templates/native-go-vue/frontend/src/identity/session.ts +9 -8
- package/dist/templates/native-go-vue/frontend/src/nas/NasPicker.vue +31 -12
- package/dist/templates/native-go-vue/frontend/src/nas/destination.test.ts +48 -0
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/de.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/en.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/es.json +10 -10
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/fr.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/it.json +12 -12
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/ja.json +15 -15
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/ko.json +12 -12
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/zh-CN.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/nas/i18n/files/zh-TW.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/portal/PortalSettings.vue +39 -0
- package/dist/templates/native-go-vue/frontend/src/shell/i18n/fr.json +1 -1
- package/dist/templates/native-go-vue/frontend/src/shell/i18n/ja.json +1 -1
- package/dist/templates/native-go-vue/frontend/test/apps.test.ts +14 -0
- package/dist/templates/native-go-vue/frontend/test/portal-settings.test.ts +71 -0
- package/dist/templates/native-go-vue/frontend/test/shell-i18n.test.ts +50 -0
- package/package.json +5 -1
- package/schema/package-metadata.schema.json +101 -0
- package/schema/synology-app.schema.json +112 -0
- package/skills/SKILL.md +106 -4
- package/skills/reference/create.md +101 -2
- package/skills/reference/deploy.md +2 -2
- package/skills/reference/files.md +113 -2
- package/skills/reference/identity.md +70 -1
- package/skills/reference/portal.md +17 -0
- package/skills/reference/ui-vue.md +12 -0
- package/templates/_daemon/go.mod +1 -1
- package/templates/_daemon/main.go +6 -3
- package/templates/_daemon/main_test.go +82 -9
- package/templates/_daemon/testdata/child.go +3 -0
- package/templates/_executor/README.md +130 -16
- package/templates/_executor/anchor.go +156 -0
- package/templates/_executor/anchor_test.go +161 -0
- package/templates/_executor/apppriv_review_test.go +1 -1
- package/templates/_executor/cancel_contract_test.go +236 -0
- package/templates/_executor/copy.go +64 -0
- package/templates/_executor/copy_test.go +88 -0
- package/templates/_executor/digest_review_test.go +2 -2
- package/templates/_executor/dsm.go +63 -13
- package/templates/_executor/dsm_test.go +95 -1
- package/templates/_executor/executor.go +260 -49
- package/templates/_executor/executor_test.go +36 -6
- package/templates/_executor/go.mod +2 -0
- package/templates/_executor/identity.go +27 -1
- package/templates/_executor/identity_kernel_linux_test.go +60 -0
- package/templates/_executor/identity_linux.go +82 -0
- package/templates/_executor/identity_security_test.go +43 -0
- package/templates/_executor/internal/lifecycle/lifecycle.go +5 -0
- package/templates/_executor/internal/lifecycle/lifecycle_test.go +61 -3
- package/templates/_executor/internal/taskscript/boot.sh +9 -9
- package/templates/_executor/internal/taskscript/cmd/main.go +2 -2
- package/templates/_executor/internal/taskscript/control.sh +15 -10
- package/templates/_executor/internal/taskscript/tasks.go +5 -3
- package/templates/_executor/lifecycle_test.go +11 -0
- package/templates/_executor/link_linux.go +28 -0
- package/templates/_executor/long_running_test.go +530 -0
- package/templates/_executor/main.go +83 -25
- package/templates/_executor/managed.go +3 -3
- package/templates/_executor/managed_test.go +3 -3
- package/templates/_executor/move_linux.go +490 -0
- package/templates/_executor/move_linux_test.go +460 -0
- package/templates/_executor/move_validation.go +46 -0
- package/templates/_executor/move_validation_test.go +187 -0
- package/templates/_executor/operations.go +926 -0
- package/templates/_executor/path_test.go +18 -0
- package/templates/_executor/pid.go +37 -0
- package/templates/_executor/pid_test.go +113 -0
- package/templates/_executor/platform_linux.go +24 -173
- package/templates/_executor/platform_linux_test.go +9 -65
- package/templates/_executor/platform_other.go +38 -4
- package/templates/_executor/process.go +3 -0
- package/templates/_executor/purge_log.go +18 -0
- package/templates/_executor/records.go +242 -0
- package/templates/_executor/scope_cancel_contract_test.go +91 -0
- package/templates/_executor/scope_client.go +37 -0
- package/templates/_executor/scope_contract.go +12 -0
- package/templates/_executor/selected_scope.go +146 -0
- package/templates/_executor/selected_scope_test.go +186 -0
- package/templates/_executor/status_disabled_test.go +33 -0
- package/templates/_executor/store.go +4 -3
- package/templates/_executor/supervise.go +109 -0
- package/templates/_executor/supervise_test.go +130 -0
- package/templates/_executor/task_race_review_test.go +1 -1
- package/templates/_executor/tasks.go +52 -15
- package/templates/_executor/tasks_dsm71_test.go +114 -0
- package/templates/_executor/tasks_review_test.go +1 -1
- package/templates/_executor/tasks_test.go +62 -5
- package/templates/_executor/upgrade_watch_test.go +13 -5
- package/templates/_executor/watch.go +8 -0
- package/templates/_executor/watch_test.go +23 -2
- package/templates/_executor/write_review_linux_test.go +4 -12
- package/templates/_gateway/go.mod +2 -0
- package/templates/_shared/AGENTS.md +129 -0
- package/templates/binary/dsm-package.yaml +24 -0
- package/templates/binary/i18n/messages/de.json +4 -0
- package/templates/binary/i18n/messages/en.json +4 -0
- package/templates/binary/i18n/messages/es.json +4 -0
- package/templates/binary/i18n/messages/fr.json +4 -0
- package/templates/binary/i18n/messages/it.json +4 -0
- package/templates/binary/i18n/messages/ja.json +4 -0
- package/templates/binary/i18n/messages/ko.json +4 -0
- package/templates/binary/i18n/messages/zh-CN.json +4 -0
- package/templates/binary/i18n/messages/zh-TW.json +4 -0
- package/templates/binary/ui/app.js +19 -4
- package/templates/native-authorization/AuthorizationGate.vue +5 -3
- package/templates/native-authorization/i18n/de.json +1 -0
- package/templates/native-authorization/i18n/en.json +1 -0
- package/templates/native-authorization/i18n/es.json +2 -1
- package/templates/native-authorization/i18n/fr.json +1 -0
- package/templates/native-authorization/i18n/it.json +11 -10
- package/templates/native-authorization/i18n/ja.json +1 -0
- package/templates/native-authorization/i18n/ko.json +10 -9
- package/templates/native-authorization/i18n/zh-CN.json +6 -5
- package/templates/native-authorization/i18n/zh-TW.json +6 -5
- package/templates/native-go/README.md +43 -10
- package/templates/native-go/backend/cmd/app/main.go +27 -7
- package/templates/native-go/backend/go.mod +1 -1
- package/templates/native-go/backend/internal/api/entry_test.go +47 -0
- package/templates/native-go/backend/internal/api/permissions_test.go +3 -3
- package/templates/native-go/backend/internal/api/registry.go +11 -0
- package/templates/native-go/backend/internal/api/sdk-permissions.json +14 -1
- package/templates/native-go/backend/internal/api/server.go +18 -5
- package/templates/native-go/backend/internal/app/delegate_config.go +57 -0
- package/templates/native-go/backend/internal/app/delegate_config_test.go +28 -0
- package/templates/native-go/backend/internal/app/portal.go +30 -0
- package/templates/native-go/backend/internal/app/portal_test.go +55 -0
- package/templates/native-go/backend/internal/app/routes.go +8 -2
- package/templates/native-go/backend/internal/background/runner.go +1 -1
- package/templates/native-go/backend/internal/background/store.go +16 -14
- package/templates/native-go/backend/internal/dsm/admin.go +8 -2
- package/templates/native-go/backend/internal/dsm/admin_linux.go +43 -13
- package/templates/native-go/backend/internal/dsm/admin_linux_test.go +56 -0
- package/templates/native-go/backend/internal/dsm/admin_other.go +4 -1
- package/templates/native-go/backend/internal/dsm/apppriv.go +30 -0
- package/templates/native-go/backend/internal/dsm/bridge_file.go +75 -0
- package/templates/native-go/backend/internal/dsm/bridge_file_test.go +57 -0
- package/templates/native-go/backend/internal/dsm/entry.go +177 -0
- package/templates/native-go/backend/internal/dsm/entry_test.go +315 -0
- package/templates/native-go/backend/internal/dsm/native/admin-armv7.elf +0 -0
- package/templates/native-go/backend/internal/dsm/native/apppriv-aarch64.elf +0 -0
- package/templates/native-go/backend/internal/dsm/native/apppriv-armv7.elf +0 -0
- package/templates/native-go/backend/internal/dsm/native/apppriv-x86_64.elf +0 -0
- package/templates/native-go/backend/internal/dsm/native/apppriv_check.c +33 -0
- package/templates/native-go/backend/internal/dsm/native/build.sh +13 -4
- package/templates/native-go/backend/internal/dsm/native/provenance.json +9 -3
- package/templates/native-go/backend/internal/filestation/check_permission.go +71 -0
- package/templates/native-go/backend/internal/filestation/check_permission_test.go +77 -0
- package/templates/native-go/backend/internal/filestation/client.go +39 -3
- package/templates/native-go/backend/internal/filestation/download_dsm71_test.go +82 -0
- package/templates/native-go/backend/internal/filestation/sdk_policy_test.go +39 -0
- package/templates/native-go/backend/internal/filestation/service.go +1 -1
- package/templates/native-go/backend/internal/identity/README.md +5 -1
- package/templates/native-go/backend/internal/identity/dsm.go +24 -5
- package/templates/native-go/backend/internal/identity/http.go +1 -1
- package/templates/native-go/backend/internal/identity/identity_test.go +48 -1
- package/templates/native-go/backend/internal/identity/service.go +1 -1
- package/templates/native-go/backend/internal/portal/portal.go +138 -0
- package/templates/native-go/backend/internal/portal/portal_test.go +89 -0
- package/templates/native-go/dsm-package.yaml +20 -1
- package/templates/native-go/i18n/glossary.json +2 -1
- package/templates/native-go/i18n/messages/de.json +1 -0
- package/templates/native-go/i18n/messages/en.json +1 -0
- package/templates/native-go/i18n/messages/es.json +1 -0
- package/templates/native-go/i18n/messages/fr.json +1 -0
- package/templates/native-go/i18n/messages/it.json +1 -0
- package/templates/native-go/i18n/messages/ja.json +1 -0
- package/templates/native-go/i18n/messages/ko.json +1 -0
- package/templates/native-go/i18n/messages/zh-CN.json +1 -0
- package/templates/native-go/i18n/messages/zh-TW.json +1 -0
- package/templates/native-go/ui/app.css +10 -0
- package/templates/native-go/ui/app.js +11 -1
- package/templates/native-go-delegate/DELEGATE.md +126 -5
- package/templates/native-go-delegate/backend/cmd/background-worker/main.go +7 -0
- package/templates/native-go-delegate/backend/internal/app/delegate.go +11 -1
- package/templates/native-go-delegate/backend/internal/app/delegate_routes_test.go +14 -0
- package/templates/native-go-delegate/backend/internal/background/delegated_moves.go +270 -0
- package/templates/native-go-delegate/backend/internal/delegate/admission_recovery_test.go +410 -0
- package/templates/native-go-delegate/backend/internal/delegate/cancel_contract_test.go +95 -0
- package/templates/native-go-delegate/backend/internal/delegate/client.go +8 -0
- package/templates/native-go-delegate/backend/internal/delegate/destination.go +110 -0
- package/templates/native-go-delegate/backend/internal/delegate/destination_state.go +117 -0
- package/templates/native-go-delegate/backend/internal/delegate/destination_state_test.go +60 -0
- package/templates/native-go-delegate/backend/internal/delegate/destination_test.go +116 -0
- package/templates/native-go-delegate/backend/internal/delegate/example.go +81 -0
- package/templates/native-go-delegate/backend/internal/delegate/example_test.go +91 -0
- package/templates/native-go-delegate/backend/internal/delegate/executor_contract_test.go +511 -0
- package/templates/native-go-delegate/backend/internal/delegate/files.go +1 -1
- package/templates/native-go-delegate/backend/internal/delegate/long_running_routes.go +92 -0
- package/templates/native-go-delegate/backend/internal/delegate/long_running_routes_test.go +99 -0
- package/templates/native-go-delegate/backend/internal/delegate/move.go +348 -0
- package/templates/native-go-delegate/backend/internal/delegate/move_test.go +351 -0
- package/templates/native-go-delegate/backend/internal/delegate/operations_list.go +65 -0
- package/templates/native-go-delegate/backend/internal/delegate/operations_list_test.go +114 -0
- package/templates/native-go-delegate/backend/internal/delegate/retry_test.go +1 -1
- package/templates/native-go-delegate/backend/internal/delegate/service.go +58 -17
- package/templates/native-go-delegate/backend/internal/delegate/staging.go +121 -0
- package/templates/native-go-delegate/backend/internal/delegate/status_disabled_test.go +51 -0
- package/templates/native-go-delegate/backend/internal/delegate/testdata/executor_contract.txt +112 -0
- package/templates/native-go-delegate/backend/internal/delegate/transient_contract_test.go +137 -0
- package/templates/native-go-delegate/backend/internal/filestation/files.go +1 -31
- package/templates/native-go-delegate/frontend/src/CapabilityPanels.vue +30 -3
- package/templates/native-go-delegate/frontend/src/delegate/BackgroundSavePanel.vue +113 -0
- package/templates/native-go-delegate/frontend/src/delegate/copy.ts +5 -6
- package/templates/native-go-delegate/frontend/test/background-save.test.ts +121 -0
- package/templates/native-go-delegate/frontend/test/delegate.test.ts +15 -0
- package/templates/native-go-delegate/frontend/test/scope-settings.test.ts +49 -0
- package/templates/native-go-delegate/test.sh +1 -0
- package/templates/native-go-jobs/frontend/src/background/i18n/de.json +2 -2
- package/templates/native-go-jobs/frontend/src/background/i18n/en.json +2 -2
- package/templates/native-go-jobs/frontend/src/background/i18n/es.json +12 -12
- package/templates/native-go-jobs/frontend/src/background/i18n/fr.json +4 -4
- package/templates/native-go-jobs/frontend/src/background/i18n/it.json +17 -17
- package/templates/native-go-jobs/frontend/src/background/i18n/ja.json +7 -7
- package/templates/native-go-jobs/frontend/src/background/i18n/ko.json +15 -15
- package/templates/native-go-jobs/frontend/src/background/i18n/zh-CN.json +3 -3
- package/templates/native-go-jobs/frontend/src/background/i18n/zh-TW.json +2 -2
- package/templates/native-go-jobs/frontend/test/background.test.ts +25 -28
- package/templates/native-go-root-ops/backend/internal/app/executor.go +30 -2
- package/templates/native-go-root-ops/backend/internal/app/executor_test.go +64 -0
- package/templates/native-go-vue/README.md +4 -0
- package/templates/native-go-vue/frontend/package-lock.json +4 -4
- package/templates/native-go-vue/frontend/package.json +1 -1
- package/templates/native-go-vue/frontend/src/App.vue +18 -13
- package/templates/native-go-vue/frontend/src/context.ts +31 -0
- package/templates/native-go-vue/frontend/src/delegate/ExecutorSettings.vue +54 -9
- package/templates/native-go-vue/frontend/src/delegate/catalogs.ts +11 -0
- package/templates/native-go-vue/frontend/src/delegate/copy.test.ts +12 -0
- package/templates/native-go-vue/frontend/src/delegate/copy.ts +4 -4
- package/templates/native-go-vue/frontend/src/delegate/executor-settings.test.ts +23 -0
- package/templates/native-go-vue/frontend/src/delegate/executor-setup.ts +8 -2
- package/templates/native-go-vue/frontend/src/delegate/facade.test.ts +100 -0
- package/templates/native-go-vue/frontend/src/delegate/facade.ts +85 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/de.json +47 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/en.json +13 -2
- package/templates/native-go-vue/frontend/src/delegate/i18n/es.json +47 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/fr.json +47 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/it.json +47 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/ja.json +47 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/ko.json +47 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/de.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/en.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/es.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/fr.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/it.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/ja.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/ko.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-CN.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/save/zh-TW.json +42 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/zh-CN.json +47 -0
- package/templates/native-go-vue/frontend/src/delegate/i18n/zh-TW.json +16 -5
- package/templates/native-go-vue/frontend/src/delegate/long-running.ts +57 -0
- package/templates/native-go-vue/frontend/src/delegate/save-copy.test.ts +12 -0
- package/templates/native-go-vue/frontend/src/delegate/save-copy.ts +24 -0
- package/templates/native-go-vue/frontend/src/delegate/scoped-picker.test.ts +12 -0
- package/templates/native-go-vue/frontend/src/delegate/scoped-picker.ts +21 -0
- package/templates/native-go-vue/frontend/src/files/files.test.ts +7 -0
- package/templates/native-go-vue/frontend/src/i18n/de.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/en.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/es.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/fr.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/it.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/ja.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/ko.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/zh-CN.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n/zh-TW.json +20 -0
- package/templates/native-go-vue/frontend/src/i18n.ts +13 -0
- package/templates/native-go-vue/frontend/src/identity/LoginPage.vue +16 -14
- package/templates/native-go-vue/frontend/src/identity/i18n/de.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/en.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/es.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/fr.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/it.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/ja.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/ko.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/zh-CN.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n/zh-TW.json +27 -0
- package/templates/native-go-vue/frontend/src/identity/i18n.ts +14 -0
- package/templates/native-go-vue/frontend/src/identity/session.test.ts +4 -0
- package/templates/native-go-vue/frontend/src/identity/session.ts +9 -8
- package/templates/native-go-vue/frontend/src/nas/NasPicker.vue +31 -12
- package/templates/native-go-vue/frontend/src/nas/destination.test.ts +48 -0
- package/templates/native-go-vue/frontend/src/nas/i18n/files/de.json +1 -1
- package/templates/native-go-vue/frontend/src/nas/i18n/files/en.json +1 -1
- package/templates/native-go-vue/frontend/src/nas/i18n/files/es.json +10 -10
- package/templates/native-go-vue/frontend/src/nas/i18n/files/fr.json +1 -1
- package/templates/native-go-vue/frontend/src/nas/i18n/files/it.json +12 -12
- package/templates/native-go-vue/frontend/src/nas/i18n/files/ja.json +15 -15
- package/templates/native-go-vue/frontend/src/nas/i18n/files/ko.json +12 -12
- package/templates/native-go-vue/frontend/src/nas/i18n/files/zh-CN.json +1 -1
- package/templates/native-go-vue/frontend/src/nas/i18n/files/zh-TW.json +1 -1
- package/templates/native-go-vue/frontend/src/portal/PortalSettings.vue +39 -0
- package/templates/native-go-vue/frontend/src/shell/i18n/fr.json +1 -1
- package/templates/native-go-vue/frontend/src/shell/i18n/ja.json +1 -1
- package/templates/native-go-vue/frontend/test/apps.test.ts +14 -0
- package/templates/native-go-vue/frontend/test/portal-settings.test.ts +71 -0
- package/templates/native-go-vue/frontend/test/shell-i18n.test.ts +50 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"os"
|
|
6
|
+
"path/filepath"
|
|
7
|
+
"strings"
|
|
8
|
+
"testing"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
// dsm71Scheduler answers like DSM 7.1.1-42962 (vt-62): TaskScheduler stops at
|
|
12
|
+
// list v2 (offset/limit) and get v3. t-0234 measured the refusals: a version
|
|
13
|
+
// above maxVersion 3 returns 104; a method absent at an existing version, 103.
|
|
14
|
+
type dsm71Scheduler struct {
|
|
15
|
+
recordingScheduler
|
|
16
|
+
refusal string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
func (s *dsm71Scheduler) Exec(ctx context.Context, path string, args []string) ([]byte, error) {
|
|
20
|
+
api, method, version := schedulerCall(args)
|
|
21
|
+
s.calls = append(s.calls, api+" "+method+" v"+version)
|
|
22
|
+
if api == "SYNO.Core.TaskScheduler" {
|
|
23
|
+
if method == "list" && version == "3" && s.refusal != "" {
|
|
24
|
+
return []byte(`{"success":false,"error":{"code":` + s.refusal + `}}`), nil
|
|
25
|
+
}
|
|
26
|
+
supported := map[string]string{"list": "2", "get": "3", "delete": "2", "run": "2"}
|
|
27
|
+
if supported[method] != version {
|
|
28
|
+
if version > "3" {
|
|
29
|
+
return []byte(`{"success":false,"error":{"code":104}}`), nil
|
|
30
|
+
}
|
|
31
|
+
return []byte(`{"success":false,"error":{"code":103}}`), nil
|
|
32
|
+
}
|
|
33
|
+
if method == "list" && (!contains(args, "offset=0") || !contains(args, "limit=500")) {
|
|
34
|
+
return []byte(`{"success":false,"error":{"code":101}}`), nil
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return s.schedulerFixture.Exec(ctx, path, args)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
func purgeWith(t *testing.T, cmd Command) {
|
|
41
|
+
t.Helper()
|
|
42
|
+
inventory := taskInventory{Package: "TestApp", PolicyDigest: strings.Repeat("b", 64), Tasks: []approvedTask{{Kind: "boot", Name: "TestApp executor boot", ScriptDigest: canonicalTaskDigest(t, "boot")}, {Kind: "control", Name: "TestApp executor control", ScriptDigest: canonicalTaskDigest(t, "control")}}}
|
|
43
|
+
state := filepath.Join(t.TempDir(), "state")
|
|
44
|
+
socket := filepath.Join(t.TempDir(), "socket")
|
|
45
|
+
os.MkdirAll(filepath.Join(state, "runtime"), 0700)
|
|
46
|
+
os.MkdirAll(socket, 0700)
|
|
47
|
+
if err := purgeWithInventory(context.Background(), &liveDSM{Command: cmd}, "TestApp", inventory, state, filepath.Join(state, "runtime"), socket, func(string) {}); err != nil {
|
|
48
|
+
t.Fatal(err)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
func TestPurgeFindsAndDeletesBothTasksOnDSM71(t *testing.T) {
|
|
53
|
+
cmd := &dsm71Scheduler{}
|
|
54
|
+
purgeWith(t, cmd)
|
|
55
|
+
if strings.Join(cmd.deleted, ",") != "SYNO.Core.EventScheduler,SYNO.Core.TaskScheduler" {
|
|
56
|
+
t.Fatal("DSM 7.1 tasks left behind", cmd.deleted, cmd.calls)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
func TestSchedulerReadFallsBackOnlyOnUnsupportedVersion(t *testing.T) {
|
|
61
|
+
for _, code := range []string{"105", "119", "102", "3121"} {
|
|
62
|
+
t.Run(code, func(t *testing.T) {
|
|
63
|
+
cmd := &dsm71Scheduler{refusal: code}
|
|
64
|
+
purgeWith(t, cmd)
|
|
65
|
+
for _, call := range cmd.calls {
|
|
66
|
+
if call == "SYNO.Core.TaskScheduler list v2" || call == "SYNO.Core.TaskScheduler get v3" {
|
|
67
|
+
t.Fatal("fell back after code", code, cmd.calls)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if contains(cmd.deleted, "SYNO.Core.TaskScheduler") {
|
|
71
|
+
t.Fatal("deleted without exact readback", cmd.deleted)
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
func TestModernSchedulerNeverUsesLegacyVersions(t *testing.T) {
|
|
78
|
+
cmd := &recordingScheduler{}
|
|
79
|
+
purgeWith(t, cmd)
|
|
80
|
+
for _, call := range cmd.calls {
|
|
81
|
+
if call == "SYNO.Core.TaskScheduler list v2" || call == "SYNO.Core.TaskScheduler get v3" {
|
|
82
|
+
t.Fatal("modern DSM used a legacy version", cmd.calls)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if len(cmd.deleted) != 2 {
|
|
86
|
+
t.Fatal(cmd.deleted)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
type recordingScheduler struct {
|
|
91
|
+
schedulerFixture
|
|
92
|
+
calls []string
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
func (s *recordingScheduler) Exec(ctx context.Context, path string, args []string) ([]byte, error) {
|
|
96
|
+
api, method, version := schedulerCall(args)
|
|
97
|
+
s.calls = append(s.calls, api+" "+method+" v"+version)
|
|
98
|
+
return s.schedulerFixture.Exec(ctx, path, args)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
func schedulerCall(args []string) (api, method, version string) {
|
|
102
|
+
for _, a := range args {
|
|
103
|
+
k, v, _ := strings.Cut(a, "=")
|
|
104
|
+
switch k {
|
|
105
|
+
case "api":
|
|
106
|
+
api = v
|
|
107
|
+
case "method":
|
|
108
|
+
method = v
|
|
109
|
+
case "version":
|
|
110
|
+
version = v
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return
|
|
114
|
+
}
|
|
@@ -35,7 +35,7 @@ func TestReviewSnapshotRejectsUnrelatedSameNamedRootTasks(t *testing.T) {
|
|
|
35
35
|
func TestReviewPurgeRejectsUnrelatedSameNamedRootTasks(t *testing.T) {
|
|
36
36
|
script := "#!/bin/sh\n# synopkgland executor boot\n# " + strings.Repeat("a", 64) + strings.Repeat("b", 64) + "\necho unrelated-backup-task\n"
|
|
37
37
|
cmd := &schedulerFixture{script: script}
|
|
38
|
-
inv := taskInventory{Package: "TestApp",
|
|
38
|
+
inv := taskInventory{Package: "TestApp", PolicyDigest: strings.Repeat("b", 64), Tasks: []approvedTask{{Kind: "boot", Name: "TestApp executor boot", ScriptDigest: hashBytes([]byte(script))}, {Kind: "control", Name: "TestApp executor control", ScriptDigest: hashBytes([]byte(script))}}}
|
|
39
39
|
purgeTasks(context.Background(), &liveDSM{Command: cmd}, "TestApp", inv, func(string) {})
|
|
40
40
|
if len(cmd.deleted) != 0 {
|
|
41
41
|
t.Fatal("deleted unrelated tasks", cmd.deleted)
|
|
@@ -6,6 +6,7 @@ import (
|
|
|
6
6
|
"errors"
|
|
7
7
|
"os"
|
|
8
8
|
"path/filepath"
|
|
9
|
+
"regexp"
|
|
9
10
|
"strings"
|
|
10
11
|
"synopkgland/executor/internal/taskscript"
|
|
11
12
|
"testing"
|
|
@@ -14,7 +15,9 @@ import (
|
|
|
14
15
|
type schedulerFixture struct {
|
|
15
16
|
changed, foreignOwner, duplicate bool
|
|
16
17
|
script string
|
|
17
|
-
|
|
18
|
+
// deleteReply replaces the delete envelope, as DSM sends it.
|
|
19
|
+
deleteReply string
|
|
20
|
+
deleted []string
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
func (s *schedulerFixture) Exec(_ context.Context, _ string, args []string) ([]byte, error) {
|
|
@@ -31,7 +34,7 @@ func (s *schedulerFixture) Exec(_ context.Context, _ string, args []string) ([]b
|
|
|
31
34
|
if s.foreignOwner {
|
|
32
35
|
owner = "other"
|
|
33
36
|
}
|
|
34
|
-
generated, _ := taskscript.Generate("TestApp", strings.Repeat("
|
|
37
|
+
generated, _ := taskscript.Generate("TestApp", strings.Repeat("b", 64))
|
|
35
38
|
script := generated[1].Script
|
|
36
39
|
if api == "SYNO.Core.EventScheduler" {
|
|
37
40
|
script = generated[0].Script
|
|
@@ -48,6 +51,9 @@ func (s *schedulerFixture) Exec(_ context.Context, _ string, args []string) ([]b
|
|
|
48
51
|
if api == "SYNO.Core.TaskScheduler" && !contains(args, `tasks=[{"id":7,"real_owner":"root"}]`) {
|
|
49
52
|
return nil, errors.New("wrong delete reference")
|
|
50
53
|
}
|
|
54
|
+
if s.deleteReply != "" {
|
|
55
|
+
return []byte(s.deleteReply), nil
|
|
56
|
+
}
|
|
51
57
|
data = map[string]any{}
|
|
52
58
|
} else if api == "SYNO.Core.EventScheduler" {
|
|
53
59
|
data = map[string]any{"task_name": "TestApp executor boot", "owner": map[string]string{"0": owner}, "operation": script, "operation_type": "script", "event": "bootup", "enable": true}
|
|
@@ -66,7 +72,7 @@ func TestPurgeDeletesOnlyExactOwnRootTasksAndProtectedState(t *testing.T) {
|
|
|
66
72
|
for _, mode := range []string{"exact", "script changed", "owner changed", "duplicate control", "foreign name"} {
|
|
67
73
|
t.Run(mode, func(t *testing.T) {
|
|
68
74
|
cmd := &schedulerFixture{changed: mode == "script changed", foreignOwner: mode == "owner changed", duplicate: mode == "duplicate control"}
|
|
69
|
-
inventory := taskInventory{Package: "TestApp",
|
|
75
|
+
inventory := taskInventory{Package: "TestApp", PolicyDigest: strings.Repeat("b", 64), Tasks: []approvedTask{{Kind: "boot", Name: "TestApp executor boot", ScriptDigest: canonicalTaskDigest(t, "boot")}, {Kind: "control", Name: "TestApp executor control", ScriptDigest: canonicalTaskDigest(t, "control")}}}
|
|
70
76
|
if mode == "foreign name" {
|
|
71
77
|
inventory.Tasks[0].Name = "OtherApp executor boot"
|
|
72
78
|
}
|
|
@@ -101,7 +107,7 @@ func TestSnapshotRequiresBothExactSchedulerDefinitionsBeforeWritingInventory(t *
|
|
|
101
107
|
ed := strings.Repeat("a", 64)
|
|
102
108
|
pd := strings.Repeat("b", 64)
|
|
103
109
|
tasks := []map[string]string{}
|
|
104
|
-
generated, err := taskscript.Generate("TestApp",
|
|
110
|
+
generated, err := taskscript.Generate("TestApp", pd)
|
|
105
111
|
if err != nil {
|
|
106
112
|
t.Fatal(err)
|
|
107
113
|
}
|
|
@@ -152,7 +158,7 @@ func (s *snapshotFixture) Exec(ctx context.Context, path string, args []string)
|
|
|
152
158
|
|
|
153
159
|
func canonicalTaskDigest(t *testing.T, kind string) string {
|
|
154
160
|
t.Helper()
|
|
155
|
-
tasks, err := taskscript.Generate("TestApp", strings.Repeat("
|
|
161
|
+
tasks, err := taskscript.Generate("TestApp", strings.Repeat("b", 64))
|
|
156
162
|
if err != nil {
|
|
157
163
|
t.Fatal(err)
|
|
158
164
|
}
|
|
@@ -164,3 +170,54 @@ func canonicalTaskDigest(t *testing.T, kind string) string {
|
|
|
164
170
|
t.Fatal("task kind")
|
|
165
171
|
return ""
|
|
166
172
|
}
|
|
173
|
+
|
|
174
|
+
// t-0229: preuninst took 15-23 s; time each scheduler phase and the file
|
|
175
|
+
// removal separately, naming the package, so a device log shows which waits.
|
|
176
|
+
func TestPurgeLogsPhaseTimingWithPackageName(t *testing.T) {
|
|
177
|
+
cmd := &schedulerFixture{}
|
|
178
|
+
inventory := taskInventory{Package: "TestApp", PolicyDigest: strings.Repeat("b", 64), Tasks: []approvedTask{{Kind: "boot", Name: "TestApp executor boot", ScriptDigest: canonicalTaskDigest(t, "boot")}, {Kind: "control", Name: "TestApp executor control", ScriptDigest: canonicalTaskDigest(t, "control")}}}
|
|
179
|
+
state := filepath.Join(t.TempDir(), "state")
|
|
180
|
+
socket := filepath.Join(t.TempDir(), "socket")
|
|
181
|
+
os.MkdirAll(filepath.Join(state, "runtime"), 0700)
|
|
182
|
+
os.MkdirAll(socket, 0700)
|
|
183
|
+
logs := []string{}
|
|
184
|
+
if err := purgeWithInventory(context.Background(), &liveDSM{Command: cmd}, "TestApp", inventory, state, filepath.Join(state, "runtime"), socket, func(s string) { logs = append(logs, s) }); err != nil {
|
|
185
|
+
t.Fatal(err)
|
|
186
|
+
}
|
|
187
|
+
task := regexp.MustCompile(`^task cleanup timing: package=TestApp kind=(boot|control) lookup_ms=\d+ delete_ms=\d+ verify_ms=\d+$`)
|
|
188
|
+
total := regexp.MustCompile(`^purge timing: package=TestApp tasks_ms=\d+ files_ms=\d+$`)
|
|
189
|
+
kinds := []string{}
|
|
190
|
+
for _, line := range logs {
|
|
191
|
+
if m := task.FindStringSubmatch(line); m != nil {
|
|
192
|
+
kinds = append(kinds, m[1])
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if strings.Join(kinds, ",") != "boot,control" || len(logs) == 0 || !total.MatchString(logs[len(logs)-1]) {
|
|
196
|
+
t.Fatal(logs)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// t-0237: EventScheduler delete v1 and TaskScheduler delete v2 answer a success
|
|
201
|
+
// without data; that is a confirmed delete, while a refusal stays unconfirmed.
|
|
202
|
+
func TestPurgeConfirmsDatalessDeleteSuccess(t *testing.T) {
|
|
203
|
+
for reply, unconfirmed := range map[string]bool{
|
|
204
|
+
`{"success":true}`: false,
|
|
205
|
+
`{"httpd_restart":false,"success":true}`: false,
|
|
206
|
+
`{"success":false,"error":{"code":4800}}`: true,
|
|
207
|
+
`{"success":true,"error":{"code":4800}}`: true,
|
|
208
|
+
} {
|
|
209
|
+
cmd := &schedulerFixture{deleteReply: reply}
|
|
210
|
+
inventory := taskInventory{Package: "TestApp", PolicyDigest: strings.Repeat("b", 64), Tasks: []approvedTask{{Kind: "boot", Name: "TestApp executor boot", ScriptDigest: canonicalTaskDigest(t, "boot")}, {Kind: "control", Name: "TestApp executor control", ScriptDigest: canonicalTaskDigest(t, "control")}}}
|
|
211
|
+
logs := []string{}
|
|
212
|
+
purgeTasks(context.Background(), &liveDSM{Command: cmd}, "TestApp", inventory, func(s string) { logs = append(logs, s) })
|
|
213
|
+
found := 0
|
|
214
|
+
for _, line := range logs {
|
|
215
|
+
if strings.HasPrefix(line, "task cleanup unconfirmed: ") {
|
|
216
|
+
found++
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (found == 2) != unconfirmed || (found != 0 && found != 2) || len(cmd.deleted) != 2 {
|
|
220
|
+
t.Fatal(reply, logs)
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
@@ -2,6 +2,7 @@ package main
|
|
|
2
2
|
|
|
3
3
|
import (
|
|
4
4
|
"context"
|
|
5
|
+
"errors"
|
|
5
6
|
"net"
|
|
6
7
|
"os"
|
|
7
8
|
"path/filepath"
|
|
@@ -70,13 +71,20 @@ func TestUpgradeGapPreservesRuntimeAndResumesOnlyApprovedPins(t *testing.T) {
|
|
|
70
71
|
}
|
|
71
72
|
opened.Add(1)
|
|
72
73
|
return func() { listener.Close(); closed.Add(1) }, nil
|
|
73
|
-
}, func(ctx context.Context) bool {
|
|
74
|
+
}, func(ctx context.Context) bool {
|
|
75
|
+
// The production decision: only differing pins ask for approval.
|
|
76
|
+
pins := packagePins(ctx, target, info, func(os.FileInfo) bool { return true }, ed, pd)
|
|
77
|
+
return approvedPins(pins, func() error { return errors.New("no anchored upgrade here") }, func() error { return nil }, func(message string) {
|
|
78
|
+
if strings.Contains(message, "administrator approval") {
|
|
79
|
+
select {
|
|
80
|
+
case approval <- struct{}{}:
|
|
81
|
+
default:
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
}, func() error {
|
|
74
86
|
purged.Add(1)
|
|
75
87
|
return finishControl(state, filepath.Join(state, "runtime"), sockDir, true)
|
|
76
|
-
}, func(message string) {
|
|
77
|
-
if strings.Contains(message, "administrator approval") {
|
|
78
|
-
approval <- struct{}{}
|
|
79
|
-
}
|
|
80
88
|
})
|
|
81
89
|
}()
|
|
82
90
|
t.Cleanup(func() {
|
|
@@ -32,6 +32,14 @@ func newLifecycleMonitor(pkg, packageDir, control string, log func(string)) *lif
|
|
|
32
32
|
return m
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
// A supervisor restart carries no new approval, so a stop already in the
|
|
36
|
+
// mailbox stays in force.
|
|
37
|
+
func newRevivedLifecycleMonitor(pkg, packageDir, control string, log func(string)) *lifecycleMonitor {
|
|
38
|
+
m := newLifecycleMonitor(pkg, packageDir, control, log)
|
|
39
|
+
m.initialStop = nil
|
|
40
|
+
return m
|
|
41
|
+
}
|
|
42
|
+
|
|
35
43
|
// DSM's var link is expected. Resolve its parent, then reject final symlinks,
|
|
36
44
|
// FIFOs and oversized input. Linux openRegular pins all resolved components.
|
|
37
45
|
func readLifecycleFile(path string, limit int) ([]byte, os.FileInfo, error) {
|
|
@@ -209,7 +209,8 @@ func TestLifecycleWatchIgnoresInvalidControlAndResumesAfterOldStop(t *testing.T)
|
|
|
209
209
|
os.WriteFile(control, []byte("stop\n"), 0600)
|
|
210
210
|
var mu sync.Mutex
|
|
211
211
|
logs := 0
|
|
212
|
-
|
|
212
|
+
observed := make(chan struct{}, 32)
|
|
213
|
+
monitor := newLifecycleMonitor("TestApp", pkg, control, func(string) { mu.Lock(); logs++; mu.Unlock(); observed <- struct{}{} })
|
|
213
214
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
|
214
215
|
defer cancel()
|
|
215
216
|
result := make(chan string, 1)
|
|
@@ -225,7 +226,13 @@ func TestLifecycleWatchIgnoresInvalidControlAndResumesAfterOldStop(t *testing.T)
|
|
|
225
226
|
checkRunning()
|
|
226
227
|
for _, value := range []string{"STOP", " purge", "purge\n\n", "purge;id", "wrong"} {
|
|
227
228
|
os.WriteFile(control, []byte(value), 0600)
|
|
228
|
-
|
|
229
|
+
select {
|
|
230
|
+
case <-observed:
|
|
231
|
+
case got := <-result:
|
|
232
|
+
t.Fatalf("unexpected action %q", got)
|
|
233
|
+
case <-ctx.Done():
|
|
234
|
+
t.Fatal("invalid request not observed")
|
|
235
|
+
}
|
|
229
236
|
}
|
|
230
237
|
mu.Lock()
|
|
231
238
|
count := logs
|
|
@@ -268,3 +275,17 @@ func TestLifecycleMonitorReadsStartAfterStopAndKeepsCheckingPurge(t *testing.T)
|
|
|
268
275
|
}
|
|
269
276
|
}
|
|
270
277
|
}
|
|
278
|
+
|
|
279
|
+
// A supervisor restart is not a new administrator approval: the stop already in
|
|
280
|
+
// the mailbox keeps the revived monitor paused.
|
|
281
|
+
func TestRevivedMonitorHonorsStopAlreadyInMailbox(t *testing.T) {
|
|
282
|
+
pkg := t.TempDir()
|
|
283
|
+
os.WriteFile(filepath.Join(pkg, "INFO"), []byte("package=\"TestApp\"\n"), 0600)
|
|
284
|
+
control := filepath.Join(pkg, "control")
|
|
285
|
+
os.WriteFile(control, []byte("stop\n"), 0600)
|
|
286
|
+
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
|
287
|
+
defer cancel()
|
|
288
|
+
if got := newRevivedLifecycleMonitor("TestApp", pkg, control, func(string) {}).watch(ctx, time.Millisecond); got != "stop" || ctx.Err() != nil {
|
|
289
|
+
t.Fatal("revived monitor ignored stop", got, ctx.Err())
|
|
290
|
+
}
|
|
291
|
+
}
|
|
@@ -11,15 +11,6 @@ import (
|
|
|
11
11
|
"time"
|
|
12
12
|
)
|
|
13
13
|
|
|
14
|
-
func TestReviewCopyChild(t *testing.T) {
|
|
15
|
-
if os.Getenv("P2_REVIEW_COPY_CHILD") != "1" {
|
|
16
|
-
t.Skip("child only")
|
|
17
|
-
}
|
|
18
|
-
if err := runWriteChild(os.Getenv("P2_REVIEW_CLEANUP_CHILD") == "1"); err != nil {
|
|
19
|
-
os.Exit(2)
|
|
20
|
-
}
|
|
21
|
-
os.Exit(0)
|
|
22
|
-
}
|
|
23
14
|
func TestReviewCanceledWriteDoesNotLeavePartialDestination(t *testing.T) {
|
|
24
15
|
if os.Geteuid() != 0 {
|
|
25
16
|
t.Skip("requires disposable local Linux root runner")
|
|
@@ -39,7 +30,7 @@ func TestReviewCanceledWriteDoesNotLeavePartialDestination(t *testing.T) {
|
|
|
39
30
|
if err != nil {
|
|
40
31
|
t.Fatal(err)
|
|
41
32
|
}
|
|
42
|
-
if err = src.Truncate(
|
|
33
|
+
if err = src.Truncate(8 << 30); err != nil {
|
|
43
34
|
src.Close()
|
|
44
35
|
t.Skip(err)
|
|
45
36
|
}
|
|
@@ -49,7 +40,7 @@ func TestReviewCanceledWriteDoesNotLeavePartialDestination(t *testing.T) {
|
|
|
49
40
|
t.Fatal(err)
|
|
50
41
|
}
|
|
51
42
|
launcher := filepath.Join(base, "child")
|
|
52
|
-
body := "#!/bin/sh\nexport
|
|
43
|
+
body := "#!/bin/sh\nexport W3_MOVE_CHILD=\"$1\"\nexec " + strconv.Quote(binary) + " -test.run=^TestMoveChild$ 2>" + strconv.Quote(filepath.Join(base, "error")) + "\n"
|
|
53
44
|
os.WriteFile(launcher, []byte(body), 0700)
|
|
54
45
|
ctx, cancel := context.WithCancel(context.Background())
|
|
55
46
|
defer cancel()
|
|
@@ -74,7 +65,8 @@ func TestReviewCanceledWriteDoesNotLeavePartialDestination(t *testing.T) {
|
|
|
74
65
|
}
|
|
75
66
|
select {
|
|
76
67
|
case err := <-done:
|
|
77
|
-
|
|
68
|
+
b, _ := os.ReadFile(filepath.Join(base, "error"))
|
|
69
|
+
t.Fatalf("child ended before write: %v %s", err, b)
|
|
78
70
|
case <-deadline:
|
|
79
71
|
t.Fatal("write did not start")
|
|
80
72
|
default:
|
|
@@ -15,3 +15,132 @@ From the project root, run `synopkgland check --json`,
|
|
|
15
15
|
`synopkgland build --json`, then `synopkgland inspect <spk> --json` on the emitted SPK.
|
|
16
16
|
For Vue, first run `npm ci`, `npm test` and `npm run build` in frontend.
|
|
17
17
|
Do not connect to or change a NAS without explicit task authorization.
|
|
18
|
+
|
|
19
|
+
## Who may use the app (`entry`)
|
|
20
|
+
|
|
21
|
+
Omit `entry` to keep legacy access. `entry: admin-only` admits DSM administrators
|
|
22
|
+
only. `entry: app-privilege` also admits accounts that Control Panel >
|
|
23
|
+
Application Privileges allows for `SYNO.SDS.<package>.Instance`; DSM's install
|
|
24
|
+
default allows administrators only, so nobody else enters until an admin grants
|
|
25
|
+
access. One CGI check covers every route; failures refuse; changes apply within
|
|
26
|
+
30 seconds. Never re-implement AppPriv rules in the App.
|
|
27
|
+
Mark routes ordinary users call `authenticated` in permissions.json, keep whole
|
|
28
|
+
admin routes at the default, guard global settings inside shared routes with
|
|
29
|
+
`api.RequireAdmin(caller)`, and hide admin controls with `ctx.user?.isAdmin`
|
|
30
|
+
(UI only, never the authority). Example: users read the greeting; only admins
|
|
31
|
+
call `greeting.set`.
|
|
32
|
+
|
|
33
|
+
## DSM Application Portal (`portal`)
|
|
34
|
+
|
|
35
|
+
`synopkgland add portal` (or `portal: {}` / `portal: {alias: my-app}` in
|
|
36
|
+
dsm-package.yaml; Compose: `integration.web.portal` for a DSM-window app behind
|
|
37
|
+
the auth gateway) registers `https://<nas>/<alias>/`, which opens the app after
|
|
38
|
+
DSM sign-in. Read `synopkgland skill show portal` before changing it.
|
|
39
|
+
The install wizard only proposes the alias; an administrator activates it from
|
|
40
|
+
the app's portal panel (`ctx.portal`, DSM's own `SYNO.Core.AppPortal` in the
|
|
41
|
+
admin's session) or Control Panel > Login Portal > Applications. Ordinary users
|
|
42
|
+
get the link from the backend's read-only `portal.status`, else "ask an
|
|
43
|
+
administrator". Never write `AppPortal.json` or `@appconf/<package>`, never add
|
|
44
|
+
a backend route that sets the alias, and never relay QuickConnect responses or
|
|
45
|
+
build QuickConnect links. A portal needs os_min_ver 7.3.2-86009 or later (DSM
|
|
46
|
+
7.1.1 refuses it with error 320; 7.2 is untested) and `add portal` raises it;
|
|
47
|
+
beyond that, support is detected (SYNO.API.Info), not version-gated.
|
|
48
|
+
|
|
49
|
+
## Permanent destination integration
|
|
50
|
+
|
|
51
|
+
`init --with delegate` / `add delegate` default to `operations: [files.moveFromStaging]`,
|
|
52
|
+
`destinations: [save]`, `lifetime: until-revoked`, `scope: install-selected`. Existing legacy
|
|
53
|
+
TTL declarations retain their 1–3600 second service / 30-day wire ceiling and
|
|
54
|
+
64 MiB / 60-second URL example. Do not apply those limits to the new move API.
|
|
55
|
+
Delegate can coexist with daemon; ordinary standalone jobs cannot. Preserve
|
|
56
|
+
App business route floors. Binary/compose remain unsupported.
|
|
57
|
+
|
|
58
|
+
Use File Station `/home[/...]`, never `/homes/<user>`. The SDK destination picker
|
|
59
|
+
selection itself grants access after fresh DSM session/UID/write verification,
|
|
60
|
+
without a second consent dialog. Ordinary and administrator subjects use their
|
|
61
|
+
own nonzero UID/current groups, never root. An online App can create an in-scope
|
|
62
|
+
grant using a valid session; there is no trusted external consent or notification.
|
|
63
|
+
|
|
64
|
+
Use the default `createBackgroundSaveFacade(ctx)` / CapabilityPanels management
|
|
65
|
+
page. `delegate.status` exposes verified `disabled` and manifest mode; missing
|
|
66
|
+
protected evidence must not imply enabled. `delegate.operations.list` accepts
|
|
67
|
+
only `{}`, uses the backend move mirrors, and returns the caller's username+UID
|
|
68
|
+
operations only, including for admins. Mirrors are not completion receipts:
|
|
69
|
+
query original `delegate.operations.get` and show Saved only for committed with
|
|
70
|
+
a receipt. Cancel by the same reference; revoke by grant ID. Never resubmit
|
|
71
|
+
uncertain/interrupted work. Admin disable is protected and revokes grants;
|
|
72
|
+
enable/mailbox start does not resurrect them. Keep IDs, never session credentials.
|
|
73
|
+
|
|
74
|
+
App-owned daemon completion and scheduled CSV export call configured Go
|
|
75
|
+
`Service.MoveFromStaging` with `delegation_id`, stable `job_id`, private relative
|
|
76
|
+
`staging`, `name`, `size`. No owner/UID selector. Bounds: 16 GiB/file, queued16,
|
|
77
|
+
active1/package, 24-hour attempt, 5-second revalidation, 10 MiB operation records,
|
|
78
|
+
50 MiB audit. Scope is a usage restriction, not hard subtree confinement.
|
|
79
|
+
Local production-executor fixtures use fake DSM/peer/bulk writer; do not claim
|
|
80
|
+
NAS ACL, actual writer UID, logout/reboot or full lifecycle acceptance from them.
|
|
81
|
+
Gopeed product wiring remains a separate task.
|
|
82
|
+
|
|
83
|
+
Admission recovery (per job): on `EXECUTOR_UNAVAILABLE`, `EXECUTOR_TIMEOUT`,
|
|
84
|
+
`EXECUTOR_PROTOCOL`, `canceled`, `EXECUTOR_PAUSED`, `queue-full`,
|
|
85
|
+
`STORAGE_ERROR`, `ADMISSION_PENDING`, `jobs_busy` or `jobs_unavailable` (the
|
|
86
|
+
package journal was busy or failed transiently; a caller deadline or cancel
|
|
87
|
+
spent waiting for it is `canceled`), call `MoveFromStaging` again later with
|
|
88
|
+
the same exact params. It queries the original reference first and re-sends
|
|
89
|
+
admission only when the executor does not know it and the pinned source is
|
|
90
|
+
unchanged; executor tuple deduplication keeps one operation, so a lost reply or a
|
|
91
|
+
racing caller never copies twice. At most 10 possibly-delivered sends, 2 s
|
|
92
|
+
backoff doubling to 5 min; the worker sweep does the same. Terminal, do not
|
|
93
|
+
retry: `APP_DENIED`, `DELEGATION_DENIED`, `operation-conflict`, `disabled`,
|
|
94
|
+
`SCOPE_DENIED` and other executor refusals, `STAGING_CHANGED`,
|
|
95
|
+
`ADMISSION_EXHAUSTED`, `spool_unsafe` and `journal_corrupt` (repair the package
|
|
96
|
+
spool first), and `operation-not-found` for an accepted operation.
|
|
97
|
+
Never change job/grant IDs, delete mirrors or call the socket directly to retry.
|
|
98
|
+
|
|
99
|
+
Cancellation (per job): `CancelOperation` / `delegate.operations.cancel` with the
|
|
100
|
+
original ref is idempotent; repeat it with the same ref after any retryable
|
|
101
|
+
error or a lost reply. A reply `queued`→`canceled` is final at once. A copy in
|
|
102
|
+
flight answers `copying` with code `CANCEL_REQUESTED`: the cancel is accepted and
|
|
103
|
+
durable, not finished; poll `OperationStatus` on the same ref until terminal
|
|
104
|
+
(repeating the cancel is harmless). `canceled` (`OPERATION_CANCELED`) guarantees the writer
|
|
105
|
+
stopped, its part file is removed, nothing was published and staging is kept; it
|
|
106
|
+
stays canceled across executor crash, package stop/start and logout. `committed`
|
|
107
|
+
means publication won the race: the file stays (cancel never removes it) and only
|
|
108
|
+
the app record may be dropped. `uncertain` means a publish attempt failed before
|
|
109
|
+
the cancel; keep querying. A cancel of a ref the executor has not admitted yet
|
|
110
|
+
(reserved/sent mirror) returns `canceled` and leaves a tombstone, so a late or
|
|
111
|
+
recovered admission of that ref returns `canceled` and never copies; a producer
|
|
112
|
+
cancel is also written to the mirror first, so `MoveFromStaging` and the worker
|
|
113
|
+
sweep forward the cancel instead of admitting it.
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
### Install-selected scope and the destination API
|
|
117
|
+
|
|
118
|
+
- The DSM install wizard dynamically lists local shares (`SYNO.Core.Share list`
|
|
119
|
+
via `api_store`) and offers home. It saves only a package-owned pre-selection
|
|
120
|
+
in `var/delegate-install.json`; never trust that file for authority.
|
|
121
|
+
- The existing administrator PasswordConfirm form displays this pre-selection
|
|
122
|
+
at first enable. `ctx.executor.authorize(password, selectedScope)` confirms it
|
|
123
|
+
through a pinned, exact-readback one-time root task. Settings changes use the
|
|
124
|
+
same form/password path; no App CGI route may set protected scope directly.
|
|
125
|
+
- The executor trusts `/usr/local/etc/synopkgland/<pkg>/delegations/selected-scope.record`
|
|
126
|
+
only. Its scope/generation are runtime protected state; shipped policy pins
|
|
127
|
+
lock the selection mode and operations. Changes revoke old grants and cancel
|
|
128
|
+
pending writes. Change-away-and-back never revives an old grant.
|
|
129
|
+
- Follow `selection` from verified `delegate.status` / `sdk.destination(key)`.
|
|
130
|
+
If the draft differs, display the difference and follow the protected value.
|
|
131
|
+
Home and fixed `shared:<name>` manifests stay compatible.
|
|
132
|
+
- Frontend: `const sdk = createBackgroundSaveFacade(ctx); const current = await
|
|
133
|
+
sdk.destination('save')` returns typed `{key, selection, destination, status}`.
|
|
134
|
+
`selection` contains `{scope, root, generation}`; `destination` is this caller's
|
|
135
|
+
grant or null. Handle active/missing/reselection-required/needs-scope-confirmation/disabled.
|
|
136
|
+
- Go: `Service.Destination(ctx, caller, request, key)` verifies the fresh DSM
|
|
137
|
+
session and username+UID. Capture its active grant ID into the App job. The
|
|
138
|
+
offline producer uses existing `Service.MoveFromStaging`; no user/UID selector,
|
|
139
|
+
cookie, token, or browser path cache. Executor revalidates at use/publication.
|
|
140
|
+
- The generated Background saves page includes a working **Save example file**
|
|
141
|
+
(`sdk.exportExample({key, job_id})`, `delegate.example.export`). Go
|
|
142
|
+
`ExportExample` creates a private JSON file, calls `MoveFromStaging` once, and
|
|
143
|
+
repeats the original request on repeated IDs. Review `example.go` to
|
|
144
|
+
adapt a real producer; show Saved only from a protected committed receipt.
|
|
145
|
+
- Wizard support is measured on vt-nas DSM 7.4 via a session-only SSH local
|
|
146
|
+
forward. This is not proof of other DSM releases or full writer/reboot behavior.
|
|
@@ -6,7 +6,27 @@ build: 1
|
|
|
6
6
|
displayname: __DISPLAY_NAME__
|
|
7
7
|
description: A DSM package with a prebuilt binary CGI and DSM window UI.
|
|
8
8
|
maintainer: Your Name
|
|
9
|
+
# Optional INFO/website metadata. Omit fields you do not need.
|
|
10
|
+
# metadata:
|
|
11
|
+
# contact_email: you@example.com
|
|
12
|
+
# support_email: support@example.com
|
|
13
|
+
# homepage: https://example.com
|
|
14
|
+
# source_url: https://github.com/you/your-app
|
|
15
|
+
# issues_url: https://github.com/you/your-app/issues
|
|
16
|
+
# license: MIT
|
|
17
|
+
# long_description:
|
|
18
|
+
# en: |-
|
|
19
|
+
# Explain what the app does and how to use it.
|
|
20
|
+
# zh-TW: Translated description.
|
|
21
|
+
# changelog: # text, or per-language like long_description
|
|
22
|
+
# en: |-
|
|
23
|
+
# - Most important change first. Omit to use Release notes.
|
|
24
|
+
# zh-TW: |-
|
|
25
|
+
# - Translated changes.
|
|
26
|
+
# screenshots: [https://example.com/screenshot.png]
|
|
9
27
|
os_min_ver: "7.1-42661"
|
|
28
|
+
# One SPK per architecture. For armv7, add it here and a static 32-bit ARM file
|
|
29
|
+
# under files (e.g. CGO_ENABLED=0 GOARCH=arm GOARM=7 go build).
|
|
10
30
|
arches: [x86_64, aarch64]
|
|
11
31
|
backend:
|
|
12
32
|
kind: binary
|
|
@@ -14,6 +34,10 @@ backend:
|
|
|
14
34
|
x86_64: prebuilt/api-x86_64
|
|
15
35
|
aarch64: prebuilt/api-aarch64
|
|
16
36
|
ui: {dir: ui}
|
|
37
|
+
# UI languages: i18n/messages/<locale>.json for en, zh-TW, zh-CN, ja, ko, de,
|
|
38
|
+
# fr, es and it (DSM's other languages fall back to English); ctx.t(key) reads them.
|
|
39
|
+
i18n:
|
|
40
|
+
messages: i18n/messages
|
|
17
41
|
# init compiles example/main.go for convenience. Replace prebuilt/api-* with
|
|
18
42
|
# your application's static Linux ELF files; the CGI owns authentication.
|
|
19
43
|
# daemon may optionally declare a separately packaged foreground service.
|
|
@@ -2,16 +2,31 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
window.DsmPackageApps = window.DsmPackageApps || {};
|
|
4
4
|
window.DsmPackageApps["__PACKAGE__"] = {
|
|
5
|
-
|
|
5
|
+
// ctx.t(key) returns text from i18n/messages/<locale>.json in DSM's language.
|
|
6
|
+
// ctx.portal exists only with `portal:` in dsm-package.yaml; its panel
|
|
7
|
+
// shows the DSM Application Portal link, or the alias form to administrators.
|
|
8
|
+
mount(root, ctx) {
|
|
6
9
|
const app = document.createElement("main");
|
|
7
10
|
app.className = "binary-app";
|
|
8
11
|
const title = document.createElement("h1");
|
|
9
|
-
title.textContent = "
|
|
12
|
+
title.textContent = ctx.t("app.title");
|
|
10
13
|
const description = document.createElement("p");
|
|
11
|
-
description.textContent = "
|
|
14
|
+
description.textContent = ctx.t("app.description");
|
|
12
15
|
app.append(title, description);
|
|
16
|
+
let portalPanel = null;
|
|
17
|
+
if (ctx.portal) {
|
|
18
|
+
const portal = document.createElement("section");
|
|
19
|
+
portal.setAttribute("class", "dsmapp-portal");
|
|
20
|
+
app.append(portal);
|
|
21
|
+
portalPanel = ctx.portal.mountPanel(portal);
|
|
22
|
+
}
|
|
13
23
|
root.append(app);
|
|
14
|
-
return {
|
|
24
|
+
return {
|
|
25
|
+
unmount() {
|
|
26
|
+
if (portalPanel) portalPanel.dispose();
|
|
27
|
+
app.remove();
|
|
28
|
+
},
|
|
29
|
+
};
|
|
15
30
|
},
|
|
16
31
|
};
|
|
17
32
|
})();
|