@synopackageland/templates 0.40.2 → 0.40.4

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.
Files changed (34) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +40 -1
  3. package/package.json +1 -1
  4. package/templates/_shared/AGENTS.md +21 -2
  5. package/templates/_shared/tests/local/package.test.mjs +1 -1
  6. package/templates/binary/.env.example +5 -0
  7. package/templates/binary/README.md +18 -0
  8. package/templates/binary/gitignore +6 -0
  9. package/templates/compose/.env.example +5 -0
  10. package/templates/compose/README.md +27 -0
  11. package/templates/compose/gitignore +6 -0
  12. package/templates/native-go/.env.example +5 -0
  13. package/templates/native-go/README.md +40 -1
  14. package/templates/native-go/backend/internal/app/background_test.go +17 -2
  15. package/templates/native-go/gitignore +6 -0
  16. package/templates/native-go-jobs/backend/internal/app/background_routes_test.go +12 -7
  17. package/templates/native-go-vue/README.md +29 -1
  18. package/templates/native-go-vue/gitignore +6 -0
  19. package/templates/native-node/.env.example +5 -0
  20. package/templates/native-node/README.md +19 -2
  21. package/templates/native-node/dsm-package.yaml +1 -1
  22. package/templates/native-node/gitignore +6 -0
  23. package/templates/native-node-vue/README.md +18 -1
  24. package/templates/native-node-vue/gitignore +6 -0
  25. package/templates/native-python/.env.example +5 -0
  26. package/templates/native-python/README.md +18 -1
  27. package/templates/native-python/gitignore +6 -0
  28. package/templates/native-python-vue/README.md +18 -1
  29. package/templates/native-python-vue/gitignore +6 -0
  30. package/templates/native-rust/.env.example +5 -0
  31. package/templates/native-rust/README.md +18 -1
  32. package/templates/native-rust/gitignore +6 -0
  33. package/templates/native-rust-vue/README.md +18 -1
  34. package/templates/native-rust-vue/gitignore +6 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.40.4
4
+
5
+ - Ignore private environment variants, key and certificate files, and npm credentials in every scaffold while keeping `.env.example` trackable
6
+ - Include placeholder-only environment examples for the optional AI tests
7
+ - Document secret storage under `synology/` for upstream forks without changing upstream ignore files
8
+ - Verify Git ignore behavior for every template and UI variant, including upstream forks, using the packed templates and actual CLI
9
+
10
+ ## 0.40.3
11
+
12
+ - Use CLI architecture names in local package tests and SDK constants in background-limit assertions
13
+ - Exercise earlier request deadlines in journal-lock tests without waiting for the SDK's full operation allowance
14
+ - Install scaffold test and build tools with `--include=dev`, including when `NODE_ENV=production`
15
+ - Explain the upstream-web-only `ui: false` layout, retained entry-gate files and removable browser examples
16
+ - Smoke-test freshly generated projects for every template and native UI variant with the current CLI
17
+
3
18
  ## 0.40.2
4
19
 
5
20
  - Include independent examples and npm scripts for local unit and registry contracts, local package checks, real-NAS ctl, deterministic UI outcomes and optional AI actions
package/README.md CHANGED
@@ -216,8 +216,18 @@ scripts/assemble.sh --language rust /tmp/app-rs plain jobs # python, node or ru
216
216
  scripts/gate.sh # layout, every combination, binary, npm pack
217
217
  scripts/gate.sh --fast # only the combinations the changes reach
218
218
  scripts/assemble.sh --list vue jobs # the templates a combination uses
219
+ SYNOPKGLAND_CLI="$(command -v synopkgland)" node --test scripts/test/scaffold.test.mjs
219
220
  ```
220
221
 
222
+ The gate installs the CLI range declared by the shared scaffold into its temporary
223
+ directory, or uses the executable in `SYNOPKGLAND_CLI`. Its existing `node:test`
224
+ harness runs real CLI init for every template and both native UI variants,
225
+ then each generated project's default `npm test`. Native projects assert the
226
+ starter operation; binary and Compose report the expected skip because they
227
+ have no starter registry. One plain native project also runs its generated
228
+ `test:local` check/build/inspect tier. Backend tests and Vue builds stay in the
229
+ existing combination checks; Rust builds and frontend checks run on the Docker host.
230
+
221
231
  Without `SYNOPKGLAND_SDK_DIR` the combinations use the released SDK that
222
232
  `backend/go.mod` and `frontend/package.json` pin. With it, `assemble.sh` adds
223
233
  `replace github.com/synopackageland/syno-pkg-land-sdk => $SYNOPKGLAND_SDK_DIR`
@@ -344,10 +354,39 @@ configuration and DSM service definition, and upgrades retain the selection.
344
354
  Changing ports uses reinstall. Declare `{port: gateway_https}` runtime bindings
345
355
  when an upstream application needs its public port in its own configuration.
346
356
 
357
+ ## Secret files
358
+
359
+ Every scaffold ignores `.env`, `.env.*`, `*.pem`, `*.key`, `*.p12` and `.npmrc`
360
+ at any depth within its project. `.env.example` remains trackable and contains
361
+ only placeholders for the optional AI tests; those commands load `.env` from
362
+ their working directory. Copy the example only when configuring those tests.
363
+ Keep real credentials out of examples and commits.
364
+
365
+ Templates ship ignore files as `gitignore` because npm excludes `.gitignore`;
366
+ `synopkgland init` restores the `.gitignore` name in the generated project.
367
+ The scaffold tests use the actual packed templates to verify that behavior.
368
+
369
+ ### Upstream fork secret storage
370
+
371
+ For `init --upstream-fork`, all wrapper-owned files belong in `synology/`.
372
+ Store secrets in **`synology/.env`, never the fork root**, and run the optional
373
+ tests from `synology/`. Copy `synology/.env.example` only when configuring the
374
+ optional AI tests. Keep keys, certificates and private npm configuration under
375
+ `synology/` as well.
376
+
377
+ The upstream root `.gitignore` is not ours to edit and may not ignore a root
378
+ `.env`. The generated `synology/.gitignore` protects secrets inside `synology/`;
379
+ it cannot protect files in the parent directory. Preserve upstream ignore files
380
+ and history. Use the CLI's `synopkgland skill show upstream-fork` for the rest of
381
+ the fork workflow.
382
+
347
383
  ## App-open smoke
348
384
 
349
385
  Every generated project includes `tests/e2e/smoke.e2e.ts`, `e2e.config.ts` and
350
- a root `package.json`. Run `npm install` at the project root, install Chromium once with
386
+ a root `package.json`. Run `npm install --include=dev` at the project root
387
+ (or `npm ci --include=dev` after committing its lockfile).
388
+ `NODE_ENV=production` skips devDependencies; `test:local` needs the CLI.
389
+ Install Chromium once with
351
390
  `npx @e2e-dev/web install chromium`, then run `npm run e2e:smoke`. Set `DSM_E2E_SSH` and private mode-600 account files in
352
391
  `DSM_E2E_ACCOUNT_ADMIN` and `DSM_E2E_ACCOUNT_NORMAL`; grant the normal account
353
392
  Application Privileges first. Missing normal credentials/profile produces a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synopackageland/templates",
3
- "version": "0.40.2",
3
+ "version": "0.40.4",
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": {
@@ -22,7 +22,7 @@ sections at the end name each language's files, types and test commands.
22
22
 
23
23
  From the project root, run `synopkgland check --json`,
24
24
  `synopkgland build --json`, then `synopkgland inspect <spk> --json` on the emitted SPK.
25
- For Vue, first run `npm ci` and `npm run build` in frontend. Run its tests only if the user chose tests.
25
+ For Vue, first run `npm ci --include=dev` and `npm run build` in frontend. Run its tests only if the user chose tests.
26
26
  Do not connect to or change a NAS without explicit task authorization.
27
27
 
28
28
  ## Optional testing
@@ -33,6 +33,11 @@ on tests. Scaffolding is included by default; writing and running tests are opti
33
33
  Read `synopkgland skill show testing` when setting up or extending tests.
34
34
 
35
35
  The default `npm test` runs only fast local unit/ctl registry contracts.
36
+ At the project root, run `npm install --include=dev` first; after committing its
37
+ lockfile, use `npm ci --include=dev`.
38
+ `NODE_ENV=production` skips devDependencies; `test:local` needs the CLI and frontend builds need dev tools.
39
+ Before `test:local`, prepare the backend/frontend as described below and run
40
+ `synopkgland ctl generate` for a native App.
36
41
  `npm run test:local` opts into check/build/inspect. Only on explicit user request,
37
42
  run `npm run test:nas:ctl`, `npm run e2e:smoke`, `npm run e2e:ui` or `npm run e2e:ai`.
38
43
  The full suite is slow. Never call these from build, install, DSM hooks or release.
@@ -49,6 +54,20 @@ the cheapest adequate model and low effort; never default to an expensive model.
49
54
  Use E2E_LLM_BASE_URL, E2E_LLM_MODEL, E2E_LLM_API_KEY_FILE (mode 600) or
50
55
  E2E_LLM_API_KEY, and optional E2E_LLM_REASONING_EFFORT (default low).
51
56
 
57
+ ## Upstream web UI only
58
+
59
+ For an `--upstream-fork` wrapper whose only UI is the upstream web panel, set
60
+ `ui: false` in `synology/dsm-package.yaml` and configure `identity_gateway`
61
+ for that panel. `--ui plain` selects `ui/app.js`; it does not mean `ui: false`.
62
+ The current scaffold still creates UI and browser-test examples: remove
63
+ `synology/ui/` (or `synology/frontend/` for Vue), `synology/tests/e2e/`,
64
+ `synology/e2e.config.ts` and `synology/e2e.ai.config.ts`, and remove the
65
+ `e2e:*` scripts from `synology/package.json`.
66
+ Keep `synology/backend/`, `synology/i18n/messages/`, `synology/operations.json` and
67
+ the local/ctl tests: the entry gate still needs the backend and message catalogs.
68
+ Read `synopkgland skill show upstream-fork` and
69
+ `synopkgland skill show orchestrator` for the wrapper workflow.
70
+
52
71
  ## Lifecycle scripts (`dsm-scripts/`)
53
72
 
54
73
  `dsm-scripts/` holds DSM's own lifecycle scripts (preinst, postinst, preupgrade,
@@ -371,7 +390,7 @@ their capabilities with `synopkgland init --with`.
371
390
  `new AppError(code, message)`, `AppError.badRequest(message)`. Call services
372
391
  through `service(ctx, op, params)` (`service.ts`), which passes the runtime's
373
392
  refusals on; a bare `ctx.runtime` refusal would reach the browser as `internal`.
374
- - Test with `(cd backend && npm ci && npm test && npm run typecheck)`; `test/support.ts`'s
393
+ - Test with `(cd backend && npm ci --include=dev && npm test && npm run typecheck)`; `test/support.ts`'s
375
394
  `call` plays the runtime.
376
395
 
377
396
  ## Rust backend
@@ -6,7 +6,7 @@ import { cli } from '../support/cli.mjs';
6
6
  // Explicit local build tier; no deployment or NAS connection.
7
7
  test('the App checks, builds and passes package inspection', {timeout: 300_000}, () => {
8
8
  cli('check');
9
- const built = cli('build', '--arch', process.env.APP_TEST_ARCH || 'amd64');
9
+ const built = cli('build', '--arch', process.env.APP_TEST_ARCH || 'x86_64');
10
10
  assert.ok(built.outputs.length > 0);
11
11
  for (const spk of built.outputs) {
12
12
  assert.equal(existsSync(spk), true);
@@ -0,0 +1,5 @@
1
+ # Optional AI tests only: replace these placeholders in your private .env.
2
+ # For an upstream fork, use synology/.env, never the fork root.
3
+ E2E_LLM_BASE_URL=https://api.example.com/v1
4
+ E2E_LLM_MODEL=replace-with-model
5
+ E2E_LLM_API_KEY=replace-with-api-key
@@ -0,0 +1,18 @@
1
+ # __DISPLAY_NAME__
2
+
3
+ ## Local tests
4
+
5
+ Copy `.env.example` to the ignored `.env` only for optional AI tests; keep real credentials out of examples and commits.
6
+
7
+ From the project root, install the test tools before running the optional tests:
8
+
9
+ ```sh
10
+ npm install --include=dev
11
+ npm test
12
+ ```
13
+
14
+ `NODE_ENV=production` skips devDependencies; `test:local` needs the CLI.
15
+ After committing the generated root lockfile, use `npm ci --include=dev`.
16
+ The scaffold provides example prebuilt binaries; replace them with your own
17
+ Linux binaries before packaging. See `AGENTS.md` for the package workflow.
18
+
@@ -4,3 +4,9 @@ dist/
4
4
  # Private NAS smoke sessions and credentials
5
5
  .e2e/
6
6
  .env
7
+ .env.*
8
+ !.env.example
9
+ *.pem
10
+ *.key
11
+ *.p12
12
+ .npmrc
@@ -0,0 +1,5 @@
1
+ # Optional AI tests only: replace these placeholders in your private .env.
2
+ # For an upstream fork, use synology/.env, never the fork root.
3
+ E2E_LLM_BASE_URL=https://api.example.com/v1
4
+ E2E_LLM_MODEL=replace-with-model
5
+ E2E_LLM_API_KEY=replace-with-api-key
@@ -0,0 +1,27 @@
1
+ # __DISPLAY_NAME__
2
+
3
+ ## Local tests
4
+
5
+ Copy `.env.example` to the ignored `.env` only for optional AI tests; keep real credentials out of examples and commits.
6
+
7
+ From the project root, install the test tools before running the optional tests:
8
+
9
+ ```sh
10
+ npm install --include=dev
11
+ npm test
12
+ ```
13
+
14
+ `NODE_ENV=production` skips devDependencies; `test:local` needs the CLI.
15
+ After committing the generated root lockfile, use `npm ci --include=dev`.
16
+ Configure the upstream image and its real readiness endpoint before
17
+ `test:local`; see `AGENTS.md` for the Compose packaging workflow.
18
+
19
+ ## Secrets in an upstream fork
20
+
21
+ With `--upstream-fork`, store secrets in `synology/.env`, never in the fork root.
22
+ Run the optional tests from `synology/`; its `.gitignore` protects `.env`,
23
+ `.env.*`, `*.pem`, `*.key`, `*.p12` and `.npmrc`, while `.env.example` remains
24
+ trackable with placeholders only. The upstream root `.gitignore` is not ours
25
+ to edit and may not ignore a root `.env`.
26
+ See the [fork guide](https://github.com/synopackageland/syno-pkg-land-templates#upstream-fork-secret-storage).
27
+
@@ -1,5 +1,11 @@
1
1
  node_modules/
2
2
  .e2e/
3
3
  .env
4
+ .env.*
5
+ !.env.example
6
+ *.pem
7
+ *.key
8
+ *.p12
9
+ .npmrc
4
10
  dist/
5
11
  *.spk
@@ -0,0 +1,5 @@
1
+ # Optional AI tests only: replace these placeholders in your private .env.
2
+ # For an upstream fork, use synology/.env, never the fork root.
3
+ E2E_LLM_BASE_URL=https://api.example.com/v1
4
+ E2E_LLM_MODEL=replace-with-model
5
+ E2E_LLM_API_KEY=replace-with-api-key
@@ -25,10 +25,36 @@ independent package-account worker and report phase/progress. Authenticate
25
25
  status/result polling by that ID; a slow NAS or failed status read leaves the
26
26
  last queued/running state intact. After a lost admission reply, reuse the same
27
27
  idempotency key and input instead of replaying a mutation with a new key.
28
- Jobs default to 30 minutes; approved executor limits remain separate. ctl keeps
28
+ Jobs use the SDK's default operation allowance; approved executor limits remain separate. ctl keeps
29
29
  its 62-second transport default; use an explicit `--timeout` or an existing
30
30
  nonblocking job. See the SDK's [request deadline contract](https://github.com/synopackageland/syno-pkg-land-sdk/blob/main/docs/request-deadlines.md).
31
31
 
32
+ ## Local tests
33
+
34
+ Copy `.env.example` to the ignored `.env` only for optional AI tests; keep real credentials out of examples and commits.
35
+
36
+ From the project root, install the test tools before running the optional tests:
37
+
38
+ ```sh
39
+ npm install --include=dev
40
+ npm test
41
+ ```
42
+
43
+ `NODE_ENV=production` skips devDependencies; `test:local` needs the CLI.
44
+ After committing the generated root lockfile, use `npm ci --include=dev`.
45
+ Before `npm run test:local`, prepare the backend and, for Vue, build the
46
+ frontend using the steps below and the backend section in `AGENTS.md`, then
47
+ run `synopkgland ctl generate`.
48
+
49
+ ## Secrets in an upstream fork
50
+
51
+ With `--upstream-fork`, store secrets in `synology/.env`, never in the fork root.
52
+ Run the optional tests from `synology/`; its `.gitignore` protects `.env`,
53
+ `.env.*`, `*.pem`, `*.key`, `*.p12` and `.npmrc`, while `.env.example` remains
54
+ trackable with placeholders only. The upstream root `.gitignore` is not ours
55
+ to edit and may not ignore a root `.env`.
56
+ See the [fork guide](https://github.com/synopackageland/syno-pkg-land-templates#upstream-fork-secret-storage).
57
+
32
58
  ## Quick start
33
59
 
34
60
  Needs Node.js with `synopkgland` installed, and Go 1.26.10.
@@ -443,3 +469,16 @@ Draft writes require a non-mutating preview and explicit human confirmation.
443
469
  Long operations use the existing job flow; tools own polling and pagination.
444
470
 
445
471
  Use a matching SDK/CLI/templates release containing the registry support.
472
+
473
+ ## Upstream web UI only
474
+
475
+ `init --upstream-fork --ui plain` still creates a plain SDK UI; it does not
476
+ select `ui: false`. For an upstream web panel with no SDK UI, set `ui: false`
477
+ in `synology/dsm-package.yaml` and configure `identity_gateway` for the panel.
478
+ Remove `synology/ui/` (or `synology/frontend/` for Vue),
479
+ `synology/tests/e2e/`, `synology/e2e.config.ts` and
480
+ `synology/e2e.ai.config.ts`, and remove the `e2e:*` npm scripts.
481
+ Keep `synology/backend/`, `synology/i18n/messages/`, `synology/operations.json` and
482
+ the local/ctl tests: the entry gate still needs the backend and message catalogs.
483
+ Read `synopkgland skill show upstream-fork` and
484
+ `synopkgland skill show orchestrator` for the wrapper workflow.
@@ -34,6 +34,10 @@ func newBgEnv(t *testing.T) *bgEnv {
34
34
  }
35
35
 
36
36
  func (e *bgEnv) call(auth api.Authenticator, method, params string) (string, map[string]any) {
37
+ return e.callContext(context.Background(), auth, method, params)
38
+ }
39
+
40
+ func (e *bgEnv) callContext(ctx context.Context, auth api.Authenticator, method, params string) (string, map[string]any) {
37
41
  e.t.Helper()
38
42
  // SDK policy provides owner routes immediately.
39
43
  routes := newBackgroundRoutes(e.store, e.dataDir)
@@ -42,6 +46,7 @@ func (e *bgEnv) call(auth api.Authenticator, method, params string) (string, map
42
46
  e.t.Fatal(err)
43
47
  }
44
48
  req := httptest.NewRequest(http.MethodPost, "/api.cgi", strings.NewReader(`{"method":"`+method+`","params":`+params+`}`))
49
+ req = req.WithContext(ctx)
45
50
  req.Header.Set("Content-Type", "application/json")
46
51
  req.Header.Set("Sec-Fetch-Site", "same-origin")
47
52
  rec := httptest.NewRecorder()
@@ -112,8 +117,18 @@ func TestBackgroundStatusReportsLimitsAndWorker(t *testing.T) {
112
117
  t.Fatalf("%s %v", code, out)
113
118
  }
114
119
  limits := d["limits"].(map[string]any)
115
- if limits["maxInputBytes"].(float64) != 512*1024 || limits["maxQueued"].(float64) != 16 || limits["maxTotalBytes"].(float64) != 16<<20 || limits["jobTimeoutSeconds"].(float64) != 30*60 {
116
- t.Fatalf("limits: %v", limits)
120
+ for name, want := range map[string]float64{
121
+ "maxInputBytes": background.MaxInputBytes,
122
+ "maxQueued": background.MaxQueued,
123
+ "maxSchedules": background.MaxSchedules,
124
+ "maxTotalBytes": background.MaxTotalBytes,
125
+ "maxOwnerPending": background.MaxOwnerPending,
126
+ "maxOwnerBytes": background.MaxOwnerBytes,
127
+ "jobTimeoutSeconds": background.JobTimeout.Seconds(),
128
+ } {
129
+ if got := limits[name]; got != want {
130
+ t.Errorf("limits[%q] = %v, want %v", name, got, want)
131
+ }
117
132
  }
118
133
  info := background.WorkerInfo{PID: os.Getpid(), UID: os.Getuid(), Username: "pkg"}
119
134
  if err := e.store.Heartbeat(context.Background(), info); err != nil {
@@ -3,3 +3,9 @@ dist/
3
3
  # Private NAS smoke sessions and credentials
4
4
  .e2e/
5
5
  .env
6
+ .env.*
7
+ !.env.example
8
+ *.pem
9
+ *.key
10
+ *.p12
11
+ .npmrc
@@ -52,7 +52,7 @@ func TestBackgroundBusyErrorCode(t *testing.T) {
52
52
  }
53
53
  }
54
54
 
55
- func TestBackgroundRequestSubmitBusyAndProductionConstruction(t *testing.T) {
55
+ func TestBackgroundRequestSubmitDeadlineAndProductionConstruction(t *testing.T) {
56
56
  e := newBgEnv(t)
57
57
  dir := filepath.Join(t.TempDir(), "background")
58
58
  e.store = background.NewRequestStore(dir)
@@ -68,12 +68,17 @@ func TestBackgroundRequestSubmitBusyAndProductionConstruction(t *testing.T) {
68
68
  t.Fatal(err)
69
69
  }
70
70
  defer syscall.Flock(int(f.Fd()), syscall.LOCK_UN)
71
+ // Use an earlier caller deadline instead of waiting for the SDK's full
72
+ // operation allowance. The API reports that deadline, not jobs_busy.
73
+ budget := min(50*time.Millisecond, background.RequestLockTimeout/2)
74
+ ctx, cancel := context.WithTimeout(context.Background(), budget)
75
+ defer cancel()
71
76
  start := time.Now()
72
- code, out := e.call(alice, "bg.jobs.submit", e.submitParams("k1"))
73
- if code != "jobs_busy" || time.Since(start) > background.RequestLockTimeout+time.Second {
74
- t.Fatalf("busy submit: %s %+v", code, out)
77
+ code, out := e.callContext(ctx, alice, "bg.jobs.submit", e.submitParams("k1"))
78
+ if code != "request_timeout" || time.Since(start) > budget+time.Second {
79
+ t.Fatalf("submit deadline: %s %+v", code, out)
75
80
  }
76
- // The actual production assembly must use the same bounded wait policy.
81
+ // The production route assembly must also honor an earlier request deadline.
77
82
  srv, err := api.NewServerWithPermissions(alice, []byte(`{"schema":1,"default":"administrators","methods":{}}`), BackgroundRoutes(filepath.Dir(dir))...)
78
83
  if err != nil {
79
84
  t.Fatal(err)
@@ -82,8 +87,8 @@ func TestBackgroundRequestSubmitBusyAndProductionConstruction(t *testing.T) {
82
87
  r.Header.Set("Content-Type", "application/json")
83
88
  r.Header.Set("Sec-Fetch-Site", "same-origin")
84
89
  w := httptest.NewRecorder()
85
- srv.ServeHTTP(w, r)
86
- if !strings.Contains(w.Body.String(), `"jobs_busy"`) {
90
+ api.WithRequestDeadline(srv, api.Timeout(budget)).ServeHTTP(w, r)
91
+ if !strings.Contains(w.Body.String(), `"request_timeout"`) {
87
92
  t.Fatal(w.Body.String())
88
93
  }
89
94
  }
@@ -7,9 +7,37 @@ files, portal, jobs and delegate components come from `@synopackageland/sdk/vue`
7
7
  `github.com/synopackageland/syno-pkg-land-sdk` version in `backend/go.mod`. See
8
8
  <https://github.com/synopackageland/syno-pkg-land-sdk> for the components and their props.
9
9
 
10
+ ## Local tests
11
+
12
+ Copy `.env.example` to the ignored `.env` only for optional AI tests; keep real credentials out of examples and commits.
13
+
14
+ From the project root, install the test tools before running the optional tests:
15
+
16
+ ```sh
17
+ npm install --include=dev
18
+ npm test
19
+ ```
20
+
21
+ `NODE_ENV=production` skips devDependencies; `test:local` needs the CLI.
22
+ After committing the generated root lockfile, use `npm ci --include=dev`.
23
+ Before `npm run test:local`, prepare the backend and, for Vue, build the
24
+ frontend using the steps below and the backend section in `AGENTS.md`, then
25
+ run `synopkgland ctl generate`.
26
+
27
+ ## Secrets in an upstream fork
28
+
29
+ With `--upstream-fork`, store secrets in `synology/.env`, never in the fork root.
30
+ Run the optional tests from `synology/`; its `.gitignore` protects `.env`,
31
+ `.env.*`, `*.pem`, `*.key`, `*.p12` and `.npmrc`, while `.env.example` remains
32
+ trackable with placeholders only. The upstream root `.gitignore` is not ours
33
+ to edit and may not ignore a root `.env`.
34
+ See the [fork guide](https://github.com/synopackageland/syno-pkg-land-templates#upstream-fork-secret-storage).
35
+
36
+ ## Frontend
37
+
10
38
  ```sh
11
39
  cd frontend
12
- npm ci
40
+ npm ci --include=dev
13
41
  npm test
14
42
  npm run build
15
43
  ```
@@ -4,3 +4,9 @@ node_modules/
4
4
  # Private NAS smoke sessions and credentials
5
5
  .e2e/
6
6
  .env
7
+ .env.*
8
+ !.env.example
9
+ *.pem
10
+ *.key
11
+ *.p12
12
+ .npmrc
@@ -0,0 +1,5 @@
1
+ # Optional AI tests only: replace these placeholders in your private .env.
2
+ # For an upstream fork, use synology/.env, never the fork root.
3
+ E2E_LLM_BASE_URL=https://api.example.com/v1
4
+ E2E_LLM_MODEL=replace-with-model
5
+ E2E_LLM_API_KEY=replace-with-api-key
@@ -25,16 +25,33 @@ independent package-account worker and report phase/progress. Authenticate
25
25
  status/result polling by that ID; a slow NAS or failed status read leaves the
26
26
  last queued/running state intact. After a lost admission reply, reuse the same
27
27
  idempotency key and input instead of replaying a mutation with a new key.
28
- Jobs default to 30 minutes; approved executor limits remain separate. ctl keeps
28
+ Jobs use the SDK's default operation allowance; approved executor limits remain separate. ctl keeps
29
29
  its 62-second transport default; use an explicit `--timeout` or an existing
30
30
  nonblocking job. See the SDK's [request deadline contract](https://github.com/synopackageland/syno-pkg-land-sdk/blob/main/docs/request-deadlines.md).
31
31
 
32
+ ## Local tests
33
+
34
+ Copy `.env.example` to the ignored `.env` only for optional AI tests; keep real credentials out of examples and commits.
35
+
36
+ From the project root, install the test tools before running the optional tests:
37
+
38
+ ```sh
39
+ npm install --include=dev
40
+ npm test
41
+ ```
42
+
43
+ `NODE_ENV=production` skips devDependencies; `test:local` needs the CLI.
44
+ After committing the generated root lockfile, use `npm ci --include=dev`.
45
+ Before `npm run test:local`, prepare the backend and, for Vue, build the
46
+ frontend using the steps below and the backend section in `AGENTS.md`, then
47
+ run `synopkgland ctl generate`.
48
+
32
49
  ## Quick start
33
50
 
34
51
  Needs Node.js 20 or later with `synopkgland` installed. The SPK depends on DSM's **Node.js v20** package (INFO `install_dep_packages`).
35
52
 
36
53
  ```bash
37
- (cd backend && npm ci && npm test && npm run build) # method tests, then app/*.js
54
+ (cd backend && npm ci --include=dev && npm test && npm run build) # method tests, then app/*.js
38
55
  synopkgland ctl generate
39
56
  synopkgland check
40
57
  synopkgland build # → dist/__PACKAGE__-0.1.0-0001-{x86_64,aarch64}.spk
@@ -42,7 +42,7 @@ arches: [x86_64, aarch64]
42
42
  # and app/permissions.json, then runs `node main.js` in backend/app as the
43
43
  # package account, once per call, with Package Center's Node.js (node.package
44
44
  # becomes an install dependency). backend/src compiles to backend/app: run
45
- # `npm ci` and `npm run build` in backend before check and build. sdk is the
45
+ # `npm ci --include=dev` and `npm run build` in backend before check and build. sdk is the
46
46
  # SDK release whose runtime and Node SDK (node_modules/@synopackageland/app)
47
47
  # the build ships; the build reads the methods from `main.js --describe`.
48
48
  backend:
@@ -6,3 +6,9 @@ backend/app/*.js
6
6
  # Private NAS smoke sessions and credentials
7
7
  .e2e/
8
8
  .env
9
+ .env.*
10
+ !.env.example
11
+ *.pem
12
+ *.key
13
+ *.p12
14
+ .npmrc
@@ -7,9 +7,26 @@ delegate components come from `@synopackageland/sdk/vue` (types from
7
7
  `@synopackageland/sdk`); its version must equal the `backend.sdk` in dsm-package.yaml. See
8
8
  <https://github.com/synopackageland/syno-pkg-land-sdk> for the components and their props.
9
9
 
10
+ ## Local tests
11
+
12
+ Copy `.env.example` to the ignored `.env` only for optional AI tests; keep real credentials out of examples and commits.
13
+
14
+ From the project root, install the test tools before running the optional tests:
15
+
16
+ ```sh
17
+ npm install --include=dev
18
+ npm test
19
+ ```
20
+
21
+ `NODE_ENV=production` skips devDependencies; `test:local` needs the CLI.
22
+ After committing the generated root lockfile, use `npm ci --include=dev`.
23
+ Before `npm run test:local`, prepare the backend and, for Vue, build the
24
+ frontend using the steps below and the backend section in `AGENTS.md`, then
25
+ run `synopkgland ctl generate`.
26
+
10
27
  ```sh
11
28
  cd frontend
12
- npm ci
29
+ npm ci --include=dev
13
30
  npm test
14
31
  npm run build
15
32
  ```
@@ -6,3 +6,9 @@ backend/app/*.js
6
6
  # Private NAS smoke sessions and credentials
7
7
  .e2e/
8
8
  .env
9
+ .env.*
10
+ !.env.example
11
+ *.pem
12
+ *.key
13
+ *.p12
14
+ .npmrc
@@ -0,0 +1,5 @@
1
+ # Optional AI tests only: replace these placeholders in your private .env.
2
+ # For an upstream fork, use synology/.env, never the fork root.
3
+ E2E_LLM_BASE_URL=https://api.example.com/v1
4
+ E2E_LLM_MODEL=replace-with-model
5
+ E2E_LLM_API_KEY=replace-with-api-key
@@ -25,10 +25,27 @@ independent package-account worker and report phase/progress. Authenticate
25
25
  status/result polling by that ID; a slow NAS or failed status read leaves the
26
26
  last queued/running state intact. After a lost admission reply, reuse the same
27
27
  idempotency key and input instead of replaying a mutation with a new key.
28
- Jobs default to 30 minutes; approved executor limits remain separate. ctl keeps
28
+ Jobs use the SDK's default operation allowance; approved executor limits remain separate. ctl keeps
29
29
  its 62-second transport default; use an explicit `--timeout` or an existing
30
30
  nonblocking job. See the SDK's [request deadline contract](https://github.com/synopackageland/syno-pkg-land-sdk/blob/main/docs/request-deadlines.md).
31
31
 
32
+ ## Local tests
33
+
34
+ Copy `.env.example` to the ignored `.env` only for optional AI tests; keep real credentials out of examples and commits.
35
+
36
+ From the project root, install the test tools before running the optional tests:
37
+
38
+ ```sh
39
+ npm install --include=dev
40
+ npm test
41
+ ```
42
+
43
+ `NODE_ENV=production` skips devDependencies; `test:local` needs the CLI.
44
+ After committing the generated root lockfile, use `npm ci --include=dev`.
45
+ Before `npm run test:local`, prepare the backend and, for Vue, build the
46
+ frontend using the steps below and the backend section in `AGENTS.md`, then
47
+ run `synopkgland ctl generate`.
48
+
32
49
  ## Quick start
33
50
 
34
51
  Needs Node.js with `synopkgland` installed, and Python 3.8 or later.
@@ -4,3 +4,9 @@ __pycache__/
4
4
  # Private NAS smoke sessions and credentials
5
5
  .e2e/
6
6
  .env
7
+ .env.*
8
+ !.env.example
9
+ *.pem
10
+ *.key
11
+ *.p12
12
+ .npmrc
@@ -7,9 +7,26 @@ delegate components come from `@synopackageland/sdk/vue` (types from
7
7
  `@synopackageland/sdk`); its version must equal the `backend.sdk` in dsm-package.yaml. See
8
8
  <https://github.com/synopackageland/syno-pkg-land-sdk> for the components and their props.
9
9
 
10
+ ## Local tests
11
+
12
+ Copy `.env.example` to the ignored `.env` only for optional AI tests; keep real credentials out of examples and commits.
13
+
14
+ From the project root, install the test tools before running the optional tests:
15
+
16
+ ```sh
17
+ npm install --include=dev
18
+ npm test
19
+ ```
20
+
21
+ `NODE_ENV=production` skips devDependencies; `test:local` needs the CLI.
22
+ After committing the generated root lockfile, use `npm ci --include=dev`.
23
+ Before `npm run test:local`, prepare the backend and, for Vue, build the
24
+ frontend using the steps below and the backend section in `AGENTS.md`, then
25
+ run `synopkgland ctl generate`.
26
+
10
27
  ```sh
11
28
  cd frontend
12
- npm ci
29
+ npm ci --include=dev
13
30
  npm test
14
31
  npm run build
15
32
  ```
@@ -5,3 +5,9 @@ node_modules/
5
5
  # Private NAS smoke sessions and credentials
6
6
  .e2e/
7
7
  .env
8
+ .env.*
9
+ !.env.example
10
+ *.pem
11
+ *.key
12
+ *.p12
13
+ .npmrc
@@ -0,0 +1,5 @@
1
+ # Optional AI tests only: replace these placeholders in your private .env.
2
+ # For an upstream fork, use synology/.env, never the fork root.
3
+ E2E_LLM_BASE_URL=https://api.example.com/v1
4
+ E2E_LLM_MODEL=replace-with-model
5
+ E2E_LLM_API_KEY=replace-with-api-key
@@ -25,10 +25,27 @@ independent package-account worker and report phase/progress. Authenticate
25
25
  status/result polling by that ID; a slow NAS or failed status read leaves the
26
26
  last queued/running state intact. After a lost admission reply, reuse the same
27
27
  idempotency key and input instead of replaying a mutation with a new key.
28
- Jobs default to 30 minutes; approved executor limits remain separate. ctl keeps
28
+ Jobs use the SDK's default operation allowance; approved executor limits remain separate. ctl keeps
29
29
  its 62-second transport default; use an explicit `--timeout` or an existing
30
30
  nonblocking job. See the SDK's [request deadline contract](https://github.com/synopackageland/syno-pkg-land-sdk/blob/main/docs/request-deadlines.md).
31
31
 
32
+ ## Local tests
33
+
34
+ Copy `.env.example` to the ignored `.env` only for optional AI tests; keep real credentials out of examples and commits.
35
+
36
+ From the project root, install the test tools before running the optional tests:
37
+
38
+ ```sh
39
+ npm install --include=dev
40
+ npm test
41
+ ```
42
+
43
+ `NODE_ENV=production` skips devDependencies; `test:local` needs the CLI.
44
+ After committing the generated root lockfile, use `npm ci --include=dev`.
45
+ Before `npm run test:local`, prepare the backend and, for Vue, build the
46
+ frontend using the steps below and the backend section in `AGENTS.md`, then
47
+ run `synopkgland ctl generate`.
48
+
32
49
  ## Quick start
33
50
 
34
51
  Needs Node.js with `synopkgland` installed, Rust through rustup, Zig and `cargo-zigbuild`: `backend/rust-toolchain.toml` pins 1.97.1 with the three DSM targets, so the first `cargo` run installs them.
@@ -4,3 +4,9 @@ backend/target/
4
4
  # Private NAS smoke sessions and credentials
5
5
  .e2e/
6
6
  .env
7
+ .env.*
8
+ !.env.example
9
+ *.pem
10
+ *.key
11
+ *.p12
12
+ .npmrc
@@ -7,9 +7,26 @@ delegate components come from `@synopackageland/sdk/vue` (types from
7
7
  `@synopackageland/sdk`); its version must equal the `syno-pkg-land-app` tag in backend/Cargo.toml. See
8
8
  <https://github.com/synopackageland/syno-pkg-land-sdk> for the components and their props.
9
9
 
10
+ ## Local tests
11
+
12
+ Copy `.env.example` to the ignored `.env` only for optional AI tests; keep real credentials out of examples and commits.
13
+
14
+ From the project root, install the test tools before running the optional tests:
15
+
16
+ ```sh
17
+ npm install --include=dev
18
+ npm test
19
+ ```
20
+
21
+ `NODE_ENV=production` skips devDependencies; `test:local` needs the CLI.
22
+ After committing the generated root lockfile, use `npm ci --include=dev`.
23
+ Before `npm run test:local`, prepare the backend and, for Vue, build the
24
+ frontend using the steps below and the backend section in `AGENTS.md`, then
25
+ run `synopkgland ctl generate`.
26
+
10
27
  ```sh
11
28
  cd frontend
12
- npm ci
29
+ npm ci --include=dev
13
30
  npm test
14
31
  npm run build
15
32
  ```
@@ -5,3 +5,9 @@ backend/target/
5
5
  # Private NAS smoke sessions and credentials
6
6
  .e2e/
7
7
  .env
8
+ .env.*
9
+ !.env.example
10
+ *.pem
11
+ *.key
12
+ *.p12
13
+ .npmrc