export type NodeStatus = "online" | "offline" | "recording" | "unconfigured"; export type ApprovalStatus = "pending" | "approved" | "rejected"; export interface NodeRecord { node_id: string; name: string; lat: number; lon: number; status: NodeStatus; configured: boolean; last_seen: string | null; assigned_system_id: string | null; approval_status: ApprovalStatus | null; } export interface VocabularyPendingTerm { term: string; source: "induction" | "correction"; added_at: string; } export interface SystemRecord { system_id: string; name: string; type: string; // P25 | DMR | NBFM config: Record; vocabulary?: string[]; vocabulary_pending?: VocabularyPendingTerm[]; vocabulary_bootstrapped?: boolean; ten_codes?: Record; // {"10-10": "Commercial Alarm", ...} } export interface TranscriptSegment { start: number; end: number; text: string; } export interface CallRecord { call_id: string; node_id: string; system_id: string | null; talkgroup_id: number | null; talkgroup_name: string | null; freq: number | null; started_at: string; ended_at: string | null; audio_url: string | null; transcript: string | null; transcript_corrected: string | null; segments: TranscriptSegment[] | null; /** New: one entry per scene detected in the recording. */ incident_ids: string[]; /** Legacy field — present on calls recorded before the multi-scene migration. */ incident_id?: string | null; location: string | null; tags: string[]; status: "active" | "ended"; // Correlation debug — written by the correlator, present after a call is linked corr_path?: string | null; corr_score?: number | null; corr_distance_km?: number | null; corr_incident_idle_min?: number | null; corr_shared_units?: number | null; corr_candidates?: number | null; } export interface IncidentRecord { incident_id: string; title: string | null; type: string | null; status: "active" | "resolved"; location: string | null; location_coords: { lat: number; lng: number } | null; call_ids: string[]; system_ids: string[]; talkgroup_ids: string[]; units: string[]; vehicles: string[]; severity: string | null; started_at: string; updated_at: string; summary: string | null; tags: string[]; } export interface AlertRule { rule_id: string; name: string; keywords: string[]; talkgroup_ids: number[]; enabled: boolean; discord_webhook: string | null; created_at?: string; } export interface AlertEvent { alert_id: string; rule_id: string; rule_name: string; call_id: string; node_id: string; talkgroup_id: number | null; talkgroup_name: string | null; matched_keywords: string[]; transcript_snippet: string | null; triggered_at: string; acknowledged: boolean; }