diff --git a/.hgtags b/.hgtags
index 0ce14b51bba18c794989839bf2bb9cd55f87ff45_LmhndGFncw==..219b18bb38d8091f0a1f18d2eba9e59fb2d2aec4_LmhndGFncw== 100644
--- a/.hgtags
+++ b/.hgtags
@@ -13,3 +13,5 @@
 1ec96eae270f2bac3b80666e469d67d24b27874b 15.0.3.1.0
 0f20c71059ad5c526588f6b8ad65fa685a8b71f5 16.0.0.0.0
 a269f2a9de83b2393cee75c58f3c675232273b45 16.0.1.0.0
+da9a0fe039b65f5cfd3d5a5a60eaac2665026a91 13.0.3.2.0
+32a53dec98817ee36336896716cbacf8477a6d0a 15.0.3.2.0
diff --git a/NEWS.rst b/NEWS.rst
index 0ce14b51bba18c794989839bf2bb9cd55f87ff45_TkVXUy5yc3Q=..219b18bb38d8091f0a1f18d2eba9e59fb2d2aec4_TkVXUy5yc3Q= 100644
--- a/NEWS.rst
+++ b/NEWS.rst
@@ -1,6 +1,17 @@
 Changelog
 =========
 
+16.0.1.1.0
+----------
+
+(port from 15.0.3.2.0 / 13.0.3.2.0)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Export constants from ``.base``.
+Used by other modules; these exports got removed when I replaced an ``import *`` earlier.
+
+``jsonschema`` âž” ``fastjsonschema``.
+
 16.0.1.0.0
 ----------
 
diff --git a/__init__.py b/__init__.py
index 0ce14b51bba18c794989839bf2bb9cd55f87ff45_X19pbml0X18ucHk=..219b18bb38d8091f0a1f18d2eba9e59fb2d2aec4_X19pbml0X18ucHk= 100644
--- a/__init__.py
+++ b/__init__.py
@@ -20,6 +20,11 @@
 
 from . import models
 from .base import (
+    OPERATION_CREATION,
+    OPERATION_UPDATE,
+    PHASE_POSTCREATE,
+    PHASE_PRECREATE,
+    PHASE_UPDATE,
     Computed,
     Constant,
     ContextBuilder,
diff --git a/__manifest__.py b/__manifest__.py
index 0ce14b51bba18c794989839bf2bb9cd55f87ff45_X19tYW5pZmVzdF9fLnB5..219b18bb38d8091f0a1f18d2eba9e59fb2d2aec4_X19tYW5pZmVzdF9fLnB5 100644
--- a/__manifest__.py
+++ b/__manifest__.py
@@ -22,10 +22,10 @@
     "name": "Converter",
     "license": "AGPL-3",
     "summary": "Convert odoo records to/from plain data structures.",
-    "version": "16.0.1.0.0",
+    "version": "16.0.1.1.0",
     "category": "Hidden",
     "author": "XCG Consulting",
     "website": "https://orbeet.io/",
     "depends": ["base", "mail"],
     "data": [],
     "installable": True,
@@ -26,8 +26,8 @@
     "category": "Hidden",
     "author": "XCG Consulting",
     "website": "https://orbeet.io/",
     "depends": ["base", "mail"],
     "data": [],
     "installable": True,
-    "external_dependencies": {"python": ["jsonschema"]},
+    "external_dependencies": {"python": ["fastjsonschema"]},
 }
diff --git a/model.py b/model.py
index 0ce14b51bba18c794989839bf2bb9cd55f87ff45_bW9kZWwucHk=..219b18bb38d8091f0a1f18d2eba9e59fb2d2aec4_bW9kZWwucHk= 100644
--- a/model.py
+++ b/model.py
@@ -23,8 +23,6 @@
 from collections.abc import Iterable, Mapping
 from typing import Any, Optional
 
-import jsonschema
-
 from odoo import api, models
 
 from .base import (
@@ -97,7 +95,7 @@
         if self.validation != VALIDATION_SKIP and self._jsonschema is not None:
             try:
                 self.validator.validate(self._jsonschema, message_data)
-            except jsonschema.exceptions.ValidationError as exception:
+            except Exception as exception:
                 _logger.warning("Validation failed", exc_info=1)
                 if self.validation == VALIDATION_STRICT:
                     raise exception
diff --git a/pyproject.toml b/pyproject.toml
index 0ce14b51bba18c794989839bf2bb9cd55f87ff45_cHlwcm9qZWN0LnRvbWw=..219b18bb38d8091f0a1f18d2eba9e59fb2d2aec4_cHlwcm9qZWN0LnRvbWw= 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -13,7 +13,7 @@
   "Framework :: Odoo :: 16.0",
   "License :: OSI Approved :: GNU Affero General Public License v3"
 ]
-dependencies = ["odoo==16.0.*", "jsonschema"]
+dependencies = ["odoo==16.0.*", "fastjsonschema"]
 
 [project.optional-dependencies]
 doc = ["sphinx", "sphinx-odoo-autodoc"]
diff --git a/validate.py b/validate.py
index 0ce14b51bba18c794989839bf2bb9cd55f87ff45_dmFsaWRhdGUucHk=..219b18bb38d8091f0a1f18d2eba9e59fb2d2aec4_dmFsaWRhdGUucHk= 100644
--- a/validate.py
+++ b/validate.py
@@ -19,6 +19,5 @@
 ##############################################################################
 
 import json
-import math
 import os
 
@@ -23,6 +22,6 @@
 import os
 
-import jsonschema
+import fastjsonschema
 
 import odoo.addons
 
@@ -46,5 +45,4 @@
         self.repository = repository
         # exemple "https://annonces-legales.fr/xbus/schemas/v1/{}.schema.json"
         self.default_url_pattern = default_url_pattern
-        self.schemastore = {}
         self.validators = {}
@@ -50,5 +48,4 @@
         self.validators = {}
-        self.search_path = "not initialized, please call initialize()"
         self.initialized = False
         self.encoding = "UTF-8"
 
@@ -56,6 +53,9 @@
         repo_module_basepath = os.path.dirname(
             getattr(odoo.addons, self.repository_module_name).__file__
         )
+
+        # Read local schema definitions.
+        schemas = {}
         schema_search_path = os.path.abspath(
             os.path.join(repo_module_basepath, self.repository)
         )
@@ -59,12 +59,10 @@
         schema_search_path = os.path.abspath(
             os.path.join(repo_module_basepath, self.repository)
         )
-        self.search_path = schema_search_path
-
-        for root, _dirs, files in os.walk(self.search_path):
+        for root, _dirs, files in os.walk(schema_search_path):
             for fname in files:
                 fpath = os.path.join(root, fname)
                 if fpath.endswith((".json",)):
                     with open(fpath, "r", encoding=self.encoding) as schema_fd:
                         schema = json.load(schema_fd)
                         if "$id" in schema:
@@ -65,9 +63,18 @@
             for fname in files:
                 fpath = os.path.join(root, fname)
                 if fpath.endswith((".json",)):
                     with open(fpath, "r", encoding=self.encoding) as schema_fd:
                         schema = json.load(schema_fd)
                         if "$id" in schema:
-                            self.schemastore[schema["$id"]] = schema
+                            schemas[schema["$id"]] = schema
+
+        # Prepare validators for each schema. We add an HTTPS handler that
+        # points back to our schema definition cache built above.
+        for schema_id, schema in schemas.items():
+            self.validators[schema_id] = fastjsonschema.compile(
+                schema,
+                handlers={"https": lambda uri: schemas[uri]},
+                use_default=False,
+            )
         self.initialized = True
 
@@ -72,6 +79,6 @@
         self.initialized = True
 
-    def validate(self, schema_id, doc) -> None:
+    def validate(self, schema_id, payload) -> None:
         if not self.initialized:
             raise NotInitialized("please call the initialize() method")
 
@@ -75,34 +82,4 @@
         if not self.initialized:
             raise NotInitialized("please call the initialize() method")
 
-        uri = "file://{}/{}.schema.json".format(self.search_path, schema_id)
-        validator = self.validators.get(uri)
-        if validator is None:
-            schema = self.schemastore[self.default_url_pattern.format(schema_id)]
-
-            resolver = jsonschema.RefResolver(uri, schema, self.schemastore)
-
-            validator = jsonschema.Draft7Validator(schema, resolver=resolver)
-            self.validators[uri] = validator
-
-        validator.validate(doc)
-
-
-def multiple_of(validator, db, instance, schema):
-    """Fix rounding which fails when comparing e.g. 66.6 vs 0.01"""
-
-    if not validator.is_type(instance, "number"):
-        return
-
-    if isinstance(db, float):
-        quotient = instance / db
-        failed = not math.isclose(round(quotient), quotient)
-    else:
-        failed = instance % db
-
-    if failed:
-        yield jsonschema.ValidationError("%r is not a multiple of %r" % (instance, db))
-
-
-# Fix rounding which fails when comparing e.g. 66.6 vs 0.01
-jsonschema.Draft7Validator.VALIDATORS["multipleOf"] = multiple_of
+        self.validators[self.default_url_pattern.format(schema_id)](payload)