@synopackageland/templates 0.14.1 → 0.15.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/README.md +11 -3
- package/package.json +1 -1
- package/templates/compose/compose.yaml +4 -7
- package/templates/compose/dsm-package.yaml +23 -0
- package/templates/native-go/backend/THIRD_PARTY_NOTICES.txt +1 -1
- package/templates/native-go/backend/cmd/app/main.go +25 -0
- package/templates/native-go/backend/go.mod +1 -1
- package/templates/native-go/backend/go.sum +2 -2
- package/templates/native-go/dsm-package.yaml +31 -0
- package/templates/native-go-vue/frontend/package-lock.json +4 -4
- package/templates/native-go-vue/frontend/package.json +1 -1
- package/templates/native-node/dsm-package.yaml +32 -1
- package/templates/native-python/dsm-package.yaml +32 -1
- package/templates/native-rust/backend/Cargo.lock +2 -2
- package/templates/native-rust/backend/Cargo.toml +1 -1
- package/templates/native-rust/dsm-package.yaml +31 -0
- package/templates/compose/synology-app.yaml +0 -22
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ the files an App owns; the SDK (`github.com/synopackageland/syno-pkg-land-sdk`,
|
|
|
17
17
|
| `native-{python,node,rust}-{jobs,root-ops,delegate}` | The capability's example module, replacing the base's stub, with its tests |
|
|
18
18
|
| `native-{python,node,rust}-vue` | The README and `.gitignore` of the Vue shell |
|
|
19
19
|
| `binary` | A prebuilt static CGI (`example/main.go`) with a plain UI |
|
|
20
|
-
| `compose` | Container Manager project (`compose.yaml`, `
|
|
20
|
+
| `compose` | Container Manager project (upstream `compose.yaml`, schema-2 `dsm-package.yaml`) |
|
|
21
21
|
| `_shared` | Agent guides, template license, Go license texts, third-party notice writer, `dsm-scripts/` (DSM lifecycle scripts) |
|
|
22
22
|
|
|
23
23
|
Overlays are copied over `native-go` in the order root-ops, vue, jobs, delegate.
|
|
@@ -38,11 +38,11 @@ calls each one from the generated script of the same name (`synopkgland skill sh
|
|
|
38
38
|
The placeholders `__PACKAGE__` (also the Go module path), `__DISPLAY_NAME__` and
|
|
39
39
|
`__BACKGROUND_ENABLED__` are substituted by `init`.
|
|
40
40
|
|
|
41
|
-
`backend/go.mod` requires `github.com/synopackageland/syno-pkg-land-sdk v0.
|
|
41
|
+
`backend/go.mod` requires `github.com/synopackageland/syno-pkg-land-sdk v0.15.0`; that line is
|
|
42
42
|
the single source of the SDK version and `frontend/package.json` pins
|
|
43
43
|
`@synopackageland/sdk` to the same version. Python and Node.js name it in
|
|
44
44
|
`backend.sdk`, Rust in the `syno-pkg-land-app` tag of `backend/Cargo.toml`
|
|
45
|
-
(and `Cargo.lock`); all of them pin 0.
|
|
45
|
+
(and `Cargo.lock`); all of them pin 0.15.0. The Vue frontend pins
|
|
46
46
|
`@synopackageland/ui` 0.11.0.
|
|
47
47
|
|
|
48
48
|
## Notice writer
|
|
@@ -139,3 +139,11 @@ service: omitted `ui.launch` resolves to `new-page`, without Application Portal.
|
|
|
139
139
|
Both Compose routes share `contract/app-launch.ts` for defaults and launcher types.
|
|
140
140
|
An explicit `ui.launch` overrides this default. Native SDK Apps without a web
|
|
141
141
|
service keep `dsm-window` when `ui.launch` is absent.
|
|
142
|
+
|
|
143
|
+
## Compose identity and file access
|
|
144
|
+
|
|
145
|
+
The CLI preserves upstream bytes and the SDK planner generates an override and one worker model. No dummy backend, UI or wrapper container is needed. Containers use the fixed package identity and do not inherit each signed-in user's File Station ACL. Shared Folder intent is explicit composeMounts, confirmed by an admin after install; activation is unsupported until official protected ACL/project control is verified. Fine egress allowlists are rejected; isolated/internet are the two declared levels. See the SDK Compose support matrix before deployment.
|
|
146
|
+
|
|
147
|
+
## AI commands
|
|
148
|
+
|
|
149
|
+
All four native templates explicitly declare status and greeting commands in `ctl.commands`. Build packages a private `synopkgland-api.json`; only the authenticated SDK description endpoint returns it. Internal routes are not automatically commands. Read `synopkgland skill show ctl` before adding command schemas or workflow bindings.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synopackageland/templates",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
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": {"type": "git", "url": "git+https://github.com/synopackageland/syno-pkg-land-templates.git"},
|
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
services:
|
|
2
|
-
|
|
3
|
-
image:
|
|
4
|
-
command: [
|
|
5
|
-
|
|
6
|
-
# intentionally outside the zero-config docker-project resource-worker path.
|
|
7
|
-
- "${MEDIA_SHARE}/data:/data:ro"
|
|
8
|
-
- "${SYNOPKG_PKGVAR}/state:/state"
|
|
2
|
+
web:
|
|
3
|
+
image: busybox:1.37.0
|
|
4
|
+
command: [httpd, -f, -p, '8080']
|
|
5
|
+
ports: ['8080:8080']
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Upstream Compose stays byte-for-byte unchanged. Only DSM differences go here.
|
|
2
|
+
schema: 2
|
|
3
|
+
package: __PACKAGE__
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
build: 1
|
|
6
|
+
displayname: __DISPLAY_NAME__
|
|
7
|
+
description: An upstream container application with a DSM identity gateway.
|
|
8
|
+
maintainer: Your Name
|
|
9
|
+
os_min_ver: "7.2.1-69057"
|
|
10
|
+
arches: [x86_64, aarch64]
|
|
11
|
+
capabilities: {}
|
|
12
|
+
compose:
|
|
13
|
+
files: [compose.yaml]
|
|
14
|
+
web: {service: web, port: 8080, health: {path: /, status: 200}}
|
|
15
|
+
network: {egress: isolated}
|
|
16
|
+
identity_gateway:
|
|
17
|
+
sdk: 0.15.0
|
|
18
|
+
mode: none
|
|
19
|
+
listen: {http: 28000}
|
|
20
|
+
# Web Apps default to new-page through the shared app-launch resolver.
|
|
21
|
+
# ui: {launch: new-page}
|
|
22
|
+
# Containers use a fixed package UID, never the signed-in user's File Station ACL.
|
|
23
|
+
# For existing Share access, opt in to composeMounts and confirm after install.
|
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
package main
|
|
7
7
|
|
|
8
8
|
import (
|
|
9
|
+
"encoding/json"
|
|
9
10
|
"fmt"
|
|
10
11
|
"log"
|
|
11
12
|
"net/http"
|
|
12
13
|
"net/http/cgi"
|
|
13
14
|
"os"
|
|
15
|
+
"path/filepath"
|
|
14
16
|
"strconv"
|
|
15
17
|
"time"
|
|
16
18
|
|
|
@@ -65,6 +67,24 @@ func main() {
|
|
|
65
67
|
}
|
|
66
68
|
return
|
|
67
69
|
}
|
|
70
|
+
if os.Getenv("GATEWAY_INTERFACE") == "" && len(os.Args) == 2 && os.Args[1] == "--describe" {
|
|
71
|
+
permissions, err := appapi.Permissions()
|
|
72
|
+
if err != nil {
|
|
73
|
+
log.Fatal(err)
|
|
74
|
+
}
|
|
75
|
+
cfg := app.Config{PackageID: packageID, Version: version, DataDir: ".", Portal: portal != ""}
|
|
76
|
+
if app.SessionFilesEnabled(fileStation) {
|
|
77
|
+
cfg.SessionFiles = filestation.Local(cfg.DataDir)
|
|
78
|
+
}
|
|
79
|
+
methods, err := api.DescribeRoutes(permissions, app.Routes(cfg)...)
|
|
80
|
+
if err != nil {
|
|
81
|
+
log.Fatal(err)
|
|
82
|
+
}
|
|
83
|
+
if err := json.NewEncoder(os.Stdout).Encode(methods); err != nil {
|
|
84
|
+
log.Fatal(err)
|
|
85
|
+
}
|
|
86
|
+
return
|
|
87
|
+
}
|
|
68
88
|
if os.Getenv("GATEWAY_INTERFACE") == "" {
|
|
69
89
|
fmt.Fprintf(os.Stderr, "%s %s: this program runs as the package's DSM CGI; open the app from the DSM main menu.\n", packageID, version)
|
|
70
90
|
os.Exit(2)
|
|
@@ -118,6 +138,11 @@ func main() {
|
|
|
118
138
|
if standalone != nil {
|
|
119
139
|
handler = standalone.Wrap(handler)
|
|
120
140
|
}
|
|
141
|
+
descriptorAuth, err := dsm.NewEntryGate(dsm.NewAuthenticator(), entry, packageID, cfg.DataDir)
|
|
142
|
+
if err != nil {
|
|
143
|
+
log.Fatal(err)
|
|
144
|
+
}
|
|
145
|
+
handler = api.WithDescription(handler, descriptorAuth, filepath.Join("/var/packages", packageID, "target", api.DescriptionFile))
|
|
121
146
|
if err := cgi.Serve(api.WithRequestDeadline(handler, deadline())); err != nil {
|
|
122
147
|
log.Fatal(err)
|
|
123
148
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
github.com/synopackageland/syno-pkg-land-sdk v0.
|
|
2
|
-
github.com/synopackageland/syno-pkg-land-sdk v0.
|
|
1
|
+
github.com/synopackageland/syno-pkg-land-sdk v0.15.0 h1:M/QoJFpARKzLbK/xRk5GU3FEdCl7drgeO8prgHgD/y4=
|
|
2
|
+
github.com/synopackageland/syno-pkg-land-sdk v0.15.0/go.mod h1:msR4MhJQnVZ8NKLb0E/1K79ldZUvcOJmWhKq+gPEa+4=
|
|
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=
|
|
@@ -89,3 +89,34 @@ capabilities: {}
|
|
|
89
89
|
# state:
|
|
90
90
|
# items:
|
|
91
91
|
# - key: jobs # i18n key uninstall.state.jobs
|
|
92
|
+
|
|
93
|
+
# Explicit AI commands. Internal/UI methods are not automatically exposed.
|
|
94
|
+
ctl:
|
|
95
|
+
enabled: true
|
|
96
|
+
commands:
|
|
97
|
+
status.show:
|
|
98
|
+
cli: [status]
|
|
99
|
+
summary: Show this App's status and verified caller
|
|
100
|
+
effect: read
|
|
101
|
+
flow: {type: invoke, method: app.status}
|
|
102
|
+
paramsSchema: {type: object, additionalProperties: false}
|
|
103
|
+
examples: [{}]
|
|
104
|
+
greeting.get:
|
|
105
|
+
cli: [greeting, get]
|
|
106
|
+
summary: Read the greeting
|
|
107
|
+
effect: read
|
|
108
|
+
flow: {type: invoke, method: greeting.get}
|
|
109
|
+
paramsSchema: {type: object, additionalProperties: false}
|
|
110
|
+
examples: [{}]
|
|
111
|
+
greeting.set:
|
|
112
|
+
cli: [greeting, set]
|
|
113
|
+
summary: Set the greeting
|
|
114
|
+
effect: write
|
|
115
|
+
flow: {type: invoke, method: greeting.set}
|
|
116
|
+
paramsSchema:
|
|
117
|
+
type: object
|
|
118
|
+
required: [text]
|
|
119
|
+
additionalProperties: false
|
|
120
|
+
properties:
|
|
121
|
+
text: {type: string, minLength: 1, maxLength: 200, description: Greeting text, examples: [Hello]}
|
|
122
|
+
examples: [{text: Hello}]
|
|
@@ -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.
|
|
10
|
+
"@synopackageland/sdk": "0.15.0",
|
|
11
11
|
"@synopackageland/ui": "0.11.4",
|
|
12
12
|
"vue": "3.5.43"
|
|
13
13
|
},
|
|
@@ -1148,9 +1148,9 @@
|
|
|
1148
1148
|
}
|
|
1149
1149
|
},
|
|
1150
1150
|
"node_modules/@synopackageland/sdk": {
|
|
1151
|
-
"version": "0.
|
|
1152
|
-
"resolved": "https://registry.npmjs.org/@synopackageland/sdk/-/sdk-0.
|
|
1153
|
-
"integrity": "sha512-
|
|
1151
|
+
"version": "0.15.0",
|
|
1152
|
+
"resolved": "https://registry.npmjs.org/@synopackageland/sdk/-/sdk-0.15.0.tgz",
|
|
1153
|
+
"integrity": "sha512-Y8NRMedQ96Plex8Ori5SmsiqY8X7edhyyHm7oaot1/PizinyOBrW3zE9ZhjrvSu5Kh6PFwEE+Uz7SM8yK2wJpw==",
|
|
1154
1154
|
"license": "MIT",
|
|
1155
1155
|
"peerDependencies": {
|
|
1156
1156
|
"@lucide/vue": "^1.48.0",
|
|
@@ -49,7 +49,7 @@ backend:
|
|
|
49
49
|
runtime: node
|
|
50
50
|
dir: backend/app
|
|
51
51
|
entry: main.js
|
|
52
|
-
sdk: 0.
|
|
52
|
+
sdk: 0.15.0
|
|
53
53
|
node: { package: Node.js_v20 }
|
|
54
54
|
|
|
55
55
|
ui:
|
|
@@ -80,3 +80,34 @@ i18n:
|
|
|
80
80
|
|
|
81
81
|
# Optional SDK capabilities; delegate/rootOps share administrator-approved executor setup.
|
|
82
82
|
capabilities: {}
|
|
83
|
+
|
|
84
|
+
# Explicit AI commands. Internal/UI methods are not automatically exposed.
|
|
85
|
+
ctl:
|
|
86
|
+
enabled: true
|
|
87
|
+
commands:
|
|
88
|
+
status.show:
|
|
89
|
+
cli: [status]
|
|
90
|
+
summary: Show this App's status and verified caller
|
|
91
|
+
effect: read
|
|
92
|
+
flow: {type: invoke, method: app.status}
|
|
93
|
+
paramsSchema: {type: object, additionalProperties: false}
|
|
94
|
+
examples: [{}]
|
|
95
|
+
greeting.get:
|
|
96
|
+
cli: [greeting, get]
|
|
97
|
+
summary: Read the greeting
|
|
98
|
+
effect: read
|
|
99
|
+
flow: {type: invoke, method: greeting.get}
|
|
100
|
+
paramsSchema: {type: object, additionalProperties: false}
|
|
101
|
+
examples: [{}]
|
|
102
|
+
greeting.set:
|
|
103
|
+
cli: [greeting, set]
|
|
104
|
+
summary: Set the greeting
|
|
105
|
+
effect: write
|
|
106
|
+
flow: {type: invoke, method: greeting.set}
|
|
107
|
+
paramsSchema:
|
|
108
|
+
type: object
|
|
109
|
+
required: [text]
|
|
110
|
+
additionalProperties: false
|
|
111
|
+
properties:
|
|
112
|
+
text: {type: string, minLength: 1, maxLength: 200, description: Greeting text, examples: [Hello]}
|
|
113
|
+
examples: [{text: Hello}]
|
|
@@ -47,7 +47,7 @@ backend:
|
|
|
47
47
|
runtime: python
|
|
48
48
|
dir: backend/app
|
|
49
49
|
entry: main.py
|
|
50
|
-
sdk: 0.
|
|
50
|
+
sdk: 0.15.0
|
|
51
51
|
|
|
52
52
|
ui:
|
|
53
53
|
# Non-UI-SDK frontends open a full page; Portal is a separate opt-in.
|
|
@@ -77,3 +77,34 @@ i18n:
|
|
|
77
77
|
|
|
78
78
|
# Optional SDK capabilities; delegate/rootOps share administrator-approved executor setup.
|
|
79
79
|
capabilities: {}
|
|
80
|
+
|
|
81
|
+
# Explicit AI commands. Internal/UI methods are not automatically exposed.
|
|
82
|
+
ctl:
|
|
83
|
+
enabled: true
|
|
84
|
+
commands:
|
|
85
|
+
status.show:
|
|
86
|
+
cli: [status]
|
|
87
|
+
summary: Show this App's status and verified caller
|
|
88
|
+
effect: read
|
|
89
|
+
flow: {type: invoke, method: app.status}
|
|
90
|
+
paramsSchema: {type: object, additionalProperties: false}
|
|
91
|
+
examples: [{}]
|
|
92
|
+
greeting.get:
|
|
93
|
+
cli: [greeting, get]
|
|
94
|
+
summary: Read the greeting
|
|
95
|
+
effect: read
|
|
96
|
+
flow: {type: invoke, method: greeting.get}
|
|
97
|
+
paramsSchema: {type: object, additionalProperties: false}
|
|
98
|
+
examples: [{}]
|
|
99
|
+
greeting.set:
|
|
100
|
+
cli: [greeting, set]
|
|
101
|
+
summary: Set the greeting
|
|
102
|
+
effect: write
|
|
103
|
+
flow: {type: invoke, method: greeting.set}
|
|
104
|
+
paramsSchema:
|
|
105
|
+
type: object
|
|
106
|
+
required: [text]
|
|
107
|
+
additionalProperties: false
|
|
108
|
+
properties:
|
|
109
|
+
text: {type: string, minLength: 1, maxLength: 200, description: Greeting text, examples: [Hello]}
|
|
110
|
+
examples: [{text: Hello}]
|
|
@@ -104,8 +104,8 @@ dependencies = [
|
|
|
104
104
|
|
|
105
105
|
[[package]]
|
|
106
106
|
name = "syno-pkg-land-app"
|
|
107
|
-
version = "0.
|
|
108
|
-
source = "git+https://github.com/synopackageland/syno-pkg-land-sdk?tag=v0.
|
|
107
|
+
version = "0.15.0"
|
|
108
|
+
source = "git+https://github.com/synopackageland/syno-pkg-land-sdk?tag=v0.15.0#a68ee74f311b2fa7b980330c340bd61bd146aec4"
|
|
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.
|
|
12
|
+
syno-pkg-land-app = { git = "https://github.com/synopackageland/syno-pkg-land-sdk", tag = "v0.15.0" }
|
|
13
13
|
|
|
14
14
|
[profile.release]
|
|
15
15
|
# A handler panic becomes an "internal" reply; abort would end the App without one.
|
|
@@ -78,3 +78,34 @@ i18n:
|
|
|
78
78
|
|
|
79
79
|
# Optional SDK capabilities; delegate/rootOps share administrator-approved executor setup.
|
|
80
80
|
capabilities: {}
|
|
81
|
+
|
|
82
|
+
# Explicit AI commands. Internal/UI methods are not automatically exposed.
|
|
83
|
+
ctl:
|
|
84
|
+
enabled: true
|
|
85
|
+
commands:
|
|
86
|
+
status.show:
|
|
87
|
+
cli: [status]
|
|
88
|
+
summary: Show this App's status and verified caller
|
|
89
|
+
effect: read
|
|
90
|
+
flow: {type: invoke, method: app.status}
|
|
91
|
+
paramsSchema: {type: object, additionalProperties: false}
|
|
92
|
+
examples: [{}]
|
|
93
|
+
greeting.get:
|
|
94
|
+
cli: [greeting, get]
|
|
95
|
+
summary: Read the greeting
|
|
96
|
+
effect: read
|
|
97
|
+
flow: {type: invoke, method: greeting.get}
|
|
98
|
+
paramsSchema: {type: object, additionalProperties: false}
|
|
99
|
+
examples: [{}]
|
|
100
|
+
greeting.set:
|
|
101
|
+
cli: [greeting, set]
|
|
102
|
+
summary: Set the greeting
|
|
103
|
+
effect: write
|
|
104
|
+
flow: {type: invoke, method: greeting.set}
|
|
105
|
+
paramsSchema:
|
|
106
|
+
type: object
|
|
107
|
+
required: [text]
|
|
108
|
+
additionalProperties: false
|
|
109
|
+
properties:
|
|
110
|
+
text: {type: string, minLength: 1, maxLength: 200, description: Greeting text, examples: [Hello]}
|
|
111
|
+
examples: [{text: Hello}]
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
schema: 1
|
|
2
|
-
package: com.synology.hello.files
|
|
3
|
-
version: 0.1.0
|
|
4
|
-
displayname: Hello Files
|
|
5
|
-
description: A minimal headless app with a Shared Folder mount.
|
|
6
|
-
# Package Center and DSM window icon: a square PNG of at least 256x256, or a
|
|
7
|
-
# folder of icon_<size>.png. Omit to use the SDK default icon.
|
|
8
|
-
# icon: assets/icon.png
|
|
9
|
-
maintainer: Syno Package Land
|
|
10
|
-
os_min_ver: "7.2.1-69057"
|
|
11
|
-
|
|
12
|
-
install:
|
|
13
|
-
MEDIA_SHARE:
|
|
14
|
-
type: shared_folder
|
|
15
|
-
RUN_AS:
|
|
16
|
-
type: dsm_user
|
|
17
|
-
|
|
18
|
-
# For a web frontend, declare adminport/adminurl and explicitly choose:
|
|
19
|
-
# integration:
|
|
20
|
-
# web:
|
|
21
|
-
# launch: new-page
|
|
22
|
-
# No Application Portal declaration is needed. Omitted web launch means new-page.
|