Files
ln-bi/src/server/db/schema/guard.ts
T
dsh-agent 954d626afc refactor(stage8): 建表语句集中到 server/db/schema,并修复只读模式的漏写
问题
- 4 处运行时 DDL(scheduling / ele / feedback / mileage 日报)分散在路由与 store 里;
- 只读保护只按 HTTP 方法拦截,而建表由 GET 处理器触发,
  于是 DB_READ_ONLY=1 的"只读预览"仍可能执行 CREATE TABLE / ALTER TABLE(已记录在案的漏洞)。

改动
- 新增 src/server/db/schema/{guard,scheduling,ele,feedback,mileage-report}.ts:
  建表/改表的唯一位置;guard 提供 ddlAllowed(),DB_READ_ONLY=1 时每个 ensure* 直接跳过并打印一行日志。
- daily-report-store 的表名改为从 schema 模块导出,避免两处各写一份表名。
- 移除 feedback/index.ts 与 ele/migration.ts 中的内联 DDL。

验证
- 实测:DB_READ_ONLY=1 下依次调用 4 个 ensure*,全部跳过且未触碰数据库(无连接错误/挂起)。
- 架构测试新增 2 条:DDL 只允许出现在 server/db/schema;每个 schema 模块必须检查 ddlAllowed()。

lint / test(139) / build 全绿。
2026-09-11 10:29:50 +08:00

17 lines
546 B
TypeScript

import { isDbReadOnly } from '../../config.js';
/**
* 运行时建表守卫。
*
* 只读预览(DB_READ_ONLY=1)下不允许任何 DDL。此前只读保护只按 HTTP 方法拦截,
* 而建表实际由 GET 处理器触发,于是"只读"预览仍可能执行 CREATE TABLE。
*/
export function ddlAllowed(): boolean {
return !isDbReadOnly();
}
/** 统一的跳过日志,避免每个 schema 模块各写一份。 */
export function logDdlSkipped(name: string): void {
console.log(`[schema] ${name} skipped (DB_READ_ONLY=1)`);
}