diff --git a/lib/types/sqlite-types.js b/lib/types/sqlite-types.js
new file mode 100644
--- /dev/null
+++ b/lib/types/sqlite-types.js
@@ -0,0 +1,8 @@
+// @flow
+
+export type ReceivedMessageToDevice = {
+  +messageID: string,
+  +senderDeviceID: string,
+  +plaintext: string,
+  +status: string,
+};
diff --git a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h
--- a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h
+++ b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h
@@ -12,6 +12,7 @@
 #include "entities/OlmPersistAccount.h"
 #include "entities/OlmPersistSession.h"
 #include "entities/PersistItem.h"
+#include "entities/ReceivedMessageToDevice.h"
 #include "entities/Report.h"
 #include "entities/SyncedMetadataEntry.h"
 #include "entities/Thread.h"
@@ -142,6 +143,12 @@
       const ClientMessageToDevice &lastConfirmedMessage) const = 0;
   virtual void
   removeAllMessagesForDevice(const std::string &deviceID) const = 0;
+  virtual void
+  addReceivedMessageToDevice(ReceivedMessageToDevice message) const = 0;
+  virtual std::vector<ReceivedMessageToDevice>
+  getAllReceivedMessageToDevice() const = 0;
+  virtual void
+  removeReceivedMessagesToDevice(const std::vector<std::string> &ids) const = 0;
 
 #ifdef EMSCRIPTEN
   virtual std::vector<WebThread> getAllThreadsWeb() const = 0;
diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h
--- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h
+++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h
@@ -152,6 +152,12 @@
   void removeMessagesToDeviceOlderThan(
       const ClientMessageToDevice &lastConfirmedMessage) const override;
   void removeAllMessagesForDevice(const std::string &deviceID) const override;
+  void
+  addReceivedMessageToDevice(ReceivedMessageToDevice message) const override;
+  std::vector<ReceivedMessageToDevice>
+  getAllReceivedMessageToDevice() const override;
+  void removeReceivedMessagesToDevice(
+      const std::vector<std::string> &ids) const override;
 
 #ifdef EMSCRIPTEN
   std::vector<WebThread> getAllThreadsWeb() const override;
diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
--- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
+++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
@@ -2155,6 +2155,41 @@
       SQLiteQueryExecutor::getConnection(), removeMessagesSQL, keys);
 }
 
+void SQLiteQueryExecutor::addReceivedMessageToDevice(
+    ReceivedMessageToDevice message) const {
+  static std::string addMessage =
+      "REPLACE INTO received_messages_to_device ("
+      " message_id, sender_device_id, plaintext, status)"
+      "VALUES (?, ?, ?, ?);";
+
+  replaceEntity<ReceivedMessageToDevice>(
+      SQLiteQueryExecutor::getConnection(), addMessage, message);
+}
+
+std::vector<ReceivedMessageToDevice>
+SQLiteQueryExecutor::getAllReceivedMessageToDevice() const {
+  static std::string query =
+      "SELECT message_id, sender_device_id, plaintext, status "
+      "FROM received_messages_to_device;";
+  return getAllEntities<ReceivedMessageToDevice>(
+      SQLiteQueryExecutor::getConnection(), query);
+}
+
+void SQLiteQueryExecutor::removeReceivedMessagesToDevice(
+    const std::vector<std::string> &ids) const {
+  if (!ids.size()) {
+    return;
+  }
+
+  std::stringstream removeMessagesSQLStream;
+  removeMessagesSQLStream << "DELETE FROM received_messages_to_device "
+                             "WHERE message_id IN "
+                          << getSQLStatementArray(ids.size()) << ";";
+
+  removeEntitiesByKeys(
+      SQLiteQueryExecutor::getConnection(), removeMessagesSQLStream.str(), ids);
+}
+
 #ifdef EMSCRIPTEN
 std::vector<WebThread> SQLiteQueryExecutor::getAllThreadsWeb() const {
   auto threads = this->getAllThreads();
diff --git a/native/cpp/CommonCpp/DatabaseManagers/entities/ReceivedMessageToDevice.h b/native/cpp/CommonCpp/DatabaseManagers/entities/ReceivedMessageToDevice.h
new file mode 100644
--- /dev/null
+++ b/native/cpp/CommonCpp/DatabaseManagers/entities/ReceivedMessageToDevice.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <sqlite3.h>
+#include <memory>
+#include <string>
+
+#include "SQLiteDataConverters.h"
+
+namespace comm {
+
+struct ReceivedMessageToDevice {
+  std::string message_id;
+  std::string sender_device_id;
+  std::string plaintext;
+  std::string status;
+
+  static ReceivedMessageToDevice fromSQLResult(sqlite3_stmt *sqlRow, int idx) {
+    return ReceivedMessageToDevice{
+        getStringFromSQLRow(sqlRow, idx),
+        getStringFromSQLRow(sqlRow, idx + 1),
+        getStringFromSQLRow(sqlRow, idx + 2),
+        getStringFromSQLRow(sqlRow, idx + 3),
+    };
+  }
+
+  int bindToSQL(sqlite3_stmt *sql, int idx) const {
+    bindStringToSQL(message_id, sql, idx);
+    bindStringToSQL(sender_device_id, sql, idx + 1);
+    bindStringToSQL(plaintext, sql, idx + 2);
+    return bindStringToSQL(status, sql, idx + 3);
+  }
+};
+
+} // namespace comm
diff --git a/web/cpp/SQLiteQueryExecutorBindings.cpp b/web/cpp/SQLiteQueryExecutorBindings.cpp
--- a/web/cpp/SQLiteQueryExecutorBindings.cpp
+++ b/web/cpp/SQLiteQueryExecutorBindings.cpp
@@ -1,6 +1,7 @@
 #include "SQLiteQueryExecutor.cpp"
 #include "entities/MessageToDevice.h"
 #include "entities/Nullable.h"
+#include "entities/ReceivedMessageToDevice.h"
 
 #include <emscripten/bind.h>
 #include <vector>
@@ -121,6 +122,12 @@
       .field("plaintext", &ClientMessageToDevice::plaintext)
       .field("ciphertext", &ClientMessageToDevice::ciphertext);
 
+  value_object<ReceivedMessageToDevice>("ReceivedMessageToDevice")
+      .field("messageID", &ReceivedMessageToDevice::message_id)
+      .field("senderDeviceID", &ReceivedMessageToDevice::sender_device_id)
+      .field("plaintext", &ReceivedMessageToDevice::plaintext)
+      .field("status", &ReceivedMessageToDevice::status);
+
   class_<SQLiteQueryExecutor>("SQLiteQueryExecutor")
       .constructor<std::string>()
       .function("updateDraft", &SQLiteQueryExecutor::updateDraft)
@@ -264,7 +271,16 @@
           &SQLiteQueryExecutor::removeAllMessagesForDevice)
       .function(
           "getAllMessagesToDevice",
-          &SQLiteQueryExecutor::getAllMessagesToDevice);
+          &SQLiteQueryExecutor::getAllMessagesToDevice)
+      .function(
+          "addReceivedMessageToDevice",
+          &SQLiteQueryExecutor::addReceivedMessageToDevice)
+      .function(
+          "getAllReceivedMessageToDevice",
+          &SQLiteQueryExecutor::getAllReceivedMessageToDevice)
+      .function(
+          "removeReceivedMessagesToDevice",
+          &SQLiteQueryExecutor::removeReceivedMessagesToDevice);
 }
 
 } // namespace comm
diff --git a/web/shared-worker/_generated/comm-query-executor.js b/web/shared-worker/_generated/comm-query-executor.js
--- a/web/shared-worker/_generated/comm-query-executor.js
+++ b/web/shared-worker/_generated/comm-query-executor.js
@@ -117,7 +117,7 @@
 V.prototype.fromWireType=function(a){function b(){return this.Vb?Jb(this.Ta.Eb,{Xa:this.Md,Sa:c,fb:this,ab:a}):Jb(this.Ta.Eb,{Xa:this,Sa:a})}var c=this.xd(a);if(!c)return this.Hc(a),null;var d=Ib(this.Ta,c);if(void 0!==d){if(0===d.Na.count.value)return d.Na.Sa=c,d.Na.ab=a,d.clone();d=d.clone();this.Hc(a);return d}d=this.Ta.vd(c);d=Db[d];if(!d)return b.call(this);d=this.Tb?d.jd:d.pointerType;var f=Cb(c,this.Ta,d.Ta);return null===f?b.call(this):this.Vb?Jb(d.Ta.Eb,{Xa:d,Sa:f,fb:this,ab:a}):Jb(d.Ta.Eb,
 {Xa:d,Sa:f})};Wb=e.UnboundTypeError=rb("UnboundTypeError");e.count_emval_handles=function(){for(var a=0,b=5;b<Y.length;++b)void 0!==Y[b]&&++a;return a};e.get_first_emval=function(){for(var a=5;a<Y.length;++a)if(void 0!==Y[a])return Y[a];return null};
 var Lc={b:function(a){return wc(a+24)+24},c:function(a,b,c){(new Oa(a)).Db(b,c);Pa++;throw a;},_:function(a,b){try{return a=y(a),N.chmod(a,b),0}catch(c){if("undefined"==typeof N||!(c instanceof N.Ma))throw c;return-c.Ra}},da:function(a,b,c){try{b=y(b);b=P(a,b);if(c&-8)return-28;var d=N.Ua(b,{eb:!0}).node;if(!d)return-44;a="";c&4&&(a+="r");c&2&&(a+="w");c&1&&(a+="x");return a&&N.sb(d,a)?-2:0}catch(f){if("undefined"==typeof N||!(f instanceof N.Ma))throw f;return-f.Ra}},$:function(a,b){try{return N.fchmod(a,
-b),0}catch(c){if("undefined"==typeof N||!(c instanceof N.Ma))throw c;return-c.Ra}},Z:function(a,b,c){try{return N.fchown(a,b,c),0}catch(d){if("undefined"==typeof N||!(d instanceof N.Ma))throw d;return-d.Ra}},h:function(a,b,c){gb=c;try{var d=Q(a);switch(b){case 0:var f=hb();return 0>f?-28:N.Fc(d,f).fd;case 1:case 2:return 0;case 3:return d.flags;case 4:return f=hb(),d.flags|=f,0;case 5:return f=hb(),D[f+0>>1]=2,0;case 6:case 7:return 0;case 16:case 8:return-28;case 9:return E[Kc()>>2]=28,-1;default:return-28}}catch(g){if("undefined"==
+b),0}catch(c){if("undefined"==typeof N||!(c instanceof N.Ma))throw c;return-c.Ra}},Z:function(a,b,c){try{return N.fchown(a,b,c),0}catch(d){if("undefined"==typeof N||!(d instanceof N.Ma))throw d;return-d.Ra}},i:function(a,b,c){gb=c;try{var d=Q(a);switch(b){case 0:var f=hb();return 0>f?-28:N.Fc(d,f).fd;case 1:case 2:return 0;case 3:return d.flags;case 4:return f=hb(),d.flags|=f,0;case 5:return f=hb(),D[f+0>>1]=2,0;case 6:case 7:return 0;case 16:case 8:return-28;case 9:return E[Kc()>>2]=28,-1;default:return-28}}catch(g){if("undefined"==
 typeof N||!(g instanceof N.Ma))throw g;return-g.Ra}},X:function(a,b){try{var c=Q(a);return fb(N.stat,c.path,b)}catch(d){if("undefined"==typeof N||!(d instanceof N.Ma))throw d;return-d.Ra}},E:function(a,b,c){try{b=c+2097152>>>0<4194305-!!b?(b>>>0)+4294967296*c:NaN;if(isNaN(b))return-61;N.ud(a,b);return 0}catch(d){if("undefined"==typeof N||!(d instanceof N.Ma))throw d;return-d.Ra}},S:function(a,b){try{if(0===b)return-28;var c=N.cwd(),d=ta(c)+1;if(b<d)return-68;A(c,z,a,b);return d}catch(f){if("undefined"==
 typeof N||!(f instanceof N.Ma))throw f;return-f.Ra}},M:function(a,b,c){try{var d=Q(a);d.ub||(d.ub=N.readdir(d.path));a=0;for(var f=N.bb(d,0,1),g=Math.floor(f/280);g<d.ub.length&&a+280<=c;){var k=d.ub[g];if("."===k){var h=d.node.id;var n=4}else if(".."===k)h=N.Ua(d.path,{parent:!0}).node.id,n=4;else{var q=N.kb(d.node,k);h=q.id;n=N.Jb(q.mode)?2:N.Ya(q.mode)?4:N.vb(q.mode)?10:8}J=[h>>>0,(G=h,1<=+Math.abs(G)?0<G?(Math.min(+Math.floor(G/4294967296),4294967295)|0)>>>0:~~+Math.ceil((G-+(~~G>>>0))/4294967296)>>>
 0:0)];E[b+a>>2]=J[0];E[b+a+4>>2]=J[1];J=[280*(g+1)>>>0,(G=280*(g+1),1<=+Math.abs(G)?0<G?(Math.min(+Math.floor(G/4294967296),4294967295)|0)>>>0:~~+Math.ceil((G-+(~~G>>>0))/4294967296)>>>0:0)];E[b+a+8>>2]=J[0];E[b+a+12>>2]=J[1];D[b+a+16>>1]=280;B[b+a+18>>0]=n;A(k,z,b+a+19,256);a+=280;g+=1}N.bb(d,280*g,0);return a}catch(p){if("undefined"==typeof N||!(p instanceof N.Ma))throw p;return-p.Ra}},Y:function(a,b,c){gb=c;try{var d=Q(a);switch(b){case 21509:case 21505:return d.tty?0:-59;case 21510:case 21511:case 21512:case 21506:case 21507:case 21508:return d.tty?
@@ -138,7 +138,7 @@
 F[n>>2],p=k(),t,x=n+4,l=0;l<=q;++l){var u=n+4+l*b;if(l==q||0==p[u>>h])x=d(x,u-x),void 0===t?t=x:(t+=String.fromCharCode(0),t+=x),x=u+b}X(n);return t},toWireType:function(n,q){"string"!=typeof q&&T("Cannot pass non-string to C++ string type "+c);var p=g(q),t=wc(4+p+b);F[t>>2]=p>>h;f(q,t+4,p+b);null!==n&&n.push(X,t);return t},argPackAdvance:8,readValueFromPointer:lb,ib:function(n){X(n)}})},f:function(a,b,c,d,f,g){jb[a]={name:S(b),rc:W(c,d),pb:W(f,g),Lc:[]}},d:function(a,b,c,d,f,g,k,h,n,q){jb[a].Lc.push({rd:S(b),
 zd:c,Sb:W(d,f),yd:g,Sd:k,Rd:W(h,n),Td:q})},ga:function(a,b){b=S(b);R(a,{Dd:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},o:function(){return Date.now()},aa:function(){return!0},k:function(a,b,c){a=ec(a);b=oc(b,"emval::as");var d=[],f=Sb(d);F[c>>2]=f;return b.toWireType(d,a)},A:function(a,b,c,d){a=rc[a];b=ec(b);c=qc(c);a(b,c,null,d)},na:dc,oa:function(a,b){var c=tc(a,b),d=c[0];b=d.name+"_$"+c.slice(1).map(function(p){return p.name}).join("_")+"$";var f=uc[b];if(void 0!==
 f)return f;f=["retType"];for(var g=[d],k="",h=0;h<a-1;++h)k+=(0!==h?", ":"")+"arg"+h,f.push("argType"+h),g.push(c[1+h]);var n="return function "+pb("methodCaller_"+b)+"(handle, name, destructors, args) {\n",q=0;for(h=0;h<a-1;++h)n+="    var arg"+h+" = argType"+h+".readValueFromPointer(args"+(q?"+"+q:"")+");\n",q+=c[h+1].argPackAdvance;n+="    var rv = handle[name]("+k+");\n";for(h=0;h<a-1;++h)c[h+1].deleteObject&&(n+="    argType"+h+".deleteObject(arg"+h+");\n");d.Dd||(n+="    return retType.toWireType(destructors, rv);\n");
-f.push(n+"};\n");a=ac(f).apply(null,g);f=sc(a);return uc[b]=f},z:function(a,b){a=ec(a);b=ec(b);return Sb(a[b])},C:function(a){4<a&&(Y[a].uc+=1)},B:function(){return Sb([])},ma:function(a){return Sb(qc(a))},la:function(a){var b=ec(a);kb(b);dc(a)},i:function(a,b){a=oc(a,"_emval_take_value");a=a.readValueFromPointer(b);return Sb(a)},ba:function(a,b){a=new Date(1E3*ib(a));E[b>>2]=a.getSeconds();E[b+4>>2]=a.getMinutes();E[b+8>>2]=a.getHours();E[b+12>>2]=a.getDate();E[b+16>>2]=a.getMonth();E[b+20>>2]=a.getFullYear()-
+f.push(n+"};\n");a=ac(f).apply(null,g);f=sc(a);return uc[b]=f},z:function(a,b){a=ec(a);b=ec(b);return Sb(a[b])},C:function(a){4<a&&(Y[a].uc+=1)},B:function(){return Sb([])},ma:function(a){return Sb(qc(a))},la:function(a){var b=ec(a);kb(b);dc(a)},h:function(a,b){a=oc(a,"_emval_take_value");a=a.readValueFromPointer(b);return Sb(a)},ba:function(a,b){a=new Date(1E3*ib(a));E[b>>2]=a.getSeconds();E[b+4>>2]=a.getMinutes();E[b+8>>2]=a.getHours();E[b+12>>2]=a.getDate();E[b+16>>2]=a.getMonth();E[b+20>>2]=a.getFullYear()-
 1900;E[b+24>>2]=a.getDay();var c=new Date(a.getFullYear(),0,1);E[b+28>>2]=(a.getTime()-c.getTime())/864E5|0;E[b+36>>2]=-(60*a.getTimezoneOffset());var d=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();c=c.getTimezoneOffset();E[b+32>>2]=(d!=c&&a.getTimezoneOffset()==Math.min(c,d))|0},N:function(a,b,c,d,f,g){try{var k=N.rb(d);if(!k)return-8;var h=N.yb(k,a,f,b,c),n=h.Sa;E[g>>2]=h.zc;return n}catch(q){if("undefined"==typeof N||!(q instanceof N.Ma))throw q;return-q.Ra}},O:function(a,b,c,d,f,g){try{var k=
 N.rb(f);if(k&&c&2){var h=z.slice(a,a+b);N.Fb(k,h,g,b,d)}}catch(n){if("undefined"==typeof N||!(n instanceof N.Ma))throw n;return-n.Ra}},ca:yc,m:function(){v("")},J:function(){return 2147483648},w:zc,n:function(a){var b=z.length;a>>>=0;if(2147483648<a)return!1;for(var c=1;4>=c;c*=2){var d=b*(1+.2/c);d=Math.min(d,a+100663296);var f=Math;d=Math.max(a,d);f=f.min.call(f,2147483648,d+(65536-d%65536)%65536);a:{try{pa.grow(f-ua.byteLength+65535>>>16);ya();var g=1;break a}catch(k){}g=void 0}if(g)return!0}return!1},
 Q:function(a,b){var c=0;Bc().forEach(function(d,f){var g=b+c;f=F[a+4*f>>2]=g;for(g=0;g<d.length;++g)B[f++>>0]=d.charCodeAt(g);B[f>>0]=0;c+=d.length+1});return 0},R:function(a,b){var c=Bc();F[a>>2]=c.length;var d=0;c.forEach(function(f){d+=f.length+1});F[b>>2]=d;return 0},l:function(a){try{var b=Q(a);N.close(b);return 0}catch(c){if("undefined"==typeof N||!(c instanceof N.Ma))throw c;return c.Ra}},H:function(a,b){try{var c=Q(a);B[b>>0]=c.tty?2:N.Ya(c.mode)?3:N.vb(c.mode)?7:4;return 0}catch(d){if("undefined"==
diff --git a/web/shared-worker/_generated/comm_query_executor.wasm b/web/shared-worker/_generated/comm_query_executor.wasm
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001

literal 0
Hc$@<O00001

diff --git a/web/shared-worker/queries/received-messages-to-device-queries.test.js b/web/shared-worker/queries/received-messages-to-device-queries.test.js
new file mode 100644
--- /dev/null
+++ b/web/shared-worker/queries/received-messages-to-device-queries.test.js
@@ -0,0 +1,77 @@
+// @flow
+
+import type { ReceivedMessageToDevice } from 'lib/types/sqlite-types.js';
+
+import { getDatabaseModule } from '../db-module.js';
+import type { EmscriptenModule } from '../types/module.js';
+import { type SQLiteQueryExecutor } from '../types/sqlite-query-executor.js';
+import { clearSensitiveData } from '../utils/db-utils.js';
+
+const FILE_PATH = 'test.sqlite';
+
+const device1 = 'device-1';
+const device2 = 'device-2';
+
+const TEST_MSG_1: ReceivedMessageToDevice = {
+  messageID: 'id-1',
+  senderDeviceID: device1,
+  plaintext: 'decrypted-1',
+  status: 'none',
+};
+
+const TEST_MSG_2: ReceivedMessageToDevice = {
+  messageID: 'id-2',
+  senderDeviceID: device2,
+  plaintext: 'decrypted-2',
+  status: 'none',
+};
+
+const TEST_MSG_3: ReceivedMessageToDevice = {
+  messageID: 'id-3',
+  senderDeviceID: device1,
+  plaintext: 'decrypted-3',
+  status: 'none',
+};
+
+const messagesOrdered = [TEST_MSG_1, TEST_MSG_2, TEST_MSG_3];
+
+describe('Received messages to device queries', () => {
+  let queryExecutor: ?SQLiteQueryExecutor = null;
+  let dbModule: ?EmscriptenModule = null;
+
+  beforeAll(async () => {
+    dbModule = getDatabaseModule();
+  });
+
+  beforeEach(() => {
+    if (!dbModule) {
+      throw new Error('Database module is missing');
+    }
+    queryExecutor = new dbModule.SQLiteQueryExecutor(FILE_PATH);
+    if (!queryExecutor) {
+      throw new Error('SQLiteQueryExecutor is missing');
+    }
+    queryExecutor?.addReceivedMessageToDevice(TEST_MSG_1);
+    queryExecutor?.addReceivedMessageToDevice(TEST_MSG_2);
+    queryExecutor?.addReceivedMessageToDevice(TEST_MSG_3);
+  });
+
+  afterEach(() => {
+    if (!dbModule || !queryExecutor) {
+      return;
+    }
+    clearSensitiveData(dbModule, FILE_PATH, queryExecutor);
+  });
+
+  it('should return all messages', () => {
+    const messages = queryExecutor?.getAllReceivedMessageToDevice() ?? [];
+    expect(messages.length).toBe(3);
+    expect(messages).toStrictEqual(messagesOrdered);
+  });
+  it('should remove messages', () => {
+    queryExecutor?.removeReceivedMessagesToDevice([TEST_MSG_2.messageID]);
+    const messages = queryExecutor?.getAllReceivedMessageToDevice() ?? [];
+    expect(messages.length).toBe(2);
+    expect(messages).toStrictEqual([TEST_MSG_1, TEST_MSG_3]);
+  });
+});
diff --git a/web/shared-worker/types/sqlite-query-executor.js b/web/shared-worker/types/sqlite-query-executor.js
--- a/web/shared-worker/types/sqlite-query-executor.js
+++ b/web/shared-worker/types/sqlite-query-executor.js
@@ -9,6 +9,7 @@
 import type { ClientDBThreadActivityEntry } from 'lib/ops/thread-activity-store-ops.js';
 import type { ClientDBUserInfo } from 'lib/ops/user-store-ops.js';
 import type { ClientDBDraftInfo } from 'lib/types/draft-types.js';
+import type { ReceivedMessageToDevice } from 'lib/types/sqlite-types.js';
 
 import {
   type WebClientDBThreadInfo,
@@ -171,6 +172,10 @@
     deviceID: string,
   ): $ReadOnlyArray<ClientMessageToDevice>;
 
+  addReceivedMessageToDevice(message: ReceivedMessageToDevice): void;
+  getAllReceivedMessageToDevice(): $ReadOnlyArray<ReceivedMessageToDevice>;
+  removeReceivedMessagesToDevice(ids: $ReadOnlyArray<string>): void;
+
   // method is provided to manually signal that a C++ object
   // is no longer needed and can be deleted
   delete(): void;