tftsr-devops_investigation/src/lib/tauriCommands.ts

1637 lines
50 KiB
TypeScript
Raw Normal View History

feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
import { invoke } from "@tauri-apps/api/core";
// ─── Types matching Rust backend models ───────────────────────────────────────
export interface ProviderConfig {
provider_type?: string;
max_tokens?: number;
temperature?: number;
name: string;
api_url: string;
api_key: string;
model: string;
custom_endpoint_path?: string;
custom_auth_header?: string;
custom_auth_prefix?: string;
api_format?: string;
session_id?: string;
user_id?: string;
use_datastore_upload?: boolean;
supports_tool_calling?: boolean;
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
}
export interface Message {
role: string;
content: string;
}
export interface TokenUsage {
prompt_tokens: number;
completion_tokens: number;
total_tokens: number;
}
export interface ChatResponse {
content: string;
model: string;
usage?: TokenUsage;
/** What was stored in the DB — may be auto-redacted. Use this for display and history. */
user_message?: string;
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
}
export interface AnalysisResult {
summary: string;
key_findings: string[];
suggested_why1: string;
severity_assessment: string;
}
export interface ProviderInfo {
name: string;
supports_streaming: boolean;
models: string[];
}
export interface Issue {
id: string;
title: string;
description: string;
severity: string;
status: string;
category: string;
source: string;
created_at: string;
updated_at: string;
resolved_at?: string;
assigned_to: string;
tags: string;
}
export interface FiveWhyEntry {
id: string;
why_number: number;
question: string;
answer?: string;
created_at: number;
}
export interface TimelineEvent {
id: string;
issue_id: string;
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
event_type: string;
description: string;
metadata: string;
created_at: string;
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
}
export interface AiConversation {
id: string;
issue_id: string;
provider: string;
model: string;
created_at: string;
title: string;
}
export interface ResolutionStep {
id: string;
issue_id: string;
step_order: number;
why_question: string;
answer: string;
evidence: string;
created_at: string;
}
export interface IssueDetail {
issue: Issue;
log_files: LogFile[];
image_attachments: ImageAttachment[];
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
resolution_steps: ResolutionStep[];
conversations: AiConversation[];
timeline_events: TimelineEvent[];
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
}
export interface IssueSummary {
id: string;
title: string;
severity: string;
status: string;
category: string;
created_at: string;
updated_at: string;
domain?: string;
log_count: number;
step_count: number;
}
export interface IssueListQuery {
status?: string;
domain?: string;
severity?: string;
search?: string;
limit?: number;
offset?: number;
}
export interface NewIssue {
title: string;
domain: string;
description?: string;
severity?: string;
}
export interface LogFile {
id: string;
issue_id: string;
file_name: string;
file_path: string;
file_size: number;
mime_type: string;
content_hash: string;
uploaded_at: string;
redacted: boolean;
}
export interface ImageAttachment {
id: string;
issue_id: string;
file_name: string;
file_path: string;
file_size: number;
mime_type: string;
upload_hash: string;
uploaded_at: string;
pii_warning_acknowledged: boolean;
is_paste: boolean;
}
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
export interface PiiSpan {
id: string;
pii_type: string;
start: number;
end: number;
original: string;
replacement: string;
}
export interface PiiDetectionResult {
log_file_id: string;
detections: PiiSpan[];
total_pii_found: number;
}
export interface RedactedLogFile {
id: string;
original_file_id: string;
file_name: string;
file_hash: string;
redaction_count: number;
}
export interface Document_ {
id: string;
issue_id: string;
doc_type: string;
title: string;
content_md: string;
created_at: number;
updated_at: number;
}
export interface HardwareInfo {
total_ram_gb: number;
cpu_arch: string;
gpu_vendor?: string;
gpu_vram_gb?: number;
}
export interface ModelRecommendation {
name: string;
size: string;
min_ram_gb: number;
description: string;
recommended: boolean;
}
export interface OllamaModel {
name: string;
size: number;
modified: string;
}
export interface OllamaStatus {
installed: boolean;
version?: string;
running: boolean;
}
export interface InstallGuide {
platform: string;
steps: string[];
url: string;
}
export interface AuditEntry {
id: string;
timestamp: string;
action: string;
entity_type: string;
entity_id: string;
user_id: string;
details: string;
}
export interface AuditFilter {
action?: string;
entity_type?: string;
entity_id?: string;
limit?: number;
}
export interface AppSettings {
theme: string;
ai_providers: ProviderConfig[];
active_provider?: string;
default_provider: string;
default_model: string;
ollama_url: string;
}
// ─── TriageMessage (for UI store, not a DB type) ──────────────────────────────
export interface TriageMessage {
id: string;
issue_id: string;
role: string;
content: string;
why_level?: number;
created_at: number;
}
// ─── AI commands ──────────────────────────────────────────────────────────────
export const analyzeLogsCmd = (issueId: string, logFileIds: string[], providerConfig: ProviderConfig) =>
invoke<AnalysisResult>("analyze_logs", { issueId, logFileIds, providerConfig });
fix(security): address PR review — move attachment handling to backend, auto-redact PII Resolves all four findings from the automated review: [BLOCKER 1] Attachment PII scan error path left pendingFiles intact, allowing retry with stale file references. Fix: file content is no longer held in frontend state at all — PendingFile drops the content field entirely. logFileIds are captured before setPendingFiles([]) and passed directly to the backend. [BLOCKER 2] Raw file content stored in PendingFile.content created a UI-visible PII surface and a data-residency risk. Fix: frontend never reads or stores file content. The backend loads file data from disk, auto-redacts PII in-memory using pii::apply_redactions(), and embeds the clean text into the AI message. No PII ever touches the frontend. [WARNING 1] String-based attachment header parsing was fragile and bypassable. Fix: parsing is gone — backend identifies attachments by log_file_id, reads them directly from the DB/disk path, and applies redaction at that level. [WARNING 2] Error message disclosed PII type list to the caller. Fix: PII types are logged via tracing::warn only; no type details in the user-facing error or API response. Additionally: typed chat messages are now auto-redacted rather than blocked. scanTextForPiiCmd runs on the typed text; detected spans are replaced in reverse-offset order before the message is sent to the AI and stored in the DB. The user sees the redacted form in their chat bubble. Architecture: - chat_message now accepts log_file_ids: Option<Vec<String>> - Backend reads file → detects PII → redacts in memory → embeds - Frontend: no readTextFile, no content field, no frontend PII gate
2026-06-01 00:20:46 +00:00
export const chatMessageCmd = (
issueId: string,
message: string,
logFileIds: string[],
providerConfig: ProviderConfig,
systemPrompt?: string
) =>
invoke<ChatResponse>("chat_message", {
issueId,
message,
logFileIds: logFileIds.length > 0 ? logFileIds : undefined,
fix(security): address PR review — move attachment handling to backend, auto-redact PII Resolves all four findings from the automated review: [BLOCKER 1] Attachment PII scan error path left pendingFiles intact, allowing retry with stale file references. Fix: file content is no longer held in frontend state at all — PendingFile drops the content field entirely. logFileIds are captured before setPendingFiles([]) and passed directly to the backend. [BLOCKER 2] Raw file content stored in PendingFile.content created a UI-visible PII surface and a data-residency risk. Fix: frontend never reads or stores file content. The backend loads file data from disk, auto-redacts PII in-memory using pii::apply_redactions(), and embeds the clean text into the AI message. No PII ever touches the frontend. [WARNING 1] String-based attachment header parsing was fragile and bypassable. Fix: parsing is gone — backend identifies attachments by log_file_id, reads them directly from the DB/disk path, and applies redaction at that level. [WARNING 2] Error message disclosed PII type list to the caller. Fix: PII types are logged via tracing::warn only; no type details in the user-facing error or API response. Additionally: typed chat messages are now auto-redacted rather than blocked. scanTextForPiiCmd runs on the typed text; detected spans are replaced in reverse-offset order before the message is sent to the AI and stored in the DB. The user sees the redacted form in their chat bubble. Architecture: - chat_message now accepts log_file_ids: Option<Vec<String>> - Backend reads file → detects PII → redacts in memory → embeds - Frontend: no readTextFile, no content field, no frontend PII gate
2026-06-01 00:20:46 +00:00
providerConfig,
systemPrompt: systemPrompt ?? null,
});
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
export const listProvidersCmd = () => invoke<ProviderInfo[]>("list_providers");
// ─── Analysis / PII commands ──────────────────────────────────────────────────
export const uploadLogFileCmd = (issueId: string, filePath: string) =>
invoke<LogFile>("upload_log_file", { issueId, filePath });
export const uploadLogFileByContentCmd = (issueId: string, fileName: string, content: string) =>
invoke<LogFile>("upload_log_file_by_content", { issueId, fileName, content });
export const uploadImageAttachmentCmd = (issueId: string, filePath: string) =>
invoke<ImageAttachment>("upload_image_attachment", { issueId, filePath });
export const uploadImageAttachmentByContentCmd = (issueId: string, fileName: string, base64Content: string) =>
invoke<ImageAttachment>("upload_image_attachment_by_content", { issueId, fileName, base64Content });
export const uploadFileToDatastoreCmd = (providerConfig: ProviderConfig, filePath: string) =>
invoke<string>("upload_file_to_datastore", { providerConfig, filePath });
export const uploadFileToDatastoreAnyCmd = (providerConfig: ProviderConfig, filePath: string) =>
invoke<string>("upload_file_to_datastore_any", { providerConfig, filePath });
export const uploadPasteImageCmd = (issueId: string, base64Image: string, mimeType: string) =>
invoke<ImageAttachment>("upload_paste_image", { issueId, base64Image, mimeType });
export const listImageAttachmentsCmd = (issueId: string) =>
invoke<ImageAttachment[]>("list_image_attachments", { issueId });
export const deleteImageAttachmentCmd = (attachmentId: string) =>
invoke<void>("delete_image_attachment", { attachmentId });
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
export const detectPiiCmd = (logFileId: string) =>
invoke<PiiDetectionResult>("detect_pii", { logFileId });
export const scanTextForPiiCmd = (text: string) =>
invoke<PiiDetectionResult>("scan_text_for_pii", { text });
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
export const applyRedactionsCmd = (logFileId: string, approvedSpanIds: string[]) =>
invoke<RedactedLogFile>("apply_redactions", { logFileId, approvedSpanIds });
// ─── Issue CRUD ───────────────────────────────────────────────────────────────
export const testProviderConnectionCmd = (providerConfig: ProviderConfig) =>
invoke<ChatResponse>("test_provider_connection", { providerConfig });
export const detectToolCallingSupportCmd = (providerConfig: ProviderConfig) =>
invoke<boolean>("detect_tool_calling_support", { providerConfig });
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
export const createIssueCmd = (newIssue: NewIssue) =>
invoke<Issue>("create_issue", {
title: newIssue.title,
description: newIssue.description ?? "",
severity: newIssue.severity ?? "P3",
category: newIssue.domain,
});
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
export const getIssueCmd = (issueId: string) =>
invoke<IssueDetail>("get_issue", { issueId });
export const listIssuesCmd = (query: IssueListQuery) =>
invoke<IssueSummary[]>("list_issues", { filter: query });
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
export const updateIssueCmd = (
issueId: string,
updates: { title?: string; status?: string; severity?: string; description?: string; domain?: string }
) => invoke<Issue>("update_issue", { issueId, updates });
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
export const deleteIssueCmd = (issueId: string) =>
invoke<void>("delete_issue", { issueId });
export const searchIssuesCmd = (query: string) =>
invoke<IssueSummary[]>("search_issues", { query });
export interface IssueMessage {
id: string;
conversation_id: string;
role: string;
content: string;
token_count: number;
created_at: string;
}
export const getIssueMessagesCmd = (issueId: string) =>
invoke<IssueMessage[]>("get_issue_messages", { issueId });
export const addFiveWhyCmd = (
issueId: string,
stepOrder: number,
whyQuestion: string,
answer: string,
evidence: string
) => invoke<ResolutionStep>("add_five_why", { issueId, stepOrder, whyQuestion, answer, evidence });
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
export const updateFiveWhyCmd = (entryId: string, answer: string) =>
invoke<void>("update_five_why", { entryId, answer });
export const addTimelineEventCmd = (issueId: string, eventType: string, description: string, metadata?: string) =>
invoke<TimelineEvent>("add_timeline_event", { issueId, eventType, description, metadata: metadata ?? null });
export const getTimelineEventsCmd = (issueId: string) =>
invoke<TimelineEvent[]>("get_timeline_events", { issueId });
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
// ─── Document commands ────────────────────────────────────────────────────────
export const generateRcaCmd = (issueId: string) => invoke<Document_>("generate_rca", { issueId });
export const generatePostmortemCmd = (issueId: string) =>
invoke<Document_>("generate_postmortem", { issueId });
export const updateDocumentCmd = (docId: string, contentMd: string) =>
invoke<Document_>("update_document", { docId, contentMd });
export const exportDocumentCmd = (docId: string, title: string, contentMd: string, format: string, outputDir: string) =>
invoke<string>("export_document", { title, contentMd, format, outputDir });
feat: initial implementation of TFTSR IT Triage & RCA application Implements Phases 1-8 of the TFTSR implementation plan. Rust backend (Tauri 2.x, src-tauri/): - Multi-provider AI: OpenAI-compatible, Anthropic, Gemini, Mistral, Ollama - PII detection engine: 11 regex patterns with overlap resolution - SQLCipher AES-256 encrypted database with 10 versioned migrations - 28 Tauri IPC commands for triage, analysis, document, and system ops - Ollama: hardware probe, model recommendations, pull/delete with events - RCA and blameless post-mortem Markdown document generators - PDF export via printpdf - Audit log: SHA-256 hash of every external data send - Integration stubs for Confluence, ServiceNow, Azure DevOps (v0.2) Frontend (React 18 + TypeScript + Vite, src/): - 9 pages: full triage workflow NewIssue→LogUpload→Triage→Resolution→RCA→Postmortem→History+Settings - 7 components: ChatWindow, TriageProgress, PiiDiffViewer, DocEditor, HardwareReport, ModelSelector, UI primitives - 3 Zustand stores: session, settings (persisted), history - Type-safe tauriCommands.ts matching Rust backend types exactly - 8 IT domain system prompts (Linux, Windows, Network, K8s, DB, Virt, HW, Obs) DevOps: - .woodpecker/test.yml: rustfmt, clippy, cargo test, tsc, vitest on every push - .woodpecker/release.yml: linux/amd64 + linux/arm64 builds, Gogs release upload Verified: - cargo check: zero errors - tsc --noEmit: zero errors - vitest run: 13/13 unit tests passing Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 03:36:25 +00:00
// ─── Ollama & System ──────────────────────────────────────────────────────────
export const checkOllamaInstalledCmd = () => invoke<OllamaStatus>("check_ollama_installed");
export const getOllamaInstallGuideCmd = (platform: string) =>
invoke<InstallGuide>("get_ollama_install_guide", { platform });
export const listOllamaModelsCmd = () => invoke<OllamaModel[]>("list_ollama_models");
export const pullOllamaModelCmd = (modelName: string) =>
invoke<void>("pull_ollama_model", { modelName });
export const deleteOllamaModelCmd = (modelName: string) =>
invoke<void>("delete_ollama_model", { modelName });
export const detectHardwareCmd = () => invoke<HardwareInfo>("detect_hardware");
export const recommendModelsCmd = () => invoke<ModelRecommendation[]>("recommend_models");
// ─── Settings & Audit ─────────────────────────────────────────────────────────
export const getSettingsCmd = () => invoke<AppSettings>("get_settings");
export const updateSettingsCmd = (partialSettings: Partial<AppSettings>) =>
invoke<AppSettings>("update_settings", { partialSettings });
export const getAuditLogCmd = (filter: AuditFilter) =>
invoke<AuditEntry[]>("get_audit_log", { filter });
feat: add OAuth2 frontend UI and complete integration flow Phase 2.2: OAuth2 flow - FRONTEND COMPLETE ✅ Implemented: - TypeScript command wrappers in tauriCommands.ts * initiateOauthCmd(service) -> OAuthInitResponse * handleOauthCallbackCmd(service, code, stateKey) * test*ConnectionCmd() for all services * OAuthInitResponse and ConnectionResult types - Complete Settings/Integrations UI * Three integration cards: Confluence, ServiceNow, ADO * Connect with OAuth2 buttons (Confluence, ADO) * Basic auth note for ServiceNow * Configuration inputs: baseUrl, username, projectName, spaceKey * Test connection buttons with loading states * Success/error feedback with color-coded messages * OAuth2 flow instructions for users - OAuth2 flow in browser * Opens auth URL in default browser via shell plugin * User authenticates with service * Redirected to localhost:8765/callback * Callback server handles token exchange automatically * Success message shown to user - CSP updates in tauri.conf.json * Added http://localhost:8765 (callback server) * Added https://auth.atlassian.com (Confluence OAuth) * Added https://*.atlassian.net (Confluence API) * Added https://login.microsoftonline.com (ADO OAuth) * Added https://dev.azure.com (ADO API) - UI improvements * Fixed Cancel button variant (ghost instead of secondary) * Loading spinners with Loader2 icon * Check/X icons for success/error states * Disabled states when not configured * Optimistic UI updates on connect Frontend + Backend = COMPLETE END-TO-END OAUTH2 FLOW: 1. User goes to Settings → Integrations 2. Enters base URL and config 3. Clicks 'Connect with OAuth2' 4. Browser opens with service auth page 5. User logs in and authorizes 6. Redirected to localhost:8765/callback 7. Token exchanged and encrypted automatically 8. Stored in SQLite credentials table 9. Ready for API calls to external services ✅ TypeScript: All types checked, no errors Frontend build: ✅ Built in 2.26s Total lines: ~400 lines of new UI code Next: Phase 2.3 - Integration API clients (Confluence REST, ServiceNow REST, ADO REST)
2026-04-03 20:04:12 +00:00
// ─── OAuth & Integrations ─────────────────────────────────────────────────────
export interface OAuthInitResponse {
auth_url: string;
state: string;
}
export interface ConnectionResult {
success: boolean;
message: string;
}
export const initiateOauthCmd = (service: string) =>
invoke<OAuthInitResponse>("initiate_oauth", { service });
export const handleOauthCallbackCmd = (service: string, code: string, stateKey: string) =>
invoke<void>("handle_oauth_callback", { service, code, stateKey });
export const testConfluenceConnectionCmd = (baseUrl: string, credentials: Record<string, unknown>) =>
invoke<ConnectionResult>("test_confluence_connection", { baseUrl, credentials });
export const testServiceNowConnectionCmd = (instanceUrl: string, credentials: Record<string, unknown>) =>
invoke<ConnectionResult>("test_servicenow_connection", { instanceUrl, credentials });
export const testAzureDevOpsConnectionCmd = (orgUrl: string, credentials: Record<string, unknown>) =>
invoke<ConnectionResult>("test_azuredevops_connection", { orgUrl, credentials });
// ─── Webview & Token Authentication ──────────────────────────────────────────
export interface WebviewAuthResponse {
success: boolean;
message: string;
webview_id: string;
}
export interface TokenAuthRequest {
service: string;
token: string;
token_type: string;
base_url: string;
}
fix: persist integration settings and implement persistent browser windows ## Integration Settings Persistence - Add database commands to save/load integration configs (base_url, username, project_name, space_key) - Frontend now loads configs from DB on mount and saves changes automatically - Fixes issue where settings were lost on app restart ## Persistent Browser Window Architecture - Integration browser windows now stay open for user browsing and authentication - Extract fresh cookies before each API call to handle token rotation - Track open windows in app state (integration_webviews HashMap) - Windows titled as "{Service} Browser (TFTSR)" for clarity - Support easy navigation between app and browser windows (Cmd+Tab/Alt+Tab) - Gracefully handle closed windows with automatic cleanup ## Bug Fixes - Fix Rust formatting issues across 8 files - Fix clippy warnings: - Use is_some_and() instead of map_or() in openai.rs - Use .to_string() instead of format!() in integrations.rs - Add missing OptionalExtension import for .optional() method ## Tests - Add test_integration_config_serialization - Add test_webview_tracking - Add test_token_auth_request_serialization - All 6 integration tests passing ## Files Modified - src-tauri/src/state.rs: Add integration_webviews tracking - src-tauri/src/lib.rs: Register 3 new commands, initialize webviews HashMap - src-tauri/src/commands/integrations.rs: Config persistence, fresh cookie extraction (+151 lines) - src-tauri/src/integrations/webview_auth.rs: Persistent window behavior - src/lib/tauriCommands.ts: TypeScript wrappers for new commands - src/pages/Settings/Integrations.tsx: Load/save configs from DB Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-04-04 14:57:22 +00:00
export interface IntegrationConfig {
service: string;
base_url: string;
username?: string;
project_name?: string;
space_key?: string;
}
export const authenticateWithWebviewCmd = (service: string, baseUrl: string, projectName?: string) =>
invoke<WebviewAuthResponse>("authenticate_with_webview", { service, baseUrl, projectName });
export const extractCookiesFromWebviewCmd = (service: string, webviewId: string) =>
invoke<ConnectionResult>("extract_cookies_from_webview", { service, webviewId });
export const saveManualTokenCmd = (request: TokenAuthRequest) =>
invoke<ConnectionResult>("save_manual_token", { request });
fix: persist integration settings and implement persistent browser windows ## Integration Settings Persistence - Add database commands to save/load integration configs (base_url, username, project_name, space_key) - Frontend now loads configs from DB on mount and saves changes automatically - Fixes issue where settings were lost on app restart ## Persistent Browser Window Architecture - Integration browser windows now stay open for user browsing and authentication - Extract fresh cookies before each API call to handle token rotation - Track open windows in app state (integration_webviews HashMap) - Windows titled as "{Service} Browser (TFTSR)" for clarity - Support easy navigation between app and browser windows (Cmd+Tab/Alt+Tab) - Gracefully handle closed windows with automatic cleanup ## Bug Fixes - Fix Rust formatting issues across 8 files - Fix clippy warnings: - Use is_some_and() instead of map_or() in openai.rs - Use .to_string() instead of format!() in integrations.rs - Add missing OptionalExtension import for .optional() method ## Tests - Add test_integration_config_serialization - Add test_webview_tracking - Add test_token_auth_request_serialization - All 6 integration tests passing ## Files Modified - src-tauri/src/state.rs: Add integration_webviews tracking - src-tauri/src/lib.rs: Register 3 new commands, initialize webviews HashMap - src-tauri/src/commands/integrations.rs: Config persistence, fresh cookie extraction (+151 lines) - src-tauri/src/integrations/webview_auth.rs: Persistent window behavior - src/lib/tauriCommands.ts: TypeScript wrappers for new commands - src/pages/Settings/Integrations.tsx: Load/save configs from DB Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-04-04 14:57:22 +00:00
// ─── Integration Configuration Persistence ────────────────────────────────────
export const saveIntegrationConfigCmd = (config: IntegrationConfig) =>
invoke<void>("save_integration_config", { config });
export const getIntegrationConfigCmd = (service: string) =>
invoke<IntegrationConfig | null>("get_integration_config", { service });
export const getAllIntegrationConfigsCmd = () =>
invoke<IntegrationConfig[]>("get_all_integration_configs");
// ─── AI Provider Configuration ────────────────────────────────────────────────
export const saveAiProviderCmd = (config: ProviderConfig) =>
invoke<void>("save_ai_provider", { provider: config });
export const loadAiProvidersCmd = () =>
invoke<ProviderConfig[]>("load_ai_providers");
export const deleteAiProviderCmd = (name: string) =>
invoke<void>("delete_ai_provider", { name });
// ─── MCP Server types ────────────────────────────────────────────────────────
export interface McpServer {
id: string;
name: string;
url: string;
transport_type: "stdio" | "http";
transport_config: string;
auth_type: "none" | "api_key" | "bearer" | "oauth2";
auth_value?: string;
enabled: boolean;
last_discovered_at?: string;
discovery_status: "pending" | "connected" | "unreachable" | "error";
discovery_error?: string;
created_at: string;
updated_at: string;
}
export interface McpTool {
id: string;
server_id: string;
name: string;
tool_key: string;
description?: string;
parameters: string;
}
export interface McpResource {
id: string;
server_id: string;
uri: string;
name?: string;
description?: string;
}
export interface McpServerStatus {
server_id: string;
status: "pending" | "connected" | "unreachable" | "error";
error?: string;
tool_count: number;
resource_count: number;
last_discovered_at?: string;
}
export interface CreateMcpServerRequest {
name: string;
url: string;
transport_type: "stdio" | "http";
transport_config: string;
auth_type: "none" | "api_key" | "bearer" | "oauth2";
auth_value?: string;
enabled: boolean;
fix(mcp): add environment variable and HTTP header support for MCP servers Add dual-mode environment variable support for stdio MCP servers and custom HTTP headers for HTTP-based MCP servers to enable proper authentication and configuration. Backend changes (Rust): - Add migration 023 for env_config column in mcp_servers table - Add env_config field to McpServer, CreateMcpServerRequest, UpdateMcpServerRequest - Encrypt env_config using AES-256-GCM on create/update in store.rs - Add get_server_env_config() helper to decrypt and parse env vars - Parse plaintext env from transport_config.env (stdio only) - Parse custom headers from transport_config.headers (HTTP only) - Merge plaintext and encrypted env vars (encrypted takes precedence) - Update connect_stdio() to accept HashMap<String, String> for env vars - Update connect_http() to accept HashMap<String, String> for headers - Apply env vars to tokio::process::Command via .env() method - Add warning for HTTP headers (rmcp v1.7.0 limitation - no .header() method) - Add comprehensive tests for encryption, merging, and clearing Frontend changes (TypeScript/React): - Add env_config field to CreateMcpServerRequest and UpdateMcpServerRequest - Add plaintext_env, encrypted_env, http_headers to ServerForm interface - Add parsing helpers: parseEnvVars(), formatEnvVars(), parseHeaders(), formatHeaders() - Update startEdit() to extract and format env vars/headers from transport_config - Update handleSave() to build transport_config with env/headers and env_config JSON - Add conditional UI fields: stdio (plaintext + encrypted env), HTTP (custom headers) - Use password input type for all sensitive fields Security: - Encrypted env vars stored using AES-256-GCM (matching auth_value pattern) - Plaintext env vars in transport_config for non-sensitive values - UI masks all env/header fields with password input type - Never display decrypted values when editing Fixes inability to configure MCP servers that require environment variables (e.g., GitHub MCP server with GITHUB_PERSONAL_ACCESS_TOKEN). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-01 13:32:51 +00:00
env_config?: string;
}
export interface UpdateMcpServerRequest {
name?: string;
url?: string;
transport_type?: "stdio" | "http";
transport_config?: string;
auth_type?: "none" | "api_key" | "bearer" | "oauth2";
auth_value?: string;
enabled?: boolean;
fix(mcp): add environment variable and HTTP header support for MCP servers Add dual-mode environment variable support for stdio MCP servers and custom HTTP headers for HTTP-based MCP servers to enable proper authentication and configuration. Backend changes (Rust): - Add migration 023 for env_config column in mcp_servers table - Add env_config field to McpServer, CreateMcpServerRequest, UpdateMcpServerRequest - Encrypt env_config using AES-256-GCM on create/update in store.rs - Add get_server_env_config() helper to decrypt and parse env vars - Parse plaintext env from transport_config.env (stdio only) - Parse custom headers from transport_config.headers (HTTP only) - Merge plaintext and encrypted env vars (encrypted takes precedence) - Update connect_stdio() to accept HashMap<String, String> for env vars - Update connect_http() to accept HashMap<String, String> for headers - Apply env vars to tokio::process::Command via .env() method - Add warning for HTTP headers (rmcp v1.7.0 limitation - no .header() method) - Add comprehensive tests for encryption, merging, and clearing Frontend changes (TypeScript/React): - Add env_config field to CreateMcpServerRequest and UpdateMcpServerRequest - Add plaintext_env, encrypted_env, http_headers to ServerForm interface - Add parsing helpers: parseEnvVars(), formatEnvVars(), parseHeaders(), formatHeaders() - Update startEdit() to extract and format env vars/headers from transport_config - Update handleSave() to build transport_config with env/headers and env_config JSON - Add conditional UI fields: stdio (plaintext + encrypted env), HTTP (custom headers) - Use password input type for all sensitive fields Security: - Encrypted env vars stored using AES-256-GCM (matching auth_value pattern) - Plaintext env vars in transport_config for non-sensitive values - UI masks all env/header fields with password input type - Never display decrypted values when editing Fixes inability to configure MCP servers that require environment variables (e.g., GitHub MCP server with GITHUB_PERSONAL_ACCESS_TOKEN). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-01 13:32:51 +00:00
env_config?: string;
}
// ─── MCP Commands ─────────────────────────────────────────────────────────────
export function listMcpServersCmd(): Promise<McpServer[]> {
return invoke<McpServer[]>("list_mcp_servers");
}
export function createMcpServerCmd(request: CreateMcpServerRequest): Promise<McpServer> {
return invoke<McpServer>("create_mcp_server", { request });
}
export function updateMcpServerCmd(id: string, request: UpdateMcpServerRequest): Promise<McpServer> {
return invoke<McpServer>("update_mcp_server", { id, request });
}
export function deleteMcpServerCmd(id: string): Promise<void> {
return invoke<void>("delete_mcp_server", { id });
}
export function toggleMcpServerCmd(id: string, enabled: boolean): Promise<void> {
return invoke<void>("toggle_mcp_server", { id, enabled });
}
export function discoverMcpServerCmd(id: string): Promise<McpServerStatus> {
return invoke<McpServerStatus>("discover_mcp_server", { id });
}
export function getMcpServerStatusCmd(id: string): Promise<McpServerStatus> {
return invoke<McpServerStatus>("get_mcp_server_status", { id });
}
export function initiateMcpOauthCmd(id: string): Promise<void> {
return invoke<void>("initiate_mcp_oauth", { id });
}
// ─── Sudo credential commands ─────────────────────────────────────────────────
export interface SudoConfigStatus {
configured: boolean;
username: string;
updated_at: string;
}
export const setSudoPasswordCmd = (password: string, username?: string) =>
invoke<void>("set_sudo_password", { password, username: username ?? null });
export const getSudoConfigStatusCmd = () =>
invoke<SudoConfigStatus>("get_sudo_config_status");
export const testSudoPasswordCmd = () =>
invoke<boolean>("test_sudo_password");
export const clearSudoPasswordCmd = () =>
invoke<void>("clear_sudo_password");
// ─── System / Version ─────────────────────────────────────────────────────────
export const getAppVersionCmd = () =>
invoke<string>("get_app_version");
// ─── Attachment cross-incident types ─────────────────────────────────────────
export interface LogFileSummary {
id: string;
issue_id: string;
issue_title: string;
file_name: string;
file_path: string;
file_size: number;
mime_type: string;
content_hash: string;
uploaded_at: string;
redacted: boolean;
}
export interface ImageAttachmentSummary {
id: string;
issue_id: string;
issue_title: string;
file_name: string;
file_path: string;
file_size: number;
mime_type: string;
upload_hash: string;
uploaded_at: string;
pii_warning_acknowledged: boolean;
is_paste: boolean;
}
// ─── Attachment cross-incident commands ───────────────────────────────────────
export const getLogFileContentCmd = (logFileId: string) =>
invoke<string>("get_log_file_content", { logFileId });
export const listAllLogFilesCmd = (search?: string, issueId?: string) =>
invoke<LogFileSummary[]>("list_all_log_files", {
search: search ?? null,
issueId: issueId ?? null,
});
export const getImageAttachmentDataCmd = (attachmentId: string) =>
invoke<string>("get_image_attachment_data", { attachmentId });
export const listAllImageAttachmentsCmd = (search?: string, issueId?: string) =>
invoke<ImageAttachmentSummary[]>("list_all_image_attachments", {
search: search ?? null,
issueId: issueId ?? null,
});
// ─── Shell Execution Commands ────────────────────────────────────────────────
export interface KubeconfigInfo {
id: string;
name: string;
context: string;
cluster_url?: string;
is_active: boolean;
}
export interface CommandExecution {
id: string;
command: string;
tier: number;
approval_status: string;
exit_code: number | null;
stdout: string | null;
stderr: string | null;
execution_time_ms: number | null;
executed_at: string;
}
export interface KubectlStatus {
installed: boolean;
path?: string;
version?: string;
}
export const uploadKubeconfigCmd = (name: string, content: string) =>
invoke<string>("upload_kubeconfig", { name, content });
export const listKubeconfigsCmd = () =>
invoke<KubeconfigInfo[]>("list_kubeconfigs");
export const activateKubeconfigCmd = (id: string) =>
invoke<void>("activate_kubeconfig", { id });
export const deleteKubeconfigCmd = (id: string) =>
invoke<void>("delete_kubeconfig", { id });
export const respondToShellApprovalCmd = (approvalId: string, decision: string) =>
invoke<void>("respond_to_shell_approval", { approvalId, decision });
export const listCommandExecutionsCmd = (issueId?: string) =>
invoke<CommandExecution[]>("list_command_executions", {
issueId: issueId ?? null,
});
export const checkKubectlInstalledCmd = () =>
invoke<KubectlStatus>("check_kubectl_installed");
fix(classifier): fix 3 safety bugs, extract const arrays, make tier UI dynamic Bug 1 — Dead multi-word tier3 entries / missing single-token commands parse_single_command() extracts only the first token as `command`, so multi-word entries like "kill -9", "init 0", "service stop" in the tier3 array never matched. Adding the single-token forms "kill", "pkill", "killall", "init" to TIER3_COMMANDS ensures these commands are always denied. Removed all dead multi-word entries. Bug 2 — systemctl Tier 1 special case was dead code systemctl was not in tier1_general, so the block that was supposed to auto-execute `systemctl status` never ran. Moved systemctl handling into its own block (TIER1_SYSTEMCTL_SUBCOMMANDS / TIER2_SYSTEMCTL_SUBCOMMANDS) evaluated before the general tier checks. status, is-active, is-enabled, list-units, list-unit-files → Tier 1; all others → Tier 2. Bug 3 — ldapmodify / ldapdelete / ldapadd misclassified as Tier 1 Both appeared in the old tier1_general and tier2_general arrays; the tier1 check ran first, so LDAP write operations auto-executed. Removed them from tier1. ldapsearch (read-only) remains Tier 1. Dynamic Safety Architecture UI Extracted all tier classification arrays to module-level pub const slices (TIER3_COMMANDS, TIER1_KUBECTL_SUBCOMMANDS, etc.) so both the classifier logic and a new get_classifier_rules() Tauri command share a single source of truth. ShellExecution.tsx now calls getClassifierRulesCmd() on mount and renders the actual command lists in collapsible per-tier cards — any change to the const arrays is automatically reflected in the UI with no manual documentation update needed. Also fixes the cargo fmt CI failure introduced in the previous commit (ClusterClient::new call reformatted to a single line).
2026-06-07 23:15:42 +00:00
export interface ClassifierRules {
tier1_kubectl: string[];
tier1_systemctl: string[];
tier1_proxmox: string[];
tier1_general: string[];
tier2_kubectl: string[];
tier2_systemctl: string[];
tier2_proxmox: string[];
tier2_general: string[];
tier3: string[];
}
export const getClassifierRulesCmd = () =>
invoke<ClassifierRules>("get_classifier_rules");
// ─── Kubernetes Management Types ──────────────────────────────────────────────
export interface ClusterInfo {
id: string;
name: string;
context: string;
cluster_url: string;
}
export interface ContextInfo {
name: string;
cluster: string;
user: string;
}
export interface ResourceInfo {
name: string;
namespace: string;
[key: string]: unknown;
}
export interface PortForwardRequest {
cluster_id: string;
namespace: string;
pod: string;
container_port: number;
local_port?: number;
}
export interface PortForwardResponse {
id: string;
cluster_id: string;
namespace: string;
pod: string;
container_ports: number[];
local_ports: number[];
status: string;
}
feat(k8s): implement clean-room Kubernetes management GUI - Backend: kube module with ClusterClient, PortForwardSession, RefreshRegistry - 7 Tauri IPC commands: add_cluster, remove_cluster, list_clusters, start_port_forward, stop_port_forward, list_port_forwards, delete_port_forward, shutdown_port_forwards - AppState extended with clusters, port_forwards, refresh_registry fields - Version bumped to 1.1.0 in Cargo.toml and package.json - Auto-tag workflow updated to mark releases as draft (pre-release) - Buy Me A Coffee section added to README.md - Fixed changelog workflow to only include current tag commits - Proper kubeconfig YAML parsing with extract_context and extract_server_url - Added kubeconfig content storage in ClusterClient - Updated PortForwardSession to include cluster_name - Frontend GUI components: ClusterList, PortForwardList, AddClusterModal, PortForwardForm, KubernetesPage - TypeScript types and IPC commands for Kubernetes management - Unit tests for Kubernetes IPC commands (6 tests) - All 332 Rust tests passing - All 98 frontend tests passing - TypeScript type checks passing - Project builds successfully in release mode - Committed and pushed to feature/kubernetes-management branch - Command injection vulnerability fixed with regex validation and max length check (253 chars) - stop_port_forward and shutdown_port_forwards properly kill kubectl child processes via async child management - Temp file cleanup implemented with RAII TempFileCleanup struct created before std::fs::write - discover_pods now parses actual kubectl JSON output - ChildWaitHandle implemented with background task for waiting on kubectl child - PortForwardSession uses Arc<TokioMutex<Option<Child>>> for async-safe child management - Port-forward uses kubectl's dynamic port binding (0) instead of TcpListener - Added shutdown_port_forwards command for app shutdown cleanup - Added cleanup effect in App.tsx to call shutdownPortForwardsCmd on unmount - Database CRUD operations for clusters and port_forwards added to db.rs - validate_resource_name uses lazy_static! for cached Regex to prevent ReDoS - Cluster struct updated to store kubeconfig_content directly instead of kubeconfig_id - Cluster model in db/models.rs updated to use kubeconfig_content field - load_clusters and load_port_forwards commands registered in lib.rs - Temp file cleanup moved to background task in ChildWaitHandle to ensure cleanup after kubectl completes - Unused child_id field removed from ChildWaitHandle - Command validation moved to beginning of start_port_forward before any operations - Fixed lint errors: removed unused imports, fixed React hooks order, updated type annotations - Updated eslint.config.js to properly configure file patterns
2026-06-07 01:27:39 +00:00
export interface PodInfo {
name: string;
namespace: string;
feat(k8s): implement clean-room Kubernetes management GUI - Backend: kube module with ClusterClient, PortForwardSession, RefreshRegistry - 7 Tauri IPC commands: add_cluster, remove_cluster, list_clusters, start_port_forward, stop_port_forward, list_port_forwards, delete_port_forward, shutdown_port_forwards - AppState extended with clusters, port_forwards, refresh_registry fields - Version bumped to 1.1.0 in Cargo.toml and package.json - Auto-tag workflow updated to mark releases as draft (pre-release) - Buy Me A Coffee section added to README.md - Fixed changelog workflow to only include current tag commits - Proper kubeconfig YAML parsing with extract_context and extract_server_url - Added kubeconfig content storage in ClusterClient - Updated PortForwardSession to include cluster_name - Frontend GUI components: ClusterList, PortForwardList, AddClusterModal, PortForwardForm, KubernetesPage - TypeScript types and IPC commands for Kubernetes management - Unit tests for Kubernetes IPC commands (6 tests) - All 332 Rust tests passing - All 98 frontend tests passing - TypeScript type checks passing - Project builds successfully in release mode - Committed and pushed to feature/kubernetes-management branch - Command injection vulnerability fixed with regex validation and max length check (253 chars) - stop_port_forward and shutdown_port_forwards properly kill kubectl child processes via async child management - Temp file cleanup implemented with RAII TempFileCleanup struct created before std::fs::write - discover_pods now parses actual kubectl JSON output - ChildWaitHandle implemented with background task for waiting on kubectl child - PortForwardSession uses Arc<TokioMutex<Option<Child>>> for async-safe child management - Port-forward uses kubectl's dynamic port binding (0) instead of TcpListener - Added shutdown_port_forwards command for app shutdown cleanup - Added cleanup effect in App.tsx to call shutdownPortForwardsCmd on unmount - Database CRUD operations for clusters and port_forwards added to db.rs - validate_resource_name uses lazy_static! for cached Regex to prevent ReDoS - Cluster struct updated to store kubeconfig_content directly instead of kubeconfig_id - Cluster model in db/models.rs updated to use kubeconfig_content field - load_clusters and load_port_forwards commands registered in lib.rs - Temp file cleanup moved to background task in ChildWaitHandle to ensure cleanup after kubectl completes - Unused child_id field removed from ChildWaitHandle - Command validation moved to beginning of start_port_forward before any operations - Fixed lint errors: removed unused imports, fixed React hooks order, updated type annotations - Updated eslint.config.js to properly configure file patterns
2026-06-07 01:27:39 +00:00
status: string;
ready: string;
age: string;
fix(kube): resolve automated PR review blockers and warnings Blockers: - Replace serde_yaml::from_str with serde_json::from_str in all 6 parse_*_json functions (parse_namespaces, parse_pods, parse_services, parse_deployments, parse_statefulsets, parse_daemonsets). Update .as_sequence() → .as_array(), .as_mapping() → .as_object(), and mapping iterator patterns throughout. Explicitly type serde_yaml::Value in extract_context/extract_server_url which legitimately parse YAML. Warnings: - Add containers: Vec<String> to PodInfo struct; parse from spec.containers[].name in parse_pods_json - Fix PodList.tsx to use selectedPod.containers instead of [selectedPod.name] - Fix exec_pod: add optional shell param with allowlist validation (sh/bash/ash/dash); correct arg ordering — -c container now placed before -- separator - Handle empty namespace with --all-namespaces in all 5 list commands - Fix dialog overflow: overflow-hidden → overflow-y-auto on inner div - Memoize namespace options with useMemo in ResourceBrowser Lint cleanup (all pre-existing, surfaced by eslint config fix): - Deduplicate eslint.config.js (was doubled to 272 lines); move ignores to standalone global object; allow console.log in cli section - Remove stale .eslintignore (migrated to eslint.config.js) - Remove unused Card/CardTitle imports from Kubernetes list components - Rename unused props to _clusterId/_namespace in DaemonSetList, ServiceList, StatefulSetList - Fix useEffect/useCallback missing deps in Triage and LogUpload - Remove debug console.log from App.tsx provider auto-test - Rename unused hover prop to _hover in TableRow (ui/index.tsx) - Add #[allow(unused_variables)] to Phase 3 stub Tauri commands - Restore get_pod_logs, scale_deployment, restart_deployment, delete_resource, exec_pod to lib.rs handler registration (were accidentally dropped in Phase 3 expansion) All checks pass: cargo clippy -D warnings, tsc --noEmit, eslint --max-warnings 0, 331 Rust tests, 98 frontend tests.
2026-06-07 04:55:44 +00:00
containers: string[];
restarts?: number;
ip?: string;
node?: string;
feat(k8s): implement clean-room Kubernetes management GUI - Backend: kube module with ClusterClient, PortForwardSession, RefreshRegistry - 7 Tauri IPC commands: add_cluster, remove_cluster, list_clusters, start_port_forward, stop_port_forward, list_port_forwards, delete_port_forward, shutdown_port_forwards - AppState extended with clusters, port_forwards, refresh_registry fields - Version bumped to 1.1.0 in Cargo.toml and package.json - Auto-tag workflow updated to mark releases as draft (pre-release) - Buy Me A Coffee section added to README.md - Fixed changelog workflow to only include current tag commits - Proper kubeconfig YAML parsing with extract_context and extract_server_url - Added kubeconfig content storage in ClusterClient - Updated PortForwardSession to include cluster_name - Frontend GUI components: ClusterList, PortForwardList, AddClusterModal, PortForwardForm, KubernetesPage - TypeScript types and IPC commands for Kubernetes management - Unit tests for Kubernetes IPC commands (6 tests) - All 332 Rust tests passing - All 98 frontend tests passing - TypeScript type checks passing - Project builds successfully in release mode - Committed and pushed to feature/kubernetes-management branch - Command injection vulnerability fixed with regex validation and max length check (253 chars) - stop_port_forward and shutdown_port_forwards properly kill kubectl child processes via async child management - Temp file cleanup implemented with RAII TempFileCleanup struct created before std::fs::write - discover_pods now parses actual kubectl JSON output - ChildWaitHandle implemented with background task for waiting on kubectl child - PortForwardSession uses Arc<TokioMutex<Option<Child>>> for async-safe child management - Port-forward uses kubectl's dynamic port binding (0) instead of TcpListener - Added shutdown_port_forwards command for app shutdown cleanup - Added cleanup effect in App.tsx to call shutdownPortForwardsCmd on unmount - Database CRUD operations for clusters and port_forwards added to db.rs - validate_resource_name uses lazy_static! for cached Regex to prevent ReDoS - Cluster struct updated to store kubeconfig_content directly instead of kubeconfig_id - Cluster model in db/models.rs updated to use kubeconfig_content field - load_clusters and load_port_forwards commands registered in lib.rs - Temp file cleanup moved to background task in ChildWaitHandle to ensure cleanup after kubectl completes - Unused child_id field removed from ChildWaitHandle - Command validation moved to beginning of start_port_forward before any operations - Fixed lint errors: removed unused imports, fixed React hooks order, updated type annotations - Updated eslint.config.js to properly configure file patterns
2026-06-07 01:27:39 +00:00
}
export interface ClusterConnectionState {
type: "Connected" | "Disconnected";
error?: string;
}
export interface ClusterConnectionStatus {
status: ClusterConnectionState;
context: string;
}
// ─── Kubernetes Resource Discovery Types ──────────────────────────────────────
export interface NamespaceInfo {
name: string;
status: string;
age: string;
}
export interface ServicePort {
name?: string;
port: number;
target_port?: string;
protocol: string;
}
export interface ServiceInfo {
name: string;
namespace: string;
type: string;
cluster_ip: string;
external_ip?: string;
ports: ServicePort[];
age: string;
selector: Record<string, string>;
}
export interface DeploymentInfo {
name: string;
namespace: string;
ready: string;
up_to_date: string;
available: string;
age: string;
replicas: number;
labels: Record<string, string>;
}
export interface StatefulSetInfo {
name: string;
namespace: string;
ready: string;
age: string;
replicas: number;
labels: Record<string, string>;
}
export interface DaemonSetInfo {
name: string;
namespace: string;
desired: number;
current: number;
ready: number;
up_to_date: number;
available: number;
age: string;
labels: Record<string, string>;
}
export interface NodeMetrics {
name: string;
cpu_usage: string;
memory_usage: string;
cpu_percentage: number;
memory_percentage: number;
age: string;
}
export interface PodMetrics {
name: string;
namespace: string;
cpu_usage: string;
memory_usage: string;
cpu_percentage: number;
memory_percentage: number;
}
export interface LogResponse {
logs: string;
}
export interface ExecResponse {
stdout: string;
stderr: string;
exit_code: number | null;
}
export interface ExecSessionResponse {
session_id: string;
cluster_id: string;
namespace: string;
pod: string;
container?: string;
status: string;
}
// ─── Kubernetes Management Commands ───────────────────────────────────────────
export const addClusterCmd = (id: string, name: string, kubeconfigContent: string) =>
invoke<ClusterInfo>("add_cluster", { id, name, kubeconfig_content: kubeconfigContent });
export const removeClusterCmd = (id: string) =>
invoke<void>("remove_cluster", { id });
fix(kube): bridge kubeconfig storage to in-memory cluster map and fix UI issues Resolves four bugs in the Kubernetes management interface: 1. **Cluster not found error** - commands/kube.rs::list_nodes (and all other kube resource commands) look up clusters from state.clusters (in-memory map) which was never populated from the kubeconfig_files table. Add a new connect_cluster_from_kubeconfig Tauri command that reads the encrypted kubeconfig from the DB, decrypts it, and inserts a ClusterClient into state.clusters. Wire it into KubernetesPage on initial load and cluster change so the in-memory map is always populated before any kube command runs. 2. **Dropdown selection has no effect** - same root cause as #1; activating a kubeconfig only updated the DB flag but never loaded the client into memory. handleClusterChange now calls connectClusterFromKubeconfigCmd after activation. 3. **GUID shown instead of cluster name** - ClusterOverview displayed the raw internal UUID as the page subtitle. Now accepts a clusterName prop (populated from kubeconfig.context) and renders that instead. ClusterDetails similarly changed to show kubeconfig.context in the header, not the UUID. 4. **Bell icon not clickable** - Hotbar bell button had no onClick handler. Add optional onNotifications / notificationCount props; badge count is now dynamic rather than hardcoded. KubernetesPage wires up a notifications dialog showing active cluster context and a link to the Events section. All changes follow TDD: failing tests written first, then implementation.
2026-06-07 22:39:07 +00:00
export const connectClusterFromKubeconfigCmd = (id: string) =>
invoke<void>("connect_cluster_from_kubeconfig", { id });
/** Diagnostic: runs kubectl cluster-info and returns a human-readable summary. */
export const testKubectlConnectionCmd = (clusterId: string) =>
invoke<string>("test_kubectl_connection", { clusterId });
export const listClustersCmd = () =>
invoke<ClusterInfo[]>("list_clusters");
export const startPortForwardCmd = (request: PortForwardRequest) =>
invoke<PortForwardResponse>("start_port_forward", { request });
export const stopPortForwardCmd = (id: string) =>
invoke<void>("stop_port_forward", { id });
export const deletePortForwardCmd = (id: string) =>
invoke<void>("delete_port_forward", { id });
export const listPortForwardsCmd = () =>
invoke<PortForwardResponse[]>("list_port_forwards");
export const shutdownPortForwardsCmd = () =>
invoke<void>("shutdown_port_forwards");
feat(k8s): implement clean-room Kubernetes management GUI - Backend: kube module with ClusterClient, PortForwardSession, RefreshRegistry - 7 Tauri IPC commands: add_cluster, remove_cluster, list_clusters, start_port_forward, stop_port_forward, list_port_forwards, delete_port_forward, shutdown_port_forwards - AppState extended with clusters, port_forwards, refresh_registry fields - Version bumped to 1.1.0 in Cargo.toml and package.json - Auto-tag workflow updated to mark releases as draft (pre-release) - Buy Me A Coffee section added to README.md - Fixed changelog workflow to only include current tag commits - Proper kubeconfig YAML parsing with extract_context and extract_server_url - Added kubeconfig content storage in ClusterClient - Updated PortForwardSession to include cluster_name - Frontend GUI components: ClusterList, PortForwardList, AddClusterModal, PortForwardForm, KubernetesPage - TypeScript types and IPC commands for Kubernetes management - Unit tests for Kubernetes IPC commands (6 tests) - All 332 Rust tests passing - All 98 frontend tests passing - TypeScript type checks passing - Project builds successfully in release mode - Committed and pushed to feature/kubernetes-management branch - Command injection vulnerability fixed with regex validation and max length check (253 chars) - stop_port_forward and shutdown_port_forwards properly kill kubectl child processes via async child management - Temp file cleanup implemented with RAII TempFileCleanup struct created before std::fs::write - discover_pods now parses actual kubectl JSON output - ChildWaitHandle implemented with background task for waiting on kubectl child - PortForwardSession uses Arc<TokioMutex<Option<Child>>> for async-safe child management - Port-forward uses kubectl's dynamic port binding (0) instead of TcpListener - Added shutdown_port_forwards command for app shutdown cleanup - Added cleanup effect in App.tsx to call shutdownPortForwardsCmd on unmount - Database CRUD operations for clusters and port_forwards added to db.rs - validate_resource_name uses lazy_static! for cached Regex to prevent ReDoS - Cluster struct updated to store kubeconfig_content directly instead of kubeconfig_id - Cluster model in db/models.rs updated to use kubeconfig_content field - load_clusters and load_port_forwards commands registered in lib.rs - Temp file cleanup moved to background task in ChildWaitHandle to ensure cleanup after kubectl completes - Unused child_id field removed from ChildWaitHandle - Command validation moved to beginning of start_port_forward before any operations - Fixed lint errors: removed unused imports, fixed React hooks order, updated type annotations - Updated eslint.config.js to properly configure file patterns
2026-06-07 01:27:39 +00:00
export const testClusterConnectionCmd = (clusterId: string) =>
invoke<ClusterConnectionStatus>("test_cluster_connection", { clusterId });
export const discoverPodsCmd = (clusterId: string, namespace: string) =>
invoke<PodInfo[]>("discover_pods", { clusterId, namespace });
// ─── Kubernetes Resource Discovery Commands ───────────────────────────────────
export const listNamespacesCmd = (clusterId: string) =>
invoke<NamespaceInfo[]>("list_namespaces", { clusterId });
export const listPodsCmd = (clusterId: string, namespace: string) =>
invoke<PodInfo[]>("list_pods", { clusterId, namespace });
export const listServicesCmd = (clusterId: string, namespace: string) =>
invoke<ServiceInfo[]>("list_services", { clusterId, namespace });
export const listDeploymentsCmd = (clusterId: string, namespace: string) =>
invoke<DeploymentInfo[]>("list_deployments", { clusterId, namespace });
export const listStatefulsetsCmd = (clusterId: string, namespace: string) =>
invoke<StatefulSetInfo[]>("list_statefulsets", { clusterId, namespace });
export const listDaemonsetsCmd = (clusterId: string, namespace: string) =>
invoke<DaemonSetInfo[]>("list_daemonsets", { clusterId, namespace });
// ─── Kubernetes Resource Management Commands ──────────────────────────────────
export const getPodLogsCmd = (clusterId: string, namespace: string, podName: string, containerName: string) =>
invoke<LogResponse>("get_pod_logs", { clusterId, namespace, podName, containerName });
export const scaleDeploymentCmd = (clusterId: string, namespace: string, deploymentName: string, replicas: number) =>
invoke<void>("scale_deployment", { clusterId, namespace, deploymentName, replicas });
export const restartDeploymentCmd = (clusterId: string, namespace: string, deploymentName: string) =>
invoke<void>("restart_deployment", { clusterId, namespace, deploymentName });
export const deleteResourceCmd = (clusterId: string, resourceType: string, namespace: string, resourceName: string) =>
invoke<void>("delete_resource", { clusterId, resourceType, namespace, resourceName });
fix(kube): resolve automated PR review blockers and warnings Blockers: - Replace serde_yaml::from_str with serde_json::from_str in all 6 parse_*_json functions (parse_namespaces, parse_pods, parse_services, parse_deployments, parse_statefulsets, parse_daemonsets). Update .as_sequence() → .as_array(), .as_mapping() → .as_object(), and mapping iterator patterns throughout. Explicitly type serde_yaml::Value in extract_context/extract_server_url which legitimately parse YAML. Warnings: - Add containers: Vec<String> to PodInfo struct; parse from spec.containers[].name in parse_pods_json - Fix PodList.tsx to use selectedPod.containers instead of [selectedPod.name] - Fix exec_pod: add optional shell param with allowlist validation (sh/bash/ash/dash); correct arg ordering — -c container now placed before -- separator - Handle empty namespace with --all-namespaces in all 5 list commands - Fix dialog overflow: overflow-hidden → overflow-y-auto on inner div - Memoize namespace options with useMemo in ResourceBrowser Lint cleanup (all pre-existing, surfaced by eslint config fix): - Deduplicate eslint.config.js (was doubled to 272 lines); move ignores to standalone global object; allow console.log in cli section - Remove stale .eslintignore (migrated to eslint.config.js) - Remove unused Card/CardTitle imports from Kubernetes list components - Rename unused props to _clusterId/_namespace in DaemonSetList, ServiceList, StatefulSetList - Fix useEffect/useCallback missing deps in Triage and LogUpload - Remove debug console.log from App.tsx provider auto-test - Rename unused hover prop to _hover in TableRow (ui/index.tsx) - Add #[allow(unused_variables)] to Phase 3 stub Tauri commands - Restore get_pod_logs, scale_deployment, restart_deployment, delete_resource, exec_pod to lib.rs handler registration (were accidentally dropped in Phase 3 expansion) All checks pass: cargo clippy -D warnings, tsc --noEmit, eslint --max-warnings 0, 331 Rust tests, 98 frontend tests.
2026-06-07 04:55:44 +00:00
export const execPodCmd = (clusterId: string, namespace: string, podName: string, containerName: string, command: string, shell?: string) =>
invoke<ExecResponse>("exec_pod", { clusterId, namespace, podName, containerName, shell, command });
// ─── Additional Kubernetes Resource Discovery Types ───────────────────────────
export interface ReplicaSetInfo {
name: string;
namespace: string;
replicas: number;
ready: string;
age: string;
labels: Record<string, string>;
}
export interface JobInfo {
name: string;
namespace: string;
completions: string;
duration: string;
age: string;
labels: Record<string, string>;
}
export interface CronJobInfo {
name: string;
namespace: string;
schedule: string;
active: number;
last_schedule: string;
age: string;
labels: Record<string, string>;
}
export interface ConfigMapInfo {
name: string;
namespace: string;
data_keys: number;
age: string;
}
export interface SecretInfo {
name: string;
namespace: string;
type: string;
data_keys: number;
age: string;
}
export interface NodeInfo {
name: string;
status: string;
roles: string;
version: string;
internal_ip: string;
external_ip?: string;
os_image: string;
kernel_version: string;
kubelet_version: string;
age: string;
}
export interface EventInfo {
name: string;
namespace: string;
event_type: string;
reason: string;
object: string;
count: number;
first_seen: string;
last_seen: string;
message: string;
}
export interface IngressInfo {
name: string;
namespace: string;
class?: string;
host: string;
addresses: string[];
age: string;
}
export interface PersistentVolumeClaimInfo {
name: string;
namespace: string;
status: string;
volume: string;
capacity: string;
access_modes: string[];
age: string;
}
export interface PersistentVolumeInfo {
name: string;
status: string;
capacity: string;
access_modes: string[];
reclaim_policy: string;
storage_class: string;
age: string;
}
export interface ServiceAccountInfo {
name: string;
namespace: string;
secrets: number;
age: string;
}
export interface RoleInfo {
name: string;
namespace: string;
age: string;
}
export interface ClusterRoleInfo {
name: string;
age: string;
}
export interface RoleBindingInfo {
name: string;
namespace: string;
role: string;
age: string;
}
export interface ClusterRoleBindingInfo {
name: string;
cluster_role: string;
age: string;
}
export interface HorizontalPodAutoscalerInfo {
name: string;
namespace: string;
min_replicas: number;
max_replicas: number;
current_replicas: number;
desired_replicas: number;
age: string;
}
// ─── Additional Kubernetes Resource Discovery Commands ────────────────────────
export const listReplicasetsCmd = (clusterId: string, namespace: string) =>
invoke<ReplicaSetInfo[]>("list_replicasets", { clusterId, namespace });
export const listJobsCmd = (clusterId: string, namespace: string) =>
invoke<JobInfo[]>("list_jobs", { clusterId, namespace });
export const listCronjobsCmd = (clusterId: string, namespace: string) =>
invoke<CronJobInfo[]>("list_cronjobs", { clusterId, namespace });
export const listConfigmapsCmd = (clusterId: string, namespace: string) =>
invoke<ConfigMapInfo[]>("list_configmaps", { clusterId, namespace });
export const listSecretsCmd = (clusterId: string, namespace: string) =>
invoke<SecretInfo[]>("list_secrets", { clusterId, namespace });
export const listNodesCmd = (clusterId: string) =>
invoke<NodeInfo[]>("list_nodes", { clusterId });
export const listEventsCmd = (clusterId: string, namespace?: string) =>
invoke<EventInfo[]>("list_events", { clusterId, namespace });
export const listIngressesCmd = (clusterId: string, namespace: string) =>
invoke<IngressInfo[]>("list_ingresses", { clusterId, namespace });
export const listPersistentvolumeclaimsCmd = (clusterId: string, namespace: string) =>
invoke<PersistentVolumeClaimInfo[]>("list_persistentvolumeclaims", { clusterId, namespace });
export const listPersistentvolumesCmd = (clusterId: string) =>
invoke<PersistentVolumeInfo[]>("list_persistentvolumes", { clusterId });
export const listServiceaccountsCmd = (clusterId: string, namespace: string) =>
invoke<ServiceAccountInfo[]>("list_serviceaccounts", { clusterId, namespace });
export const listRolesCmd = (clusterId: string, namespace: string) =>
invoke<RoleInfo[]>("list_roles", { clusterId, namespace });
export const listClusterrolesCmd = (clusterId: string) =>
invoke<ClusterRoleInfo[]>("list_clusterroles", { clusterId });
export const listRolebindingsCmd = (clusterId: string, namespace: string) =>
invoke<RoleBindingInfo[]>("list_rolebindings", { clusterId, namespace });
export const listClusterrolebindingsCmd = (clusterId: string) =>
invoke<ClusterRoleBindingInfo[]>("list_clusterrolebindings", { clusterId });
export const listHorizontalpodautoscalersCmd = (clusterId: string, namespace: string) =>
invoke<HorizontalPodAutoscalerInfo[]>("list_horizontalpodautoscalers", { clusterId, namespace });
feat(kubernetes): implement Lens Desktop v5 feature-parity UI Complete overhaul of the Kubernetes management page from a basic config panel into a full Lens-style IDE shell with 26 resource types, real-time data, and a comprehensive test suite. Layout & navigation: - Rewrite KubernetesPage as a Lens v5-style shell: collapsible sidebar (Workloads / Services & Networking / Config & Storage / Access Control / Cluster), top hotbar with cluster+namespace selectors, Ctrl+K command palette - All 26 resource types now accessible via sidebar navigation (previously 5) New resource types (Rust + TypeScript + React): - StorageClasses, NetworkPolicies, ResourceQuotas, LimitRanges - 4 new Tauri commands registered in generate_handler![] Component implementations (replacing stubs with real IPC): - Terminal: full xterm.js with multi-tab sessions and exec_pod IPC - YamlEditor: Monaco editor with YAML syntax highlighting - MetricsChart: recharts LineChart/BarChart - ClusterOverview: live node/pod/deployment/namespace counts - ClusterDetails: real kubeconfig + node data - PodDetail, DeploymentDetail, ServiceDetail, ConfigMapDetail, SecretDetail: all connected to real IPC data, zero hardcoded values - CreateResourceModal, EditResourceModal: wired to createResourceCmd / editResourceCmd - RbacViewer: live data from 4 RBAC IPC commands - RbacEditor: create roles/cluster-roles via YAML editor - CommandPalette: 12 real navigation commands, keyboard nav Dependencies added: xterm@5, xterm-addon-fit, xterm-addon-web-links, @monaco-editor/react@4, recharts@2 Tooling: - Replace eslint-plugin-react (incompatible with ESLint 10) with @eslint-react/eslint-plugin; fix eslint.config.js for flat config - Fix pre-existing hoisting lint errors in Security.tsx, PortForwardForm.tsx - Fix eventBus.ts: replace all `any` generics with `unknown` Tests: 251 passing across 35 test files (was 94/19) - 16 new test files covering all new and fixed components (TDD) - npx tsc --noEmit: 0 errors - cargo clippy -- -D warnings: 0 warnings - cargo fmt --check: passes - eslint src/ --max-warnings 0: 0 issues
2026-06-07 21:41:28 +00:00
// ─── Additional Lens Resource Types ───────────────────────────────────────────
export interface StorageClassInfo {
name: string;
provisioner: string;
reclaim_policy: string;
volume_binding_mode: string;
allow_volume_expansion: boolean;
age: string;
}
export interface NetworkPolicyInfo {
name: string;
namespace: string;
pod_selector: string;
policy_types: string[];
age: string;
}
export interface ResourceQuotaInfo {
name: string;
namespace: string;
request_cpu: string;
request_memory: string;
limit_cpu: string;
limit_memory: string;
age: string;
}
export interface LimitRangeInfo {
name: string;
namespace: string;
limit_count: number;
age: string;
}
export const listStorageclassesCmd = (clusterId: string) =>
invoke<StorageClassInfo[]>("list_storageclasses", { clusterId });
export const listNetworkpoliciesCmd = (clusterId: string, namespace: string) =>
invoke<NetworkPolicyInfo[]>("list_networkpolicies", { clusterId, namespace });
export const listResourcequotasCmd = (clusterId: string, namespace: string) =>
invoke<ResourceQuotaInfo[]>("list_resourcequotas", { clusterId, namespace });
export const listLimitrangesCmd = (clusterId: string, namespace: string) =>
invoke<LimitRangeInfo[]>("list_limitranges", { clusterId, namespace });
// ─── Additional Kubernetes Resource Management Commands ───────────────────────
export const cordonNodeCmd = (clusterId: string, nodeName: string) =>
invoke<void>("cordon_node", { clusterId, nodeName });
export const uncordonNodeCmd = (clusterId: string, nodeName: string) =>
invoke<void>("uncordon_node", { clusterId, nodeName });
export const drainNodeCmd = (clusterId: string, nodeName: string) =>
invoke<void>("drain_node", { clusterId, nodeName });
export const rollbackDeploymentCmd = (clusterId: string, namespace: string, deploymentName: string) =>
invoke<void>("rollback_deployment", { clusterId, namespace, deploymentName });
export const createResourceCmd = (clusterId: string, namespace: string, resourceType: string, yamlContent: string) =>
invoke<void>("create_resource", { clusterId, namespace, resourceType, yamlContent });
export const editResourceCmd = (clusterId: string, namespace: string, resourceType: string, resourceName: string, yamlContent: string) =>
invoke<void>("edit_resource", { clusterId, namespace, resourceType, resourceName, yamlContent });
// ─── Missing Resource Types ───────────────────────────────────────────────────
export interface ReplicationControllerInfo {
name: string;
namespace: string;
desired: number;
ready: number;
current: number;
age: string;
}
export interface PodDisruptionBudgetInfo {
name: string;
namespace: string;
min_available: string;
max_unavailable: string;
disruptions_allowed: number;
age: string;
}
export interface PriorityClassInfo {
name: string;
value: number;
global_default: boolean;
age: string;
}
export interface RuntimeClassInfo {
name: string;
handler: string;
age: string;
}
export interface LeaseInfo {
name: string;
namespace: string;
holder: string;
age: string;
}
export interface WebhookConfigInfo {
name: string;
webhooks: number;
age: string;
}
export interface EndpointInfo {
name: string;
namespace: string;
addresses: string[];
ports: string[];
age: string;
}
export interface EndpointSliceInfo {
name: string;
namespace: string;
address_type: string;
endpoints: number;
ports: string[];
age: string;
}
export interface IngressClassInfo {
name: string;
controller: string;
is_default: boolean;
age: string;
}
export interface NamespaceResourceInfo {
name: string;
status: string;
age: string;
}
// ─── Helm Types ───────────────────────────────────────────────────────────────
export interface HelmRepository {
name: string;
url: string;
}
export interface HelmChart {
name: string;
chart_version: string;
app_version: string;
description: string;
repository: string;
}
export interface HelmRelease {
name: string;
namespace: string;
chart: string;
chart_version: string;
app_version: string;
status: string;
updated: string;
}
// ─── Custom Resource / CRD Types ─────────────────────────────────────────────
export interface PrinterColumn {
name: string;
json_path: string;
type: string;
description?: string;
priority: number;
}
export interface CrdVersion {
name: string;
served: boolean;
storage: boolean;
printer_columns: PrinterColumn[];
}
export interface CrdInfo {
name: string;
group: string;
version: string;
versions: CrdVersion[];
kind: string;
plural: string;
scope: string;
age: string;
}
export interface CustomResourceInfo {
name: string;
namespace: string;
age: string;
additional_columns: Record<string, string>;
}
// ─── Resource Actions ─────────────────────────────────────────────────────────
export interface DescribeResponse {
output: string;
}
export interface LogStreamConfig {
cluster_id: string;
namespace: string;
pod_name: string;
container_name: string;
follow: boolean;
timestamps: boolean;
tail_lines?: number;
}
// ─── New Resource List Commands ───────────────────────────────────────────────
export const listReplicationcontrollersCmd = (clusterId: string, namespace: string) =>
invoke<ReplicationControllerInfo[]>("list_replicationcontrollers", { clusterId, namespace });
export const listPoddisruptionbudgetsCmd = (clusterId: string, namespace: string) =>
invoke<PodDisruptionBudgetInfo[]>("list_poddisruptionbudgets", { clusterId, namespace });
export const listPriorityclassesCmd = (clusterId: string) =>
invoke<PriorityClassInfo[]>("list_priorityclasses", { clusterId });
export const listRuntimeclassesCmd = (clusterId: string) =>
invoke<RuntimeClassInfo[]>("list_runtimeclasses", { clusterId });
export const listLeasesCmd = (clusterId: string, namespace: string) =>
invoke<LeaseInfo[]>("list_leases", { clusterId, namespace });
export const listMutatingwebhookconfigurationsCmd = (clusterId: string) =>
invoke<WebhookConfigInfo[]>("list_mutatingwebhookconfigurations", { clusterId });
export const listValidatingwebhookconfigurationsCmd = (clusterId: string) =>
invoke<WebhookConfigInfo[]>("list_validatingwebhookconfigurations", { clusterId });
export const listEndpointsCmd = (clusterId: string, namespace: string) =>
invoke<EndpointInfo[]>("list_endpoints", { clusterId, namespace });
export const listEndpointslicesCmd = (clusterId: string, namespace: string) =>
invoke<EndpointSliceInfo[]>("list_endpointslices", { clusterId, namespace });
export const listIngressclassesCmd = (clusterId: string) =>
invoke<IngressClassInfo[]>("list_ingressclasses", { clusterId });
export const listNamespacesResourceCmd = (clusterId: string) =>
invoke<NamespaceResourceInfo[]>("list_namespaces_resource", { clusterId });
export const createNamespaceCmd = (clusterId: string, name: string) =>
invoke<void>("create_namespace", { clusterId, name });
export const deleteNamespaceCmd = (clusterId: string, name: string) =>
invoke<void>("delete_namespace", { clusterId, name });
// ─── Resource Action Commands ─────────────────────────────────────────────────
export const attachPodCmd = (clusterId: string, namespace: string, podName: string, containerName: string) =>
invoke<ExecSessionResponse>("attach_pod", { clusterId, namespace, podName, containerName });
export const forceDeleteResourceCmd = (clusterId: string, resourceType: string, namespace: string, resourceName: string) =>
invoke<void>("force_delete_resource", { clusterId, resourceType, namespace, resourceName });
export const describeResourceCmd = (clusterId: string, resourceType: string, namespace: string, resourceName: string) =>
invoke<DescribeResponse>("describe_resource", { clusterId, resourceType, namespace, resourceName });
export const getResourceYamlCmd = (clusterId: string, resourceType: string, namespace: string, resourceName: string) =>
invoke<string>("get_resource_yaml", { clusterId, resourceType, namespace, resourceName });
export const restartStatefulsetCmd = (clusterId: string, namespace: string, name: string) =>
invoke<void>("restart_statefulset", { clusterId, namespace, name });
export const restartDaemonsetCmd = (clusterId: string, namespace: string, name: string) =>
invoke<void>("restart_daemonset", { clusterId, namespace, name });
export const scaleStatefulsetCmd = (clusterId: string, namespace: string, name: string, replicas: number) =>
invoke<void>("scale_statefulset", { clusterId, namespace, name, replicas });
export const scaleReplicasetCmd = (clusterId: string, namespace: string, name: string, replicas: number) =>
invoke<void>("scale_replicaset", { clusterId, namespace, name, replicas });
export const scaleReplicationcontrollerCmd = (clusterId: string, namespace: string, name: string, replicas: number) =>
invoke<void>("scale_replicationcontroller", { clusterId, namespace, name, replicas });
export const suspendCronjobCmd = (clusterId: string, namespace: string, name: string) =>
invoke<void>("suspend_cronjob", { clusterId, namespace, name });
export const resumeCronjobCmd = (clusterId: string, namespace: string, name: string) =>
invoke<void>("resume_cronjob", { clusterId, namespace, name });
export const triggerCronjobCmd = (clusterId: string, namespace: string, name: string) =>
invoke<void>("trigger_cronjob", { clusterId, namespace, name });
// ─── Log Streaming Commands ───────────────────────────────────────────────────
export const streamPodLogsCmd = (config: LogStreamConfig) =>
invoke<string>("stream_pod_logs", { config });
export const stopLogStreamCmd = (streamId: string) =>
invoke<void>("stop_log_stream", { streamId });
// ─── Helm Commands ────────────────────────────────────────────────────────────
export const helmListReposCmd = (clusterId: string) =>
invoke<HelmRepository[]>("helm_list_repos", { clusterId });
export const helmAddRepoCmd = (clusterId: string, name: string, url: string) =>
invoke<void>("helm_add_repo", { clusterId, name, url });
export const helmUpdateReposCmd = (clusterId: string) =>
invoke<void>("helm_update_repos", { clusterId });
export const helmSearchRepoCmd = (clusterId: string, query: string) =>
invoke<HelmChart[]>("helm_search_repo", { clusterId, query });
export const helmListReleasesCmd = (clusterId: string, namespace: string) =>
invoke<HelmRelease[]>("helm_list_releases", { clusterId, namespace });
export const helmUninstallCmd = (clusterId: string, namespace: string, releaseName: string) =>
invoke<void>("helm_uninstall", { clusterId, namespace, releaseName });
export const helmRollbackCmd = (clusterId: string, namespace: string, releaseName: string, revision?: number) =>
invoke<void>("helm_rollback", { clusterId, namespace, releaseName, revision });
// ─── CRD / Custom Resource Commands ──────────────────────────────────────────
export const listCrdsCmd = (clusterId: string) =>
invoke<CrdInfo[]>("list_crds", { clusterId });
export const listCustomResourcesCmd = (clusterId: string, group: string, version: string, resource: string, namespace: string) =>
invoke<CustomResourceInfo[]>("list_custom_resources", { clusterId, group, version, resource, namespace });
// ─── PTY Terminal Commands ────────────────────────────────────────────────────
export interface PtySessionInfo {
session_id: string;
cluster_id: string;
namespace: string;
pod_name: string;
container_name: string | null;
session_type: "exec" | "attach";
}
export const startPtyExecSessionCmd = (
clusterId: string,
namespace: string,
podName: string,
containerName: string | null,
_shell: string
) =>
invoke<string>("start_pty_exec_session", {
clusterId,
namespace,
pod: podName,
container: containerName,
});
export const startPtyAttachSessionCmd = (
clusterId: string,
namespace: string,
podName: string,
containerName: string | null
) =>
invoke<string>("start_pty_attach_session", {
clusterId,
namespace,
pod: podName,
container: containerName,
});
export const sendPtyStdinCmd = (sessionId: string, data: string) =>
invoke<void>("send_pty_stdin", { sessionId, data });
export const resizePtySessionCmd = (sessionId: string, rows: number, cols: number) =>
invoke<void>("resize_pty_session", { sessionId, rows, cols });
export const terminatePtySessionCmd = (sessionId: string) =>
invoke<void>("terminate_pty_session", { sessionId });
export const listPtySessionsCmd = () => invoke<PtySessionInfo[]>("list_pty_sessions", {});
// ─── Metrics ─────────────────────────────────────────────────────────────────
export interface ContainerMetrics {
name: string;
cpu: string;
memory: string;
}
export interface PodMetrics {
name: string;
namespace: string;
containers: ContainerMetrics[];
cpu: string;
memory: string;
}
export interface NodeMetrics {
name: string;
cpu: string;
memory: string;
cpu_percent: number;
memory_percent: number;
}
export const getPodMetricsCmd = (clusterId: string, namespace: string) =>
invoke<PodMetrics[]>("get_pod_metrics", { clusterId, namespace });
export const getNodeMetricsCmd = (clusterId: string) =>
invoke<NodeMetrics[]>("get_node_metrics", { clusterId });
// ─── Proxmox Management Types ─────────────────────────────────────────────────
export interface ProxmoxClusterInfo {
id: string;
name: string;
clusterType: "ve" | "pbs";
url: string;
port: number;
username: string;
createdAt: string;
updatedAt: string;
}
// ─── Proxmox Management Commands ──────────────────────────────────────────────
export const addProxmoxClusterCmd = (
id: string,
name: string,
clusterType: "ve" | "pbs",
url: string,
port: number,
username: string,
password: string
) =>
invoke<ProxmoxClusterInfo>("add_proxmox_cluster", {
id,
name,
cluster_type: clusterType,
connection: { url, port },
username,
password,
});
export const removeProxmoxClusterCmd = (id: string) =>
invoke<void>("remove_proxmox_cluster", { id });
export const listProxmoxClustersCmd = () =>
invoke<ProxmoxClusterInfo[]>("list_proxmox_clusters");
export const getProxmoxClusterCmd = (id: string) =>
invoke<ProxmoxClusterInfo | null>("get_proxmox_cluster", { id });