v1.5.0: IRM — инциденты, задачи, эскалации

- docs/IRM.md; Alembic 002: incidents, tasks, escalation_policies
- Модули incidents/tasks/escalations: API, UI, register_events(bus, pool)
- Авто-инцидент из alert.received; тесты test_irm_modules.py

Made-with: Cursor
This commit is contained in:
Alexandr
2026-04-03 09:03:16 +03:00
parent 0787745098
commit 89b5983526
20 changed files with 772 additions and 16 deletions

View File

@ -0,0 +1,72 @@
"""irm core: incidents, tasks, escalation_policies
Revision ID: 002_irm_core
Revises: 001_initial
Create Date: 2026-04-03
"""
from typing import Sequence, Union
from alembic import op
revision: str = "002_irm_core"
down_revision: Union[str, None] = "001_initial"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
op.execute(
"""
CREATE TABLE IF NOT EXISTS incidents (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
title text NOT NULL,
status text NOT NULL DEFAULT 'open',
severity text NOT NULL DEFAULT 'warning',
source text NOT NULL DEFAULT 'grafana',
ingress_event_id uuid REFERENCES ingress_events (id) ON DELETE SET NULL,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
);
"""
)
op.execute(
"""
CREATE INDEX IF NOT EXISTS incidents_created_at_idx
ON incidents (created_at DESC);
"""
)
op.execute(
"""
CREATE TABLE IF NOT EXISTS tasks (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
incident_id uuid REFERENCES incidents (id) ON DELETE CASCADE,
title text NOT NULL,
status text NOT NULL DEFAULT 'open',
created_at timestamptz NOT NULL DEFAULT now()
);
"""
)
op.execute(
"""
CREATE INDEX IF NOT EXISTS tasks_incident_id_idx ON tasks (incident_id);
"""
)
op.execute(
"""
CREATE TABLE IF NOT EXISTS escalation_policies (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
name text NOT NULL,
enabled boolean NOT NULL DEFAULT true,
steps jsonb NOT NULL DEFAULT '[]'::jsonb,
created_at timestamptz NOT NULL DEFAULT now()
);
"""
)
def downgrade() -> None:
op.execute("DROP TABLE IF EXISTS tasks;")
op.execute("DROP TABLE IF EXISTS incidents;")
op.execute("DROP TABLE IF EXISTS escalation_policies;")