-- 1.3.0 — 증거 보존(legal hold) + 디스패처 생존 기록 -- -- 적용 조건: 2026-09-04-fall-from-height.sql 이후. -- -- 왜 이 두 개가 한 마이그레이션인가: 둘 다 "조용한 실패"를 드러내는 같은 종류의 장치다. -- -- 1) move_events.hold_until — 스냅샷 보존 보류 -- 스냅샷은 보존기간이 지나면 나이만 보고 지워졌다. 중대재해 조사는 몇 주에서 몇 달인데 -- 사진은 7일이면 사라진다. 우리가 노조와 고객에게 말해 온 목적("사고 후 원인 분석")이 -- 8일째에 증발하는 상태였다. 보류는 명시적 조작이어야 하고(자동 연장은 결국 전량 보존이 -- 되어 프라이버시 약속을 무너뜨린다) 감사에 남아야 한다. -- -- 2) move_app_state — 크론이 마지막으로 돈 시각 -- 죽은 노드는 스스로 신고할 수 없어서 크론이 하트비트의 부재로 판정한다. 그런데 그 -- 크론이 죽으면 아무도 판정하지 않는다. 통보·확대·장치 이상 발행이 전부 한 프로세스에 -- 걸려 있는데, 화면에는 "크론으로 실행 중이어야 합니다"라는 안내문만 있었다. -- 감시자의 생존은 감시자가 아닌 쪽(운영자의 브라우저)이 읽어야 하므로, 크론이 자기 -- 실행 시각을 남기고 대시보드가 그 나이를 본다. ALTER TABLE move_events ADD COLUMN hold_until BIGINT UNSIGNED NULL AFTER false_positive_at; -- 보존 정리는 "이 스냅샷의 이벤트가 보류 중인가"를 건마다 묻는다. 보류는 드물기 때문에 -- 전체 스캔이 아니라 보류된 것만 찾는 인덱스가 맞다. CREATE INDEX ix_events_hold ON move_events (hold_until); CREATE TABLE move_app_state ( k VARCHAR(64) NOT NULL, v VARCHAR(255) NOT NULL, updated_at BIGINT UNSIGNED NOT NULL, PRIMARY KEY (k) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 검증 쿼리 — 아래 둘이 각각 1행, 0행을 내면 성공입니다. -- SHOW COLUMNS FROM move_events LIKE 'hold_until'; -- SELECT * FROM move_app_state;