@synopackageland/cli 0.31.0 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -799
- package/README.md +11 -3
- package/dist/cli.js +18 -1
- package/dist/error-registry.js +3 -0
- package/dist/init-upstream.d.ts +4 -0
- package/dist/init-upstream.js +19 -0
- package/dist/init.d.ts +4 -0
- package/dist/package-metadata.d.ts +1 -0
- package/dist/package-metadata.js +2 -0
- package/dist/upstream-attribution.d.ts +7 -0
- package/dist/upstream-attribution.js +56 -0
- package/dist/validate.js +2 -1
- package/package.json +1 -1
- package/schema/package-metadata.schema.json +5 -0
- package/schema/synology-app.schema.json +5 -0
- package/skills/SKILL.md +9 -1
- package/skills/reference/compose.md +1 -1
- package/skills/reference/upstream-fork.md +38 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,802 +1,8 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
3
|
+
## 0.32.0 (2026-10-27)
|
|
4
4
|
|
|
5
|
-
-
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
- The CLI's own `.env` loading now sets only `DSM_*` and `SYNOPKGLAND_*` variables; set other variables (for example `GOCACHE` or `PATH`) in the shell.
|
|
10
|
-
- Harden the DSM curl fallback (headers and form fields go through a private curl config; form text is sent literally), human-readable output (control characters are escaped), `ctl` examples and package versions, the UI directory (must resolve inside the project), and standalone inspect (INFO `package` must be an SDK package id).
|
|
11
|
-
|
|
12
|
-
## 0.30.0 (2026-10-24)
|
|
13
|
-
|
|
14
|
-
- Package and forward `identity_gateway.external_access.single_origin`; use SDK 0.30.0 for one-URL Apps, provider-aware DSM menu launches and launch probes.
|
|
15
|
-
- Pin templates 0.30.x and its SDK/App 0.30.0 defaults; keep immutable executor/v0.27.0.
|
|
16
|
-
|
|
17
|
-
## 0.29.0 (2026-10-24)
|
|
18
|
-
|
|
19
|
-
- Depend on templates `~0.29.0` with SDK/App 0.29.0 and UI 0.14.10. SDK 0.29.0 reuses executor/v0.27.0 through executor manifest format 1; no executor digests change.
|
|
20
|
-
- Package `identity_gateway.external_access` (`connect: optional | none`, `origin_change: none | confirm`) for SDK 0.29.0 or later gateways; check refuses it for older SDKs and inspect verifies the packaged external declaration and `settings.cgi` gateway entry.
|
|
21
|
-
|
|
22
|
-
## 0.28.0 (2026-10-24)
|
|
23
|
-
|
|
24
|
-
- Depend on templates `~0.28.0` with SDK/App 0.28.0 and UI 0.14.10. SDK 0.28.0 reuses executor/v0.27.0 through executor manifest format 1; no executor digests change.
|
|
25
|
-
- Default the Compose startup budget to 900 seconds and document slow-NAS readiness; the SDK owns health timing and the Starting status. No per-App option is added.
|
|
26
|
-
- Keep UI CGI scripts executable in built SPKs, and let external OIDC resume tokens reach only the fixed DSM CGI.
|
|
27
|
-
- The release gate checks SDK 0.27.1+ executor builds against the SDK executor manifest instead of requiring a frozen legacy table entry.
|
|
28
|
-
|
|
29
|
-
## 0.27.1 (2026-10-23)
|
|
30
|
-
|
|
31
|
-
- Read executor release mappings, toolchain and six payload pins from SDK executor manifest format 1. Accept compatible SDK minors independently of CLI versions; keep the frozen 0.26.0/0.27.0 fallback. Remove the CLI digest-recording script.
|
|
32
|
-
|
|
33
|
-
## 0.27.0 (2026-10-23)
|
|
34
|
-
|
|
35
|
-
- Depend on templates `~0.27.0` with SDK/App 0.27.0 and UI 0.14.9. Templates patches can ship independently and resolve during npm installation/update; runtime uses the installed templates without network fetching. SDK minor upgrades still require a CLI release for executor mappings/digests and `SDK_UNSUPPORTED` checks. New scaffolds use browser same-origin DSM file operations and the idle-storage fixes.
|
|
36
|
-
- Resolve SDK 0.27.0 to the new executor/v0.27.0 and ship all six verified executor/lifecycle digests. Preserve the previous 0.26.0 inventory and exact-version refusal for unrecorded patches. Protected Apps must rebuild and follow normal administrator approval.
|
|
37
|
-
- Keep Go 1.26.10 and the existing runtime/toolchain requirements. Rust crate publication and NAS/App upgrade certification are outside this release.
|
|
38
|
-
|
|
39
|
-
## 0.26.0 (2026-10-22)
|
|
40
|
-
|
|
41
|
-
- Support SDK/App 0.26.x and pin templates 0.26.0, retaining UI 0.14.3 and executor/v0.24.0 with unchanged protected payload digests.
|
|
42
|
-
- Add optional bounded `daemon.restart` crash recovery for native Apps; require SDK 0.26.0 or later, validate the policy and record it for inspection. Initial startup and intentional stops retain their existing behavior.
|
|
43
|
-
|
|
44
|
-
- Add `ui: false` for native Apps with `identity_gateway` and no SDK window. The main menu gets one url launcher to `sso/open.cgi` (new tab) and Package Center's Open goes to the same entry through INFO `adminurl`, as for Compose Apps. check refuses it without a gateway, with `console` or `portal`, or with capabilities whose approval or sign-in needs the SDK window (`STANDALONE_UI_NO_WINDOW_INVALID`); inspect verifies the single launcher and `adminurl`. Apps with `ui.dir` build unchanged.
|
|
45
|
-
|
|
46
|
-
## 0.25.2 (2026-10-22)
|
|
47
|
-
|
|
48
|
-
- Use templates 0.25.1 with the native Rust lockfile pinned to the public SDK 0.25.0 commit. SDK/App support and executor/lifecycle digests are unchanged.
|
|
49
|
-
- Update SDK download and Go build diagnostics for anonymous access to the public repository.
|
|
50
|
-
|
|
51
|
-
## 0.25.1 (2026-10-22)
|
|
52
|
-
|
|
53
|
-
- Fix upgrades that first add a `daemon`: the generated `preupgrade` ran the old payload's missing `daemon/control` and DSM rolled back with error 4541. The hook now exits 0 when the outgoing payload has no `daemon/` (plain, executor and delegated-worker variants); inspect still accepts the released unguarded hook.
|
|
54
|
-
- Add `daemon.node` (`package: Node.js_v18|v20|v22`, optional `min_version`): the daemon's `exec` is a JavaScript entry run by the Package Center Node.js package through a generated launcher, with INFO `install_dep_packages`. The SPK bundles no Node. See docs/daemon.md for availability and dependency behaviour.
|
|
55
|
-
- Add `daemon.ingress` (`path`, optional `timeout`, default 3600 s): a same-origin path in DSM's nginx through web-config `nginx-static-config` `type: dsm`, proxied unbuffered to `/tmp/synopkgland-ingress-<package>.sock`, with nginx reloads in INFO. check requires os_min_ver 7.2-64570 or later (`STANDALONE_DAEMON_INGRESS_MIN_DSM`); inspect verifies the location, resource, INFO and daemon environment.
|
|
56
|
-
|
|
57
|
-
## 0.25.0 (2026-10-22)
|
|
58
|
-
|
|
59
|
-
- Add the opt-in `console` declaration for native Apps with `identity_gateway`: a native UI URL launcher and an administrator-only DSM console, selected by Package Center Open. Validate both entries and refuse incompatible launch declarations.
|
|
60
|
-
- Fix installation-settings inspection when native identity-gateway diagnostics precede the settings hook, retaining full lifecycle validation.
|
|
61
|
-
- Document punctuation rules for owned UI copy in the development skill.
|
|
62
|
-
- Support SDK/App 0.25.0 and templates 0.25.0, with UI 0.14.3 in Vue scaffolds. Reuse executor/v0.24.0 with unchanged protected executor/lifecycle payloads and Go 1.26.10. OIDC browser cold-login continuation requires SDK 0.25.0. No NAS acceptance is claimed.
|
|
63
|
-
|
|
64
|
-
## 0.24.1 (2026-10-22)
|
|
65
|
-
|
|
66
|
-
- Build SDK/App 0.24.1 with the verified immutable executor/v0.24.0 release and its exact executor/lifecycle digests; retain SDK/App 0.24.0 support. SDK 0.24.1 adds AppShell brand navigation to the first page and supports UI 0.14.3.
|
|
67
|
-
- Keep templates 0.24.0 and Go 1.26.10. Executor and lifecycle payloads remain unchanged.
|
|
68
|
-
|
|
69
|
-
## 0.24.0 (2026-10-22)
|
|
70
|
-
|
|
71
|
-
- Pin Go 1.26.10 for every SDK runtime build, addressing crypto/x509 GO-2026-6809. Ship the matching executor/lifecycle digest inventory for SDK 0.24.0; older release records are preserved in their release history.
|
|
72
|
-
- Include the native HTTPS prestart port-release wait and diagnostics, and SDK/App UI 0.14 compatibility already merged in this release line.
|
|
73
|
-
- Use templates 0.24.0 with UI 0.14.0 and the supported DSM Node.js_v22 dependency. Update build/test environments to Node.js 24.22.1 LTS.
|
|
74
|
-
- Known limitations: rebuilding and upgrading executor Apps changes their protected payload digests and requires administrator reapproval of system access. No NAS acceptance is claimed.
|
|
75
|
-
|
|
76
|
-
## 0.23.2 (2026-10-22)
|
|
77
|
-
|
|
78
|
-
- Build SDK/App 0.23.2 with its verified immutable executor/v0.20.0 digests; retain support for SDK/App 0.23.0 and 0.23.1. SDK 0.23.2 adds compatibility with UI 0.14.0.
|
|
79
|
-
- Keep templates 0.23.0 and its existing scaffold pins. Executor and lifecycle payloads remain unchanged.
|
|
80
|
-
|
|
81
|
-
## 0.23.1 (2026-10-22)
|
|
82
|
-
|
|
83
|
-
- Build SDK/App 0.23.1 with its verified immutable executor/v0.20.0 digests; retain support for SDK/App 0.23.0. This enables the SDK HTTP transfer error-status fix without changing executor or lifecycle payloads.
|
|
84
|
-
- Include the native HTTPS shutdown/start port-release fix and recognize its exact diagnostic prefix when inspecting Portal and background-job lifecycle scripts. Keep templates 0.23.0 and the existing UI pin.
|
|
85
|
-
|
|
86
|
-
## 0.23.0 (2026-10-21)
|
|
87
|
-
|
|
88
|
-
- Validate the explicit OIDC `browser_redirect` contract before packaging and pin templates/SDK 0.23.0.
|
|
89
|
-
- Reuse executor/v0.20.0 with unchanged executor and lifecycle payloads.
|
|
90
|
-
|
|
91
|
-
## 0.22.0 (2026-10-21)
|
|
92
|
-
|
|
93
|
-
- Support SDK/App 0.22.x and pin templates 0.22.0 with published UI 0.12.5.
|
|
94
|
-
- Register actionable diagnostics for invalid, unsupported or unbuildable native installation settings.
|
|
95
|
-
- Validate provider-only public upstream access, host UDP listeners, fixed launch paths and native installation settings.
|
|
96
|
-
- Reuse immutable executor/v0.20.0 with exact SDK-version digest checks.
|
|
97
|
-
|
|
98
|
-
## 0.21.1 (2026-10-21)
|
|
99
|
-
|
|
100
|
-
- Resolve SDK/App 0.21.1 to the verified immutable executor/v0.20.0 release while keeping exact SDK-version digest checks.
|
|
101
|
-
- Pin templates 0.21.1 with SDK/App 0.21.1 and UI 0.13.1 for new projects.
|
|
102
|
-
|
|
103
|
-
## 0.21.0 (2026-10-21)
|
|
104
|
-
|
|
105
|
-
- Validate and preserve `compose.devices.gpu` in check, build and inspect for optional Intel render-node access and software fallback.
|
|
106
|
-
- Pin SDK/templates 0.21.0 and reuse immutable executor/v0.20.0 with verified unchanged executor/lifecycle digests.
|
|
107
|
-
|
|
108
|
-
## 0.20.0 (2026-10-21)
|
|
109
|
-
|
|
110
|
-
- Align CLI/templates and the supported SDK minor line at 0.20; retain published UI 0.12.5.
|
|
111
|
-
- Compare upgrade approval requirements with `build/inspect --baseline`.
|
|
112
|
-
- Package native Compose shared-folder mounts with `select: install` and pass host health readiness to the daemon.
|
|
113
|
-
- Pin the 0.20.0 executor/lifecycle digest inventory and refresh canonical approval fixtures. Rebuilt executor Apps require administrator reapproval after upgrade.
|
|
114
|
-
|
|
115
|
-
## 0.19.1 (2026-10-20)
|
|
116
|
-
|
|
117
|
-
- Record SDK 0.19.1 executor and lifecycle digests for the executor fix that accepts `deadline_ms` on delegated `webapi.call`; SDK 0.19.0 digests remain. Executor Apps rebuilt with SDK 0.19.1 require one administrator reapproval after upgrading.
|
|
118
|
-
- Compare upgrade approval requirements with a baseline SPK: `build --baseline` and `inspect --baseline` report root program digests, policy differences, task template changes and executor-only handoff eligibility.
|
|
119
|
-
- Retain templates 0.19.0 (SDK 0.19.0) and UI 0.12.5.
|
|
120
|
-
|
|
121
|
-
## 0.19.0 (2026-10-20)
|
|
122
|
-
|
|
123
|
-
- Align the CLI SDK minor line and templates at 0.19.0; retain UI 0.12.5.
|
|
124
|
-
- Support native DSM OIDC login without a browser bridge for compatible clients.
|
|
125
|
-
- Refresh canonical executor setup fixtures and all three executor/lifecycle architecture pins for SDK 0.19.0. Rebuilt executor Apps require one administrator reapproval after upgrading.
|
|
126
|
-
|
|
127
|
-
## 0.18.0 (2026-10-20)
|
|
128
|
-
|
|
129
|
-
- Support the SDK 0.18.x minor line and pin templates 0.18.0 with SDK/App 0.18.0 and UI 0.12.5.
|
|
130
|
-
- Record SDK 0.18.0 executor and lifecycle digests and refresh executor setup fixtures.
|
|
131
|
-
- Add the native OIDC browser bridge and App launch resume flow.
|
|
132
|
-
- Default upstream forks to no ctl integration and document the fixed ctl coverage checklist.
|
|
133
|
-
- Declare optional native-client passthrough capabilities.
|
|
134
|
-
|
|
135
|
-
## 0.17.8 (2026-10-20)
|
|
136
|
-
|
|
137
|
-
- Update SDK 0.17.7 executor and lifecycle digests for the administrator-role fix.
|
|
138
|
-
|
|
139
|
-
## 0.17.7 (2026-10-20)
|
|
140
|
-
|
|
141
|
-
- Inspect Compose Apps with custom icons and localized titles using their archived build inputs, preserving every icon size and strict launcher validation. Preserve declared daemon uninstall hooks when checking fixed lifecycle scripts.
|
|
142
|
-
|
|
143
|
-
## 0.17.6 (2026-10-20)
|
|
144
|
-
|
|
145
|
-
- Inspect sharedFolder, Portal and install-selected Apps by reconstructing fixed lifecycle scripts from their complete inputs, including native HTTPS ingress and App hooks.
|
|
146
|
-
|
|
147
|
-
## 0.17.5 (2026-10-20)
|
|
148
|
-
|
|
149
|
-
- Run native HTTPS preparation inside the SDK lifecycle steps before App hooks, keeping generated hook wrappers inspectable.
|
|
150
|
-
|
|
151
|
-
- Preserve older SDK gateway/controller JSON and supported timeout limits so their direct-connection fallback remains buildable; reject expanded budgets that require SDK 0.17.5.
|
|
152
|
-
|
|
153
|
-
- Keep Compose named volumes without adding executor/root permissions; warn before uninstall and report their exact undeleted names in nine native locales when delete-data is selected. Clear package-owned data/config/home contents only on explicit uninstall, preserving data on upgrades, stops and keep.
|
|
154
|
-
|
|
155
|
-
- Default supported gateway Apps to a DSM-managed HTTPS origin using native package resources and a private authenticated gateway socket. Preserve direct connections for older SDK/DSM targets with an explanation before opening them.
|
|
156
|
-
- Prepare private connection credentials as the package account after DSM creates package state, and reject modified gateway proxy settings during SPK inspection.
|
|
157
|
-
- Apply `ctl --timeout` to discovery, JSON requests, polling and transfer inactivity without replaying uncertain writes; use a 62-second default transport allowance.
|
|
158
|
-
- Reuse `daemon.timeouts` for native, Compose and background lifecycle work, including declarations that need no daemon executable. Allow lifecycle and App purge budgets up to 3600 seconds while retaining the Compose startup cap.
|
|
159
|
-
- Generate matching gateway, supervisor and approved executor budgets, preserve them through SPK inspection, and report pending uninstall cleanup within bounded TERM/reap reserve.
|
|
160
|
-
|
|
161
|
-
- Pin templates 0.17.8 and SDK/App 0.17.5, including UI 0.12.4 full-page layout. Updated executor and lifecycle payloads require administrator reapproval after upgrading rebuilt Apps.
|
|
162
|
-
|
|
163
|
-
## 0.17.4 (2026-10-19)
|
|
164
|
-
|
|
165
|
-
- Accept `compose.startup_timeout_seconds` (default 120, integer 2–900), use the SDK plan's value for daemon start, and deliver the same budget to container bootstrap adapters through the SDK-generated environment. Reject a planner that cannot honor an explicitly declared budget. Keep ingress closed until readiness succeeds.
|
|
166
|
-
|
|
167
|
-
- Show actionable image-pull diagnosis in nine locales and direct users to Package Center Repair when a package starts with stale container assets.
|
|
168
|
-
- Pin templates 0.17.6 and SDK/App 0.17.4; keep UI at 0.12.3.
|
|
169
|
-
|
|
170
|
-
## 0.17.3 (2026-10-19)
|
|
171
|
-
|
|
172
|
-
- Pin templates 0.17.5, SDK/App 0.17.3 and UI 0.12.3 for generated Apps.
|
|
173
|
-
- Record SDK 0.17.3 executor and lifecycle digests; all six payloads are unchanged from 0.17.1.
|
|
174
|
-
- Keep the “User password” wording in all nine locales and package the generated native SDK version identifiers.
|
|
175
|
-
|
|
176
|
-
## 0.17.2 (2026-10-19)
|
|
177
|
-
|
|
178
|
-
- Pin templates with matching frontend and native SDK versions.
|
|
179
|
-
- Record the verified SDK 0.17.1 executor and lifecycle payload digests.
|
|
180
|
-
- Rename password labels and approval instructions to “User password” across all nine locales.
|
|
181
|
-
|
|
182
|
-
## 0.17.1 (2026-10-19)
|
|
183
|
-
|
|
184
|
-
- Remove environment-specific release notes and source comments from distributed content, including generated DSM window scripts.
|
|
185
|
-
- Prepare npm releases from a clean package directory without local archive references.
|
|
186
|
-
|
|
187
|
-
## 0.17.0 (2026-10-19)
|
|
188
|
-
|
|
189
|
-
- Pin SDK/App 0.17.0 and templates 0.17.1, with UI 0.12.1 in Vue scaffolds; package the executor fixes for directory users and request batches.
|
|
190
|
-
- Fetch SynoToken early in standalone and Portal windows so the first API request can start sooner.
|
|
191
|
-
- Allow Portal without an executor from DSM 7.2-64570. Request DSM nginx reload through INFO during install, upgrade and uninstall; DSM 7.1 still needs an executor for registration.
|
|
192
|
-
|
|
193
|
-
- Expose ctx.batch in generated SDK windows, sharing the existing request guards and token recovery. Keep single-call retries unchanged; never replay a batch after partial execution.
|
|
194
|
-
|
|
195
|
-
## 0.16.0 (2026-10-19)
|
|
196
|
-
|
|
197
|
-
- Pin SDK/templates 0.16.0; generated Shared Folder flows use the shared SDK readback and settings components.
|
|
198
|
-
- Add the upstream-fork recipe/init/check workflow, Container Manager preflight and architecture-matched storage initializer packaging while preserving official images.
|
|
199
|
-
- Remove internal deployment details from published content and scan actual npm tarballs before release.
|
|
200
|
-
|
|
201
|
-
## 0.15.4 (2026-10-18)
|
|
202
|
-
|
|
203
|
-
- Fix Compose import and undeclared SDK defaults after CLI-only patch releases. Resolve the SDK from the exactly pinned templates' Go module instead of assuming the CLI and SDK share a patch version; daemon-control defaults use the same source.
|
|
204
|
-
- Preserve explicit Compose and identity-gateway SDK declarations. Add subprocess regressions with differing CLI/SDK versions and no SDK source override, plus release smoke coverage for real Compose imports and headless manifests.
|
|
205
|
-
- Keep templates/SDK pinned to 0.15.2 and every executor/lifecycle digest entry unchanged. Upgrade from CLI 0.15.3 to 0.15.4 to restore `init -t compose --from`; SDK/helper bytes do not change and no new administrator reapproval requirement is introduced.
|
|
206
|
-
|
|
207
|
-
繁中摘要:修正 CLI 與 SDK patch 版本不同時,Compose 匯入/未宣告 SDK 的預設路徑下載不存在 SDK tag 的問題;改由固定 templates 的 Go module 讀取 SDK pin,daemon-control 預設值亦同步。保留明確 SDK 宣告的優先順序,新增無 source override 的版本拆分回歸測試與正式產物 smoke。templates/SDK 保持 0.15.2,全部 executor/lifecycle digest 不變;請由 CLI 0.15.3 升級至 0.15.4,不新增管理員重新核准要求。
|
|
208
|
-
|
|
209
|
-
## 0.15.3 (2026-10-18)
|
|
210
|
-
|
|
211
|
-
- Pin templates and SDK fixtures/examples to 0.15.2, including UI 0.12.0 scaffolds, concise UI copy/tokens and delegate DTO contract checks.
|
|
212
|
-
- Add the SDK 0.15.2 executor/lifecycle digest entry using Go 1.26.9; retain every earlier entry unchanged. All six digests match 0.15.1, so upgrading from 0.15.1 adds no administrator reapproval requirement. Apps upgrading from 0.15.0 retain the one-time approval introduced in SDK 0.15.1.
|
|
213
|
-
- Include CLI-5 shared OFF_GLOSSARY rules and CLI-6 command failure exit codes from CLI 0.15.2. CLI 0.15.2 was already published with templates 0.15.1; use 0.15.3 for the coordinated SDK/templates release.
|
|
214
|
-
|
|
215
|
-
繁中摘要:templates/SDK pins 同步 0.15.2,帶入 UI 0.12.0、精簡文案/token 與 DTO 契約檢查;保留 CLI-5 詞彙規則及 CLI-6 正確退出碼。新增 SDK 0.15.2 digest 表項,六個 digest 均與 0.15.1 相同,保留全部舊 pins;從 0.15.1 升級不新增重新核准要求,從 0.15.0 升級仍需完成一次管理員核准。CLI 0.15.2 已先發佈,因此本次協同發版使用 CLI 0.15.3。
|
|
216
|
-
|
|
217
|
-
## 0.15.2 (2026-10-18)
|
|
218
|
-
|
|
219
|
-
- Preserve command-set process exit codes instead of resetting them to 0 after CLI dispatch. `ctl` failures now reach scripts and CI with their documented exit codes; successful commands still exit 0 and uncaught exceptions exit 1.
|
|
220
|
-
- Add subprocess regression coverage for `ctl` exit codes 0–8, confirmation before writes, and failures from `check`, `build`, `inspect`, `status` and `test`. Document the existing `ctl` exit-code contract and informational discovery/session results.
|
|
221
|
-
- CLI-only patch: templates and SDK fixtures/examples remain pinned to 0.15.1; executor/lifecycle digests are unchanged.
|
|
222
|
-
|
|
223
|
-
繁中摘要:修正 CLI 在子指令完成後把退出碼覆寫成 0 的問題,讓 `ctl` 失敗正確傳遞至腳本與 CI;成功仍為 0,未捕捉例外仍為 1。新增實際子行程測試,涵蓋 `ctl` 的 0–8 退出碼、寫入確認及其他主要指令的失敗;README 記錄既有退出碼與 discovery/session 資訊結果。此次僅更新 CLI,templates/SDK 維持 0.15.1,executor/lifecycle digest 不變。
|
|
224
|
-
|
|
225
|
-
## 0.15.1 (2026-10-18)
|
|
226
|
-
|
|
227
|
-
- Require explicit `DSM_E2E_SSH` for e2e tunnels and use `dsm` as the default saved-profile target; set `DSM_E2E_TARGET` to reuse an earlier target name. Anonymize internal NAS fixtures and documentation.
|
|
228
|
-
- Pin templates and SDK fixtures/examples to 0.15.1. Add the 0.15.1 executor/lifecycle digest entry and retain the published 0.15.0 pins unchanged.
|
|
229
|
-
- Cover package-named control.sh refusal logs and rejected `.executor` / `.policy.json` staging cleanup.
|
|
230
|
-
- Executor task definitions change: Apps rebuilt with SDK 0.15.1 require one administrator reapproval after upgrade.
|
|
231
|
-
|
|
232
|
-
繁中摘要:e2e tunnel 必須明確設定 `DSM_E2E_SSH`,profile 預設 target 改為 `dsm`(沿用舊 profile 時設定 `DSM_E2E_TARGET`);清理內部 NAS 範例資訊。templates/SDK pins 同步 0.15.1;新增同版三架構 executor/lifecycle digest,保留 0.15.0 pins。驗證 control.sh 拒絕 log 的套件名與 runtime copies 清除。**task 定義改變:App 使用新 SDK 重建升級後,管理員需重新核准一次。**
|
|
233
|
-
|
|
234
|
-
## 0.15.0 (2026-10-18)
|
|
235
|
-
|
|
236
|
-
- Add `synopkgland ctl` host/session management, authenticated API v1 discovery, explicit command trust, typed invocation and fixed job/pagination/NDJSON/upload flows. Commands keep App backend authorization; writes require confirmation.
|
|
237
|
-
- Document resource/verb naming recommendations without a verb allowlist or effect inference; explicit effects remain mandatory and binding checks remain unchanged.
|
|
238
|
-
- Redact standard JSON Schema writeOnly values in dry-run/confirmation plans, schema errors, results, list/help and caches, including nested arrays/objects and multi-host output; keep outgoing requests unchanged.
|
|
239
|
-
- Pin templates and released executor digests to 0.15.0, retaining the same-minor digest selection rule.
|
|
240
|
-
- Breaking: remove the legacy Compose route and bridge publish mode. Migrate to schema 2 `dsm-package.yaml` with ordered `compose.files`, `compose.web` container port/health and `identity_gateway.sdk: 0.15.0`; remove old `integration.compose`/`integration.identity_gateway`. `web.host_port` is accepted but ignored. Build/check/inspect share the SDK planner. Rebuild with templates/SDK 0.15.0 and verify install/upgrade; historical `.sc` cleanup requires separate authorization. Changing subnet candidate requires a clean installation, not an automatic network migration.
|
|
241
|
-
|
|
242
|
-
繁中摘要:新增 writeOnly 敏感值遮罩(巢狀、陣列、多主機、計畫、錯誤及快取),實際請求保持原值。新增 `synopkgland ctl`,從已安裝 App 的 authenticated「Syno Package Land API 描述」v1 發現並執行明確 commands,支援多主機與固定任務流程。**不相容變更**:移除舊 Compose 打包路線及 publish 模式;改用 schema 2 `compose`/`identity_gateway`,固定 SDK/templates 0.15.0 並重建驗證。gateway 直接連固定 bridge IP 的 container port;`web.host_port` 僅解析相容、會忽略,歷史 `.sc` 與既有子網不自動清除或遷移。
|
|
243
|
-
|
|
244
|
-
## 0.14.1
|
|
245
|
-
|
|
246
|
-
- DSM 會改寫 standalone URL,因此沒有 SDK class 的 schema 1 web launcher 使用 url;schema 2 identity_gateway + compose 與原生 new-page 使用 standalone。兩條 Compose 路線共用預設解析。
|
|
247
|
-
|
|
248
|
-
## 0.14.0
|
|
249
|
-
|
|
250
|
-
- 原生 App 支援 ui.launch: dsm-window | new-page;new-page 使用 DSM standalone launcher。SDK 原生 App 的內建預設維持 dsm-window;Docker/Web App(含 schema 2 identity_gateway + compose)共用解析邏輯,內建預設改為 new-page,主選單與套件中心皆可開啟既有 gateway/public alias。inspect 驗證 launcher 與 Portal 宣告,完整頁統一設定標題、favicon 與手機 viewport。Web App 省略開啟方式的行為變更,因此採用 0.14.0。
|
|
251
|
-
|
|
252
|
-
## 0.13.1 (2026-10-17)
|
|
253
|
-
|
|
254
|
-
- Use templates 0.13.1, SDK 0.13.1 fixtures and the unchanged executor/lifecycle digests on the 0.13 minor line.
|
|
255
|
-
|
|
256
|
-
繁中摘要:模板與 SDK 範例同步至 0.13.1;沿用 0.13.0 的 executor/lifecycle digest,既有 App 不因本次版本更新重核准。
|
|
257
|
-
|
|
258
|
-
## 0.13.0 (2026-10-17)
|
|
259
|
-
|
|
260
|
-
- Add the identity gateway for daemon web applications and package-account compose upstreams: OIDC, header and token modes, validated native payload targets and bounded connection policies. UDP connections are handled separately from TCP.
|
|
261
|
-
- `account.on_delete` declares application account/session cleanup when a local DSM account disappears; domain accounts support explicit gateway purge. Bundle the `identity-gateway` skill for wrapping and verifying existing open-source applications.
|
|
262
|
-
- Generated Apps pin templates/SDK 0.13.0 and UI 0.10.5; record the 0.13.0 executor/lifecycle digests. Skill examples use the released SDK version. This CLI builds SDK 0.13.x; upgrade backend and frontend pins together.
|
|
263
|
-
|
|
264
|
-
繁中摘要:daemon 與 package-account compose App 可宣告 identity gateway,以 DSM 身分透過 OIDC、header 或 token 登入,並限制原生 payload 目標與網路連線(區分 UDP/TCP)。`account.on_delete` 宣告本機 DSM 帳號刪除時的 App 帳號/session 清理;網域帳號支援明確 purge。新增 `identity-gateway` skill 說明既有 OSS App 的包裝及驗證。templates/SDK 同步 0.13.0、UI 0.10.5,更新 executor digest 與範例版本;此 CLI 建置 SDK 0.13.x,後端/前端 pin 應一併升級。
|
|
265
|
-
|
|
266
|
-
## 0.12.2 (2026-10-16)
|
|
267
|
-
|
|
268
|
-
- Generated Apps use templates 0.12.2, SDK 0.12.2 and UI 0.10.3. SDK 0.12.2 types `ctx.launchParams` and `ctx.onLaunch` and adds `followLaunchRoute`, `launchRoute` and `dsmLaunchURL`.
|
|
269
|
-
- Pin the SDK 0.12.2 executor and lifecycle digests, identical to 0.12.1 for all three architectures.
|
|
270
|
-
- The DSM window forwards launch parameters to the App. `ctx.launchParams` holds the App's own string values from the launch that opened the window, from a desktop URL `?launchApp=SYNO.SDS.<package>.Instance&launchParam=<url-encoded key=value&...>` or `SYNO.SDS.AppLaunch(id, {key: value})`; `ctx.onLaunch(fn)` runs fn with those of each later launch of the open window. DSM's own keys, non-string values, keys outside `[A-Za-z][A-Za-z0-9_.-]{0,63}`, values over 2048 characters or with control characters, and keys past 32 are left out.
|
|
271
|
-
- `ctx.reopen` callbacks now run when DSM launches the already open window again (main menu, desktop URL or AppLaunch); DSM calls the window's onRequest then, never onOpen again.
|
|
272
|
-
|
|
273
|
-
繁中摘要:新專案使用 templates 0.12.2、SDK 0.12.2 與 UI 0.10.3,並加入 SDK 0.12.2 的 executor digest(與 0.12.1 相同)。DSM 視窗把啟動參數轉給 App:`ctx.launchParams` 是開啟視窗那次的 App 字串參數(桌面 URL `launchParam` 或 `SYNO.SDS.AppLaunch`),`ctx.onLaunch(fn)` 在已開視窗再次被帶參數啟動時呼叫;DSM 自有欄位、非字串、不合格的 key、超過 2048 字元或含控制字元的值與第 32 個之後的 key 會被略過。已開視窗再次啟動時 `ctx.reopen` 現在會觸發(DSM 呼叫 onRequest,不會再呼叫 onOpen)。
|
|
274
|
-
|
|
275
|
-
## 0.12.1 (2026-10-16)
|
|
276
|
-
|
|
277
|
-
- Preserve optional `raw_max_bytes` in WebAPI profiles and administrator policy digests. Reject invalid limits and require raw-capable SDK 0.12.1; zero/omitted profiles stay JSON-only. Generated approval details receive the byte limit.
|
|
278
|
-
- Pin the SDK 0.12.1 three-architecture executor and lifecycle digests. Templates remain 0.12.0; no template change is needed for an optional consumer-declared profile.
|
|
279
|
-
|
|
280
|
-
繁中摘要:WebAPI profile 支援 raw_max_bytes 明確啟用原始回應與大小上限;驗證及核准 digest 保留此設定,需搭配 SDK 0.12.1。更新 executor digest,templates 維持 0.12.0。
|
|
281
|
-
|
|
282
|
-
## 0.12.0 (2026-10-16)
|
|
283
|
-
|
|
284
|
-
- Generated Apps use templates 0.12.0, SDK 0.12.0 and UI 0.10.1. Vue pages and sections stack at the UI section gap, and SDK dialogs size to their content.
|
|
285
|
-
- `metadata.screenshots` accepts up to 5 `https://` URLs, matching the catalog; `check` refuses more, or an `http://` URL, with `STANDALONE_TEXT_INVALID`.
|
|
286
|
-
- The executor digest table records SDK 0.12.0, whose executor and lifecycle digests equal 0.11.0's. This CLI builds SDK 0.12.x executors; upgrade backend and frontend pins to 0.12.0 together.
|
|
287
|
-
- 繁中:產生的 App 使用 templates 0.12.0、SDK 0.12.0 與 UI 0.10.1;Vue 頁面與區塊以 UI section gap 排列,SDK 對話框依內容決定寬度。`metadata.screenshots` 最多 5 個 `https://` URL,與 catalog 一致,超過或使用 `http://` 時 `check` 回報 `STANDALONE_TEXT_INVALID`。digest 表記錄 SDK 0.12.0(與 0.11.0 相同);此 CLI 建置 SDK 0.12.x executor,後端/前端 pin 需一併升級至 0.12.0。
|
|
288
|
-
|
|
289
|
-
## 0.11.0 (2026-10-16)
|
|
290
|
-
|
|
291
|
-
- Add capabilities.webapi named profiles with purpose and exact API/method/version lists, pinned in the administrator-approved executor policy. Build, inspect, lifecycle, bridge services and consent details support WebAPI-only Apps without granting file/root operations.
|
|
292
|
-
- Require SDK 0.11.0 for WebAPI profiles and record the three-architecture executor/lifecycle digests. The SDK and templates now share the 0.11 minor line; upgrade backend/frontend pins together.
|
|
293
|
-
- 繁中:新增具名 WebAPI profile,宣告用途與 API/method/version 清單並納入管理員核准;建置、檢查、生命週期與 bridge 支援僅 WebAPI 的 App。使用此功能需 SDK 0.11.0,後端/前端 pin 一併升級至 0.11。
|
|
294
|
-
|
|
295
|
-
## 0.10.12 (2026-10-15)
|
|
296
|
-
|
|
297
|
-
- Generated Apps use templates 0.10.13, SDK 0.10.12 and UI 0.9.10, including PageInfo, responsive page headers and confirmation before removing a Portal page's own entry.
|
|
298
|
-
- Executor and lifecycle digests are unchanged from SDK 0.10.11 for all three architectures.
|
|
299
|
-
|
|
300
|
-
繁中摘要:更新 templates 至 0.10.13、SDK 至 0.10.12、UI 至 0.9.10;帶入頁面附註、標題換行與入口移除確認。三架構 executor/lifecycle digest 不變。
|
|
301
|
-
|
|
302
|
-
## 0.10.11 (2026-10-15)
|
|
303
|
-
|
|
304
|
-
- Bridge App builds with a manifest minimum below DSM 7.2 inject executor portal mode so Rust, Python and Node Apps can use the fixed entry enable/remove routes on DSM 7.1 and 7.4.
|
|
305
|
-
- Pin templates 0.10.12 and SDK 0.10.11, including the three updated executor digests. Generated Vue Apps use UI 0.9.9.
|
|
306
|
-
|
|
307
|
-
繁中摘要:manifest 最低 DSM 低於 7.2 時,bridge App 建置帶入 executor portal mode,提供 DSM 7.1/7.4 的入口啟用與移除;更新 templates 0.10.12、SDK 0.10.11 及三架構 executor digest,UI 保持 0.9.9。
|
|
308
|
-
|
|
309
|
-
## 0.10.10 (2026-10-15)
|
|
310
|
-
|
|
311
|
-
- Uses SDK 0.10.10, templates 0.10.11 and UI 0.9.9. `init` pins these versions for the generated project, and the executor digest table pins SDK 0.10.10 for x86_64, aarch64 and armv7.
|
|
312
|
-
- The shared DSM window wrapper waits for the SDK session helper before backend and DSM WebAPI calls. A portal window without a desktop SynoToken obtains the current token through a shared same-origin request; cookie, token, principal and original client-address validation remain enforced.
|
|
313
|
-
- Every Go child process merges `github.com/synopackageland/*` into its effective `GOPRIVATE`, `GONOPROXY` and `GONOSUMDB`, preserving environment and `go env -w` settings. Git credentials are needed to fetch the private SDK. Direct `go get` commands supply their own GOPRIVATE setting.
|
|
314
|
-
- SDK approval components explain the requested system privileges with a single consent card, expandable details and inline password errors. `ExecutorApproval`, `ExecutorNotice` and `ExecutorSettings` take `purpose`; background-save settings use one save-folder row per destination key. See the SDK CHANGELOG for translation-key and slot changes.
|
|
315
|
-
- App pins: `@synopackageland/cli` 0.10.10 with its lockfile; SDK 0.10.10 for Go, npm, Cargo and `backend.sdk`; UI 0.9.9. Rebuild the App. An unchanged policy and a matching root-owned INFO anchor preserve an existing approval; policy or capability changes require administrator approval.
|
|
316
|
-
|
|
317
|
-
繁中摘要:使用 SDK 0.10.10、templates 0.10.11、UI 0.9.9 與三架構新 executor digest。portal 缺少 token 時,視窗 wrapper 先等待共用 SDK helper 取得 token,再呼叫後端與 DSM WebAPI,維持驗證。所有 Go 子行程自動合併 private namespace 並保留既有設定。核准畫面使用 consent 卡片,元件可傳入 `purpose`;背景存檔設定每個 key 只有一列存放資料夾。App 更新 exact pin 與 lock 後重建。
|
|
318
|
-
|
|
319
|
-
## 0.10.9 (2026-10-15)
|
|
320
|
-
|
|
321
|
-
Builds with SDK 0.10.9 and templates 0.10.10: `init` writes SDK v0.10.9,
|
|
322
|
-
`@synopackageland/sdk` 0.10.9 and `@synopackageland/ui` 0.9.8, and the root-ops
|
|
323
|
-
template's `ExecutorGate.vue` passes `preload`. The executor digest table adds
|
|
324
|
-
SDK 0.10.8 and 0.10.9 (equal to each other; the executor changed in 0.10.8).
|
|
325
|
-
An executor upgrade keeps the existing approval when the policy is unchanged
|
|
326
|
-
and the new executor matches its root-owned INFO anchor. A policy or capability
|
|
327
|
-
change requires an administrator's approval again.
|
|
328
|
-
The CLI still needs SDK 0.10.5 or later: an executor without `tasks` (before
|
|
329
|
-
0.10.8) receives the window's full readback. Without an executor setup,
|
|
330
|
-
SDK 0.10.9's `ExecutorApproval` shows the pages alone, with or without `preload`.
|
|
331
|
-
|
|
332
|
-
To upgrade an App: devDependency `@synopackageland/cli` 0.10.9 (exact) with
|
|
333
|
-
its lockfile; an App that depends on the SDK directly moves to 0.10.9 (Go
|
|
334
|
-
`require github.com/synopackageland/syno-pkg-land-sdk v0.10.9` with go.sum,
|
|
335
|
-
`@synopackageland/sdk` and `@synopackageland/app` 0.10.9, Cargo tag
|
|
336
|
-
`v0.10.9`, `backend.sdk: 0.10.9`); then rebuild and upgrade. An unchanged
|
|
337
|
-
policy and matching root-owned INFO anchor preserve the existing approval.
|
|
338
|
-
|
|
339
|
-
繁中摘要:搭配 SDK 0.10.9、templates 0.10.10(UI 0.9.8)。digest 表新增 SDK 0.10.8/0.10.9
|
|
340
|
-
(兩者相同,executor 在 0.10.8 改變)。policy 不變且新 executor 符合 root-owned INFO anchor 時,
|
|
341
|
-
升級沿用原核准;policy/能力改變才需管理員重新核准。SDK 下限維持 0.10.5(沒有 `tasks` 的舊 executor 完整核對)。沒有 executor setup 時,SDK 0.10.9 只顯示頁面。
|
|
342
|
-
App 要改:`@synopackageland/cli` 0.10.9+lock;直接依賴 SDK 的 App 升到 0.10.9。
|
|
343
|
-
|
|
344
|
-
- The DSM window shows an administrator the App without reading Task
|
|
345
|
-
Scheduler and EventScheduler when the pinned, running executor's status
|
|
346
|
-
says its own readback of the approval tasks is `ready` (`tasks`, SDK
|
|
347
|
-
0.10.8 or later). That readback runs at the executor's start and
|
|
348
|
-
every 10 minutes; a task another administrator changes after it is seen at
|
|
349
|
-
the next one, up to 15 minutes later, instead of when the window opens.
|
|
350
|
-
Approval, the control task's start, stop and purge, and a scope selection
|
|
351
|
-
still read both tasks back first. An executor without `tasks`, or with a
|
|
352
|
-
readback that is not `ready`, is read back by the window as before, and
|
|
353
|
-
the first status request now also serves its health check.
|
|
354
|
-
繁中:管理員開啟視窗時,若 executor 回報自己的排程核對為 ready,就不再呼叫兩個
|
|
355
|
-
排程 API;核准、start/stop/purge 與範圍選擇仍先完整核對。舊 executor 照舊核對。
|
|
356
|
-
|
|
357
|
-
## 0.10.8 (2026-10-15)
|
|
358
|
-
|
|
359
|
-
Builds with SDK 0.10.7 and templates 0.10.8, as 0.10.7 did: `init` still
|
|
360
|
-
writes SDK v0.10.7, `@synopackageland/sdk` 0.10.7 and `@synopackageland/ui`
|
|
361
|
-
0.9.8, and the executor digest table is unchanged, so an App rebuilt on it
|
|
362
|
-
keeps its approval when the policy is unchanged and the executor matches its
|
|
363
|
-
root-owned INFO anchor. A policy or capability change requires approval again. Only the DSM
|
|
364
|
-
window's `ctx.call` changes. The CLI still needs SDK 0.10.5 or later: the
|
|
365
|
-
SDK's Gate, `useLifecycleRetry`, `appLifecycle` and `ExecutorApproval` already
|
|
366
|
-
read an `APP_STOPPED` that arrives at once and check again; SDK 0.10.7 changed
|
|
367
|
-
only its protocol README's wording, and nothing in the CLI depends on it.
|
|
368
|
-
|
|
369
|
-
繁中摘要:搭配 SDK 0.10.7、templates 0.10.8(UI 0.9.8),digest 不變;SDK 下限維持 0.10.5
|
|
370
|
-
(SDK 的 Gate/`useLifecycleRetry`/`appLifecycle`/`ExecutorApproval` 本來就處理立即回的
|
|
371
|
-
`APP_STOPPED`)。只改 DSM window 的 `ctx.call`。
|
|
372
|
-
|
|
373
|
-
- `ctx.call` rejects `APP_STOPPED` at once: a stopped package waits for the
|
|
374
|
-
user to start it in Package Center, so the SDK's stopped copy shows within a
|
|
375
|
-
page's next read instead of 30 s later (Download Hub 29.3 s; Reclaim
|
|
376
|
-
showed its old content or loading). `APP_STARTING` and
|
|
377
|
-
`EXECUTOR_STARTING` repeat for 4 s of waiting (0.5, 1, 2, 0.5 s), so a short
|
|
378
|
-
start still shows the page nothing and the SDK's starting copy follows a
|
|
379
|
-
longer one within its own 4 s recheck. `executor.control`, which the window's
|
|
380
|
-
approval starts the executor with, still repeats a start for 30 s; the SDK's
|
|
381
|
-
status reads are still not repeated.
|
|
382
|
-
繁中:套件停止時 `ctx.call` 立即回 `APP_STOPPED`;啟動中最多重試 4 s(`executor.control` 維持 30 s)。
|
|
383
|
-
|
|
384
|
-
### Behavior changes
|
|
385
|
-
|
|
386
|
-
- An App rebuilt with CLI 0.10.8 shows a stopped package's copy within its
|
|
387
|
-
page's next read: `ctx.call` rejects `APP_STOPPED` at once instead of after
|
|
388
|
-
about 30 s, and repeats `APP_STARTING` and `EXECUTOR_STARTING` for at most
|
|
389
|
-
about 4 s. The App's code needs no change; only its devDependency
|
|
390
|
-
`@synopackageland/cli` 0.10.8 and its lockfile, then a rebuild.
|
|
391
|
-
- An e2e test that waits only for the Gate's stopped title
|
|
392
|
-
(`authorization.stopped.title`) can miss it: `ExecutorApproval` now takes
|
|
393
|
-
over first and shows its own stopped copy. Accept either of the SDK's stopped
|
|
394
|
-
copies.
|
|
395
|
-
繁中:App 升到 CLI 0.10.8 重新 build 後,套件停止時頁面立即收到 `APP_STOPPED`(不再等 30 s),
|
|
396
|
-
啟動中最多重試約 4 s;App 不需改程式。E2E 若只等 Gate 的停止標題,應接受 SDK 的任一停止文案。
|
|
397
|
-
|
|
398
|
-
## 0.10.7 (2026-10-15)
|
|
399
|
-
|
|
400
|
-
Builds with SDK 0.10.7 and templates 0.10.8: `init` writes SDK v0.10.7 (Go
|
|
401
|
-
module, Rust crate tag and `backend.sdk`), `@synopackageland/sdk` 0.10.7 and
|
|
402
|
-
`@synopackageland/ui` 0.9.8. The executor digest table adds SDK 0.10.7, whose
|
|
403
|
-
executor and lifecycle digests equal 0.10.6, so an App rebuilt on it keeps its
|
|
404
|
-
approval unless its executor or policy changes. The CLI still needs SDK
|
|
405
|
-
0.10.5 or later: `ctx.portal.lastStatus()` is new and optional, SDK 0.10.7's
|
|
406
|
-
`PortalSettings` keeps its placeholder rows without it, and older SDKs do not
|
|
407
|
-
read it; nothing in the CLI depends on SDK 0.10.7. An App gets the settings
|
|
408
|
-
page without placeholder movement only with both SDK 0.10.7 and a DSM window
|
|
409
|
-
built by CLI 0.10.7.
|
|
410
|
-
|
|
411
|
-
繁中摘要:搭配 SDK 0.10.7、templates 0.10.8(UI 0.9.8);digest 與 0.10.6 相同;SDK 下限維持
|
|
412
|
-
0.10.5(`ctx.portal.lastStatus()` 是選用的新增,舊 SDK 不讀、SDK 0.10.7 沒有它就畫佔位列)。
|
|
413
|
-
e2e 新增 `openUntilLoaded`(`signIn` 遇 `net::ERR_ABORTED` 最多重開約 30 s)、遮蔽 socket.io `sid=`。
|
|
414
|
-
|
|
415
|
-
- `signIn` and `dsmLoginSetup` keep reopening DSM's login page while the
|
|
416
|
-
navigation fails with `net::ERR_ABORTED`, for up to about 30 s, after a saved
|
|
417
|
-
profile is refused (error 119); they then fail with a clear error. Any other
|
|
418
|
-
error still fails at once. The helper is exported as
|
|
419
|
-
`openUntilLoaded(app, path, {timeoutMs, pauseMs})`.
|
|
420
|
-
- e2e output and report masking also masks the `sid=` query parameter of DSM's
|
|
421
|
-
socket.io URLs, which carries the connection id.
|
|
422
|
-
- `ctx.portal` reads the portal status when the DSM window opens and keeps
|
|
423
|
-
the newest one it read (`lastStatus()`); a `status()` asked for while a read
|
|
424
|
-
runs shares it. The SDK's `PortalSettings` starts from it, so a settings
|
|
425
|
-
page no longer moves when its placeholder rows become the real section
|
|
426
|
-
(Reclaim: 100 px).
|
|
427
|
-
|
|
428
|
-
## 0.10.6 (2026-10-15)
|
|
429
|
-
|
|
430
|
-
Builds with SDK 0.10.6 and templates 0.10.7: `init` writes SDK v0.10.6 (Go
|
|
431
|
-
module, Rust crate tag and `backend.sdk`), `@synopackageland/sdk` 0.10.6 and
|
|
432
|
-
`@synopackageland/ui` 0.9.8, whose `CellText` takes `wrap`. Templates 0.10.6
|
|
433
|
-
was tagged but not published (a failing delegate frontend test); 0.10.7 is the
|
|
434
|
-
same templates with that test fixed. The executor digest table adds SDK 0.10.6,
|
|
435
|
-
whose executor and lifecycle digests equal 0.10.5, so an App rebuilt on it keeps
|
|
436
|
-
its approval unless its own root programs change. The CLI still needs SDK 0.10.5
|
|
437
|
-
or later: SDK 0.10.5's panels already read `executor_starting` as a starting
|
|
438
|
-
package and check again, and nothing in the CLI depends on SDK 0.10.6.
|
|
439
|
-
|
|
440
|
-
繁中摘要:搭配 SDK 0.10.6、templates 0.10.7(UI 0.9.8);templates 0.10.6 有 tag 但未發佈;
|
|
441
|
-
digest 與 0.10.5 相同;SDK 下限維持 0.10.5。e2e 新增 `openPath`、`handleDialogs`、80/443 通道。
|
|
442
|
-
|
|
443
|
-
- `signIn`, `openDesktop` and `openPortal` open their page once more when
|
|
444
|
-
the first navigation fails with `net::ERR_ABORTED`, which about one run in
|
|
445
|
-
ten met as DSM's desktop navigated on its own; any other
|
|
446
|
-
failure, or a second abort, still fails. The helper is exported as
|
|
447
|
-
`openPath(app, path)`.
|
|
448
|
-
- The DSM window's `status()` answers a pinned executor that reports
|
|
449
|
-
`state: "starting"` (its `root.start` step) at once, blocked with code
|
|
450
|
-
`executor_starting` and no approval offered, instead of waiting up to 75 s
|
|
451
|
-
for the step. The SDK's panels read that code as a starting package and
|
|
452
|
-
check again on their own, as they do `APP_STARTING` since CLI 0.10.5.
|
|
453
|
-
Approving and `control("start")` still wait for the step.
|
|
454
|
-
- `openApp(app, appId, timeout, browser)` and `openPortal(app, path, browser)`
|
|
455
|
-
take the test's `browser` fixture and accept native alert and confirm dialogs
|
|
456
|
-
through its `onDialog`, recording their text (`handleDialogs(browser)` returns
|
|
457
|
-
the list). DSM's `alert("You are not authorized to use this service.")` no
|
|
458
|
-
longer fails the test as an unhandled dialog. Without `browser` nothing
|
|
459
|
-
changes.
|
|
460
|
-
- `openPortal` registers the session's cookies as e2e secrets too (a portal
|
|
461
|
-
page may have no SynoToken, which is no failure); only `signIn` and
|
|
462
|
-
`openDesktop` did.
|
|
463
|
-
- `signIn` accepts a restored profile only when the desktop holds a SynoToken
|
|
464
|
-
and DSM's `/webman/login.cgi` still accepts the session (`dsmSessionLive`).
|
|
465
|
-
A profile with only the `stay_login` cookie, or an expired session (DSM error
|
|
466
|
-
119), now clears the cookies and signs in again with the account file's
|
|
467
|
-
password; the desktop alone used to be enough, and the app's CGIs then
|
|
468
|
-
answered "authorization unavailable".
|
|
469
|
-
- `runWithTunnel` also forwards the NAS's port 80 and 443 when
|
|
470
|
-
`DSM_E2E_TUNNEL_HTTP_PORT` and `DSM_E2E_TUNNEL_HTTPS_PORT` name local ports
|
|
471
|
-
(portal alias tests), and hands both to the command; the targets default to
|
|
472
|
-
80 and 443 (`DSM_E2E_REMOTE_HTTP_PORT`, `DSM_E2E_REMOTE_HTTPS_PORT`). Without
|
|
473
|
-
them the tunnel is unchanged.
|
|
474
|
-
|
|
475
|
-
## 0.10.5 (2026-10-15)
|
|
476
|
-
|
|
477
|
-
Builds with SDK 0.10.5 and templates 0.10.5: `init` writes SDK v0.10.5 (Go
|
|
478
|
-
module, Rust crate tag and `backend.sdk`), `@synopackageland/sdk` 0.10.5 and
|
|
479
|
-
`@synopackageland/ui` 0.9.7, whose `Space` aligns its items to the start. The
|
|
480
|
-
executor digest table adds SDK 0.10.5, whose executor and lifecycle digests
|
|
481
|
-
equal 0.10.4, so an App rebuilt on it keeps its approval unless its own root
|
|
482
|
-
programs change. New: the `@synopackageland/cli/e2e` module for real-NAS e2e
|
|
483
|
-
suites.
|
|
484
|
-
|
|
485
|
-
繁中摘要:搭配 SDK 0.10.5、templates 0.10.5(UI 0.9.7);需要 SDK 0.10.5 以上;
|
|
486
|
-
digest 與 0.10.4 相同;新增 `@synopackageland/cli/e2e`。
|
|
487
|
-
|
|
488
|
-
- **Incompatible:** the CLI needs SDK 0.10.5 or later. `check` and `build` refuse an App
|
|
489
|
-
whose backend requires SDK 0.10.3 or 0.10.4 (`SDK_UNSUPPORTED`, naming 0.10.5); raise
|
|
490
|
-
the Go module, Cargo tag or `backend.sdk` and the frontend's `@synopackageland/sdk` to
|
|
491
|
-
0.10.5. The DSM window now answers the SDK's status reads at once while the package is
|
|
492
|
-
stopped or starting, and only SDK 0.10.5's panels show that state and check again;
|
|
493
|
-
SDK 0.10.4's would show the package as needing approval.
|
|
494
|
-
|
|
495
|
-
繁中摘要:CLI 需要 SDK 0.10.5 以上;App 若仍用 SDK 0.10.3/0.10.4,`check`/`build` 會以
|
|
496
|
-
`SDK_UNSUPPORTED` 拒絕。DSM 視窗的 status 讀取不再替 App 重試,只有 SDK 0.10.5 的面板會自行重試。
|
|
497
|
-
- `@synopackageland/cli/e2e` (`src/e2e/dsm.ts`): DSM helpers for a package's
|
|
498
|
-
real-NAS suite on `e2e` 0.19 and `@e2e-dev/web` 0.14 (optional peers).
|
|
499
|
-
`dsmTarget`, `magpieAgent` (magpie GPT-6 Luna at max reasoning effort,
|
|
500
|
-
`E2E_LLM_*` override), `dsmLoginSetup` and `signIn` (a mode 600 saved profile,
|
|
501
|
-
restored while it still reaches the desktop), `openDesktop`, `openApp`,
|
|
502
|
-
`openPortal`, `dismissNotifications` and `runWithTunnel`
|
|
503
|
-
(`node dsm.js tunnel -- <command>`, an npm script such as `e2e:nas`). The file
|
|
504
|
-
is self-contained, so a package may copy it to `tests/e2e/support/dsm.ts`.
|
|
505
|
-
繁中:新增共用 DSM e2e 模組,App 可改為 import `@synopackageland/cli/e2e`。
|
|
506
|
-
- `runWithTunnel` opens the tunnel on a free loopback port unless
|
|
507
|
-
`DSM_E2E_TUNNEL_PORT` names one, so parallel runs do not collide on 15000.
|
|
508
|
-
- A saved DSM profile is reused by host, not port, and saved atomically, so
|
|
509
|
-
concurrent runs never leave it half written.
|
|
510
|
-
- `dismissNotifications` waits up to `DSM_E2E_NOTIFICATION_WAIT_MS` (default
|
|
511
|
-
5000) for the cards DSM shows after the desktop (the admin's "Admin account
|
|
512
|
-
security" card, about 2 s later on DSM 7.4) and matches DSM 7.4's container.
|
|
513
|
-
- `runWithTunnel` masks DSM's session cookies (`id`, `did`, `_SSID`),
|
|
514
|
-
`X-SYNO-TOKEN`, `SynoToken` and `_sid` as `***` in the command's stdout and
|
|
515
|
-
stderr and in the text files under `DSM_E2E_OUTPUT_DIR` (default `.e2e`), and
|
|
516
|
-
makes that directory private (directories 700, files 600). A Playwright call
|
|
517
|
-
log in a run error had carried the session cookie into `report.json` and the
|
|
518
|
-
run's output; e2e redacts only the secrets its config declares. Saved
|
|
519
|
-
sessions keep their cookies. `redactDsmSecrets` and `protectE2eOutput` are
|
|
520
|
-
exported for a package with its own runner. Before that, `signIn` and
|
|
521
|
-
`openDesktop` (and so `openApp`) register the session's cookies and
|
|
522
|
-
SynoToken as e2e secrets in the test's worker (`registerDsmSecrets`), so e2e
|
|
523
|
-
itself masks them in a run error, `report.json` and its output; e2e 0.19
|
|
524
|
-
keeps that ledger internal, so a later layout without it leaves the second
|
|
525
|
-
mask alone.
|
|
526
|
-
繁中:e2e 輸出與 log 遮蔽 DSM cookie/token,輸出目錄改為 700/600。
|
|
527
|
-
- `ctx.call` no longer repeats the SDK's status reads (`delegate.status`,
|
|
528
|
-
`authorization.status`, `executor.status`) while the package is stopped or
|
|
529
|
-
starting: they reject with the code at once, and SDK 0.10.5's panels show the
|
|
530
|
-
stopped or starting package and check again on their own. A page no longer
|
|
531
|
-
shows nothing for the first seconds after an upgrade (6.7 s in the regression test). Calls
|
|
532
|
-
that change something, approvals and controls among them, still repeat for up
|
|
533
|
-
to 30 s. `ctx.executor.status()` for a user who is not an administrator says
|
|
534
|
-
the package is stopped or starting instead of `admin_required`.
|
|
535
|
-
繁中:status 類讀取遇停止/啟動中立即回傳該碼,交給 SDK 重試;核准等呼叫維持重試。
|
|
536
|
-
|
|
537
|
-
## 0.10.4 (2026-10-14)
|
|
538
|
-
|
|
539
|
-
Builds with SDK 0.10.4 and templates 0.10.4: `init` writes SDK v0.10.4 (Go
|
|
540
|
-
module, Rust crate tag and `backend.sdk`), `@synopackageland/sdk` 0.10.4 and
|
|
541
|
-
`@synopackageland/ui` 0.9.6. `check` and `build` still accept SDK 0.10.3 or
|
|
542
|
-
later: nothing in this CLI needs 0.10.4, and an App on 0.10.3 never sees the
|
|
543
|
-
stop and start codes the window now repeats. The executor digest table adds
|
|
544
|
-
SDK 0.10.4, whose executor and lifecycle digests equal 0.10.3, so an App
|
|
545
|
-
rebuilt on it keeps its approval unless its own root programs change. The
|
|
546
|
-
gate refuses a stale SDK `ts/dist` and builds the executor flow's race binary
|
|
547
|
-
before its timeout.
|
|
548
|
-
|
|
549
|
-
繁中摘要:使用 SDK 0.10.4 與 templates 0.10.4(UI 0.9.6);`check`/`build` 仍接受 SDK
|
|
550
|
-
0.10.3 以上。`ctx.call` 自動重試套件停止/啟動中的碼;非管理員的
|
|
551
|
-
`ctx.executor.status()` 可讀到已核准的 executor。digest 表新增 SDK 0.10.4(與 0.10.3
|
|
552
|
-
相同),重建的 App 不需重新核准(除非自己的 root 程式改變)。
|
|
553
|
-
|
|
554
|
-
- `ctx.call` repeats a call the package refused with `APP_STOPPED`,
|
|
555
|
-
`APP_STARTING` or `EXECUTOR_STARTING` (the executor op was not sent): after
|
|
556
|
-
0.5 s, doubling to at most 8 s, for 30 s of waiting in all, so an App comes
|
|
557
|
-
back by itself once the package has started. Other codes reject at once; past
|
|
558
|
-
the budget the last refusal rejects; leaving the page cancels the wait.
|
|
559
|
-
繁中:套件停止/啟動中時 `ctx.call` 自動有界重試(最多等 30 s)。
|
|
560
|
-
- The window approval of an upgrade (outdated tasks) makes 11 scheduler calls
|
|
561
|
-
instead of 12: the outdated boot task is deleted by the approval's own first
|
|
562
|
-
EventScheduler get, made moments before the password, instead of a second
|
|
563
|
-
get (2.9 s on the test NAS in the regression test). The control task is still read again by id
|
|
564
|
-
before its delete (spec/scheduler/v1). A fresh approval stays at 8.
|
|
565
|
-
繁中:升級核准的排程呼叫由 12 降為 11(boot 任務不再於刪除前重讀)。
|
|
566
|
-
- A scope approval reads the executor's selection back every second at most
|
|
567
|
-
(it backed off to 2 s), so the window sees the landed scope within a second
|
|
568
|
-
of `scope.confirm` (the Dialog closed 4.8 s after it in the regression test). Removing
|
|
569
|
-
the temporary selection task still lists Task Scheduler first, as
|
|
570
|
-
spec/scheduler/v1 requires of a delete.
|
|
571
|
-
繁中:範圍核准讀回間隔上限 2 s → 1 s,confirmed 後 1 s 內看到結果。
|
|
572
|
-
- `ctx.executor.status()` for a user who is not an administrator asks the
|
|
573
|
-
App's `executor.status` (open to every signed-in user) instead of refusing
|
|
574
|
-
before any request: the pinned, running executor reads `ready`; anything
|
|
575
|
-
else stays `blocked` with `admin_required`. Task Scheduler is still read only
|
|
576
|
-
for administrators. A user no longer sees an approved executor as waiting
|
|
577
|
-
for approval.
|
|
578
|
-
繁中:非管理員的 `ctx.executor.status()` 會向 App 的 `executor.status` 詢問,已核准且
|
|
579
|
-
執行中即為 `ready`,不再一律回 `admin_required`。
|
|
580
|
-
|
|
581
|
-
## 0.10.3 (2026-10-14)
|
|
582
|
-
|
|
583
|
-
Builds with SDK 0.10.3 and templates 0.10.3: `init` writes SDK v0.10.3 (Go
|
|
584
|
-
module, Rust crate tag and `backend.sdk`), `@synopackageland/sdk` 0.10.3 and
|
|
585
|
-
`@synopackageland/ui` 0.9.5. **Incompatible:** `check` and `build` need SDK
|
|
586
|
-
0.10.3 or later. The executor digest table adds SDK 0.10.3 and keeps 0.10.0
|
|
587
|
-
to 0.10.2, so `inspect` still recognizes their SPKs. SDK 0.10.3's executor
|
|
588
|
-
records the package version at every start, so an App rebuilt on it carries
|
|
589
|
-
a new executor digest; when its policy digest does not change, the upgrade
|
|
590
|
-
puts the new executor in place without approval. An App that declares
|
|
591
|
-
`root.start` changes its policy and is approved again. The lifecycle digests
|
|
592
|
-
equal 0.10.2.
|
|
593
|
-
|
|
594
|
-
繁中摘要:使用 SDK 0.10.3 與 templates 0.10.3(UI 0.9.5);`check`/`build` 需要 SDK
|
|
595
|
-
0.10.3 以上(不相容)。digest 表新增 SDK 0.10.3(保留 0.10.0~0.10.2)。policy digest
|
|
596
|
-
不變的 App 升級時自動換 executor;宣告 `root.start` 的 App 需要重新核准。lifecycle
|
|
597
|
-
digest 與 0.10.2 相同。
|
|
598
|
-
|
|
599
|
-
### Added
|
|
600
|
-
|
|
601
|
-
- `root.start` in dsm-package.yaml names a `root/` program as the executor's start step: the
|
|
602
|
-
executor runs it as root once at the first start after each install or upgrade (`install`,
|
|
603
|
-
or `upgrade` and the previous version), only while the approval is live, for at most 60
|
|
604
|
-
seconds, and a failure never blocks the start. `build` writes it into the policy as `start`;
|
|
605
|
-
`check` refuses a name outside `root/` and a program that also declares `run` or `job`
|
|
606
|
-
(`STANDALONE_ROOT_PROGRAMS_INVALID`); the SDK executor's `check-policy` checks the rest.
|
|
607
|
-
`inspect` lists the root steps. Declaring it changes the policy digest, so the App needs
|
|
608
|
-
approval again; Apps without it keep their policy.
|
|
609
|
-
|
|
610
|
-
繁中摘要:`root.start` 指定一個 root 程式,executor 在每次安裝或升級後第一次啟動時以 root 執行一次;
|
|
611
|
-
失敗只記 log、不擋啟動。宣告後 policy digest 改變需重新核准,沒有宣告的 App 不受影響。
|
|
612
|
-
|
|
613
|
-
- Lifecycle scripts: a project's `dsm-scripts/<DSM script name>` (`preinst`, `postinst`,
|
|
614
|
-
`preupgrade`, `postupgrade`, `preuninst`, `postuninst`, `start-stop-status`) is packed as
|
|
615
|
-
`scripts/app/<name>` and called from the generated script of the same name: after the SDK
|
|
616
|
-
steps, and before them for `preupgrade`, `preuninst` and `stop`. It runs as the package
|
|
617
|
-
account with DSM's arguments, environment and exit codes; a failed App `start` stops the SDK
|
|
618
|
-
again. Native and Compose projects. `check` refuses other names (`APP_SCRIPT_UNKNOWN`),
|
|
619
|
-
non-executable files and files without `#!`; `inspect` lists the App scripts. Projects
|
|
620
|
-
without `dsm-scripts/` build unchanged. Guide: `synopkgland skill show lifecycle`.
|
|
621
|
-
|
|
622
|
-
繁中摘要:專案 `dsm-scripts/` 下以 DSM 原生檔名放的腳本會被打包,並在 CLI 產生的同名腳本中於
|
|
623
|
-
SDK 步驟之後(preupgrade/preuninst/stop 在之前)以套件帳號執行;沒有該資料夾時行為不變。
|
|
624
|
-
|
|
625
|
-
- Login Portal style: a portal App's launcher now carries DSM's `loginStyle` and `loginIcon`,
|
|
626
|
-
so Control Panel > Login Portal > Applications shows a thumbnail instead of a blank box, and
|
|
627
|
-
the alias login page gets a wallpaper, a button colour and the App icon. The CLI ships a
|
|
628
|
-
neutral default (`assets/login-style/`); `login_style` in dsm-package.yaml overrides
|
|
629
|
-
`color`, `wallpaper` with `wallpaper_thumbnail`, and `title`. `check` validates the images
|
|
630
|
-
(`STANDALONE_LOGIN_STYLE_INVALID`, `STANDALONE_LOGIN_STYLE_IMAGE_INVALID`) and prints the
|
|
631
|
-
style; `inspect` prints it and flags a portal SPK without one (`LOGIN_STYLE_MISSING`).
|
|
632
|
-
Rebuilding an existing portal App with this CLI adds the default; no change to the project.
|
|
633
|
-
|
|
634
|
-
繁中摘要:有 portal 的 App 重新 build 後會自動帶入預設登入樣式,「登入入口 › 應用程式」縮圖不再
|
|
635
|
-
空白,別名登入頁有桌布、按鈕色與 App icon;可用 `login_style` 換主色、桌布與標題圖。
|
|
636
|
-
|
|
637
|
-
### Changed
|
|
638
|
-
|
|
639
|
-
- **Incompatible:** the CLI needs SDK 0.10.3 or later. `check` and `build` refuse an App
|
|
640
|
-
whose backend requires SDK 0.10.0, 0.10.1 or 0.10.2 (`SDK_UNSUPPORTED`, naming 0.10.3);
|
|
641
|
-
raise the Go module, Cargo tag or `backend.sdk` and the frontend's
|
|
642
|
-
`@synopackageland/sdk` to 0.10.3. The CLI no longer carries the fallbacks for those
|
|
643
|
-
releases: the pre-`timeouts.json` timeouts, skipping `executor check-policy` for an SDK
|
|
644
|
-
without it, and `EXECUTOR_START_STEP_UNSUPPORTED`.
|
|
645
|
-
|
|
646
|
-
繁中摘要:CLI 需要 SDK 0.10.3 以上;App 若仍用 SDK 0.10.0~0.10.2,`check`/`build` 會以
|
|
647
|
-
`SDK_UNSUPPORTED` 拒絕。移除為舊版保留的逾時退回值、check-policy 略過與 start 步驟檢查。
|
|
648
|
-
|
|
649
|
-
- `check` and `build` refuse a request deadline that ends before a root program `root.run`
|
|
650
|
-
may run would answer (`STANDALONE_REQUEST_TIMEOUT_SHORT`): `backend.timeout_seconds`
|
|
651
|
-
(60 by default) must be at least the program's `run.timeout_s` (20 by default) + 20, the
|
|
652
|
-
executor's 10 seconds and its client's 10 (SDK `spec/protocol/v1`, Timeouts). The default
|
|
653
|
-
covers programs of up to 40 seconds; a 120-second program needs `timeout_seconds: 140`.
|
|
654
|
-
A program with only `job`, `start` or `stop` is not affected.
|
|
655
|
-
- The request default, the window's wait past the request deadline and the `root.run`
|
|
656
|
-
deadline check read their values from the App's SDK, `spec/protocol/v1/timeouts.json`,
|
|
657
|
-
instead of the CLI's own copies, so they follow the SDK the App builds with. An App
|
|
658
|
-
without the SDK keeps 60 seconds, 2 seconds, and a `run.timeout_s` of 20 + 20. The
|
|
659
|
-
generated values do not change with SDK 0.10.3.
|
|
660
|
-
|
|
661
|
-
繁中摘要:request 預設逾時、視窗多等的時間與 root.run 逾時檢查改讀 App 所用 SDK 的
|
|
662
|
-
timeouts.json,不再用 CLI 手抄的值;沒有 SDK 的 App 沿用 60 秒、2 秒、20 + 20。
|
|
663
|
-
- The DSM window's approval and `control start` wait for an executor that answers
|
|
664
|
-
`state: "starting"` while it runs its start step, for up to 75 seconds, instead of giving
|
|
665
|
-
up after 30 seconds; past that the result is blocked with code `executor_starting`, and the
|
|
666
|
-
plain-UI panel and the SDK settings say the service is still starting. The plain-UI panel
|
|
667
|
-
says it is waiting for the background service while a request runs.
|
|
668
|
-
|
|
669
|
-
繁中摘要:核准與 control start 會等待回報「starting」的 executor(最多 75 秒),超過則以
|
|
670
|
-
`executor_starting` 阻擋並說明仍在啟動。
|
|
671
|
-
|
|
672
|
-
- The DSM window's approval asks DSM's schedulers 8 times instead of 15, following the SDK's
|
|
673
|
-
`spec/scheduler/v1`. The boot task is read with one EventScheduler `get` by its name
|
|
674
|
-
(DSM keeps event task names unique) and never listed; Task Scheduler is listed once before
|
|
675
|
-
and once after the writes, and the control task is then read by its listed id. A step reads
|
|
676
|
-
each task once and reuses that read; a delete still reads the task again first. After the
|
|
677
|
-
boot task runs, only `executor.status` is asked: the tasks were read back exactly just
|
|
678
|
-
before, and the executor's pins answer for the rest. `executor.status` is asked every
|
|
679
|
-
500 ms for the first 4 seconds, then backs off to 2 seconds. `status` (and `check`) gets the
|
|
680
|
-
boot task by name instead of listing EventScheduler. Measured on a DSM 7.4 x86_64 NAS with
|
|
681
|
-
a fresh install: ready came 1.1-4.9 s after the boot task ran instead of 6.3-10.9 s, and
|
|
682
|
-
10.1-21.8 s after Approve instead of 16.3-26.9 s (DSM's scheduler calls vary by seconds).
|
|
683
|
-
|
|
684
|
-
繁中摘要:視窗核准對 DSM 排程 API 的呼叫從 15 次降為 8 次:boot 任務改用名稱 get、不再 list
|
|
685
|
-
EventScheduler;Task Scheduler 在寫入前後各 list 一次,之後用 id get;執行 boot 任務後只問
|
|
686
|
-
`executor.status`,前 4 秒每 500 ms 問一次。安全檢查(重複、內容逐字比對、pins)都保留。
|
|
687
|
-
|
|
688
|
-
### Fixed
|
|
689
|
-
|
|
690
|
-
- The DSM window's `openFileManager` and `revealFile` take a `/volumeN/...` path as the SDK's
|
|
691
|
-
`fileStationPath` does: a DSM volume mount (`/volumeN`, `/volumeUSBN`, `/volumeSATAN`) is
|
|
692
|
-
stripped instead of refused, and the reveal recovery follows the path File Station got.
|
|
693
|
-
Anything but one canonical shared-folder path is still `invalid-input`.
|
|
694
|
-
- Executor approval results carry a structured `code` beside the English `reason`, and an
|
|
695
|
-
`outcome` when the approval rolled back: a refused administrator password is
|
|
696
|
-
`password_rejected` (DSM 3121), other PasswordConfirm refusals `password_required`,
|
|
697
|
-
`session_ended` or `password_confirm_failed`; scheduler, task and executor failures have
|
|
698
|
-
codes of their own (`scheduler_denied`, `task_missing`, `executor_unreachable`, …) and the
|
|
699
|
-
outcomes are `restored`, `withdrawn`, `restore_failed` and `withdraw_failed`. The SDK's
|
|
700
|
-
`ExecutorSettings` reads `code`. The plain-UI window panel now shows the code and outcome in
|
|
701
|
-
the DSM language, followed by the DSM code (`dsm_3121`), instead of the English reason.
|
|
702
|
-
Rebuild the App to pick this up.
|
|
703
|
-
|
|
704
|
-
繁中摘要:核准結果新增結構化 `code`(例如 `password_rejected`)與回復結果 `outcome`,`reason`
|
|
705
|
-
仍保留英文細節;純 UI 視窗面板改以 DSM 語系顯示原因,不再直接顯示英文;需重新 build App。
|
|
706
|
-
|
|
707
|
-
- Executor approval: a scheduler write that fails partway no longer leaves the earlier
|
|
708
|
-
approval half deleted. The approval stops at the first failed write, withdraws the tasks
|
|
709
|
-
it created and recreates the earlier boot and control tasks it removed, then offers
|
|
710
|
-
approval again. DSM cannot hold two same-named tasks, so the old task is still deleted
|
|
711
|
-
before its replacement is created. When the rollback itself fails, the window says so, and
|
|
712
|
-
the next approval converges from what is left. A DSM session that ended (`dsm_106`,
|
|
713
|
-
`dsm_107`, `dsm_119`) asks the administrator to sign in to DSM again.
|
|
714
|
-
|
|
715
|
-
繁中摘要:核准半途寫入失敗時,會撤回這次建立的排程並重建先前核准的舊排程,再提供重新核准;
|
|
716
|
-
還原失敗時會明白說明,下次核准可自動收斂。DSM session 失效時提示重新登入。
|
|
717
|
-
|
|
718
|
-
- An App opened through its Application Portal alias (`https://nas/<alias>/`) reaches its
|
|
719
|
-
backend again. The generated window posted `ctx.call` and `ctx.files` to the absolute
|
|
720
|
-
`/webman/3rdparty/<package>/cgi/api.cgi`, which DSM answers with 403 on the alias, so every
|
|
721
|
-
call failed with `bad_response` and an approved executor read as unavailable. The path is
|
|
722
|
-
now relative to the page, as the App's own assets are; the DSM desktop resolves it to the
|
|
723
|
-
same URL as before. Rebuild the App to pick this up.
|
|
724
|
-
|
|
725
|
-
繁中摘要:從應用程式入口別名網址開啟 App 時,`ctx.call`/`ctx.files` 改用相對路徑,不再被
|
|
726
|
-
DSM 以 403 拒絕(原本顯示 `bad_response`、已核准的 executor 顯示無法使用);需重新 build App。
|
|
727
|
-
|
|
728
|
-
- `check` and `build` refusing a `root.start`, `root.stop` or `uninstall.purge` program that
|
|
729
|
-
also declares `run` or `job` (`EXECUTOR_POLICY_REJECTED`) now say what to do: give the step
|
|
730
|
-
another program name in `root.programs`, one without `run` or `job`.
|
|
731
|
-
|
|
732
|
-
繁中摘要:start/stop/purge 的 program 同時宣告 run/job 而被拒時,提示改用另一個沒有
|
|
733
|
-
run/job 的 program 名稱。
|
|
734
|
-
|
|
735
|
-
- `init` and `build` of a Python App whose SDK has no Python SDK (`python/synopkgland_app`)
|
|
736
|
-
report `STANDALONE_PYTHON_SDK_MISSING` with the path, instead of a bare `ENOENT`.
|
|
737
|
-
|
|
738
|
-
繁中摘要:找不到 Python SDK 時改回專屬錯誤碼 `STANDALONE_PYTHON_SDK_MISSING`,不再是 `ENOENT`。
|
|
739
|
-
|
|
740
|
-
### Removed
|
|
741
|
-
|
|
742
|
-
- `@synopackageland/cli/authorization-sdk` is gone: `ROOT_RUNTIME` and
|
|
743
|
-
`AUTHORIZATION_RUNTIME`, the window runtimes of a native product with its own pinned root
|
|
744
|
-
tasks, ship unchanged in `@synopackageland/sdk/native`. A native product imports them from
|
|
745
|
-
the SDK; generated Apps are not affected.
|
|
746
|
-
|
|
747
|
-
繁中摘要:native 產品的 root/authorization 視窗 runtime 改由 SDK(`@synopackageland/sdk/native`)提供,
|
|
748
|
-
CLI 不再匯出 `authorization-sdk`;一般產生的 App 不受影響。
|
|
749
|
-
|
|
750
|
-
- The CLI's copy of the Application Portal panel text (19 keys in 9 languages) is gone:
|
|
751
|
-
`build` reads it from the App's SDK (`ts/i18n/portal/<locale>.json`, in every SDK 0.10.x),
|
|
752
|
-
the same text the SDK's `PortalSettings` shows. The built window is unchanged; a fix to the
|
|
753
|
-
text reaches an App with its next SDK.
|
|
754
|
-
|
|
755
|
-
繁中摘要:Application Portal 面板文案改從 App 的 SDK 讀取,CLI 不再保留一份;建出的視窗不變,文案修正隨 SDK 更新。
|
|
756
|
-
|
|
757
|
-
- `dist/runtime/delegate-contract.js` keeps only the operation names the build checks; the
|
|
758
|
-
background-save DTOs, route table and limits, which nothing in the CLI used, and the frozen
|
|
759
|
-
v1 vector now live only in the SDK (`ts/src/delegate/long-running.ts`).
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
## 0.10.2 (2026-10-14)
|
|
763
|
-
|
|
764
|
-
First release of the changelog. `@synopackageland/cli` (`synopkgland`)
|
|
765
|
-
builds Synology DSM 7 packages (SPK) from a template, checks them, and
|
|
766
|
-
installs them on a NAS. It builds with SDK 0.10.2 and templates 0.10.2.
|
|
767
|
-
|
|
768
|
-
繁中摘要:`synopkgland` 從模板建立 DSM 7 套件(SPK),檢查、打包並安裝到
|
|
769
|
-
NAS;搭配 SDK 0.10.2 與 templates 0.10.2。
|
|
770
|
-
|
|
771
|
-
### Templates
|
|
772
|
-
|
|
773
|
-
- `native-go`: a Go backend with a Vue UI (or `--ui plain`).
|
|
774
|
-
- `native-python`, `native-node`, `native-rust`: the same App with a Python,
|
|
775
|
-
Node.js (TypeScript) or Rust backend behind the SDK's Go runtime.
|
|
776
|
-
- `binary`: a static Linux program you build yourself.
|
|
777
|
-
- `compose`: an existing Docker Compose app (`--from compose.yaml`).
|
|
778
|
-
- Existing native products keep their own payload layout with
|
|
779
|
-
`backend: {kind: native}`.
|
|
780
|
-
|
|
781
|
-
### Capabilities
|
|
782
|
-
|
|
783
|
-
`init --with …` or `add` adds `files`, `jobs`, `login`, `delegate`,
|
|
784
|
-
`root-ops` and `portal`. `delegate` and `root-ops` run through the SDK's
|
|
785
|
-
executor, which an administrator approves once by digest; `check` and
|
|
786
|
-
`build` have the App's executor validate its policy first
|
|
787
|
-
(`EXECUTOR_POLICY_REJECTED`).
|
|
788
|
-
|
|
789
|
-
### Commands
|
|
790
|
-
|
|
791
|
-
- `init`, `add`: create a project and add capabilities.
|
|
792
|
-
- `check`, `build`: validate the manifest and build the SPK for one or more
|
|
793
|
-
architectures, with the executor checked against the digests shipped in the
|
|
794
|
-
CLI.
|
|
795
|
-
- `inspect`: check any SPK against the DSM 7 package format without
|
|
796
|
-
installing it.
|
|
797
|
-
- `deploy`, `status`, `logs`: install on a NAS and read its state.
|
|
798
|
-
- `dev`, `test`, `images`: run, test and pin images for Compose projects.
|
|
799
|
-
- `skill`: the bundled guidance for AI assistants.
|
|
800
|
-
|
|
801
|
-
`--json` prints one JSON object on stdout; failures carry a stable `code`
|
|
802
|
-
and a `hint`.
|
|
5
|
+
- Attribute upstream Apps to their original project/team or owner and the packaging publisher as distributor, with generic skill guidance and a release checklist
|
|
6
|
+
- Prefill upstream-fork attribution from the upstream repository and publisher options or environment configuration; use a bounded public GitHub owner lookup and explicit TODOs offline
|
|
7
|
+
- Warn when upstream attribution is incomplete or the maintainer equals the distributor; warnings appear in check JSON and keep exit status successful
|
|
8
|
+
- Keep templates 0.31.x and its SDK defaults; CLI minor releases can ship independently of templates
|
package/README.md
CHANGED
|
@@ -29,6 +29,14 @@ synopkgland status --host my-nas --json
|
|
|
29
29
|
`deploy --dry-run` prints the deployment plan without connecting to a NAS. You can also install
|
|
30
30
|
the SPK with Package Center's Manual Install.
|
|
31
31
|
|
|
32
|
+
When packaging someone else's open-source App, name its original project/team
|
|
33
|
+
(or owner display name, then login) as maintainer and yourself as distributor.
|
|
34
|
+
Use `init --upstream-fork --upstream <repo-url> --publisher <name> --publisher-url <url>`;
|
|
35
|
+
`--upstream-maintainer` records a verified project/team name. Publisher defaults
|
|
36
|
+
come from `SYNOPKGLAND_PUBLISHER` / `SYNOPKGLAND_PUBLISHER_URL`. Offline lookups
|
|
37
|
+
leave TODOs; `check --json` reports attribution warnings without failing.
|
|
38
|
+
See the [upstream scaffold and release checklist](skills/reference/upstream-fork.md).
|
|
39
|
+
|
|
32
40
|
## Templates
|
|
33
41
|
|
|
34
42
|
| Template | Use it for | Manifest |
|
|
@@ -62,12 +70,12 @@ alongside npm lockfiles. Do not disable checksum verification for public SDK
|
|
|
62
70
|
packages. Private mirrors can use explicitly configured Go authentication and
|
|
63
71
|
checksum settings; a failed fetch reports `SDK_DOWNLOAD_FAILED`.
|
|
64
72
|
|
|
65
|
-
CLI-only
|
|
73
|
+
CLI-only releases can differ from the SDK patch. Compose import and SDK defaults
|
|
66
74
|
read the SDK pin from the installed templates; explicit App SDK declarations take precedence.
|
|
67
75
|
|
|
68
76
|
`init` and `add` read their templates from the locally installed
|
|
69
|
-
`@synopackageland/templates`. CLI 0.
|
|
70
|
-
update can select the latest templates patch in the 0.
|
|
77
|
+
`@synopackageland/templates`. CLI 0.32.0 depends on `~0.31.0`: npm installation or
|
|
78
|
+
update can select the latest templates patch in the 0.31 minor line. Templates
|
|
71
79
|
patches need only a templates release; update the npm installation to receive them.
|
|
72
80
|
The CLI never fetches templates at runtime, so offline use works after installation;
|
|
73
81
|
commit a lockfile and use `npm ci` to reproduce a chosen dependency tree.
|
package/dist/cli.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { upstreamRepository, upstreamMaintainer } from './upstream-attribution.js';
|
|
1
2
|
import { Command, CommanderError } from "commander";
|
|
2
3
|
import { existsSync, readFileSync, renameSync, statSync } from "node:fs";
|
|
3
4
|
import { createHash } from "node:crypto";
|
|
@@ -324,6 +325,8 @@ export async function runCli(argv) {
|
|
|
324
325
|
throw failure(validation.errors[0].code, formatErrors(validation.errors), validation.errors[0].suggestion);
|
|
325
326
|
const standalone = standaloneRoot(rootOf(command));
|
|
326
327
|
if (standalone) {
|
|
328
|
+
if (validation.warnings?.length)
|
|
329
|
+
console.error(formatErrors(validation.warnings));
|
|
327
330
|
const loaded = isNativeLayout(standalone)
|
|
328
331
|
? loadNativeLayout(standalone)
|
|
329
332
|
: loadStandaloneManifest(standalone);
|
|
@@ -348,6 +351,7 @@ export async function runCli(argv) {
|
|
|
348
351
|
: undefined;
|
|
349
352
|
emit("check", {
|
|
350
353
|
package: loaded.manifest.package,
|
|
354
|
+
warnings: validation.warnings ?? [],
|
|
351
355
|
...("installSettings" in loaded.manifest && loaded.manifest.installSettings ? { installSettings: loaded.manifest.installSettings } : {}),
|
|
352
356
|
...("identityGateway" in loaded.manifest && gatewayAdmissionReport(loaded.manifest.identityGateway, loaded.manifest.entry) ? { identityGateway: gatewayAdmissionReport(loaded.manifest.identityGateway, loaded.manifest.entry) } : {}),
|
|
353
357
|
capabilities: "capabilities" in loaded.manifest
|
|
@@ -442,6 +446,10 @@ export async function runCli(argv) {
|
|
|
442
446
|
.option("--package <id>", "INFO.package (defaults to the directory name)")
|
|
443
447
|
.option("--name <display>", "Display name")
|
|
444
448
|
.option("--upstream-image <repository>", "compose fork: official image repository; upgrade pins its matching tag and index digest")
|
|
449
|
+
.option("--upstream <url>", "Original upstream repository URL (defaults to the upstream Git remote)")
|
|
450
|
+
.option("--upstream-maintainer <name>", "Verified original project/team name; otherwise resolve the GitHub owner")
|
|
451
|
+
.option("--publisher <name>", "Your distributor name (or SYNOPKGLAND_PUBLISHER)")
|
|
452
|
+
.option("--publisher-url <url>", "Your distributor URL (or SYNOPKGLAND_PUBLISHER_URL)")
|
|
445
453
|
.option("--upstream-fork", "Create only synology/ inside an upstream source fork (compose or native-go)")
|
|
446
454
|
.option("--health-path <path>", "compose: actual readiness endpoint; redirects are not followed")
|
|
447
455
|
.option("--health-status <status>", "compose: expected 2xx readiness status (no default)", Number)
|
|
@@ -455,7 +463,7 @@ export async function runCli(argv) {
|
|
|
455
463
|
.option("--min-dsm <version>", `Minimum DSM version (native templates and binary default to ${DEFAULT_MIN_DSM}, compose to ${CONTAINER_MIN_DSM})`)
|
|
456
464
|
.argument("[dir]", "Target directory", ".")
|
|
457
465
|
.addHelpText("after", "\nNative projects: native-go, native-python, native-node, native-rust and binary use dsm-package.yaml schema 2.\nCompose projects: compose uses dsm-package.yaml schema 2; --from imports compose.yaml.\nQuick start: synopkgland init -t native-go --with files,jobs,login my-app\n cd my-app && synopkgland build\n")
|
|
458
|
-
.action((dir, options, command) => {
|
|
466
|
+
.action(async (dir, options, command) => {
|
|
459
467
|
if (command.parent?.opts().project)
|
|
460
468
|
throw failure("CLI_OPTION_INVALID", "--project does not apply to init.");
|
|
461
469
|
if (!options.template)
|
|
@@ -463,7 +471,16 @@ export async function runCli(argv) {
|
|
|
463
471
|
if (!isTemplateName(options.template))
|
|
464
472
|
throw failure("INIT_TEMPLATE_UNKNOWN", `Unknown template: ${options.template}`);
|
|
465
473
|
const targetDir = resolve(dir);
|
|
474
|
+
const upstream = options.upstreamFork ? upstreamRepository(targetDir, options.upstream) : undefined;
|
|
475
|
+
if (options.upstream && !upstream)
|
|
476
|
+
throw failure("INIT_UPSTREAM_INVALID", "Supply an http(s) repository URL without credentials");
|
|
477
|
+
if (!options.upstreamFork && (options.upstream || options.upstreamMaintainer || options.publisher || options.publisherUrl))
|
|
478
|
+
throw failure("INIT_OPTIONS_UNSUPPORTED", "Attribution options require --upstream-fork");
|
|
466
479
|
initFromTemplate(options.template, targetDir, {
|
|
480
|
+
upstream,
|
|
481
|
+
upstreamMaintainer: options.upstreamMaintainer ?? (options.upstreamFork ? await upstreamMaintainer(upstream) : undefined),
|
|
482
|
+
publisher: options.publisher ?? process.env.SYNOPKGLAND_PUBLISHER,
|
|
483
|
+
publisherUrl: options.publisherUrl ?? process.env.SYNOPKGLAND_PUBLISHER_URL,
|
|
467
484
|
upstreamFork: options.upstreamFork,
|
|
468
485
|
upstreamImage: options.upstreamImage,
|
|
469
486
|
healthPath: options.healthPath,
|
package/dist/error-registry.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { COMPOSE_ERRORS } from "./standalone/compose-errors.js";
|
|
2
2
|
export const ERROR_REGISTRY = {
|
|
3
3
|
...COMPOSE_ERRORS,
|
|
4
|
+
INIT_UPSTREAM_INVALID: { code: "INIT_UPSTREAM_INVALID", description: "The upstream repository URL is invalid.", suggestion: "Supply --upstream with an http(s) repository URL without credentials." },
|
|
5
|
+
INIT_PUBLISHER_INVALID: { code: "INIT_PUBLISHER_INVALID", description: "The attribution name or publisher URL is invalid.", suggestion: "Use plain single-line project/publisher names and an http(s) publisher URL without credentials." },
|
|
6
|
+
UPSTREAM_ATTRIBUTION: { code: "UPSTREAM_ATTRIBUTION", description: "Upstream App attribution is incomplete or names the distributor as maintainer.", suggestion: "Name the original project/team or owner as maintainer; set metadata.maintainer_url to the upstream repository and metadata.distributor/distributor_url to your publisher; resolve TODOs before release." },
|
|
4
7
|
INSTALL_SETTINGS_INVALID: { "code": "INSTALL_SETTINGS_INVALID", "description": "The installation setting declaration is invalid.", "suggestion": "Declare 1–32 lowercase identifier keys in install.settings, each with type https-origin, a plain label and an explicit boolean required; omit defaults and values." },
|
|
5
8
|
SDK_INSTALL_SETTINGS_UNSUPPORTED: { "code": "SDK_INSTALL_SETTINGS_UNSUPPORTED", "description": "The selected SDK does not provide native installation settings.", "suggestion": "Pin SDK 0.24.0 or a matching supported release with installsettings/cmd/control, then rebuild with the matching CLI." },
|
|
6
9
|
SDK_INSTALL_SETTINGS_BUILD_FAILED: { "code": "SDK_INSTALL_SETTINGS_BUILD_FAILED", "description": "The SDK installation settings controller could not be built.", "suggestion": "Install the pinned Go toolchain, inspect the compiler diagnostics and rebuild with a complete matching SDK release." },
|
package/dist/init-upstream.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export interface ForkRecipeOptions {
|
|
2
2
|
upstreamImage?: string;
|
|
3
3
|
from?: string;
|
|
4
|
+
upstream?: string;
|
|
5
|
+
upstreamMaintainer?: string;
|
|
6
|
+
publisher?: string;
|
|
7
|
+
publisherUrl?: string;
|
|
4
8
|
}
|
|
5
9
|
export declare function validateForkRecipe(template: 'compose' | 'native-go', options: ForkRecipeOptions): void;
|
|
6
10
|
/** CLI-owned packaging recipe; upstream files and history stay untouched. */
|
package/dist/init-upstream.js
CHANGED
|
@@ -3,8 +3,17 @@ import { join } from 'node:path';
|
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import { parseDocument } from 'yaml';
|
|
5
5
|
import { API_PERMISSIONS_FILE } from './standalone/api-permissions.js';
|
|
6
|
+
import { safeMetadataUrl } from './package-metadata.js';
|
|
6
7
|
import { parseImageReference } from './images/pin.js';
|
|
7
8
|
export function validateForkRecipe(template, options) {
|
|
9
|
+
if (options.upstream && !safeMetadataUrl(options.upstream))
|
|
10
|
+
throw new Error('[INIT_UPSTREAM_INVALID] Supply an http(s) upstream repository URL without credentials.');
|
|
11
|
+
if (options.publisherUrl && !safeMetadataUrl(options.publisherUrl))
|
|
12
|
+
throw new Error('[INIT_PUBLISHER_INVALID] Supply an http(s) publisher URL without credentials.');
|
|
13
|
+
for (const value of [options.publisher, options.upstreamMaintainer]) {
|
|
14
|
+
if (value !== undefined && (!value.trim() || /[\x00-\x1f\x7f"\\]/.test(value) || value.length > 200))
|
|
15
|
+
throw new Error('[INIT_PUBLISHER_INVALID] Attribution names must be plain, non-empty single-line text.');
|
|
16
|
+
}
|
|
8
17
|
if (template === 'native-go' && options.upstreamImage)
|
|
9
18
|
throw new Error('[INIT_OPTIONS_UNSUPPORTED] Native forks stage official release binaries or use a source build hook; image options apply only to compose.');
|
|
10
19
|
if (template !== 'compose')
|
|
@@ -28,6 +37,14 @@ export function writeForkScaffold(packaging, template, options) {
|
|
|
28
37
|
? { kind: 'official-image', repository: options.upstreamImage, service, imageTag: 'tag' }
|
|
29
38
|
: { kind: 'native-source' };
|
|
30
39
|
writeFileSync(join(packaging, 'upstream-recipe.json'), JSON.stringify(recipe, null, 2) + '\n');
|
|
40
|
+
doc.set('maintainer', options.upstreamMaintainer ?? 'TODO: original upstream project or owner');
|
|
41
|
+
doc.setIn(['metadata', 'distributor'], options.publisher ?? 'TODO: your publisher name');
|
|
42
|
+
if (options.upstream) {
|
|
43
|
+
doc.setIn(['metadata', 'upstream'], options.upstream);
|
|
44
|
+
doc.setIn(['metadata', 'maintainer_url'], options.upstream);
|
|
45
|
+
}
|
|
46
|
+
if (options.publisherUrl)
|
|
47
|
+
doc.setIn(['metadata', 'distributor_url'], options.publisherUrl);
|
|
31
48
|
doc.set('entry', 'admin-only');
|
|
32
49
|
doc.delete('ctl');
|
|
33
50
|
if (official) {
|
|
@@ -53,6 +70,8 @@ export function writeForkScaffold(packaging, template, options) {
|
|
|
53
70
|
const guidance = `
|
|
54
71
|
## Integrating an existing open-source App
|
|
55
72
|
|
|
73
|
+
If you package someone else's open-source project, set maintainer to the original project/owner (prefer the project's own team/org name, else the owner's display name, else login), metadata.maintainer_url to the upstream repo, and yourself as metadata.distributor/metadata.distributor_url. Resolve all attribution TODOs before release; run check and review its warnings. Only your own Apps use your publisher as maintainer.
|
|
74
|
+
|
|
56
75
|
Keep the upstream fork/history and remote upstream. All wrapper-owned files belong in synology/; never edit upstream files or treat the App as an SDK component. Read synopkgland skill show upstream-fork.
|
|
57
76
|
|
|
58
77
|
Leave ctl absent from the manifest by default. Ask whether the user wants AI control; add ctl only when explicitly requested. If requested, read synopkgland skill show ctl and produce ctl-plan covering existing UI actions and public API endpoints, including common reads and writes. Status-only commands do not meet completion. Wrap existing native APIs without changing upstream code or inventing features. Long operations must return through existing asynchronous APIs without waiting for completion; report synchronous-only long APIs as blockers for discussion.
|
package/dist/init.d.ts
CHANGED
|
@@ -18,6 +18,10 @@ export interface InitOptions {
|
|
|
18
18
|
from?: string;
|
|
19
19
|
upstreamFork?: boolean;
|
|
20
20
|
upstreamImage?: string;
|
|
21
|
+
upstream?: string;
|
|
22
|
+
upstreamMaintainer?: string;
|
|
23
|
+
publisher?: string;
|
|
24
|
+
publisherUrl?: string;
|
|
21
25
|
healthPath?: string;
|
|
22
26
|
healthStatus?: number;
|
|
23
27
|
/** native-go: `install.sharedFolder` (select from the NAS, or create one). key defaults to "shared", permission to "rw". */
|
package/dist/package-metadata.js
CHANGED
|
@@ -27,6 +27,7 @@ export function validateMetadata(raw) {
|
|
|
27
27
|
"support_email",
|
|
28
28
|
"homepage",
|
|
29
29
|
"source_url",
|
|
30
|
+
"upstream",
|
|
30
31
|
"issues_url",
|
|
31
32
|
"license",
|
|
32
33
|
"maintainer_url",
|
|
@@ -66,6 +67,7 @@ export function validateMetadata(raw) {
|
|
|
66
67
|
if ([
|
|
67
68
|
"homepage",
|
|
68
69
|
"source_url",
|
|
70
|
+
"upstream",
|
|
69
71
|
"issues_url",
|
|
70
72
|
"maintainer_url",
|
|
71
73
|
"distributor_url",
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ValidationError } from './types.js';
|
|
2
|
+
/** A repository URL is provenance, never a credential-bearing transport URL. */
|
|
3
|
+
export declare function upstreamRepository(root: string, explicit?: string): string | undefined;
|
|
4
|
+
/** Best effort, bounded and public: offline/rate-limited lookups retain an explicit TODO. */
|
|
5
|
+
export declare function upstreamMaintainer(url?: string, fetcher?: typeof fetch): Promise<string | undefined>;
|
|
6
|
+
/** Advice only: attribution never changes manifest validity or the command exit status. */
|
|
7
|
+
export declare function upstreamAttributionWarnings(root: string): ValidationError[];
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { basename, join } from 'node:path';
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
import { parse } from 'yaml';
|
|
5
|
+
import { safeMetadataUrl } from './package-metadata.js';
|
|
6
|
+
/** A repository URL is provenance, never a credential-bearing transport URL. */
|
|
7
|
+
export function upstreamRepository(root, explicit) {
|
|
8
|
+
const raw = explicit ?? spawnSync('git', ['remote', 'get-url', 'upstream'], {
|
|
9
|
+
cwd: root, encoding: 'utf8', timeout: 1000,
|
|
10
|
+
}).stdout?.trim();
|
|
11
|
+
if (!raw)
|
|
12
|
+
return undefined;
|
|
13
|
+
const url = raw.replace(/^git@github\.com:/, 'https://github.com/').replace(/\.git$/, '');
|
|
14
|
+
return safeMetadataUrl(url) ? url : undefined;
|
|
15
|
+
}
|
|
16
|
+
/** Best effort, bounded and public: offline/rate-limited lookups retain an explicit TODO. */
|
|
17
|
+
export async function upstreamMaintainer(url, fetcher = fetch) {
|
|
18
|
+
if (!url)
|
|
19
|
+
return undefined;
|
|
20
|
+
const match = /^https:\/\/github\.com\/([\w-]+)\/[^/?#]+\/?$/.exec(url);
|
|
21
|
+
if (!match)
|
|
22
|
+
return undefined;
|
|
23
|
+
try {
|
|
24
|
+
const response = await fetcher(`https://api.github.com/users/${match[1]}`, {
|
|
25
|
+
headers: { Accept: 'application/vnd.github+json' }, signal: AbortSignal.timeout(3000),
|
|
26
|
+
});
|
|
27
|
+
if (!response.ok)
|
|
28
|
+
return undefined;
|
|
29
|
+
const owner = await response.json();
|
|
30
|
+
const name = typeof owner.name === 'string' && owner.name.trim() ? owner.name.trim() : owner.login;
|
|
31
|
+
return typeof name === 'string' && name.length <= 200 && !/[\x00-\x1f\x7f"\\]/.test(name) ? name : undefined;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Advice only: attribution never changes manifest validity or the command exit status. */
|
|
38
|
+
export function upstreamAttributionWarnings(root) {
|
|
39
|
+
const raw = parse(readFileSync(join(root, 'dsm-package.yaml'), 'utf8'));
|
|
40
|
+
const m = raw?.metadata ?? {};
|
|
41
|
+
const fork = existsSync(join(root, 'upstream-recipe.json')) ||
|
|
42
|
+
(basename(root) === 'synology' && existsSync(join(root, 'upgrade.sh')));
|
|
43
|
+
if (!m.upstream && !fork)
|
|
44
|
+
return [];
|
|
45
|
+
const todo = (v) => typeof v !== 'string' || !v.trim() || /^TODO\b/i.test(v.trim());
|
|
46
|
+
if (!todo(raw.maintainer) && !todo(m.distributor) &&
|
|
47
|
+
raw.maintainer.trim().toLowerCase() !== m.distributor.trim().toLowerCase() &&
|
|
48
|
+
!todo(m.maintainer_url) && !todo(m.distributor_url))
|
|
49
|
+
return [];
|
|
50
|
+
return [{
|
|
51
|
+
code: 'UPSTREAM_ATTRIBUTION', severity: 'warning',
|
|
52
|
+
span: { file: 'dsm-package.yaml', line: 1, column: 1 },
|
|
53
|
+
message: 'Upstream App attribution is incomplete or names the distributor as maintainer',
|
|
54
|
+
suggestion: "Set maintainer to the original project/team, else the owner's display name or login; set metadata.maintainer_url to the upstream repository and metadata.distributor/distributor_url to your publisher. Resolve attribution TODOs before release",
|
|
55
|
+
}];
|
|
56
|
+
}
|
package/dist/validate.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { upstreamAttributionWarnings } from './upstream-attribution.js';
|
|
1
2
|
import { existsSync } from "node:fs";
|
|
2
3
|
import { join } from "node:path";
|
|
3
4
|
import { getErrorCode } from "./error-registry.js";
|
|
@@ -36,6 +37,6 @@ export function validateProject(project, _options = {}) {
|
|
|
36
37
|
"Correct the schema-2 declaration; see the SDK Compose support matrix.",
|
|
37
38
|
})),
|
|
38
39
|
}
|
|
39
|
-
: { ok: true, errors: [] };
|
|
40
|
+
: { ok: true, errors: [], warnings: upstreamAttributionWarnings(project.root) };
|
|
40
41
|
}
|
|
41
42
|
export { findProjectRoot } from "./discovery.js";
|
package/package.json
CHANGED
package/skills/SKILL.md
CHANGED
|
@@ -5,7 +5,7 @@ description: Initialize, extend, check, build, inspect, and deploy Synology appl
|
|
|
5
5
|
|
|
6
6
|
# Independent Synology SPKs
|
|
7
7
|
|
|
8
|
-
CLI 0.
|
|
8
|
+
CLI 0.32.0 installs templates through `~0.31.0`. A templates patch needs only a
|
|
9
9
|
templates release; npm install/update selects a patch in that minor line. The CLI
|
|
10
10
|
uses the locally installed templates and reads their SDK pin for defaults; it
|
|
11
11
|
never downloads templates at runtime. Preserve the lockfile and use `npm ci` for
|
|
@@ -22,6 +22,14 @@ Use this guide to initialize, build and inspect own applications or upstream OSS
|
|
|
22
22
|
|
|
23
23
|
For an existing open-source App, first read [reference/upstream-fork.md](reference/upstream-fork.md): upstream fork/history + untouched upstream files + all packaging in `synology/`, official container images pinned by tag/index digest, native official release binaries pinned by SHA-256 or a source build hook, and a single tag-merge upgrade command. Use `init --upstream-fork`; never rewrite the App as a component. Integrated upstream Apps require direct DSM administrator entry without a separate App password or an OIDC/SSO server: supported trusted headers first, disabling native login second; the shipped OpenList pattern uses the existing SDK 0.17.3 token adapter (`mode: token`, `access: dsm-admins`, `entry: admin-only`) with server-side Authorization injection. All DSM admins share one upstream admin; token reset requires package restart; WebDAV retains its native credentials.
|
|
24
24
|
|
|
25
|
+
**If you package someone else's open-source project, set `maintainer` to the
|
|
26
|
+
original project/owner (prefer the project's own team/org name, else the owner's
|
|
27
|
+
display name, else login), `metadata.maintainer_url` to the upstream repository,
|
|
28
|
+
and yourself as `metadata.distributor` / `metadata.distributor_url`.** Only your
|
|
29
|
+
own Apps use your publisher as maintainer. Pass upstream and publisher attribution
|
|
30
|
+
to `init --upstream-fork`; resolve TODOs and review `check` warnings before release.
|
|
31
|
+
See the scaffold steps and release checklist in [reference/upstream-fork.md](reference/upstream-fork.md).
|
|
32
|
+
|
|
25
33
|
For upstream OSS packaging, leave `ctl` absent from the manifest by default. Ask whether the user wants AI control; implement it only when explicitly requested. Read [reference/ctl.md](reference/ctl.md) for the required `ctl-plan`, UI/API coverage checklist and asynchronous-operation rules. Own Apps retain the native template's ctl defaults, with commands covering their main features; status-only coverage is incomplete.
|
|
26
34
|
|
|
27
35
|
Start with `synopkgland init -t native-go`, `synopkgland init -t binary`, or `synopkgland init -t compose`. Read reference/create.md or reference/wrap.md, then reference/deploy.md. Native CGI session checks belong to the package. For wrapping upstream OSS with DSM accounts, read [reference/identity-gateway.md](reference/identity-gateway.md) first. For all Compose work, read [reference/compose.md](reference/compose.md): schema-2 upstream files, generated override, SDK planner, fixed package identity and current DSM blockers. Containers do not inherit a signed-in user's File Station ACL. Existing Shared Folder mounts are blocked until official protected ACL/project control is verified.
|
|
@@ -247,7 +247,7 @@ declared availability readiness, LAN isolation/egress, protected grant lifecycle
|
|
|
247
247
|
ACLs, two-user visibility and clean install/upgrade/reboot/stop/uninstall before
|
|
248
248
|
calling the package supported on a NAS. No NAS is accessed by the build gate.
|
|
249
249
|
|
|
250
|
-
The unified Compose contract uses SDK
|
|
250
|
+
The unified Compose contract uses SDK defaults from locally installed templates `~0.31.0` with CLI 0.32.0. Templates patches can ship independently; npm install/update resolves them, and SDK defaults come from the installed templates. SDK minor upgrades do not require a CLI release when they declare supported executor manifest format 1; the resolved SDK owns the release mapping and verified payload digests. The CLI does not fetch templates at runtime. The legacy packaging route and bridge publish mode are removed.
|
|
251
251
|
|
|
252
252
|
Primary override files, and each included override set, must share a directory. Cross-directory override bases are rejected before loader I/O. Included implicit .env files are confined, inventoried and preserved; symlinks are rejected.
|
|
253
253
|
|
|
@@ -11,6 +11,30 @@ under `synology/`, such as DSM install wizards and gateway pages; leave upstream
|
|
|
11
11
|
UI/locale strings and release notes unchanged, and exclude upstream source from
|
|
12
12
|
any future punctuation checker.
|
|
13
13
|
|
|
14
|
+
## Maintainer and distributor
|
|
15
|
+
|
|
16
|
+
If you package someone else's open-source project, set `maintainer` to the original
|
|
17
|
+
project/owner (prefer the project's own team/org name, else the owner's display
|
|
18
|
+
name, else login), `metadata.maintainer_url` to the upstream repository, and
|
|
19
|
+
**yourself** as `metadata.distributor` / `metadata.distributor_url`. Only your own
|
|
20
|
+
Apps use your publisher as maintainer. Syno Package Land is the distributor only
|
|
21
|
+
when it distributes the App; this rule applies to every third-party developer.
|
|
22
|
+
|
|
23
|
+
Pass `--upstream <repo-url>` (or retain the `upstream` Git remote), your verified
|
|
24
|
+
`--upstream-maintainer <project-team>` when known, and `--publisher <name>` /
|
|
25
|
+
`--publisher-url <url>` to `init --upstream-fork`. Publisher defaults come from
|
|
26
|
+
`SYNOPKGLAND_PUBLISHER` / `SYNOPKGLAND_PUBLISHER_URL`. The CLI tries the public
|
|
27
|
+
GitHub owner profile with a bounded lookup, using its display name then login.
|
|
28
|
+
Offline or unsupported hosts leave an explicit maintainer TODO. Missing publisher
|
|
29
|
+
configuration leaves a distributor TODO. Resolve these manually before release.
|
|
30
|
+
`metadata.upstream` records the repository; `check` warns, without failing, for
|
|
31
|
+
missing attribution or a maintainer that equals the distributor. The fork layout
|
|
32
|
+
also enables this warning without `metadata.upstream`.
|
|
33
|
+
|
|
34
|
+
These metadata fields become standard SPK INFO fields; upstream source stays
|
|
35
|
+
unchanged. Catalog attribution may change before rebuilding; installed INFO
|
|
36
|
+
changes only after an SPK upgrade.
|
|
37
|
+
|
|
14
38
|
## Decide whether to expose AI control
|
|
15
39
|
|
|
16
40
|
Ask whether the user needs AI control unless they have already explicitly requested it.
|
|
@@ -37,11 +61,12 @@ git clone <your-fork-url> app
|
|
|
37
61
|
cd app
|
|
38
62
|
git remote add upstream <upstream-url>
|
|
39
63
|
synopkgland init -t compose --upstream-fork --package MyApp \
|
|
40
|
-
--upstream
|
|
64
|
+
--upstream https://github.com/owner/app --publisher "Your team" \
|
|
65
|
+
--publisher-url https://example.com --upstream-image owner/app --health-path /actual-readiness --health-status 200 .
|
|
41
66
|
```
|
|
42
67
|
|
|
43
68
|
Replace `owner/app` with the verified official repository. `init` does not guess
|
|
44
|
-
|
|
69
|
+
the official image publisher. Only attribution uses a best-effort GitHub profile lookup. Configure `synology/upstream-recipe.json`:
|
|
45
70
|
`repository`, the actual Compose `service`, and `imageTag: tag` (exact upstream
|
|
46
71
|
tag) or `version` (strip the leading `v` only if the official image uses that
|
|
47
72
|
spelling). Adjust the App's port, storage and DSM login adapter before committing.
|
|
@@ -78,7 +103,9 @@ workaround with the framework ownership mechanism once available and verified.
|
|
|
78
103
|
## Native: official release binaries or a source build hook
|
|
79
104
|
|
|
80
105
|
```sh
|
|
81
|
-
synopkgland init -t native-go --ui plain --upstream-fork --package MyApp
|
|
106
|
+
synopkgland init -t native-go --ui plain --upstream-fork --package MyApp \
|
|
107
|
+
--upstream https://github.com/owner/app --publisher "Your team" \
|
|
108
|
+
--publisher-url https://example.com .
|
|
82
109
|
```
|
|
83
110
|
|
|
84
111
|
Native Apps can stage official release binaries pinned by **SHA-256**, or compile
|
|
@@ -180,3 +207,11 @@ returns 503 even when the gateway is down. Availability is not identity attestat
|
|
|
180
207
|
Declare only Container Manager-capable `arches`/INFO platforms; exclude unsupported
|
|
181
208
|
NAS architectures and review models in each family. Actual missing-package wizard
|
|
182
209
|
behavior and DSM's dependency not-ready behavior remain device acceptance items.
|
|
210
|
+
|
|
211
|
+
## Release checklist
|
|
212
|
+
|
|
213
|
+
- Verify the original project/team or owner is the maintainer, its repository is
|
|
214
|
+
`metadata.maintainer_url` / `metadata.upstream`, and your publisher is the distributor
|
|
215
|
+
- Resolve attribution TODOs and review all `check --json` warnings
|
|
216
|
+
- Inspect the built SPK INFO attribution, preserve notices/source correspondence,
|
|
217
|
+
and verify the selected upstream release before publishing
|