diff --git a/docs/source/3_dev/2_structure/1_backend/1_techstack.rst b/docs/source/3_dev/2_structure/1_backend/1_techstack.rst
new file mode 100644
index 0000000..576a583
--- /dev/null
+++ b/docs/source/3_dev/2_structure/1_backend/1_techstack.rst
@@ -0,0 +1,16 @@
+Librerie e tecnologie utilizzate
+--------------------------------
+
+.. note::
+
+ Sono elencate solo le principali librerie utilizzate; dipendenze e librerie minori non sono specificate, ma sono visibili all'interno del file ``poetry.lock``.
+
+- Il linguaggio di programmazione `Python `_
+ - Il gestore di dipendenze `Poetry `_
+ - Il framework web `Django `_
+ - L'estensione per Django `Django REST Framework `_
+ - L'estensione per Django `Django CORS Headers `_
+ - L'adattatore database per PostgreSQL `Psycopg `_
+ - Il `Docker SDK for Python `_
+ - I server web `Gunicorn `_ e `Uvicorn `_
+ - L'utilità `lazy-object-proxy `_
diff --git a/docs/source/3_dev/2_structure/1_backend/2_sophon.rst b/docs/source/3_dev/2_structure/1_backend/2_sophon.rst
new file mode 100644
index 0000000..db9b562
--- /dev/null
+++ b/docs/source/3_dev/2_structure/1_backend/2_sophon.rst
@@ -0,0 +1,89 @@
+Il progetto sophon
+------------------
+.. default-domain:: py
+.. default-role:: obj
+.. module:: sophon
+
+Il progetto Django Sophon aggiunge varie funzionalità al template base dei progetti Django.
+
+
+Pagina di amministrazione personalizzata
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. module:: sophon.admin
+
+La pagina di amministrazione viene personalizzata con la classe `SophonAdminSite`, che modifica alcuni parametri della classe base.
+
+Inoltre, il template predefinito viene sovrascritto da quello all'interno del file ``templates/admin/base.html``, che sostituisce il foglio di stile con uno personalizzato per Sophon.
+
+.. class:: SophonAdminSite(django.contrib.admin.AdminSite)
+
+ .. attribute:: site_header = "Sophon Server Administration"
+
+ Il nome della pagina nell'header viene modificato a *Sophon Server Administration*.
+
+ .. attribute:: site_title = "Sophon Server Administration"
+
+ Il titolo della pagina nell'header viene anch'esso modificato a *Sophon Server Administration*.
+
+ .. attribute:: site_url = None
+
+ Il collegamento *View Site* viene rimosso, in quanto è possibile accedere all'interfaccia web di Sophon da più domini contemporaneamente.
+
+ .. attribute:: index_title = "Resources Administration"
+
+ Il titolo dell'indice viene modificato a *Resources Administration*.
+
+.. class:: SophonAdminConfig(django.contrib.admin.apps.AdminConfig)
+
+ .. attribute:: default_site = "sophon.admin.SophonAdminSite"
+
+ `.SophonAdminSite` è selezionata come classe predefinita per il sito di amministrazione.
+
+
+Impostazioni dinamiche
+^^^^^^^^^^^^^^^^^^^^^^
+.. module:: sophon.settings
+
+Il file di impostazioni viene modificato per **permettere la configurazione attraverso variabili di ambiente** invece che attraverso il file ``settings.py``, rendendo il deployment con Docker molto più semplice.
+
+.. code-block:: python
+
+ try:
+ DATABASE_ENGINE = os.environ["DJANGO_DATABASE_ENGINE"]
+ except KeyError:
+ log.warning("DJANGO_DATABASE_ENGINE was not set, defaulting to PostgreSQL")
+ DATABASE_ENGINE = "django.db.backends.postgresql"
+ log.debug(f"{DATABASE_ENGINE = }")
+
+Inoltre, viene configurato il modulo `logging` per emettere testo colorato di più facile comprensione usando il package `coloredlogs`.
+
+.. code-block:: python
+
+ "detail": {
+ "()": coloredlogs.ColoredFormatter,
+ "format": "{asctime:>19} | {name:<24} | {levelname:>8} | {message}",
+ "style": "{",
+ }
+
+
+Autenticazione migliorata
+^^^^^^^^^^^^^^^^^^^^^^^^^
+.. module:: sophon.auth1
+
+La classe `rest_framework.authentication.TokenAuthentication` viene modificata per ottenere un comportamento conforme agli standard del web.
+
+.. class:: BearerTokenAuthentication(rest_framework.authentication.TokenAuthentication)
+
+ .. attribute:: keyword = "Bearer"
+
+ Si configura `rest_framework` per accettare header di autenticazione nella forma ``Bearer ``, invece che ``Token ``.
+
+.. module:: sophon.auth2
+
+La view `rest_framework.authtoken.views.ObtainAuthToken` viene estesa per aggiungere dati alla risposta di autenticazione riuscita.
+
+.. class:: CustomObtainAuthToken(rest_framework.authtoken.views.ObtainAuthToken)
+
+ .. method:: post(self, request, *args, **kwargs)
+
+ In particolare, viene aggiunta una chiave ``user``, che contiene i dettagli sull'utente che ha effettuato il login.
diff --git a/docs/source/3_dev/2_structure/1_backend/3_core.rst b/docs/source/3_dev/2_structure/1_backend/3_core.rst
new file mode 100644
index 0000000..041f3a1
--- /dev/null
+++ b/docs/source/3_dev/2_structure/1_backend/3_core.rst
@@ -0,0 +1,214 @@
+L'app sophon.core
+-----------------
+.. default-domain:: py
+.. default-role:: obj
+.. module:: sophon.core
+
+
+L'app `sophon.core` è l'app principale del progetto, e non può essere disattivata, in quanto dipendenza obbligatoria di tutte le altre app.
+
+
+Aggiunta di un nuovo comando di gestione
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. module:: sophon.core.management.commands.initsuperuser
+
+Per permettere l'integrazione la creazione automatica del primo :ref:`superutente` quando Sophon viene eseguito da Docker, viene introdotto il comando di gestione ``initsuperuser``.
+
+.. class:: Command
+
+ Questo comando crea automaticamente un :ref:`superutente` con le credenziali specificate in :ref:`\`\`DJANGO_SU_USERNAME\`\``, :ref:`\`\`DJANGO_SU_EMAIL\`\`` e :ref:`\`\`DJANGO_SU_PASSWORD\`\``.
+
+
+Modello base astratto
+^^^^^^^^^^^^^^^^^^^^^
+.. module:: sophon.core.models
+
+Viene estesa la classe astratta `django.db.models.Model` con funzioni per stabilire il livello di accesso di un utente all'oggetto e per generare automaticamente i `rest_framework.serializers.ModelSerializer` in base al livello di accesso.
+
+.. class:: SophonModel(django.db.models.Model)
+
+ .. method:: can_edit(self, user: django.contrib.auth.models.User) -> bool
+ :abstractmethod:
+
+ Controlla se un utente può modificare l'oggetto attuale.
+
+ :param user: L'utente da controllare.
+ :returns: `True` se l'utente deve poter modificare l'oggetto, altrimenti `False`.
+
+ .. method:: can_admin(self, user: django.contrib.auth.models.User) -> bool
+ :abstractmethod:
+
+ Controlla se un utente può amministrare l'oggetto attuale.
+
+ :param user: L'utente da controllare.
+ :returns: `True` se l'utente deve poter amministrare l'oggetto, altrimenti `False`.
+
+ .. classmethod:: get_fields(cls) -> set[str]
+
+ :returns: il `set` di nomi di campi che devono essere mostrati quando viene richiesto l'oggetto attraverso l'API.
+
+ .. classmethod:: get_editable_fields(cls) -> set[str]
+
+ :returns: il `set` di nomi di campi di cui deve essere permessa la modifica se l'utente può modificare (`.can_edit`) l'oggetto.
+
+ .. classmethod:: get_administrable_fields(cls) -> set[str]
+
+ :returns: il `set` di nomi di campi di cui deve essere permessa la modifica se l'utente può amministrare (`.can_admin`) l'oggetto.
+
+ .. classmethod:: get_creation_fields(cls) -> set[str]
+
+ :returns: il `set` di nomi di campi che possono essere specificati dall'utente al momento della creazione dell'oggetto.
+
+
+Modello di autorizzazione astratto
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Viene definito un nuovo modello astratto, basato su `SophonModel`, che permette di determinare i permessi dell'utente in base alla sua appartenenza al gruppo a cui è collegato l'oggetto implementatore.
+
+.. class:: SophonGroupModel(SophonModel)
+
+ .. method:: get_group(self) -> ResearchGroup
+ :abstractmethod:
+
+ :returns: Il gruppo a cui appartiene l'oggetto.
+
+ .. classmethod:: get_access_to_edit(cls) -> sophon.core.enums.SophonGroupAccess
+
+ :returns: Il livello di autorità all'interno del gruppo necessario per modificare l'oggetto.
+
+ .. classmethod:: get_access_to_admin(cls) -> sophon.core.enums.SophonGroupAccess
+
+ :returns: Il livello di autorità all'interno del gruppo necessario per amministrare l'oggetto.
+
+ .. method:: get_access_serializer(self, user: User) -> typing.Type[rest_framework.serializers.ModelSerializer]
+
+ :returns: Restituisce il `rest_framework.serializers.ModelSerializer` adeguato al livello di autorità dell'utente.
+
+
+.. class:: sophon.core.enums.SophonGroupAccess(enum.IntEnum)
+
+ Enumerazione che stabilisce il livello di autorità che un utente può avere all'interno di un gruppo.
+
+ .. attribute:: NONE = 0
+
+ Utente :ref:`ospite`.
+
+ .. attribute:: REGISTERED = 10
+
+ :ref:`Utente` registrato.
+
+ .. attribute:: MEMBER = 50
+
+ Membro del :ref:`gruppo di ricerca`.
+
+ .. attribute:: OWNER = 100
+
+ Creatore del :ref:`gruppo di ricerca`.
+
+ .. attribute:: SUPERUSER = 200
+
+ :ref:`Superutente` con privilegi universali.
+
+
+Modello dei dettagli dell'istanza
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Viene creato il modello che rappresenta i dettagli dell':ref:`istanza` Sophon.
+
+.. class:: SophonInstanceDetails(SophonModel)
+
+ .. attribute:: id: IntegerField [1]
+
+ Impostando ``1`` come unica scelta per il campo della chiave primaria ``id``, si crea un modello "singleton", ovvero un modello di cui può esistere un'istanza sola in tutto il database.
+
+ .. attribute:: name: CharField
+ .. attribute:: description: TextField
+ .. attribute:: theme: CharField ["sophon", "paper", "royalblue", "hacker", "amber"]
+
+ .. method:: version: str
+ :property:
+
+ :returns: La versione installata del pacchetto `sophon`.
+
+ .. seealso::
+
+ :ref:`Sophon instance details` nella guida per l'amministratore.
+
+
+Modello del gruppo di ricerca
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. class:: ResearchGroup(SophonGroupModel)
+
+ Modello che rappresenta un :ref:`gruppo di ricerca`.
+
+ .. attribute:: slug: SlugField
+ .. attribute:: name: CharField
+ .. attribute:: description: TextField
+ .. attribute:: members: ManyToManyField → django.contrib.auth.models.User
+ .. attribute:: owner: ForeignKey → django.contrib.auth.models.User
+ .. attribute:: access: CharField ["MANUAL", "OPEN"]
+
+
+Estensione ai permessi di Django
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. module:: sophon.core.permissions
+
+I permessi di `rest_framework` vengono estesi con due nuove classi che utilizzano il :ref:`modello di autorizzazione` precedentemente definito.
+
+.. class:: Edit(rest_framework.permissions.BasePermission)
+
+ Consente l'interazione solo agli utenti che possono modificare (`.can_edit`) l'oggetto.
+
+.. class:: Admin(rest_framework.permissions.BasePermission)
+
+ Consente l'interazione solo agli utenti che possono amministrare (`.can_admin`) l'oggetto.
+
+
+Viewset astratte
+^^^^^^^^^^^^^^^^
+.. module:: sophon.core.views
+
+Vengono definiti due viewset in grado di utilizzare i metodi aggiunti dalle classi astratte `.models.SophonModel` e `.models.SophonGroupModel`.
+
+.. class:: ReadSophonViewSet(rest_framework.viewsets.ReadOnlyModelViewSet, metaclass=abc.ABCMeta)
+
+ Estende la classe base `rest_framework.viewsets.ReadOnlyModelViewSet` con metodi di utilità mancanti nell'implementazione originale, allacciandola inoltre a `.models.SophonGroupModel`.
+
+ .. method:: get_queryset(self) -> QuerySet
+ :abstractmethod:
+
+ Imposta come astratto (e quindi obbligatorio) il metodo `rest_framework.viewsets.ReadOnlyModelViewSet.get_queryset`.
+
+ .. method:: permission_classes(self)
+ :property:
+
+ Sovrascrive il campo di classe `rest_framework.viewsets.ReadOnlyModelViewSet.permission_classes` con una funzione, permettendone la selezione dei permessi richiesti al momento di ricezione di una richiesta HTTP (invece che al momento di definizione della classe).
+
+ Delega la selezione delle classi a `.get_permission_classes`.
+
+ .. method:: get_permission_classes(self) -> typing.Collection[typing.Type[permissions.BasePermission]]
+
+ Funzione che permette la selezione dei permessi necessari per effetuare una determinata richiesta al momento di ricezione di quest'ultima.
+
+ Utile per le classi che erediteranno da questa.
+
+ .. method:: get_serializer_class(self) -> typing.Type[Serializer]
+ :final:
+
+ Funzione che permette la selezione del `rest_framework.serializers.Serializer` da utilizzare per una determinata richiesta al momento di ricezione di quest'ultima.
+
+ Utilizza:
+
+ - il serializzatore **in sola lettura** per elencare gli oggetti (azione ``list``);
+ - il serializzatore **di creazione** per creare nuovi oggetti (azione ``create``) e per generare i metadati del viewset (azione ``metadata``);
+ - il serializzatore ottenuto da `.models.SophonGroupModel.get_access_serializer` per la visualizzazione dettagliata (azione ``retrieve``), la modifica (azioni ``update`` e ``partial_update``) e l'eliminazione (azione ``destroy``) di un singolo oggetto;
+ - il serializzatore ottenuto da `.get_custom_serializer_classes` per le azioni personalizzate.
+
+ .. seealso::
+
+ `.models.SophonGroupModel`
+
+ .. method:: get_custom_serializer_classes(self) -> t.Type[Serializer]
+
+ Permette alle classi che ereditano da questa di selezionare quale `rest_framework.serializers.Serializer` utilizzare per le azioni personalizzate.
\ No newline at end of file
diff --git a/docs/source/3_dev/2_structure/1_backend/4_projects.rst b/docs/source/3_dev/2_structure/1_backend/4_projects.rst
new file mode 100644
index 0000000..8f38cf7
--- /dev/null
+++ b/docs/source/3_dev/2_structure/1_backend/4_projects.rst
@@ -0,0 +1,6 @@
+L'app sophon.projects
+-----------------------
+.. default-domain:: py
+.. default-role:: obj
+.. module:: sophon.projects
+
diff --git a/docs/source/3_dev/2_structure/1_backend/5_notebooks.rst b/docs/source/3_dev/2_structure/1_backend/5_notebooks.rst
new file mode 100644
index 0000000..b831918
--- /dev/null
+++ b/docs/source/3_dev/2_structure/1_backend/5_notebooks.rst
@@ -0,0 +1,6 @@
+L'app sophon.notebooks
+----------------------
+.. default-domain:: py
+.. default-role:: obj
+.. module:: sophon.notebooks
+
diff --git a/docs/source/3_dev/2_structure/1_backend/index.rst b/docs/source/3_dev/2_structure/1_backend/index.rst
index 7c2e0fe..cee31c5 100644
--- a/docs/source/3_dev/2_structure/1_backend/index.rst
+++ b/docs/source/3_dev/2_structure/1_backend/index.rst
@@ -4,153 +4,17 @@ Modulo backend
.. default-role:: obj
.. py:currentmodule:: sophon
-Il *modulo backend* consiste in un server web che consente agli utenti:
-
-- Attraverso l'API:
- - *autenticazione* e *autorizzazione* degli utenti;
- - *visualizzazione*, *interazione*, *creazione*, *modifica* ed *eliminazione* di gruppi di ricerca, progetti di ricerca e notebook
- - *visualizzazione* di utenti e dettagli sull'istanza Sophon.
-
-- Attraverso pagine web dinamiche:
- - *amministrazione* dell'istanza Sophon.
-
-Inoltre, effettua le seguenti operazioni in risposta a determinate richieste effettuate dagli utenti:
-
-- *configurazione*, *avvio* e *arresto* di container Docker basati sulle immagini specificate dai notebook;
-- *configurazione*, *attivazione* e *disattivazione* del servizio di proxying effettuato dal :ref:`modulo proxy`.
+Il *modulo backend* consiste in un server web che espone un'API e un sito web per l'amministrazione.
È collocato all'interno del repository in ``/backend``.
+È formato dal package Python `sophon`, che contiene al suo interno un progetto Django, che a sua volta contiene le tre app Django `sophon.core`, `sophon.projects` e `sophon.notebooks`.
-Librerie e tecnologie utilizzate
---------------------------------
-
-.. note::
-
- Sono elencate solo le principali librerie utilizzate; dipendenze e librerie minori non sono specificate, ma sono visibili all'interno del file ``poetry.lock``.
-
-- Il linguaggio di programmazione `Python `_
- - Il gestore di dipendenze `Poetry `_
- - Il framework web `Django `_
- - L'estensione per Django `Django REST Framework `_
- - L'estensione per Django `Django CORS Headers `_
- - L'adattatore database per PostgreSQL `Psycopg `_
- - Il `Docker SDK for Python `_
- - I server web `Gunicorn `_ e `Uvicorn `_
- - L'utilità `lazy-object-proxy `_
-
-
-Struttura del modulo
---------------------
-
-Il modulo consiste nel package Python :mod:`sophon`, che contiene al suo interno un progetto Django, che a sua volta contiene tre app Django.
-
-
-Il progetto `sophon`
-^^^^^^^^^^^^^^^^^^^^
-.. module:: sophon
-
-Il progetto Django Sophon aggiunge varie funzionalità al template base dei progetti Django.
-
-
-Pagina di amministrazione personalizzata
-""""""""""""""""""""""""""""""""""""""""
-
-.. module:: sophon.admin
-
-.. class:: SophonAdminSite(django.contrib.admin.AdminSite)
-
- La pagina di amministrazione viene personalizzata con la classe `SophonAdminSite`, che sovrascrive alcuni parametri della classe di default.
-
- Inoltre, il template predefinito viene sovrascritto da quello all'interno del file ``templates/admin/base.html``, che sostituisce il foglio di stile con uno personalizzato per Sophon.
-
- .. attribute:: site_header = "Sophon Server Administration"
-
- Il nome della pagina nell'header viene modificato a *Sophon Server Administration*.
-
- .. attribute:: site_title = "Sophon Server Administration"
-
- Il titolo della pagina nell'header viene anch'esso modificato a *Sophon Server Administration*.
-
- .. attribute:: site_url = None
-
- Il collegamento *View Site* viene rimosso, in quanto è possibile accedere all'interfaccia web di Sophon da più domini contemporaneamente.
-
- .. attribute:: index_title = "Resources Administration"
-
- Il titolo dell'indice viene modificato a *Resources Administration*.
-
-.. class:: SophonAdminConfig(django.contrib.admin.apps.AdminConfig)
-
- La configurazione di default della pagina di amministrazione viene sovrascritta da questa classe.
-
- .. attribute:: default_site = "sophon.admin.SophonAdminSite"
-
- `.SophonAdminSite` è selezionata come classe predefinita.
-
-
-Impostazioni dinamiche
-""""""""""""""""""""""
-.. module:: sophon.settings
-
-Il file di impostazioni viene modificato per **permettere la configurazione attraverso variabili di ambiente** invece che attraverso il file ``settings.py``, rendendo il deployment con Docker molto più semplice.
-
-.. code-block:: python
-
- try:
- DATABASE_ENGINE = os.environ["DJANGO_DATABASE_ENGINE"]
- except KeyError:
- log.warning("DJANGO_DATABASE_ENGINE was not set, defaulting to PostgreSQL")
- DATABASE_ENGINE = "django.db.backends.postgresql"
- log.debug(f"{DATABASE_ENGINE = }")
-
-Inoltre, viene configurato il modulo `logging` per emettere testo colorato di più facile comprensione usando il package `coloredlogs`.
-
-.. code-block:: python
-
- "detail": {
- "()": coloredlogs.ColoredFormatter,
- "format": "{asctime:>19} | {name:<24} | {levelname:>8} | {message}",
- "style": "{",
- }
-
-
-Autenticazione migliorata
-"""""""""""""""""""""""""
-.. module:: sophon.auth1
-
-.. class:: BearerTokenAuthentication(rest_framework.authentication.TokenAuthentication)
-
- La classe `rest_framework.authentication.TokenAuthentication` viene modificata per ottenere un comportamento conforme agli standard del web.
-
- .. attribute:: keyword = "Bearer"
-
- Si configura `rest_framework` per accettare header di autenticazione nella forma ``Bearer ``, invece che ``Token ``.
-
-.. module:: sophon.auth2
-
-.. class:: CustomObtainAuthToken(rest_framework.authtoken.views.ObtainAuthToken)
-
- La view `rest_framework.authtoken.views.ObtainAuthToken` viene estesa per aggiungere dati alla risposta di autenticazione riuscita.
-
- .. method:: post(self, request, *args, **kwargs)
-
- In particolare, viene aggiunta una chiave ``user``, che contiene i dettagli sull'utente che ha effettuato il login.
-
-.. todo: whoa ma io mi ero scordato di sta cosa
-
-
-L'app `sophon.core`
-^^^^^^^^^^^^^^^^^^^
-.. module:: sophon.core
-
-
-L'app `sophon.projects`
-^^^^^^^^^^^^^^^^^^^^^^^
-.. module:: sophon.projects
-
-
-L'app `sophon.notebooks`
-^^^^^^^^^^^^^^^^^^^^^^^^
-.. module:: sophon.notebooks
+.. toctree::
+ :maxdepth: 1
+ 1_techstack
+ 2_sophon
+ 3_core
+ 4_projects
+ 5_notebooks
\ No newline at end of file
diff --git a/docs/source/3_dev/2_structure/index.rst b/docs/source/3_dev/2_structure/index.rst
index 778dfbd..98dca12 100644
--- a/docs/source/3_dev/2_structure/index.rst
+++ b/docs/source/3_dev/2_structure/index.rst
@@ -3,6 +3,8 @@ Struttura del progetto
Sophon è composto da quattro moduli, *backend*, *frontend*, *proxy* e *jupyter*, che interagiscono tra loro per fornire agli utenti tutti i servizi necessari.
+
+
.. toctree::
:maxdepth: 2