@dsh-plus/access-gate 0.3.12 → 0.3.14

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/lib/client.js CHANGED
@@ -42,7 +42,7 @@ window.__ModuleLoader__.load({
42
42
  className: `${p}-pending`,
43
43
  children: props.dirtyLabel
44
44
  }) : null,
45
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: `${p}-chevron${props.open ? ` ${p}-chevronOpen` : ""}` })
45
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { className: `${p}-chevron${props.open ? ` ${p}-chevronOpen` : ""}` })
46
46
  ]
47
47
  }), props.open ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
48
48
  className: `${p}-body`,
@@ -379,8 +379,8 @@ ${extra}
379
379
  * 与 0.1.6-alpha.2 插件页 plugins.row.config / plugins.bundle.config,view 分发 summary/page)。
380
380
  * 外壳与基础控件走 @dsh-plus/shared/client 套件(CardChrome/TextField/CheckRow),
381
381
  * 本文件保留业务字段(白名单 textarea/诊断面板)与保存逻辑。
382
- * 配置读写走官方 settingsScope 传输:value 为 schema 解析后的视图,
383
- * 保存经 settings.update 深合并。
382
+ * 配置读写经共享层 ctx.remote.settings 直连(0.1.7 起 settingsScope 已由
383
+ * configForms 取代):value 为 schema 解析后的视图,保存经 settings.update 深合并。
384
384
  * 卡片顶部「当前页面诊断」读 /dsh-plus/gate/status(本页放行原因/客户端 IP/
385
385
  * 官方 cookie 状态)。
386
386
  *
package/lib/index.d.ts CHANGED
@@ -1,18 +1,22 @@
1
1
  import { Context, Service } from "@deepseek-ai/cordis";
2
+ import { UnwrapVolatile } from "@dsh-plus/shared";
2
3
  import z from "@deepseek-ai/schemastery";
3
4
  //#region src/config.d.ts
4
- declare const Config: z<Schemastery.ObjectS<{
5
- enabled: z<boolean, boolean>;
6
- allowedIps: z<string[], string[]>;
7
- trustForwardedFor: z<boolean, boolean>;
8
- autoLoginTrustedIps: z<boolean, boolean>;
9
- }>, Schemastery.ObjectT<{
10
- enabled: z<boolean, boolean>;
11
- allowedIps: z<string[], string[]>;
12
- trustForwardedFor: z<boolean, boolean>;
13
- autoLoginTrustedIps: z<boolean, boolean>;
14
- }>>;
15
- type AccessGateConfig = Schemastery.TypeT<typeof Config>;
5
+ declare const Config: z<Schemastery.ObjectS<NoInfer<{
6
+ enabled: z<boolean, boolean, "volatile-defined">;
7
+ allowedIps: z<NoInfer<string[]>, NoInfer<string[]>, "volatile-defined">;
8
+ trustForwardedFor: z<boolean, boolean, "volatile-defined">;
9
+ autoLoginTrustedIps: z<boolean, boolean, "volatile-defined">;
10
+ }>>, Schemastery.ObjectT<NoInfer<{
11
+ enabled: z<boolean, boolean, "volatile-defined">;
12
+ allowedIps: z<NoInfer<string[]>, NoInfer<string[]>, "volatile-defined">;
13
+ trustForwardedFor: z<boolean, boolean, "volatile-defined">;
14
+ autoLoginTrustedIps: z<boolean, boolean, "volatile-defined">;
15
+ }>>, "plain">;
16
+ /** 活动字段形态(0.1.7 loader 解析产物:volatile 字段为活动引用)。 */
17
+ type AccessGateConfigFields = Schemastery.TypeT<typeof Config>;
18
+ /** 平面配置形态(服务与判定面的消费形态,由活动引用解包得到)。 */
19
+ type AccessGateConfig = UnwrapVolatile<AccessGateConfigFields>;
16
20
  //#endregion
17
21
  //#region src/index.d.ts
18
22
  declare const name = "dsh-plus-access-gate";
@@ -22,12 +26,12 @@ declare module '@deepseek-ai/cordis' {
22
26
  accessGate: AccessGateService;
23
27
  }
24
28
  }
25
- /** 围栏服务:持有当前配置读取器(settings 用户层热更新经 setSource 注入)。 */
29
+ /** 围栏服务:持有当前配置读取器(0.1.7 起为 volatile 活动引用的平面解包,读即最新)。 */
26
30
  declare class AccessGateService extends Service {
27
31
  private current;
28
32
  /** 官方 browser-auth 签名密钥(惰性读取缓存;读取失败 = null,autoLogin fail-safe 降级)。 */
29
33
  private signingSecret;
30
- constructor(ctx: Context, config: AccessGateConfig);
34
+ constructor(ctx: Context, config: AccessGateConfig | AccessGateConfigFields);
31
35
  /** 当前生效配置(诊断用)。 */
32
36
  policy(): AccessGateConfig;
33
37
  /** 官方签名密钥(惰性缓存;失败返回 null 并记录,autoLogin 降级 fail-safe)。 */
@@ -37,6 +41,6 @@ declare class AccessGateService extends Service {
37
41
  warn(message: string): void;
38
42
  }): boolean;
39
43
  }
40
- declare function apply(ctx: Context, config: AccessGateConfig): void;
44
+ declare function apply(ctx: Context, config: AccessGateConfig | AccessGateConfigFields): void;
41
45
  //#endregion
42
46
  export { AccessGateService, Config, apply, inject, name };
package/lib/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { Service } from "@deepseek-ai/cordis";
2
2
  import { dshHomePath } from "@deepseek-ai/dsh-home-paths";
3
+ import { unwrapVolatile } from "@dsh-plus/shared";
3
4
  import z from "@deepseek-ai/schemastery";
4
5
  import { createHash, createHmac } from "node:crypto";
5
6
  import { readFileSync } from "node:fs";
6
7
  import { join } from "node:path";
7
- //#endregion
8
8
  //#region src/config.ts
9
9
  /**
10
10
  * 配置单一事实源:cordis 行级 Config(组合默认值,dev/prod patch 层可覆盖)
@@ -18,13 +18,11 @@ import { join } from "node:path";
18
18
  * schemastery 透传忽略,不阻断加载(已实测验证)。
19
19
  * @module access-gate/config
20
20
  */
21
- /** settings 命名空间(字面量即合法命名空间,0.1.2-alpha.2 起编译期校验;webui 配置卡片与插件运行期读取同一份)。 */
22
- const SETTINGS_NS = "dsh-plus-access-gate";
23
21
  const Config = z.object({
24
- enabled: z.boolean().description("访问围栏总开关(false = 一切放行,等价插件缺席)").default(false),
25
- allowedIps: z.array(z.string()).description("附加 IP 围栏:非空时仅白名单条目(精确 IP 或 CIDR,IPv4/IPv6 皆可)可通行与登录;空 = 不限制来源 IP(仅官方登录保护)").default([]),
26
- trustForwardedFor: z.boolean().description("是否信任 x-forwarded-for 还原真实客户端 IP(仅当入口代理强制覆盖该头时开启;tailscale serve 满足)").default(true),
27
- autoLoginTrustedIps: z.boolean().description("IP 信任自动登录:来源命中 allowedIps 白名单且未认证时,服务端自动签发官方登录 cookie(免启动 token,仅对白名单来源生效);默认关闭,需显式开启").default(false)
22
+ enabled: z.boolean().description("访问围栏总开关(false = 一切放行,等价插件缺席)").default(false).volatile(),
23
+ allowedIps: z.array(z.string()).description("附加 IP 围栏:非空时仅白名单条目(精确 IP 或 CIDR,IPv4/IPv6 皆可)可通行与登录;空 = 不限制来源 IP(仅官方登录保护)").default([]).volatile(),
24
+ trustForwardedFor: z.boolean().description("是否信任 x-forwarded-for 还原真实客户端 IP(仅当入口代理强制覆盖该头时开启;tailscale serve 满足)").default(true).volatile(),
25
+ autoLoginTrustedIps: z.boolean().description("IP 信任自动登录:来源命中 allowedIps 白名单且未认证时,服务端自动签发官方登录 cookie(免启动 token,仅对白名单来源生效);默认关闭,需显式开启").default(false).volatile()
28
26
  });
29
27
  //#endregion
30
28
  //#region src/cookie.ts
@@ -741,22 +739,14 @@ function assertGateStructure(server) {
741
739
  //#region src/index.ts
742
740
  const name = "dsh-plus-access-gate";
743
741
  const inject = ["webServer", "connection"];
744
- /** 围栏服务:持有当前配置读取器(settings 用户层热更新经 setSource 注入)。 */
742
+ /** 围栏服务:持有当前配置读取器(0.1.7 起为 volatile 活动引用的平面解包,读即最新)。 */
745
743
  var AccessGateService = class extends Service {
746
744
  current;
747
745
  /** 官方 browser-auth 签名密钥(惰性读取缓存;读取失败 = null,autoLogin fail-safe 降级)。 */
748
746
  signingSecret;
749
747
  constructor(ctx, config) {
750
748
  super(ctx, "accessGate");
751
- this.current = () => config;
752
- ctx.inject(["settings"], (settingsCtx) => {
753
- settingsCtx.settings.installSection(ctx, SETTINGS_NS, Config, config, {
754
- setSource: (source) => {
755
- this.current = source;
756
- },
757
- onChange: () => {}
758
- });
759
- });
749
+ this.current = () => unwrapVolatile(config);
760
750
  const logger = ctx.logger("access-gate");
761
751
  const officialAuth = (req) => ctx.connection.requestRejection({ headers: req.headers }) === void 0;
762
752
  const secretOf = () => this.readSigningSecret(logger);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-plus/access-gate",
3
- "version": "0.3.12",
3
+ "version": "0.3.14",
4
4
  "description": "dsh-plus service+ui plugin: dsh web 全量访问围栏——与官方 browser-auth 合并:官方 cookie 为唯一凭据,可选 IP 附加围栏,未认证导航渲染 token 输入页(PWA 可恢复),loopback 管理通道",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -31,21 +31,21 @@
31
31
  }
32
32
  },
33
33
  "dependencies": {
34
- "@dsh-plus/shared": "0.1.21"
34
+ "@dsh-plus/shared": "0.1.23"
35
35
  },
36
36
  "peerDependencies": {
37
- "@deepseek-ai/cordis": "^4.0.2",
38
- "@deepseek-ai/dsh-home-paths": "^0.1.6-alpha.2",
39
- "@deepseek-ai/dsh-settings": "^0.1.6-alpha.2",
40
- "@deepseek-ai/schemastery": "^3.18.2"
37
+ "@deepseek-ai/cordis": "^4.0.4",
38
+ "@deepseek-ai/dsh-home-paths": "^0.1.7-rc.1",
39
+ "@deepseek-ai/dsh-settings": "^0.1.7-rc.1",
40
+ "@deepseek-ai/schemastery": "^3.18.4"
41
41
  },
42
42
  "devDependencies": {
43
- "@deepseek-ai/cordis": "4.0.2",
44
- "@deepseek-ai/dsh-client-connection": "0.1.6-alpha.2",
45
- "@deepseek-ai/dsh-home-paths": "0.1.6-alpha.2",
46
- "@deepseek-ai/dsh-host-webserver": "0.1.6-alpha.2",
47
- "@deepseek-ai/dsh-settings": "0.1.6-alpha.2",
48
- "@deepseek-ai/schemastery": "3.18.2",
43
+ "@deepseek-ai/cordis": "4.0.4",
44
+ "@deepseek-ai/dsh-client-connection": "0.1.7-rc.1",
45
+ "@deepseek-ai/dsh-home-paths": "0.1.7-rc.1",
46
+ "@deepseek-ai/dsh-host-webserver": "0.1.7-rc.1",
47
+ "@deepseek-ai/dsh-settings": "0.1.7-rc.1",
48
+ "@deepseek-ai/schemastery": "3.18.4",
49
49
  "@types/react": "~18.3.31",
50
50
  "react": "^18.2.0"
51
51
  },
@@ -3,8 +3,8 @@
3
3
  * 与 0.1.6-alpha.2 插件页 plugins.row.config / plugins.bundle.config,view 分发 summary/page)。
4
4
  * 外壳与基础控件走 @dsh-plus/shared/client 套件(CardChrome/TextField/CheckRow),
5
5
  * 本文件保留业务字段(白名单 textarea/诊断面板)与保存逻辑。
6
- * 配置读写走官方 settingsScope 传输:value 为 schema 解析后的视图,
7
- * 保存经 settings.update 深合并。
6
+ * 配置读写经共享层 ctx.remote.settings 直连(0.1.7 起 settingsScope 已由
7
+ * configForms 取代):value 为 schema 解析后的视图,保存经 settings.update 深合并。
8
8
  * 卡片顶部「当前页面诊断」读 /dsh-plus/gate/status(本页放行原因/客户端 IP/
9
9
  * 官方 cookie 状态)。
10
10
  *
@@ -8,7 +8,7 @@
8
8
  * 类型说明:浏览器半只用到 slots/locale/remote 的很窄一面,
9
9
  * scope 与基础控件走 @dsh-plus/shared/client 套件(收编自本插件原实现)。
10
10
  * 配置读写经 ctx.remote.settings 直连(0.1.2-alpha.1 起 connection.api.settings
11
- * 已移除;不复用 settingsScope 服务——非 loopback 页面下它固定 memory 模式无数据)。
11
+ * 已移除;0.1.7 起 settingsScope 服务亦删除——configForms 取代,自始直连)。
12
12
  * 卡片 key/rowId 约定见 @dsh-plus/shared/client/config-slots。
13
13
  * @module @dsh-plus/access-gate/client
14
14
  */
package/src/config.ts CHANGED
@@ -11,38 +11,49 @@
11
11
  * @module access-gate/config
12
12
  */
13
13
  import z from '@deepseek-ai/schemastery'
14
+ import type { UnwrapVolatile } from '@dsh-plus/shared'
14
15
 
15
16
  import { SETTINGS_NS as NS_LITERAL } from './ns.ts'
16
17
 
17
18
  /** settings 命名空间(字面量即合法命名空间,0.1.2-alpha.2 起编译期校验;webui 配置卡片与插件运行期读取同一份)。 */
18
19
  export const SETTINGS_NS = NS_LITERAL
19
20
 
21
+ // 0.1.7:全部字段 `.volatile()`——loader 解析为活动引用(用户层 override 并入
22
+ // 行级 config,GUI 写入原位提交热生效),同时使本条目进入 settings describe
23
+ // 视图(配置卡片可读写);缺 volatile 标记的条目会被 describe 跳过。
20
24
  export const Config = z.object({
21
25
  enabled: z
22
26
  .boolean()
23
27
  .description('访问围栏总开关(false = 一切放行,等价插件缺席)')
24
- .default(false),
28
+ .default(false)
29
+ .volatile(),
25
30
  allowedIps: z
26
31
  .array(z.string())
27
32
  .description(
28
33
  '附加 IP 围栏:非空时仅白名单条目(精确 IP 或 CIDR,IPv4/IPv6 皆可)可通行与登录;空 = 不限制来源 IP(仅官方登录保护)',
29
34
  )
30
- .default([]),
35
+ .default([])
36
+ .volatile(),
31
37
  trustForwardedFor: z
32
38
  .boolean()
33
39
  .description(
34
40
  '是否信任 x-forwarded-for 还原真实客户端 IP(仅当入口代理强制覆盖该头时开启;tailscale serve 满足)',
35
41
  )
36
- .default(true),
42
+ .default(true)
43
+ .volatile(),
37
44
  autoLoginTrustedIps: z
38
45
  .boolean()
39
46
  .description(
40
47
  'IP 信任自动登录:来源命中 allowedIps 白名单且未认证时,服务端自动签发官方登录 cookie(免启动 token,仅对白名单来源生效);默认关闭,需显式开启',
41
48
  )
42
- .default(false),
49
+ .default(false)
50
+ .volatile(),
43
51
  })
44
52
 
45
- export type AccessGateConfig = Schemastery.TypeT<typeof Config>
53
+ /** 活动字段形态(0.1.7 loader 解析产物:volatile 字段为活动引用)。 */
54
+ export type AccessGateConfigFields = Schemastery.TypeT<typeof Config>
55
+ /** 平面配置形态(服务与判定面的消费形态,由活动引用解包得到)。 */
56
+ export type AccessGateConfig = UnwrapVolatile<AccessGateConfigFields>
46
57
 
47
58
  /** 判定所需的最小配置视图(测试与决策函数共用窄面)。 */
48
59
  export interface GatePolicy {
package/src/index.ts CHANGED
@@ -32,8 +32,9 @@ import { type Context, Service } from '@deepseek-ai/cordis'
32
32
  import type {} from '@deepseek-ai/dsh-client-connection'
33
33
  import { dshHomePath } from '@deepseek-ai/dsh-home-paths'
34
34
  import type {} from '@deepseek-ai/dsh-settings'
35
+ import { unwrapVolatile } from '@dsh-plus/shared'
35
36
 
36
- import { type AccessGateConfig, Config, SETTINGS_NS } from './config.ts'
37
+ import { type AccessGateConfig, type AccessGateConfigFields, Config } from './config.ts'
37
38
  import {
38
39
  credentialsPath,
39
40
  mintAutoLoginCookie,
@@ -55,25 +56,17 @@ declare module '@deepseek-ai/cordis' {
55
56
  }
56
57
  }
57
58
 
58
- /** 围栏服务:持有当前配置读取器(settings 用户层热更新经 setSource 注入)。 */
59
+ /** 围栏服务:持有当前配置读取器(0.1.7 起为 volatile 活动引用的平面解包,读即最新)。 */
59
60
  export class AccessGateService extends Service {
60
61
  private current: () => AccessGateConfig
61
62
  /** 官方 browser-auth 签名密钥(惰性读取缓存;读取失败 = null,autoLogin fail-safe 降级)。 */
62
63
  private signingSecret: Buffer | null | undefined
63
64
 
64
- constructor(ctx: Context, config: AccessGateConfig) {
65
+ constructor(ctx: Context, config: AccessGateConfig | AccessGateConfigFields) {
65
66
  super(ctx, 'accessGate')
66
- this.current = () => config
67
- // 官方 installSection 范式(0.1.2-alpha.2):settings 提供方在时以行级 config 为
68
- // base 注册用户层命名空间,缺席/ detach 时回落行级 config。
69
- ctx.inject(['settings'], (settingsCtx) => {
70
- settingsCtx.settings.installSection(ctx, SETTINGS_NS, Config, config, {
71
- setSource: (source) => {
72
- this.current = source
73
- },
74
- onChange: () => {},
75
- })
76
- })
67
+ // 0.1.7 替代 0.1.6 installSection/setSource:loader 解析层已把用户层
68
+ // override 并入行级 config 并以活动引用原位提交,current() 现取即热。
69
+ this.current = () => unwrapVolatile(config)
77
70
  const logger = ctx.logger('access-gate')
78
71
 
79
72
  // 官方凭据校验委托:undefined = 已通过(含官方 Host 信任围栏)。
@@ -142,6 +135,6 @@ export class AccessGateService extends Service {
142
135
  }
143
136
  }
144
137
 
145
- export function apply(ctx: Context, config: AccessGateConfig): void {
138
+ export function apply(ctx: Context, config: AccessGateConfig | AccessGateConfigFields): void {
146
139
  ctx.plugin(AccessGateService, config)
147
140
  }