/** * portal/lifecycle/model.mjs — 생명주기(§23)·사이트 수 반환(§14) 영역 추가 표·열. * lifecycle_events 상태 전이 기록(누가·언제·어디서→어디로·이유). 화면의 "되돌릴 수 없는 시점"·"다음 알림" 계산 근거. * sites.mail_choice 해지 때 사이트 대표 메일 처리 선택(keep=독립 메일로 전환 | end=종료) * sites.next_notice_at 다음 알림 예정 시각(§23.3) * sites.delete_hold_reason 법적 보존·분쟁으로 삭제 보류(§23.2) * sites.public_stopped_at 공개 서비스 중지 시각(§14 1단계 근거) * sites.prev_lifecycle 해지 예약을 되돌릴 때 복귀할 상태 * domains.routed 공개 라우팅 여부(1=연결, 0=해제 §14 2단계) * mail_services.lifecycle / next_notice_at / delete_hold_reason 메일 서비스 생명주기(active·paused·readonly_retention·pending_delete·deleted·delete_hold) */ export const MIGRATIONS = [{ id: 'lifecycle_0001', sql: ` CREATE TABLE IF NOT EXISTS lifecycle_events ( id TEXT PRIMARY KEY, subject_type TEXT NOT NULL, subject_id TEXT NOT NULL, group_id TEXT, from_state TEXT, to_state TEXT NOT NULL, at TEXT NOT NULL, by TEXT, reason TEXT, detail_json TEXT ); CREATE INDEX IF NOT EXISTS lifecycle_events_subject ON lifecycle_events(subject_type, subject_id, at); ALTER TABLE sites ADD COLUMN mail_choice TEXT; ALTER TABLE sites ADD COLUMN next_notice_at TEXT; ALTER TABLE sites ADD COLUMN delete_hold_reason TEXT; ALTER TABLE sites ADD COLUMN public_stopped_at TEXT; ALTER TABLE sites ADD COLUMN prev_lifecycle TEXT; ALTER TABLE domains ADD COLUMN routed INTEGER NOT NULL DEFAULT 1; ALTER TABLE mail_services ADD COLUMN lifecycle TEXT NOT NULL DEFAULT 'active'; ALTER TABLE mail_services ADD COLUMN next_notice_at TEXT; ALTER TABLE mail_services ADD COLUMN delete_hold_reason TEXT; ` }];