docs: enhance AGENTS.md with architecture internals and create CLAUDE.md (#1210)

Integrated into release/v3.6.5
This commit is contained in:
Paijo
2026-04-13 23:10:22 +07:00
committed by GitHub
parent 625bcf105c
commit ee5a1f0e7a
4 changed files with 613 additions and 9 deletions

102
src/lib/db/AGENTS.md Normal file
View File

@@ -0,0 +1,102 @@
# src/lib/db/ — SQLite Persistence Layer
**Purpose**: Domain-driven SQLite persistence. Each module owns a specific table set. Schema migrations are versioned and idempotent. No raw SQL in routes — all ops go through `src/lib/db/` modules.
---
## Key Modules
### Core Infrastructure
- **`core.ts`** — `getDbInstance()` returns singleton `better-sqlite3` with WAL journaling. Exports `rowToCamel()` (snake_case → camelCase), `encryptConnectionFields()` for provider credentials at rest. `SCHEMA_SQL` defines 15 base tables.
- **`migrationRunner.ts`** — Applies versioned SQL files from `db/migrations/` inside transactions. Tracks applied migrations in `_omniroute_migrations`. Runs at startup; each migration is idempotent.
- **`db/migrations/`** — 21 SQL files (`001_initial_schema.sql``021_combo_call_log_targets.sql`). Each migration has single responsibility, runs in a transaction, never fails partially.
- **`localDb.ts`** — Re-export layer only. Never add logic here. Consumers import domain modules from this file for convenience.
### Domain Modules (22 total)
Each module owns specific tables + CRUD operations:
| Module | Tables | Responsibility |
| ----------------------- | ------------------------- | ------------------------------------------------------- |
| `providers.ts` | `provider_connections` | OAuth/API key provider registration and credentials |
| `models.ts` | `models` | Model definitions, capabilities, pricing |
| `combos.ts` | `combos`, `combo_targets` | Combo routing configs, target ordering |
| `apiKeys.ts` | `api_keys` | API key lifecycle, scopes, quota tracking |
| `settings.ts` | `settings` | KV store for system configuration |
| `backup.ts` | Backup export/import ops | Serialize/deserialize entire DB state |
| `proxies.ts` | `proxies` | MITM proxy configs and routing rules |
| `prompts.ts` | `prompts` | Reusable prompt templates, versioning |
| `webhooks.ts` | `webhooks` | Event-driven webhook subscriptions and logs |
| `detailedLogs.ts` | `detailed_logs` | Per-request audit logging (optional, high volume) |
| `domainState.ts` | `domain_state` | Transient runtime state (not persisted across restarts) |
| `registeredKeys.ts` | `registered_keys` | Whitelisted API keys for MCP/A2A access |
| `quotaSnapshots.ts` | `quota_snapshots` | Historical quota usage for analytics |
| `modelComboMappings.ts` | `model_combo_mappings` | Map models to combo defaults |
| `cliToolState.ts` | `cli_tool_state` | CLI-specific persistent state |
| `encryption.ts` | — | Helpers for encrypting/decrypting sensitive fields |
| `readCache.ts` | — | In-memory cache for read-heavy ops (models, providers) |
| `secrets.ts` | `secrets` | Encrypted secret storage (API keys at rest) |
| `stateReset.ts` | — | Wipe/reset DB state for testing or recovery |
| `contextHandoffs.ts` | `context_handoffs` | Store/retrieve session context for agent handoff |
| `migrations/` | — | Versioned SQL schema evolution |
| `core.ts` | — | Singleton DB instance, helpers, schema definition |
### Encryption & Security
- **Sensitive fields** (API keys, OAuth tokens, connection strings) encrypted at rest using `src/lib/encryption/` utilities
- **`encryptConnectionFields()`** in `core.ts` — Automatic encryption when storing provider credentials
- **`secrets.ts`** — Dedicated encrypted store for long-term secret handling
- **Never log** SQLite encryption keys or raw secrets; always use redacted values in logs
### Testing Strategy
For authoritative coverage requirements and test execution guidelines, see [`CONTRIBUTING.md#running-tests`](../../CONTRIBUTING.md#running-tests) (lines 136162).
- **Unit tests** mock `getDbInstance()` to return isolated sqlite in-memory instance
- **Integration tests** use real SQLite with migrations applied, data cleaned up after each test
- **No fixture interdependencies** — each test runs migrations fresh
- Test files: `tests/unit/db/*.test.mjs`, `tests/integration/db/*.test.mjs`
### Anti-Patterns
- ❌ Raw SQL in routes — always use domain module functions
- ❌ Direct `prepare()` statements outside `db/` modules — breaks modularity
- ❌ Mixing encryption logic in domain modules — use `encryption.ts` helpers only
- ❌ Accessing `provider_connections` table from `combos.ts` — each module owns its tables
- ❌ Skipping migrations for schema changes — all changes go through `db/migrations/`
### Adding a New Domain Module
1. Create `src/lib/db/[module].ts` with CRUD functions (create, read, update, delete, list)
2. Export from `src/lib/db/localDb.ts` (add re-export)
3. If new tables required: create migration in `db/migrations/NNN_[description].sql`
4. Run migration via `migrationRunner.ts` at startup (automatic)
5. Add unit tests in `tests/unit/db/[module].test.mjs`
6. Ensure tests meet the coverage requirements in [`CONTRIBUTING.md#running-tests`](../../CONTRIBUTING.md#running-tests)
### Performance Notes
- **Read cache** (`readCache.ts`) — Pre-loads frequently accessed data (models, providers) at startup; invalidated on write
- **WAL journaling** (`core.ts`) — Enables concurrent reads during writes
- **Batch operations** — Use prepared statements with parameter binding to avoid SQL injection
- **Connection pooling** — Singleton pattern prevents per-request connection overhead
---
## Key Decisions
- **SQLite over PostgreSQL**: Simpler deployment, no separate database server, encryption at application layer
- **Versioned migrations**: Each schema change is tracked, reproducible, reversible with effort
- **Domain modules**: Enforces single responsibility, prevents cross-module table access
- **Re-export layer**: Convenience for consumers; `localDb.ts` is re-export-only to prevent circular dependencies
---
## Review Focus
- DB module changes must preserve domain boundaries (one module = one table set)
- New migrations must be idempotent and run inside transactions
- Encryption helpers used for all sensitive fields
- Test coverage and PR requirements: see [`CONTRIBUTING.md#running-tests`](../../CONTRIBUTING.md#running-tests) (lines 136162)
- No raw SQL in routes or non-db modules