talk / backend /sql /028_error_reports.sql
user
Deploy StyleVoiceChat backend
aa9892b
Raw History Blame Contribute Delete
3.3 kB
-- ์‚ฌ์šฉ์ž ์˜ค๋ฅ˜ ์‹ ๊ณ  (์šด์ „๋ชจ๋“œ ๋“ฑ์—์„œ "์˜ค๋ฅ˜ ์‹ ๊ณ ํ•˜๊ธฐ" ๋ฒ„ํŠผ)
--
-- ํ™”๋ฉด ์Šคํฌ๋ฆฐ์ƒท + ๊ตฌ์กฐํ™” ๋กœ๊ทธ (DrivingTimingProvider.turnLogs / SttPlugin ์ด๋ฒคํŠธ ๋“ฑ) +
-- ๋””๋ฐ”์ด์Šค ์ปจํ…์ŠคํŠธ (platform / version / route) ๋ฅผ ๋ฐ›์•„ ๋ณด๊ด€. admin /ad โ†’ "์˜ค๋ฅ˜ ์‹ ๊ณ "
-- ํƒญ์—์„œ ๋ชฉ๋ก/์ƒ์„ธ ํ™•์ธ ๊ฐ€๋Šฅ.
--
-- Storage: ์Šคํฌ๋ฆฐ์ƒท์€ ๊ธฐ์กด `scheduled-audio` bucket ์˜ `error-reports/<user_id>/<report_id>.png`
-- ๊ฒฝ๋กœ ์žฌ์‚ฌ์šฉ (๋ณ„๋„ bucket ์•ˆ ๋งŒ๋“ค๊ณ  ๋‹จ์ˆœํ™”).
CREATE TABLE IF NOT EXISTS public.error_reports (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
-- ์‚ฌ์šฉ์ž ์ž…๋ ฅ
route TEXT NOT NULL, -- '/driving', '/message' ๋“ฑ (์ž๋™ ์บก์ฒ˜)
description TEXT, -- ์„ ํƒ โ€” ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ํ•œ ์ค„ ๋ฉ”๋ชจ
-- ์ž๋™ ์ฒจ๋ถ€
screenshot_path TEXT, -- storage path (signed URL ์œผ๋กœ admin ํ‘œ์‹œ)
screenshot_url TEXT, -- signed URL (1๋…„)
logs JSONB, -- ๊ตฌ์กฐํ™” ๋กœ๊ทธ (turnLogs, events ๋“ฑ)
context JSONB, -- ๋””๋ฐ”์ด์Šค/ํ”Œ๋žซํผ ์ •๋ณด
-- admin ์ฒ˜๋ฆฌ ์ƒํƒœ
handled BOOLEAN NOT NULL DEFAULT FALSE,
handled_at TIMESTAMPTZ,
admin_note TEXT, -- admin ๋ฉ”๋ชจ (ํ•ด๊ฒฐ์ฑ… / ๋ถ„๋ฅ˜)
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_error_reports_created
ON public.error_reports (created_at DESC);
CREATE INDEX IF NOT EXISTS idx_error_reports_unhandled
ON public.error_reports (created_at DESC)
WHERE handled = FALSE;
ALTER TABLE public.error_reports ENABLE ROW LEVEL SECURITY;
-- ์‚ฌ์šฉ์ž: ๋ณธ์ธ ์‹ ๊ณ ๋งŒ INSERT
DROP POLICY IF EXISTS error_reports_insert ON public.error_reports;
CREATE POLICY error_reports_insert ON public.error_reports
FOR INSERT
WITH CHECK (user_id = auth.uid());
-- ์‚ฌ์šฉ์ž: ๋ณธ์ธ ์‹ ๊ณ ๋งŒ SELECT (์ž๊ธฐ ์‹ ๊ณ  ๋ชฉ๋ก ํ™•์ธ์šฉ, ํ–ฅํ›„ ์‚ฌ์šฉ)
DROP POLICY IF EXISTS error_reports_select_own ON public.error_reports;
CREATE POLICY error_reports_select_own ON public.error_reports
FOR SELECT
USING (user_id = auth.uid());
-- admin (service_role ์‚ฌ์šฉ) ์€ RLS bypass โ€” ๋ชจ๋“  ์‹ ๊ณ  ์กฐํšŒ/๊ฐฑ์‹  ๊ฐ€๋Šฅ.
CREATE OR REPLACE FUNCTION public._error_reports_touch_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS error_reports_touch_updated_at ON public.error_reports;
CREATE TRIGGER error_reports_touch_updated_at
BEFORE UPDATE ON public.error_reports
FOR EACH ROW EXECUTE FUNCTION public._error_reports_touch_updated_at();
COMMENT ON TABLE public.error_reports IS
'์‚ฌ์šฉ์ž ์˜ค๋ฅ˜ ์‹ ๊ณ  โ€” ํ™”๋ฉด ์Šคํฌ๋ฆฐ์ƒท + ๋กœ๊ทธ + ๋””๋ฐ”์ด์Šค ์ปจํ…์ŠคํŠธ.';
COMMENT ON COLUMN public.error_reports.logs IS
'๊ตฌ์กฐํ™” ๋กœ๊ทธ. ์šด์ „๋ชจ๋“œ: {"turn_logs": [...], "events": [...]}.';
COMMENT ON COLUMN public.error_reports.context IS
'๋””๋ฐ”์ด์Šค ์ปจํ…์ŠคํŠธ: {"platform": "ios", "version": "26.4", "app_version": "...", "user_agent": "..."}.';