Files
gongxue-base/supabase/migrations/202606300002_platform_audit_alerts.sql
2026-06-30 06:12:33 +08:00

152 lines
5.9 KiB
SQL

create table if not exists public.platform_audit_alert_rules (
id uuid primary key default gen_random_uuid(),
code text not null unique,
name text not null,
description text,
enabled boolean not null default true,
severity text not null default 'medium' check (severity in ('low', 'medium', 'high', 'critical')),
action_patterns text[] not null default '{}'::text[],
target_types text[] not null default '{}'::text[],
tenant_id uuid references public.tenants(id) on delete cascade,
conditions jsonb not null default '{}'::jsonb,
metadata jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now()
);
create table if not exists public.platform_audit_alerts (
id uuid primary key default gen_random_uuid(),
rule_id uuid not null references public.platform_audit_alert_rules(id) on delete cascade,
audit_log_id uuid not null references public.audit_logs(id) on delete cascade,
tenant_id uuid references public.tenants(id) on delete cascade,
severity text not null check (severity in ('low', 'medium', 'high', 'critical')),
status text not null default 'open' check (status in ('open', 'acknowledged', 'resolved', 'ignored')),
action text not null,
target_type text,
target_id text,
title text not null,
summary text,
details jsonb not null default '{}'::jsonb,
first_seen_at timestamptz not null default now(),
last_seen_at timestamptz not null default now(),
acknowledged_by uuid references public.platform_users(id) on delete set null,
acknowledged_at timestamptz,
resolved_by uuid references public.platform_users(id) on delete set null,
resolved_at timestamptz,
resolution_note text,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now(),
unique (rule_id, audit_log_id)
);
create index if not exists idx_platform_audit_alert_rules_enabled
on public.platform_audit_alert_rules(enabled, severity, code);
create index if not exists idx_platform_audit_alerts_status_severity
on public.platform_audit_alerts(status, severity, created_at desc);
create index if not exists idx_platform_audit_alerts_tenant
on public.platform_audit_alerts(tenant_id, status, created_at desc);
create index if not exists idx_platform_audit_alerts_audit_log
on public.platform_audit_alerts(audit_log_id);
alter table public.platform_audit_alert_rules enable row level security;
alter table public.platform_audit_alerts enable row level security;
drop policy if exists platform_admin_audit_alert_rules on public.platform_audit_alert_rules;
create policy platform_admin_audit_alert_rules on public.platform_audit_alert_rules
for all
using (app.is_platform_admin())
with check (app.is_platform_admin());
drop policy if exists platform_admin_audit_alerts on public.platform_audit_alerts;
create policy platform_admin_audit_alerts on public.platform_audit_alerts
for all
using (app.is_platform_admin())
with check (app.is_platform_admin());
drop trigger if exists set_updated_at on public.platform_audit_alert_rules;
create trigger set_updated_at
before update on public.platform_audit_alert_rules
for each row execute function app.touch_updated_at();
drop trigger if exists set_updated_at on public.platform_audit_alerts;
create trigger set_updated_at
before update on public.platform_audit_alerts
for each row execute function app.touch_updated_at();
insert into public.platform_audit_alert_rules (
code, name, description, severity, action_patterns, target_types, conditions, metadata
)
values
(
'platform_tenant_status_changed',
'租户状态变更',
'平台租户启停、账务状态变化等高影响操作。',
'high',
array['platform.tenant.status_updated'],
array['tenant'],
'{"riskArea":"tenant_lifecycle"}'::jsonb,
'{"defaultRule":true}'::jsonb
),
(
'platform_billing_profile_changed',
'租户账务资料变更',
'开票抬头、税号、联系人或银行掩码资料发生变化。',
'medium',
array['platform.tenant.billing_profile_upserted'],
array['tenant_billing_profile'],
'{"riskArea":"billing_profile"}'::jsonb,
'{"defaultRule":true}'::jsonb
),
(
'platform_invoice_batch_created',
'平台服务费批量开票',
'平台批量为租户订阅生成服务费账单。',
'medium',
array['platform.invoice.subscription_batch_created', 'platform.invoice.subscription_auto_created'],
array['tenant_invoice_batch', 'tenant_invoice'],
'{"riskArea":"platform_billing"}'::jsonb,
'{"defaultRule":true}'::jsonb
),
(
'platform_invoice_overdue_processed',
'平台服务费逾期处理',
'平台标记逾期账单或生成内部催缴记录。',
'medium',
array['platform.invoice.overdue_processed', 'platform.invoice.overdue_batch_processed'],
array['tenant_invoice', 'tenant_invoice_batch'],
'{"riskArea":"platform_dunning"}'::jsonb,
'{"defaultRule":true}'::jsonb
),
(
'platform_invoice_payment_confirmed',
'平台服务费收款确认',
'平台管理员手工确认租户服务费收款。',
'high',
array['platform.invoice.payment_confirmed'],
array['tenant_invoice'],
'{"riskArea":"platform_billing_payment"}'::jsonb,
'{"defaultRule":true}'::jsonb
),
(
'platform_audit_exported',
'平台审计日志导出',
'平台管理员导出审计日志,应留痕并进入安全运营台。',
'high',
array['platform.audit.exported'],
array['audit_logs'],
'{"riskArea":"audit_export"}'::jsonb,
'{"defaultRule":true}'::jsonb
)
on conflict (code) do update
set name = excluded.name,
description = excluded.description,
severity = excluded.severity,
action_patterns = excluded.action_patterns,
target_types = excluded.target_types,
conditions = excluded.conditions,
metadata = public.platform_audit_alert_rules.metadata || excluded.metadata,
updated_at = now();