docs: sync from docs/wiki/ at commit 0f1f4fcb

Gitea Actions 2026-05-31 23:12:49 +00:00
parent 1ab9d0a7cb
commit 20543b83cb
2 changed files with 105 additions and 1 deletions

@ -2,7 +2,7 @@
## Overview
TFTSR uses **SQLite** via `rusqlite` with the `bundled-sqlcipher` feature for AES-256 encryption in production. 18 versioned migrations are tracked in the `_migrations` table.
TFTSR uses **SQLite** via `rusqlite` with the `bundled-sqlcipher` feature for AES-256 encryption in production. 22 versioned migrations are tracked in the `_migrations` table.
**DB file location:** `{app_data_dir}/tftsr.db`
@ -344,6 +344,51 @@ CREATE TABLE mcp_resources (
- Cascade deletes ensure removing a server cleans up all associated tools and resources
- Tools and resources are replaced atomically on each discovery run (delete-all + re-insert)
### 020 — log_files content storage (Attachment Recall v0.4+)
```sql
ALTER TABLE log_files ADD COLUMN content_compressed BLOB;
```
Stores gzip-compressed extracted text for every log file uploaded after migration 020. Existing rows remain `NULL` and fall back to the `file_path` column.
**Compression:** pure-Rust gzip via `flate2` (`rust_backend` / `miniz_oxide`) — no external binary dependency, works identically on Linux, Windows, macOS.
**Usage:** The `get_log_file_content` command reads and decompresses this column. The column is never serialised to the frontend directly — content is requested on demand via IPC.
### 021 — image_attachments byte storage (Attachment Recall v0.4+)
```sql
ALTER TABLE image_attachments ADD COLUMN image_data BLOB;
```
Stores raw image bytes for every image uploaded after migration 021. Existing rows fall back to `file_path`. Images are already compressed (PNG/JPEG) so no additional compression is applied.
**Usage:** `get_image_attachment_data` reads this column and base64-encodes it into a data URL for frontend display. The `ImageThumbnail` component in the History → Attachments tab calls this on mount for each visible image.
### 022 — attachment cross-incident views (Attachment Recall v0.4+)
Two read-only views joining attachments with their parent issue titles:
```sql
CREATE VIEW IF NOT EXISTS v_log_files_with_issue AS
SELECT lf.id, lf.issue_id, lf.file_name, lf.file_path, lf.file_size,
lf.mime_type, lf.content_hash, lf.uploaded_at, lf.redacted,
i.title AS issue_title
FROM log_files lf
JOIN issues i ON i.id = lf.issue_id;
CREATE VIEW IF NOT EXISTS v_image_attachments_with_issue AS
SELECT ia.id, ia.issue_id, ia.file_name, ia.file_path, ia.file_size,
ia.mime_type, ia.upload_hash, ia.uploaded_at,
ia.pii_warning_acknowledged, ia.is_paste,
i.title AS issue_title
FROM image_attachments ia
JOIN issues i ON i.id = ia.issue_id;
```
Used by `list_all_log_files` and `list_all_image_attachments` to power the cross-incident Attachments tab in the History page. Explicitly selects named columns (not `SELECT *`) to avoid including the BLOB data in list queries.
---
## Key Design Notes

@ -113,6 +113,34 @@ applyRedactionsCmd(logFileId: string, approvedSpanIds: string[]) → RedactedLog
```
Rewrites file content with approved redactions. Records SHA-256 in audit log. Returns redacted content path.
### `get_log_file_content`
```typescript
getLogFileContentCmd(logFileId: string) → string
```
Returns the plain-text content of a log file. Primary path: reads gzip-compressed BLOB from the `content_compressed` column and decompresses in-process (no external binary required). Fallback: reads from `file_path` on disk for records uploaded before migration 020.
Used by the triage chat context loader and the "View" modal in the Attachments tab.
### `list_all_log_files`
```typescript
listAllLogFilesCmd(search?: string, issueId?: string) → LogFileSummary[]
```
Cross-incident log file listing via `v_log_files_with_issue`. Optional `search` performs `file_name LIKE '%q%'`; optional `issueId` filters to a single incident. Ordered by `uploaded_at DESC`. Never includes the compressed content blob — content is fetched separately via `get_log_file_content`.
```typescript
interface LogFileSummary {
id: string;
issue_id: string;
issue_title: string; // joined from issues table
file_name: string;
file_path: string;
file_size: number;
mime_type: string;
content_hash: string;
uploaded_at: string;
redacted: boolean;
}
```
---
## Image Attachment Commands
@ -141,6 +169,37 @@ uploadPasteImageCmd(issueId: string, base64Data: string, fileName: string, piiWa
```
Uploads an image from clipboard paste (base64). Returns `ImageAttachment` record.
**Note (v0.4+):** All three upload commands (`upload_image_attachment`, `upload_image_attachment_by_content`, `upload_paste_image`) now also store the raw image bytes in the `image_data` column of `image_attachments`, enabling retrieval without requiring the source file on disk.
### `get_image_attachment_data`
```typescript
getImageAttachmentDataCmd(attachmentId: string) → string
```
Returns image content as a base64 data URL (`data:<mime>;base64,...`). Primary path: reads raw bytes from the `image_data` BLOB column. Fallback: reads from `file_path` on disk for records uploaded before migration 021.
Suitable for use directly as an `<img src>` value or in the "View" modal.
### `list_all_image_attachments`
```typescript
listAllImageAttachmentsCmd(search?: string, issueId?: string) → ImageAttachmentSummary[]
```
Cross-incident image listing via `v_image_attachments_with_issue`. Optional `search` performs `file_name LIKE '%q%'`; optional `issueId` filters to a single incident. Ordered by `uploaded_at DESC`. Never includes the raw image bytes blob.
```typescript
interface ImageAttachmentSummary {
id: string;
issue_id: string;
issue_title: string; // joined from issues table
file_name: string;
file_path: string;
file_size: number;
mime_type: string;
upload_hash: string;
uploaded_at: string;
pii_warning_acknowledged: boolean;
is_paste: boolean;
}
```
---
## AI Commands