From a08fa7d5a4eba1a7ad5c9e8c39c820a20dffa85a Mon Sep 17 00:00:00 2001 From: Neeraj Sathish Kumar Date: Mon, 4 May 2026 12:22:07 +0530 Subject: [PATCH] fix(postgres): block cross-tenant memory id overwrite --- src/adapters/postgres.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/adapters/postgres.rs b/src/adapters/postgres.rs index 4214685..70c14a4 100644 --- a/src/adapters/postgres.rs +++ b/src/adapters/postgres.rs @@ -73,7 +73,7 @@ impl PostgresPort for PostgresAdapter { let last_accessed_at = optional_epoch_seconds(record.last_accessed_at.as_deref(), "last_accessed_at")?; - client + let rows_affected = client .execute( r#" INSERT INTO nextral_memories ( @@ -89,8 +89,6 @@ impl PostgresPort for PostgresAdapter { $22, $23, $24 ) ON CONFLICT (id) DO UPDATE SET - tenant_id = EXCLUDED.tenant_id, - user_id = EXCLUDED.user_id, session_id = EXCLUDED.session_id, content = EXCLUDED.content, content_type = EXCLUDED.content_type, @@ -111,6 +109,8 @@ impl PostgresPort for PostgresAdapter { access_count = EXCLUDED.access_count, status = EXCLUDED.status, schema_version = EXCLUDED.schema_version + WHERE nextral_memories.tenant_id = EXCLUDED.tenant_id + AND nextral_memories.user_id = EXCLUDED.user_id "#, &[ &record.id, @@ -140,6 +140,12 @@ impl PostgresPort for PostgresAdapter { ], ) .map_err(|error| CoreError::Io(error.to_string()))?; + if rows_affected == 0 { + return Err(CoreError::Conflict(format!( + "memory id '{}' already exists in a different tenant/user scope", + record.id + ))); + } Ok(()) }