@synopackageland/cli 0.29.0 → 0.30.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/CHANGELOG.md +9 -0
- package/README.md +3 -2
- package/dist/error-registry.js +1 -1
- package/dist/standalone/identity-gateway.d.ts +2 -0
- package/dist/standalone/identity-gateway.js +9 -4
- package/dist/standalone/inspect-spk.js +2 -1
- package/package.json +2 -2
- package/skills/reference/identity-gateway.md +13 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.30.0 (2026-10-24)
|
|
4
|
+
|
|
5
|
+
- Package and forward `identity_gateway.external_access.single_origin`; use SDK 0.30.0 for one-URL Apps, provider-aware DSM menu launches and launch probes.
|
|
6
|
+
- Pin templates 0.30.x and its SDK/App 0.30.0 defaults; keep immutable executor/v0.27.0.
|
|
7
|
+
|
|
8
|
+
## Unreleased
|
|
9
|
+
|
|
10
|
+
- Accept and package `identity_gateway.external_access.single_origin` (boolean) for one-URL upstreams. Build requires SDK sources with `single_origin` support, and inspect accepts the packaged `single_origin: true` declaration.
|
|
11
|
+
|
|
3
12
|
## 0.29.0 (2026-10-24)
|
|
4
13
|
|
|
5
14
|
- Depend on templates `~0.29.0` with SDK/App 0.29.0 and UI 0.14.10. SDK 0.29.0 reuses executor/v0.27.0 through executor manifest format 1; no executor digests change.
|
package/README.md
CHANGED
|
@@ -66,7 +66,7 @@ CLI-only patch releases can differ from the SDK patch. Compose import and SDK de
|
|
|
66
66
|
read the SDK pin from the installed templates; explicit App SDK declarations take precedence.
|
|
67
67
|
|
|
68
68
|
`init` and `add` read their templates from the locally installed
|
|
69
|
-
`@synopackageland/templates`. CLI 0.
|
|
69
|
+
`@synopackageland/templates`. CLI 0.30.0 depends on `~0.30.0`: npm installation or
|
|
70
70
|
update can select the latest templates patch in the 0.29 minor line. Templates
|
|
71
71
|
patches need only a templates release; update the npm installation to receive them.
|
|
72
72
|
The CLI never fetches templates at runtime, so offline use works after installation;
|
|
@@ -308,7 +308,8 @@ and default to `external_access: {connect: optional, origin_change: none}`.
|
|
|
308
308
|
Declare `identity_gateway.external_access.connect: none` to ignore Connect's
|
|
309
309
|
public URL projection; manual URLs remain available without Connect. Use
|
|
310
310
|
`origin_change: confirm` for Apps that need confirmation when their public
|
|
311
|
-
origin changes
|
|
311
|
+
origin changes, and `single_origin: true` (SDK 0.30.0+) for an upstream that
|
|
312
|
+
works on one URL only. `connect: required` is rejected, and declaring `external_access`
|
|
312
313
|
with SDK older than 0.29.0 is rejected. Compose and gateway SDK pins must match.
|
|
313
314
|
See [external access configuration](skills/reference/identity-gateway.md#external-access)
|
|
314
315
|
for the manifest, settings entry, URL rules and cold-login handoff.
|
package/dist/error-registry.js
CHANGED
|
@@ -365,7 +365,7 @@ export const ERROR_REGISTRY = {
|
|
|
365
365
|
STANDALONE_IDENTITY_GATEWAY_EXTERNAL_INVALID: {
|
|
366
366
|
code: "STANDALONE_IDENTITY_GATEWAY_EXTERNAL_INVALID",
|
|
367
367
|
description: "The external access declaration does not match the gateway contract.",
|
|
368
|
-
suggestion: "Set identity_gateway.external_access.connect to optional or none,
|
|
368
|
+
suggestion: "Set identity_gateway.external_access.connect to optional or none, origin_change to none or confirm, and single_origin to a boolean; required is not supported.",
|
|
369
369
|
},
|
|
370
370
|
STANDALONE_IDENTITY_GATEWAY_EXTERNAL_SDK_REQUIRED: {
|
|
371
371
|
code: "STANDALONE_IDENTITY_GATEWAY_EXTERNAL_SDK_REQUIRED",
|
|
@@ -16,6 +16,8 @@ export type GatewayMode = "none" | "oidc" | "header" | "token";
|
|
|
16
16
|
export interface GatewayExternalAccess {
|
|
17
17
|
connect: "optional" | "none";
|
|
18
18
|
origin_change: "none" | "confirm";
|
|
19
|
+
/** One-URL upstream: DSM launch and local navigations go to the primary external origin. */
|
|
20
|
+
single_origin?: true;
|
|
19
21
|
}
|
|
20
22
|
export declare const EXTERNAL_ACCESS_MIN_SDK = "0.29.0";
|
|
21
23
|
/** SDK 0.28 has the diagnostic ping only; older gateways reject external JSON. */
|
|
@@ -167,13 +167,14 @@ export function readIdentityGateway(value, daemon, fail, packagedPayload = false
|
|
|
167
167
|
let externalAccess;
|
|
168
168
|
if (v.external_access !== undefined) {
|
|
169
169
|
const external = v.external_access;
|
|
170
|
-
if (!record(external) || !only(external, ["connect", "origin_change"]) ||
|
|
170
|
+
if (!record(external) || !only(external, ["connect", "origin_change", "single_origin"]) ||
|
|
171
171
|
(external.connect !== undefined && external.connect !== "optional" && external.connect !== "none") ||
|
|
172
|
-
(external.origin_change !== undefined && external.origin_change !== "none" && external.origin_change !== "confirm")
|
|
173
|
-
|
|
172
|
+
(external.origin_change !== undefined && external.origin_change !== "none" && external.origin_change !== "confirm") ||
|
|
173
|
+
(external.single_origin !== undefined && typeof external.single_origin !== "boolean")) {
|
|
174
|
+
fail({ code: "STANDALONE_IDENTITY_GATEWAY_EXTERNAL_INVALID", message: "identity_gateway.external_access accepts only connect (optional or none), origin_change (none or confirm) and single_origin (boolean); required is not supported." });
|
|
174
175
|
return undefined;
|
|
175
176
|
}
|
|
176
|
-
externalAccess = { connect: external.connect ?? "optional", origin_change: external.origin_change ?? "none" };
|
|
177
|
+
externalAccess = { connect: external.connect ?? "optional", origin_change: external.origin_change ?? "none", ...(external.single_origin ? { single_origin: true } : {}) };
|
|
177
178
|
}
|
|
178
179
|
if (v.launch_path !== undefined) {
|
|
179
180
|
try {
|
|
@@ -531,6 +532,10 @@ export async function buildIdentityGateway(m, arch, work, run) {
|
|
|
531
532
|
if (!existsSync(config) || !/`json:"external(?:,omitempty)?"`/.test(readFileSync(config, "utf8")) ||
|
|
532
533
|
!existsSync(main) || !/["']\/?settings\.cgi["']/.test(readFileSync(main, "utf8")))
|
|
533
534
|
throw new StandaloneBuildError("STANDALONE_IDENTITY_GATEWAY_EXTERNAL_SDK_REQUIRED", `The selected SDK source lacks external access or settings.cgi support; use SDK ${EXTERNAL_ACCESS_MIN_SDK} or later with matching sources.`);
|
|
535
|
+
const external = join(sdk.goDir, "idgateway/external.go");
|
|
536
|
+
if (gatewayExternalAccess(m.identityGateway)?.single_origin &&
|
|
537
|
+
(!existsSync(external) || !/`json:"single_origin(?:,omitempty)?"`/.test(readFileSync(external, "utf8"))))
|
|
538
|
+
throw new StandaloneBuildError("STANDALONE_IDENTITY_GATEWAY_EXTERNAL_SDK_REQUIRED", "The selected SDK source lacks external_access.single_origin support; use a matching SDK release or an explicit development source override.");
|
|
534
539
|
}
|
|
535
540
|
if (m.identityGateway.oidc?.browser_redirect) {
|
|
536
541
|
const capability = join(sdk.goDir, "idgateway/browser_redirect.go");
|
|
@@ -1135,8 +1135,9 @@ async function inspectExternalGateway(dir, paths, payload, saved, findings) {
|
|
|
1135
1135
|
return;
|
|
1136
1136
|
const external = saved;
|
|
1137
1137
|
if (!external || typeof external !== "object" || Array.isArray(external) ||
|
|
1138
|
-
Object.keys(external).length !== 2 || (external.connect !== "optional" && external.connect !== "none") ||
|
|
1138
|
+
Object.keys(external).length !== (external.single_origin === undefined ? 2 : 3) || (external.connect !== "optional" && external.connect !== "none") ||
|
|
1139
1139
|
(external.origin_change !== "none" && external.origin_change !== "confirm") ||
|
|
1140
|
+
(external.single_origin !== undefined && external.single_origin !== true) ||
|
|
1140
1141
|
!isDeepStrictEqual(cfg.external, external) || cfg.package !== info.package)
|
|
1141
1142
|
throw new Error("external configuration differs from its package declaration");
|
|
1142
1143
|
const arch = info.arch.split(/\s+/).map(familyOfArchToken).find(Boolean) ?? "x86_64";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synopackageland/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0",
|
|
4
4
|
"description": "Syno Package Land Developer Kit CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@napi-rs/keyring": "^2.1.1",
|
|
30
|
-
"@synopackageland/templates": "~0.
|
|
30
|
+
"@synopackageland/templates": "~0.30.0",
|
|
31
31
|
"ajv": "^8.17.1",
|
|
32
32
|
"commander": "^13.1.0",
|
|
33
33
|
"json-canonicalize": "^3.0.1",
|
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## External access
|
|
4
4
|
|
|
5
|
-
Use SDK 0.
|
|
5
|
+
Use SDK 0.30.0 or later with matching gateway sources. Add this to the existing
|
|
6
6
|
complete gateway declaration; keep the App's upstream, listener and auth policy:
|
|
7
7
|
|
|
8
8
|
```yaml
|
|
9
9
|
identity_gateway:
|
|
10
|
-
sdk: 0.
|
|
10
|
+
sdk: 0.30.0
|
|
11
11
|
external_access:
|
|
12
12
|
connect: optional # optional | none
|
|
13
13
|
origin_change: none # none | confirm
|
|
14
|
+
single_origin: false # true for an upstream that works on one URL only
|
|
14
15
|
```
|
|
15
16
|
|
|
16
17
|
Omitting the block or either member uses `connect: optional` and
|
|
@@ -38,11 +39,18 @@ installation. It edits only `manual_origin` and `dsm_origin` in private
|
|
|
38
39
|
URL fields.
|
|
39
40
|
|
|
40
41
|
Public origins must use HTTPS and a DNS hostname. Port 443 is normalized;
|
|
41
|
-
other ports, IP addresses, paths, queries and user information are rejected,
|
|
42
|
+
other ports (except a single-origin App's `manual_origin`), IP addresses, paths, queries and user information are rejected,
|
|
42
43
|
as is an origin equal to the DSM origin. Manual takes precedence, then the
|
|
43
44
|
Connect projection when `connect: optional`; the first effective origin is
|
|
44
45
|
primary. `connect: none` ignores that projection. Private URLs are display-only.
|
|
45
46
|
Use `origin_change: confirm` for an App that must confirm public-origin changes.
|
|
47
|
+
Declare `single_origin: true` (with `origin_change: confirm`) for an App whose
|
|
48
|
+
upstream sign-in works on one fixed URL, such as Vaultwarden's `DOMAIN`. While
|
|
49
|
+
an external origin is set, the DSM launcher opens the primary origin and local
|
|
50
|
+
browser navigations redirect to it; the settings page says that only that
|
|
51
|
+
address can sign in. Without an external origin nothing changes. The generated
|
|
52
|
+
`external` object then carries `"single_origin":true`, and build rejects a
|
|
53
|
+
development SDK source without `single_origin` support.
|
|
46
54
|
|
|
47
55
|
Cold DSM login preserves external resume tokens
|
|
48
56
|
`<txn>:x<n>:<r1>.<r2>` in the fixed `authorize.cgi?resume=<encoded token>`
|
|
@@ -260,3 +268,5 @@ control characters are rejected. Caller query values cannot override it.
|
|
|
260
268
|
Use the upstream's supported entry route; this does not modify upstream UI,
|
|
261
269
|
produce an App session, or unlock encrypted data. HTTPS and App-specific
|
|
262
270
|
fragment/query semantics still require deployment acceptance.
|
|
271
|
+
|
|
272
|
+
Single-origin Apps require SDK 0.30.0 or later. Their `manual_origin` may include an explicit HTTPS port (for example, `https://example.ts.net:29443`). The DSM launcher resolves the destination for the provider used to open DSM, probes `/_spl/ping` for up to eight seconds, and offers **Open anyway** if the probe fails. A single-origin App always uses its configured primary origin. Other Apps and the `external-origin` install setting continue to require HTTPS DNS origins on port 443.
|