diff --git a/src/__tests__/supabaseNameDrift.test.ts b/src/__tests__/supabaseNameDrift.test.ts new file mode 100644 index 00000000..64cf88ec --- /dev/null +++ b/src/__tests__/supabaseNameDrift.test.ts @@ -0,0 +1,70 @@ +/** + * supabaseNameDrift.test.ts — PR-SQL-3A: Supabase isim drift hizalaması kilidi. + * + * Eski tablo adları canlı/kanonik adlarla eşitlendi: + * system_configs → runtime_policies (superAdminService) + * linking_codes → vehicle_linking_codes (website vehicle/code API) + * (push_subscriptions → vehicle_push_tokens KAPSAM DIŞI: kolon paritesi yok — Web Push ≠ FCM.) + * + * Bu test: (1) davranışsal — superAdminService .from() hedeflerini açıkça kilitler; + * (2) kaynak-kilit — eski adların ilgili aktif kod yollarında kalmadığını doğrular (?raw). + */ +import { describe, it, expect, vi, beforeEach } from 'vitest'; + +// Aktif kod yolu kaynakları (transform-time sabit — paralel flake'e bağışık). +import superAdminSrc from '../platform/superadmin/superAdminService.ts?raw'; +import vehicleCodeRouteSrc from '../../website/src/app/api/vehicle/code/route.ts?raw'; + +/* ── Supabase admin client mock — .from() hedeflerini yakalar ─────────────── */ +const fromCalls: string[] = []; +vi.mock('../platform/roleSystem/RoleStore', () => ({ + getAdminClient: () => { + const q: Record = {}; + Object.assign(q, { + select: () => q, + order: () => Promise.resolve({ data: [{ id: 'p1', key: 'max_speed', name: 'Max Hız', value: 120, unit: 'km/h', updated_at: '2026-01-01T00:00:00Z' }], error: null }), + update: () => q, + insert: () => Promise.resolve({ data: null, error: null }), + eq: () => Promise.resolve({ error: null }), + }); + return { + auth: { getUser: async () => ({ data: { user: { id: 'u1', email: 'admin@x.co' } } }) }, + from: (t: string) => { fromCalls.push(t); return q; }, + }; + }, +})); + +import { getSystemPolicies, updatePolicy } from '../platform/superadmin/superAdminService'; + +beforeEach(() => { fromCalls.length = 0; }); + +/* ── Davranışsal: .from() hedefi kilidi ──────────────────────────────────── */ +describe('superAdminService — runtime_policies hizalaması', () => { + it('getSystemPolicies runtime_policies üzerinden OKUR (system_configs DEĞİL)', async () => { + const res = await getSystemPolicies(); + expect(fromCalls).toContain('runtime_policies'); + expect(fromCalls).not.toContain('system_configs'); + expect(res[0]?.key).toBe('max_speed'); + }); + + it('updatePolicy runtime_policies üzerinden YAZAR (system_configs DEĞİL) + audit', async () => { + await updatePolicy('max_speed', 130); + expect(fromCalls).toContain('runtime_policies'); + expect(fromCalls).not.toContain('system_configs'); + expect(fromCalls).toContain('audit_logs'); // logAdminAction akışı korundu + }); +}); + +/* ── Kaynak-kilit: eski adlar aktif kod yollarında kalmadı ───────────────── */ +describe('isim drift — eski adlar aktif kod yolunda YOK', () => { + it('superAdminService: from(\'system_configs\') kalmadı; runtime_policies var', () => { + expect(superAdminSrc).not.toMatch(/from\(\s*['"]system_configs['"]/); + expect(superAdminSrc).toMatch(/from\(\s*['"]runtime_policies['"]/); + }); + + it('website vehicle/code API: from(\'linking_codes\') kalmadı; vehicle_linking_codes var', () => { + // 'vehicle_linking_codes' eşleşmesin diye tırnak-hemen-sonrası guard. + expect(vehicleCodeRouteSrc).not.toMatch(/from\(\s*['"]linking_codes['"]/); + expect(vehicleCodeRouteSrc).toMatch(/from\(\s*['"]vehicle_linking_codes['"]/); + }); +}); diff --git a/src/components/admin/SuperAdminShell.tsx b/src/components/admin/SuperAdminShell.tsx index 26aa7ba4..d2f0f9b7 100644 --- a/src/components/admin/SuperAdminShell.tsx +++ b/src/components/admin/SuperAdminShell.tsx @@ -514,7 +514,7 @@ export function SuperAdminShell() { ) : policiesList.length === 0 ? (

- POLİTİKA_YOK: system_configs tablosu boş + POLİTİKA_YOK: runtime_policies tablosu boş

) : ( policiesList.map((policy) => ( diff --git a/src/platform/superadmin/superAdminService.ts b/src/platform/superadmin/superAdminService.ts index e3f7daa9..0a321707 100644 --- a/src/platform/superadmin/superAdminService.ts +++ b/src/platform/superadmin/superAdminService.ts @@ -587,7 +587,9 @@ export async function updateRolloutStatus( } /** - * system_configs tablosundaki aktif politikaları döner. + * runtime_policies tablosundaki aktif politikaları döner. + * (İsim hizalama: eski `system_configs` adı canlı/kanonik `runtime_policies` ile eşitlendi; + * kolon paritesi doğrulandı — id/key/name/value/unit/updated_at mevcut.) */ export async function getSystemPolicies(): Promise { const client = getAdminClient(); @@ -595,7 +597,7 @@ export async function getSystemPolicies(): Promise { try { const { data, error } = await client - .from('system_configs') + .from('runtime_policies') .select('id, key, name, value, unit, updated_at') .order('key', { ascending: true }); @@ -638,7 +640,7 @@ export async function updatePolicy( }); // eslint-disable-next-line @typescript-eslint/no-explicit-any - const { error } = await (client.from('system_configs') as any) + const { error } = await (client.from('runtime_policies') as any) .update({ value: String(value), updated_at: new Date().toISOString() }) .eq('key', key); diff --git a/website/src/app/api/vehicle/code/route.ts b/website/src/app/api/vehicle/code/route.ts index 903df570..720656ed 100644 --- a/website/src/app/api/vehicle/code/route.ts +++ b/website/src/app/api/vehicle/code/route.ts @@ -49,7 +49,7 @@ export async function POST(req: NextRequest) { const expiresAt = new Date(Date.now() + 60_000).toISOString(); const { error } = await supabaseAdmin - .from('linking_codes') + .from('vehicle_linking_codes') .insert({ vehicle_id: vehicle.id, code, expires_at: expiresAt }); if (error) {