@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.
- package/CHANGELOG.md +20 -1
- package/README.md +33 -18
- package/dist/build-spk/generator.d.ts +3 -2
- package/dist/build-spk/generator.js +6 -846
- package/dist/build-spk/resource-worker.d.ts +2 -14
- package/dist/build-spk/resource-worker.js +3 -166
- package/dist/cli.js +208 -56
- package/dist/compose/analyze.d.ts +3 -61
- package/dist/compose/analyze.js +35 -776
- package/dist/compose/env.d.ts +5 -3
- package/dist/compose/env.js +17 -25
- package/dist/compose/runner.js +23 -6
- package/dist/contract/unsupported-types.js +1 -1
- package/dist/contract/validate.js +2 -2
- package/dist/contract/web-launch.d.ts +1 -12
- package/dist/contract/web-launch.js +10 -74
- package/dist/ctl/cli.d.ts +36 -0
- package/dist/ctl/cli.js +218 -0
- package/dist/ctl/descriptor.d.ts +81 -0
- package/dist/ctl/descriptor.js +93 -0
- package/dist/ctl/dsm-auth.d.ts +10 -0
- package/dist/ctl/dsm-auth.js +30 -0
- package/dist/ctl/errors.d.ts +17 -0
- package/dist/ctl/errors.js +32 -0
- package/dist/ctl/flows.d.ts +11 -0
- package/dist/ctl/flows.js +52 -0
- package/dist/ctl/input.d.ts +20 -0
- package/dist/ctl/input.js +128 -0
- package/dist/ctl/json.d.ts +2 -0
- package/dist/ctl/json.js +38 -0
- package/dist/ctl/redaction.d.ts +15 -0
- package/dist/ctl/redaction.js +198 -0
- package/dist/ctl/service.d.ts +38 -0
- package/dist/ctl/service.js +156 -0
- package/dist/ctl/store.d.ts +51 -0
- package/dist/ctl/store.js +93 -0
- package/dist/ctl/transfers.d.ts +14 -0
- package/dist/ctl/transfers.js +74 -0
- package/dist/ctl/transport.d.ts +11 -0
- package/dist/ctl/transport.js +79 -0
- package/dist/deploy/deploy.d.ts +4 -3
- package/dist/deploy/deploy.js +5 -210
- package/dist/deploy/plan.js +26 -7
- package/dist/dev.js +5 -4
- package/dist/e2e/dsm.d.ts +2 -2
- package/dist/e2e/dsm.js +10 -6
- package/dist/error-registry.js +1020 -834
- package/dist/host/share-permission-lookup.d.ts +1 -1
- package/dist/host/share-permission.d.ts +1 -1
- package/dist/host/share-permission.js +1 -1
- package/dist/info.js +120 -28
- package/dist/init.js +188 -64
- package/dist/inspect.js +21 -6
- package/dist/runtime/executor-digests.json +5 -5
- package/dist/skill.js +51 -9
- package/dist/standalone/api-description-inspect.d.ts +4 -0
- package/dist/standalone/api-description-inspect.js +12 -0
- package/dist/standalone/api-description.d.ts +7 -0
- package/dist/standalone/api-description.js +73 -0
- package/dist/standalone/build.d.ts +3 -0
- package/dist/standalone/build.js +140 -33
- package/dist/standalone/compose-errors.d.ts +3 -0
- package/dist/standalone/compose-errors.js +243 -0
- package/dist/standalone/compose.d.ts +97 -10
- package/dist/standalone/compose.js +306 -75
- package/dist/standalone/daemon.js +111 -29
- package/dist/standalone/dsm-window.js +39 -8
- package/dist/standalone/identity-gateway.d.ts +9 -2
- package/dist/standalone/identity-gateway.js +282 -66
- package/dist/standalone/inspect-spk.d.ts +12 -0
- package/dist/standalone/inspect-spk.js +666 -136
- package/dist/standalone/lifecycle.js +124 -42
- package/dist/standalone/manifest.d.ts +8 -1
- package/dist/standalone/manifest.js +303 -86
- package/dist/standalone/resource.js +6 -2
- package/dist/standalone/spk.d.ts +4 -1
- package/dist/standalone/spk.js +138 -39
- package/dist/template-paths.d.ts +0 -2
- package/dist/template-paths.js +0 -5
- package/dist/test-command.d.ts +1 -1
- package/dist/test-command.js +1 -1
- package/dist/validate.d.ts +3 -3
- package/dist/validate.js +32 -140
- package/package.json +5 -3
- package/schema/synopkgland-api-v1.schema.json +423 -0
- package/skills/SKILL.md +4 -2
- package/skills/reference/compose.md +349 -0
- package/skills/reference/create.md +9 -18
- package/skills/reference/ctl.md +41 -0
- package/skills/reference/deploy.md +1 -1
- package/skills/reference/files.md +5 -1
- package/skills/reference/identity-gateway.md +8 -144
- package/skills/reference/wrap.md +10 -39
- package/assets/go/daemon/fixture_linux_test.go +0 -15
- package/assets/go/daemon/fixture_other_test.go +0 -7
- package/assets/go/daemon/go.mod +0 -5
- package/assets/go/daemon/main.go +0 -636
- package/assets/go/daemon/main_test.go +0 -315
- package/assets/go/daemon/network.go +0 -107
- package/assets/go/daemon/network_test.go +0 -86
- package/assets/go/daemon/process_linux.go +0 -55
- package/assets/go/daemon/process_linux_test.go +0 -161
- package/assets/go/daemon/process_other.go +0 -14
- package/assets/go/daemon/testdata/child.go +0 -44
- package/assets/go/gateway/auth.go +0 -101
- package/assets/go/gateway/auth_test.go +0 -216
- package/assets/go/gateway/cgi.go +0 -133
- package/assets/go/gateway/cgi_test.go +0 -156
- package/assets/go/gateway/csrf.go +0 -73
- package/assets/go/gateway/csrf_test.go +0 -155
- package/assets/go/gateway/directory.go +0 -108
- package/assets/go/gateway/directory_test.go +0 -202
- package/assets/go/gateway/gateway.go +0 -412
- package/assets/go/gateway/gateway_test.go +0 -676
- package/assets/go/gateway/go.mod +0 -5
- package/assets/go/gateway/groups.go +0 -66
- package/assets/go/gateway/main.go +0 -45
- package/dist/build-spk/gateway.d.ts +0 -31
- package/dist/build-spk/gateway.js +0 -60
- package/dist/compose/privilege.d.ts +0 -14
- 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 {
|
|
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([
|
|
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" &&
|
|
14
|
-
|
|
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
|
-
|
|
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" &&
|
|
20
|
-
|
|
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 = () => {
|
|
25
|
-
|
|
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) ||
|
|
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" ||
|
|
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 &&
|
|
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) ||
|
|
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) ||
|
|
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 = {
|
|
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) ||
|
|
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 {
|
|
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
|
|
63
|
-
|
|
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", [
|
|
70
|
-
|
|
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
|
-
|
|
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), {
|
|
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) => {
|
|
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 ||
|
|
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
|
|
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 {
|
|
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 = {
|
|
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)
|
|
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;
|