mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-19 13:23:50 +03:00
* mcp/audit: fall back when better-sqlite3 export is not callable
Dashboard MCP status polls reopen a failed native sqlite load every 30s
because a minified TypeError ("a is not a function") was not treated as
a native load failure and a failed open was not cached. Classify that
shape, fall back to node:sqlite, cache the miss, and refuse to ship a
Docker image without better_sqlite3.node.
Signed-off-by: Minxi Hou <houminxi@gmail.com>
* mcp/audit: force native better-sqlite3 compile in Docker
better-sqlite3 13 ships a linux prebuild. Bare `node-gyp rebuild`
then only TOUCHes stamp files and never writes
build/Release/better_sqlite3.node, so the new test -f gate fails the
image build. Pass --force_build=1, matching the package's own
build-release script.
Signed-off-by: Minxi Hou <houminxi@gmail.com>
* db/core: keep native-load classification under the file-size cap
The audit fallback added two TypeError fingerprints in core.ts and
crossed the frozen 1788-line cap. Move the classifier into
sqliteLoadError.ts and re-export it so existing importers stay stable.
Signed-off-by: Minxi Hou <houminxi@gmail.com>
* build/bootstrap: keep the encrypted-credentials probe narrow
The native-load classifier was copied into scripts/build/bootstrap-env.mjs
alongside the runtime one, but the two files consume its verdict in opposite
directions. In src/lib/db/sqliteLoadError.ts a true verdict means "the driver
is unusable, cascade to node:sqlite", so treating a non-callable export as a
load failure is what we want. In the bootstrap the verdict feeds
hasEncryptedCredentials, where true means "no encrypted credentials found" and
clears the way to generate a fresh STORAGE_ENCRYPTION_KEY.
With the TypeError patterns in the bootstrap copy, a binding that loads but
exports something non-callable over a database full of enc:v1: rows reads as an
empty database, and the operator silently loses access to every stored
credential. Drop those two patterns from the bootstrap copy only, and note in
both files why the pair is deliberately not identical.
A corrupt binding still fails loudly there, now with the database path, the
underlying message, and a rebuild hint, so the narrower classifier does not
cost any diagnosability.
Signed-off-by: Minxi Hou <houminxi@gmail.com>
* fix(mcp): keep audit logging recoverable when the database is created later
getDb() cached a null for the "storage.sqlite does not exist yet" branch, and
closeAuditDb() returns before clearing a falsy cache — so an MCP server started
before the app created the database stayed without audit logging for the whole
process lifetime. Only a genuine driver-load failure is cached now; the
not-found branch retries, which is how it recovers when the file appears.
Covered by a new test that fails without the change.
Also replace the fabricated minified TypeError text ("a is not a function")
thrown by the loader with "better-sqlite3 export is not a function": the
operator sees a diagnosable message and isNativeSqliteLoadError() still
classifies it (it matches on "is not a function").
---------
Signed-off-by: Minxi Hou <houminxi@gmail.com>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
5.4 KiB
5.4 KiB
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.
Live count: ls src/lib/db/*.ts | wc -l (currently 131). Migrations: ls src/lib/db/migrations/*.sql | wc -l (currently 148).
Core Infrastructure
core.ts—getDbInstance()returns singletonbetter-sqlite3with WAL journaling. ExportsrowToCamel()(snake_case → camelCase),encryptConnectionFields()for provider credentials at rest.SCHEMA_SQLdefines 17 base tables (verify:grep -c "CREATE TABLE" src/lib/db/core.tsminus 1 for_omniroute_migrations). Native-load / missing-driver classification lives insqliteLoadError.tsand is re-exported from here.migrationRunner.ts— Applies versioned SQL files fromdb/migrations/inside transactions. Tracks applied migrations in_omniroute_migrations. Each migration is idempotent.db/migrations/— 148 SQL files (001_initial_schema.sql→153_radar_local_model_state.sql; numbering has intentional gaps). Each runs in a transaction, never fails partially.- The old
localDb.tsbarrel has been removed — consumers must import from the owning named module below.
Key Domain Modules
| Module | Tables / Scope | 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 |
secrets.ts |
secrets |
Encrypted secret storage (API keys at rest) |
quotaSnapshots.ts |
quota_snapshots |
Historical quota usage for analytics |
quotaPools.ts |
quota_pools |
Quota-Share pool management |
creditBalance.ts |
credit_balance |
Per-provider credit tracking |
compression.ts |
compression settings | Prompt compression pipeline config |
compressionCombos.ts |
compression_combos |
Per-combo compression pipeline assignments |
evals.ts |
eval tables | Eval framework persistence |
webhooks.ts |
webhooks |
Event-driven webhook subscriptions and logs |
reasoningCache.ts |
reasoning cache | Hybrid in-memory + SQLite reasoning replay |
skills.ts |
skills |
Skill registration and metadata |
plugins.ts |
plugins |
Plugin marketplace state |
gamification.ts |
gamification tables | Levels, badges, leaderboard |
notion.ts |
notion tables | Notion integration state |
obsidian.ts |
obsidian tables | Obsidian vault integration state |
files.ts |
file storage | Uploaded file management |
batches.ts |
batch processing | Batch job tracking |
featureFlags.ts |
feature flags | Runtime feature flag overrides |
backup.ts |
backup ops | Serialize/deserialize entire DB state |
cleanup.ts |
cleanup ops | Stale data purging |
healthCheck.ts |
health ops | DB health monitoring |
databaseSettings.ts |
database settings | DB-level configuration |
Full list: ls src/lib/db/*.ts | wc -l (131 files). Drift detection: npm run check:docs-counts.
Encryption & Security
- Sensitive fields (API keys, OAuth tokens, connection strings) encrypted at rest using AES-256-GCM
encryptConnectionFields()incore.ts— automatic encryption when storing provider credentialssecrets.ts— dedicated encrypted store for long-term secret handling- Never log SQLite encryption keys or raw secrets; always use redacted values in logs
Adding a New Domain Module
- Create
src/lib/db/[module].tswith CRUD functions - If new tables: create migration in
db/migrations/NNN_[description].sql - Migration runs automatically at startup via
migrationRunner.ts - Add unit tests in
tests/unit/db/
Anti-Patterns
- Raw SQL in routes — always use domain module functions
- Direct
prepare()statements outsidedb/— breaks modularity - Barrel-importing from
localDb.ts— import specific modules instead - Skipping migrations for schema changes — all changes go through
db/migrations/