feat: harden auth and study workflows

- replace plaintext login and unlock requests with RSA-OAEP/AES-GCM encrypted payloads

- add login challenge replay protection, production RSA key validation, and auth tests

- wire compose to environment-driven dev/prod settings without committing local secrets

- update setup-config smoke scripts and Postman docs for encrypted login

- add visit schedule migrations/tests and update study/subject setup workflows
This commit is contained in:
Cheng Zhou
2026-05-08 22:13:12 +08:00
parent a7bbcaa5dc
commit 74feca4467
47 changed files with 2423 additions and 534 deletions
+18 -8
View File
@@ -15,8 +15,9 @@ export interface ApiError {
}
export interface LoginRequest {
email: string;
password: string;
key_id: string;
challenge: string;
ciphertext: string;
}
export interface LoginResponse {
@@ -24,6 +25,13 @@ export interface LoginResponse {
token_type: string;
}
export interface LoginKeyResponse {
key_id: string;
public_key: string;
challenge: string;
expires_at: string;
}
export type UserRole = "PM" | "CRA" | "PV" | "IMP" | "QA" | "ADMIN";
export type UserStatus = "PENDING" | "ACTIVE" | "REJECTED" | "DISABLED";
@@ -79,20 +87,22 @@ export interface Study {
planned_enrollment_count?: number | null;
enrollment_monthly_goal_note?: string | null;
enrollment_stage_breakdown?: string | null;
summary_note?: string | null;
objective_note?: string | null;
phase?: string | null;
status: string;
is_locked?: boolean;
visit_interval_days?: number | null;
visit_total?: number | null;
visit_window_start_offset?: number | null;
visit_window_end_offset?: number | null;
visit_schedule?: VisitScheduleItem[];
created_by?: string | null;
created_at?: string;
role_in_study?: string | null;
}
export interface VisitScheduleItem {
visit_code: string;
baseline_offset_days: number;
window_before_days: number;
window_after_days: number;
}
export interface StudyMember {
id: string;
study_id: string;
+8 -6
View File
@@ -66,6 +66,13 @@ export interface SetupConfigDraft {
centerConfirm: CenterConfirmDraft[];
}
export interface VisitScheduleItem {
visit_code: string;
baseline_offset_days: number;
window_before_days: number;
window_after_days: number;
}
export interface ProjectPublishSnapshot {
code: string;
name: string;
@@ -85,13 +92,8 @@ export interface ProjectPublishSnapshot {
plan_end_date: string;
planned_site_count: number | null;
planned_enrollment_count: number | null;
summary_note: string;
objective_note: string;
status: string;
visit_interval_days: number | null;
visit_total: number | null;
visit_window_start_offset: number | null;
visit_window_end_offset: number | null;
visit_schedule: VisitScheduleItem[];
}
export interface StudySetupConfigResponse {