docs: sync wiki with latest changes including LiteLLM + Bedrock guide
parent
10e1491638
commit
10b14a2ffe
@ -19,7 +19,7 @@ pub trait Provider {
|
||||
|
||||
### 1. OpenAI-Compatible
|
||||
|
||||
Covers: OpenAI, Azure OpenAI, LM Studio, vLLM, and any OpenAI-API-compatible endpoint.
|
||||
Covers: OpenAI, Azure OpenAI, LM Studio, vLLM, **LiteLLM (AWS Bedrock)**, and any OpenAI-API-compatible endpoint.
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
@ -30,7 +30,9 @@ Covers: OpenAI, Azure OpenAI, LM Studio, vLLM, and any OpenAI-API-compatible end
|
||||
|
||||
**Models:** `gpt-4o`, `gpt-4o-mini`, `gpt-4-turbo`
|
||||
|
||||
**Custom endpoint:** Set `config.base_url` to any OpenAI-compatible API (e.g., LM Studio at `http://localhost:1234/v1`).
|
||||
**Custom endpoint:** Set `config.base_url` to any OpenAI-compatible API:
|
||||
- LM Studio: `http://localhost:1234/v1`
|
||||
- **LiteLLM (AWS Bedrock):** `http://localhost:8000/v1` — See [LiteLLM + Bedrock Setup](LiteLLM-Bedrock-Setup) for full configuration guide
|
||||
|
||||
---
|
||||
|
||||
|
||||
243
CICD-Pipeline.md
243
CICD-Pipeline.md
@ -4,10 +4,26 @@
|
||||
|
||||
| Component | URL | Notes |
|
||||
|-----------|-----|-------|
|
||||
| Gogs | `http://172.0.0.29:3000` / `https://gogs.tftsr.com` | Git server, version 0.14 |
|
||||
| Woodpecker CI (direct) | `http://172.0.0.29:8084` | v0.15.4 |
|
||||
| Woodpecker CI (proxy) | `http://172.0.0.29:8085` | nginx with custom login page |
|
||||
| PostgreSQL (Gogs DB) | Container: `gogs_postgres_db` | DB: `gogsdb`, User: `gogs` |
|
||||
| Gitea | `https://gogs.tftsr.com` / `http://172.0.0.29:3000` | Git server (migrated from Gogs 0.14) |
|
||||
| Woodpecker CI (direct) | `http://172.0.0.29:8084` | v2.x |
|
||||
| Woodpecker CI (proxy) | `http://172.0.0.29:8085` | nginx reverse proxy |
|
||||
| PostgreSQL (Gitea DB) | Container: `gogs_postgres_db` | DB: `gogsdb`, User: `gogs` |
|
||||
|
||||
### CI Agents
|
||||
|
||||
| Agent | Platform | Host | Purpose |
|
||||
|-------|----------|------|---------|
|
||||
| `gitea_act_runner_amd64` (Docker) | `linux-amd64` | 172.0.0.29 | Native x86_64 — test builds + amd64/windows release |
|
||||
| `act_runner` (systemd) | `linux-arm64` | 172.0.0.29 | Native aarch64 — arm64 release builds |
|
||||
| `act_runner` (launchd) | `macos-arm64` | sarman's local Mac | Native Apple Silicon — macOS `.dmg` release builds |
|
||||
|
||||
Agent labels configured in `~/.config/act_runner/config.yaml`:
|
||||
```yaml
|
||||
runner:
|
||||
labels:
|
||||
- "macos-arm64:host"
|
||||
```
|
||||
macOS runner runs jobs **directly on the host** (no Docker container) — macOS SDK cannot run in Docker.
|
||||
|
||||
---
|
||||
|
||||
@ -19,140 +35,227 @@
|
||||
Pipeline steps:
|
||||
1. rust-fmt-check → cargo fmt --check
|
||||
2. rust-clippy → cargo clippy -- -D warnings
|
||||
3. rust-tests → cargo test
|
||||
3. rust-tests → cargo test (64 tests)
|
||||
4. frontend-typecheck → npx tsc --noEmit
|
||||
5. frontend-tests → npm run test:run (Vitest)
|
||||
5. frontend-tests → npm run test:run (13 Vitest tests)
|
||||
```
|
||||
|
||||
**Docker images used:**
|
||||
- `rust:1.88-slim` — Rust steps (minimum for cookie_store + time + darling)
|
||||
- `node:22-alpine` — Frontend steps
|
||||
|
||||
**System dependencies installed in CI (Rust steps):**
|
||||
```
|
||||
libwebkit2gtk-4.1-dev, libssl-dev, libgtk-3-dev, libsoup-3.0-dev,
|
||||
librsvg2-dev, libglib2.0-dev
|
||||
```
|
||||
|
||||
**Pipeline YAML format (Woodpecker 0.15.4 — legacy MAP format):**
|
||||
**Pipeline YAML format (Woodpecker 2.x — steps list format):**
|
||||
```yaml
|
||||
clone:
|
||||
git:
|
||||
image: woodpeckerci/plugin-git
|
||||
network_mode: gogs_default # requires repo_trusted=1
|
||||
environment:
|
||||
- CI_REPO_CLONE_URL=http://gogs_app:3000/sarman/tftsr-devops_investigation.git
|
||||
- CI_REPO_CLONE_URL=http://gitea_app:3000/sarman/tftsr-devops_investigation.git
|
||||
|
||||
pipeline:
|
||||
step-name: # KEY = step name (MAP, not list!)
|
||||
steps:
|
||||
- name: step-name # LIST format (- name:)
|
||||
image: rust:1.88-slim
|
||||
commands:
|
||||
- cargo test
|
||||
```
|
||||
|
||||
> ⚠️ **Do NOT** use the newer `steps:` list format — Woodpecker 0.15.4 uses the Drone-legacy map format.
|
||||
> ⚠️ Woodpecker 2.x uses the `steps:` list format. The legacy `pipeline:` map format from
|
||||
> Woodpecker 0.15.4 is no longer supported.
|
||||
|
||||
---
|
||||
|
||||
## Release Pipeline (`.woodpecker/release.yml`)
|
||||
## Release Pipeline (`.gitea/workflows/release.yml`)
|
||||
|
||||
**Triggers:** Git tags matching `v*`
|
||||
|
||||
```
|
||||
Pipeline steps:
|
||||
1. build-linux-amd64 → cargo tauri build (x86_64-unknown-linux-gnu)
|
||||
2. build-linux-arm64 → cargo tauri build (aarch64-unknown-linux-gnu, cross-compile)
|
||||
3. upload-release → Create Gogs release + upload artifacts via API
|
||||
Jobs (run in parallel):
|
||||
build-linux-amd64 → cargo tauri build (x86_64-unknown-linux-gnu)
|
||||
→ {.deb, .rpm, .AppImage} uploaded to Gitea release
|
||||
build-windows-amd64 → cargo tauri build (x86_64-pc-windows-gnu) via mingw-w64
|
||||
→ {.exe, .msi} uploaded to Gitea release
|
||||
build-linux-arm64 → cargo tauri build (aarch64-unknown-linux-gnu)
|
||||
→ {.deb, .rpm, .AppImage} uploaded to Gitea release
|
||||
build-macos-arm64 → cargo tauri build (aarch64-apple-darwin) — runs on local Mac
|
||||
→ {.dmg} uploaded to Gitea release
|
||||
→ unsigned; after install run: xattr -cr /Applications/TFTSR.app
|
||||
```
|
||||
|
||||
**Per-step agent routing (Woodpecker 2.x labels):**
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- name: build-linux-amd64
|
||||
labels:
|
||||
platform: linux/amd64 # → woodpecker_agent on 172.0.0.29
|
||||
|
||||
- name: build-linux-arm64
|
||||
labels:
|
||||
platform: linux/arm64 # → woodpecker-agent.service on local arm64 machine
|
||||
```
|
||||
|
||||
**Multi-agent workspace isolation:**
|
||||
|
||||
Steps routed to different agents do **not** share a workspace. The arm64 step clones
|
||||
the repo directly within its commands (using `http://172.0.0.29:3000`, accessible from
|
||||
the local machine) and uploads its artifacts inline. The `upload-release` step (amd64)
|
||||
handles amd64 + windows artifacts only.
|
||||
|
||||
**Clone override (release.yml — amd64 workspace):**
|
||||
|
||||
```yaml
|
||||
clone:
|
||||
git:
|
||||
image: alpine/git
|
||||
network_mode: gogs_default
|
||||
commands:
|
||||
- git init -b master
|
||||
- git remote add origin http://gitea_app:3000/sarman/tftsr-devops_investigation.git
|
||||
- git fetch --depth=1 origin +refs/tags/${CI_COMMIT_TAG}:refs/tags/${CI_COMMIT_TAG}
|
||||
- git checkout ${CI_COMMIT_TAG}
|
||||
```
|
||||
|
||||
**Windows cross-compile environment:**
|
||||
```yaml
|
||||
environment:
|
||||
TARGET: x86_64-pc-windows-gnu
|
||||
CC_x86_64_pc_windows_gnu: x86_64-w64-mingw32-gcc
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER: x86_64-w64-mingw32-gcc
|
||||
```
|
||||
|
||||
**Artifacts per platform:**
|
||||
- Linux amd64: `.deb`, `.rpm`, `.AppImage`
|
||||
- Linux arm64: `.deb`, `.AppImage`
|
||||
- Windows amd64: `.exe` (NSIS installer), `.msi`
|
||||
- Linux arm64: `.deb`, `.rpm`, `.AppImage`
|
||||
|
||||
**Gogs Release API:**
|
||||
**Upload step (requires gogs_default network for amd64, host IP for arm64):**
|
||||
```yaml
|
||||
# amd64 upload step
|
||||
upload-release:
|
||||
image: curlimages/curl:latest
|
||||
labels:
|
||||
platform: linux/amd64
|
||||
network_mode: gogs_default
|
||||
secrets: [GOGS_TOKEN]
|
||||
```
|
||||
|
||||
The `GOGS_TOKEN` Woodpecker secret must be created via the Woodpecker UI or API after
|
||||
migration. The secret name stays `GOGS_TOKEN` for pipeline compatibility.
|
||||
|
||||
**Gitea Release API (replaces Gogs API — same endpoints, different container name):**
|
||||
```bash
|
||||
# Create release
|
||||
POST $API/repos/sarman/tftsr-devops_investigation/releases
|
||||
POST http://gitea_app:3000/api/v1/repos/sarman/tftsr-devops_investigation/releases
|
||||
Authorization: token $GOGS_TOKEN
|
||||
|
||||
# Upload artifact
|
||||
POST $API/repos/sarman/tftsr-devops_investigation/releases/{id}/assets
|
||||
POST http://gitea_app:3000/api/v1/repos/sarman/tftsr-devops_investigation/releases/{id}/assets
|
||||
```
|
||||
|
||||
The `GOGS_TOKEN` is stored as a Woodpecker secret.
|
||||
From the arm64 agent (local machine), use `http://172.0.0.29:3000/api/v1` instead.
|
||||
|
||||
---
|
||||
|
||||
## Multi-File Pipeline Support (Woodpecker 2.x)
|
||||
|
||||
Woodpecker 2.x supports multiple pipeline files in the `.woodpecker/` directory.
|
||||
All `.yml` files are evaluated on every trigger; `when:` conditions control which
|
||||
pipelines actually run.
|
||||
|
||||
Current files:
|
||||
- `.woodpecker/test.yml` — runs on every push/PR
|
||||
- `.woodpecker/release.yml` — runs on `v*` tags only
|
||||
|
||||
No DB config path switching needed (unlike Woodpecker 0.15.4).
|
||||
|
||||
---
|
||||
|
||||
## Webhook Configuration
|
||||
|
||||
**Hook ID:** 6 (in Gogs)
|
||||
**Events:** `create`, `push`, `pull_request`
|
||||
**URL:** `http://172.0.0.29:8084/hook?access_token=<JWT>`
|
||||
**Woodpecker 2.x with Gitea OAuth2:**
|
||||
|
||||
**JWT signing:**
|
||||
- Algorithm: HS256
|
||||
- Secret: `repo_hash` value from Woodpecker DB (`dK8zFWtAu67qfKd3Et6N8LptqTmedumJ`)
|
||||
- Payload: `{"text":"sarman/tftsr-devops_investigation","type":"hook"}`
|
||||
After migration, Woodpecker 2.x registers webhooks automatically when a repo is
|
||||
activated via the UI. No manual JWT-signed webhook setup required.
|
||||
|
||||
> ⚠️ JWT has an `iat` claim. If it's stale, regenerate it.
|
||||
1. Log in at `http://172.0.0.29:8085` via Gitea OAuth2
|
||||
2. Add repo `sarman/tftsr-devops_investigation`
|
||||
3. Woodpecker creates webhook in Gitea automatically
|
||||
|
||||
---
|
||||
|
||||
## Woodpecker DB State
|
||||
## Branch Protection
|
||||
|
||||
SQLite at `/docker_mounts/woodpecker/data/woodpecker.sqlite` (on host `172.0.0.29`).
|
||||
Master branch is protected: all changes require a PR.
|
||||
|
||||
Key values:
|
||||
```sql
|
||||
-- User
|
||||
SELECT user_token FROM users WHERE user_login='sarman';
|
||||
-- Should be: a6b3ee679fe9601e983f1a0c01493758d6033ef3
|
||||
-- Gitea branch protection (via psql on gogs_postgres_db container)
|
||||
-- Check protection
|
||||
SELECT name, protected, require_pull_request FROM protect_branch WHERE repo_id=42;
|
||||
|
||||
-- Repo
|
||||
SELECT repo_active, repo_trusted, repo_config_path, repo_hash
|
||||
FROM repos WHERE repo_full_name='sarman/tftsr-devops_investigation';
|
||||
-- repo_active=1, repo_trusted=1
|
||||
-- repo_config_path='.woodpecker/test.yml'
|
||||
-- repo_hash='dK8zFWtAu67qfKd3Et6N8LptqTmedumJ'
|
||||
-- Temporarily disable for urgent fixes (restore immediately after!)
|
||||
UPDATE protect_branch SET protected=false WHERE repo_id=42 AND name='master';
|
||||
-- ... push ...
|
||||
UPDATE protect_branch SET protected=true, require_pull_request=true WHERE repo_id=42 AND name='master';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Known Issues & Fixes
|
||||
|
||||
### Webhook JWT Must Use `?access_token=`
|
||||
`token.ParseRequest()` in Woodpecker 0.15.4 does **not** read `?token=` URL params. Use `?access_token=<JWT>` instead.
|
||||
### Step Containers Cannot Reach `gitea_app`
|
||||
Default Docker bridge containers cannot resolve `gitea_app` or reach `172.0.0.29:3000`
|
||||
(host firewall). Fix: use `network_mode: gogs_default` in any step that needs Gitea
|
||||
access. Requires `repo_trusted=1`.
|
||||
|
||||
### JWT Signed with `repo_hash` (Not User Hash)
|
||||
Hook JWT must be signed with the `repo_hash` value, not the user's hash.
|
||||
### `CI=woodpecker` Rejected by Tauri CLI
|
||||
Woodpecker sets `CI=woodpecker`; `cargo tauri build` expects a boolean. Fix: prefix with
|
||||
`CI=true cargo tauri build`.
|
||||
|
||||
### Directory-Based Config Not Supported
|
||||
Woodpecker 0.15.4 only supports a **single config file**. Set `repo_config_path = .woodpecker/test.yml` in the Woodpecker DB. The `.woodpecker/` directory approach requires v2.x+.
|
||||
|
||||
### Step Containers Network Isolation
|
||||
Pipeline step containers run on the default Docker bridge and cannot resolve `gogs_app` hostname. Fix: set `network_mode: gogs_default` in the clone section (requires `repo_trusted=1`).
|
||||
|
||||
### Empty Clone URL Bug
|
||||
Woodpecker 0.15.4's `go-gogs-client` `PayloadRepo` struct lacks `CloneURL`/`SSHURL` fields, so `build_remote` is always empty from Gogs push payloads. Fix: override the clone URL via `CI_REPO_CLONE_URL` environment variable.
|
||||
|
||||
### Gogs Token Authentication
|
||||
The `sha1` field in Gogs token create API response **is** the actual bearer token (not a hash). Use it directly:
|
||||
```
|
||||
Authorization: token <sha1_from_create_response>
|
||||
### Agent Stalls After Server Restart
|
||||
After restarting the Woodpecker server, the agent may enter a loop cleaning up orphaned
|
||||
containers and stop picking up new builds. Fix:
|
||||
```bash
|
||||
docker rm -f $(docker ps -aq --filter 'name=0_')
|
||||
docker volume rm $(docker volume ls -q | grep '0_')
|
||||
docker restart woodpecker_agent
|
||||
```
|
||||
|
||||
### Gogs SPA Login Field Mismatch
|
||||
Gogs 0.14 SPA login form uses `login=` field; the Gogs backend reads `username=`. A custom login page is served by nginx at `/login`.
|
||||
### Windows DLL Export Ordinal Too Large
|
||||
`/usr/bin/x86_64-w64-mingw32-ld: error: export ordinal too large: 106290`
|
||||
|
||||
### Gogs OAuth2 Limitation
|
||||
Gogs 0.14 has no OAuth2 provider support, blocking upgrade to Woodpecker 2.x.
|
||||
Fix: `src-tauri/.cargo/config.toml`:
|
||||
```toml
|
||||
[target.x86_64-pc-windows-gnu]
|
||||
rustflags = ["-C", "link-arg=-Wl,--exclude-all-symbols"]
|
||||
```
|
||||
|
||||
### GOGS_TOKEN Secret Must Be Recreated After Migration
|
||||
After migrating from Woodpecker 0.15.4 to 2.x, recreate the `GOGS_TOKEN` secret:
|
||||
1. Log in to Gitea, create a new API token under Settings → Applications
|
||||
2. In Woodpecker UI → Repository → Secrets, add secret `GOGS_TOKEN` with the token value
|
||||
|
||||
---
|
||||
|
||||
## Gogs PostgreSQL Access
|
||||
## Gitea PostgreSQL Access
|
||||
|
||||
```bash
|
||||
docker exec gogs_postgres_db psql -U gogs -d gogsdb -c "SELECT id, lower_name FROM repository;"
|
||||
```
|
||||
|
||||
> Database name is `gogsdb`, not `gogs`.
|
||||
> Database name is `gogsdb` (unchanged from Gogs migration).
|
||||
|
||||
---
|
||||
|
||||
## Migration Notes (Gogs 0.14 → Gitea)
|
||||
|
||||
Gitea auto-migrates the Gogs PostgreSQL schema on first start. Users, repos, teams, and
|
||||
issues are preserved. API tokens stored in the DB are also migrated but should be
|
||||
regenerated for security.
|
||||
|
||||
Key changes after migration:
|
||||
- Container name: `gogs_app` → `gitea_app`
|
||||
- Config dir: `/data/gitea` (was `/data/gogs` inside container, same host volume)
|
||||
- Repo dir: `gogs-repositories` → `gitea-repositories` (renamed on host during migration)
|
||||
- OAuth2 provider: Gitea now supports OAuth2 (Woodpecker 2.x uses this for login)
|
||||
- Woodpecker 2.x multi-file pipeline support enabled (no more single config file limitation)
|
||||
|
||||
@ -90,7 +90,7 @@ npm run test:coverage
|
||||
npx tsc --noEmit
|
||||
```
|
||||
|
||||
Current test status: **13/13 frontend tests passing**, Rust tests passing.
|
||||
Current test status: **13/13 frontend tests passing**, **64/64 Rust tests passing**.
|
||||
|
||||
---
|
||||
|
||||
|
||||
27
Home.md
27
Home.md
@ -2,6 +2,8 @@
|
||||
|
||||
**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.
|
||||
|
||||
**CI:**  — rustfmt · clippy · 64 Rust tests · tsc · vitest — all green
|
||||
|
||||
## Quick Navigation
|
||||
|
||||
| Topic | Description |
|
||||
@ -10,9 +12,10 @@
|
||||
| [Development Setup](wiki/Development-Setup) | Prerequisites, commands, environment |
|
||||
| [Database](wiki/Database) | Schema, migrations, encryption |
|
||||
| [AI Providers](wiki/AI-Providers) | Supported providers and configuration |
|
||||
| [LiteLLM + Bedrock Setup](wiki/LiteLLM-Bedrock-Setup) | AWS Bedrock integration via LiteLLM proxy |
|
||||
| [PII Detection](wiki/PII-Detection) | Patterns, redaction flow, security |
|
||||
| [IPC Commands](wiki/IPC-Commands) | Full list of Tauri backend commands |
|
||||
| [CI/CD Pipeline](wiki/CICD-Pipeline) | Woodpecker CI + Gogs setup |
|
||||
| [CI/CD Pipeline](wiki/CICD-Pipeline) | Gitea Actions setup, multi-platform builds, act_runner config |
|
||||
| [Security Model](wiki/Security-Model) | Encryption, audit trail, capabilities |
|
||||
| [Integrations](wiki/Integrations) | Confluence, ServiceNow, Azure DevOps (v0.2) |
|
||||
| [Troubleshooting](wiki/Troubleshooting) | Known issues and fixes |
|
||||
@ -21,22 +24,30 @@
|
||||
|
||||
- **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, local Ollama (fully offline)
|
||||
- **Multi-Provider AI** — OpenAI, Anthropic Claude, Google Gemini, Mistral, AWS Bedrock (via LiteLLM), local Ollama (fully offline)
|
||||
- **SQLCipher AES-256** — All issue history encrypted at rest
|
||||
- **RCA + Post-Mortem Generation** — Auto-populated Markdown templates, exportable as MD/PDF
|
||||
- **Ollama Management** — Hardware detection, model recommendations, in-app model management
|
||||
- **Audit Trail** — Every external data send logged with SHA-256 hash
|
||||
- **Domain-Specific Prompts** — 8 IT domains: Linux, Windows, Network, Kubernetes, Databases, Virtualization, Hardware, Observability
|
||||
|
||||
## Releases
|
||||
|
||||
| Version | Status | Platforms |
|
||||
|---------|--------|-----------|
|
||||
| v0.1.1 | 🚀 Released | linux/amd64 · linux/arm64 · windows/amd64 (.deb, .rpm, .AppImage, .exe, .msi) |
|
||||
|
||||
Download from [Releases](https://gogs.tftsr.com/sarman/tftsr-devops_investigation/releases). All builds are produced natively (no QEMU emulation).
|
||||
|
||||
## Project Status
|
||||
|
||||
| Phase | Status |
|
||||
|-------|--------|
|
||||
| Phases 1–8 (Core) | ✅ Complete |
|
||||
| Phase 9 (History/Search FTS) | 🔄 Partially integrated |
|
||||
| Phases 1–8 (Core application) | ✅ Complete |
|
||||
| Phase 9 (History/Search) | 🔲 Pending |
|
||||
| Phase 10 (Integrations) | 🕐 v0.2 stubs only |
|
||||
| Phase 11 (CLI) | 🕐 Planned |
|
||||
| Phase 12 (Release packaging) | 🔄 Linux done; macOS/Windows pending |
|
||||
| Phase 11 (CI/CD) | ✅ Complete — Gitea Actions fully operational |
|
||||
| Phase 12 (Release packaging) | ✅ linux/amd64 · linux/arm64 (native) · windows/amd64 |
|
||||
|
||||
## Tech Stack
|
||||
|
||||
@ -49,5 +60,5 @@
|
||||
| Database | rusqlite + SQLCipher (AES-256) |
|
||||
| Secret storage | tauri-plugin-stronghold |
|
||||
| State | Zustand |
|
||||
| Testing | Vitest (frontend) + `#[cfg(test)]` (Rust) |
|
||||
| CI/CD | Woodpecker CI v0.15.4 + Gogs |
|
||||
| Testing | Vitest (13 frontend) + `#[cfg(test)]` (64 Rust tests) |
|
||||
| CI/CD | Gitea Actions (act_runner v0.3.1) + Gitea |
|
||||
|
||||
396
LiteLLM-Bedrock-Setup.md
Normal file
396
LiteLLM-Bedrock-Setup.md
Normal file
@ -0,0 +1,396 @@
|
||||
# LiteLLM + AWS Bedrock Setup
|
||||
|
||||
This guide covers how to use **Claude via AWS Bedrock** with TFTSR through the LiteLLM proxy, providing an OpenAI-compatible API gateway.
|
||||
|
||||
## Why LiteLLM + Bedrock?
|
||||
|
||||
- **Enterprise AWS contracts** — Use existing AWS Bedrock credits instead of direct Anthropic API
|
||||
- **Multiple AWS accounts** — Run personal and business Bedrock accounts simultaneously
|
||||
- **OpenAI-compatible API** — Works with any tool expecting OpenAI's API format
|
||||
- **Claude Code integration** — Reuse the same AWS credentials used by Claude Code CLI
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **AWS account** with Bedrock access and Claude models enabled
|
||||
- **AWS credentials** configured (either default profile or named profile)
|
||||
- **Python 3.8+** for LiteLLM installation
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
### 1. Install LiteLLM
|
||||
|
||||
```bash
|
||||
pip install 'litellm[proxy]'
|
||||
```
|
||||
|
||||
Verify installation:
|
||||
```bash
|
||||
litellm --version
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Basic Setup — Single AWS Account
|
||||
|
||||
### 1. Create Configuration File
|
||||
|
||||
Create `~/.litellm/config.yaml`:
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
- model_name: bedrock-claude
|
||||
litellm_params:
|
||||
model: bedrock/us.anthropic.claude-sonnet-4-6
|
||||
aws_region_name: us-east-1
|
||||
# Uses default AWS credentials from ~/.aws/credentials
|
||||
|
||||
general_settings:
|
||||
master_key: sk-1234 # Any value — used for API authentication
|
||||
```
|
||||
|
||||
### 2. Start LiteLLM Proxy
|
||||
|
||||
```bash
|
||||
# Run in background
|
||||
nohup litellm --config ~/.litellm/config.yaml --port 8000 > ~/.litellm/litellm.log 2>&1 &
|
||||
|
||||
# Verify it's running
|
||||
ps aux | grep litellm
|
||||
```
|
||||
|
||||
### 3. Test the Connection
|
||||
|
||||
```bash
|
||||
curl http://localhost:8000/v1/chat/completions \
|
||||
-H "Authorization: Bearer sk-1234" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"model": "bedrock-claude",
|
||||
"messages": [{"role": "user", "content": "Hello"}],
|
||||
"max_tokens": 50
|
||||
}'
|
||||
```
|
||||
|
||||
Expected response:
|
||||
```json
|
||||
{
|
||||
"id": "chatcmpl-...",
|
||||
"model": "bedrock-claude",
|
||||
"choices": [{
|
||||
"message": {
|
||||
"role": "assistant",
|
||||
"content": "Hello! How can I help you today?"
|
||||
}
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Configure TFTSR
|
||||
|
||||
In **Settings → AI Providers → Add Provider**:
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Provider Name | OpenAI |
|
||||
| Base URL | `http://localhost:8000/v1` |
|
||||
| API Key | `sk-1234` (or your master_key from config) |
|
||||
| Model | `bedrock-claude` |
|
||||
| Display Name | `Bedrock Claude` |
|
||||
|
||||
---
|
||||
|
||||
## Advanced Setup — Multiple AWS Accounts
|
||||
|
||||
If you have **personal** and **business** Bedrock accounts, you can run both through the same LiteLLM instance.
|
||||
|
||||
### 1. Configure AWS Profiles
|
||||
|
||||
Ensure you have AWS profiles set up in `~/.aws/credentials`:
|
||||
|
||||
```ini
|
||||
[default]
|
||||
aws_access_key_id = AKIA...
|
||||
aws_secret_access_key = ...
|
||||
|
||||
[ClaudeCodeLP]
|
||||
aws_access_key_id = AKIA...
|
||||
aws_secret_access_key = ...
|
||||
```
|
||||
|
||||
Or if using credential process (like Claude Code does):
|
||||
|
||||
```ini
|
||||
# ~/.aws/config
|
||||
[profile ClaudeCodeLP]
|
||||
credential_process = /Users/${USER}/claude-code-with-bedrock/credential-process --profile ClaudeCodeLP
|
||||
region = us-east-1
|
||||
```
|
||||
|
||||
### 2. Update Configuration File
|
||||
|
||||
Edit `~/.litellm/config.yaml`:
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
- model_name: bedrock-personal
|
||||
litellm_params:
|
||||
model: bedrock/us.anthropic.claude-sonnet-4-6
|
||||
aws_region_name: us-east-1
|
||||
# Uses default AWS credentials
|
||||
|
||||
- model_name: bedrock-business
|
||||
litellm_params:
|
||||
model: bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0
|
||||
aws_region_name: us-east-1
|
||||
aws_profile_name: ClaudeCodeLP # Named profile for business account
|
||||
|
||||
general_settings:
|
||||
master_key: sk-1234
|
||||
```
|
||||
|
||||
### 3. Restart LiteLLM
|
||||
|
||||
```bash
|
||||
# Find and stop existing process
|
||||
pkill -f "litellm --config"
|
||||
|
||||
# Start with new config
|
||||
nohup litellm --config ~/.litellm/config.yaml --port 8000 > ~/.litellm/litellm.log 2>&1 &
|
||||
```
|
||||
|
||||
### 4. Verify Both Models
|
||||
|
||||
```bash
|
||||
# List available models
|
||||
curl -s http://localhost:8000/v1/models \
|
||||
-H "Authorization: Bearer sk-1234" | python3 -m json.tool
|
||||
|
||||
# Test personal account
|
||||
curl -s http://localhost:8000/v1/chat/completions \
|
||||
-H "Authorization: Bearer sk-1234" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"model": "bedrock-personal", "messages": [{"role": "user", "content": "test"}]}'
|
||||
|
||||
# Test business account
|
||||
curl -s http://localhost:8000/v1/chat/completions \
|
||||
-H "Authorization: Bearer sk-1234" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"model": "bedrock-business", "messages": [{"role": "user", "content": "test"}]}'
|
||||
```
|
||||
|
||||
### 5. Configure in TFTSR
|
||||
|
||||
Add both models as separate providers:
|
||||
|
||||
**Provider 1 — Personal:**
|
||||
- Provider: OpenAI
|
||||
- Base URL: `http://localhost:8000/v1`
|
||||
- API Key: `sk-1234`
|
||||
- Model: `bedrock-personal`
|
||||
- Display Name: `Bedrock (Personal)`
|
||||
|
||||
**Provider 2 — Business:**
|
||||
- Provider: OpenAI
|
||||
- Base URL: `http://localhost:8000/v1`
|
||||
- API Key: `sk-1234`
|
||||
- Model: `bedrock-business`
|
||||
- Display Name: `Bedrock (Business)`
|
||||
|
||||
---
|
||||
|
||||
## Claude Code Integration
|
||||
|
||||
If you're using [Claude Code](https://claude.ai/claude-code) with AWS Bedrock, you can reuse the same AWS credentials.
|
||||
|
||||
### 1. Check Claude Code Settings
|
||||
|
||||
Read your Claude Code configuration:
|
||||
|
||||
```bash
|
||||
cat ~/.claude/settings.json
|
||||
```
|
||||
|
||||
Look for:
|
||||
- `AWS_PROFILE` environment variable (e.g., `ClaudeCodeLP`)
|
||||
- `awsAuthRefresh` credential process path
|
||||
- `AWS_REGION` setting
|
||||
|
||||
### 2. Use Same Profile in LiteLLM
|
||||
|
||||
In `~/.litellm/config.yaml`, add a model using the same profile:
|
||||
|
||||
```yaml
|
||||
model_list:
|
||||
- model_name: claude-code-bedrock
|
||||
litellm_params:
|
||||
model: bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0
|
||||
aws_region_name: us-east-1
|
||||
aws_profile_name: ClaudeCodeLP # Same as Claude Code
|
||||
```
|
||||
|
||||
Now both Claude Code and TFTSR use the same Bedrock account without duplicate credential management.
|
||||
|
||||
---
|
||||
|
||||
## Available Claude Models on Bedrock
|
||||
|
||||
| Model ID | Name | Context | Best For |
|
||||
|----------|------|---------|----------|
|
||||
| `us.anthropic.claude-sonnet-4-6` | Claude Sonnet 4.6 | 200k tokens | Most tasks, best quality |
|
||||
| `us.anthropic.claude-sonnet-4-5-20250929-v1:0` | Claude Sonnet 4.5 | 200k tokens | High performance |
|
||||
| `us.anthropic.claude-opus-4-6` | Claude Opus 4.6 | 200k tokens | Complex reasoning |
|
||||
| `us.anthropic.claude-haiku-4-5-20251001` | Claude Haiku 4.5 | 200k tokens | Speed + cost optimization |
|
||||
|
||||
Check your AWS Bedrock console for available models in your region.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Port Already in Use
|
||||
|
||||
If port 8000 is occupied:
|
||||
|
||||
```bash
|
||||
# Find what's using the port
|
||||
lsof -i :8000
|
||||
|
||||
# Use a different port
|
||||
litellm --config ~/.litellm/config.yaml --port 8080
|
||||
```
|
||||
|
||||
Update the Base URL in TFTSR to match: `http://localhost:8080/v1`
|
||||
|
||||
### AWS Credentials Not Found
|
||||
|
||||
```bash
|
||||
# Verify AWS CLI works
|
||||
aws bedrock list-foundation-models --region us-east-1
|
||||
|
||||
# Test specific profile
|
||||
aws bedrock list-foundation-models --region us-east-1 --profile ClaudeCodeLP
|
||||
```
|
||||
|
||||
If AWS CLI fails, fix credentials first before debugging LiteLLM.
|
||||
|
||||
### Model Not Available
|
||||
|
||||
Error: `Model not found` or `Access denied`
|
||||
|
||||
1. Check [AWS Bedrock Console](https://console.aws.amazon.com/bedrock/) → Model Access
|
||||
2. Request access to Claude models if not enabled
|
||||
3. Verify model ID matches exactly (case-sensitive)
|
||||
|
||||
### LiteLLM Won't Start
|
||||
|
||||
Check logs:
|
||||
```bash
|
||||
cat ~/.litellm/litellm.log
|
||||
```
|
||||
|
||||
Common issues:
|
||||
- Missing Python dependencies: `pip install 'litellm[proxy]' --upgrade`
|
||||
- YAML syntax error: Validate with `python3 -c "import yaml; yaml.safe_load(open('${HOME}/.litellm/config.yaml'))"`
|
||||
|
||||
---
|
||||
|
||||
## Auto-Start LiteLLM on Boot
|
||||
|
||||
### macOS — LaunchAgent
|
||||
|
||||
Create `~/Library/LaunchAgents/com.litellm.proxy.plist`:
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.litellm.proxy</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/opt/homebrew/bin/litellm</string>
|
||||
<string>--config</string>
|
||||
<string>/Users/${USER}/.litellm/config.yaml</string>
|
||||
<string>--port</string>
|
||||
<string>8000</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>KeepAlive</key>
|
||||
<true/>
|
||||
<key>StandardOutPath</key>
|
||||
<string>/Users/${USER}/.litellm/litellm.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/Users/${USER}/.litellm/litellm-error.log</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Load it:
|
||||
```bash
|
||||
launchctl load ~/Library/LaunchAgents/com.litellm.proxy.plist
|
||||
```
|
||||
|
||||
### Linux — systemd
|
||||
|
||||
Create `/etc/systemd/system/litellm.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=LiteLLM Proxy
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=${USER}
|
||||
ExecStart=/usr/local/bin/litellm --config /home/${USER}/.litellm/config.yaml --port 8000
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Enable and start:
|
||||
```bash
|
||||
sudo systemctl enable litellm
|
||||
sudo systemctl start litellm
|
||||
sudo systemctl status litellm
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cost Comparison
|
||||
|
||||
| Provider | Model | Input (per 1M tokens) | Output (per 1M tokens) |
|
||||
|----------|-------|----------------------|----------------------|
|
||||
| **Anthropic Direct** | Claude Sonnet 4 | $3.00 | $15.00 |
|
||||
| **AWS Bedrock** | Claude Sonnet 4 | $3.00 | $15.00 |
|
||||
|
||||
Pricing is identical, but Bedrock provides:
|
||||
- AWS consolidated billing
|
||||
- AWS Credits applicability
|
||||
- Integration with AWS services (S3, Lambda, etc.)
|
||||
- Enterprise support contracts
|
||||
|
||||
---
|
||||
|
||||
## Security Notes
|
||||
|
||||
1. **Master Key** — The `master_key` in config is required but doesn't need to be complex since LiteLLM runs locally
|
||||
2. **AWS Credentials** — Never commit `.aws/credentials` or credential process scripts to git
|
||||
3. **Local Only** — LiteLLM proxy should only bind to `127.0.0.1` (localhost) — never expose to network
|
||||
4. **Audit Logs** — TFTSR logs all AI requests with SHA-256 hashes in the audit table
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [LiteLLM Documentation](https://docs.litellm.ai/)
|
||||
- [AWS Bedrock Claude Models](https://docs.aws.amazon.com/bedrock/latest/userguide/models-claude.html)
|
||||
- [Claude Code on Bedrock](https://docs.anthropic.com/claude/docs/claude-code)
|
||||
@ -1,70 +1,133 @@
|
||||
# Troubleshooting
|
||||
|
||||
## CI/CD
|
||||
## CI/CD — Gitea Actions
|
||||
|
||||
### Builds Not Triggering After Push
|
||||
### Build Not Triggering After Push
|
||||
|
||||
**Cause:** Woodpecker 0.15.4 `token.ParseRequest()` does not read `?token=` URL params.
|
||||
|
||||
**Fix:** Webhook URL must use `?access_token=<JWT>` (not `?token=`).
|
||||
```
|
||||
http://172.0.0.29:8084/hook?access_token=<JWT>
|
||||
```
|
||||
|
||||
Regenerate the JWT if it's stale (JWT has an `iat` claim):
|
||||
```bash
|
||||
# JWT payload: {"text":"sarman/tftsr-devops_investigation","type":"hook"}
|
||||
# Signed with: repo_hash (dK8zFWtAu67qfKd3Et6N8LptqTmedumJ)
|
||||
```
|
||||
**Check:**
|
||||
1. Verify the workflow file exists in `.gitea/workflows/` on the pushed branch
|
||||
2. Check the Actions tab at `http://172.0.0.29:3000/sarman/tftsr-devops_investigation/actions`
|
||||
3. Confirm the act_runner is online: `docker logs gitea_act_runner_amd64 --since 5m`
|
||||
|
||||
---
|
||||
|
||||
### Pipeline Step Can't Reach Gogs
|
||||
### Job Container Can't Reach Gitea (`172.0.0.29:3000` blocked)
|
||||
|
||||
**Cause:** Step containers run on the default Docker bridge, not on `gogs_default` network.
|
||||
**Cause:** act_runner creates an isolated Docker network per job (when `container:` is specified). Traffic from the job container to `172.0.0.29:3000` is blocked by the host firewall.
|
||||
|
||||
**Fix:** Use `network_mode: gogs_default` in the clone section and ensure `repo_trusted=1`:
|
||||
```bash
|
||||
docker exec woodpecker_db sqlite3 /data/woodpecker.sqlite \
|
||||
"UPDATE repos SET repo_trusted=1 WHERE repo_full_name='sarman/tftsr-devops_investigation';"
|
||||
```
|
||||
**Fix:** Ensure `container.network: host` is set in the act_runner config AND that `CONFIG_FILE=/data/config.yaml` is in the container's environment:
|
||||
|
||||
---
|
||||
|
||||
### Woodpecker Login Fails
|
||||
|
||||
**Cause:** Gogs 0.14 SPA login form uses `login=` field; backend reads `username=`.
|
||||
|
||||
**Fix:** Use the nginx proxy at `http://172.0.0.29:8085/login` which serves a corrected login form.
|
||||
|
||||
---
|
||||
|
||||
### Empty Clone URL in Pipeline
|
||||
|
||||
**Cause:** Woodpecker 0.15.4 `go-gogs-client` `PayloadRepo` struct is missing `CloneURL`.
|
||||
|
||||
**Fix:** Override with `CI_REPO_CLONE_URL` environment variable in the clone section:
|
||||
```yaml
|
||||
clone:
|
||||
git:
|
||||
environment:
|
||||
- CI_REPO_CLONE_URL=http://gogs_app:3000/sarman/tftsr-devops_investigation.git
|
||||
# /docker_mounts/gitea/runner/amd64/config.yaml
|
||||
container:
|
||||
network: "host"
|
||||
```
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml for act-runner-amd64
|
||||
environment:
|
||||
- CONFIG_FILE=/data/config.yaml
|
||||
```
|
||||
|
||||
Also set `capacity: 1` — with capacity > 1, concurrent jobs may not get host networking:
|
||||
|
||||
```yaml
|
||||
runner:
|
||||
capacity: 1
|
||||
```
|
||||
|
||||
Restart runner: `docker restart gitea_act_runner_amd64`
|
||||
|
||||
---
|
||||
|
||||
### `Unable to locate package git` in Rust Job
|
||||
|
||||
**Cause:** `rust:1.88-slim` has an empty apt package cache.
|
||||
|
||||
**Fix:** Always run `apt-get update` before `apt-get install`:
|
||||
```yaml
|
||||
- name: Checkout
|
||||
run: |
|
||||
apt-get update -qq && apt-get install -y -qq git
|
||||
git init
|
||||
git remote add origin http://172.0.0.29:3000/sarman/tftsr-devops_investigation.git
|
||||
git fetch --depth=1 origin $GITHUB_SHA
|
||||
git checkout FETCH_HEAD
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `exec: "node": executable file not found in $PATH`
|
||||
|
||||
**Cause:** `actions/checkout@v4` is a Node.js action. `rust:1.88-slim` and similar slim images don't have Node.
|
||||
|
||||
**Fix:** Don't use `actions/checkout@v4` — use direct git commands instead (see above).
|
||||
|
||||
---
|
||||
|
||||
### Job Skipped (status 6) on Tag Push
|
||||
|
||||
**Cause:** Pattern matching issue with `on: push: tags:`. Use unquoted glob in the workflow:
|
||||
|
||||
```yaml
|
||||
# Correct
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
```
|
||||
|
||||
Also add `workflow_dispatch` for manual triggering during testing:
|
||||
```yaml
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Release tag'
|
||||
required: true
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### `CI=woodpecker` Rejected by `cargo tauri build`
|
||||
|
||||
**Cause:** CI runners set `CI=woodpecker` (string). Tauri CLI expects `true`/`false`.
|
||||
|
||||
**Fix:** Prefix the build command:
|
||||
```yaml
|
||||
- run: CI=true cargo tauri build --target $TARGET
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Release Artifacts Not Uploaded
|
||||
|
||||
**Cause 1:** `RELEASE_TOKEN` secret not set or expired.
|
||||
```bash
|
||||
# Recreate via admin CLI:
|
||||
docker exec -u git gitea_app gitea admin user generate-access-token \
|
||||
--username sarman --token-name gitea-ci-token --raw \
|
||||
--scopes 'write:repository,read:user'
|
||||
# Add the token as RELEASE_TOKEN in repo Settings > Actions > Secrets
|
||||
```
|
||||
|
||||
**Cause 2:** Each build job uploads its own artifacts independently. All jobs require host network on the runner (see above).
|
||||
|
||||
---
|
||||
|
||||
## Rust Compilation
|
||||
|
||||
### `MutexGuard` Not `Send` Across Await
|
||||
|
||||
**Error:**
|
||||
```
|
||||
error[E0277]: `MutexGuard<'_, Connection>` cannot be sent between threads safely
|
||||
```
|
||||
|
||||
**Fix:** Release the mutex lock before any `.await` point:
|
||||
```rust
|
||||
// ✅ Correct
|
||||
let result = {
|
||||
let db = state.db.lock().map_err(|e| e.to_string())?;
|
||||
db.query_row(...)?
|
||||
@ -76,21 +139,18 @@ async_fn().await?;
|
||||
|
||||
### Clippy Lints Fail in CI
|
||||
|
||||
Common lint fixes:
|
||||
Common lint fixes required by `-D warnings` (Rust 1.88+):
|
||||
|
||||
```rust
|
||||
// uninlined_format_args
|
||||
format!("{}", x) → format!("{x}")
|
||||
|
||||
// range::contains
|
||||
x >= a && x < b → (a..b).contains(&x)
|
||||
|
||||
// push_str single char
|
||||
s.push_str("a") → s.push('a')
|
||||
```
|
||||
|
||||
Run locally: `cargo clippy --manifest-path src-tauri/Cargo.toml -- -D warnings`
|
||||
|
||||
Auto-fix: `cargo clippy --manifest-path src-tauri/Cargo.toml --fix --allow-dirty -- -D warnings`
|
||||
|
||||
---
|
||||
|
||||
### `cargo tauri dev` Fails — Missing System Libraries
|
||||
@ -101,6 +161,12 @@ sudo dnf install -y glib2-devel gtk3-devel webkit2gtk4.1-devel \
|
||||
libsoup3-devel openssl-devel librsvg2-devel
|
||||
```
|
||||
|
||||
**Fix (Debian/Ubuntu):**
|
||||
```bash
|
||||
sudo apt-get install -y libwebkit2gtk-4.1-dev libssl-dev libgtk-3-dev \
|
||||
libayatana-appindicator3-dev librsvg2-dev patchelf pkg-config
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Database
|
||||
@ -109,52 +175,41 @@ sudo dnf install -y glib2-devel gtk3-devel webkit2gtk4.1-devel \
|
||||
|
||||
**Symptom:** App fails to start with SQLCipher error.
|
||||
|
||||
**Check:**
|
||||
1. `TFTSR_DB_KEY` env var is set
|
||||
2. Key matches what was used when DB was created
|
||||
3. File isn't corrupted (try `file tftsr.db` — should say `SQLite 3.x database`)
|
||||
|
||||
**Warning:** Changing the key requires re-encrypting the database:
|
||||
```bash
|
||||
sqlite3 tftsr.db "ATTACH 'new.db' AS newdb KEY 'new-key'; \
|
||||
SELECT sqlcipher_export('newdb'); DETACH DATABASE newdb;"
|
||||
```
|
||||
3. File isn't corrupted: `file tftsr.db` should say `SQLite 3.x database`
|
||||
|
||||
---
|
||||
|
||||
### Migration Fails to Run
|
||||
|
||||
Check which migrations have already been applied:
|
||||
Check which migrations have been applied:
|
||||
```sql
|
||||
SELECT name, applied_at FROM _migrations ORDER BY id;
|
||||
```
|
||||
|
||||
If a migration is partially applied, the DB may be in an inconsistent state. Restore from backup or recreate.
|
||||
|
||||
---
|
||||
|
||||
## Frontend
|
||||
|
||||
### TypeScript Errors After Pulling
|
||||
|
||||
Run a fresh type check:
|
||||
```bash
|
||||
npx tsc --noEmit
|
||||
```
|
||||
|
||||
Ensure `tauriCommands.ts` matches the Rust command signatures exactly (especially `IssueDetail` nesting).
|
||||
Ensure `tauriCommands.ts` matches Rust command signatures exactly (especially `IssueDetail` nesting).
|
||||
|
||||
---
|
||||
|
||||
### `IssueDetail` Field Access Errors
|
||||
|
||||
The `get_issue` command returns a **nested** struct:
|
||||
`get_issue()` returns a **nested** struct:
|
||||
```typescript
|
||||
// ✅ Correct
|
||||
// Correct
|
||||
const title = detail.issue.title;
|
||||
const severity = detail.issue.severity;
|
||||
|
||||
// ❌ Wrong — these fields don't exist at the top level
|
||||
// Wrong — field doesn't exist at top level
|
||||
const title = detail.title;
|
||||
```
|
||||
|
||||
@ -162,26 +217,25 @@ const title = detail.title;
|
||||
|
||||
### Vitest Tests Fail
|
||||
|
||||
```bash
|
||||
npm run test:run
|
||||
```
|
||||
|
||||
Common causes:
|
||||
- Mocked `invoke()` return type doesn't match updated command signature
|
||||
- `sessionStore` state not reset between tests (call `store.reset()` in `beforeEach`)
|
||||
|
||||
---
|
||||
|
||||
## Gogs
|
||||
## Gitea
|
||||
|
||||
### Token Authentication
|
||||
### API Token Authentication
|
||||
|
||||
The `sha1` field from the Gogs token create API **is** the bearer token — use it directly:
|
||||
```bash
|
||||
curl -H "Authorization: token <sha1_value>" https://gogs.tftsr.com/api/v1/user
|
||||
curl -H "Authorization: token <token_value>" http://172.0.0.29:3000/api/v1/user
|
||||
```
|
||||
|
||||
Do not confuse with the `sha1` column in the `access_token` table, which stores `sha1(token)[:40]`.
|
||||
Create tokens in Gitea Settings > Applications > Access Tokens, or via admin CLI:
|
||||
```bash
|
||||
docker exec -u git gitea_app gitea admin user generate-access-token \
|
||||
--username sarman --token-name mytoken --raw --scopes 'read:user,write:repository'
|
||||
```
|
||||
|
||||
### PostgreSQL Access
|
||||
|
||||
@ -189,4 +243,4 @@ Do not confuse with the `sha1` column in the `access_token` table, which stores
|
||||
docker exec gogs_postgres_db psql -U gogs -d gogsdb -c "SELECT id, lower_name, is_private FROM repository;"
|
||||
```
|
||||
|
||||
Database is named `gogsdb`, not `gogs`.
|
||||
Database is named `gogsdb`. The PostgreSQL instance uses SCRAM-SHA-256 auth (MD5 also configured for the `gogs` user for compatibility with older clients).
|
||||
|
||||
Loading…
Reference in New Issue
Block a user