CustomBlock: ERP & Headless CMS
Framework-as-a-service con Server-Driven UI
Di cosa si tratta?
CustomBlock è un backend modulare e multi-tenant (B2B) che opera con un modello 'framework-as-a-service'. Un core condiviso gestisce l'autenticazione, i log di audit e la generazione della UI, mentre i singoli moduli tenant (come l'Headless CMS di questo portfolio o un gestionale ERP) si innestano fornendo solo i propri modelli dati — azzerando tutto il codice boilerplate.
La Sfida
L'obiettivo era costruire un'architettura multi-tenant con una rigida separazione tra il framework core e il codice del cliente, permettendo aggiornamenti zero-downtime tramite immagini Docker versionate. Volevo inoltre eliminare la scrittura manuale dell'HTML ingegnerizzando una Server-Driven UI capace di generare form, datagrid e API dinamicamente leggendo i metadati del database.
Architettura della Sicurezza
JWT (HttpOnly)
Token HS256 in cookie HttpOnly, SameSite=Lax. Login dual-mode: i client browser ricevono un redirect Set-Cookie, i client API ricevono {"access_token": ...} JSON — dallo stesso endpoint.
RBAC
Factory function che restituisce dependency FastAPI-injectable. Guard preconfigurati: allow_admin, allow_authenticated. Gli item di navigazione sono filtrati lato server per ruolo — nessun dropdown vuoto per utenti con accesso limitato.
Audit Log Automatico
Event hook SQLAlchemy (after_insert, before_update, before_delete) catturano silenziosamente ogni modifica tramite ContextVar. Le entry vengono scritte nella stessa transazione DB della modifica — nessun log fantasma in caso di rollback.
Anonimizzazione GDPR
Motore a 5 step per l'Art. 17: anonimizza i campi PII, elimina la storia di audit del record target, anonimizza le azioni storiche dell'utente e scansiona tutti i log per l'email del soggetto. Attivato tramite un bottone con conferma modale nel form di modifica.
Tenant Attivi
Otto modelli interconnessi: Prodotti, Categorie, Magazzini, Fornitori, Ordini d'Acquisto, Clienti, Ordini di Vendita. Tre dropdown di navigazione. L'intera interfaccia admin è registrata in circa 10 righe di Python.
Otto modelli multilingua (IT/EN). API pubblica con language flattening lato server, filtro bozze, risoluzione URL assoluti e endpoint dedicato per il download CV cross-origin. Alimenta questo sito portfolio.
Architettura Docker
Il Dockerfile copia solo core/ — le directory dei clienti sono deliberatamente escluse. Il risultato è un'immagine versioned immutabile cb-core:<versione>. Il .env di ogni cliente fissa il proprio CORE_VERSION per rollout graduali. Due clienti in esecuzione simultanea non condividono nulla: reti separate, volumi separati, database separati.
cbenv.sh — Developer CLI
Sorgente nella shell (source cbenv.sh), espone il comando cbdev. Un controllo pre-avvio verifica che l'immagine cb-core richiesta esista in locale prima di avviare qualsiasi stack — nessun pull silenzioso o errore a metà avvio.
-
cbdev build <version>— Costruisce un'immagine cb-core versioned dal Dockerfile locale -
cbdev <customer> start— Renderizza il template Compose e avvia lo stack del tenant -
cbdev <customer> migrate— Esegue alembic upgrade head dentro il container -
cbdev <customer> bash— Apre una shell dentro il container dell'app in esecuzione -
cbdev <customer> remove— Ferma lo stack ed elimina i suoi volumi (distruttivo)