tftsr-devops_investigation/AGENTS.md
Shaun Arman d5e180740e
Some checks failed
Test / rust-test (push) Failing after 6s
Test / frontend-test (push) Failing after 54s
docs: remove all Gitea/Gogs/172.0.0.29 references; update to GitHub
Replace every remaining reference to the old Gitea infrastructure with the
new GitHub-hosted equivalents across all documentation, wiki pages, test
files, and historical ticket summaries.

- README.md: CI badge, clone URL, releases link, CI/CD section, project structure
- docs/wiki/CICD-Pipeline.md: full rewrite for GitHub Actions + ghcr.io
- docs/wiki/Home.md: CI badge, releases link, phase status, tech stack
- docs/wiki/Troubleshooting.md: rewrite CI troubleshooting for GitHub Actions
- docs/architecture/README.md: update CI/CD pipeline diagram
- AGENTS.md: CI/CD section, environment references
- PLAN.md: directory structure, pipeline table
- SECURITY_AUDIT.md: mark C3 and L4 findings as resolved
- ticket-git-cliff-changelog.md: workflow path updated
- tickets/ci-runner-speed-optimization.md: image registry updated
- 2026-hackathon_AgenticFeature.md: workflow path updated
- tests: workflow path assertions updated in all three test files
2026-06-01 16:18:34 -05:00

159 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# AGENTS.md — Quick Start for OpenCode
## Commands
| Task | Command |
|------|---------|
| Run full dev (Tauri + Vite) | `cargo tauri dev` |
| Frontend only (port 1420) | `npm run dev` |
| Frontend production build | `npm run build` |
| Rust fmt check | `cargo fmt --manifest-path src-tauri/Cargo.toml --check` |
| Rust fmt fix | `cargo fmt --manifest-path src-tauri/Cargo.toml` |
| Rust clippy | `cargo clippy --manifest-path src-tauri/Cargo.toml -- -D warnings` |
| Rust tests | `cargo test --manifest-path src-tauri/Cargo.toml -- --test-threads=1` |
| Rust single test module | `cargo test --manifest-path src-tauri/Cargo.toml -- --test-threads=1 pii::detector` |
| Rust single test | `cargo test --manifest-path src-tauri/Cargo.toml -- --test-threads=1 test_detect_ipv4` |
| Frontend test (single run) | `npm run test:run` |
| Frontend test (watch) | `npm run test` |
| Frontend coverage | `npm run test:coverage` |
| TypeScript type check | `npx tsc --noEmit` |
| Frontend lint | `npx eslint . --quiet` |
**Lint Policy**: **ALWAYS run `cargo fmt` and `cargo clippy` after any Rust code change**. Fix all issues before proceeding.
**Note**: The build runs `npm run build` before Rust build (via `beforeBuildCommand` in `tauri.conf.json`). This ensures TS is type-checked before packaging.
**Requirement**: Rust toolchain must be in PATH: `source ~/.cargo/env`
---
## Project Structure
| Path | Responsibility |
|------|----------------|
| `src-tauri/src/lib.rs` | Entry point: app builder, plugin registration, IPC handler registration |
| `src-tauri/src/state.rs` | `AppState` (DB, settings, integration_webviews) |
| `src-tauri/src/commands/` | Tauri IPC handlers (db, ai, analysis, docs, integrations, system) |
| `src-tauri/src/ai/provider.rs` | `Provider` trait + `create_provider()` factory |
| `src-tauri/src/pii/` | Detection engine (12 patterns) + redaction |
| `src-tauri/src/db/models.rs` | DB types: `Issue`, `IssueDetail` (nested), `LogFile`, `ResolutionStep`, `AiConversation` |
| `src-tauri/src/audit/log.rs` | `write_audit_event()` before every external send |
| `src/lib/tauriCommands.ts` | **Source of truth** for all Tauri IPC calls |
| `src/lib/domainPrompts.ts` | 15 domain system prompts (Linux, Windows, Network, K8s, DBs, etc.) |
| `src/stores/` | Zustand: `sessionStore` (ephemeral), `settingsStore` (persisted), `historyStore` |
---
## Key Patterns
### Rust Mutex Usage
Lock `Mutex` inside a block and release **before** `.await`. Holding `MutexGuard` across await points fails to compile (not `Send`):
```rust
let state: State<'_, AppState> = app.state();
let db = state.db.clone();
// Lock and release before await
{ let conn = state.db.lock().unwrap(); /* use conn */ }
// Now safe to .await
db.query(...).await?;
```
### IssueDetail Nesting
`get_issue()` returns a **nested** struct — use `detail.issue.title`, not `detail.title`:
```rust
pub struct IssueDetail {
pub issue: Issue,
pub log_files: Vec<LogFile>,
pub resolution_steps: Vec<ResolutionStep>,
pub conversations: Vec<AiConversation>,
}
```
TypeScript mirrors this shape exactly in `tauriCommands.ts`.
### PII Before AI Send
`apply_redactions` **must** be called before sending logs to AI. Record the SHA-256 hash via `audit::log::write_audit_event()`. PII spans are non-overlapping (longest span wins on overlap); redactor iterates in reverse order to preserve offsets.
### State Persistence
- `sessionStore`: ephemeral triage session (issue, messages, PII spans, why-level 05, loading) — **not persisted**
- `settingsStore`: persisted to `localStorage` as `"tftsr-settings"`
---
## CI/CD (GitHub Actions)
| Workflow | Trigger | Jobs |
|----------|---------|------|
| `.github/workflows/test.yml` | Every push/PR targeting `main` | `rust-test` (fmt → clippy → cargo test) · `frontend-test` (tsc → vitest) |
| `.github/workflows/release.yml` | Push to `main` (auto-tag), `v*` tags | Auto-tag, build linux/amd64 + linux/arm64 + windows/amd64 + macOS ARM64 + macOS Intel, upload to GitHub Releases |
| `.github/workflows/build-images.yml` | `.docker/**` changes on `main` | Build and push pre-baked CI images to `ghcr.io/msicie/` |
**Artifacts**: `src-tauri/target/{target}/release/bundle/`
**Environments**:
- Test CI images at `ghcr.io/msicie/` (pull `trcaa-*:rust1.88-node22`)
- GitHub repo: `https://github.com/msicie/apollo_nxt-trcaa`
- Wiki: sync from `docs/wiki/*.md``https://github.com/msicie/apollo_nxt-trcaa/wiki`
---
## Environment Variables
| Variable | Default | Purpose |
|----------|---------|---------|
| `TFTSR_DATA_DIR` | Platform data dir | Override database location |
| `TFTSR_DB_KEY` | Auto-generated | SQLCipher encryption key override |
| `TFTSR_ENCRYPTION_KEY` | Auto-generated | Credential encryption key override |
| `RUST_LOG` | `info` | Tracing level (`debug`, `info`, `warn`, `error`) |
**Database path**:
- Linux: `~/.local/share/trcaa/trcaa.db`
- macOS: `~/Library/Application Support/trcaa/trcaa.db`
- Windows: `%APPDATA%\trcaa\trcaa.db`
---
## Architecture Highlights
### Rust Backend
- **Entry point**: `src-tauri/src/lib.rs::run()` → init tracing → init DB → register plugins → `generate_handler![]`
- **Database**: `rusqlite` + `bundled-sqlcipher-vendored-openssl` (AES-256). `cfg!(debug_assertions)` → plain SQLite; release → SQLCipher
- **AI providers**: `Provider` trait with factory dispatch on `config.name`. Adding a provider: implement `Provider` trait + add match arm
- **Integration clients**: Confluence, ServiceNow, Azure DevOps stubs (v0.2). OAuth2 via WebView + callback server (warp, port 8765)
### Frontend (React + Vite)
- **Dev server**: port **1420** (hardcoded)
- **IPC**: All `invoke()` calls in `src/lib/tauriCommands.ts` — typed wrappers for every backend command
- **Domain prompts**: 15 expert prompts injected as first message in every triage conversation (Linux, Windows, Network, K8s, DBs, Virtualization, Hardware, Observability, Telephony, Security, Public Safety, Application, Automation, HPE, Dell, Identity)
### Security
- **Database encryption**: AES-256 (SQLCipher in release builds)
- **Credential encryption**: AES-256-GCM, keys stored in `TFTSR_ENCRYPTION_KEY` or auto-generated `.enckey` (mode 0600)
- **Audit trail**: Hash-chained entries (`prev_hash` + `entry_hash`) for tamper evidence
- **PII protection**: 12-pattern detector → user approval gate → hash-chained audit entry
---
## Testing
| Layer | Command | Notes |
|-------|---------|-------|
| Rust | `cargo test --manifest-path src-tauri/Cargo.toml` | 64 tests, runs in `rust:1.88-slim` container |
| TypeScript | `npm run test:run` | Vitest, 13 tests |
| Type check | `npx tsc --noEmit` | `skipLibCheck: true` |
| E2E | `TAURI_BINARY_PATH=./src-tauri/target/release/tftsr npm run test:e2e` | WebdriverIO, requires compiled binary |
**Frontend coverage**: `npm run test:coverage``tests/unit/` coverage report
---
## Critical Gotchas
1. **Mutex across await**: Never `lock().unwrap()` and `.await` without releasing the guard
2. **IssueDetail nesting**: `detail.issue.title`, never `detail.title`
3. **PII before AI**: Always redact and record hash before external send
4. **Port 1420**: Vite dev server is hard-coded to 1420, not 3000
5. **Build order**: Rust fmt → clippy → test → TS check → JS test
6. **CI images**: Use `ghcr.io/msicie/` registry for pre-baked builder images