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

demo
Inventory & ERP

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.

portfolio
Headless Portfolio CMS

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.

Live Development Mode — Un override docker-compose monta ./core come bind-mount e abilita Uvicorn --reload, permettendo il ricaricamento istantaneo del codice del framework all'interno dell'ambiente Docker correttamente isolato.

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)