fix: harden unicode safety checks

This commit is contained in:
Affaan Mustafa
2026-03-29 08:59:06 -04:00
parent dd675d4258
commit 866d9ebb53
239 changed files with 3780 additions and 3962 deletions

View File

@@ -23,7 +23,7 @@ origin: ECC
### RESTful API Yapısı
```typescript
// Kaynak tabanlı URL'ler
// PASS: Kaynak tabanlı URL'ler
GET /api/markets # Kaynakları listele
GET /api/markets/:id # Tek kaynak getir
POST /api/markets # Kaynak oluştur
@@ -31,7 +31,7 @@ PUT /api/markets/:id # Kaynağı değiştir (tam)
PATCH /api/markets/:id # Kaynağı güncelle (kısmi)
DELETE /api/markets/:id # Kaynağı sil
// Filtreleme, sıralama, sayfalama için query parametreleri
// PASS: Filtreleme, sıralama, sayfalama için query parametreleri
GET /api/markets?status=active&sort=volume&limit=20&offset=0
```
@@ -131,7 +131,7 @@ export default withAuth(async (req, res) => {
### Sorgu Optimizasyonu
```typescript
// İYİ: Sadece gerekli sütunları seç
// PASS: İYİ: Sadece gerekli sütunları seç
const { data } = await supabase
.from('markets')
.select('id, name, status, volume')
@@ -139,7 +139,7 @@ const { data } = await supabase
.order('volume', { ascending: false })
.limit(10)
// KÖTÜ: Her şeyi seç
// FAIL: KÖTÜ: Her şeyi seç
const { data } = await supabase
.from('markets')
.select('*')
@@ -148,13 +148,13 @@ const { data } = await supabase
### N+1 Sorgu Önleme
```typescript
// KÖTÜ: N+1 sorgu problemi
// FAIL: KÖTÜ: N+1 sorgu problemi
const markets = await getMarkets()
for (const market of markets) {
market.creator = await getUser(market.creator_id) // N sorgu
}
// İYİ: Toplu getirme
// PASS: İYİ: Toplu getirme
const markets = await getMarkets()
const creatorIds = markets.map(m => m.creator_id)
const creators = await getUsers(creatorIds) // 1 sorgu

View File

@@ -48,12 +48,12 @@ Tüm projelerde uygulanabilir evrensel kodlama standartları.
### Değişken İsimlendirme
```typescript
// İYİ: Açıklayıcı isimler
// PASS: İYİ: Açıklayıcı isimler
const marketSearchQuery = 'election'
const isUserAuthenticated = true
const totalRevenue = 1000
// KÖTÜ: Belirsiz isimler
// FAIL: KÖTÜ: Belirsiz isimler
const q = 'election'
const flag = true
const x = 1000
@@ -62,12 +62,12 @@ const x = 1000
### Fonksiyon İsimlendirme
```typescript
// İYİ: Fiil-isim kalıbı
// PASS: İYİ: Fiil-isim kalıbı
async function fetchMarketData(marketId: string) { }
function calculateSimilarity(a: number[], b: number[]) { }
function isValidEmail(email: string): boolean { }
// KÖTÜ: Belirsiz veya sadece isim
// FAIL: KÖTÜ: Belirsiz veya sadece isim
async function market(id: string) { }
function similarity(a, b) { }
function email(e) { }
@@ -76,7 +76,7 @@ function email(e) { }
### Değişmezlik Kalıbı (KRİTİK)
```typescript
// HER ZAMAN spread operatörü kullanın
// PASS: HER ZAMAN spread operatörü kullanın
const updatedUser = {
...user,
name: 'New Name'
@@ -84,7 +84,7 @@ const updatedUser = {
const updatedArray = [...items, newItem]
// ASLA doğrudan mutasyon yapmayın
// FAIL: ASLA doğrudan mutasyon yapmayın
user.name = 'New Name' // KÖTÜ
items.push(newItem) // KÖTÜ
```
@@ -92,7 +92,7 @@ items.push(newItem) // KÖTÜ
### Hata Yönetimi
```typescript
// İYİ: Kapsamlı hata yönetimi
// PASS: İYİ: Kapsamlı hata yönetimi
async function fetchData(url: string) {
try {
const response = await fetch(url)
@@ -108,7 +108,7 @@ async function fetchData(url: string) {
}
}
// KÖTÜ: Hata yönetimi yok
// FAIL: KÖTÜ: Hata yönetimi yok
async function fetchData(url) {
const response = await fetch(url)
return response.json()
@@ -118,14 +118,14 @@ async function fetchData(url) {
### Async/Await En İyi Uygulamaları
```typescript
// İYİ: Mümkün olduğunda paralel yürütme
// PASS: İYİ: Mümkün olduğunda paralel yürütme
const [users, markets, stats] = await Promise.all([
fetchUsers(),
fetchMarkets(),
fetchStats()
])
// KÖTÜ: Gereksiz yere sıralı
// FAIL: KÖTÜ: Gereksiz yere sıralı
const users = await fetchUsers()
const markets = await fetchMarkets()
const stats = await fetchStats()
@@ -134,7 +134,7 @@ const stats = await fetchStats()
### Tür Güvenliği
```typescript
// İYİ: Doğru tipler
// PASS: İYİ: Doğru tipler
interface Market {
id: string
name: string
@@ -146,7 +146,7 @@ function getMarket(id: string): Promise<Market> {
// Implementation
}
// KÖTÜ: 'any' kullanımı
// FAIL: KÖTÜ: 'any' kullanımı
function getMarket(id: any): Promise<any> {
// Implementation
}
@@ -157,7 +157,7 @@ function getMarket(id: any): Promise<any> {
### Bileşen Yapısı
```typescript
// İYİ: Tiplerle fonksiyonel bileşen
// PASS: İYİ: Tiplerle fonksiyonel bileşen
interface ButtonProps {
children: React.ReactNode
onClick: () => void
@@ -182,7 +182,7 @@ export function Button({
)
}
// KÖTÜ: Tip yok, belirsiz yapı
// FAIL: KÖTÜ: Tip yok, belirsiz yapı
export function Button(props) {
return <button onClick={props.onClick}>{props.children}</button>
}
@@ -191,7 +191,7 @@ export function Button(props) {
### Özel Hook'lar
```typescript
// İYİ: Yeniden kullanılabilir özel hook
// PASS: İYİ: Yeniden kullanılabilir özel hook
export function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value)
@@ -213,25 +213,25 @@ const debouncedQuery = useDebounce(searchQuery, 500)
### State Yönetimi
```typescript
// İYİ: Doğru state güncellemeleri
// PASS: İYİ: Doğru state güncellemeleri
const [count, setCount] = useState(0)
// Önceki state'e dayalı fonksiyonel güncelleme
setCount(prev => prev + 1)
// KÖTÜ: Doğrudan state referansı
// FAIL: KÖTÜ: Doğrudan state referansı
setCount(count + 1) // Async senaryolarda eski olabilir
```
### Koşullu Render
```typescript
// İYİ: Açık koşullu render
// PASS: İYİ: Açık koşullu render
{isLoading && <Spinner />}
{error && <ErrorMessage error={error} />}
{data && <DataDisplay data={data} />}
// KÖTÜ: Ternary cehennemi
// FAIL: KÖTÜ: Ternary cehennemi
{isLoading ? <Spinner /> : error ? <ErrorMessage error={error} /> : data ? <DataDisplay data={data} /> : null}
```
@@ -254,7 +254,7 @@ GET /api/markets?status=active&limit=10&offset=0
### Response Formatı
```typescript
// İYİ: Tutarlı response yapısı
// PASS: İYİ: Tutarlı response yapısı
interface ApiResponse<T> {
success: boolean
data?: T
@@ -285,7 +285,7 @@ return NextResponse.json({
```typescript
import { z } from 'zod'
// İYİ: Schema doğrulama
// PASS: İYİ: Schema doğrulama
const CreateMarketSchema = z.object({
name: z.string().min(1).max(200),
description: z.string().min(1).max(2000),
@@ -348,14 +348,14 @@ types/market.types.ts # .types soneki ile camelCase
### Ne Zaman Yorum Yapmalı
```typescript
// İYİ: NİÇİN'i açıklayın, NE'yi değil
// PASS: İYİ: NİÇİN'i açıklayın, NE'yi değil
// Kesintiler sırasında API'yi aşırı yüklemekten kaçınmak için exponential backoff kullan
const delay = Math.min(1000 * Math.pow(2, retryCount), 30000)
// Büyük dizilerle performans için burada kasıtlı olarak mutasyon kullanılıyor
items.push(newItem)
// KÖTÜ: Açık olanı belirtmek
// FAIL: KÖTÜ: Açık olanı belirtmek
// Sayacı 1 artır
count++
@@ -395,12 +395,12 @@ export async function searchMarkets(
```typescript
import { useMemo, useCallback } from 'react'
// İYİ: Pahalı hesaplamaları memoize et
// PASS: İYİ: Pahalı hesaplamaları memoize et
const sortedMarkets = useMemo(() => {
return markets.sort((a, b) => b.volume - a.volume)
}, [markets])
// İYİ: Callback'leri memoize et
// PASS: İYİ: Callback'leri memoize et
const handleSearch = useCallback((query: string) => {
setSearchQuery(query)
}, [])
@@ -411,7 +411,7 @@ const handleSearch = useCallback((query: string) => {
```typescript
import { lazy, Suspense } from 'react'
// İYİ: Ağır bileşenleri lazy yükle
// PASS: İYİ: Ağır bileşenleri lazy yükle
const HeavyChart = lazy(() => import('./HeavyChart'))
export function Dashboard() {
@@ -426,13 +426,13 @@ export function Dashboard() {
### Veritabanı Sorguları
```typescript
// İYİ: Sadece gerekli sütunları seç
// PASS: İYİ: Sadece gerekli sütunları seç
const { data } = await supabase
.from('markets')
.select('id, name, status')
.limit(10)
// KÖTÜ: Her şeyi seç
// FAIL: KÖTÜ: Her şeyi seç
const { data } = await supabase
.from('markets')
.select('*')
@@ -459,12 +459,12 @@ test('benzerliği doğru hesaplar', () => {
### Test İsimlendirme
```typescript
// İYİ: Açıklayıcı test isimleri
// PASS: İYİ: Açıklayıcı test isimleri
test('sorguya uygun market bulunamadığında boş dizi döndürür', () => { })
test('OpenAI API anahtarı eksikse hata fırlatır', () => { })
test('Redis kullanılamazsa substring aramaya geri döner', () => { })
// KÖTÜ: Belirsiz test isimleri
// FAIL: KÖTÜ: Belirsiz test isimleri
test('çalışır', () => { })
test('arama testi', () => { })
```
@@ -475,12 +475,12 @@ Bu anti-kalıplara dikkat edin:
### 1. Uzun Fonksiyonlar
```typescript
// KÖTÜ: 50 satırdan uzun fonksiyon
// FAIL: KÖTÜ: 50 satırdan uzun fonksiyon
function processMarketData() {
// 100 satır kod
}
// İYİ: Küçük fonksiyonlara böl
// PASS: İYİ: Küçük fonksiyonlara böl
function processMarketData() {
const validated = validateData()
const transformed = transformData(validated)
@@ -490,7 +490,7 @@ function processMarketData() {
### 2. Derin İç İçe Geçme
```typescript
// KÖTÜ: 5+ seviye iç içe geçme
// FAIL: KÖTÜ: 5+ seviye iç içe geçme
if (user) {
if (user.isAdmin) {
if (market) {
@@ -503,7 +503,7 @@ if (user) {
}
}
// İYİ: Erken dönüşler
// PASS: İYİ: Erken dönüşler
if (!user) return
if (!user.isAdmin) return
if (!market) return
@@ -515,11 +515,11 @@ if (!hasPermission) return
### 3. Sihirli Sayılar
```typescript
// KÖTÜ: Açıklanmamış sayılar
// FAIL: KÖTÜ: Açıklanmamış sayılar
if (retryCount > 3) { }
setTimeout(callback, 500)
// İYİ: İsimlendirilmiş sabitler
// PASS: İYİ: İsimlendirilmiş sabitler
const MAX_RETRIES = 3
const DEBOUNCE_DELAY_MS = 500

View File

@@ -23,7 +23,7 @@ React, Next.js ve performanslı kullanıcı arayüzleri için modern frontend ka
### Kalıtım Yerine Composition
```typescript
// İYİ: Bileşen composition
// PASS: İYİ: Bileşen composition
interface CardProps {
children: React.ReactNode
variant?: 'default' | 'outlined'
@@ -294,17 +294,17 @@ export function useMarkets() {
### Memoization
```typescript
// Pahalı hesaplamalar için useMemo
// PASS: Pahalı hesaplamalar için useMemo
const sortedMarkets = useMemo(() => {
return markets.sort((a, b) => b.volume - a.volume)
}, [markets])
// Alt bileşenlere geçirilen fonksiyonlar için useCallback
// PASS: Alt bileşenlere geçirilen fonksiyonlar için useCallback
const handleSearch = useCallback((query: string) => {
setSearchQuery(query)
}, [])
// Pure bileşenler için React.memo
// PASS: Pure bileşenler için React.memo
export const MarketCard = React.memo<MarketCardProps>(({ market }) => {
return (
<div className="market-card">
@@ -320,7 +320,7 @@ export const MarketCard = React.memo<MarketCardProps>(({ market }) => {
```typescript
import { lazy, Suspense } from 'react'
// ır bileşenleri lazy yükle
// PASS:ır bileşenleri lazy yükle
const HeavyChart = lazy(() => import('./HeavyChart'))
const ThreeJsBackground = lazy(() => import('./ThreeJsBackground'))
@@ -515,7 +515,7 @@ export class ErrorBoundary extends React.Component<
```typescript
import { motion, AnimatePresence } from 'framer-motion'
// Liste animasyonları
// PASS: Liste animasyonları
export function AnimatedMarketList({ markets }: { markets: Market[] }) {
return (
<AnimatePresence>
@@ -534,7 +534,7 @@ export function AnimatedMarketList({ markets }: { markets: Market[] }) {
)
}
// Modal animasyonları
// PASS: Modal animasyonları
export function Modal({ isOpen, onClose, children }: ModalProps) {
return (
<AnimatePresence>

View File

@@ -22,13 +22,13 @@ Bu skill tüm kodun güvenlik en iyi uygulamalarını takip etmesini sağlar ve
### 1. Secret Yönetimi
#### ASLA Bunu Yapmayın
#### FAIL: ASLA Bunu Yapmayın
```typescript
const apiKey = "sk-proj-xxxxx" // Hardcoded secret
const dbPassword = "password123" // Kaynak kodda
```
#### HER ZAMAN Bunu Yapın
#### PASS: HER ZAMAN Bunu Yapın
```typescript
const apiKey = process.env.OPENAI_API_KEY
const dbUrl = process.env.DATABASE_URL
@@ -108,14 +108,14 @@ function validateFileUpload(file: File) {
### 3. SQL Injection Önleme
#### ASLA SQL Concatenation Yapmayın
#### FAIL: ASLA SQL Concatenation Yapmayın
```typescript
// TEHLİKELİ - SQL Injection açığı
const query = `SELECT * FROM users WHERE email = '${userEmail}'`
await db.query(query)
```
#### HER ZAMAN Parametreli Sorgular Kullanın
#### PASS: HER ZAMAN Parametreli Sorgular Kullanın
```typescript
// Güvenli - parametreli sorgu
const { data } = await supabase
@@ -140,10 +140,10 @@ await db.query(
#### JWT Token İşleme
```typescript
// YANLIŞ: localStorage (XSS'e karşı savunmasız)
// FAIL: YANLIŞ: localStorage (XSS'e karşı savunmasız)
localStorage.setItem('token', token)
// DOĞRU: httpOnly cookies
// PASS: DOĞRU: httpOnly cookies
res.setHeader('Set-Cookie',
`token=${token}; HttpOnly; Secure; SameSite=Strict; Max-Age=3600`)
```
@@ -300,18 +300,18 @@ app.use('/api/search', searchLimiter)
#### Loglama
```typescript
// YANLIŞ: Hassas veri loglama
// FAIL: YANLIŞ: Hassas veri loglama
console.log('User login:', { email, password })
console.log('Payment:', { cardNumber, cvv })
// DOĞRU: Hassas veriyi gizle
// PASS: DOĞRU: Hassas veriyi gizle
console.log('User login:', { email, userId })
console.log('Payment:', { last4: card.last4, userId })
```
#### Hata Mesajları
```typescript
// YANLIŞ: İç detaylarıığa çıkarma
// FAIL: YANLIŞ: İç detaylarıığa çıkarma
catch (error) {
return NextResponse.json(
{ error: error.message, stack: error.stack },
@@ -319,7 +319,7 @@ catch (error) {
)
}
// DOĞRU: Genel hata mesajları
// PASS: DOĞRU: Genel hata mesajları
catch (error) {
console.error('Internal error:', error)
return NextResponse.json(

View File

@@ -314,39 +314,39 @@ npm run test:coverage
## Kaçınılması Gereken Yaygın Test Hataları
### YANLIŞ: Implementasyon Detaylarını Test Etme
### FAIL: YANLIŞ: Implementasyon Detaylarını Test Etme
```typescript
// İç state'i test etme
expect(component.state.count).toBe(5)
```
### DOĞRU: Kullanıcı Tarafından Görünen Davranışı Test Et
### PASS: DOĞRU: Kullanıcı Tarafından Görünen Davranışı Test Et
```typescript
// Kullanıcıların gördüğünü test et
expect(screen.getByText('Sayı: 5')).toBeInTheDocument()
```
### YANLIŞ: Kırılgan Selector'lar
### FAIL: YANLIŞ: Kırılgan Selector'lar
```typescript
// Kolayca bozulur
await page.click('.css-class-xyz')
```
### DOĞRU: Semantik Selector'lar
### PASS: DOĞRU: Semantik Selector'lar
```typescript
// Değişikliklere karşı dayanıklı
await page.click('button:has-text("Gönder")')
await page.click('[data-testid="submit-button"]')
```
### YANLIŞ: Test İzolasyonu Yok
### FAIL: YANLIŞ: Test İzolasyonu Yok
```typescript
// Testler birbirine bağımlı
test('kullanıcı oluşturur', () => { /* ... */ })
test('aynı kullanıcıyı günceller', () => { /* önceki teste bağımlı */ })
```
### DOĞRU: Bağımsız Testler
### PASS: DOĞRU: Bağımsız Testler
```typescript
// Her test kendi verisini hazırlar
test('kullanıcı oluşturur', () => {