142 lines
5.5 KiB
Markdown
142 lines
5.5 KiB
Markdown
|
|
# 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<Connection>` + `Mutex<AppSettings>` — 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<PiiSpan>` (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)
|