fix(mcp): open Kon database read-only
The kon-mcp stdio server is documented as "read-only, no auth, local-only" but until now opened the SQLite store via `kon_storage::init`, which returns a writable pool and runs migrations. Read-only-ness was enforced only by the exposed tool surface (list_transcripts, get_transcript, search_transcripts, list_tasks); a future bug or a malformed dispatch could escape into a write against the user's primary database. Add `kon_storage::init_readonly` that opens with `SqliteConnectOptions ::read_only(true)` and `create_if_missing(false)`, no migrations. The constraint is now structural — SQLite rejects writes at the connection level regardless of which handler runs. - New `init_readonly(path)` in crates/storage/src/database.rs. - Re-exported from kon_storage. - crates/mcp/src/main.rs switched over and updated startup banner. - Two tests: writes fail on the read-only pool, reads succeed; opening a non-existent DB returns an error instead of silently creating one. https://claude.ai/code/session_0189xUb6ie6t9qHkzatGZ9Rb
This commit is contained in:
@@ -7,8 +7,15 @@ use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let db_path = kon_storage::database_path();
|
||||
eprintln!("[kon-mcp] opening Kon database at {}", db_path.display());
|
||||
let pool = kon_storage::init(&db_path).await?;
|
||||
eprintln!(
|
||||
"[kon-mcp] opening Kon database at {} (read-only)",
|
||||
db_path.display()
|
||||
);
|
||||
// Open read-only at the connection level so the MCP server cannot write
|
||||
// to the user's database, regardless of which tools the dispatcher
|
||||
// exposes. Migrations are deliberately skipped — this binary never owns
|
||||
// the schema; the main app is the single migration writer.
|
||||
let pool = kon_storage::init_readonly(&db_path).await?;
|
||||
eprintln!("[kon-mcp] ready, waiting for JSON-RPC on stdin");
|
||||
|
||||
let mut lines = BufReader::new(tokio::io::stdin()).lines();
|
||||
|
||||
Reference in New Issue
Block a user