CREATE TABLE alert_rules ( id uuid PRIMARY KEY, schema_version integer NOT NULL CHECK (schema_version = 1), name text NOT NULL CHECK (length(name) BETWEEN 1 AND 160), enabled boolean NOT NULL DEFAULT false, severity text NOT NULL CHECK (severity IN ('attention', 'degraded', 'critical')), scope jsonb NOT NULL DEFAULT '{}'::jsonb, condition jsonb NOT NULL, evaluation_interval_seconds integer NOT NULL CHECK (evaluation_interval_seconds BETWEEN 5 AND 3600), pending_seconds integer NOT NULL CHECK (pending_seconds BETWEEN 0 AND 2592000), resolve_seconds integer NOT NULL CHECK (resolve_seconds BETWEEN 0 AND 2592000), unknown_behavior text NOT NULL CHECK (unknown_behavior IN ('retain-firing-as-unknown', 'become-unknown', 'ignore-short-gap')), group_by jsonb NOT NULL DEFAULT '[]'::jsonb, suppress_when jsonb NOT NULL DEFAULT '[]'::jsonb, message jsonb NOT NULL, current_version_id uuid, revision bigint NOT NULL DEFAULT 1 CHECK (revision > 0), created_by uuid REFERENCES users(id) ON DELETE SET NULL, created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now() ); CREATE TABLE alert_rule_versions ( id uuid PRIMARY KEY, rule_id uuid NOT NULL REFERENCES alert_rules(id) ON DELETE RESTRICT, version_number integer NOT NULL CHECK (version_number > 0), document jsonb NOT NULL, change_summary text NOT NULL DEFAULT '' CHECK (length(change_summary) <= 500), created_by uuid REFERENCES users(id) ON DELETE SET NULL, created_at timestamptz NOT NULL DEFAULT now(), UNIQUE (rule_id, version_number) ); ALTER TABLE alert_rules ADD CONSTRAINT alert_rules_current_version_fk FOREIGN KEY (current_version_id) REFERENCES alert_rule_versions(id) ON DELETE RESTRICT DEFERRABLE INITIALLY DEFERRED; CREATE INDEX alert_rules_enabled_idx ON alert_rules (enabled, evaluation_interval_seconds, updated_at DESC) WHERE enabled = true; CREATE INDEX alert_rules_severity_idx ON alert_rules (severity, updated_at DESC); CREATE INDEX alert_rule_versions_history_idx ON alert_rule_versions (rule_id, version_number DESC);