Vai al contenuto

Architettura

GesTask segue il template Yii2 Advanced: più applicazioni con entrypoint, configurazione, sessione e cookie propri, che condividono il dominio in common/.

Le applicazioni

Applicazione Entrypoint Id Scopo
Frontend frontend/web/index.php app-frontend L'interfaccia degli utenti. Vedi Frontend.
Backend backend/web/index.php app-backend Il pannello di amministrazione. Vedi Pannello di amministrazione.
API api/web/index.php app-api API REST v1 senza sessione, server MCP (POST /mcp) ed endpoint OAuth. Vedi API HTTP e Connettore MCP.
Console yii, yii.bat (yii_test per il database di test) app-console Migrazioni e attività pianificate. Vedi Console.

L'API è l'unica applicazione che php init non genera: i suoi file sono versionati, non ha un main-local.php, e YII_ENV si legge con getenv() (predefinito prod; il debug è attivo solo con dev).

Dove sta la logica

controller (frontend, api, backend, console)
        │  leggono l'input, controllano i permessi, serializzano
        ▼
servizi in common/services        ← regole di dominio, transazioni, notifiche
        │
        ▼
modelli Active Record + behavior  ← validazione, effetti automatici (storia,
                                     numerazione, avanzamento, webhook)

I controller non contengono regole. Una task bloccata non si modifica, un team non resta senza amministratore, una riunione completata è in sola lettura: lo decide il servizio, e quindi vale uguale dal Kanban, dall'API e dalla console. I servizi principali sono descritti nelle pagine del dominio; l'elenco per area è in API HTTP.

Anche le letture delle pagine stanno nei servizi quando servono a più punti d'ingresso: i numeri delle dashboard (DashboardStats, AdminStats), la visibilità delle ore (TimesheetService::forViewer()), i team che l'amministrazione vede (AdminScope). Il connettore MCP aggiunge un ultimo anello: un tool di Claude esegue l'action dell'API, che chiama il servizio.

Claude ──MCP──▶ api/controllers/McpController ──▶ action v1 ──▶ servizio

Configurazione

Ordine di caricamento

Applicazione File, dal più generale al più specifico
Frontend, backend common/config/main.php → common/config/main-local.php → <app>/config/main.php → <app>/config/main-local.php
API common/config/main.php → common/config/main-local.php → api/config/main.php
Console come frontend e backend, con console/config/
yii_test common main, main-local, test, test-local, poi console main, main-local, test, test-local

I params seguono lo stesso ordine (params.php, poi params-local.php, prima di common e poi dell'applicazione) e si fondono con array_merge.

I file *-local.php non sono versionati: li crea php init a partire da environments/dev o environments/prod.

Docker

Se la variabile DOCKER_ENV è valorizzata, i main-local.php aggiungono common/config/docker.php. Quel file:

  • configura db, redis, queue (Redis) e mailer dalle variabili d'ambiente;
  • sovrascrive dopo il caricamento i params che dipendono dall'installazione: mittente e destinatari delle email, frontendUrl, backendUrl, chiavi VAPID, server ntfy, token del bot Telegram.

L'elenco completo delle variabili è in Deploy con Docker.

Componenti comuni

common/config/main.php definisce:

  • name GesTask e timeZone Europe/Rome, ripetuto in ogni applicazione;
  • authManager: common\rbac\ProtectedDbManager, RBAC su database (vedi Sicurezza);
  • cache: FileCache (ArrayCache nei test);
  • formatter in italiano con formati d/m/Y, d/m/Y H:i, H:i. Non usare i formati estesi (long, medium, full): senza intl completo producono date in inglese;
  • urlManager con URL "belli" e senza nome dello script;
  • assetManager.appendTimestamp, per invalidare la cache del browser a ogni modifica degli asset.

Il mailer sta nel main-local.php: in sviluppo useFileTransport salva le email in runtime/mail invece di inviarle.

Parametri da conoscere

In common/config/params.php:

Parametro A cosa serve
protectedAccounts Account sempre super amministratori e sempre attivi. Vedi Sicurezza.
teamOverseers Account che vedono tutti i team, compresi gli spazi personali.
masterTokenAdmins Account che gestiscono i token API master.
user.passwordMinLength, user.passwordResetTokenExpire 8 caratteri, 3600 secondi.
pushNotifications, ntfy, telegram Configurazione dei canali di notifica.
outboundRequests Eccezioni alla protezione SSRF (allowedHosts, allowPrivateNetworks).
webhooks maxAttempts (5) e retentionDays (30) delle consegne.
trash.retentionDays Giorni dopo cui trash/purge elimina definitivamente, con purged_at (30). null: mai.
audit enabled, ignoredModels, retentionDays (365) del registro operazioni.
attachments.maxSize Dimensione massima di un allegato (20 MB).
mcp Indirizzi pubblici di frontend e API (variabili MCP_FRONTEND_URL, MCP_API_URL) e durata dei token OAuth del connettore MCP.

L'alias @api è definito in common/config/bootstrap.php, quindi anche la console raggiunge le classi dell'API (lo usa php yii mcp/tools).

Bootstrap comuni

Le classi in common/bootstrap/ si caricano in tutte e quattro le applicazioni (salvo dove indicato):

Classe Cosa fa
MailerBootstrap Fa risolvere MailerInterface sul componente mailer, così nei test si usa il mailer di Codeception.
SecurityHeadersBootstrap Solo web. Aggiunge gli header di sicurezza (vedi Sicurezza).
AccountProtectionBootstrap Solo web. Prima di ogni azione riallinea gli account protetti.
AuditLogBootstrap Registra creazioni, modifiche, eliminazioni, cestino, login e logout nel registro operazioni.
AdminAlertBootstrap Raccoglie le task spostate nel cestino durante la richiesta e invia agli amministratori una sola email alla fine.

Code di lavoro

Le operazioni lente (email, notifiche esterne, consegna dei webhook) sono job in common/jobs/: SendMailJob, SendNotificationJob, SendExternalNotificationJob, DeliverWebhookJob. Si accodano sempre con common/services/JobDispatcher::push(), che:

  • aspetta il commit della transazione in corso, e scarta il job se la transazione viene annullata;
  • usa Yii::$app->queue se esiste (in Docker: Redis, con il worker php yii queue/listen);
  • altrimenti esegue il job subito, nella stessa richiesta. È quello che succede in XAMPP: tutto funziona, ma le richieste che notificano molte persone sono più lente.

Convenzioni del dominio

  • uuid. common/behaviors/UuidBehavior assegna uno uuid v4 prima della validazione. L'id numerico resta chiave primaria ed esterna ma non esce mai: gli URL usano /<controller>/<action>/<uuid>, l'API e i webhook solo uuid.
  • Serializzazione chiusa. I modelli esposti definiscono fields() come elenco esplicito: una colonna nuova non finisce nell'API per errore, e i segreti (firma dei webhook, token dei link, destinazioni delle notifiche) non escono mai.
  • Cestino. I modelli che si possono ripristinare implementano SoftDeletable (vedi Cestino e registro operazioni). find() esclude da solo gli elementi eliminati.
  • Permessi nel servizio. Ogni operazione risolve il team della risorsa e chiede a RBAC; vedi Team e ruoli.