전 저장소 리팩터링과 SSOT 정비
This commit is contained in:
parent
14ecbd4e7d
commit
3dfddcac6f
173 changed files with 19679 additions and 6952 deletions
|
|
@ -174,6 +174,7 @@ CREATE TABLE IF NOT EXISTS app.sessions (
|
|||
session_no INT, -- 케이스 내 N번째 회기
|
||||
theory_mode TEXT, -- 'humanistic'|'cbt'|'integrative'
|
||||
stage_path JSONB NOT NULL DEFAULT '[]', -- 단계 전이 이력
|
||||
session_goals JSONB NOT NULL DEFAULT '[]', -- 이번 회기 목표 단계(학습자 선택, 최대 4)
|
||||
started_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
ended_at TIMESTAMPTZ,
|
||||
FOREIGN KEY (persona_id, persona_version)
|
||||
|
|
@ -189,6 +190,9 @@ CREATE TABLE IF NOT EXISTS app.session_review_status (
|
|||
status TEXT NOT NULL DEFAULT 'pending'
|
||||
CHECK (status IN ('pending','viewed','closed')),
|
||||
note TEXT NOT NULL DEFAULT '',
|
||||
worksheet_status TEXT NOT NULL DEFAULT 'pending',
|
||||
worksheet_note TEXT NOT NULL DEFAULT '',
|
||||
worksheet_reviewed_at TIMESTAMPTZ,
|
||||
reviewed_at TIMESTAMPTZ,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
|
|
|||
|
|
@ -321,6 +321,29 @@ CREATE POLICY p_alternative_utterance_delete ON app.alternative_utterance FOR DE
|
|||
OR app.current_role_name() IN ('admin','instructor')
|
||||
);
|
||||
|
||||
-- ── safety_events: AI/교수자/관리자와 본인 회기의 학습자만 접근 ──
|
||||
ALTER TABLE app.safety_events ENABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS p_safety_events_select ON app.safety_events;
|
||||
DROP POLICY IF EXISTS p_safety_events_insert ON app.safety_events;
|
||||
CREATE POLICY p_safety_events_select ON app.safety_events FOR SELECT USING (
|
||||
app.is_ai_context()
|
||||
OR app.current_role_name() IN ('admin','instructor')
|
||||
OR EXISTS (
|
||||
SELECT 1 FROM app.sessions s
|
||||
WHERE s.id = app.safety_events.session_id
|
||||
AND s.learner_id = app.current_uid()
|
||||
)
|
||||
);
|
||||
CREATE POLICY p_safety_events_insert ON app.safety_events FOR INSERT WITH CHECK (
|
||||
app.is_ai_context()
|
||||
OR app.current_role_name() IN ('admin','instructor')
|
||||
OR EXISTS (
|
||||
SELECT 1 FROM app.sessions s
|
||||
WHERE s.id = app.safety_events.session_id
|
||||
AND s.learner_id = app.current_uid()
|
||||
)
|
||||
);
|
||||
|
||||
-- ── case_profile / pinned_fact: 학습자=본인 케이스만(cross-trainee 누수 차단 T4) ──
|
||||
ALTER TABLE app.case_profile ENABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS p_case_select ON app.case_profile;
|
||||
|
|
|
|||
|
|
@ -161,6 +161,13 @@ CREATE INDEX IF NOT EXISTS idx_support_ticket_parent
|
|||
ON app.support_ticket(parent_ticket_id)
|
||||
WHERE parent_ticket_id IS NOT NULL;
|
||||
|
||||
ALTER TABLE app.session_review_status
|
||||
ADD COLUMN IF NOT EXISTS worksheet_status TEXT NOT NULL DEFAULT 'pending';
|
||||
ALTER TABLE app.session_review_status
|
||||
ADD COLUMN IF NOT EXISTS worksheet_note TEXT NOT NULL DEFAULT '';
|
||||
ALTER TABLE app.session_review_status
|
||||
ADD COLUMN IF NOT EXISTS worksheet_reviewed_at TIMESTAMPTZ;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS app.notification_event (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
kind TEXT NOT NULL CHECK (
|
||||
|
|
|
|||
|
|
@ -135,13 +135,46 @@ CREATE TABLE IF NOT EXISTS app.live_coach_events (
|
|||
session_id UUID NOT NULL REFERENCES app.sessions(id) ON DELETE CASCADE,
|
||||
turn_seq INT NOT NULL CHECK (turn_seq >= 1),
|
||||
stage TEXT NOT NULL,
|
||||
event_type TEXT NOT NULL DEFAULT 'use'
|
||||
CHECK (event_type IN ('use', 'recharge')),
|
||||
credit_delta INT NOT NULL DEFAULT -1,
|
||||
credit_balance INT,
|
||||
reason TEXT,
|
||||
learner_text_excerpt TEXT,
|
||||
client_reply_excerpt TEXT,
|
||||
payload JSONB NOT NULL DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
ALTER TABLE app.live_coach_events
|
||||
ADD COLUMN IF NOT EXISTS event_type TEXT NOT NULL DEFAULT 'use';
|
||||
ALTER TABLE app.live_coach_events
|
||||
ADD COLUMN IF NOT EXISTS credit_delta INT NOT NULL DEFAULT -1;
|
||||
ALTER TABLE app.live_coach_events
|
||||
ADD COLUMN IF NOT EXISTS credit_balance INT;
|
||||
ALTER TABLE app.live_coach_events
|
||||
ADD COLUMN IF NOT EXISTS reason TEXT;
|
||||
UPDATE app.live_coach_events
|
||||
SET event_type = 'use'
|
||||
WHERE event_type IS NULL OR event_type NOT IN ('use', 'recharge');
|
||||
UPDATE app.live_coach_events
|
||||
SET credit_delta = CASE WHEN event_type = 'recharge' THEN 1 ELSE -1 END
|
||||
WHERE credit_delta IS NULL;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_constraint
|
||||
WHERE conname = 'live_coach_events_event_type_check'
|
||||
) THEN
|
||||
ALTER TABLE app.live_coach_events
|
||||
ADD CONSTRAINT live_coach_events_event_type_check
|
||||
CHECK (event_type IN ('use', 'recharge'));
|
||||
END IF;
|
||||
END $$;
|
||||
CREATE INDEX IF NOT EXISTS idx_live_coach_events_session_turn
|
||||
ON app.live_coach_events(session_id, turn_seq, created_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_live_coach_events_session_type
|
||||
ON app.live_coach_events(session_id, event_type, created_at);
|
||||
|
||||
ALTER TABLE app.live_coach_events ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue