feat(scripts): D1→PostgreSQL 데이터 이전 스크립트 - #78
Merged
Conversation
- schema.sqlite(=D1)와 schema.pg의 대칭성 활용 — timestamp(정수 ms→Date)·boolean(0/1→bool)만 변환, 나머지(text/id/enum/암호문/해시)는 무변환 복사 - 암호문·해시 컬럼은 IDP_SIGNING_KEY_SECRET 동일 유지 시 그대로 이전 가능 - 컬럼 종류를 drizzle 메타에서 자동 도출(스키마 drift 자동 추종), snake_case→camelCase 매핑 - FK 부모→자식 순서(31테이블), departments 자기참조 위상정렬, onConflictDoNothing 멱등 - rowid 커서 페이지네이션(대용량 audit_events 스트리밍) - 옵션: --dry-run(기본, PG 미변경)/--apply/--skip-ephemeral/--only/--tables-exclude/--disable-fk - openScriptDb 재사용(db.ts 무수정), 소스=d1·대상=postgres 이중 가드 - 원격 DB 쓰기는 사용자가 직접 실행(CLAUDE.md 규칙) — 기본 dry-run Co-Authored-By: Claude Fable 5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
D1(Cloudflare, SQLite 기반)에서 PostgreSQL로 운영 데이터를 이전하는 일회성 스크립트입니다. 스키마 마이그레이션(drizzle)이 아니라 행 데이터 이전을 다룹니다. 독립 코드 리뷰를 통과했으며(Critical/High 0), 기본 dry-run이라 실수 실행에도 PG를 변경하지 않습니다.
왜 안전한가
schema.sqlite.ts(=D1)와schema.pg.ts는 테이블·컬럼·JS 키가 100% 대칭이라, 실제 값 변환은 **timestamp(정수 ms→Date)**와 boolean(0/1→bool) 두 종류뿐. 나머지(id·enum·JSON(text)·정수·모든 암호문/해시)는 무변환 복사.signing_keys.private_jwk_encrypted, TOTPcredentials.secret, LDAP bind,audit_events.hash, 각종 토큰/비밀번호 해시)은 base64url/hex 문자열이라IDP_SIGNING_KEY_SECRET만 동일 유지하면 그대로 이전 가능.설계
departments자기참조 위상정렬(사이클 가드)audit_events스트리밍),onConflictDoNothing멱등openScriptDb재사용(scripts/lib/db.ts무수정), 소스=d1·대상=postgres 이중 가드로 소스=대상 구조적 불가옵션
--dry-run(기본, PG 미변경) ·--apply·--skip-ephemeral(휘발성 테이블 생략) ·--only=·--tables-exclude=·--batch-size=·--page-size=·--disable-fk사용법
실행 전 체크리스트
IDP_SIGNING_KEY_SECRET가 D1 운영 때와 동일한가 (다르면 로그인/TOTP/서명 전부 깨짐)drizzle/pg마이그레이션이 적용돼 스키마가 존재하는가DATABASE_URL이 의도한 대상(프리뷰/프로덕션)인가--applySELECT count(*)대조 + 로그인/OIDC/SAML/TOTP 스모크 테스트--skip-ephemeral이 생략하는 데이터(rate_limits·만료 토큰·challenges·grants·saml 임시)는 GC가 어차피 정리하므로 이전 불필요.audit_events는 보존 데이터라 항상 포함.🤖 Generated with Claude Code