tftsr-devops_investigation/AGENTS.md
Shaun Arman 0d8970a911 feat: add image attachment support with PII detection
- Add image_attachments table to database schema (migration 013)
- Implement image upload, list, delete, and clipboard paste commands
- Add image file PII detection with user approval workflow
- Register image attachment commands in Tauri IPC
- Update TypeScript types and frontend components
- Add unit tests for image attachment functionality
- Update README and wiki documentation
2026-04-08 19:25:12 -05:00

5.5 KiB

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 buildsrc-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.rsrun() 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)

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)