@synopackageland/cli 0.14.1 → 0.15.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.
Files changed (121) hide show
  1. package/CHANGELOG.md +20 -1
  2. package/README.md +33 -18
  3. package/dist/build-spk/generator.d.ts +3 -2
  4. package/dist/build-spk/generator.js +6 -846
  5. package/dist/build-spk/resource-worker.d.ts +2 -14
  6. package/dist/build-spk/resource-worker.js +3 -166
  7. package/dist/cli.js +208 -56
  8. package/dist/compose/analyze.d.ts +3 -61
  9. package/dist/compose/analyze.js +35 -776
  10. package/dist/compose/env.d.ts +5 -3
  11. package/dist/compose/env.js +17 -25
  12. package/dist/compose/runner.js +23 -6
  13. package/dist/contract/unsupported-types.js +1 -1
  14. package/dist/contract/validate.js +2 -2
  15. package/dist/contract/web-launch.d.ts +1 -12
  16. package/dist/contract/web-launch.js +10 -74
  17. package/dist/ctl/cli.d.ts +36 -0
  18. package/dist/ctl/cli.js +218 -0
  19. package/dist/ctl/descriptor.d.ts +81 -0
  20. package/dist/ctl/descriptor.js +93 -0
  21. package/dist/ctl/dsm-auth.d.ts +10 -0
  22. package/dist/ctl/dsm-auth.js +30 -0
  23. package/dist/ctl/errors.d.ts +17 -0
  24. package/dist/ctl/errors.js +32 -0
  25. package/dist/ctl/flows.d.ts +11 -0
  26. package/dist/ctl/flows.js +52 -0
  27. package/dist/ctl/input.d.ts +20 -0
  28. package/dist/ctl/input.js +128 -0
  29. package/dist/ctl/json.d.ts +2 -0
  30. package/dist/ctl/json.js +38 -0
  31. package/dist/ctl/redaction.d.ts +15 -0
  32. package/dist/ctl/redaction.js +198 -0
  33. package/dist/ctl/service.d.ts +38 -0
  34. package/dist/ctl/service.js +156 -0
  35. package/dist/ctl/store.d.ts +51 -0
  36. package/dist/ctl/store.js +93 -0
  37. package/dist/ctl/transfers.d.ts +14 -0
  38. package/dist/ctl/transfers.js +74 -0
  39. package/dist/ctl/transport.d.ts +11 -0
  40. package/dist/ctl/transport.js +79 -0
  41. package/dist/deploy/deploy.d.ts +4 -3
  42. package/dist/deploy/deploy.js +5 -210
  43. package/dist/deploy/plan.js +26 -7
  44. package/dist/dev.js +5 -4
  45. package/dist/e2e/dsm.d.ts +2 -2
  46. package/dist/e2e/dsm.js +10 -6
  47. package/dist/error-registry.js +1020 -834
  48. package/dist/host/share-permission-lookup.d.ts +1 -1
  49. package/dist/host/share-permission.d.ts +1 -1
  50. package/dist/host/share-permission.js +1 -1
  51. package/dist/info.js +120 -28
  52. package/dist/init.js +188 -64
  53. package/dist/inspect.js +21 -6
  54. package/dist/runtime/executor-digests.json +5 -5
  55. package/dist/skill.js +51 -9
  56. package/dist/standalone/api-description-inspect.d.ts +4 -0
  57. package/dist/standalone/api-description-inspect.js +12 -0
  58. package/dist/standalone/api-description.d.ts +7 -0
  59. package/dist/standalone/api-description.js +73 -0
  60. package/dist/standalone/build.d.ts +3 -0
  61. package/dist/standalone/build.js +140 -33
  62. package/dist/standalone/compose-errors.d.ts +3 -0
  63. package/dist/standalone/compose-errors.js +243 -0
  64. package/dist/standalone/compose.d.ts +97 -10
  65. package/dist/standalone/compose.js +306 -75
  66. package/dist/standalone/daemon.js +111 -29
  67. package/dist/standalone/dsm-window.js +39 -8
  68. package/dist/standalone/identity-gateway.d.ts +9 -2
  69. package/dist/standalone/identity-gateway.js +282 -66
  70. package/dist/standalone/inspect-spk.d.ts +12 -0
  71. package/dist/standalone/inspect-spk.js +666 -136
  72. package/dist/standalone/lifecycle.js +124 -42
  73. package/dist/standalone/manifest.d.ts +8 -1
  74. package/dist/standalone/manifest.js +303 -86
  75. package/dist/standalone/resource.js +6 -2
  76. package/dist/standalone/spk.d.ts +4 -1
  77. package/dist/standalone/spk.js +138 -39
  78. package/dist/template-paths.d.ts +0 -2
  79. package/dist/template-paths.js +0 -5
  80. package/dist/test-command.d.ts +1 -1
  81. package/dist/test-command.js +1 -1
  82. package/dist/validate.d.ts +3 -3
  83. package/dist/validate.js +32 -140
  84. package/package.json +5 -3
  85. package/schema/synopkgland-api-v1.schema.json +423 -0
  86. package/skills/SKILL.md +4 -2
  87. package/skills/reference/compose.md +349 -0
  88. package/skills/reference/create.md +9 -18
  89. package/skills/reference/ctl.md +41 -0
  90. package/skills/reference/deploy.md +1 -1
  91. package/skills/reference/files.md +5 -1
  92. package/skills/reference/identity-gateway.md +8 -144
  93. package/skills/reference/wrap.md +10 -39
  94. package/assets/go/daemon/fixture_linux_test.go +0 -15
  95. package/assets/go/daemon/fixture_other_test.go +0 -7
  96. package/assets/go/daemon/go.mod +0 -5
  97. package/assets/go/daemon/main.go +0 -636
  98. package/assets/go/daemon/main_test.go +0 -315
  99. package/assets/go/daemon/network.go +0 -107
  100. package/assets/go/daemon/network_test.go +0 -86
  101. package/assets/go/daemon/process_linux.go +0 -55
  102. package/assets/go/daemon/process_linux_test.go +0 -161
  103. package/assets/go/daemon/process_other.go +0 -14
  104. package/assets/go/daemon/testdata/child.go +0 -44
  105. package/assets/go/gateway/auth.go +0 -101
  106. package/assets/go/gateway/auth_test.go +0 -216
  107. package/assets/go/gateway/cgi.go +0 -133
  108. package/assets/go/gateway/cgi_test.go +0 -156
  109. package/assets/go/gateway/csrf.go +0 -73
  110. package/assets/go/gateway/csrf_test.go +0 -155
  111. package/assets/go/gateway/directory.go +0 -108
  112. package/assets/go/gateway/directory_test.go +0 -202
  113. package/assets/go/gateway/gateway.go +0 -412
  114. package/assets/go/gateway/gateway_test.go +0 -676
  115. package/assets/go/gateway/go.mod +0 -5
  116. package/assets/go/gateway/groups.go +0 -66
  117. package/assets/go/gateway/main.go +0 -45
  118. package/dist/build-spk/gateway.d.ts +0 -31
  119. package/dist/build-spk/gateway.js +0 -60
  120. package/dist/compose/privilege.d.ts +0 -14
  121. package/dist/compose/privilege.js +0 -102
@@ -1,37 +1,63 @@
1
1
  import { goChildEnv } from "../runtime/go-env.js";
2
- import { chmodSync, copyFileSync, lstatSync, mkdirSync, readdirSync, realpathSync, writeFileSync } from "node:fs";
2
+ import { chmodSync, copyFileSync, lstatSync, mkdirSync, readdirSync, realpathSync, writeFileSync, } from "node:fs";
3
3
  import { isAbsolute, join, relative, resolve } from "node:path";
4
- import { PINNED_GO_HINT, pinnedGoBuildEnv, pinnedGoProblem } from "../build-spk/go-toolchain.js";
5
- import { goAssetDir } from "../template-paths.js";
4
+ import { PINNED_GO_HINT, pinnedGoBuildEnv, pinnedGoProblem, } from "../build-spk/go-toolchain.js";
5
+ import { sdkSource, appSdkVersion } from "../runtime/sdk-source.js";
6
+ import { CLI_VERSION } from "../cli-version.js";
6
7
  import { checkCgiBinary } from "./binary.js";
7
8
  import { composeDaemon, composeNetwork } from "./compose.js";
8
9
  import { gatewayDaemon } from "./identity-gateway.js";
9
10
  import { StandaloneBuildError } from "./spk.js";
10
- const fields = new Set(["exec", "targets", "args", "env", "timeouts", "uninstall_args"]);
11
+ const fields = new Set([
12
+ "exec",
13
+ "targets",
14
+ "args",
15
+ "env",
16
+ "timeouts",
17
+ "uninstall_args",
18
+ ]);
11
19
  const record = (v) => Boolean(v) && typeof v === "object" && !Array.isArray(v);
12
20
  /** A fixed argv or env value: only the package's own directories expand. */
13
- export const token = (v) => typeof v === "string" && Buffer.byteLength(v) <= 4096 && !v.includes("\0")
14
- && !v.replaceAll("${SYNOPKG_PKGDEST}", "").replaceAll("${SYNOPKG_PKGVAR}", "").includes("${");
21
+ export const token = (v) => typeof v === "string" &&
22
+ Buffer.byteLength(v) <= 4096 &&
23
+ !v.includes("\0") &&
24
+ !v
25
+ .replaceAll("${SYNOPKG_PKGDEST}", "")
26
+ .replaceAll("${SYNOPKG_PKGVAR}", "")
27
+ .includes("${");
15
28
  /** An application variable that cannot steer the loader, the shell or DSM. */
16
- export const envKey = (k) => /^[A-Z][A-Z0-9_]{0,63}$/.test(k)
17
- && !/^(PATH|HOME|TMPDIR|ENV|BASH_ENV|SHELLOPTS|BASHOPTS|GODEBUG|GOTRACEBACK|LD_.*|DYLD_.*|SYNOPKG_.*)$/.test(k);
29
+ export const envKey = (k) => /^[A-Z][A-Z0-9_]{0,63}$/.test(k) &&
30
+ !/^(PATH|HOME|TMPDIR|ENV|BASH_ENV|SHELLOPTS|BASHOPTS|GODEBUG|GOTRACEBACK|LD_.*|DYLD_.*|SYNOPKG_.*)$/.test(k);
18
31
  /** A relative path to a fixed executable, without `.` or `..` parts. */
19
- export const relativeExec = (v) => typeof v === "string" && v.length <= 200
20
- && /^[A-Za-z0-9_-]+(?:\/[A-Za-z0-9_.-]+)*$/.test(v) && !v.split("/").some(p => p === "." || p === "..");
32
+ export const relativeExec = (v) => typeof v === "string" &&
33
+ v.length <= 200 &&
34
+ /^[A-Za-z0-9_-]+(?:\/[A-Za-z0-9_.-]+)*$/.test(v) &&
35
+ !v.split("/").some((p) => p === "." || p === "..");
21
36
  export function readDaemon(value, root, arches, fail) {
22
37
  if (value === undefined)
23
38
  return undefined;
24
- const invalid = () => { fail({ code: "STANDALONE_DAEMON_INVALID", message: "daemon accepts only fixed exec, targets, args, env and timeouts; paths must be inside the project, and the environment does not accept loader/shell/system variables." }); return undefined; };
25
- if (!record(value) || Object.keys(value).some(k => !fields.has(k)))
39
+ const invalid = () => {
40
+ fail({
41
+ code: "STANDALONE_DAEMON_INVALID",
42
+ message: "daemon accepts only fixed exec, targets, args, env and timeouts; paths must be inside the project, and the environment does not accept loader/shell/system variables.",
43
+ });
44
+ return undefined;
45
+ };
46
+ if (!record(value) || Object.keys(value).some((k) => !fields.has(k)))
26
47
  return invalid();
27
48
  if (!relativeExec(value.exec))
28
49
  return invalid();
29
- if (!record(value.targets) || Object.keys(value.targets).length !== arches.length)
50
+ if (!record(value.targets) ||
51
+ Object.keys(value.targets).length !== arches.length)
30
52
  return invalid();
31
53
  const targets = {};
32
54
  for (const arch of arches) {
33
55
  const path = value.targets[arch];
34
- if (typeof path !== "string" || !path.trim() || path.includes("\0") || isAbsolute(path) || path.split(/[\\/]/).includes(".."))
56
+ if (typeof path !== "string" ||
57
+ !path.trim() ||
58
+ path.includes("\0") ||
59
+ isAbsolute(path) ||
60
+ path.split(/[\\/]/).includes(".."))
35
61
  return invalid();
36
62
  const resolved = resolve(root, path), rel = relative(root, resolved);
37
63
  if (!rel || rel.startsWith("..") || isAbsolute(rel))
@@ -42,32 +68,81 @@ export function readDaemon(value, root, arches, fail) {
42
68
  if (!Array.isArray(args) || args.length > 64 || !args.every(token))
43
69
  return invalid();
44
70
  const uninstall = value.uninstall_args;
45
- if (uninstall !== undefined && (!Array.isArray(uninstall) || !uninstall.length || uninstall.length > 64 || !uninstall.every(token)))
71
+ if (uninstall !== undefined &&
72
+ (!Array.isArray(uninstall) ||
73
+ !uninstall.length ||
74
+ uninstall.length > 64 ||
75
+ !uninstall.every(token)))
46
76
  return invalid();
47
77
  const env = value.env ?? {};
48
- if (!record(env) || Object.keys(env).length > 64 || Object.entries(env).some(([k, v]) => !envKey(k) || !token(v)))
78
+ if (!record(env) ||
79
+ Object.keys(env).length > 64 ||
80
+ Object.entries(env).some(([k, v]) => !envKey(k) || !token(v)))
49
81
  return invalid();
50
82
  const limits = value.timeouts ?? {};
51
- if (!record(limits) || Object.keys(limits).some(k => !["start", "stop", "status", "uninstall"].includes(k)))
83
+ if (!record(limits) ||
84
+ Object.keys(limits).some((k) => !["start", "stop", "status", "uninstall"].includes(k)))
52
85
  return invalid();
53
86
  // Defaults hold under IO load on a busy NAS; DSM's package unit allows 3600 s.
54
- const timeouts = { start: limits.start ?? 30, stop: limits.stop ?? 30, status: limits.status ?? 5, uninstall: limits.uninstall ?? 60 };
87
+ const timeouts = {
88
+ start: limits.start ?? 30,
89
+ stop: limits.stop ?? 30,
90
+ status: limits.status ?? 5,
91
+ uninstall: limits.uninstall ?? 60,
92
+ };
55
93
  for (const [key, v] of Object.entries(timeouts)) {
56
- if (!Number.isInteger(v) || v < (key === "status" ? 1 : 2) || v > (key === "status" ? 10 : 120))
94
+ if (!Number.isInteger(v) ||
95
+ v < (key === "status" ? 1 : 2) ||
96
+ v > (key === "status" ? 10 : 120))
57
97
  return invalid();
58
98
  }
59
- return { exec: value.exec, targets, args, ...(uninstall ? { uninstall_args: uninstall } : {}), env: Object.fromEntries(Object.keys(env).sort().map(key => [key, env[key]])), timeouts: timeouts };
99
+ return {
100
+ exec: value.exec,
101
+ targets,
102
+ args,
103
+ ...(uninstall ? { uninstall_args: uninstall } : {}),
104
+ env: Object.fromEntries(Object.keys(env)
105
+ .sort()
106
+ .map((key) => [key, env[key]])),
107
+ timeouts: timeouts,
108
+ };
60
109
  }
61
110
  export function daemonConfig(manifest) {
62
- const { exec, args, uninstall_args, env, timeouts } = manifest.compose ? composeDaemon(manifest) : manifest.identityGateway ? gatewayDaemon(manifest.daemon) : manifest.daemon;
63
- return JSON.stringify({ package: manifest.package, exec, args, ...(uninstall_args ? { uninstall_args } : {}), env, timeouts, ...(manifest.compose ? { network: composeNetwork(manifest) } : {}) }) + "\n";
111
+ const { exec, args, uninstall_args, env, timeouts } = manifest.compose
112
+ ? composeDaemon(manifest)
113
+ : manifest.identityGateway
114
+ ? gatewayDaemon(manifest.daemon)
115
+ : manifest.daemon;
116
+ return (JSON.stringify({
117
+ package: manifest.package,
118
+ exec,
119
+ args,
120
+ ...(uninstall_args ? { uninstall_args } : {}),
121
+ env,
122
+ timeouts,
123
+ ...(manifest.compose ? { network: composeNetwork(manifest) } : {}),
124
+ }) + "\n");
64
125
  }
65
126
  export async function buildDaemonControl(manifest, arch, work, run) {
66
- if (!manifest.daemon && !manifest.compose)
127
+ if (!manifest.daemon && !(manifest.compose && manifest.identityGateway))
67
128
  return undefined;
68
129
  const out = join(work, `daemon-control-${arch}`);
69
- const result = await run("go", ["build", "-trimpath", "-buildvcs=false", "-ldflags", "-s -w -buildid=", "-o", out, "."], {
70
- cwd: goAssetDir("daemon"), env: goChildEnv({ ...process.env, ...pinnedGoBuildEnv(arch) }),
130
+ const result = await run("go", [
131
+ "build",
132
+ "-trimpath",
133
+ "-buildvcs=false",
134
+ "-ldflags",
135
+ "-s -w -buildid=",
136
+ "-o",
137
+ out,
138
+ "./daemonctl",
139
+ ], {
140
+ cwd: sdkSource(manifest.identityGateway?.sdk ??
141
+ (manifest.backend.kind === "go"
142
+ ? appSdkVersion(manifest.backend)
143
+ : undefined) ??
144
+ CLI_VERSION).goDir,
145
+ env: goChildEnv({ ...process.env, ...pinnedGoBuildEnv(arch) }),
71
146
  });
72
147
  if (result.missing || result.status !== 0)
73
148
  throw new StandaloneBuildError("STANDALONE_DAEMON_BUILD_FAILED", `daemon controller build failed (${arch}). ${PINNED_GO_HINT}\n${result.stderr}`);
@@ -82,7 +157,10 @@ export async function buildDaemonControl(manifest, arch, work, run) {
82
157
  export function copyDaemonPayload(manifest, arch, target, controller) {
83
158
  const daemon = manifest.daemon ?? composeDaemon(manifest);
84
159
  const source = daemon.targets[arch];
85
- copyPayloadTree(manifest.root, source, join(target, "payload"));
160
+ if (source)
161
+ copyPayloadTree(manifest.root, source, join(target, "payload"));
162
+ else
163
+ mkdirSync(join(target, "payload"), { recursive: true });
86
164
  if (!manifest.compose) {
87
165
  const exec = join(source, daemon.exec);
88
166
  const problem = checkCgiBinary(manifest.root, exec, arch);
@@ -92,11 +170,15 @@ export function copyDaemonPayload(manifest, arch, target, controller) {
92
170
  }
93
171
  copyFileSync(controller, join(target, "control"));
94
172
  chmodSync(join(target, "control"), 0o755);
95
- writeFileSync(join(target, "config.json"), daemonConfig(manifest), { mode: 0o644 });
173
+ writeFileSync(join(target, "config.json"), daemonConfig(manifest), {
174
+ mode: 0o644,
175
+ });
96
176
  }
97
177
  /** Copies a bounded, link-free package-account payload tree. */
98
178
  export function copyPayloadTree(root, source, target) {
99
- const invalid = (message) => { throw new StandaloneBuildError("STANDALONE_DAEMON_PAYLOAD_INVALID", message); };
179
+ const invalid = (message) => {
180
+ throw new StandaloneBuildError("STANDALONE_DAEMON_PAYLOAD_INVALID", message);
181
+ };
100
182
  let total = 0;
101
183
  const walk = (from, to) => {
102
184
  const stat = lstatSync(from);
@@ -111,7 +193,7 @@ export function copyPayloadTree(root, source, target) {
111
193
  }
112
194
  else if (stat.isFile()) {
113
195
  total += stat.size;
114
- if (total > 512 * 1024 * 1024 || (stat.mode & 0o6000))
196
+ if (total > 512 * 1024 * 1024 || stat.mode & 0o6000)
115
197
  invalid(`The daemon payload does not accept setid bits or more than 512 MiB: ${from}`);
116
198
  copyFileSync(from, to);
117
199
  chmodSync(to, stat.mode & 0o111 ? 0o755 : 0o644);
@@ -2,13 +2,13 @@ import { resolvedSdkLaunch, dsmLauncherType } from "../contract/app-launch.js";
2
2
  import { REOPEN_EVENTS_RUNTIME } from "./reopen-events.js";
3
3
  import { LAUNCH_PARAMS_RUNTIME } from "./launch-params.js";
4
4
  import { DSM_LANGS } from "./i18n.js";
5
- import { PASSWORD_CONFIRM, ROOT_PANEL, ROOT_RUNTIME, rootPanelCatalogs } from "./root-window.js";
5
+ import { PASSWORD_CONFIRM, ROOT_PANEL, ROOT_RUNTIME, rootPanelCatalogs, } from "./root-window.js";
6
6
  import { HOST_ADAPTER_RUNTIME } from "./host-adapter.js";
7
7
  import { permitsOrdinaryUsers } from "./api-permissions.js";
8
8
  import { portalRuntime } from "./portal-window.js";
9
9
  import { portalByExecutor } from "../build-spk/dsm-version.js";
10
10
  import { uiTitleFields } from "../build-spk/ui-texts.js";
11
- import { packageIcons, windowIconFile, windowIconTemplate } from "../build-spk/dsm-icons.js";
11
+ import { packageIcons, windowIconFile, windowIconTemplate, } from "../build-spk/dsm-icons.js";
12
12
  import { DEFAULT_WINDOW, FULL_PAGE_MIN_WIDTH } from "./window-size.js";
13
13
  import { requestTimeoutSeconds } from "./request-timeout.js";
14
14
  import { appSdkTimeouts } from "../runtime/sdk-timeouts.js";
@@ -68,7 +68,13 @@ export function windowScriptName(manifest) {
68
68
  * IP rules); DSM then filters the launcher and the CGI checks the same rule.
69
69
  */
70
70
  function launcherAccess(manifest) {
71
- return manifest.entry ? entryLauncherAccess(manifest.entry) : { allUsers: permitsOrdinaryUsers(manifest.apiPermissions) };
71
+ return manifest.entry
72
+ ? entryLauncherAccess(manifest.entry)
73
+ : {
74
+ allUsers: manifest.compose
75
+ ? manifest.identityGateway?.access !== "dsm-admins"
76
+ : permitsOrdinaryUsers(manifest.apiPermissions),
77
+ };
72
78
  }
73
79
  /** The launcher fields an entry mode fixes; inspect checks a built SPK against them. */
74
80
  export function entryLauncherAccess(entry) {
@@ -77,11 +83,17 @@ export function entryLauncherAccess(entry) {
77
83
  : { allUsers: true, grantPrivilege: "all", advanceGrantPrivilege: true };
78
84
  }
79
85
  export function appTitle(manifest) {
80
- return { displayname: manifest.displayname, description: manifest.description, info: manifest.i18n?.info };
86
+ return {
87
+ displayname: manifest.displayname,
88
+ description: manifest.description,
89
+ info: manifest.i18n?.info,
90
+ };
81
91
  }
82
92
  /** The app name by locale, as `ui/texts` names the window: `createI18n(lang, ...).t("app_title")`. */
83
93
  function displayNameCatalogs(manifest) {
84
- const catalogs = { en: { app_title: manifest.displayname } };
94
+ const catalogs = {
95
+ en: { app_title: manifest.displayname },
96
+ };
85
97
  for (const [locale, text] of Object.entries(manifest.i18n?.info ?? {})) {
86
98
  if (text?.displayname)
87
99
  catalogs[locale] = { app_title: text.displayname };
@@ -97,6 +109,21 @@ export function renderUiConfig(manifest, icons = packageIcons(manifest.icon), lo
97
109
  const icon = windowIconTemplate(icons);
98
110
  const ns = `SYNO.SDS.${manifest.package}`;
99
111
  const titleFields = uiTitleFields(appTitle(manifest));
112
+ if (manifest.compose) {
113
+ if (!manifest.identityGateway)
114
+ return "{}\n";
115
+ return (JSON.stringify({
116
+ ".url": {
117
+ [`${ns}.Instance`]: {
118
+ type: dsmLauncherType(resolvedSdkLaunch(manifest), false),
119
+ ...titleFields,
120
+ icon,
121
+ ...launcherAccess(manifest),
122
+ url: `/webman/3rdparty/${manifest.package}/sso/open.cgi`,
123
+ },
124
+ },
125
+ }, null, 2) + "\n");
126
+ }
100
127
  return `${JSON.stringify({
101
128
  [windowScriptName(manifest)]: {
102
129
  [`${ns}.Instance`]: {
@@ -148,7 +175,8 @@ export function renderWindowScript(manifest, assetVersion, icons = packageIcons(
148
175
  throw new Error("A portal App's window needs the SDK's portal panel text.");
149
176
  return `/* Generated by synopkgland build. Edit your UI in the project's ui folder. */
150
177
  Ext.ns(${JSON.stringify(ns)});
151
- ${sessionRuntime ? `
178
+ ${sessionRuntime
179
+ ? `
152
180
  // The SDK owns recovery; all calls share one bounded, same-origin attempt.
153
181
  ${ns}.session = (function () {
154
182
  ${sessionRuntime}
@@ -158,7 +186,8 @@ ${sessionRuntime}
158
186
  fetch: function (url, options) { return fetch(url, options); }
159
187
  });
160
188
  })();
161
- ` : ''}
189
+ `
190
+ : ""}
162
191
 
163
192
  // The SDK's clientTimeout: past the backend's request deadline
164
193
  // (ctx.requestTimeout, from backend.timeout_seconds), so its request_timeout
@@ -547,7 +576,9 @@ ${PASSWORD_CONFIRM}
547
576
  call: call,
548
577
  wait: function (ms) { return new Promise(function (resolve) { setTimeout(resolve, ms); }); }
549
578
  });
550
- ${settingsOnlyApproval(manifest) ? "" : ` var panels = me.body && me.body.dom.querySelector(".dsmapp-rootpanels");
579
+ ${settingsOnlyApproval(manifest)
580
+ ? ""
581
+ : ` var panels = me.body && me.body.dom.querySelector(".dsmapp-rootpanels");
551
582
  if (panels) {
552
583
  ${ns}.mountRootPanel(panels, access, ${ns}.createI18n(lang, ${JSON.stringify(rootPanelCatalogs())}).t, session().admin);
553
584
  }
@@ -1,5 +1,6 @@
1
1
  import type { NativeArchFamily } from "../build-spk/dsm-arch.js";
2
2
  import type { CommandRunner } from "./build.js";
3
+ import { type WebAccessMode } from "../contract/web-launch.js";
3
4
  import { type Daemon } from "./daemon.js";
4
5
  import type { StandaloneError, StandaloneManifest } from "./manifest.js";
5
6
  /** The SDK's identity gateway: the daemon wrapper and the DSM-origin authorize CGI. */
@@ -10,7 +11,7 @@ export declare const GATEWAY_CGI_PATH = "ui/sso/authorize.cgi";
10
11
  export declare const GATEWAY_PAYLOAD_DIR = "_sso";
11
12
  export declare const GATEWAY_EXEC = "_sso/gateway";
12
13
  export declare const GATEWAY_CONFIG_PATH = "sso/gateway.json";
13
- export type GatewayMode = "oidc" | "header" | "token";
14
+ export type GatewayMode = "none" | "oidc" | "header" | "token";
14
15
  export interface GatewayRoles {
15
16
  claim: string;
16
17
  admin: string;
@@ -28,6 +29,10 @@ export interface IdentityGateway {
28
29
  /** The SDK release the gateway is built from. */
29
30
  sdk: string;
30
31
  mode: GatewayMode;
32
+ access?: WebAccessMode;
33
+ groups?: string[];
34
+ max_upload_bytes?: number;
35
+ response_header_timeout_seconds?: number;
31
36
  /** The App's loopback port. */
32
37
  upstream: number;
33
38
  listen: {
@@ -64,10 +69,12 @@ export type DeleteAction = {
64
69
  } | {
65
70
  exec: string[];
66
71
  };
67
- export declare function readIdentityGateway(value: unknown, daemon: Pick<Daemon, "targets"> | undefined, fail: (error: StandaloneError) => void): IdentityGateway | undefined;
72
+ export declare function readIdentityGateway(value: unknown, daemon: Pick<Daemon, "targets"> | undefined, fail: (error: StandaloneError) => void, packagedPayload?: boolean, composeBridge?: boolean): IdentityGateway | undefined;
68
73
  /** target/sso/gateway.json, the SDK gateway's configuration (idgateway.Config). */
69
74
  export declare function identityGatewayConfig(m: StandaloneManifest): string;
70
75
  /** The daemon as the controller runs it: the gateway, with the App as its child. */
71
76
  export declare function gatewayDaemon(daemon: Daemon): Daemon;
72
77
  /** Builds the gateway from the declared SDK release with the pinned Go, binding its config path. */
73
78
  export declare function buildIdentityGateway(m: StandaloneManifest, arch: NativeArchFamily, work: string, run: CommandRunner): Promise<string | undefined>;
79
+ /** The manifest form of a normalized gateway, retained for artifact inspection. */
80
+ export declare function identityGatewayDeclaration(g: IdentityGateway | undefined): unknown;