tftsr-devops_investigation/src-tauri/src/docs/postmortem.rs

249 lines
8.8 KiB
Rust
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
use crate::db::models::IssueDetail;
pub fn generate_postmortem_markdown(detail: &IssueDetail) -> String {
let issue = &detail.issue;
let mut md = String::new();
md.push_str(&format!(
"# Blameless Post-Mortem: {title}\n\n",
title = issue.title
));
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
// Header metadata
md.push_str("## Metadata\n\n");
md.push_str(&format!(
"- **Date:** {created_at}\n",
created_at = issue.created_at
));
md.push_str(&format!(
"- **Severity:** {severity}\n",
severity = issue.severity
));
md.push_str(&format!(
"- **Category:** {category}\n",
category = issue.category
));
md.push_str(&format!("- **Status:** {status}\n", status = issue.status));
md.push_str(&format!(
"- **Last Updated:** {updated_at}\n",
updated_at = issue.updated_at
));
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
md.push_str(&format!(
"- **Assigned To:** {}\n",
2026-03-15 17:43:46 +00:00
if issue.assigned_to.is_empty() {
"_Unassigned_"
} else {
&issue.assigned_to
}
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
));
md.push_str("- **Authors:** _[Add authors]_\n");
md.push_str("- **Reviewers:** _[Add reviewers]_\n\n");
// Executive Summary
md.push_str("## Executive Summary\n\n");
if !issue.description.is_empty() {
md.push_str(&issue.description);
md.push_str("\n\n");
} else {
md.push_str("_Provide a brief executive summary of the incident._\n\n");
}
// Impact
md.push_str("## Impact\n\n");
md.push_str("- **Duration:** _[How long did the incident last?]_\n");
md.push_str("- **Users Affected:** _[Number/percentage of affected users]_\n");
md.push_str("- **Revenue Impact:** _[Financial impact, if applicable]_\n");
md.push_str("- **SLA Impact:** _[Were any SLAs breached?]_\n\n");
// Timeline
md.push_str("## Timeline\n\n");
md.push_str("| Time (UTC) | Event |\n");
md.push_str("|------------|-------|\n");
md.push_str(&format!(
"| {created_at} | Issue created |\n",
created_at = issue.created_at
));
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
if let Some(ref resolved) = issue.resolved_at {
md.push_str(&format!("| {resolved} | Issue resolved |\n"));
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
}
md.push_str("| _HH:MM_ | _[Add additional timeline events]_ |\n\n");
// Root Cause Analysis
md.push_str("## Root Cause Analysis\n\n");
if detail.resolution_steps.is_empty() {
md.push_str("### 5 Whys\n\n");
md.push_str("1. **Why?** _[First question]_ -> _[Answer]_\n");
md.push_str("2. **Why?** _[Second question]_ -> _[Answer]_\n");
md.push_str("3. **Why?** _[Third question]_ -> _[Answer]_\n");
md.push_str("4. **Why?** _[Fourth question]_ -> _[Answer]_\n");
md.push_str("5. **Why?** _[Fifth question]_ -> _[Answer]_\n\n");
} else {
md.push_str("### 5 Whys\n\n");
for step in &detail.resolution_steps {
let answer = if step.answer.is_empty() {
"_Awaiting answer_"
} else {
&step.answer
};
md.push_str(&format!(
"{}. **Why?** {} -> {}\n",
step.step_order, step.why_question, answer
));
}
md.push('\n');
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
if let Some(last) = detail.resolution_steps.last() {
if !last.answer.is_empty() {
md.push_str(&format!(
"**Root Cause:** {answer}\n\n",
answer = last.answer
));
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
}
}
}
// Contributing Factors
md.push_str("## Contributing Factors\n\n");
md.push_str(
"_This is a blameless post-mortem. Focus on systems and processes, not individuals._\n\n",
);
md.push_str("- _[Factor 1: e.g., Insufficient monitoring coverage]_\n");
md.push_str("- _[Factor 2: e.g., Missing automated failover]_\n");
md.push_str("- _[Factor 3: e.g., Deployment timing during peak hours]_\n\n");
// What Went Well
md.push_str("## What Went Well\n\n");
md.push_str("- _[e.g., Quick detection through existing alerts]_\n");
md.push_str("- _[e.g., Effective cross-team collaboration]_\n");
md.push_str("- _[e.g., Smooth communication with stakeholders]_\n\n");
// What Could Be Improved
md.push_str("## What Could Be Improved\n\n");
md.push_str("- _[e.g., Faster escalation path]_\n");
md.push_str("- _[e.g., Better runbook documentation]_\n");
md.push_str("- _[e.g., More comprehensive testing]_\n\n");
// Action Items
md.push_str("## Action Items\n\n");
md.push_str("| Priority | Action | Owner | Due Date | Status |\n");
md.push_str("|----------|--------|-------|----------|--------|\n");
md.push_str("| P0 | _[Critical fix]_ | _[Owner]_ | _[Date]_ | Open |\n");
md.push_str("| P1 | _[Prevention measure]_ | _[Owner]_ | _[Date]_ | Open |\n");
md.push_str("| P2 | _[Monitoring improvement]_ | _[Owner]_ | _[Date]_ | Open |\n\n");
// Log Files
if !detail.log_files.is_empty() {
md.push_str("## Appendix: Log Files\n\n");
for lf in &detail.log_files {
md.push_str(&format!(
"- `{}` ({} bytes, redacted: {})\n",
lf.file_name,
lf.file_size,
if lf.redacted { "yes" } else { "no" }
));
}
md.push('\n');
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
}
md.push_str("---\n\n");
md.push_str(&format!(
"_Generated by TFTSR IT Triage on {}_\n",
chrono::Utc::now().format("%Y-%m-%d %H:%M UTC")
));
md
}
#[cfg(test)]
mod tests {
use super::*;
use crate::db::models::{Issue, IssueDetail, ResolutionStep};
fn make_test_detail() -> IssueDetail {
IssueDetail {
issue: Issue {
id: "pm-456".to_string(),
title: "Payment processing outage".to_string(),
description: "Payment gateway returning 503 for all transactions.".to_string(),
severity: "critical".to_string(),
status: "resolved".to_string(),
category: "payments".to_string(),
source: "monitoring".to_string(),
created_at: "2025-02-10 08:00:00".to_string(),
updated_at: "2025-02-10 14:00:00".to_string(),
resolved_at: Some("2025-02-10 12:30:00".to_string()),
assigned_to: "payments-team".to_string(),
tags: "[]".to_string(),
},
log_files: vec![],
resolution_steps: vec![ResolutionStep {
id: "rs-pm-1".to_string(),
issue_id: "pm-456".to_string(),
step_order: 1,
why_question: "Why did payments fail?".to_string(),
answer: "Gateway certificate expired.".to_string(),
evidence: "SSL handshake failure in logs.".to_string(),
created_at: "2025-02-10 09:00:00".to_string(),
}],
conversations: vec![],
}
}
#[test]
fn test_postmortem_contains_blameless_title() {
let md = generate_postmortem_markdown(&make_test_detail());
assert!(md.contains("# Blameless Post-Mortem: Payment processing outage"));
}
#[test]
fn test_postmortem_contains_metadata() {
let md = generate_postmortem_markdown(&make_test_detail());
assert!(md.contains("- **Severity:** critical"));
assert!(md.contains("- **Category:** payments"));
assert!(md.contains("- **Assigned To:** payments-team"));
}
#[test]
fn test_postmortem_contains_executive_summary() {
let md = generate_postmortem_markdown(&make_test_detail());
assert!(md.contains("Payment gateway returning 503"));
}
#[test]
fn test_postmortem_contains_timeline_with_resolved() {
let md = generate_postmortem_markdown(&make_test_detail());
assert!(md.contains("2025-02-10 08:00:00"));
assert!(md.contains("2025-02-10 12:30:00"));
assert!(md.contains("Issue resolved"));
}
#[test]
fn test_postmortem_contains_five_whys() {
let md = generate_postmortem_markdown(&make_test_detail());
assert!(md.contains("Why did payments fail?"));
assert!(md.contains("Gateway certificate expired."));
}
#[test]
fn test_postmortem_contains_blameless_reminder() {
let md = generate_postmortem_markdown(&make_test_detail());
assert!(md.contains("blameless post-mortem"));
}
#[test]
fn test_postmortem_empty_description_shows_placeholder() {
let mut detail = make_test_detail();
detail.issue.description = String::new();
let md = generate_postmortem_markdown(&detail);
assert!(md.contains("Provide a brief executive summary"));
}
#[test]
fn test_postmortem_action_items_table() {
let md = generate_postmortem_markdown(&make_test_detail());
assert!(md.contains("| Priority | Action | Owner | Due Date | Status |"));
assert!(md.contains("| P0 |"));
}
}