Files
dsh_shenxian/scripts/clean-ws-pollution.cjs
admin 452924d89c feat(config): 涉密内容外置到配置目录(档案 140)
把散落在代码里的真实部署值统一收进 config/,代码改为引用配置,
使仓库副本/开源导出不再带出生产域名、IP、内网路径与凭据。

新增 config/:platform.env.example(模板)· load.sh(shell 加载器)·
index.cjs(node 加载器)· README.md(键一览与优先级)。
真实值放 config/platform.env —— 已 .gitignore 排除,不入库、不进导出。

TS 侧新增 src/platform-paths.ts 作部署路径的唯一解析处(零副作用):
platformDir/stateDir/backupDir/artifactDir/installDir/scriptPath。
config.ts 接入这些字段;内置中继种子由生产 URL 改为空(改由
DSHS_OVERLAY_BOOTSTRAP_SEEDS 提供)。修掉 5 处硬编码绝对路径,
src/** 注释中性化 116 行/53 文件。

scripts/** 36 个内部运维脚本:真令牌/PG 口令/隧道目标/主机号/路径
一律改从配置取;web/wake.html 的注册域白名单改为运行时从
location.hostname 推导;test/** 夹具 119 行/13 文件改 RFC 2606/5737
保留值,并把「内置种子必须为空」固化为回归断言。

取证:tsc 0 错;npm test 373/375(唯一失败 lease 属既有);
全仓扫描(大小写不敏感)代码面涉密标识 = 0;已部署 47 并零回归
(/opt/dsh/* 未搬家,/var/lib/dshs/platform 未被误建)。
2026-09-19 15:12:19 +08:00

73 lines
3.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
const cfg = require('../config/index.cjs')
/**
* clean-ws-pollution.cjs —— 清理"平台安装插件"在用户工作区留下的污染(档案 28)
*
* 白名单(精确匹配,绝不碰其它内容):
* ws/.local pnpm store(旧 HOME=<ws> 造成)
* ws/.cache pnpm metadata 缓存
* ws/.poc-backup PoC 备份
* ws/poc PoC 源码副本
* ws/*.tgz 安装用插件包(现在改为直接用 <platform-dir>/artifacts/ 不再复制)
*
* 用法:
* node clean-ws-pollution.cjs # dry-run(默认,只打印)
* node clean-ws-pollution.cjs --apply # 实际执行:mv 到 <userRoot>/trash/<日期>-ws-pollution/
* node clean-ws-pollution.cjs --apply --user-id <uuid>
* 动作是**移动**(同盘 mv,秒级、可恢复),不是删除。
*/
const { execFileSync } = require('node:child_process')
const { existsSync, mkdirSync, readdirSync, statSync } = require('node:fs')
const { join } = require('node:path')
const Database = require('better-sqlite3')
const APPLY = process.argv.includes('--apply')
const idx = process.argv.indexOf('--user-id')
const onlyId = idx >= 0 ? process.argv[idx + 1] : ''
const STAMP = new Date().toISOString().slice(0, 10)
const db = new Database(cfg.dbFile(), { readonly: true })
const users = db.prepare('SELECT id, username, uid, home_dir FROM users').all()
.filter((u) => onlyId === '' || u.id === onlyId)
const du = (p) => {
try {
const out = execFileSync('du', ['-sk', p], { encoding: 'utf8' })
return Number(out.split(/\s+/)[0]) * 1024
} catch { return 0 }
}
const fmt = (b) => (b >= 1048576 ? (b / 1048576).toFixed(1) + ' MB' : (b / 1024).toFixed(0) + ' KB')
for (const u of users) {
const ws = join(u.home_dir, '..', 'ws')
if (!existsSync(ws)) { console.log(` ${u.username}: NO_WS`); continue }
const cands = []
for (const rel of ['.local', '.cache', '.poc-backup', 'poc']) {
const p = join(ws, rel)
if (existsSync(p)) cands.push({ p, size: du(p) })
}
for (const f of readdirSync(ws)) {
if (f.endsWith('.tgz')) {
const p = join(ws, f)
try { if (statSync(p).isFile()) cands.push({ p, size: statSync(p).size }) } catch {}
}
}
const total = cands.reduce((a, c) => a + c.size, 0)
console.log(` ${u.username}: 候选 ${cands.length} 项 / ${fmt(total)}${APPLY ? ' → 移入回收站' : '(dry-run)'}`)
for (const c of cands) console.log(` - ${c.p.replace(ws, 'ws')} ${fmt(c.size)}`)
if (APPLY && cands.length > 0) {
const trash = join(u.home_dir, '..', 'trash', `${STAMP}-ws-pollution`)
mkdirSync(trash, { recursive: true })
for (const c of cands) {
const dest = join(trash, c.p.slice(ws.length + 1).replace(/\//g, '__'))
try {
execFileSync('mv', [c.p, dest])
execFileSync('chown', ['-R', `${u.uid}:${u.uid}`, dest])
} catch (e) { console.log(` ! 移动失败 ${c.p}: ${String(e.message).split('\n')[0]}`) }
}
console.log(` → 已移至 ${trash.replace(u.home_dir, 'home')}(保留 30 天,可整目录移回恢复)`)
}
}
db.close()
console.log(APPLY ? 'done(已移动)' : 'done(dry-run,未改动)')