fix: apply optimistic locking to deposit API and add weather types

Security (P1):
- Add optimistic locking to /api/deposit/deduct endpoint
- Prevent race conditions on concurrent balance deductions
- Return 409 Conflict on version mismatch with retry hint

Type Safety (P1):
- Add WttrResponse, WttrCurrentCondition, WttrWeatherDay types
- Remove `as any` from weather-tool.ts
- Add safety checks for malformed API responses

Both P1 issues from security review resolved.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-19 23:49:16 +09:00
parent a2cb4ce686
commit 1708d78526
2 changed files with 89 additions and 25 deletions

View File

@@ -1,6 +1,39 @@
// Weather Tool - wttr.in integration
import type { Env } from '../types';
// wttr.in API 응답 타입 정의
interface WttrCurrentCondition {
temp_C: string;
FeelsLikeC: string;
weatherDesc: Array<{ value: string }>;
humidity: string;
windspeedKmph: string;
winddir16Point: string;
uvIndex: string;
visibility: string;
}
interface WttrWeatherDay {
date: string;
maxtempC: string;
mintempC: string;
hourly: Array<{
time: string;
tempC: string;
weatherDesc: Array<{ value: string }>;
chanceofrain: string;
}>;
}
interface WttrResponse {
current_condition: WttrCurrentCondition[];
weather: WttrWeatherDay[];
nearest_area: Array<{
areaName: Array<{ value: string }>;
country: Array<{ value: string }>;
}>;
}
export const weatherTool = {
type: 'function',
function: {
@@ -26,8 +59,25 @@ export async function executeWeather(args: { city: string }, env?: Env): Promise
const response = await fetch(
`${wttrUrl}/${encodeURIComponent(city)}?format=j1`
);
const data = await response.json() as any;
if (!response.ok) {
throw new Error(`API 응답 실패: ${response.status}`);
}
const data = await response.json() as WttrResponse;
// 안전한 접근 - 데이터 유효성 확인
if (!data.current_condition?.[0]) {
return `날씨 정보를 가져올 수 없습니다: ${city}`;
}
const current = data.current_condition[0];
// weatherDesc 배열 존재 확인
if (!current.weatherDesc?.[0]?.value) {
return `날씨 정보가 불완전합니다: ${city}`;
}
return `🌤 ${city} 날씨
온도: ${current.temp_C}°C (체감 ${current.FeelsLikeC}°C)
상태: ${current.weatherDesc[0].value}