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"` |
|
| `config.name` | `"gemini"` |
|
||||||
| URL | `https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent` |
|
| 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 |
|
| Max tokens | 4096 |
|
||||||
|
|
||||||
**Models:** `gemini-2.0-flash`, `gemini-2.0-pro`, `gemini-1.5-pro`, `gemini-1.5-flash`
|
**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
|
### 4. Mistral AI
|
||||||
|
|
||||||
| Field | Value |
|
| 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)
|
**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.
|
**Motorola Solutions Internal GenAI Service** — Enterprise AI platform with centralized cost tracking and model access.
|
||||||
|
|
||||||
| Field | Value |
|
| Field | Value |
|
||||||
|-------|-------|
|
|-------|-------|
|
||||||
| `config.provider_type` | `"custom"` |
|
| `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) |
|
| 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 Header | `x-msi-genai-api-key` |
|
||||||
| Auth Prefix | `` (empty - no Bearer prefix) |
|
| Auth Prefix | `` (empty - no Bearer prefix) |
|
||||||
| Endpoint Path | `` (empty - URL includes full path `/api/v2/chat`) |
|
| Endpoint Path | `` (empty - URL includes full path `/api/v2/chat`) |
|
||||||
|
|
||||||
**Available Models:**
|
**Available Models (dropdown in Settings):**
|
||||||
- `VertexGemini` — Gemini 2.0 Flash (Private/GCP)
|
- `VertexGemini` — Gemini 2.0 Flash (Private/GCP)
|
||||||
- `Claude-Sonnet-4` — Claude Sonnet 4 (Public/Anthropic)
|
- `Claude-Sonnet-4` — Claude Sonnet 4 (Public/Anthropic)
|
||||||
- `ChatGPT4o` — GPT-4o (Public/OpenAI)
|
- `ChatGPT4o` — GPT-4o (Public/OpenAI)
|
||||||
- `ChatGPT-5_2-Chat` — GPT-4.5 (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:**
|
**Request Format:**
|
||||||
```json
|
```json
|
||||||
@ -187,9 +196,9 @@ Standard OpenAI `/chat/completions` endpoint with Bearer authentication.
|
|||||||
|
|
||||||
**Configuration (Settings → AI Providers → Add Provider):**
|
**Configuration (Settings → AI Providers → Add Provider):**
|
||||||
```
|
```
|
||||||
Name: MSI GenAI
|
Name: Custom REST (MSI GenAI)
|
||||||
Type: Custom
|
Type: Custom
|
||||||
API Format: MSI GenAI
|
API Format: Custom REST
|
||||||
API URL: https://genai-service.stage.commandcentral.com/app-gateway
|
API URL: https://genai-service.stage.commandcentral.com/app-gateway
|
||||||
Model: VertexGemini
|
Model: VertexGemini
|
||||||
API Key: (your MSI GenAI API key from portal)
|
API Key: (your MSI GenAI API key from portal)
|
||||||
@ -208,13 +217,13 @@ Auth Prefix: (leave empty)
|
|||||||
| Error | Cause | Solution |
|
| Error | Cause | Solution |
|
||||||
|-------|-------|----------|
|
|-------|-------|----------|
|
||||||
| 403 Forbidden | Invalid API key or insufficient permissions | Verify key in MSI GenAI portal, check model access |
|
| 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 |
|
| No conversation history | `sessionId` not persisted | Session ID stored in `ProviderConfig.session_id` — currently per-provider, not per-conversation |
|
||||||
|
|
||||||
**Implementation Details:**
|
**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)
|
- 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
|
- 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_endpoint_path` | `Option<String>` | Override endpoint path | `/chat/completions` |
|
||||||
| `custom_auth_header` | `Option<String>` | Custom auth header name | `Authorization` |
|
| `custom_auth_header` | `Option<String>` | Custom auth header name | `Authorization` |
|
||||||
| `custom_auth_prefix` | `Option<String>` | Prefix before API key | `Bearer ` |
|
| `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 |
|
| `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:**
|
**Backward Compatibility:**
|
||||||
All fields are optional and default to OpenAI-compatible behavior. Existing provider configurations are unaffected.
|
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`)
|
## Test Pipeline (`.woodpecker/test.yml`)
|
||||||
|
|
||||||
**Triggers:** Every push and pull request to any branch.
|
**Triggers:** Pull requests only.
|
||||||
|
|
||||||
```
|
```
|
||||||
Pipeline steps:
|
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):
|
Jobs (run in parallel):
|
||||||
build-linux-amd64 → cargo tauri build (x86_64-unknown-linux-gnu)
|
build-linux-amd64 → 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
|
||||||
build-windows-amd64 → cargo tauri build (x86_64-pc-windows-gnu) via mingw-w64
|
build-windows-amd64 → 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
|
||||||
build-linux-arm64 → cargo tauri build (aarch64-unknown-linux-gnu)
|
build-linux-arm64 → 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
|
||||||
build-macos-arm64 → cargo tauri build (aarch64-apple-darwin) — runs on local Mac
|
build-macos-arm64 → cargo tauri build (aarch64-apple-darwin) — runs on local Mac
|
||||||
→ {.dmg} uploaded to Gitea release
|
→ {.dmg} uploaded to Gitea release
|
||||||
|
→ existing same-name assets are deleted before upload (rerun-safe)
|
||||||
→ unsigned; after install run: xattr -cr /Applications/TFTSR.app
|
→ 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)
|
the local machine) and uploads its artifacts inline. The `upload-release` step (amd64)
|
||||||
handles amd64 + windows artifacts only.
|
handles amd64 + windows artifacts only.
|
||||||
|
|
||||||
**Clone override (release.yml — amd64 workspace):**
|
**Clone override (auto-tag.yml — amd64 workspace):**
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
clone:
|
clone:
|
||||||
|
|||||||
@ -35,7 +35,8 @@ npm install --legacy-peer-deps
|
|||||||
| Variable | Default | Purpose |
|
| Variable | Default | Purpose |
|
||||||
|----------|---------|---------|
|
|----------|---------|---------|
|
||||||
| `TFTSR_DATA_DIR` | Platform data dir | Override DB location |
|
| `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` |
|
| `RUST_LOG` | `info` | Tracing verbosity: `debug`, `info`, `warn`, `error` |
|
||||||
|
|
||||||
Application data is stored at:
|
Application data is stored at:
|
||||||
@ -120,7 +121,7 @@ cargo tauri build
|
|||||||
# Outputs: .deb, .rpm, .AppImage (Linux)
|
# 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
|
**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
|
- **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
|
- **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)
|
- **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
|
- **External Integrations** — Confluence, ServiceNow, Azure DevOps with OAuth2 PKCE flows
|
||||||
- **SQLCipher AES-256** — All issue history and credentials encrypted at rest
|
- **SQLCipher AES-256** — All issue history and credentials encrypted at rest
|
||||||
- **RCA + Post-Mortem Generation** — Auto-populated Markdown templates, exportable as MD/PDF
|
- **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
|
1. Upload log file
|
||||||
↓
|
↓
|
||||||
2. detect_pii(log_file_id)
|
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)
|
→ Resolves overlapping matches (longest wins)
|
||||||
→ Returns Vec<PiiSpan> with byte offsets + replacements
|
→ 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
|
5. Redacted text safe to send to AI
|
||||||
```
|
```
|
||||||
|
|
||||||
## Detection Patterns (13 Types)
|
## Detection Patterns
|
||||||
|
|
||||||
| Type | Replacement | Pattern notes |
|
| 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 |
|
| `ApiKey` | `[ApiKey]` | `api_key=`, `apikey=`, `access_token=` + 16+ char value |
|
||||||
| `Password` | `[Password]` | `password=`, `passwd=`, `pwd=` + non-whitespace value |
|
| `Password` | `[Password]` | `password=`, `passwd=`, `pwd=` + non-whitespace value |
|
||||||
| `Ssn` | `[SSN]` | `\b\d{3}-\d{2}-\d{4}\b` |
|
| `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 |
|
| `Email` | `[Email]` | RFC-compliant email addresses |
|
||||||
| `MacAddress` | `[MAC]` | `XX:XX:XX:XX:XX:XX` and `XX-XX-XX-XX-XX-XX` |
|
| `MacAddress` | `[MAC]` | `XX:XX:XX:XX:XX:XX` and `XX-XX-XX-XX-XX-XX` |
|
||||||
| `Ipv6` | `[IPv6]` | Full and compressed IPv6 addresses |
|
| `Ipv6` | `[IPv6]` | Full and compressed IPv6 addresses |
|
||||||
| `Ipv4` | `[IPv4]` | Standard dotted-quad notation |
|
| `Ipv4` | `[IPv4]` | Standard dotted-quad notation |
|
||||||
| `PhoneNumber` | `[Phone]` | US and international phone formats |
|
| `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)_ | |
|
| `UrlCredentials` | _(covered by UrlWithCredentials)_ | |
|
||||||
|
|
||||||
## Overlap Resolution
|
## Overlap Resolution
|
||||||
@ -71,7 +71,7 @@ pub struct PiiSpan {
|
|||||||
pub pii_type: PiiType,
|
pub pii_type: PiiType,
|
||||||
pub start: usize, // byte offset in original text
|
pub start: usize, // byte offset in original text
|
||||||
pub end: usize,
|
pub end: usize,
|
||||||
pub original_value: String,
|
pub original: String,
|
||||||
pub replacement: String, // e.g., "[IPv4]"
|
pub replacement: String, // e.g., "[IPv4]"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -111,3 +111,4 @@ write_audit_event(
|
|||||||
- Only the redacted text is sent to AI providers
|
- Only the redacted text is sent to AI providers
|
||||||
- The SHA-256 hash in the audit log allows integrity verification
|
- 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
|
- 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
|
- **Cipher:** AES-256-CBC
|
||||||
- **KDF:** PBKDF2-HMAC-SHA512, 256,000 iterations
|
- **KDF:** PBKDF2-HMAC-SHA512, 256,000 iterations
|
||||||
- **HMAC:** HMAC-SHA512
|
- **HMAC:** HMAC-SHA512
|
||||||
- **Page size:** 4096 bytes
|
- **Page size:** 16384 bytes
|
||||||
- **Key source:** `TFTSR_DB_KEY` environment variable
|
- **Key source:** `TFTSR_DB_KEY` environment variable
|
||||||
|
|
||||||
Debug builds use plain SQLite (no encryption) for developer convenience.
|
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**
|
- Original text **never leaves the machine**
|
||||||
- Only the redacted version is transmitted
|
- Only the redacted version is transmitted
|
||||||
- The SHA-256 hash of the redacted text is recorded in the audit log for integrity verification
|
- 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
|
- 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.
|
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:**
|
**Audit entry fields:**
|
||||||
- `action` — what was done
|
- `action` — what was done
|
||||||
- `entity_type` — type of record involved
|
- `entity_type` — type of record involved
|
||||||
@ -84,7 +98,7 @@ Defined in `src-tauri/capabilities/default.json`:
|
|||||||
|--------|-------------------|
|
|--------|-------------------|
|
||||||
| `dialog` | `allow-open`, `allow-save` |
|
| `dialog` | `allow-open`, `allow-save` |
|
||||||
| `fs` | `read-text`, `write-text`, `read`, `write`, `mkdir` — scoped to app dir and temp |
|
| `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 |
|
| `http` | default — connect only to approved origins |
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -109,7 +123,9 @@ HTTP is blocked by default. Only whitelisted HTTPS endpoints (and localhost for
|
|||||||
|
|
||||||
## TLS
|
## 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 store secrets? → Use Stronghold, not the SQLite DB
|
||||||
- [ ] Does it need filesystem access? → Scope the fs capability
|
- [ ] Does it need filesystem access? → Scope the fs capability
|
||||||
- [ ] Does it need a new HTTP endpoint? → Add to CSP `connect-src`
|
- [ ] 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