加固既有生产部署流程(07-27-yang-jun-reimbursement-readiness)

这个提交包含在:
2026-08-01 18:25:20 +08:00
父节点 5dac336fbf
当前提交 07de198b51
共修改 15 个文件,包含 375 行新增和 34 行删除
+6 -15
查看文件
@@ -1,7 +1,5 @@
require("dotenv/config");
const crypto = require("node:crypto");
const { createPrismaClient } = require("../prismaClient");
const { hashPassword } = require("../utils/crypto");
const { validatePassword } = require("../utils/passwordPolicy");
@@ -94,12 +92,6 @@ async function ensureDepartment(prisma, payload) {
});
}
function generateOneTimePassword() {
// 确保满足 passwordPolicy:>=12 + 小写 + 大写 + 数字
const suffix = crypto.randomBytes(6).toString("hex");
return `TrialrunA1${suffix}`;
}
async function ensureFeatureFlag(prisma, payload) {
const now = new Date();
const existing = await prisma.featureFlag.findUnique({
@@ -248,7 +240,10 @@ async function ensureAdminEmployee(prisma, params) {
return { employeeId: existing.id, created: false, password: null };
}
const password = params.password || generateOneTimePassword();
if (!params.password) {
throw new Error('TRIALRUN_ADMIN_PASSWORD is required when creating the trialrun admin; credentials are never generated into deployment logs');
}
const password = params.password;
const errors = validatePassword(password);
if (errors.length) {
throw new Error(`Invalid TRIALRUN_ADMIN_PASSWORD: ${errors.join("; ")}`);
@@ -348,9 +343,7 @@ async function main() {
// eslint-disable-next-line no-console
console.log("Seeded trialrun admin:");
// eslint-disable-next-line no-console
console.log(`- email: ${adminEmail}`);
// eslint-disable-next-line no-console
console.log(`- phone: ${adminPhone}`);
console.log("- login identifiers: configured");
// eslint-disable-next-line no-console
console.log(`- created: ${result.created}`);
// eslint-disable-next-line no-console
@@ -361,9 +354,7 @@ async function main() {
}
if (result.password) {
// eslint-disable-next-line no-console
console.log(`- one-time password: ${result.password}`);
// eslint-disable-next-line no-console
console.log(" (请立刻保存,并在首次登录后由管理员重置/更换密码)");
console.log("- initial password: supplied by approved configuration; not logged");
} else {
// eslint-disable-next-line no-console
console.log("- password: unchanged");
+7 -7
查看文件
@@ -31,7 +31,7 @@ function evaluateWecom(config) {
return {
state: 'degraded',
detail: `企业微信基础配置已启用,但入口=${config.wecomEntryEnabled ? 'on' : 'off'} oauth=${config.wecomOauthEnabled ? 'on' : 'off'}`,
checks: [`corpId=${config.wecomCorpId}`, `agentId=${config.wecomAgentId}`],
checks: ['corpId=present', 'agentId=present'],
};
}
@@ -39,9 +39,9 @@ function evaluateWecom(config) {
state: 'ready',
detail: '企业微信入口与免登配置齐全',
checks: [
`corpId=${config.wecomCorpId}`,
`agentId=${config.wecomAgentId}`,
`redirectUri=${config.wecomRedirectUri}`,
'corpId=present',
'agentId=present',
'redirectUri=present',
`pcWebLogin=${config.wecomPcWebLoginEnabled ? 'on' : 'off'}`,
],
};
@@ -66,7 +66,7 @@ function evaluateEmail(config) {
return {
state: 'ready',
detail: 'SMTP 基础配置齐全(仅做配置契约校验,不发真实邮件)',
checks: [`from=${config.emailFrom}`, `host=${config.smtpHost}`, `port=${config.smtpPort}`, `secure=${config.smtpSecure}`],
checks: ['from=present', 'host=present', 'port=valid', `secure=${config.smtpSecure}`],
};
}
@@ -88,7 +88,7 @@ function evaluateOcr(config) {
return {
state: 'ready',
detail: '腾讯 OCR 配置齐全',
checks: [`provider=${provider}`, `region=${config.tencentOcrRegion}`],
checks: [`provider=${provider}`, 'credentials=present', 'region=present'],
};
}
@@ -112,7 +112,7 @@ function evaluateBridge(config) {
return {
state: 'ready',
detail: '消息回流桥接配置齐全',
checks: [`appOrigin=${config.appOrigin}`],
checks: ['appOrigin=present'],
};
}
+2 -2
查看文件
@@ -203,9 +203,9 @@ async function main() {
});
}
assertCondition(Boolean(adminEmployee), `未找到 active admin 员工:${adminEmail}`);
assertCondition(Boolean(adminEmployee), '未找到 active admin 员工');
assertCondition(adminEmployee.status === 'active' && !adminEmployee.archived_at, `active admin 状态异常:${adminEmployee.status}`);
console.log(`[PASS] 已找到 active admin 员工:${adminEmployee.employee_no}`);
console.log('[PASS] 已找到 active admin 员工');
const workspace = await getWorkspaceSetting(prisma);
assertWorkspaceSetting(workspace);