diff --git a/.pylintrc b/.pylintrc
new file mode 100644
index 0000000000000000000000000000000000000000..d5b831302d169f0ce8adbc8835d2909eee7fd51b
--- /dev/null
+++ b/.pylintrc
@@ -0,0 +1,9 @@
+[MAIN]
+extension-pkg-whitelist=pydantic
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+# Note that it does not contain TODO, only the default FIXME and XXX
+notes=FIXME,
+      XXX
diff --git a/gso/main.py b/gso/main.py
index ba2582a89cd363aa761b67b6dbcf4cddc388344e..6d9a9378446f72c501c57d1075822adfe630c96f 100644
--- a/gso/main.py
+++ b/gso/main.py
@@ -1,8 +1,11 @@
+"""
+The main module, from where GSO is run.
+"""
 from orchestrator import OrchestratorCore
 from orchestrator.cli.main import app as core_cli
 from orchestrator.settings import AppSettings
-import gso.products  # noqa: F401
-import gso.workflows  # noqa: F401
+import gso.products  # pylint: disable=unused-import
+import gso.workflows  # pylint: disable=unused-import
 
 
 app = OrchestratorCore(base_settings=AppSettings())
diff --git a/gso/products/__init__.py b/gso/products/__init__.py
index 857128fb672bf6350e674bfc81e8d89fa2765af2..319d1578b865217c83359a744274ac41d1e41f3e 100644
--- a/gso/products/__init__.py
+++ b/gso/products/__init__.py
@@ -1,3 +1,7 @@
+"""
+Module that updated the domain model of GSO. Should contain all types of
+subscriptions.
+"""
 from orchestrator.domain import SUBSCRIPTION_MODEL_REGISTRY
 
 from gso.products.product_types.device import Device
diff --git a/gso/services/provisioning_proxy.py b/gso/services/provisioning_proxy.py
index 20ec4a9d967de80834695f67e2a9b6b92959f651..55c272c2ccfea1d4e6ebceb517076cec38d9680c 100644
--- a/gso/services/provisioning_proxy.py
+++ b/gso/services/provisioning_proxy.py
@@ -1,3 +1,7 @@
+"""
+The Provisioning Proxy service, which interacts with LSO running externally.
+LSO is responsible for executing Ansible playbooks, that deploy subscriptions.
+"""
 import json
 import logging
 
@@ -53,7 +57,8 @@ def _send_request(endpoint: str, parameters: dict, process_id: UUIDstr,
 
     callback_url = f'{settings.load_oss_params().GENERAL.public_hostname}' \
                    f'/api/processes/{process_id}/resume'
-    logger.debug(f'[provisioning proxy] provisioning for process {process_id}')
+    logger.debug('[provisioning proxy] provisioning for process %s',
+                 process_id)
 
     parameters.update({'callback': callback_url})
     url = f'{pp_params.scheme}://{pp_params.api_base}/api/{endpoint}'
@@ -61,11 +66,11 @@ def _send_request(endpoint: str, parameters: dict, process_id: UUIDstr,
     request = None
 
     if operation == CUDOperation.POST:
-        request = requests.post(url, json=parameters)
+        request = requests.post(url, json=parameters, timeout=10000)
     elif operation == CUDOperation.PUT:
-        request = requests.put(url, json=parameters)
+        request = requests.put(url, json=parameters, timeout=10000)
     elif operation == CUDOperation.DELETE:
-        request = requests.delete(url, json=parameters)
+        request = requests.delete(url, json=parameters, timeout=10000)
 
     if request.status_code != 200:
         print(request.content)
@@ -136,7 +141,7 @@ def provision_ip_trunk(subscription: IptrunkProvisioning,
 #        'dry_run': dry_run,
 #        'old_subscription': old_subscription,
 #        'subscription': new_subscription
-#        # FIXME missing parameters
+#        # ... missing parameters
 #    }
 #
 #    _send_request('ip_trunk', parameters, process_id, CUDOperation.PUT)
diff --git a/gso/settings.py b/gso/settings.py
index 7167785cb32245f51316809db517bd09bbc251d8..8e8ad08f44ec1efdd8c3860e4e602e9e4d23e7cd 100644
--- a/gso/settings.py
+++ b/gso/settings.py
@@ -1,14 +1,25 @@
+"""
+GSO settings, ensuring that the required parameters are set correctly.
+"""
 import ipaddress
 import json
 import os
-from pydantic import BaseSettings
+from pydantic import BaseSettings, Field
 
 
 class GeneralParams(BaseSettings):
+    """
+    General parameters for a GSO configuration file.
+    """
+    #: The hostname that GSO is publicly served at, used for building the
+    #: callback URL that the provisioning proxy uses.
     public_hostname: str
 
 
 class InfoBloxParams(BaseSettings):
+    """
+    Parameters related to InfoBlox.
+    """
     scheme: str
     wapi_version: str
     host: str
@@ -17,24 +28,37 @@ class InfoBloxParams(BaseSettings):
 
 
 class V4NetworkParams(BaseSettings):
+    """
+    A set of parameters that describe an IPv4 network in InfoBlox.
+    """
     containers: list[ipaddress.IPv4Network]
     networks: list[ipaddress.IPv4Network]
-    mask: int  # TODO: validation on mask?
+    mask: int = Field(None, ge=0, le=32)
 
 
 class V6NetworkParams(BaseSettings):
+    """
+    A set of parameters that describe an IPv6 network in InfoBlox.
+    """
     containers: list[ipaddress.IPv6Network]
     networks: list[ipaddress.IPv6Network]
-    mask: int  # TODO: validation on mask?
+    mask: int = Field(None, ge=0, le=128)
 
 
 class ServiceNetworkParams(BaseSettings):
+    """
+    Parameters for InfoBlox that describe IPv4 and v6 networks, and the
+    corresponding domain name that should be used as a suffix.
+    """
     V4: V4NetworkParams
     V6: V6NetworkParams
     domain_name: str
 
 
 class IPAMParams(BaseSettings):
+    """
+    A set of parameters related to IPAM.
+    """
     INFOBLOX: InfoBloxParams
     LO: ServiceNetworkParams
     TRUNK: ServiceNetworkParams
@@ -42,6 +66,9 @@ class IPAMParams(BaseSettings):
 
 
 class ProvisioningProxyParams(BaseSettings):
+    """
+    Parameters for the provisioning proxy.
+    """
     scheme: str
     api_base: str
     auth: str  # FIXME: unfinished
@@ -49,19 +76,22 @@ class ProvisioningProxyParams(BaseSettings):
 
 
 class OSSParams(BaseSettings):
+    """
+    The set of parameters required for running GSO.
+    """
     GENERAL: GeneralParams
     IPAM: IPAMParams
-    RESOURCE_MANAGER_API_PREFIX: str  # api prefix
+    RESOURCE_MANAGER_API_PREFIX: str
     PROVISIONING_PROXY: ProvisioningProxyParams
 
 
 def load_oss_params() -> OSSParams:
     """
-    look for OSS_PARAMS_FILENAME in the environment and load the
-    parameters from that file
+    look for OSS_PARAMS_FILENAME in the environment and load the parameters
+    from that file.
     """
-    with open(os.environ['OSS_PARAMS_FILENAME']) as f:
-        return OSSParams(**json.loads(f.read()))
+    with open(os.environ['OSS_PARAMS_FILENAME'], encoding='utf-8') as file:
+        return OSSParams(**json.loads(file.read()))
 
 
 if __name__ == '__main__':
diff --git a/gso/workflows/__init__.py b/gso/workflows/__init__.py
index 268bada22e4b28b76ffc3e1371b1e23d2a8c2c47..16f97832e58ceb6963249fecdcd696798deb45e2 100644
--- a/gso/workflows/__init__.py
+++ b/gso/workflows/__init__.py
@@ -1,3 +1,6 @@
+"""
+init class that imports all workflows into GSO.
+"""
 from orchestrator.workflows import LazyWorkflowInstance
 
 LazyWorkflowInstance("gso.workflows.device.create_device", "create_device")