# AGENTS.md ## Commands & Tools ### Development - **Full dev server**: `cargo tauri dev` (requires `source ~/.cargo/env` first) - **Frontend only**: `npm run dev` (Vite at localhost:1420) - **Production build**: `cargo tauri build` → `src-tauri/target/release/bundle/` ### Testing & Verification **Order matters:** 1. `cargo fmt --manifest-path src-tauri/Cargo.toml --check` 2. `cargo clippy --manifest-path src-tauri/Cargo.toml -- -D warnings` 3. `cargo test --manifest-path src-tauri/Cargo.toml` 4. `npx tsc --noEmit` 5. `npm run test:run` **Single Rust test**: `cargo test --manifest-path src-tauri/Cargo.toml pii::detector` **Single Rust test by name**: `cargo test --manifest-path src-tauri/Cargo.toml test_detect_ipv4` --- ## Architecture Highlights ### Rust Backend (Tauri 2) - **State**: `AppState` wraps `Mutex` + `Mutex` — lock inside `{ }` blocks and **release before `.await`** - **IPC entry point**: `src-tauri/src/lib.rs` → `run()` registers all handlers in `generate_handler![]` - **AI providers**: `ai/provider.rs::create_provider()` dispatches on `provider_type` (or `name` fallback) - **PII before AI**: Every external send must call `apply_redactions()` and log SHA-256 hash via `audit::log::write_audit_event()` - **DB encryption**: `debug_assertions` → plain SQLite; release → SQLCipher. Keys from `TFTSR_DB_KEY` / `TFTSR_ENCRYPTION_KEY` env vars ### Frontend (React + TypeScript) - **IPC layer**: `src/lib/tauriCommands.ts` — single source of truth for typed `invoke()` wrappers - **Stores** (Zustand): - `sessionStore.ts`: Ephemeral triage session (not persisted) - `settingsStore.ts`: AI providers, theme, Ollama URL — persisted to `localStorage` as `"tftsr-settings"` - `historyStore.ts`: Read-only cache of past issues - **Domain prompts**: `src/lib/domain Prompts.ts` — 8 IT domains injected as first message in triage conversations ### Key Data Types - **IssueDetail** (Rust): Nested struct — `detail.issue.title`, NOT `detail.title` - **IssueDetail** (TS): Mirrors Rust — use `issue.title`, `issue.status`, etc. - **PII spans**: `PiiDetector::detect()` returns non-overlapping spans (longest wins on overlap), applies in reverse order --- ## CI/CD **Branch protection**: `master` requires PR + `sarman` approval + all 5 CI checks green **Gitea Actions workflows** (`.gitea/workflows/`): - `test.yml`: rustfmt · clippy · cargo test (64) · tsc · vitest (13) — every push/PR - `auto-tag.yml`: Auto-tag + multi-platform release build on push to `master` **Runners**: - `amd64-docker-runner`: linux/amd64 + windows/amd64 builds - `arm64-native-runner`: native linux/arm64 builds **CI test binary requirement**: `npm run test:e2e` needs `TAURI_BINARY_PATH=./src-tauri/target/release/tftsr` --- ## Database & Settings **DB path**: `~/.local/share/tftsr/tftsr.db` (Linux), override via `TFTSR_DATA_DIR` **SQLite schema**: `db/migrations.rs` tracks 10 migrations; schema in `_migrations` table **Environment variables**: - `TFTSR_DATA_DIR`: DB location override - `TFTSR_DB_KEY`: SQLCipher encryption key (required release) - `TFTSR_ENCRYPTION_KEY`: API key encryption (required release) - `RUST_LOG`: tracing level (`debug`, `info`, `warn`, `error`) --- ## PII Detection & Redaction **Patterns detected**: IPv4/IPv6, emails, tokens, passwords, SSNs, credit cards **Flow**: 1. `detect_pii(log_file_id)` → `Vec` (sorted, non-overlapping) 2. UI shows diff viewer for approval 3. `apply_redactions(log_file_id, approved_span_ids)` → creates redacted file 4. **Mandatory**: SHA-256 hash of redacted content logged via `audit::log::write_audit_event()` before any AI send --- ## AI Providers **Supported**: OpenAI (compatible), Anthropic, Google Gemini, Mistral, Ollama (local) **Adding a provider**: 1. Implement `Provider` trait in `ai/*.rs` 2. Add match arm in `ai/provider.rs::create_provider()` **Ollama defaults**: `http://localhost:11434`, default model `llama3.2:3b` (≥8 GB RAM) or `llama3.1:8b` (≥16 GB RAM) --- ## Wiki Maintenance **Source of truth**: `docs/wiki/` — automated sync to Gitea wiki on every push to `master` **Update these files when changing code**: | Area | Wiki file | |------|-----------| | Tauri commands | `IPC-Commands.md` | | DB schema/migrations | `Database.md` | | AI providers | `AI-Providers.md` | | PII detection | `PII-Detection.md` | | CI/CD changes | `CICD-Pipeline.md` | | Architecture | `Architecture.md` | | Security changes | `Security-Model.md` | | Dev setup | `Development-Setup.md` | --- ## Common Gotchas 1. **Mutex deadlock**: Never hold `MutexGuard` across `.await` — release before async calls 2. **PII enforcement**: Redaction + hash audit is mandatory before any network send 3. **Testing order**: Run `cargo check`/`cargo fmt`/`cargo clippy` before `cargo test` (order matters for CI) 4. **DB encryption**: Release builds require `TFTSR_DB_KEY` and `TFTSR_ENCRYPTION_KEY` or will fail at runtime 5. **Type mismatch**: `get_issue()` returns `IssueDetail` with nested `issue` field in both Rust and TS 6. **Integration stubs**: `integrations/` modules are v0.2 stubs — not functionally complete 7. **Rust version**: 1.88+ required (for `cookie_store`, `time`, `darling`) 8. **Linux deps**: Must install webkit2gtk4.1 + libsoup3 + openssl before `cargo build` --- ## Prerequisites (Linux/Fedora) ```bash sudo dnf install -y glib2-devel gtk3-devel webkit2gtk4.1-devel \ libsoup3-devel openssl-devel librsvg2-devel ``` **Rust**: `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh && source ~/.cargo/env` **Node**: 22+ (via package manager)