İçeriğe geç

Mail / SMS Call-Site Rehberi

Detay

Yeni veya değiştirilen sendMail(...) / sendSms(...) çağrılarında uyulması gereken kurallar. Code review (feature-dev:code-reviewer subagent veya /ultrareview) sırasında bu listeden geçilmeli.

// YANLIŞ — context yok, service auto-resolve fallback'ine güvenir
await sendMail({
to: customer.email,
template: 'admin-custom-message',
data: { ... },
});
// DOĞRU — explicit pass
await sendMail({
to: customer.email,
template: 'admin-custom-message',
data: { ... },
context: { customerId: customer.id, adminId: admin.adminId },
});

Neden: Service tarafında Customer.findUnique({ where: { email } }) ek query gerek kalmaz; çoklu Customer aynı email kullanırsa (gelecek senaryo) doğru bağlanır. Auto-resolve fallback defensive last-resort olarak servis tarafında kalır — yeni kod yolunda güvenilmemeli.

  • customerId — customer-facing iletişimde ZORUNLU
  • adminId — admin tetikli iletişimde (mailler customer panel’inde forensic için adminId’yi gösterir)
  • ipAddress — webhook / public endpoint’lerde tetiklenen mail için (request.headers.get('x-forwarded-for') veya helper)

3. Multi-recipient (to: string[]) durumunda auto-resolve atlanır

Bölüm başlığı “3. Multi-recipient (to: string[]) durumunda auto-resolve atlanır”

Çoklu alıcılı mail’lerde service customerId resolve etmez. Broadcast scenario’da bu doğru davranış. Müşteriye özgü mail tek alıcı kullanmalı.

Customer.phone E.164 normalize edilmemişse (örn. "+44 0857213415" boşluklu) auto-resolve miss olur. Yeni SMS call-site’larda explicit context.customerId zorunlu, recipient eşleştirmesine güvenme.

Yeni unit test’lerde Customer.create yaparken password: 'placeholder' yazma. Şu helper’ı kullan:

import { hashPassword } from '@/lib/auth/password';
const c = await prisma.customer.create({
data: { email: '...', password: await hashPassword('test-not-used'), name: '...' },
});

lib/auth/password.ts > isValidBcryptHash() ileride şema validation eklendiğinde placeholder testleri kıracak.

  • Mail gönderim sonrası customerAuditLog.create({ ... emailLogId, action, target }) — forensic UI navigasyonu için
  • mailResult.success === false halinde retry/fallback davranışı çağıran kararına bağlı, ama audit kaydı her durumda yazılır (status: ‘success’ veya ‘failed’)

2026-05-13 itibariyle:

  • /api/admin/customers/[id]/send-mail
  • /api/admin/customers/[id]/password-reset
  • /api/admin/customers/[id]/notifications
  • ⏳ Diğer ~22 call-site auto-resolve fallback’ine güveniyor — yeni iş yaparken geçişi de fırsat bul.
  • lib/admin/portal-details.ts > fetchPortalBundle() — credential reveal flow’larında audit log otomatik
  • lib/auth/password.ts > hashPassword() / verifyPassword() / isValidBcryptHash() — yeni Customer create / parola değişimi
  • lib/audit-actions.ts > CREDENTIAL_REVEAL_CONTEXTS — UI bağlamı string sabit (raw string YASAK)