diff --git a/src/db/libsql/mod.rs b/src/db/libsql/mod.rs index 4a54cb5f35..01465ebd14 100644 --- a/src/db/libsql/mod.rs +++ b/src/db/libsql/mod.rs @@ -357,13 +357,15 @@ impl Database for LibSqlBackend { .map_err(|e| DatabaseError::Query(e.to_string()))?; let result = async { + // Only tables with a real `user_id` column participate in the legacy + // 'default' -> owner rewrite. `dynamic_tools` is intentionally excluded: + // it is ownerless today and scoped by `scope`, not `user_id`. let tables = [ "conversations", "memory_documents", "heartbeat_state", "secrets", "wasm_tools", - "dynamic_tools", "routines", "settings", "agent_jobs", diff --git a/src/db/postgres.rs b/src/db/postgres.rs index 138d145e06..b6c11b4cba 100644 --- a/src/db/postgres.rs +++ b/src/db/postgres.rs @@ -74,13 +74,15 @@ impl Database for PgBackend { .transaction() .await .map_err(|e| DatabaseError::Query(e.to_string()))?; + // Only tables with a real `user_id` column participate in the legacy + // 'default' -> owner rewrite. `dynamic_tools` is intentionally excluded: + // it is ownerless today and scoped by `scope`, not `user_id`. let tables = [ "conversations", "memory_documents", "heartbeat_state", "secrets", "wasm_tools", - "dynamic_tools", "routines", "settings", "agent_jobs", diff --git a/tests/ownership_integration.rs b/tests/ownership_integration.rs index dd6395db8b..71d71511c1 100644 --- a/tests/ownership_integration.rs +++ b/tests/ownership_integration.rs @@ -138,7 +138,9 @@ mod tests { create_user(&db, "henry", "admin").await; // Run twice — should not error - db.migrate_default_owner("henry").await.unwrap(); + db.migrate_default_owner("owner-bootstrap-test") + .await + .unwrap(); db.migrate_default_owner("henry").await.unwrap(); // Still exactly one henry row @@ -155,6 +157,16 @@ mod tests { db.migrate_default_owner("henry").await.unwrap(); } + #[tokio::test] + async fn test_migrate_default_owner_succeeds_on_fresh_migrated_db() { + let (db, _dir) = setup_db().await; + + // Fresh installs include ownerless tables like `dynamic_tools`; the + // bootstrap rewrite should still succeed without assuming every table + // in the schema carries a `user_id` column. + db.migrate_default_owner("henry").await.unwrap(); + } + // ----------------------------------------------------------------------- // TenantScope isolation tests // -----------------------------------------------------------------------