fix: P2 medium priority issues - validation and logging

P2-1: Tool selection fallback optimization
- Return only utility tools when no patterns match
- Reduces token usage by ~80% in fallback cases

P2-2: Minimum deposit amount validation
- Add MIN_DEPOSIT_AMOUNT = 1,000원
- Prevents spam with tiny deposits

P2-3: Standardize logging
- Replace console.log/error with structured logger
- bank-sms-parser.ts and security.ts

P2-4: Nameserver format validation
- Add validateNameservers() function
- Check minimum 2 NS, valid hostname format
- Clear error messages in Korean

P2-5: Optimistic lock error context
- Return specific error for version conflicts
- User-friendly message: "동시 요청으로 처리가 지연됨"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-28 20:40:41 +09:00
parent 97b8f3c7f7
commit 69e4dcc338
5 changed files with 63 additions and 17 deletions

View File

@@ -46,6 +46,26 @@ function convertNamecheapDate(date: string): string {
return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`;
}
// 네임서버 형식 검증
function validateNameservers(nameservers: string[]): string | null {
if (!nameservers || nameservers.length < 2) {
return '❌ 최소 2개의 네임서버가 필요합니다.';
}
const nsPattern = /^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)+$/;
for (const ns of nameservers) {
if (!ns || !ns.trim()) {
return '❌ 빈 네임서버가 있습니다.';
}
if (!nsPattern.test(ns.trim())) {
return `❌ 잘못된 네임서버 형식: ${ns}`;
}
}
return null; // valid
}
// KV 캐싱 인터페이스
interface CachedTLDPrice {
tld: string;
@@ -519,6 +539,11 @@ async function executeDomainAction(
if (!domain) return '🚫 도메인을 지정해주세요.';
if (!nameservers?.length) return '🚫 네임서버를 지정해주세요.';
if (!allowedDomains.includes(domain)) return `🚫 ${domain}은 관리 권한이 없습니다.`;
// 네임서버 형식 검증
const validationError = validateNameservers(nameservers);
if (validationError) return validationError;
const result = await callNamecheapApi('set_nameservers', { domain, nameservers }, allowedDomains, env, telegramUserId, db, userId);
if (isErrorResult(result)) return `🚫 ${result.error}`;
return `${domain} 네임서버 변경 완료\n\n${nameservers.map(ns => `${ns}`).join('\n')}`;