# Theseus — Deployment & Operations

## Build

```bash
cargo build              # Debug: target/debug/theseus
cargo build --release    # Release
./install.sh             # Build release + cp to ~/.local/bin + PATH check
```

`install.sh`: `cargo build --release` → `cp target/release/theseus ~/.local/bin/` → PATH warning.

## Server

```bash
theseus serve                              # Default port 3080
theseus serve --port 8080                  # Custom port
theseus serve --deepseek-api-key sk-xxx    # Enable AI features
theseus --api-key my-secret theseus serve  # API key auth
```

Binds `0.0.0.0:{port}` (`src/main.rs:27`). Health: `GET /health`.

Frontend: `GET /` serves `static/index.html` (embedded via `include_str!`, `src/lib.rs:895`). CSS/JS read from `static/` at runtime — no rebuild for style/script changes.

## CLI

```bash
theseus project <create|list|delete|analysis|status|timeline|stats|report|check>
theseus node    <add|list|get|update|delete|search>
theseus edge    <add|list|update|delete>
theseus credential <add|list|update|delete>
theseus import  <project_id> --file data.json
theseus search  <query>
theseus tell    <project_id> "description"   # AI: natural language → nodes/edges
theseus ask     <project_id> "question"       # AI: query attack graph
```

All commands (except `serve`) use `--server` (default `http://127.0.0.1:3080`).

## Configuration

Resolution order (first found wins): `./theseus.toml` → `~/.config/theseus/config.toml` (`src/lib.rs:354-355`).

```toml
[ai]
default_provider = "deepseek"

[ai.providers.deepseek]
base_url = "https://api.deepseek.com/chat/completions"
api_key = "sk-xxx"
api_format = "openai"
```

Config fields: `api_key`, `deepseek_api_key`, `cors_origins` (`src/lib.rs:346-351`).

**Env vars**: `THESEUS_API_KEY` (server auth), `THESEUS_DEEPSEEK_API_KEY` (AI). CLI flags > env vars > config file.

**Auth**: When any API key is set, `/api/*` requires `x-api-key` header, `Authorization: Bearer`, or `?api_key=` query param. Otherwise server is open (logs warning at `src/lib.rs:805`).

**CORS**: Default `http://127.0.0.1:3080` only. Override with `cors_origins` in config. Invalid origins fall back to localhost (`src/lib.rs:842`).

## Database

SQLite file: `theseus.db` in the working directory. WAL mode + foreign keys (`src/db.rs:23`). Auto-created on first run.

6 tables: `projects`, `nodes`, `edges`, `credentials`, `evidence_files`, `agent_memory` (`src/db.rs:25-80`).

Mutex-based concurrency. Recovery from poisoned locks (`src/db.rs:18`).

**Backup**: copy `theseus.db` while server stopped. **Migration**: none built-in — schema uses `CREATE TABLE IF NOT EXISTS`. Check `src/db.rs` before upgrading.

## Evidence Files

`data/<project-uuid>/evidence/<node-uuid>/<uuid>.<ext>` — created on upload. DB metadata only; deleting record does NOT delete file. Gitignored.

## E2E Tests

```bash
# Standalone (temp DB, random port, stdlib only)
python3 tests/e2e_test.py

# Suite (builds debug, starts server on 3080, runs 10 test files)
cd e2e && ./run_all.sh
cd e2e && python3 test_projects.py       # Single file
THESEUS_PORT=8080 python3 test_projects.py  # Custom port
```

`run_all.sh`: pkill → cargo build → nohup serve → wait for health → run 10 tests → kill server.

`tests/e2e_test.py` uses `TestContext` (temp DB + random port). Covers: project CRUD, node CRUD + validation, edge CRUD + label matching, credential CRUD, analysis, import, content stdin/file, global search, edge cases.

Requires: Python 3, `requests` (`pip install requests`).

## File Layout

```
theseus/
├── theseus.db              # SQLite (runtime, gitignored)
├── theseus.toml            # Config (gitignored)
├── data/                   # Evidence files (gitignored)
├── src/
│   ├── main.rs             # CLI binary (2657 lines)
│   ├── lib.rs              # Server + middleware (901 lines)
│   ├── types.rs            # Shared DTOs
│   ├── db.rs               # SQLite CRUD (1993 lines)
│   ├── agent/              # AI agent: llm, loop, memory, tools, prompts
│   └── routes/             # 15 route modules
├── static/                 # Frontend (CSS/JS hot, HTML embedded)
├── tests/e2e_test.py       # Standalone E2E test
├── e2e/                    # E2E suite (10 test files)
└── install.sh
```

## Production Notes

- **No container/TLS** — use reverse proxy (nginx/caddy) for HTTPS.
- **Static files**: `index.html` compiled in; CSS/JS read at runtime relative to binary via `CARGO_MANIFEST_DIR`. If deploying installed binary alone, copy `static/` alongside it or run from project dir.
- **DB path**: `concat!(env!("CARGO_MANIFEST_DIR"), "/../theseus.db")` — resolves to project root at compile time.
- **WebSocket**: broadcast channel capacity 256.
- **Agent**: `tell`/`ask` require DeepSeek key. Memory in `agent_memory` table.
- **No rate limiting** — add at reverse proxy layer.
