feat(ops): 数据保留清理、CORS 白名单与上传失败回滚

- 新增每日数据保留清理任务:按保留期清空原始报文、删除过期
  事件/审计记录,批量幂等可重跑;067 迁移补齐清理索引并清理
  冗余索引,check-sql-guard 增加防线
- 生产 CORS 改为显式来源白名单(CORS_ALLOWED_ORIGINS),禁用
  通配符,非通配响应补充 Vary: Origin
- 文件上传任一步失败时回滚已上传对象,清理失败记录 warn 日志
- 新增 HTTP/CORS 与 PostgreSQL 集成测试;若干文件仅 prettier 重排
This commit is contained in:
yml2213
2026-08-30 13:59:01 +08:00
parent dcb0fa4c76
commit 02c9de8b9c
25 changed files with 489 additions and 71 deletions
@@ -79,6 +79,14 @@ export function validateRuntimeConfig(
min: 1,
max: 100,
})
if (config.retention) {
requireInteger(issues, 'retention.rawPayloadDays', config.retention.rawPayloadDays, { min: 1 })
requireInteger(issues, 'retention.taskEventDays', config.retention.taskEventDays, { min: 1 })
requireInteger(issues, 'retention.webhookEventDays', config.retention.webhookEventDays, {
min: 1,
})
requireInteger(issues, 'retention.auditLogDays', config.retention.auditLogDays, { min: 1 })
}
const storageMode = normalizeStorageMode(config.storage?.mode)
if (!storageMode) {
issues.push({
@@ -137,6 +145,24 @@ export function validateRuntimeConfig(
validateRequiredHttpUrl(issues, 'orders.claimBaseUrl', config.orders?.claimBaseUrl)
validateSecret(issues, 'admin.sessionSecret', config.admin?.sessionSecret, { minLength: 32 })
validateAdminDefaultUsers(issues, config.admin?.defaultUsers)
const allowedOrigins = config.cors?.allowedOrigins
if (Array.isArray(allowedOrigins)) {
if (allowedOrigins.length === 0 || allowedOrigins.includes('*')) {
issues.push({
path: 'cors.allowedOrigins',
message: '生产环境必须配置显式 CORS 域名白名单,不能使用 *',
})
} else {
allowedOrigins.forEach((origin, index) => {
if (!isHttpUrl(String(origin || '').trim())) {
issues.push({
path: `cors.allowedOrigins[${index}]`,
message: '必须是 http 或 https 来源 URL',
})
}
})
}
}
}
return issues