feat(monitor/db): goose migrations 0001-0003 (alerts, panel data, collector state)
This commit is contained in:
parent
618aaf43e8
commit
73c56333e6
|
|
@ -0,0 +1,110 @@
|
|||
-- ©AngelaMos | 2026
|
||||
-- 0001_alerts.sql
|
||||
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE alert_rules (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
name text NOT NULL,
|
||||
topic text NOT NULL,
|
||||
predicate text NOT NULL,
|
||||
cooldown_sec integer NOT NULL DEFAULT 300,
|
||||
enabled boolean NOT NULL DEFAULT true,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX idx_alert_rules_user ON alert_rules(user_id) WHERE enabled = true;
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE alert_channels (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
type text NOT NULL,
|
||||
label text NOT NULL,
|
||||
config_enc bytea NOT NULL,
|
||||
nonce bytea NOT NULL,
|
||||
invalid boolean NOT NULL DEFAULT false,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX idx_alert_channels_user ON alert_channels(user_id);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE alert_rule_channels (
|
||||
rule_id uuid NOT NULL REFERENCES alert_rules(id) ON DELETE CASCADE,
|
||||
channel_id uuid NOT NULL REFERENCES alert_channels(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (rule_id, channel_id)
|
||||
);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE alert_history (
|
||||
id bigserial PRIMARY KEY,
|
||||
rule_id uuid NOT NULL REFERENCES alert_rules(id) ON DELETE CASCADE,
|
||||
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
fired_at timestamptz NOT NULL DEFAULT now(),
|
||||
payload jsonb NOT NULL,
|
||||
delivered_to text[] NOT NULL DEFAULT '{}',
|
||||
delivery_errors jsonb
|
||||
);
|
||||
CREATE INDEX idx_alert_history_user_time ON alert_history(user_id, fired_at DESC);
|
||||
CREATE INDEX idx_alert_history_fired_brin ON alert_history USING BRIN (fired_at);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE telegram_webhooks (
|
||||
user_id uuid PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
||||
webhook_uuid uuid NOT NULL UNIQUE,
|
||||
secret_token text NOT NULL,
|
||||
bot_token_enc bytea NOT NULL,
|
||||
bot_token_nonce bytea NOT NULL,
|
||||
chat_id bigint,
|
||||
pending_link boolean NOT NULL DEFAULT true,
|
||||
created_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE user_preferences (
|
||||
user_id uuid PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
||||
watched_country text,
|
||||
watched_asns integer[] NOT NULL DEFAULT '{}',
|
||||
observer_lat double precision,
|
||||
observer_lon double precision,
|
||||
observer_alt_m double precision,
|
||||
digest_enabled boolean NOT NULL DEFAULT false,
|
||||
digest_local_tz text NOT NULL DEFAULT 'UTC',
|
||||
digest_local_time time NOT NULL DEFAULT '08:00',
|
||||
digest_window_hours integer NOT NULL DEFAULT 24,
|
||||
digest_channel_ids uuid[] NOT NULL DEFAULT '{}',
|
||||
chime_enabled boolean NOT NULL DEFAULT true,
|
||||
chime_audio_object text,
|
||||
presentation_default boolean NOT NULL DEFAULT false,
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE digest_runs (
|
||||
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
fired_date date NOT NULL,
|
||||
fired_at timestamptz NOT NULL DEFAULT now(),
|
||||
status text NOT NULL,
|
||||
error text,
|
||||
PRIMARY KEY (user_id, fired_date)
|
||||
);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE IF EXISTS digest_runs;
|
||||
DROP TABLE IF EXISTS user_preferences;
|
||||
DROP TABLE IF EXISTS telegram_webhooks;
|
||||
DROP TABLE IF EXISTS alert_history;
|
||||
DROP TABLE IF EXISTS alert_rule_channels;
|
||||
DROP TABLE IF EXISTS alert_channels;
|
||||
DROP TABLE IF EXISTS alert_rules;
|
||||
-- +goose StatementEnd
|
||||
|
|
@ -0,0 +1,151 @@
|
|||
-- ©AngelaMos | 2026
|
||||
-- 0002_panel_data.sql
|
||||
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE cve_events (
|
||||
cve_id text PRIMARY KEY,
|
||||
published timestamptz,
|
||||
last_modified timestamptz NOT NULL,
|
||||
severity text,
|
||||
cvss_score numeric(3,1),
|
||||
epss_score numeric(5,4),
|
||||
epss_percentile numeric(5,4),
|
||||
in_kev boolean NOT NULL DEFAULT false,
|
||||
payload jsonb NOT NULL
|
||||
);
|
||||
CREATE INDEX idx_cve_lastmod_brin ON cve_events USING BRIN (last_modified);
|
||||
CREATE INDEX idx_cve_severity_lastmod ON cve_events (severity, last_modified DESC);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE kev_entries (
|
||||
cve_id text PRIMARY KEY,
|
||||
vendor text,
|
||||
product text,
|
||||
vulnerability_name text,
|
||||
date_added date NOT NULL,
|
||||
due_date date,
|
||||
ransomware_use text,
|
||||
payload jsonb NOT NULL
|
||||
);
|
||||
CREATE INDEX idx_kev_dateadded ON kev_entries (date_added DESC);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE earthquakes (
|
||||
id text PRIMARY KEY,
|
||||
occurred_at timestamptz NOT NULL,
|
||||
mag numeric(3,1) NOT NULL,
|
||||
place text,
|
||||
geom_lon double precision NOT NULL,
|
||||
geom_lat double precision NOT NULL,
|
||||
depth_km double precision,
|
||||
payload jsonb NOT NULL
|
||||
);
|
||||
CREATE INDEX idx_quakes_time_brin ON earthquakes USING BRIN (occurred_at);
|
||||
CREATE INDEX idx_quakes_mag ON earthquakes (mag DESC, occurred_at DESC);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE ransomware_victims (
|
||||
id text PRIMARY KEY,
|
||||
post_title text NOT NULL,
|
||||
group_name text NOT NULL,
|
||||
discovered_at timestamptz NOT NULL,
|
||||
country text,
|
||||
sector text,
|
||||
payload jsonb NOT NULL
|
||||
);
|
||||
CREATE INDEX idx_rans_time_brin ON ransomware_victims USING BRIN (discovered_at);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE btc_eth_ticks (
|
||||
symbol text NOT NULL,
|
||||
ts timestamptz NOT NULL,
|
||||
price numeric(18,8) NOT NULL,
|
||||
volume_24h numeric(20,8),
|
||||
PRIMARY KEY (symbol, ts)
|
||||
);
|
||||
CREATE INDEX idx_ticks_time_brin ON btc_eth_ticks USING BRIN (ts);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE btc_eth_minute (
|
||||
symbol text NOT NULL,
|
||||
minute timestamptz NOT NULL,
|
||||
open numeric(18,8) NOT NULL,
|
||||
high numeric(18,8) NOT NULL,
|
||||
low numeric(18,8) NOT NULL,
|
||||
close numeric(18,8) NOT NULL,
|
||||
volume numeric(20,8),
|
||||
PRIMARY KEY (symbol, minute)
|
||||
);
|
||||
CREATE INDEX idx_minute_time_brin ON btc_eth_minute USING BRIN (minute);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE outage_events (
|
||||
id text PRIMARY KEY,
|
||||
started_at timestamptz NOT NULL,
|
||||
ended_at timestamptz,
|
||||
locations text[] NOT NULL DEFAULT '{}',
|
||||
asns integer[] NOT NULL DEFAULT '{}',
|
||||
cause text,
|
||||
outage_type text,
|
||||
payload jsonb NOT NULL
|
||||
);
|
||||
CREATE INDEX idx_outage_start_brin ON outage_events USING BRIN (started_at);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE bgp_hijack_events (
|
||||
id bigint PRIMARY KEY,
|
||||
detected_at timestamptz NOT NULL,
|
||||
started_at timestamptz NOT NULL,
|
||||
duration_sec integer,
|
||||
confidence smallint,
|
||||
hijacker_asn integer,
|
||||
victim_asns integer[] NOT NULL DEFAULT '{}',
|
||||
prefixes cidr[] NOT NULL DEFAULT '{}',
|
||||
payload jsonb NOT NULL
|
||||
);
|
||||
CREATE INDEX idx_hijack_time_brin ON bgp_hijack_events USING BRIN (detected_at);
|
||||
CREATE INDEX idx_hijack_conf_time ON bgp_hijack_events (confidence DESC, detected_at DESC);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE dshield_snapshots (
|
||||
ts timestamptz NOT NULL,
|
||||
kind text NOT NULL,
|
||||
payload jsonb NOT NULL,
|
||||
PRIMARY KEY (ts, kind)
|
||||
);
|
||||
CREATE INDEX idx_dshield_ts_brin ON dshield_snapshots USING BRIN (ts);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE world_events (
|
||||
id text PRIMARY KEY,
|
||||
source text NOT NULL,
|
||||
occurred_at timestamptz NOT NULL,
|
||||
headline text NOT NULL,
|
||||
payload jsonb NOT NULL
|
||||
);
|
||||
CREATE INDEX idx_world_time_brin ON world_events USING BRIN (occurred_at);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE IF EXISTS world_events;
|
||||
DROP TABLE IF EXISTS dshield_snapshots;
|
||||
DROP TABLE IF EXISTS bgp_hijack_events;
|
||||
DROP TABLE IF EXISTS outage_events;
|
||||
DROP TABLE IF EXISTS btc_eth_minute;
|
||||
DROP TABLE IF EXISTS btc_eth_ticks;
|
||||
DROP TABLE IF EXISTS ransomware_victims;
|
||||
DROP TABLE IF EXISTS earthquakes;
|
||||
DROP TABLE IF EXISTS kev_entries;
|
||||
DROP TABLE IF EXISTS cve_events;
|
||||
-- +goose StatementEnd
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
-- ©AngelaMos | 2026
|
||||
-- 0003_collector_state.sql
|
||||
|
||||
-- +goose Up
|
||||
-- +goose StatementBegin
|
||||
CREATE TABLE collector_state (
|
||||
name text PRIMARY KEY,
|
||||
state text NOT NULL,
|
||||
last_success_at timestamptz,
|
||||
last_error_at timestamptz,
|
||||
last_error text,
|
||||
last_event_count bigint NOT NULL DEFAULT 0,
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
-- +goose StatementEnd
|
||||
|
||||
-- +goose Down
|
||||
-- +goose StatementBegin
|
||||
DROP TABLE IF EXISTS collector_state;
|
||||
-- +goose StatementEnd
|
||||
Loading…
Reference in New Issue