@synopackageland/templates 0.31.5 → 0.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,8 +22,8 @@ daemon:
22
22
  window_seconds: 300
23
23
  ```
24
24
 
25
- Templates pin UI 0.16.1 and SDK 0.31.5 in native and Compose projects.
26
- Use CLI 0.31.0 or later; with CLI 0.33.2 or later, the Vue `AppShell` shows a
25
+ Templates 0.32.0 pin UI 0.16.1 and SDK 0.32.0 in native and Compose projects.
26
+ Use CLI 0.34.0. The Vue `AppShell` shows a
27
27
  non-blocking **Reload** notice when an upgrade replaced the UI an open page
28
28
  loaded. Go Apps select
29
29
  their controller from their Go SDK requirement; an identity gateway selects it
@@ -41,7 +41,7 @@ for declaration bounds, SDK selection, build/inspect checks and diagnostics.
41
41
 
42
42
  An opt-in [Shared Folder permission example](examples/shared-folder-permission/README.md)
43
43
  shows the Go status-handler registration and a Vue notice for startup checks and
44
- storage failures. It uses the same SDK 0.31.5 release pinned by the default scaffolds.
44
+ storage failures. It uses SDK 0.32.0, matching the default scaffolds.
45
45
 
46
46
  An opt-in [native UI plus DSM console example](examples/dual-entry-console/README.md)
47
47
  shows the `console` declaration for an App that wraps a web service behind the
@@ -81,25 +81,44 @@ calls each one from the generated script of the same name (`synopkgland skill sh
81
81
  The placeholders `__PACKAGE__` (also the Go module path), `__DISPLAY_NAME__` and
82
82
  `__BACKGROUND_ENABLED__` are substituted by `init`.
83
83
 
84
- `backend/go.mod` requires `github.com/synopackageland/syno-pkg-land-sdk v0.31.5`; that line is
84
+ `backend/go.mod` requires `github.com/synopackageland/syno-pkg-land-sdk v0.32.0`; that line is
85
85
  the single source of the SDK version and `frontend/package.json` pins
86
86
  `@synopackageland/sdk` to the same version. Python and Node.js name it in
87
87
  `backend.sdk`, Rust in the `syno-pkg-land-app` tag of `backend/Cargo.toml`
88
- (and `Cargo.lock`); all of them pin 0.31.5. The Vue frontend pins
89
- `@synopackageland/ui` 0.16.1. SDK 0.31.5 accepts UI `>=0.10.1 <0.18.0`,
88
+ (and `Cargo.lock`); all of them pin 0.32.0. The Vue frontend pins
89
+ `@synopackageland/ui` 0.16.1. SDK 0.32.0 accepts UI `>=0.10.1 <0.18.0`,
90
90
  so no UI peer override is needed. Tests use jsdom 30 for UI floating-layer styles.
91
91
 
92
- SDK 0.27.0 moves interactive NAS file operations to same-origin browser calls.
92
+ Interactive NAS file operations use same-origin browser calls.
93
93
  Custom file handlers use the SDK's
94
- [session transport migration](https://github.com/synopackageland/syno-pkg-land-sdk/blob/v0.27.0/docs/dsm-session-transport.md).
95
- CLI 0.31.0 reads SDK 0.31.5's release manifest, which reuses the immutable
96
- executor/v0.31.0 and its lifecycle digests. Its `~0.31.0` templates dependency
97
- accepts templates 0.31.5 on a fresh install; no CLI patch is required. Rebuilt
98
- protected executors follow normal administrator approval. No NAS acceptance is claimed.
94
+ [session transport migration](https://github.com/synopackageland/syno-pkg-land-sdk/blob/v0.32.0/docs/dsm-session-transport.md).
95
+ CLI 0.34.0 reads SDK 0.32.0's release manifest, which names immutable
96
+ executor/v0.32.0 and its refreshed executor digests; lifecycle bytes are unchanged. Its `~0.32.0` templates
97
+ dependency selects this release. Rebuilt protected executors need fresh
98
+ administrator approval. No device acceptance is claimed.
99
+
100
+ Every App method must appear in the permissions table, including methods whose
101
+ permission equals `default: administrators`. Dynamic method names and custom
102
+ HTTP dispatchers are rejected. Register fixed SDK routes, and declare
103
+ `identity_gateway.upstream_auth_paths` for client API paths that use upstream
104
+ authentication. Other paths retain DSM entry admission. See the CLI's
105
+ [entry migration guide](https://github.com/synopackageland/syno-pkg-land-cli/blob/main/docs/app-entry.md).
99
106
 
100
107
  UI and i18n text, including the DSM glossary, omit terminal sentence periods.
101
108
  Keep punctuation between sentences and intentional loading ellipses.
102
109
 
110
+ ## Vue frontend modules
111
+
112
+ Vue scaffolds export `mount(root, ctx)` from `app.module.js` and emit `app.css`.
113
+ Keep `base: './'`, relative imports and `cssCodeSplit: false`; allow lazy chunks
114
+ with `() => import('./Page.vue')` or `defineAsyncComponent`. Each mount creates
115
+ its own Vue App and returns synchronous cleanup.
116
+
117
+ CLI 0.34.0 copies the entire output into `ui/app/<tree-sha256>/` and verifies it
118
+ during `inspect`. Changing a lazy chunk changes the snapshot URL. An open page
119
+ may need to reload after an upgrade when an old lazy chunk is unavailable.
120
+ See the SDK's [frontend bundle contract](https://github.com/synopackageland/syno-pkg-land-sdk/blob/main/docs/frontend-bundles.md).
121
+
103
122
  ## Notice writer
104
123
 
105
124
  `init` copies the writer to `frontend/third-party-notices.mjs`. Tools that keep
@@ -234,4 +253,4 @@ The bridge examples expose submission, lookup and cancellation through
234
253
 
235
254
  ## External access
236
255
 
237
- With CLI 0.31.0 and SDK 0.31.5, a gateway App may declare `identity_gateway.external_access: {connect: optional, origin_change: confirm, single_origin: true}` for an upstream that signs in on one fixed URL. The policy is forwarded to the packaged gateway. A single-origin App's `manual_origin` accepts an explicit HTTPS port; the `external-origin` installation setting remains restricted to port 443. The DSM launcher selects a provider destination, probes `/_spl/ping` for up to eight seconds, and explains failures before offering **Open anyway**. A configured single-origin App always opens its primary external origin.
256
+ With CLI 0.34.0 and SDK 0.32.0, a gateway App may declare `identity_gateway.external_access: {connect: optional, origin_change: confirm, single_origin: true}` for an upstream that signs in on one fixed URL. The policy is forwarded to the packaged gateway. A single-origin App's `manual_origin` accepts an explicit HTTPS port; the `external-origin` installation setting remains restricted to port 443. The DSM launcher selects a provider destination, probes `/_spl/ping` for up to eight seconds, and explains failures before offering **Open anyway**. A configured single-origin App always opens its primary external origin.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synopackageland/templates",
3
- "version": "0.31.5",
3
+ "version": "0.32.1",
4
4
  "description": "Project templates for synopkgland init: native-go, native-python, native-node and native-rust (plain or Vue, with jobs, delegate and root-ops overlays), binary and compose.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -54,8 +54,21 @@ Application Privileges allows for `SYNO.SDS.<package>.Instance`; DSM's install
54
54
  default allows administrators only, so nobody else enters until an admin grants
55
55
  access. One CGI check covers every route; failures refuse; changes apply within
56
56
  30 seconds. Never re-implement AppPriv rules in the App.
57
- Mark routes ordinary users call `authenticated` in permissions.json, keep whole
58
- admin routes at the default, guard global settings inside shared routes with
57
+ List every App method explicitly in permissions.json, including administrator
58
+ methods. Dynamic method names and unregistered HTTP dispatchers are rejected; use
59
+ fixed SDK route constructors. Use identity_gateway.upstream_auth_paths for
60
+ client API paths authenticated by the upstream.
61
+ SDK 0.33.0 with CLI 0.35.0 adds `api.HandleHTTP("/proxy/", "app.proxy", handler)`
62
+ for literal, disjoint full-segment prefixes outside SDK reserved paths. Declare
63
+ the key as authenticated or administrators in permissions.json. Origin, entry,
64
+ identity and permission checks precede raw streaming/initial-upgrade handlers;
65
+ CGI itself cannot upgrade a connection. For package-private worker HTTP use
66
+ `ipc.ServeUnix(ctx, path, handler)` and `ipc.DialUnix`: owned mode-0600 sockets
67
+ directly beneath the package's private `var/run`, with no custom TCP listener.
68
+ The audit follows configured binaries' Linux import graphs and excludes unshipped
69
+ dev commands. Upgrade the scaffold's SDK pin before using these APIs.
70
+ Mark routes ordinary users call `authenticated`, mark whole admin routes
71
+ `administrators`, guard global settings inside shared routes with
59
72
  the SDK's require-admin check, and hide admin controls with `ctx.user?.isAdmin`
60
73
  (UI only, never the authority). Example: users read the greeting; only admins
61
74
  call `greeting.set`.
@@ -14,7 +14,7 @@ compose:
14
14
  web: {service: web, port: 8080, health: {path: /, status: 200}}
15
15
  network: {egress: isolated}
16
16
  identity_gateway:
17
- sdk: 0.31.5
17
+ sdk: 0.32.0
18
18
  mode: none
19
19
  listen: {http: 28000}
20
20
  # Web Apps default to new-page through the shared app-launch resolver.
@@ -233,8 +233,9 @@ ui:
233
233
  command: [npm, run, build]
234
234
  ```
235
235
 
236
- The build must emit `app.js` (one script that registers `mount`) and
237
- `app.css`. The installed `@synopackageland/ui` package gives Vue components with DSM 7 styling;
236
+ The build must emit `app.js` (a classic script that registers `mount`) or
237
+ `app.module.js` (an ES module exporting `mount`), plus `app.css`. Module builds
238
+ can include relative lazy chunks; use a CLI with module UI support. The installed `@synopackageland/ui` package gives Vue components with DSM 7 styling;
238
239
  import its `themes/dsm7-embedded.css` for use inside a DSM window.
239
240
 
240
241
  ## Languages
@@ -1,6 +1,6 @@
1
1
  Native Go package build dependencies
2
2
 
3
- github.com/synopackageland/syno-pkg-land-sdk v0.31.5 (MIT)
3
+ github.com/synopackageland/syno-pkg-land-sdk v0.32.0 (MIT)
4
4
 
5
5
  Copyright (c) 2026 synopkgland
6
6
 
@@ -4,6 +4,6 @@ go 1.25.0
4
4
 
5
5
  toolchain go1.26.10
6
6
 
7
- require github.com/synopackageland/syno-pkg-land-sdk v0.31.5
7
+ require github.com/synopackageland/syno-pkg-land-sdk v0.32.0
8
8
 
9
9
  require golang.org/x/sys v0.44.0 // indirect
@@ -1,4 +1,4 @@
1
- github.com/synopackageland/syno-pkg-land-sdk v0.31.5 h1:zdz6QHQ/kOhoJSUrvOa9siVZZokhqnsk2iOe/wMk+9s=
2
- github.com/synopackageland/syno-pkg-land-sdk v0.31.5/go.mod h1:8GwREGbczc8mAk4Gv8FUHaukXXCUstjzkovQrNV59Cc=
1
+ github.com/synopackageland/syno-pkg-land-sdk v0.32.0 h1:m5AkhRV3ZA+9PnifnDTstC+5PLoQVJQ58ZYQNkzUtPE=
2
+ github.com/synopackageland/syno-pkg-land-sdk v0.32.0/go.mod h1:8GwREGbczc8mAk4Gv8FUHaukXXCUstjzkovQrNV59Cc=
3
3
  golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ=
4
4
  golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
@@ -18,6 +18,13 @@ The base app reads package status and edits the package greeting through
18
18
  `ctx.call`. Each window has its own Vue mount, request state and host
19
19
  subscriptions; unmount disposes subscriptions and ignores late responses.
20
20
 
21
+ The build emits `app.module.js`, `app.css` and any lazy chunks. The entry
22
+ exports `mount(root, ctx)`; it does not register through
23
+ `document.currentScript`. The CLI's module UI loader imports it from the
24
+ package's content-addressed asset directory. Use this template together with a
25
+ CLI that supports `app.module.js`. Keep `base: './'` and relative dynamic imports
26
+ such as `() => import('./pages/ChatPage.vue')` to split optional pages.
27
+
21
28
  `--with root-ops` adds the existing DSM approval gate for fixed `root/*.sh`
22
29
  operations, and its `ExecutorGate.vue` holds the pages with the SDK's
23
30
  `ExecutorApproval` until the executor is approved: an administrator approves
@@ -7,7 +7,7 @@
7
7
  "name": "native-dsm-vue-app",
8
8
  "dependencies": {
9
9
  "@lucide/vue": "1.48.0",
10
- "@synopackageland/sdk": "0.31.5",
10
+ "@synopackageland/sdk": "0.32.0",
11
11
  "@synopackageland/ui": "0.16.1",
12
12
  "vue": "3.5.43"
13
13
  },
@@ -1152,9 +1152,9 @@
1152
1152
  }
1153
1153
  },
1154
1154
  "node_modules/@synopackageland/sdk": {
1155
- "version": "0.31.5",
1156
- "resolved": "https://registry.npmjs.org/@synopackageland/sdk/-/sdk-0.31.5.tgz",
1157
- "integrity": "sha512-m79KCOEqJ2i69m+oJsQxEqWMA96Ageza821a5w7rJDDLYefRDxbk/TlbXeiNdyBn39USVEXFZkk5khM+iFafJA==",
1155
+ "version": "0.32.0",
1156
+ "resolved": "https://registry.npmjs.org/@synopackageland/sdk/-/sdk-0.32.0.tgz",
1157
+ "integrity": "sha512-95IT8qXgmO98y56ftLgKcHAMeDDx1QxdYrlZrWBSuga8Z7lLW545v3iWll86zY8rpbURDHbVrrunCCPyZraLSw==",
1158
1158
  "license": "MIT",
1159
1159
  "peerDependencies": {
1160
1160
  "@lucide/vue": "^1.48.0",
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "dependencies": {
10
10
  "@lucide/vue": "1.48.0",
11
- "@synopackageland/sdk": "0.31.5",
11
+ "@synopackageland/sdk": "0.32.0",
12
12
  "@synopackageland/ui": "0.16.1",
13
13
  "vue": "3.5.43"
14
14
  },
@@ -22,12 +22,4 @@ export function mount(root: HTMLElement, ctx: Context) {
22
22
  app.mount(root)
23
23
  return {unmount() {app.unmount(); if(!hadRootClass) root.classList.remove('dsmapp-vue-root')}}
24
24
  }
25
- // Register with the existing per-package DSM window loader. Never share a
26
- // singleton app or user/session state between different mount calls.
27
- const script = document.currentScript as HTMLScriptElement | null
28
- const packageID = script?.getAttribute('data-package')
29
- const host = window as unknown as {DsmPackageApps: Record<string, {mount: typeof mount}>}
30
- if (packageID) {
31
- host.DsmPackageApps = host.DsmPackageApps || {}
32
- host.DsmPackageApps[packageID] = {mount}
33
- }
25
+ // The DSM window imports this module and calls mount for each window.
@@ -0,0 +1,31 @@
1
+ // @vitest-environment node
2
+ import {mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync} from 'node:fs'
3
+ import {tmpdir} from 'node:os'
4
+ import {join, resolve} from 'node:path'
5
+ import {build, loadConfigFromFile, mergeConfig} from 'vite'
6
+ import {expect, test} from 'vitest'
7
+
8
+ test('the shipped Vite config keeps a dynamic import in a separate module', async () => {
9
+ const work = mkdtempSync(join(tmpdir(), 'module-bundle-'))
10
+ try {
11
+ writeFileSync(join(work, 'entry.ts'), 'import "./style.css"; export const open = () => import("./lazy.ts")')
12
+ writeFileSync(join(work, 'lazy.ts'), 'export const text = "optional-route-payload"')
13
+ writeFileSync(join(work, 'style.css'), '.bundle-fixture { color: green }')
14
+ const loaded = await loadConfigFromFile({command: 'build', mode: 'production'}, resolve('vite.config.ts'))
15
+ expect(loaded).not.toBeNull()
16
+ await build(mergeConfig(loaded!.config, {
17
+ configFile: false,
18
+ logLevel: 'silent',
19
+ build: {outDir: join(work, 'dist'), lib: {entry: join(work, 'entry.ts')}},
20
+ }))
21
+ const entry = readFileSync(join(work, 'dist/app.module.js'), 'utf8')
22
+ expect(entry).toMatch(/import\(["']\.\/chunks\//)
23
+ expect(entry).not.toContain('optional-route-payload')
24
+ const chunks = readdirSync(join(work, 'dist/chunks'))
25
+ expect(chunks).toHaveLength(1)
26
+ expect(readFileSync(join(work, 'dist/chunks', chunks[0]), 'utf8')).toContain('optional-route-payload')
27
+ expect(readFileSync(join(work, 'dist/app.css'), 'utf8')).toContain('bundle-fixture')
28
+ } finally {
29
+ rmSync(work, {recursive: true, force: true})
30
+ }
31
+ })
@@ -7,5 +7,6 @@ export default defineConfig(({command}) => ({
7
7
  // Library mode must replace Vue dependency env guards for the DSM browser.
8
8
  define: command === 'build' ? {'process.env.NODE_ENV': JSON.stringify('production')} : {},
9
9
  resolve: {dedupe: ['vue']},
10
- build: {lib: {entry: 'src/main.ts', formats: ['iife'], name: 'DsmVueApp', fileName: () => 'app.js'}, cssCodeSplit: false, rollupOptions: {output: {assetFileNames: 'app.[ext]'}}},
10
+ base: './',
11
+ build: {lib: {entry: 'src/main.ts', formats: ['es'], fileName: () => 'app.module.js'}, cssCodeSplit: false, rollupOptions: {output: {chunkFileNames: 'chunks/[name]-[hash].js', assetFileNames: asset => asset.names?.some(name => name.endsWith('.css')) ? 'app.css' : 'assets/[name]-[hash][extname]'}}},
11
12
  }))
@@ -49,7 +49,7 @@ backend:
49
49
  runtime: node
50
50
  dir: backend/app
51
51
  entry: main.js
52
- sdk: 0.31.5
52
+ sdk: 0.32.0
53
53
  node: { package: Node.js_v22 }
54
54
 
55
55
  ui:
@@ -47,7 +47,7 @@ backend:
47
47
  runtime: python
48
48
  dir: backend/app
49
49
  entry: main.py
50
- sdk: 0.31.5
50
+ sdk: 0.32.0
51
51
 
52
52
  ui:
53
53
  # Non-UI-SDK frontends open a full page; Portal is a separate opt-in.
@@ -104,8 +104,8 @@ dependencies = [
104
104
 
105
105
  [[package]]
106
106
  name = "syno-pkg-land-app"
107
- version = "0.31.5"
108
- source = "git+https://github.com/synopackageland/syno-pkg-land-sdk?tag=v0.31.5#138aa1bb1155f3386e38b997241ef0ef3266160a"
107
+ version = "0.32.0"
108
+ source = "git+https://github.com/synopackageland/syno-pkg-land-sdk?tag=v0.32.0#dcf4229b53ee6455c4c4ec41b4a4f52775c2b958"
109
109
  dependencies = [
110
110
  "libc",
111
111
  "serde",
@@ -9,7 +9,7 @@ libc = "0.2"
9
9
  serde = { version = "1", features = ["derive"] }
10
10
  serde_json = "1"
11
11
  # The SDK version is the tag; `synopkgland check` reads it from Cargo.lock.
12
- syno-pkg-land-app = { git = "https://github.com/synopackageland/syno-pkg-land-sdk", tag = "v0.31.5" }
12
+ syno-pkg-land-app = { git = "https://github.com/synopackageland/syno-pkg-land-sdk", tag = "v0.32.0" }
13
13
 
14
14
  [profile.release]
15
15
  # A handler panic becomes an "internal" reply; abort would end the App without one.