docs: sync from docs/wiki/ at commit 350013e0
parent
a2d81d5716
commit
665be36180
@ -55,13 +55,21 @@ Covers: OpenAI, Azure OpenAI, LM Studio, vLLM, **LiteLLM (AWS Bedrock)**, and an
|
||||
|-------|-------|
|
||||
| `config.name` | `"gemini"` |
|
||||
| URL | `https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent` |
|
||||
| Auth | API key as `?key=` query parameter |
|
||||
| Auth | `x-goog-api-key: <api_key>` header |
|
||||
| Max tokens | 4096 |
|
||||
|
||||
**Models:** `gemini-2.0-flash`, `gemini-2.0-pro`, `gemini-1.5-pro`, `gemini-1.5-flash`
|
||||
|
||||
---
|
||||
|
||||
## Transport Security Notes
|
||||
|
||||
- Provider clients use TLS certificate verification via `reqwest`
|
||||
- Provider calls are configured with explicit request timeouts to avoid indefinite hangs
|
||||
- Credentials are sent in headers (not URL query strings)
|
||||
|
||||
---
|
||||
|
||||
### 4. Mistral AI
|
||||
|
||||
| Field | Value |
|
||||
@ -113,7 +121,7 @@ The domain prompt is injected as the first `system` role message in every new co
|
||||
|
||||
---
|
||||
|
||||
## 6. Custom Provider (MSI GenAI & Others)
|
||||
## 6. Custom Provider (Custom REST & Others)
|
||||
|
||||
**Status:** ✅ **Implemented** (v0.2.6)
|
||||
|
||||
@ -137,25 +145,26 @@ Standard OpenAI `/chat/completions` endpoint with Bearer authentication.
|
||||
|
||||
---
|
||||
|
||||
### Format: MSI GenAI
|
||||
### Format: Custom REST
|
||||
|
||||
**Motorola Solutions Internal GenAI Service** — Enterprise AI platform with centralized cost tracking and model access.
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| `config.provider_type` | `"custom"` |
|
||||
| `config.api_format` | `"msi_genai"` |
|
||||
| `config.api_format` | `"custom_rest"` |
|
||||
| API URL | `https://genai-service.commandcentral.com/app-gateway` (prod)<br>`https://genai-service.stage.commandcentral.com/app-gateway` (stage) |
|
||||
| Auth Header | `x-msi-genai-api-key` |
|
||||
| Auth Prefix | `` (empty - no Bearer prefix) |
|
||||
| Endpoint Path | `` (empty - URL includes full path `/api/v2/chat`) |
|
||||
|
||||
**Available Models:**
|
||||
**Available Models (dropdown in Settings):**
|
||||
- `VertexGemini` — Gemini 2.0 Flash (Private/GCP)
|
||||
- `Claude-Sonnet-4` — Claude Sonnet 4 (Public/Anthropic)
|
||||
- `ChatGPT4o` — GPT-4o (Public/OpenAI)
|
||||
- `ChatGPT-5_2-Chat` — GPT-4.5 (Public/OpenAI)
|
||||
- See [GenAI API User Guide](../GenAI%20API%20User%20Guide.md) for full model list
|
||||
- Full list is sourced from [GenAI API User Guide](../GenAI%20API%20User%20Guide.md)
|
||||
- Includes a `Custom model...` option to manually enter any model ID
|
||||
|
||||
**Request Format:**
|
||||
```json
|
||||
@ -187,9 +196,9 @@ Standard OpenAI `/chat/completions` endpoint with Bearer authentication.
|
||||
|
||||
**Configuration (Settings → AI Providers → Add Provider):**
|
||||
```
|
||||
Name: MSI GenAI
|
||||
Name: Custom REST (MSI GenAI)
|
||||
Type: Custom
|
||||
API Format: MSI GenAI
|
||||
API Format: Custom REST
|
||||
API URL: https://genai-service.stage.commandcentral.com/app-gateway
|
||||
Model: VertexGemini
|
||||
API Key: (your MSI GenAI API key from portal)
|
||||
@ -208,13 +217,13 @@ Auth Prefix: (leave empty)
|
||||
| Error | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| 403 Forbidden | Invalid API key or insufficient permissions | Verify key in MSI GenAI portal, check model access |
|
||||
| Missing `userId` field | Configuration not saved | Ensure UI shows User ID field when `api_format=msi_genai` |
|
||||
| Missing `userId` field | Configuration not saved | Ensure UI shows User ID field when `api_format=custom_rest` |
|
||||
| No conversation history | `sessionId` not persisted | Session ID stored in `ProviderConfig.session_id` — currently per-provider, not per-conversation |
|
||||
|
||||
**Implementation Details:**
|
||||
- Backend: `src-tauri/src/ai/openai.rs::chat_msi_genai()`
|
||||
- Backend: `src-tauri/src/ai/openai.rs::chat_custom_rest()`
|
||||
- Schema: `src-tauri/src/state.rs::ProviderConfig` (added `user_id`, `api_format`, custom auth fields)
|
||||
- Frontend: `src/pages/Settings/AIProviders.tsx` (conditional UI for MSI GenAI)
|
||||
- Frontend: `src/pages/Settings/AIProviders.tsx` (conditional UI for Custom REST + model dropdown)
|
||||
- CSP whitelist: `https://genai-service.stage.commandcentral.com` and production domain
|
||||
|
||||
---
|
||||
@ -228,9 +237,9 @@ All providers support the following optional configuration fields (v0.2.6+):
|
||||
| `custom_endpoint_path` | `Option<String>` | Override endpoint path | `/chat/completions` |
|
||||
| `custom_auth_header` | `Option<String>` | Custom auth header name | `Authorization` |
|
||||
| `custom_auth_prefix` | `Option<String>` | Prefix before API key | `Bearer ` |
|
||||
| `api_format` | `Option<String>` | API format (`openai` or `msi_genai`) | `openai` |
|
||||
| `api_format` | `Option<String>` | API format (`openai` or `custom_rest`) | `openai` |
|
||||
| `session_id` | `Option<String>` | Session ID for stateful APIs | None |
|
||||
| `user_id` | `Option<String>` | User ID for cost tracking (MSI GenAI) | None |
|
||||
| `user_id` | `Option<String>` | User ID for cost tracking (Custom REST MSI contract) | None |
|
||||
|
||||
**Backward Compatibility:**
|
||||
All fields are optional and default to OpenAI-compatible behavior. Existing provider configurations are unaffected.
|
||||
|
||||
@ -29,7 +29,7 @@ macOS runner runs jobs **directly on the host** (no Docker container) — macOS
|
||||
|
||||
## Test Pipeline (`.woodpecker/test.yml`)
|
||||
|
||||
**Triggers:** Every push and pull request to any branch.
|
||||
**Triggers:** Pull requests only.
|
||||
|
||||
```
|
||||
Pipeline steps:
|
||||
@ -65,20 +65,27 @@ steps:
|
||||
|
||||
---
|
||||
|
||||
## Release Pipeline (`.gitea/workflows/release.yml`)
|
||||
## Release Pipeline (`.gitea/workflows/auto-tag.yml`)
|
||||
|
||||
**Triggers:** Git tags matching `v*`
|
||||
**Triggers:** Pushes to `master` (auto-tag), then release build/upload jobs run after `autotag`.
|
||||
|
||||
Auto tags are created by `.gitea/workflows/auto-tag.yml` using `git tag` + `git push`.
|
||||
Release jobs are executed in the same workflow and depend on `autotag` completion.
|
||||
|
||||
```
|
||||
Jobs (run in parallel):
|
||||
build-linux-amd64 → cargo tauri build (x86_64-unknown-linux-gnu)
|
||||
→ {.deb, .rpm, .AppImage} uploaded to Gitea release
|
||||
→ fails fast if no Linux artifacts are produced
|
||||
build-windows-amd64 → cargo tauri build (x86_64-pc-windows-gnu) via mingw-w64
|
||||
→ {.exe, .msi} uploaded to Gitea release
|
||||
→ fails fast if no Windows artifacts are produced
|
||||
build-linux-arm64 → cargo tauri build (aarch64-unknown-linux-gnu)
|
||||
→ {.deb, .rpm, .AppImage} uploaded to Gitea release
|
||||
→ fails fast if no Linux artifacts are produced
|
||||
build-macos-arm64 → cargo tauri build (aarch64-apple-darwin) — runs on local Mac
|
||||
→ {.dmg} uploaded to Gitea release
|
||||
→ existing same-name assets are deleted before upload (rerun-safe)
|
||||
→ unsigned; after install run: xattr -cr /Applications/TFTSR.app
|
||||
```
|
||||
|
||||
@ -102,7 +109,7 @@ the repo directly within its commands (using `http://172.0.0.29:3000`, accessibl
|
||||
the local machine) and uploads its artifacts inline. The `upload-release` step (amd64)
|
||||
handles amd64 + windows artifacts only.
|
||||
|
||||
**Clone override (release.yml — amd64 workspace):**
|
||||
**Clone override (auto-tag.yml — amd64 workspace):**
|
||||
|
||||
```yaml
|
||||
clone:
|
||||
|
||||
@ -35,7 +35,8 @@ npm install --legacy-peer-deps
|
||||
| Variable | Default | Purpose |
|
||||
|----------|---------|---------|
|
||||
| `TFTSR_DATA_DIR` | Platform data dir | Override DB location |
|
||||
| `TFTSR_DB_KEY` | `dev-key-change-in-prod` | DB encryption key (required in production) |
|
||||
| `TFTSR_DB_KEY` | _(none)_ | DB encryption key (required in release builds) |
|
||||
| `TFTSR_ENCRYPTION_KEY` | _(none)_ | Credential encryption key (required in release builds) |
|
||||
| `RUST_LOG` | `info` | Tracing verbosity: `debug`, `info`, `warn`, `error` |
|
||||
|
||||
Application data is stored at:
|
||||
@ -120,7 +121,7 @@ cargo tauri build
|
||||
# Outputs: .deb, .rpm, .AppImage (Linux)
|
||||
```
|
||||
|
||||
Release builds enable **SQLCipher AES-256** encryption. Set `TFTSR_DB_KEY` before building.
|
||||
Release builds enforce secure key configuration. Set both `TFTSR_DB_KEY` and `TFTSR_ENCRYPTION_KEY` before building.
|
||||
|
||||
---
|
||||
|
||||
|
||||
6
Home.md
6
Home.md
@ -1,6 +1,6 @@
|
||||
# TFTSR — IT Triage & RCA Desktop Application
|
||||
# Troubleshooting and RCA Assistant
|
||||
|
||||
**TFTSR** is a secure desktop application for guided IT incident triage, root cause analysis (RCA), and post-mortem documentation. Built with Tauri 2.x (Rust + WebView) and React 18.
|
||||
**Troubleshooting and RCA Assistant** is a secure desktop application for guided IT incident triage, root cause analysis (RCA), and post-mortem documentation. Built with Tauri 2.x (Rust + WebView) and React 18.
|
||||
|
||||
**CI:**  — rustfmt · clippy · 64 Rust tests · tsc · vitest — all green
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
- **5-Whys AI Triage** — Interactive guided root cause analysis via multi-turn AI chat
|
||||
- **PII Auto-Redaction** — Detects and redacts sensitive data before any AI send
|
||||
- **Multi-Provider AI** — OpenAI, Anthropic Claude, Google Gemini, Mistral, AWS Bedrock (via LiteLLM), MSI GenAI (Motorola internal), local Ollama (fully offline)
|
||||
- **Custom Provider Support** — Flexible authentication (Bearer, custom headers) and API formats (OpenAI-compatible, MSI GenAI)
|
||||
- **Custom Provider Support** — Flexible authentication (Bearer, custom headers) and API formats (OpenAI-compatible, Custom REST)
|
||||
- **External Integrations** — Confluence, ServiceNow, Azure DevOps with OAuth2 PKCE flows
|
||||
- **SQLCipher AES-256** — All issue history and credentials encrypted at rest
|
||||
- **RCA + Post-Mortem Generation** — Auto-populated Markdown templates, exportable as MD/PDF
|
||||
|
||||
@ -10,7 +10,7 @@ Before any text is sent to an AI provider, TFTSR scans it for personally identif
|
||||
1. Upload log file
|
||||
↓
|
||||
2. detect_pii(log_file_id)
|
||||
→ Scans content with 13 regex patterns
|
||||
→ Scans content with PII regex patterns (including hostname + expanded card brands)
|
||||
→ Resolves overlapping matches (longest wins)
|
||||
→ Returns Vec<PiiSpan> with byte offsets + replacements
|
||||
↓
|
||||
@ -24,7 +24,7 @@ Before any text is sent to an AI provider, TFTSR scans it for personally identif
|
||||
5. Redacted text safe to send to AI
|
||||
```
|
||||
|
||||
## Detection Patterns (13 Types)
|
||||
## Detection Patterns
|
||||
|
||||
| Type | Replacement | Pattern notes |
|
||||
|------|-------------|---------------|
|
||||
@ -33,13 +33,13 @@ Before any text is sent to an AI provider, TFTSR scans it for personally identif
|
||||
| `ApiKey` | `[ApiKey]` | `api_key=`, `apikey=`, `access_token=` + 16+ char value |
|
||||
| `Password` | `[Password]` | `password=`, `passwd=`, `pwd=` + non-whitespace value |
|
||||
| `Ssn` | `[SSN]` | `\b\d{3}-\d{2}-\d{4}\b` |
|
||||
| `CreditCard` | `[CreditCard]` | Visa/MC/Amex Luhn-format numbers |
|
||||
| `CreditCard` | `[CreditCard]` | Visa/MC/Amex/Discover/JCB/Diners patterns |
|
||||
| `Email` | `[Email]` | RFC-compliant email addresses |
|
||||
| `MacAddress` | `[MAC]` | `XX:XX:XX:XX:XX:XX` and `XX-XX-XX-XX-XX-XX` |
|
||||
| `Ipv6` | `[IPv6]` | Full and compressed IPv6 addresses |
|
||||
| `Ipv4` | `[IPv4]` | Standard dotted-quad notation |
|
||||
| `PhoneNumber` | `[Phone]` | US and international phone formats |
|
||||
| `Hostname` | _(patterns.rs)_ | Configurable hostname patterns |
|
||||
| `Hostname` | `[Hostname]` | FQDN/hostname detection for internal names |
|
||||
| `UrlCredentials` | _(covered by UrlWithCredentials)_ | |
|
||||
|
||||
## Overlap Resolution
|
||||
@ -71,7 +71,7 @@ pub struct PiiSpan {
|
||||
pub pii_type: PiiType,
|
||||
pub start: usize, // byte offset in original text
|
||||
pub end: usize,
|
||||
pub original_value: String,
|
||||
pub original: String,
|
||||
pub replacement: String, // e.g., "[IPv4]"
|
||||
}
|
||||
```
|
||||
@ -111,3 +111,4 @@ write_audit_event(
|
||||
- Only the redacted text is sent to AI providers
|
||||
- The SHA-256 hash in the audit log allows integrity verification
|
||||
- If redaction is skipped (no PII detected), the audit log still records the send
|
||||
- Stored `pii_spans.original_value` metadata is cleared after redaction is finalized
|
||||
|
||||
@ -18,20 +18,25 @@ Production builds use SQLCipher:
|
||||
- **Cipher:** AES-256-CBC
|
||||
- **KDF:** PBKDF2-HMAC-SHA512, 256,000 iterations
|
||||
- **HMAC:** HMAC-SHA512
|
||||
- **Page size:** 4096 bytes
|
||||
- **Page size:** 16384 bytes
|
||||
- **Key source:** `TFTSR_DB_KEY` environment variable
|
||||
|
||||
Debug builds use plain SQLite (no encryption) for developer convenience.
|
||||
|
||||
> ⚠️ **Never** use the default key (`dev-key-change-in-prod`) in a production environment.
|
||||
Release builds now fail startup if `TFTSR_DB_KEY` is missing or empty.
|
||||
|
||||
---
|
||||
|
||||
## API Key Storage (Stronghold)
|
||||
## Credential Encryption
|
||||
|
||||
AI provider API keys are stored in `tauri-plugin-stronghold` — an encrypted vault backed by the [IOTA Stronghold](https://github.com/iotaledger/stronghold.rs) library.
|
||||
Integration tokens are encrypted with AES-256-GCM before persistence:
|
||||
- **Key source:** `TFTSR_ENCRYPTION_KEY` (required in release builds)
|
||||
- **Key derivation:** SHA-256 hash of key material to a fixed 32-byte AES key
|
||||
- **Nonce:** Cryptographically secure random nonce per encryption
|
||||
|
||||
The vault is initialized with a password-derived key using Argon2. API keys are never written to disk in plaintext or to the SQLite database.
|
||||
Release builds fail secure operations if `TFTSR_ENCRYPTION_KEY` is unset or empty.
|
||||
|
||||
The Stronghold plugin remains enabled and now uses a per-installation salt derived from the app data directory path hash instead of a fixed static salt.
|
||||
|
||||
---
|
||||
|
||||
@ -46,6 +51,7 @@ log file → detect_pii() → user approves spans → apply_redactions() → AI
|
||||
- Original text **never leaves the machine**
|
||||
- Only the redacted version is transmitted
|
||||
- The SHA-256 hash of the redacted text is recorded in the audit log for integrity verification
|
||||
- `pii_spans.original_value` is cleared after redaction to avoid retaining raw detected secrets in storage
|
||||
- See [PII Detection](PII-Detection) for the full list of detected patterns
|
||||
|
||||
---
|
||||
@ -66,6 +72,14 @@ write_audit_event(
|
||||
|
||||
The audit log is stored in the encrypted SQLite database. It cannot be deleted through the UI.
|
||||
|
||||
### Tamper Evidence
|
||||
|
||||
`audit_log` entries now include:
|
||||
- `prev_hash` — hash of the previous audit entry
|
||||
- `entry_hash` — SHA-256 hash of current entry payload + `prev_hash`
|
||||
|
||||
This creates a hash chain and makes post-hoc modification detectable.
|
||||
|
||||
**Audit entry fields:**
|
||||
- `action` — what was done
|
||||
- `entity_type` — type of record involved
|
||||
@ -84,7 +98,7 @@ Defined in `src-tauri/capabilities/default.json`:
|
||||
|--------|-------------------|
|
||||
| `dialog` | `allow-open`, `allow-save` |
|
||||
| `fs` | `read-text`, `write-text`, `read`, `write`, `mkdir` — scoped to app dir and temp |
|
||||
| `shell` | `allow-execute` — for running system commands |
|
||||
| `shell` | `allow-open` only |
|
||||
| `http` | default — connect only to approved origins |
|
||||
|
||||
---
|
||||
@ -109,7 +123,9 @@ HTTP is blocked by default. Only whitelisted HTTPS endpoints (and localhost for
|
||||
|
||||
## TLS
|
||||
|
||||
All outbound HTTP requests use `reqwest` with default TLS settings (TLS 1.2+ required). Certificate verification is enabled. No custom trust anchors are added.
|
||||
All outbound HTTP requests use `reqwest` with certificate verification enabled and a request timeout configured for provider calls.
|
||||
|
||||
CI/CD currently uses internal `http://` endpoints for self-hosted Gitea release automation on a trusted LAN. Recommended hardening: migrate runners and API calls to HTTPS with internal certificates.
|
||||
|
||||
---
|
||||
|
||||
@ -120,3 +136,4 @@ All outbound HTTP requests use `reqwest` with default TLS settings (TLS 1.2+ req
|
||||
- [ ] Does it store secrets? → Use Stronghold, not the SQLite DB
|
||||
- [ ] Does it need filesystem access? → Scope the fs capability
|
||||
- [ ] Does it need a new HTTP endpoint? → Add to CSP `connect-src`
|
||||
- [ ] Does it add a new provider endpoint? → Avoid query-param secrets, use auth headers
|
||||
|
||||
Loading…
Reference in New Issue
Block a user