diff --git a/doc/autotodo.py b/doc/autotodo.py
index b3380fa5b77be190c2973775686583ba1375ab2c_ZG9jL2F1dG90b2RvLnB5..e5392599bf93178b228c589132a11bcfa30fc923_ZG9jL2F1dG90b2RvLnB5 100755
--- a/doc/autotodo.py
+++ b/doc/autotodo.py
@@ -2,7 +2,7 @@
 ##############################################################################
 #
 #    OpenERP, Open Source Management Solution
-#    Copyright © 2014, 2018, 2022, 2024 XCG Consulting
+#    Copyright © 2014, 2018, 2022-2024 XCG Consulting
 #
 #    This program is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Affero General Public License as
@@ -22,7 +22,7 @@
 import os
 import os.path
 import sys
-from collections.abc import Mapping
+from collections.abc import MutableMapping
 
 
 def main():
@@ -31,13 +31,13 @@
         sys.exit(1)
 
     folder = sys.argv[1]
-    exts = sys.argv[2].split(",")
-    tags = sys.argv[3].split(",")
-    todolist = {tag: [] for tag in tags}
-    path_file_length: Mapping[str, int] = {}
+    exts: list[str] = sys.argv[2].split(",")
+    tags: list[str] = sys.argv[3].split(",")
+    todolist: dict[str, list[tuple[str, int, str]]] = {tag: [] for tag in tags}
+    path_file_length: MutableMapping[str, int] = {}
 
     for root, _dirs, files in os.walk(folder):
         scan_folder((exts, tags, todolist, path_file_length), root, files)
     create_autotodo(folder, todolist, path_file_length)
 
 
@@ -38,10 +38,10 @@
 
     for root, _dirs, files in os.walk(folder):
         scan_folder((exts, tags, todolist, path_file_length), root, files)
     create_autotodo(folder, todolist, path_file_length)
 
 
-def write_info(f, infos, folder, path_file_length: Mapping[str, int]):
+def write_info(f, infos, folder, path_file_length: MutableMapping[str, int]):
     # Check sphinx version for lineno-start support
 
     import sphinx
@@ -78,10 +78,10 @@
         f.write("\n")
 
 
-def create_autotodo(folder, todolist, path_file_length: Mapping[str, int]):
+def create_autotodo(folder, todolist, path_file_length: MutableMapping[str, int]):
     with open("autotodo", "w+") as f:
         for tag, info in list(todolist.items()):
             f.write("{}\n{}\n\n".format(tag, "=" * len(tag)))
             write_info(f, info, folder, path_file_length)
 
 
@@ -82,10 +82,19 @@
     with open("autotodo", "w+") as f:
         for tag, info in list(todolist.items()):
             f.write("{}\n{}\n\n".format(tag, "=" * len(tag)))
             write_info(f, info, folder, path_file_length)
 
 
-def scan_folder(data_tuple, dirname, names):
+def scan_folder(
+    data_tuple: tuple[
+        list[str],
+        list[str],
+        dict[str, list[tuple[str, int, str]]],
+        MutableMapping[str, int],
+    ],
+    dirname: str,
+    names: list[str],
+):
     (exts, tags, res, path_file_length) = data_tuple
     for name in names:
         (root, ext) = os.path.splitext(name)
@@ -98,7 +107,9 @@
                     res[tag].extend(info)
 
 
-def scan_file(filename, tags) -> tuple[dict[str, list[tuple[str, int, str]]], int]:
+def scan_file(
+    filename: str, tags: list[str]
+) -> tuple[dict[str, list[tuple[str, int, str]]], int]:
     res: dict[str, list[tuple[str, int, str]]] = {tag: [] for tag in tags}
     line_num: int = 0
     with open(filename) as f:
diff --git a/doc/conf.py b/doc/conf.py
index b3380fa5b77be190c2973775686583ba1375ab2c_ZG9jL2NvbmYucHk=..e5392599bf93178b228c589132a11bcfa30fc923_ZG9jL2NvbmYucHk= 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -104,8 +104,6 @@
 
 # -- Options for LaTeX output ---------------------------------------------
 
-latex_elements = {}
-
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title,
 #  author, documentclass [howto, manual, or own class]).
diff --git a/models/xbus_envelope.py b/models/xbus_envelope.py
index b3380fa5b77be190c2973775686583ba1375ab2c_bW9kZWxzL3hidXNfZW52ZWxvcGUucHk=..e5392599bf93178b228c589132a11bcfa30fc923_bW9kZWxzL3hidXNfZW52ZWxvcGUucHk= 100644
--- a/models/xbus_envelope.py
+++ b/models/xbus_envelope.py
@@ -84,7 +84,9 @@
     def _compute_first_record_of_messages(self):
         for record in self:
             first_record = (
-                record.message_ids[0] if len(record.message_ids) == 1 else False
+                record.message_ids[0]
+                if len(record.message_ids) > 0
+                else self.env["xbus.message"]
             )
             record.message_type = first_record.type if first_record else False
             record.header = first_record.header if first_record else False
diff --git a/py.typed b/py.typed
new file mode 100644
diff --git a/pyproject.toml b/pyproject.toml
index b3380fa5b77be190c2973775686583ba1375ab2c_cHlwcm9qZWN0LnRvbWw=..e5392599bf93178b228c589132a11bcfa30fc923_cHlwcm9qZWN0LnRvbWw= 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -43,6 +43,7 @@
 
 [tool.hatch.build.targets.wheel]
 include = [
+  "py.typed",
   "*.csv",
   "/i18n/",
   "/static/",
diff --git a/tests/models.py b/tests/models.py
index b3380fa5b77be190c2973775686583ba1375ab2c_dGVzdHMvbW9kZWxzLnB5..e5392599bf93178b228c589132a11bcfa30fc923_dGVzdHMvbW9kZWxzLnB5 100644
--- a/tests/models.py
+++ b/tests/models.py
@@ -17,7 +17,7 @@
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 #############################################################################
-from odoo import fields, models  # type: ignore[import-untyped]
+from odoo import models  # type: ignore[import-untyped]
 
 
 class XbusMessage(models.Model):