fix: 全面 QA 审计修复 — 安全加固/代码质量/跨平台一致性/测试覆盖
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

Phase 0 安全热修复 (CRITICAL):
- 外部化微信 appid/secret 到 ERP__WECHAT__APPID/SECRET 环境变量
- 正确连接 HealthCrypto 到 ERP__HEALTH__AES_KEY/HMAC_KEY 环境变量
- 外部化小程序加密密钥到 TARO_APP_ENCRYPTION_KEY 环境变量
- 移除小程序 auth store 中的敏感信息 console.log

Phase 1 安全加固:
- 微信自动注册 display_name 添加 sanitize 防止 XSS
- 测试数据库凭据改为从 TEST_DB_URL 环境变量读取

Phase 2 代码质量:
- 提取 useThemeMode hook 消除 22 处重复暗色模式检测
- 提取共享健康常量到 constants/health.ts
- 拆分 patient_service.rs 脱敏函数到 masking.rs
- 移除未使用的 i18next/react-i18next 依赖
- 移除未使用的 api/errors.ts 和 erp-auth/anyhow 依赖

Phase 3 测试覆盖:
- 新增 5 个患者模块集成测试 (CRUD/租户隔离/验证/软删除)

Phase 4 跨平台一致性:
- 统一小程序 Patient.birthday → birth_date 匹配后端
- 统一小程序 Appointment.time_slot → start_time/end_time 匹配后端

Phase 5 架构:
- 微信登录添加多租户 TODO 注释
- 更新 wiki/infrastructure.md 环境变量文档
This commit is contained in:
iven
2026-04-25 10:00:49 +08:00
parent 07f4ba41ba
commit 945ccd64ba
56 changed files with 634 additions and 273 deletions

View File

@@ -6,7 +6,8 @@ export interface Appointment {
doctor_name: string;
department: string;
appointment_date: string;
time_slot: string;
start_time: string;
end_time: string;
status: string;
version: number;
}
@@ -22,7 +23,8 @@ export interface DoctorSchedule {
id: string;
doctor_id: string;
date: string;
time_slot: string;
start_time: string;
end_time: string;
available_count: number;
}
@@ -39,7 +41,8 @@ export async function createAppointment(data: {
doctor_id: string;
schedule_id?: string;
appointment_date: string;
time_slot: string;
start_time: string;
end_time: string;
reason?: string;
}) {
return api.post<Appointment>('/health/appointments', data);

View File

@@ -23,7 +23,7 @@ export interface PatientInfo {
id: string;
name: string;
gender?: string;
birthday?: string;
birth_date?: string;
relation: string;
}
@@ -42,3 +42,8 @@ export async function wechatBindPhone(openid: string, encryptedData: string, iv:
export async function getPatients() {
return api.get<PatientInfo[]>('/health/patients');
}
/** 开发模式:用户名密码直登 */
export async function devLogin(username: string, password: string) {
return api.post<LoginResp['token']>('/auth/login', { username, password });
}

View File

@@ -4,7 +4,7 @@ export interface Patient {
id: string;
name: string;
gender?: string;
birthday?: string;
birth_date?: string;
phone?: string;
id_number?: string;
relation?: string;
@@ -18,7 +18,7 @@ export async function listPatients() {
export async function createPatient(data: {
name: string;
gender?: string;
birthday?: string;
birth_date?: string;
phone?: string;
id_number?: string;
}) {
@@ -28,7 +28,7 @@ export async function createPatient(data: {
export interface PatientUpdateInput {
name?: string;
gender?: string;
birthday?: string;
birth_date?: string;
phone?: string;
id_number?: string;
relation?: string;