From 4a0499890ae78025fc89877b4a6c5d0cb4b72bd4 Mon Sep 17 00:00:00 2001 From: kappa Date: Mon, 19 Jan 2026 16:02:18 +0900 Subject: [PATCH] =?UTF-8?q?fix(schema):=20=EC=9E=85=EA=B8=88=EC=9E=90?= =?UTF-8?q?=EB=AA=85=20=EA=B8=B8=EC=9D=B4=20=EC=A0=9C=ED=95=9C=2050?= =?UTF-8?q?=EC=9E=90=20=E2=86=92=2015=EC=9E=90=EB=A1=9C=20=EC=A1=B0?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 근거: - SMS 입금자명: 한글 7자 제한 (은행 시스템) - 사용자 수동 입력: 15자로 충분한 여유 - 매칭 로직: 앞 7자만 사용 변경사항: - CHECK (length(depositor_name) <= 50) → 15 - 데이터 복원 시 truncate: 50자 → 15자 - SCHEMA_MIGRATION_GUIDE.md 업데이트 - MIGRATION_SUMMARY.md 업데이트 로컬 테스트 결과: - ✅ 15자 이하: 정상 입력 - 숫자 15자: "123456789012345" ✓ - 한글 15자: "홍길동아버지어머니할머님고모고" ✓ - ✅ 16자 이상: 거부됨 - 숫자 16자: "1234567890123456" ✗ (CHECK 제약조건) - 한글 16자: "홍길동아버지어머니할머님고모고모" ✗ (CHECK 제약조건) 실용성: - SMS 7자 보장 + 사용자 입력 여유 - 불필요한 긴 이름 방지 - 매칭 로직과 완벽 호환 Co-Authored-By: Claude Sonnet 4.5 --- MIGRATION_SUMMARY.md | 14 +++++++------- SCHEMA_MIGRATION_GUIDE.md | 12 ++++++------ migrations/001_schema_enhancements.sql | 6 +++--- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/MIGRATION_SUMMARY.md b/MIGRATION_SUMMARY.md index e63a6c1..4fb84eb 100644 --- a/MIGRATION_SUMMARY.md +++ b/MIGRATION_SUMMARY.md @@ -13,7 +13,7 @@ Database migration to add critical data integrity constraints and audit logging | Component | Change | Impact | |-----------|--------|--------| | `user_deposits.balance` | Add CHECK (balance >= 0) | Prevents negative balances | -| `deposit_transactions.depositor_name` | Add CHECK (length <= 50) | Enforces name length limit | +| `deposit_transactions.depositor_name` | Add CHECK (length <= 15) | Enforces name length limit | | `audit_logs` | New table | Tracks all critical operations | ### Risk Assessment @@ -50,7 +50,7 @@ telegram-bot-workers/ - [ ] Read `SCHEMA_MIGRATION_GUIDE.md` completely - [ ] Backup production database - [ ] Check for negative balances in production -- [ ] Check for long depositor names (> 50 chars) in production +- [ ] Check for long depositor names (> 15 chars) in production - [ ] Verify rollback script is accessible - [ ] Schedule deployment window (< 5 min) - [ ] Notify stakeholders (optional) @@ -209,18 +209,18 @@ balance INTEGER NOT NULL DEFAULT 0 CHECK (balance >= 0) CHECK constraint failed: balance >= 0 ``` -### Depositor Name Length <= 50 (deposit_transactions) +### Depositor Name Length <= 15 (deposit_transactions) -**Why**: Bank SMS truncates names at 7 chars, but we allow 50 for edge cases +**Why**: Bank SMS truncates names at 7 chars, but we allow 15 for flexibility **Implementation**: ```sql -depositor_name TEXT CHECK (length(depositor_name) <= 50) +depositor_name TEXT CHECK (length(depositor_name) <= 15) ``` **Effect**: Names longer than 50 chars will be rejected: ``` -CHECK constraint failed: length(depositor_name) <= 50 +CHECK constraint failed: length(depositor_name) <= 15 ``` --- @@ -282,7 +282,7 @@ wrangler d1 execute telegram-conversations \ # Check for long names wrangler d1 execute telegram-conversations \ --command "SELECT id, depositor_name, length(depositor_name) as len - FROM deposit_transactions WHERE length(depositor_name) > 50" + FROM deposit_transactions WHERE length(depositor_name) > 15" ``` 3. **Prepare Backup** diff --git a/SCHEMA_MIGRATION_GUIDE.md b/SCHEMA_MIGRATION_GUIDE.md index b5762cb..2f7eec3 100644 --- a/SCHEMA_MIGRATION_GUIDE.md +++ b/SCHEMA_MIGRATION_GUIDE.md @@ -13,7 +13,7 @@ This migration adds critical data integrity constraints and audit logging capabi | Change | Purpose | Risk Level | |--------|---------|------------| | `user_deposits.balance` CHECK constraint | Prevent negative balances | Medium | -| `deposit_transactions.depositor_name` length limit | Enforce 50 character max | Low | +| `deposit_transactions.depositor_name` length limit | Enforce 15 character max | Low | | `audit_logs` table | Track all important operations | None (new table) | --- @@ -46,20 +46,20 @@ INSERT INTO user_deposits (user_id, balance) VALUES (999999, -1000); ### 2. Depositor Name Length (`deposit_transactions`) -**Goal**: Limit `depositor_name` to 50 characters max +**Goal**: Limit `depositor_name` to 15 characters max **Implementation**: ```sql CREATE TABLE deposit_transactions ( ... - depositor_name TEXT CHECK (length(depositor_name) <= 50), + depositor_name TEXT CHECK (length(depositor_name) <= 15), ... ); ``` **Impact**: - ✅ Prevents excessively long names -- 📏 Truncates existing names >50 chars (logs truncated records) +- 📏 Truncates existing names >15 chars (logs truncated records) - 🔧 Requires table recreation (SQLite limitation) **Verification**: @@ -137,7 +137,7 @@ wrangler d1 execute telegram-conversations \ # Check for long depositor names (will be truncated) wrangler d1 execute telegram-conversations \ - --command "SELECT id, depositor_name, length(depositor_name) as len FROM deposit_transactions WHERE length(depositor_name) > 50" + --command "SELECT id, depositor_name, length(depositor_name) as len FROM deposit_transactions WHERE length(depositor_name) > 15" ``` ### 3. Notify Users (if downtime expected) @@ -496,7 +496,7 @@ wrangler d1 execute telegram-conversations \ After migration, verify: - [ ] All user_deposits records have `balance >= 0` -- [ ] All deposit_transactions have `depositor_name` length <= 50 +- [ ] All deposit_transactions have `depositor_name` length <= 15 - [ ] audit_logs table exists with correct schema - [ ] All indexes recreated successfully - [ ] Record counts match pre-migration diff --git a/migrations/001_schema_enhancements.sql b/migrations/001_schema_enhancements.sql index 491c227..6c47084 100644 --- a/migrations/001_schema_enhancements.sql +++ b/migrations/001_schema_enhancements.sql @@ -59,7 +59,7 @@ CREATE TABLE deposit_transactions ( type TEXT NOT NULL CHECK(type IN ('deposit', 'withdrawal', 'refund')), amount INTEGER NOT NULL, status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending', 'confirmed', 'rejected', 'cancelled')), - depositor_name TEXT CHECK (length(depositor_name) <= 50), + depositor_name TEXT CHECK (length(depositor_name) <= 15), description TEXT, confirmed_at DATETIME, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, @@ -78,7 +78,7 @@ SELECT status, CASE WHEN depositor_name IS NULL THEN NULL - WHEN length(depositor_name) > 50 THEN substr(depositor_name, 1, 50) + WHEN length(depositor_name) > 15 THEN substr(depositor_name, 1, 15) ELSE depositor_name END as depositor_name, description, @@ -89,7 +89,7 @@ FROM deposit_transactions_backup; -- 2.5 Log truncated records (if any) SELECT 'TRUNCATED DEPOSITOR NAME:' as warning, id, depositor_name, length(depositor_name) as original_length FROM deposit_transactions_backup -WHERE depositor_name IS NOT NULL AND length(depositor_name) > 50; +WHERE depositor_name IS NOT NULL AND length(depositor_name) > 15; -- 2.6 Drop backup table DROP TABLE deposit_transactions_backup;