mn-ws-server 0.0.0-stage → 0.2.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
package/dist/auth.js ADDED
@@ -0,0 +1,297 @@
1
+ import crypto from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ /**
5
+ * mn-ws server 侧的认证:统一登录的公开参数 + 设备令牌的签发与校验。
6
+ *
7
+ * 与 mn-rt 的 server/src/auth.js 同构,但**没有 sessionKey**:
8
+ * mn-ws 桥接的是 HTTP 请求,不是加密信封流,桥接层不需要「会话密钥」概念。
9
+ *
10
+ * 两类凭据:
11
+ * · 认证中心 access_token —— 短命,登录当场换设备令牌用完即弃,不落盘。
12
+ * · mn-ws 设备令牌(HS256 JWT)—— 长命,落盘,由本服务签发与吊销。
13
+ */
14
+ /** 设备令牌有效期(秒)。默认 90 天 —— 桥接是公网暴露面,令牌不宜过长。 */
15
+ export const DEVICE_TOKEN_TTL_SEC = 90 * 24 * 3600;
16
+ export function b64url(buf) {
17
+ return Buffer.from(buf).toString('base64')
18
+ .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
19
+ }
20
+ export function b64urlJson(obj) {
21
+ return b64url(Buffer.from(JSON.stringify(obj), 'utf8'));
22
+ }
23
+ export function fromB64url(s) {
24
+ const pad = '='.repeat((4 - (s.length % 4)) % 4);
25
+ return Buffer.from(s.replace(/-/g, '+').replace(/_/g, '/') + pad, 'base64');
26
+ }
27
+ export class AuthHub {
28
+ enabled;
29
+ issuer;
30
+ clientId;
31
+ loginClientId;
32
+ redirectUri;
33
+ scopes;
34
+ jwtSecret;
35
+ httpTimeoutMs;
36
+ dataDir;
37
+ /** 发现文档缓存。只有成功才固化——失败若被记住,容器编排下
38
+ * "本服务先于认证中心启动" 会让统一登录永久不可用直到重启。 */
39
+ _endpoints = null;
40
+ _discoverError = '';
41
+ /** clientId -> {userId, deviceName, registeredAt, lastSeenAt} */
42
+ devices = new Map();
43
+ /** jti -> 过期时间戳(吊销名单) */
44
+ revoked = new Map();
45
+ constructor(opts = {}) {
46
+ this.enabled = opts.enabled === true;
47
+ this.issuer = opts.issuer || '';
48
+ this.clientId = opts.clientId || '';
49
+ this.loginClientId = opts.loginClientId || '';
50
+ this.redirectUri = opts.redirectUri || '';
51
+ this.scopes = opts.scopes || ['openid', 'profile', 'email'];
52
+ this.jwtSecret = opts.jwtSecret || '';
53
+ this.httpTimeoutMs = opts.httpTimeoutMs || 10_000;
54
+ this.dataDir = opts.dataDir || null;
55
+ this._loadDevices();
56
+ }
57
+ // ==================== 配置与发现 ====================
58
+ /** 下发给客户端的公开参数。**绝不含任何 secret**。 */
59
+ publicConfig() {
60
+ const e = this._endpoints;
61
+ const cfg = {
62
+ enabled: this.enabled,
63
+ issuer: this.issuer,
64
+ clientId: this.clientId,
65
+ loginClientId: this.loginClientId || this.clientId,
66
+ redirectUri: this.redirectUri,
67
+ scopes: this.scopes,
68
+ authorizationEndpoint: e?.authorization_endpoint || `${this.issuer}/oauth2/auth`,
69
+ tokenEndpoint: e?.token_endpoint || `${this.issuer}/oauth2/token`,
70
+ idpAvailable: !!e,
71
+ };
72
+ if (!e)
73
+ cfg.idpError = this._discoverError || '未拉取到发现文档';
74
+ return cfg;
75
+ }
76
+ async discover() {
77
+ if (this._endpoints)
78
+ return this._endpoints;
79
+ if (!this.enabled)
80
+ throw Object.assign(new Error('统一登录未启用'), { code: 'disabled' });
81
+ const url = `${this.issuer.replace(/\/+$/, '')}/.well-known/openid-configuration`;
82
+ const doc = (await this._fetchJson(url, { method: 'GET' }));
83
+ if (!doc || !doc.token_endpoint) {
84
+ throw Object.assign(new Error('发现文档不完整'), { code: 'bad_discovery' });
85
+ }
86
+ this._endpoints = doc;
87
+ return this._endpoints;
88
+ }
89
+ async _fetchJson(urlStr, { method = 'GET', headers = {}, body = null } = {}) {
90
+ const http = await import('node:http');
91
+ return new Promise((resolve, reject) => {
92
+ let u;
93
+ try {
94
+ u = new URL(urlStr);
95
+ }
96
+ catch {
97
+ reject(new Error(`非法地址: ${urlStr}`));
98
+ return;
99
+ }
100
+ const payload = body === null ? '' : (typeof body === 'string' ? body : JSON.stringify(body));
101
+ const req = http.request({
102
+ method,
103
+ hostname: u.hostname,
104
+ port: u.port || (u.protocol === 'https:' ? 443 : 80),
105
+ path: u.pathname + u.search,
106
+ headers: {
107
+ ...(payload ? { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) } : {}),
108
+ ...headers,
109
+ },
110
+ timeout: this.httpTimeoutMs,
111
+ }, (res) => {
112
+ let raw = '';
113
+ res.on('data', (c) => { raw += c; });
114
+ res.on('end', () => {
115
+ let json = null;
116
+ try {
117
+ json = JSON.parse(raw);
118
+ }
119
+ catch { /* 非 JSON 就当原文 */ }
120
+ resolve(json || raw);
121
+ });
122
+ });
123
+ req.on('timeout', () => { req.destroy(new Error('请求超时')); });
124
+ req.on('error', reject);
125
+ if (payload)
126
+ req.write(payload);
127
+ req.end();
128
+ });
129
+ }
130
+ // ==================== 身份 ====================
131
+ /**
132
+ * 校验一枚**认证中心**的 access_token,返回身份。
133
+ *
134
+ * 与 mn-rt 的分工一致:exchange 是"我有 code,服务器你帮我换",
135
+ * verifyBearer 是"我有 token,服务器你帮我确认是谁"。两条路最终都收敛到
136
+ * 同一个结论——认证中心自己断言的 sub,所以属主判定只有一份实现。
137
+ */
138
+ async verifyBearer(accessToken) {
139
+ if (!accessToken)
140
+ throw Object.assign(new Error('缺少 access_token'), { code: 'bad_request' });
141
+ const doc = await this.discover();
142
+ const ui = (await this._fetchJson(doc.userinfo_endpoint || `${this.issuer}/oauth2/userinfo`, {
143
+ headers: { Authorization: `Bearer ${accessToken}` },
144
+ }));
145
+ const obj = (ui || {});
146
+ if (!ui || obj.error) {
147
+ throw Object.assign(new Error(`令牌无效: ${obj.error ? String(obj.error) : '无 sub'}`), { code: obj.error || 'invalid_token' });
148
+ }
149
+ if (!obj.sub)
150
+ throw Object.assign(new Error('userinfo 未返回 sub'), { code: 'no_sub' });
151
+ return {
152
+ userId: String(obj.sub),
153
+ sub: String(obj.sub),
154
+ email: obj.email ? String(obj.email) : '',
155
+ name: obj.name ? String(obj.name) : '',
156
+ preferredUsername: obj.preferred_username ? String(obj.preferred_username) : '',
157
+ };
158
+ }
159
+ // ==================== 设备令牌 ====================
160
+ /** 签发设备令牌。HS256 JWT,payload 带 userId 与 clientId。 */
161
+ issueDeviceToken({ userId, clientId, deviceName }) {
162
+ if (!this.jwtSecret) {
163
+ throw Object.assign(new Error('未配置 MN_WS_JWT_SECRET'), { code: 'no_secret' });
164
+ }
165
+ const now = Math.floor(Date.now() / 1000);
166
+ const header = { alg: 'HS256', typ: 'JWT' };
167
+ const payload = {
168
+ sub: userId,
169
+ cid: clientId,
170
+ dn: deviceName || '',
171
+ iat: now,
172
+ exp: now + DEVICE_TOKEN_TTL_SEC,
173
+ // jti 让单枚令牌可被单独吊销
174
+ jti: crypto.randomBytes(9).toString('hex'),
175
+ };
176
+ const head = b64urlJson(header);
177
+ const body = b64urlJson(payload);
178
+ const sig = b64url(crypto.createHmac('sha256', this.jwtSecret).update(`${head}.${body}`).digest());
179
+ return {
180
+ token: `${head}.${body}.${sig}`,
181
+ expiresAt: payload.exp * 1000,
182
+ jti: payload.jti,
183
+ };
184
+ }
185
+ /** 校验设备令牌。返回 payload 或 null。 */
186
+ verifyDeviceToken(token) {
187
+ if (!this.jwtSecret || !token || typeof token !== 'string')
188
+ return null;
189
+ const parts = token.split('.');
190
+ if (parts.length !== 3)
191
+ return null;
192
+ const [head, body, sig] = parts;
193
+ if (head === undefined || body === undefined || sig === undefined)
194
+ return null;
195
+ const want = b64url(crypto.createHmac('sha256', this.jwtSecret).update(`${head}.${body}`).digest());
196
+ // 常量时间比较:这里比的是"能不能冒充某个用户的一台桥"
197
+ const a = Buffer.from(sig);
198
+ const b = Buffer.from(want);
199
+ if (a.length !== b.length || !crypto.timingSafeEqual(a, b))
200
+ return null;
201
+ let payload;
202
+ try {
203
+ payload = JSON.parse(fromB64url(body).toString('utf8'));
204
+ }
205
+ catch {
206
+ return null;
207
+ }
208
+ if (!payload || !payload.sub)
209
+ return null;
210
+ if (typeof payload.exp !== 'number' || Math.floor(Date.now() / 1000) >= payload.exp)
211
+ return null;
212
+ if (this._isRevoked(payload.jti))
213
+ return null;
214
+ return payload;
215
+ }
216
+ /** 吊销某枚令牌。名单落盘 —— 否则重启即"全部恢复",而吊销往往正是因为设备丢了。 */
217
+ revoke(jti) {
218
+ if (!jti)
219
+ return;
220
+ this.revoked.set(jti, Date.now() + DEVICE_TOKEN_TTL_SEC * 1000);
221
+ this._saveDevices();
222
+ }
223
+ _isRevoked(jti) {
224
+ if (!this.revoked || !jti)
225
+ return false;
226
+ const until = this.revoked.get(jti);
227
+ if (!until)
228
+ return false;
229
+ if (until < Date.now()) {
230
+ this.revoked.delete(jti);
231
+ return false;
232
+ }
233
+ return true;
234
+ }
235
+ // ==================== 设备登记 ====================
236
+ /** 登记一台桥(client half):clientId → 属主。永久一对一。 */
237
+ registerDevice({ clientId, userId, deviceName }) {
238
+ if (!clientId)
239
+ throw Object.assign(new Error('缺少 clientId'), { code: 'bad_request' });
240
+ const existing = this.devices.get(clientId);
241
+ if (existing && existing.userId !== userId) {
242
+ throw Object.assign(new Error('该标识已属于别的账号'), { code: 'device_owned_by_other' });
243
+ }
244
+ const rec = {
245
+ userId,
246
+ clientId,
247
+ deviceName: deviceName || (existing && existing.deviceName) || '',
248
+ registeredAt: existing ? existing.registeredAt : new Date().toISOString(),
249
+ lastSeenAt: new Date().toISOString(),
250
+ };
251
+ this.devices.set(clientId, rec);
252
+ this._saveDevices();
253
+ return rec;
254
+ }
255
+ getDevice(clientId) {
256
+ return this.devices.get(clientId) || null;
257
+ }
258
+ devicesOf(userId) {
259
+ return [...this.devices.values()].filter((d) => d.userId === userId);
260
+ }
261
+ // ==================== 落盘 ====================
262
+ _devicesFile() {
263
+ return this.dataDir ? path.join(this.dataDir, 'devices.json') : null;
264
+ }
265
+ _loadDevices() {
266
+ const f = this._devicesFile();
267
+ if (!f)
268
+ return;
269
+ try {
270
+ if (!fs.existsSync(f))
271
+ return;
272
+ const raw = JSON.parse(fs.readFileSync(f, 'utf8'));
273
+ this.devices = new Map(Object.entries(raw.devices || {}));
274
+ this.revoked = new Map(Object.entries(raw.revoked || {}));
275
+ }
276
+ catch {
277
+ this.devices = new Map();
278
+ this.revoked = new Map();
279
+ }
280
+ }
281
+ _saveDevices() {
282
+ const f = this._devicesFile();
283
+ if (!f)
284
+ return;
285
+ try {
286
+ fs.mkdirSync(path.dirname(f), { recursive: true });
287
+ const tmp = `${f}.${process.pid}.tmp`;
288
+ fs.writeFileSync(tmp, JSON.stringify({
289
+ devices: Object.fromEntries(this.devices),
290
+ revoked: Object.fromEntries(this.revoked),
291
+ }, null, 2), { mode: 0o600 });
292
+ fs.renameSync(tmp, f);
293
+ }
294
+ catch { /* 落盘失败不阻断主流程 */ }
295
+ }
296
+ }
297
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * 启动 server 半。
3
+ *
4
+ * 三道安全闸(顺序不能换):
5
+ * 1. 无鉴权 → 拒绝启动(这个服务能把本机十几个服务桥到公网)
6
+ * 2. 无鉴权 → 不许绑 0.0.0.0
7
+ * 3. 端口被占 → 明确报错退出,**不静默顺延**
8
+ */
9
+ export declare function runServerCli(argv: string[]): Promise<void>;
10
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAyDA;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyFhE"}
package/dist/cli.js ADDED
@@ -0,0 +1,190 @@
1
+ import path from 'node:path';
2
+ import { createServer } from './server.js';
3
+ import { loadServerConfig, parseArgs, configDir } from './config.js';
4
+ import { isPortFree } from './apps.js';
5
+ /**
6
+ * mn-ws-server 的 CLI。
7
+ *
8
+ * server 半只有一个职责:把公网 HTTP 请求桥给本机的 nx 服务。
9
+ * 所以这里**不套** client 半那套 action 框架 —— 那套是为「CLI 与 Web 面板
10
+ * 同源」设计的,而 server 半没有面板。一台只有一个动作的服务,
11
+ * 用框架反而是负担。
12
+ *
13
+ * 命令:
14
+ * mn-ws-server 启动中继服务(公网半,HTTP 与 WS 同端口共存)
15
+ * mn-ws-server doctor 环境自检(端口占用 / 鉴权配置)
16
+ */
17
+ const C = {
18
+ reset: '\x1b[0m',
19
+ bold: '\x1b[1m',
20
+ dim: '\x1b[90m',
21
+ red: '\x1b[31m',
22
+ green: '\x1b[32m',
23
+ yellow: '\x1b[33m',
24
+ cyan: '\x1b[36m',
25
+ };
26
+ function say(msg = '') {
27
+ process.stdout.write(`${msg}\n`);
28
+ }
29
+ function printHelp(version) {
30
+ say(`
31
+ ${C.bold}mn-ws-server${C.reset} v${version} — mn-ws 的 server 半:公网侧的 HTTP ⇄ WebSocket 桥
32
+
33
+ ${C.bold}用法${C.reset}
34
+ npx mn-ws-server [options]
35
+
36
+ ${C.bold}选项${C.reset}
37
+ --host <h> 监听地址(默认 0.0.0.0;无鉴权时只允许 127.0.0.1)
38
+ --port <n> 监听端口(默认 7777)
39
+ --ws-path <p> WebSocket 路径(默认 /ws)
40
+ --token <TOKEN> 静态注册门禁(与 client 半配同一个)
41
+ --jwt-secret <s> 统一登录的 JWT 签名密钥(配了就启用设备令牌)
42
+ --auth-enabled <bool> 显式开/关统一登录(1/true/yes/on 与 0/false/no/off)
43
+ --issuer <url> 认证中心地址(默认 http://47.110.80.47:8082)
44
+ --idp-client-id <id> server 半在认证中心的身份(默认 mn-ws-server)
45
+ --login-client-id <id> client 半在认证中心的身份(默认 mn-ws-client)
46
+ --insecure 允许无鉴权启动(**仅限本机自测**)
47
+ --log-level <level> debug | info | warn | error(默认 info)
48
+ --help 显示帮助
49
+ --version 显示版本
50
+ `);
51
+ }
52
+ /**
53
+ * 启动 server 半。
54
+ *
55
+ * 三道安全闸(顺序不能换):
56
+ * 1. 无鉴权 → 拒绝启动(这个服务能把本机十几个服务桥到公网)
57
+ * 2. 无鉴权 → 不许绑 0.0.0.0
58
+ * 3. 端口被占 → 明确报错退出,**不静默顺延**
59
+ */
60
+ export async function runServerCli(argv) {
61
+ const { flags, positional } = parseArgs(argv);
62
+ const version = (await readVersion()) || '0.0.0';
63
+ if (flags.version) {
64
+ say(version);
65
+ return;
66
+ }
67
+ if (flags.help || positional[0] === 'help') {
68
+ printHelp(version);
69
+ return;
70
+ }
71
+ if (positional[0] === 'doctor') {
72
+ await runDoctor(argv);
73
+ return;
74
+ }
75
+ if (positional.length) {
76
+ say(`${C.red}未知命令:${positional.join(' ')}${C.reset}`);
77
+ printHelp(version);
78
+ process.exitCode = 1;
79
+ return;
80
+ }
81
+ const cfg = loadServerConfig(flags);
82
+ // ── 闸 1:没有鉴权就不许起 ──
83
+ const hasGate = !!cfg.token;
84
+ const hasJwt = !!cfg.jwtSecret;
85
+ const wantAuth = cfg.authEnabled === undefined ? hasJwt : cfg.authEnabled;
86
+ if (wantAuth && !hasJwt) {
87
+ say(`${C.red}✗ 拒绝启动:统一登录已开启,但没有 JWT secret${C.reset}`);
88
+ say(`${C.dim}签不出设备令牌 = 统一登录等于没开。给一个随机串,或把 MN_WS_AUTH_ENABLED 关掉。${C.reset}`);
89
+ process.exitCode = 1;
90
+ return;
91
+ }
92
+ if (!wantAuth && hasJwt) {
93
+ say(`${C.yellow}! 统一登录已显式关闭${C.reset}${C.dim},JWT secret 不会生效${C.reset}`);
94
+ }
95
+ if (!hasGate && !wantAuth && !cfg.insecure) {
96
+ say(`${C.red}✗ 拒绝启动:没有任何鉴权配置${C.reset}`);
97
+ say(`${C.dim}mn-ws server 会把本机的 nx 服务桥到公网,没有鉴权等于把整台机器挂在网上。${C.reset}`);
98
+ say('');
99
+ say(` ${C.cyan}--token <TOKEN>${C.reset} 与客户端配同一个静态门禁`);
100
+ say(` ${C.cyan}MN_WS_JWT_SECRET=<随机>${C.reset} 启用统一登录(推荐,可按用户隔离)`);
101
+ say(` ${C.cyan}--insecure${C.reset} 仅限本机自测,明知风险才用`);
102
+ process.exitCode = 1;
103
+ return;
104
+ }
105
+ if (!hasGate && !wantAuth && cfg.insecure) {
106
+ say(`${C.yellow}! 已用 --insecure:无鉴权启动${C.reset}${C.dim} —— 任何人都能通过它调用本机服务${C.reset}`);
107
+ }
108
+ // ── 闸 2:无鉴权时只许绑回环 ──
109
+ if (cfg.host === '0.0.0.0' && !hasGate && !wantAuth) {
110
+ say(`${C.red}✗ 无鉴权时不允许绑 0.0.0.0${C.reset}:请用 --host 127.0.0.1 自测`);
111
+ process.exitCode = 1;
112
+ return;
113
+ }
114
+ // ── 闸 3:端口被占 → 明确报错,不静默顺延 ──
115
+ const free = await isPortFree(cfg.port, cfg.host === '0.0.0.0' ? '0.0.0.0' : cfg.host);
116
+ if (!free.free) {
117
+ say(`${C.red}✗ 端口 ${cfg.port} 已被占用${C.reset}${C.dim}(${(free.error && free.error.code) || ''})${C.reset}`);
118
+ say(`${C.dim}换端口:--port <n>。不静默顺延 —— 客户端还按 ${cfg.port} 连,顺延只会让两边对不上账。${C.reset}`);
119
+ process.exitCode = 1;
120
+ return;
121
+ }
122
+ const server = createServer({
123
+ host: cfg.host,
124
+ port: cfg.port,
125
+ wsPath: cfg.wsPath,
126
+ token: cfg.token,
127
+ issuer: cfg.issuer,
128
+ idpClientId: cfg.idpClientId,
129
+ loginClientId: cfg.loginClientId,
130
+ redirectUri: cfg.redirectUri || `http://127.0.0.1:${cfg.port}/auth/callback`,
131
+ jwtSecret: cfg.jwtSecret,
132
+ authEnabled: wantAuth,
133
+ insecure: cfg.insecure,
134
+ requestTimeoutMs: cfg.requestTimeoutMs,
135
+ dataDir: cfg.dataDir,
136
+ logLevel: cfg.logLevel,
137
+ });
138
+ const actual = await server.listen();
139
+ say(`${C.green}✓ mn-ws server 已启动${C.reset} http://${cfg.host}:${actual} ws=${cfg.wsPath}`);
140
+ say(`${C.dim} 鉴权:${wantAuth ? '统一登录(设备令牌)' : ''}${wantAuth && hasGate ? ' + ' : ''}${hasGate ? '静态门禁' : ''}${!wantAuth && !hasGate ? '无(--insecure)' : ''}${C.reset}`);
141
+ say(`${C.dim} 配置目录:${configDir()}${C.reset}`);
142
+ const shutdown = async (sig) => {
143
+ say(`\n${C.dim}收到 ${sig},正在关闭…${C.reset}`);
144
+ await server.close();
145
+ process.exit(0);
146
+ };
147
+ process.on('SIGINT', () => { void shutdown('SIGINT'); });
148
+ process.on('SIGTERM', () => { void shutdown('SIGTERM'); });
149
+ }
150
+ /** 环境自检。 */
151
+ async function runDoctor(argv) {
152
+ const { flags } = parseArgs(argv);
153
+ const cfg = loadServerConfig(flags);
154
+ say(`${C.bold}mn-ws-server doctor${C.reset} ${C.dim}v${(await readVersion()) || '0.0.0'}${C.reset}`);
155
+ say('');
156
+ say(`${C.bold}端口${C.reset}`);
157
+ const free = await isPortFree(cfg.port, cfg.host === '0.0.0.0' ? '0.0.0.0' : cfg.host);
158
+ say(free.free
159
+ ? ` server :${cfg.port} ${C.green}空闲${C.reset}`
160
+ : ` server :${cfg.port} ${C.red}已被占用${C.reset}`);
161
+ say('');
162
+ say(`${C.bold}鉴权${C.reset}`);
163
+ if (cfg.jwtSecret)
164
+ say(` ${C.green}✓${C.reset} 统一登录密钥已配置`);
165
+ else
166
+ say(` ${C.yellow}!${C.reset} 未配置统一登录密钥(MN_WS_JWT_SECRET)`);
167
+ if (cfg.token)
168
+ say(` ${C.green}✓${C.reset} 静态门禁 token(共享密钥,等价全量访问)`);
169
+ else
170
+ say(` ${C.yellow}!${C.reset} 未配置静态门禁(客户端只能用设备令牌注册)`);
171
+ say('');
172
+ say(`${C.bold}身份${C.reset}`);
173
+ say(` issuer ${cfg.issuer}`);
174
+ say(` server 半 client_id ${cfg.idpClientId}`);
175
+ say(` client 半 client_id ${cfg.loginClientId}`);
176
+ say('');
177
+ say(`${C.dim} 数据目录:${path.join(configDir(), 'data')}${C.reset}`);
178
+ }
179
+ async function readVersion() {
180
+ try {
181
+ const fs = await import('node:fs');
182
+ const url = new URL('../package.json', import.meta.url);
183
+ const raw = fs.readFileSync(url, 'utf8');
184
+ return JSON.parse(raw).version || null;
185
+ }
186
+ catch {
187
+ return null;
188
+ }
189
+ }
190
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * server 半的配置解析。
3
+ *
4
+ * 优先级:**默认值 < 配置文件 < 环境变量 < 命令行参数**(与 mn-rt 同一套)。
5
+ *
6
+ * 配置文件位置:~/.mn-ws/server.json(环境变量 MN_WS_HOME 可覆盖)。
7
+ *
8
+ * ⚠️ 账号表(多账号登录态)在 **client 半**——只有它需要「谁登录了这台机器」。
9
+ * server 半只认凭据,不认人;人的身份由 client 半带来的设备令牌断言。
10
+ */
11
+ /** server 半的最终配置。 */
12
+ export interface ServerConfig {
13
+ host: string;
14
+ port: number;
15
+ wsPath: string;
16
+ token: string;
17
+ issuer: string;
18
+ /** server 半自己的 OIDC 身份 */
19
+ idpClientId: string;
20
+ /** client 半的身份:真正发起授权码流程的是它 */
21
+ loginClientId: string;
22
+ redirectUri: string;
23
+ jwtSecret: string;
24
+ authEnabled: boolean | undefined;
25
+ insecure: boolean;
26
+ requestTimeoutMs: number;
27
+ logLevel: string;
28
+ dataDir: string | null;
29
+ }
30
+ /** 命令行解析结果。 */
31
+ export interface ParsedArgs {
32
+ flags: Record<string, unknown>;
33
+ positional: string[];
34
+ }
35
+ export declare function configDir(): string;
36
+ export declare function serverConfigFile(): string;
37
+ export declare function readConfigFile(): Record<string, unknown>;
38
+ /** 真值判定:1 / true / yes / on(大小写不敏感)。 */
39
+ export declare function isEnvTruthy(value: unknown): boolean;
40
+ /**
41
+ * 布尔开关的严格解析。
42
+ *
43
+ * 空 → undefined(**没表态**,让上层按「跟随其他配置」处理);
44
+ * 1/true/yes/on → true;0/false/no/off → false;其他值 → **直接抛错**。
45
+ *
46
+ * 为什么要严格:部署脚本里 `MN_WS_AUTH_ENABLED=1` 被当成「关闭」时,
47
+ * 服务照常启动、/health 照样绿,而整套按用户隔离的属主判据**静默不存在** ——
48
+ * CI 全绿、人以为开着。这类「配了等于没配」必须在解析层就炸掉。
49
+ */
50
+ export declare function parseBoolFlag(v: unknown): boolean | undefined;
51
+ /** 命令行解析:--key value / --key=value / --flag / 位置参数。 */
52
+ export declare function parseArgs(argv: string[]): ParsedArgs;
53
+ export declare function camel(s: string): string;
54
+ /**
55
+ * 取字符串值,缺省是**空串**。
56
+ *
57
+ * 为什么不能直接 String(pick(...)):pick 全空时返回 undefined,
58
+ * 而 `String(undefined)` 是字符串 **"undefined"** —— 不是空串!
59
+ * 这里是**安全项**:token / jwtSecret 若是 "undefined",
60
+ * `config.token && gate === config.token` 就等于「任何人都能用
61
+ * `X-Mn-Ws-Token: undefined` 通过门禁」。所以缺省必须是空串。
62
+ */
63
+ export declare function str(v: unknown): string;
64
+ /**
65
+ * 合并出最终配置。
66
+ *
67
+ * 环境变量前缀 MN_WS_(REMOTETYPE_ 那种大写下划线风格)。
68
+ */
69
+ export declare function loadServerConfig(flags?: Record<string, unknown>): ServerConfig;
70
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH,qBAAqB;AACrB,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,QAAQ,EAAE,OAAO,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,eAAe;AACf,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQxD;AAED,wCAAwC;AACxC,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAInD;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAO7D;AAED,uDAAuD;AACvD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAgCpD;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEvC;AASD;;;;;;;;GAQG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAEtC;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,YAAY,CAsBlF"}