docs: sync from docs/wiki/ at commit 74f56b6a

Gitea Actions 2026-06-05 15:30:40 +00:00
parent 05b4c5504b
commit ca09347f58
6 changed files with 895 additions and 12 deletions

@ -90,16 +90,49 @@ Uses OpenAI-compatible request/response format.
| Field | Value | | Field | Value |
|-------|-------| |-------|-------|
| `config.name` | `"ollama"` | | `config.name` | `"ollama"` |
| Default URL | `http://localhost:11434/api/chat` | | Default URL | `http://localhost:11434` |
| Auth | None | | Auth | None |
| Max tokens | No limit enforced | | Max tokens | No limit enforced |
| **Tool Calling** | ✅ **Fully Supported** (v1.0.7+) |
| Timeout | 180s (tool calling), 60s (regular chat) |
| Retry Logic | 3 attempts with 2s delay |
**Models:** Any model pulled locally — `llama3.1`, `llama3`, `mistral`, `codellama`, `phi3`, etc. **Recommended Models (≥3B parameters):**
Fully offline. Responses include `eval_count` / `prompt_eval_count` token stats. | Model | Size | Min RAM | Notes |
|-------|------|---------|-------|
| `llama3.2:3b` | 2.0 GB | 6 GB | Balanced performance |
| `phi3.5:3.8b` | 2.2 GB | 6 GB | Excellent reasoning |
| `llama3.1:8b` | 4.7 GB | 10 GB | **RECOMMENDED** - Strong IT analysis |
| `qwen2.5:14b` | 9.0 GB | 16 GB | Best for complex log analysis |
| `gemma2:9b` | 5.5 GB | 12 GB | Google's efficient model |
**⚠️ Important:** Models with <3B parameters (e.g., `llama3.2:1b`) cannot reliably follow tool calling instructions. They will describe tools instead of invoking them.
**Features:**
- ✅ **Function Calling Support** (v1.0.7): Executes shell commands, kubectl operations
- ✅ **Multi-turn Tool Conversations**: Preserves `tool_call_id` for correlation
- ✅ **Resilient Parsing**: Skips malformed tool calls with warnings
- ✅ **Connection Reliability** (v1.0.8): Health checks, retry logic, extended timeouts
- ✅ **Auto-Start**: Automatically starts Ollama service if not running
- ✅ **Fully Offline**: No internet required, complete privacy
**Custom URL:** Change the Ollama URL in Settings → AI Providers → Ollama (stored in `settingsStore.ollama_url`). **Custom URL:** Change the Ollama URL in Settings → AI Providers → Ollama (stored in `settingsStore.ollama_url`).
**Troubleshooting:**
| Error | Cause | Solution |
|-------|-------|----------|
| "Cannot connect to Ollama" | Service not running | Run `ollama serve` or check auto-start |
| Timeout after 60s (chat) / 180s (tool calling) | Model too slow / tool calling needs more time | Use a smaller model, reduce tool usage, or wait for the higher tool-calling timeout to elapse |
| Tool calls described but not executed | Model too small (<3B) | Use `llama3.2:3b` or larger |
| Model not loaded | First request loads model | Wait 5-10s for model to load into VRAM |
**Performance Tips:**
- Use quantized models (Q4_K_M or Q4_0) for faster responses
- Keep model loaded with `ollama run <model>` in background
- Monitor VRAM usage - models stay loaded for 5 minutes by default
--- ---
## Domain System Prompts ## Domain System Prompts

@ -5,10 +5,11 @@
| Component | URL | Notes | | Component | URL | Notes |
|-----------|-----|-------| |-----------|-----|-------|
| Gitea | `https://gogs.tftsr.com` / `http://172.0.0.29:3000` | Git server (migrated from Gogs 0.14) | | Gitea | `https://gogs.tftsr.com` / `http://172.0.0.29:3000` | Git server (migrated from Gogs 0.14) |
| Woodpecker CI (direct) | `http://172.0.0.29:8084` | v2.x | | Gitea Actions | Built into Gitea | Native GitHub Actions-compatible CI/CD |
| Woodpecker CI (proxy) | `http://172.0.0.29:8085` | nginx reverse proxy |
| PostgreSQL (Gitea DB) | Container: `gogs_postgres_db` | DB: `gogsdb`, User: `gogs` | | PostgreSQL (Gitea DB) | Container: `gogs_postgres_db` | DB: `gogsdb`, User: `gogs` |
**CI/CD System:** Gitea Actions (v1.22+) with native GitHub Actions API compatibility. Uses `.gitea/workflows/*.yml` for workflow definitions.
### CI Agents ### CI Agents
| Agent | Platform | Host | Purpose | | Agent | Platform | Host | Purpose |
@ -35,9 +36,9 @@ Rust toolchain, cross-compilers) so that CI jobs skip package installation entir
| Image | Used by jobs | Contents | | Image | Used by jobs | Contents |
|-------|-------------|----------| |-------|-------------|----------|
| `172.0.0.29:3000/sarman/trcaa-linux-amd64:rust1.88-node22` | `rust-fmt-check`, `rust-clippy`, `rust-tests`, `build-linux-amd64` | Rust 1.88 + rustfmt + clippy + Tauri amd64 libs + Node.js 22 | | `172.0.0.29:3000/sarman/tftsr-linux-amd64:rust1.88-node22` | `rust-fmt-check`, `rust-clippy`, `rust-tests`, `build-linux-amd64` | Rust 1.88 + rustfmt + clippy + Tauri amd64 libs + Node.js 22 |
| `172.0.0.29:3000/sarman/trcaa-windows-cross:rust1.88-node22` | `build-windows-amd64` | Rust 1.88 + mingw-w64 + NSIS + Node.js 22 | | `172.0.0.29:3000/sarman/tftsr-windows-cross:rust1.88-node22` | `build-windows-amd64` | Rust 1.88 + mingw-w64 + NSIS + Node.js 22 |
| `172.0.0.29:3000/sarman/trcaa-linux-arm64:rust1.88-node22` | `build-linux-arm64` | Rust 1.88 + aarch64 cross-toolchain + arm64 multiarch libs + Node.js 22 | | `172.0.0.29:3000/sarman/tftsr-linux-arm64:rust1.88-node22` | `build-linux-arm64` | Rust 1.88 + aarch64 cross-toolchain + arm64 multiarch libs + Node.js 22 |
**Rebuild triggers:** Rust toolchain version bump, webkit2gtk/gtk major version change, Node.js major version change. **Rebuild triggers:** Rust toolchain version bump, webkit2gtk/gtk major version change, Node.js major version change.
@ -106,7 +107,7 @@ Pipeline jobs (run in parallel):
``` ```
**Docker images used:** **Docker images used:**
- `172.0.0.29:3000/sarman/trcaa-linux-amd64:rust1.88-node22` — Rust steps (replaces `rust:1.88-slim`) - `172.0.0.29:3000/sarman/tftsr-linux-amd64:rust1.88-node22` — Rust steps (replaces `rust:1.88-slim`)
- `node:22-alpine` — Frontend steps - `node:22-alpine` — Frontend steps
--- ---
@ -120,15 +121,15 @@ Release jobs are executed in the same workflow and depend on `autotag` completio
``` ```
Jobs (run in parallel after autotag): Jobs (run in parallel after autotag):
build-linux-amd64 → image: trcaa-linux-amd64:rust1.88-node22 build-linux-amd64 → image: tftsr-linux-amd64:rust1.88-node22
→ cargo tauri build (x86_64-unknown-linux-gnu) → cargo tauri build (x86_64-unknown-linux-gnu)
→ {.deb, .rpm, .AppImage} uploaded to Gitea release → {.deb, .rpm, .AppImage} uploaded to Gitea release
→ fails fast if no Linux artifacts are produced → fails fast if no Linux artifacts are produced
build-windows-amd64 → image: trcaa-windows-cross:rust1.88-node22 build-windows-amd64 → image: tftsr-windows-cross:rust1.88-node22
→ cargo tauri build (x86_64-pc-windows-gnu) via mingw-w64 → cargo tauri build (x86_64-pc-windows-gnu) via mingw-w64
→ {.exe, .msi} uploaded to Gitea release → {.exe, .msi} uploaded to Gitea release
→ fails fast if no Windows artifacts are produced → fails fast if no Windows artifacts are produced
build-linux-arm64 → image: trcaa-linux-arm64:rust1.88-node22 (ubuntu:22.04-based) build-linux-arm64 → image: tftsr-linux-arm64:rust1.88-node22 (ubuntu:22.04-based)
→ cargo tauri build (aarch64-unknown-linux-gnu) → cargo tauri build (aarch64-unknown-linux-gnu)
→ {.deb, .rpm, .AppImage} uploaded to Gitea release → {.deb, .rpm, .AppImage} uploaded to Gitea release
→ fails fast if no Linux artifacts are produced → fails fast if no Linux artifacts are produced

@ -389,6 +389,96 @@ CREATE VIEW IF NOT EXISTS v_image_attachments_with_issue AS
Used by `list_all_log_files` and `list_all_image_attachments` to power the cross-incident Attachments tab in the History page. Explicitly selects named columns (not `SELECT *`) to avoid including the BLOB data in list queries. Used by `list_all_log_files` and `list_all_image_attachments` to power the cross-incident Attachments tab in the History page. Explicitly selects named columns (not `SELECT *`) to avoid including the BLOB data in list queries.
### 023 — MCP Resources table (MCP Integration v0.3.0+)
```sql
CREATE TABLE IF NOT EXISTS mcp_resources (
id TEXT PRIMARY KEY,
server_id TEXT NOT NULL,
uri TEXT NOT NULL,
name TEXT NOT NULL,
description TEXT,
mime_type TEXT,
discovered_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY(server_id) REFERENCES mcp_servers(id) ON DELETE CASCADE
);
CREATE INDEX idx_mcp_resources_server ON mcp_resources(server_id);
```
Stores resources (files, data sources) exposed by MCP servers for AI agent access.
### 024 — shell_commands table (Shell Execution v1.0.0+)
```sql
CREATE TABLE IF NOT EXISTS shell_commands (
id TEXT PRIMARY KEY,
command_template TEXT NOT NULL,
tier INTEGER NOT NULL CHECK(tier IN (1, 2, 3)),
description TEXT,
category TEXT NOT NULL, -- 'kubectl', 'proxmox', 'general'
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
```
Pre-defined command templates with tier classification for the three-tier safety system. See [[Shell-Execution]] for details.
### 025 — kubeconfig_files table (Shell Execution v1.0.0+)
```sql
CREATE TABLE IF NOT EXISTS kubeconfig_files (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
encrypted_content TEXT NOT NULL,
context TEXT NOT NULL,
cluster_url TEXT,
is_active INTEGER NOT NULL DEFAULT 0,
uploaded_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX idx_kubeconfig_active ON kubeconfig_files(is_active);
```
Encrypted storage for kubectl configuration files. Content encrypted with AES-256-GCM. Only one config can be active at a time.
### 026 — command_executions table (Shell Execution v1.0.0+)
```sql
CREATE TABLE IF NOT EXISTS command_executions (
id TEXT PRIMARY KEY,
issue_id TEXT,
command TEXT NOT NULL,
tier INTEGER NOT NULL,
approval_status TEXT NOT NULL, -- 'auto', 'approved', 'denied'
kubeconfig_id TEXT,
exit_code INTEGER,
stdout TEXT,
stderr TEXT,
execution_time_ms INTEGER,
executed_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE,
FOREIGN KEY (kubeconfig_id) REFERENCES kubeconfig_files(id) ON DELETE SET NULL
);
CREATE INDEX idx_command_executions_issue ON command_executions(issue_id);
CREATE INDEX idx_command_executions_executed ON command_executions(executed_at);
```
Complete audit trail of all shell command executions with exit codes, stdout/stderr capture, and execution timing.
### 027 — approval_decisions table (Shell Execution v1.0.0+)
```sql
CREATE TABLE IF NOT EXISTS approval_decisions (
id TEXT PRIMARY KEY,
command_pattern TEXT NOT NULL,
decision TEXT NOT NULL CHECK(decision IN ('allow_once', 'allow_session', 'deny')),
session_id TEXT,
decided_at TEXT NOT NULL DEFAULT (datetime('now')),
expires_at TEXT
);
CREATE INDEX idx_approval_decisions_session ON approval_decisions(session_id);
```
Session-based approval preferences for Tier 2 commands. Allows users to approve similar commands for the duration of a session.
--- ---
## Key Design Notes ## Key Design Notes

@ -28,6 +28,20 @@ Node **v22** required. Install via nvm or system package manager.
npm install --legacy-peer-deps npm install --legacy-peer-deps
``` ```
### kubectl Binary (for Shell Execution)
kubectl v1.30.0 is bundled with the application. To download binaries for development:
```bash
./scripts/download-kubectl.sh linux amd64
./scripts/download-kubectl.sh linux arm64
./scripts/download-kubectl.sh darwin arm64
./scripts/download-kubectl.sh darwin amd64
./scripts/download-kubectl.sh windows amd64
```
Binaries are placed in `binaries/kubectl-{os}-{arch}` and bundled via `tauri.conf.json` resources. See [[Shell-Execution]] for runtime usage details.
--- ---
## Environment Variables ## Environment Variables

@ -603,6 +603,86 @@ interface TicketResult {
--- ---
## Shell Execution Commands
> **Status:** Fully Implemented (v1.0.0+)
>
> See [[Shell-Execution]] for complete documentation of the three-tier safety system.
### `upload_kubeconfig`
```typescript
uploadKubeconfigCmd(name: string, content: string) → string
```
Upload and encrypt a kubeconfig file. Returns the kubeconfig ID.
### `list_kubeconfigs`
```typescript
listKubeconfigsCmd() → KubeconfigInfo[]
```
List all uploaded kubeconfig files with metadata.
```typescript
interface KubeconfigInfo {
id: string;
name: string;
context: string;
cluster_url?: string;
is_active: boolean;
}
```
### `activate_kubeconfig`
```typescript
activateKubeconfigCmd(id: string) → void
```
Set a kubeconfig as active for kubectl commands.
### `delete_kubeconfig`
```typescript
deleteKubeconfigCmd(id: string) → void
```
Delete a kubeconfig file permanently.
### `respond_to_shell_approval`
```typescript
respondToShellApprovalCmd(approvalId: string, decision: string) → void
```
Respond to a Tier 2 command approval request.
- `decision`: `"deny"`, `"allow_once"`, or `"allow_session"`
### `list_command_executions`
```typescript
listCommandExecutionsCmd(issueId?: string) → CommandExecution[]
```
List recent command executions, optionally filtered by issue ID.
```typescript
interface CommandExecution {
id: string;
command: string;
tier: number; // 1, 2, or 3
approval_status: string; // 'auto', 'approved', 'denied'
exit_code?: number;
stdout?: string;
stderr?: string;
execution_time_ms?: number;
executed_at: string;
}
```
### `check_kubectl_installed`
```typescript
checkKubectlInstalledCmd() → KubectlStatus
```
Check if kubectl is installed and return version info.
```typescript
interface KubectlStatus {
installed: boolean;
path?: string;
version?: string;
}
```
---
## Authentication Storage ## Authentication Storage
All integration credentials are stored in the `credentials` table: All integration credentials are stored in the `credentials` table:

665
Shell-Execution.md Normal file

@ -0,0 +1,665 @@
# Shell Execution
**Status**: ✅ Production-ready agentic shell execution with three-tier safety classification (v1.0.0)
## Overview
The Shell Execution feature enables AI-powered autonomous execution of diagnostic commands with intelligent safety controls. The AI can directly execute kubectl, Proxmox tools, and general shell commands to gather troubleshooting data without manual intervention.
**Key Features**:
- Three-tier command safety classification (auto/approve/deny)
- Real-time approval modal for mutating operations
- kubectl integration with bundled binary (v1.30.0)
- Multi-cluster support via multiple kubeconfig files
- AES-256-GCM encrypted kubeconfig storage
- Complete audit trail for all executions
- Pipe/chain command analysis with tier escalation
- Command timeout protection (30s)
- Approval timeout protection (60s)
## Three-Tier Safety Architecture
Commands are automatically classified into three safety tiers based on their potential impact:
### Tier 1: Auto-Execute (Read-Only)
**Behavior**: Execute immediately without user approval
**kubectl commands**:
- `kubectl get [resource]` - List resources
- `kubectl describe [resource]` - Show detailed resource information
- `kubectl logs [pod]` - View pod logs
**General commands**:
- `cat [file]` - Display file contents
- `grep [pattern]` - Search text patterns
- `ls` - List directory contents
- `pwd` - Print working directory
- `whoami` - Display current user
- `date` - Show system date/time
- `uptime` - Show system uptime
- `df -h` - Show disk usage
- `free -m` - Show memory usage
- `ps aux` - List processes
**Proxmox commands**:
- `pvecm status` - Show cluster status
- `pvesh get /cluster/status` - Get cluster status via API
### Tier 2: Require Approval (Mutating)
**Behavior**: Pause execution and display approval modal to user
**kubectl commands**:
- `kubectl apply -f [file]` - Apply configuration
- `kubectl delete [resource]` - Delete resources
- `kubectl scale [deployment]` - Scale deployments
- `kubectl exec -it [pod]` - Execute command in container
- `kubectl port-forward` - Forward ports
- `kubectl patch` - Update resource fields
- `kubectl create` - Create resources
- `kubectl edit` - Edit resources
**System commands**:
- `ssh` - Remote shell access
- `scp` - Secure copy
- `chmod` - Change file permissions
- `chown` - Change file ownership
- `systemctl restart [service]` - Restart services
- `systemctl stop [service]` - Stop services
- `systemctl start [service]` - Start services
- `docker restart [container]` - Restart Docker containers
- `docker stop [container]` - Stop Docker containers
- `reboot` (with confirmation) - System reboot
**Proxmox commands**:
- `qm start [vmid]` - Start virtual machine
- `qm stop [vmid]` - Stop virtual machine
- `qm restart [vmid]` - Restart virtual machine
### Tier 3: Always Deny (Destructive)
**Behavior**: Immediate denial with clear reasoning
**Destructive operations**:
- `rm -rf` - Recursive force delete
- `mkfs` - Format filesystem
- `dd` - Low-level disk operations
- `fdisk` - Partition manipulation
- `parted` - Partition editing
- `shutdown` - System shutdown
- `init 0` - System halt
- `halt` - System halt
- `poweroff` - System power off
- `wipefs` - Wipe filesystem signatures
**Why Tier 3 is Denied**:
These commands can cause irreversible data loss, system downtime, or infrastructure damage. They should only be executed manually by authorized personnel with explicit intent.
## Pipe and Chain Analysis
The classifier analyzes complex command structures and escalates to the highest tier found:
### Piped Commands
```bash
# Tier 1: Both commands are read-only
kubectl get pods | grep nginx
# Tier 2: Second command is mutating (escalates entire chain)
kubectl get pods | kubectl delete -f -
# Tier 3: Contains destructive operation (entire chain denied)
cat /tmp/list.txt | xargs rm -rf
```
### Logical Operators
```bash
# Tier 2: Uses && to chain mutating operations
kubectl apply -f deployment.yaml && kubectl rollout status deployment/nginx
# Tier 2: Uses || for fallback (escalates to highest tier)
ssh server1 || ssh server2
# Tier 3: Contains destructive command (entire chain denied)
cd /tmp && rm -rf *
```
### Command Substitution
Commands using `$()` or backticks are flagged with a risk factor and analyzed recursively:
```bash
# Tier 2: Inner command is read-only, but ssh requires approval
ssh server "$(cat /tmp/script.sh)"
# Tier 3: Inner command is destructive (entire operation denied)
rm -rf $(find / -name "*.tmp")
```
## Approval Workflow
When a Tier 2 command is detected:
1. **Execution Paused**: Command execution stops before running
2. **Modal Displayed**: Real-time modal appears in the UI showing:
- Full command text
- Safety tier badge
- Classification reasoning
- Risk factors (if any)
- Safety controls in place
3. **User Decision**: Three options available:
- **Deny**: Reject the command permanently
- **Allow Once**: Execute this specific command only
- **Allow for Session**: Execute this and future similar commands in the current session
4. **Timeout**: If no response within 60 seconds, automatically deny
### Approval Modal Screenshot
```
┌─────────────────────────────────────────────────────────┐
│ 🛡️ Command Approval Required │
├─────────────────────────────────────────────────────────┤
│ This command requires your approval before execution │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ $ kubectl delete pod nginx-5d5f4c7d9-abcde │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ Safety Tier: [Tier 2] │
│ │
│ ⚠️ Why approval is needed: │
│ Mutating operation: kubectl delete │
│ │
│ Safety Controls: │
│ • Command execution is logged and auditable │
│ • 30-second timeout protection │
│ • PII detection before execution │
│ • Output is captured for review │
│ │
│ [Deny] [Allow Once] [Allow for Session] │
└─────────────────────────────────────────────────────────┘
```
## kubectl Integration
### Bundled Binary
kubectl v1.30.0 is bundled with the application for all platforms:
- **Linux**: amd64, arm64
- **macOS**: Intel (x86_64), Apple Silicon (aarch64)
- **Windows**: amd64
The binary is automatically selected based on the runtime platform.
### Kubeconfig Management
**Upload Process**:
1. Navigate to **Settings → Kubeconfig**
2. Click **Upload Kubeconfig**
3. Select your kubeconfig file (.yaml or .yml)
4. Provide a friendly name (e.g., "production-cluster")
5. File is parsed and validated
6. Content is encrypted using AES-256-GCM
7. Stored in `kubeconfig_files` table
**Multiple Clusters**:
- Upload multiple kubeconfig files for different clusters
- Only one can be **active** at a time
- Activate a config by clicking **Activate** button
- Active config is used for all kubectl commands
- Cluster URL and context displayed for each config
**Auto-Detection**:
Kubeconfig auto-detection from `~/.kube/config` is implemented but not enabled at startup due to AppHandle state access limitations. Users must manually upload kubeconfig files via the UI.
### Environment Isolation
When kubectl commands execute:
- `KUBECONFIG` environment variable set to active config path
- Sensitive environment variables cleared (AWS credentials, etc.)
- Working directory isolated if specified
- 30-second timeout per command
## Command Execution Flow
### Full Execution Pipeline
1. **AI Tool Call**: AI invokes `execute_shell_command` tool with command text
2. **PII Detection**: Command text scanned for sensitive data (passwords, tokens, API keys)
3. **Audit Log (Pre-Execution)**: Command logged with hash chain before execution
4. **Classification**: CommandClassifier analyzes command structure and assigns tier
5. **Tier Decision**:
- **Tier 1**: Proceed directly to execution
- **Tier 2**: Emit `shell:approval-needed` event, wait for user response
- **Tier 3**: Return error immediately with reasoning
6. **Execution** (if approved):
- For kubectl: Use `execute_kubectl()` with active kubeconfig
- For general: Use `tokio::process::Command` with 30s timeout
7. **Result Capture**: Capture exit code, stdout, stderr, execution time
8. **Database Record**: Store execution in `command_executions` table
9. **Audit Log (Post-Execution)**: Log result with exit code
10. **Return to AI**: Format output as text for AI analysis
### Error Handling
- **Timeout**: 30s command timeout, returns timeout error
- **Approval Timeout**: 60s approval timeout, command denied
- **Execution Failure**: Exit code != 0, stderr captured and returned
- **Classification Error**: Unparseable command, denied with reasoning
- **PII Detected**: Warning logged but execution continues (non-blocking)
## Audit Trail
All command executions are recorded in the `command_executions` table:
**Fields**:
- `id`: Unique UUID
- `command`: Full command text
- `tier`: Safety tier (1, 2, or 3)
- `approval_status`: "auto", "approved", or "denied"
- `kubeconfig_id`: Reference to active kubeconfig (if kubectl)
- `exit_code`: Command exit code
- `stdout`: Command output
- `stderr`: Error output
- `execution_time_ms`: Execution duration
- `executed_at`: Timestamp
**Audit Logging**:
All executions are also written to the audit log (`audit_events` table) with:
- Event type: `shell_command_execution`
- Entity type: `shell_command`
- Entity ID: Command text
- Details JSON: `{"command": "...", "exit_code": 0}`
- Hash chain linkage for tamper detection
**Viewing History**:
Navigate to **Settings → Shell Execution** to view recent command executions:
- Last 10 commands displayed
- Tier badge and approval status
- Exit code (green for 0, red for non-zero)
- Execution time
- Timestamp
- Collapsible stdout output
## Security Controls
### Encryption
- **Kubeconfig Files**: AES-256-GCM encryption at rest
- **Encryption Key**: Derived from `TFTSR_ENCRYPTION_KEY` environment variable
- **Nonce**: Random 12-byte nonce per encryption operation
- **Authentication Tag**: 16-byte tag for integrity verification
### PII Detection
Before execution, commands are scanned for:
- Passwords (e.g., `--password=secret`)
- API keys (patterns like `AKIAIOSFODNN7EXAMPLE`)
- Tokens (e.g., `token=abc123`)
- SSH keys (private key patterns)
If PII is detected:
- Warning logged with span count
- Execution continues (non-blocking)
- Consider sanitizing command history in future enhancement
### Command Injection Prevention
- No shell interpretation of user-provided arguments
- Arguments passed directly to `tokio::process::Command`
- kubectl arguments parsed from command string, not shell-interpreted
### Timeout Protection
- **Command Timeout**: 30 seconds per command
- **Approval Timeout**: 60 seconds for user response
- Prevents indefinite hangs or runaway processes
### Hash-Chained Audit Log
All executions recorded in audit log with:
- Previous event hash
- Current event data hash
- Timestamp
- Tamper detection via hash verification
## Settings
### Shell Execution Settings
**Location**: Settings → Shell Execution
**Features**:
- kubectl installation status and version display
- Link to Kubeconfig Manager
- Three-tier safety architecture visualization
- Recent command execution history (last 10)
### Kubeconfig Manager
**Location**: Settings → Kubeconfig
**Features**:
- Upload kubeconfig files (.yaml, .yml)
- List all uploaded configs with context and cluster URL
- Activate/deactivate configs
- Delete configs with confirmation
- Preview uploaded file content (first 500 chars)
## API Reference
### Backend Commands
#### `upload_kubeconfig`
Upload and encrypt a kubeconfig file.
**Parameters**:
- `name: String` - Friendly name for the config
- `content: String` - Full kubeconfig YAML content
**Returns**: `Result<String, String>` - Config ID on success
#### `list_kubeconfigs`
List all uploaded kubeconfig files.
**Returns**: `Result<Vec<KubeconfigInfo>, String>`
**KubeconfigInfo**:
```rust
pub struct KubeconfigInfo {
pub id: String,
pub name: String,
pub context: String,
pub cluster_url: Option<String>,
pub is_active: bool,
}
```
#### `activate_kubeconfig`
Set a kubeconfig as active.
**Parameters**:
- `id: String` - Config ID to activate
**Returns**: `Result<(), String>`
#### `delete_kubeconfig`
Delete a kubeconfig file.
**Parameters**:
- `id: String` - Config ID to delete
**Returns**: `Result<(), String>`
#### `respond_to_shell_approval`
Respond to a shell command approval request.
**Parameters**:
- `approval_id: String` - Unique approval request ID
- `decision: String` - "deny", "allow_once", or "allow_session"
**Returns**: `Result<(), String>`
#### `list_command_executions`
List recent command executions.
**Parameters**:
- `issue_id: Option<String>` - Filter by issue ID (optional)
**Returns**: `Result<Vec<CommandExecution>, String>`
**CommandExecution**:
```rust
pub struct CommandExecution {
pub id: String,
pub command: String,
pub tier: i32,
pub approval_status: String,
pub exit_code: Option<i32>,
pub stdout: Option<String>,
pub stderr: Option<String>,
pub execution_time_ms: Option<i64>,
pub executed_at: String,
}
```
#### `check_kubectl_installed`
Check if kubectl is installed and get version info.
**Returns**: `Result<KubectlStatus, String>`
**KubectlStatus**:
```rust
pub struct KubectlStatus {
pub installed: bool,
pub path: Option<String>,
pub version: Option<String>,
}
```
### AI Tool: `execute_shell_command`
**Description**: Execute shell commands with automatic safety classification.
**Parameters**:
- `command: String` (required) - Shell command to execute
- `working_directory: String` (optional) - Working directory for execution
- `kubeconfig_id: String` (optional) - Kubeconfig file ID for kubectl commands
**Returns**: String with formatted output:
```
Exit Code: 0
Stdout:
NAME READY STATUS RESTARTS AGE
nginx-5d5f4c7d9-abcde 1/1 Running 0 5m
Stderr:
```
**Usage in AI Context**:
```typescript
{
"name": "execute_shell_command",
"arguments": {
"command": "kubectl get pods -n production",
"kubeconfig_id": "uuid-of-active-config"
}
}
```
## Database Schema
### `shell_commands` (Migration 024)
Pre-defined command templates with tier classification.
```sql
CREATE TABLE IF NOT EXISTS shell_commands (
id TEXT PRIMARY KEY,
command_template TEXT NOT NULL,
tier INTEGER NOT NULL CHECK(tier IN (1, 2, 3)),
description TEXT,
category TEXT NOT NULL, -- 'kubectl', 'proxmox', 'general'
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
```
### `kubeconfig_files` (Migration 025)
Encrypted kubeconfig storage.
```sql
CREATE TABLE IF NOT EXISTS kubeconfig_files (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
encrypted_content TEXT NOT NULL,
context TEXT NOT NULL,
cluster_url TEXT,
is_active INTEGER NOT NULL DEFAULT 0,
uploaded_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX idx_kubeconfig_active ON kubeconfig_files(is_active);
```
### `command_executions` (Migration 026)
Full audit trail of all command executions.
```sql
CREATE TABLE IF NOT EXISTS command_executions (
id TEXT PRIMARY KEY,
issue_id TEXT,
command TEXT NOT NULL,
tier INTEGER NOT NULL,
approval_status TEXT NOT NULL, -- 'auto', 'approved', 'denied'
kubeconfig_id TEXT,
exit_code INTEGER,
stdout TEXT,
stderr TEXT,
execution_time_ms INTEGER,
executed_at TEXT NOT NULL DEFAULT (datetime('now')),
FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE,
FOREIGN KEY (kubeconfig_id) REFERENCES kubeconfig_files(id) ON DELETE SET NULL
);
CREATE INDEX idx_command_executions_issue ON command_executions(issue_id);
CREATE INDEX idx_command_executions_executed ON command_executions(executed_at);
```
### `approval_decisions` (Migration 027)
Session-based approval preferences.
```sql
CREATE TABLE IF NOT EXISTS approval_decisions (
id TEXT PRIMARY KEY,
command_pattern TEXT NOT NULL,
decision TEXT NOT NULL CHECK(decision IN ('allow_once', 'allow_session', 'deny')),
session_id TEXT,
decided_at TEXT NOT NULL DEFAULT (datetime('now')),
expires_at TEXT
);
CREATE INDEX idx_approval_decisions_session ON approval_decisions(session_id);
```
## Testing
### Backend Tests
**Location**: `src-tauri/src/shell/`
**Classifier Tests** (`classifier.rs`):
- `test_tier1_kubectl_get` - Auto-execute kubectl get
- `test_tier2_kubectl_delete` - Require approval for kubectl delete
- `test_tier3_rm_rf` - Deny rm -rf
- `test_pipe_tier_escalation` - Piped command tier analysis
- 19 total tests covering all tier classifications
**kubectl Tests** (`kubectl.rs`):
- `test_locate_kubectl_finds_binary` - Binary location logic
- `test_kubectl_version_check` - Verify binary works
- `test_execute_kubectl_with_timeout` - Timeout implementation
- 3 total tests
**Executor Tests** (`executor.rs`):
- Currently ignored (require full app setup)
- Placeholder tests for approval flow
**Coverage**:
- Classifier: 100% (critical safety component)
- kubectl: 90%
- Executor: Needs integration test environment
### Frontend Tests
**Location**: `src/components/__tests__/`, `src/pages/__tests__/`
**Component Tests**:
- ShellApprovalModal: Event listener, modal rendering, button actions
- All existing tests passing (103 total)
### Integration Testing
**Manual Test Cases**:
1. **Tier 1 Auto-Execution**
- AI request: "Show me all pods in the default namespace"
- Expected: Command executes immediately without modal
- Verify: `command_executions` has `approval_status='auto'`
2. **Tier 2 Approval Flow**
- AI request: "Scale the nginx deployment to 5 replicas"
- Expected: Approval modal appears
- Test: Deny → execution blocked
- Test: Allow Once → execution proceeds
- Test: Allow for Session → execution proceeds
3. **Tier 3 Denial**
- AI request: "Delete all files in /tmp"
- Expected: No modal, immediate error with reasoning
- Verify: Command not executed
4. **Piped Command Analysis**
- Command: `kubectl get pods | grep nginx` → Tier 1 (auto-execute)
- Command: `kubectl get pods | kubectl delete -f -` → Tier 2 (approval)
- Command: `cat /tmp/list.txt | xargs rm -rf` → Tier 3 (deny)
5. **Timeout Protection**
- Command: `sleep 60` → Times out after 30s
- Approval: Wait 61s → Approval times out, command denied
6. **Audit Trail**
- Query: `SELECT * FROM command_executions ORDER BY executed_at DESC`
- Verify: All commands logged with correct tier, status, exit code
## Troubleshooting
### kubectl not found
**Problem**: "kubectl is not installed" message in Shell Execution settings
**Solutions**:
1. Check if kubectl is bundled: Binary should be at `Resources/kubectl` (macOS) or similar platform path
2. Verify PATH: Ensure system PATH includes kubectl location
3. Reinstall: Download latest application bundle with kubectl included
### Kubeconfig upload fails
**Problem**: "Failed to parse kubeconfig" error
**Solutions**:
1. Validate YAML: Ensure kubeconfig is valid YAML format
2. Check contexts: Kubeconfig must have at least one context defined
3. Cluster URL: Ensure cluster URL is accessible
4. File format: Only .yaml or .yml files accepted
### Commands not executing
**Problem**: Commands hang or don't execute
**Solutions**:
1. Check timeout: Commands timeout after 30 seconds
2. Approval timeout: User must respond within 60 seconds for Tier 2
3. Active kubeconfig: Ensure a kubeconfig is activated for kubectl commands
4. Review logs: Check audit log for denial reason
### Approval modal not appearing
**Problem**: Tier 2 command doesn't show approval modal
**Solutions**:
1. Check browser: Ensure JavaScript is enabled
2. Event listener: Modal listens for `shell:approval-needed` event
3. Tauri events: Verify Tauri event system is working
4. Console errors: Check browser console for errors
## Future Enhancements
**Planned Features**:
- Session-based approval preferences (approve all kubectl get for 1 hour)
- Command templating (save frequently used commands)
- Execution rollback (undo kubectl apply operations)
- Tier overrides (admin can override tier classification)
- Command history search and filtering
- Export execution history as CSV/JSON
- Integration with issue timeline (show commands executed during incident)
- Proxmox advanced commands (cluster management, backups)
- Multi-kubeconfig context switching within single file
- Auto-detection of ~/.kube/config on startup (pending AppHandle fix)
**Stretch Goals**:
- Parallel command execution (run multiple commands concurrently)
- Command scheduling (execute command at specific time)
- Command chaining with dependencies (run X, then Y if X succeeds)
- Command output parsing (extract structured data from stdout)
- Integration with monitoring systems (auto-execute commands on alerts)
## Related Documentation
- [[Architecture]] - Overall application architecture
- [[Security-Model]] - Security architecture and threat model
- [[Database]] - Database schema and migrations
- [[IPC-Commands]] - Frontend-backend communication
- [[AI-Providers]] - AI integration and tool use
## Version History
- **v1.0.0** (2026-06-02): Initial release with three-tier safety classification, kubectl bundling, and multi-cluster support