tftsr-devops_investigation/src/lib/tauriCommands.ts

1223 lines
36 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");
// ─── 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;
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[];
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 });
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 });