운영 지표와 지원 요청 저장소 추가
This commit is contained in:
parent
50fa4ad432
commit
e7ebb38177
20 changed files with 3038 additions and 39 deletions
|
|
@ -92,6 +92,28 @@ CREATE TABLE IF NOT EXISTS app.admin_health_event (
|
|||
CREATE INDEX IF NOT EXISTS idx_admin_health_event_observed
|
||||
ON app.admin_health_event(observed_at DESC, service_key);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS app.admin_health_daily_rollup (
|
||||
rollup_date DATE NOT NULL,
|
||||
environment TEXT NOT NULL,
|
||||
engine_mode TEXT NOT NULL,
|
||||
service_key TEXT NOT NULL,
|
||||
service_name TEXT NOT NULL,
|
||||
sample_count INTEGER NOT NULL DEFAULT 0 CHECK (sample_count >= 0),
|
||||
ok_samples INTEGER NOT NULL DEFAULT 0 CHECK (ok_samples >= 0),
|
||||
degraded_samples INTEGER NOT NULL DEFAULT 0 CHECK (degraded_samples >= 0),
|
||||
down_samples INTEGER NOT NULL DEFAULT 0 CHECK (down_samples >= 0),
|
||||
first_observed_at TIMESTAMPTZ NOT NULL,
|
||||
last_observed_at TIMESTAMPTZ NOT NULL,
|
||||
latest_status TEXT NOT NULL CHECK (latest_status IN ('ok','degraded','down')),
|
||||
last_down_at TIMESTAMPTZ,
|
||||
max_load REAL NOT NULL DEFAULT 0.0 CHECK (max_load >= 0.0 AND max_load <= 1.0),
|
||||
generated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (rollup_date, environment, engine_mode, service_key)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_admin_health_daily_rollup_latest
|
||||
ON app.admin_health_daily_rollup(last_observed_at DESC, service_key);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS app.support_ticket (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
reporter_id UUID REFERENCES app.app_user(user_id) ON DELETE SET NULL,
|
||||
|
|
@ -115,6 +137,8 @@ CREATE TABLE IF NOT EXISTS app.support_ticket (
|
|||
subject TEXT NOT NULL,
|
||||
body TEXT NOT NULL,
|
||||
source_path TEXT NOT NULL DEFAULT '',
|
||||
fingerprint TEXT NOT NULL DEFAULT '',
|
||||
parent_ticket_id UUID REFERENCES app.support_ticket(id) ON DELETE SET NULL,
|
||||
assigned_group TEXT NOT NULL DEFAULT '',
|
||||
resolution_note TEXT NOT NULL DEFAULT '',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
|
|
@ -129,15 +153,68 @@ CREATE INDEX IF NOT EXISTS idx_support_ticket_status_priority
|
|||
CREATE INDEX IF NOT EXISTS idx_support_ticket_reporter
|
||||
ON app.support_ticket(reporter_id, created_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_support_ticket_fingerprint
|
||||
ON app.support_ticket(fingerprint, created_at DESC)
|
||||
WHERE fingerprint <> '';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_support_ticket_parent
|
||||
ON app.support_ticket(parent_ticket_id)
|
||||
WHERE parent_ticket_id IS NOT NULL;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS app.learner_prepost_measure (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
learner_id UUID NOT NULL REFERENCES app.app_user(user_id) ON DELETE CASCADE,
|
||||
pilot_id TEXT NOT NULL DEFAULT 'phase3-pilot-draft',
|
||||
measure_name TEXT NOT NULL CHECK (
|
||||
measure_name IN ('self_efficacy','skill_proficiency','training_satisfaction')
|
||||
),
|
||||
timepoint TEXT NOT NULL CHECK (timepoint IN ('pre','post')),
|
||||
raw_score NUMERIC(8,3) NOT NULL,
|
||||
min_score NUMERIC(8,3) NOT NULL DEFAULT 1.0,
|
||||
max_score NUMERIC(8,3) NOT NULL DEFAULT 5.0,
|
||||
instrument_version TEXT NOT NULL DEFAULT 'pilot-prepost-scaffold-2026-06-28',
|
||||
item_count INTEGER NOT NULL DEFAULT 1 CHECK (item_count >= 1 AND item_count <= 80),
|
||||
collected_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
CHECK (max_score > min_score),
|
||||
CHECK (raw_score >= min_score AND raw_score <= max_score),
|
||||
UNIQUE (learner_id, pilot_id, measure_name, timepoint, instrument_version)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_learner_prepost_measure_pilot
|
||||
ON app.learner_prepost_measure(pilot_id, measure_name, timepoint);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_learner_prepost_measure_learner
|
||||
ON app.learner_prepost_measure(learner_id, pilot_id);
|
||||
|
||||
ALTER TABLE app.admin_health_event ENABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS p_admin_health_event_select ON app.admin_health_event;
|
||||
DROP POLICY IF EXISTS p_admin_health_event_insert ON app.admin_health_event;
|
||||
DROP POLICY IF EXISTS p_admin_health_event_delete ON app.admin_health_event;
|
||||
CREATE POLICY p_admin_health_event_select
|
||||
ON app.admin_health_event FOR SELECT
|
||||
USING (app.current_role_name() = 'admin');
|
||||
CREATE POLICY p_admin_health_event_insert
|
||||
ON app.admin_health_event FOR INSERT
|
||||
WITH CHECK (app.current_role_name() = 'admin');
|
||||
CREATE POLICY p_admin_health_event_delete
|
||||
ON app.admin_health_event FOR DELETE
|
||||
USING (app.current_role_name() = 'admin');
|
||||
|
||||
ALTER TABLE app.admin_health_daily_rollup ENABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS p_admin_health_daily_rollup_select ON app.admin_health_daily_rollup;
|
||||
DROP POLICY IF EXISTS p_admin_health_daily_rollup_insert ON app.admin_health_daily_rollup;
|
||||
DROP POLICY IF EXISTS p_admin_health_daily_rollup_update ON app.admin_health_daily_rollup;
|
||||
CREATE POLICY p_admin_health_daily_rollup_select
|
||||
ON app.admin_health_daily_rollup FOR SELECT
|
||||
USING (app.current_role_name() = 'admin');
|
||||
CREATE POLICY p_admin_health_daily_rollup_insert
|
||||
ON app.admin_health_daily_rollup FOR INSERT
|
||||
WITH CHECK (app.current_role_name() = 'admin');
|
||||
CREATE POLICY p_admin_health_daily_rollup_update
|
||||
ON app.admin_health_daily_rollup FOR UPDATE
|
||||
USING (app.current_role_name() = 'admin')
|
||||
WITH CHECK (app.current_role_name() = 'admin');
|
||||
|
||||
ALTER TABLE app.support_ticket ENABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS p_support_ticket_select ON app.support_ticket;
|
||||
|
|
@ -164,6 +241,41 @@ CREATE POLICY p_support_ticket_delete
|
|||
ON app.support_ticket FOR DELETE
|
||||
USING (app.current_role_name() = 'admin');
|
||||
|
||||
ALTER TABLE app.learner_prepost_measure ENABLE ROW LEVEL SECURITY;
|
||||
DROP POLICY IF EXISTS p_learner_prepost_measure_select ON app.learner_prepost_measure;
|
||||
DROP POLICY IF EXISTS p_learner_prepost_measure_insert ON app.learner_prepost_measure;
|
||||
DROP POLICY IF EXISTS p_learner_prepost_measure_update ON app.learner_prepost_measure;
|
||||
CREATE POLICY p_learner_prepost_measure_select
|
||||
ON app.learner_prepost_measure FOR SELECT
|
||||
USING (
|
||||
app.current_role_name() = 'admin'
|
||||
OR learner_id = app.current_uid()
|
||||
OR (
|
||||
app.current_role_name() = 'instructor'
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM app.app_user u
|
||||
WHERE u.user_id = app.learner_prepost_measure.learner_id
|
||||
AND u.cohort = current_setting('app.current_cohort', true)
|
||||
)
|
||||
)
|
||||
);
|
||||
CREATE POLICY p_learner_prepost_measure_insert
|
||||
ON app.learner_prepost_measure FOR INSERT
|
||||
WITH CHECK (
|
||||
app.current_role_name() = 'admin'
|
||||
OR learner_id = app.current_uid()
|
||||
);
|
||||
CREATE POLICY p_learner_prepost_measure_update
|
||||
ON app.learner_prepost_measure FOR UPDATE
|
||||
USING (
|
||||
app.current_role_name() = 'admin'
|
||||
OR learner_id = app.current_uid()
|
||||
)
|
||||
WITH CHECK (
|
||||
app.current_role_name() = 'admin'
|
||||
OR learner_id = app.current_uid()
|
||||
);
|
||||
|
||||
ALTER TABLE app.sessions
|
||||
ADD COLUMN IF NOT EXISTS runtime_case_id UUID,
|
||||
ADD COLUMN IF NOT EXISTS persona_code TEXT,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue