Architecture

La séparation moderne app/public, l'arborescence complète du projet, et comment une requête circule du navigateur à la base de données et retour.

Sur cette page

Architecture

CBGenesis suit la disposition moderne de ColdBox : le code applicatif est entièrement séparé de la racine web publique, si bien que rien sous app/ n'est jamais directement accessible depuis le web.

Vue d'ensemble en couches

flowchart TD
    A["Browser Request"] --> B

    subgraph B["public/ — Webroot"]
        B1["Application.bx — entry point, bootstraps ColdBox + ORM"]
        B2["index.bxm — front controller"]
        B3["includes/ — Vite compiled assets"]
    end

    B --> C

    subgraph C["app/ — Application code (not web-accessible)"]
        C1["config/ — ColdBox, Router, CacheBox, WireBox, Scheduler"]
        C2["handlers/ — Controllers, auth, admin, audit log"]
        C3["models/ — Entities, Services"]
        C4["views/ + layouts/ — BXM templates"]
        C5["email_templates/ — Token-based email bodies"]
        C6["interceptors/ — Audit logging hook"]
    end

    C --> D

    subgraph D["resources/ — Source assets"]
        D1["assets/js/ — Alpine components + stores"]
        D2["assets/scss/ — Bootstrap + custom SCSS"]
        D3["database/ — Migrations + seeders"]
    end

    D --> E

    subgraph E["lib/ — Dependencies (not source-controlled)"]
        E1["coldbox/, testbox/, modules/ — qb, cbsecurity, cborm, ..."]
    end
Pourquoi cette séparation ?

Tout ce qu'un attaquant pourrait autrement parcourir directement - code source des handlers, configuration, templates de vues - ne vit tout simplement pas sous la racine web. app/Application.bx est une garde abort; d'une seule ligne, conservée uniquement pour que la convention du framework tienne même si un serveur web venait à être mal configuré pour servir app/ directement.

Cycle de vie d'une requête

Chaque requête entre par public/Application.bx, qui amorce ColdBox avant de passer la main au routeur et, finalement, à votre handler :

sequenceDiagram
    Browser->>+public/Application.bx: HTTP Request
    public/Application.bx->>+ColdBox Bootstrap: loadColdbox()
    ColdBox Bootstrap->>+Main Handler: onRequestStart
    Main Handler->>+Router: Match route
    Router->>+Target Handler: Dispatch event
    Target Handler->>+Service Layer: Business logic
    Service Layer->>+ORM / qb: Data access
    Target Handler->>+View / Layout: Render response
    View / Layout-->>-Browser: HTML + Vite assets

Main.bx (app/handlers/Main.bx) est le handler d'événement implicite câblé dans app/config/Coldbox.bx :

  • onAppInit - exécute settingService.preFlightCheck(), qui insère en base tout paramètre d'application manquant
  • onRequestStart - charge prc.settings et prc.authUser pour chaque requête
  • onException - le gestionnaire d'exceptions à l'échelle de l'application

Intercepteurs

app/config/Coldbox.bx enregistre trois intercepteurs applicatifs, dans cet ordre :

app/interceptors/AuditLogger.bx écrit dans le journal d'audit sur quatre points d'interception :

PointEnregistré
postAuthenticationUne connexion réussie
preLogoutUne déconnexion
cbSecurity_onInvalidAuthenticationUne requête qui nécessitait une session et n'en avait aucune
cbSecurity_onInvalidAuthorizationUn utilisateur authentifié auquel manque la permission requise

app/interceptors/RateLimiter.bx se déclenche sur preProcess - avant le routage, avant tout handler - et limite le débit de cinq actions Auth non authentifiées (connexion, inscription, mot de passe oublié/réinitialisation, activation d'invitation) par IP client. Voir Limitation de débit pour les paramètres et le fonctionnement.

app/interceptors/SSOAuthorization.bx gère le point d'interception CBSSOAuthorization de cbSSO. Il relie une identité de fournisseur vérifiée au modèle utilisateur local, impose la politique connexion-vs-liaison, provisionne les utilisateurs lorsque cela est autorisé, et crée la session cbauth. Voir Authentification unique pour le déroulement du callback et la raison pour laquelle cbGenesis utilise un handler personnalisé plutôt que l'intégration cbAuth générique de cbSSO.

Ajoutez les vôtres au tableau variables.interceptors de Coldbox.bx ; ils se déclenchent dans l'ordre de déclaration.

Tâches planifiées

app/config/Scheduler.bx enregistre trois tâches de fond quotidiennes, chacune onOneServer() et withNoOverlaps() afin qu'un déploiement multi-instance n'exécute chacune d'elles qu'une seule fois :

TâcheS'exécuteSupprimeRégie par
Purge des jetons API expirés03:00Les lignes de user_api_tokens dont l'expiration est dépasséeDurée de vie du jeton fixée à l'émission à partir de cbApiTokenMaxValidityMonths (par défaut 12 mois) - voir Paramètres de l'application
Purge des jetons « se souvenir de moi » expirés03:15Les lignes de user_remember_tokens dont l'expiration est dépasséeExpiration fixe définie à l'émission du jeton (SecurityService/RememberTokenService)
Purge des anciens journaux d'audit03:30Les lignes de audit_logs plus anciennes que la fenêtre de rétentioncbAuditLogRetentionDays (par défaut 90 ; 0 désactive la purge) - voir Paramètres de l'application

Toutes les trois appellent une méthode purgeExpiredTokens()/purgeOlderThan() sur le service propriétaire plutôt que d'interroger directement la table, si bien que la même logique de purge reste accessible (et testable) en dehors du planificateur. Ajoutez une nouvelle tâche de la même façon - voir Étendre l'application.

Arborescence complète du projet

cbgenesis/
├── app/                      Application code
│   ├── Application.bx        Abort-only gate (prevents direct /app access)
│   ├── config/
│   │   ├── Coldbox.bx        Framework settings, environments, logging
│   │   ├── Router.bx         All application routes
│   │   ├── CacheBox.bx       Cache regions (default, template, sessions, rateLimit)
│   │   ├── WireBox.bx        DI container configuration
│   │   ├── Scheduler.bx      Scheduled tasks
│   │   └── modules/          Per-module settings (cbsecurity, cbauth, cborm, ...)
│   ├── handlers/              Controllers (Auth, Dashboard, Users, Roles, ...)
│   ├── layouts/                Admin, AuthCenter, AuthSplit, Main
│   ├── models/
│   │   ├── BaseEntity.bx      ORM base: timestamps, soft delete, memento
│   │   ├── BaseService.bx     Service base: cborm + qb + cache + validation
│   │   ├── security/            Role, Permission, APIToken, RememberToken,
│   │   │                        Passkey, UserActionToken, SecurityService, ...
│   │   └── system/              User, Setting, AuditLog + their services
│   ├── views/                  BXM templates, one folder per handler
│   │   └── _components/        Reusable UI partials (app, auth, ui)
│   ├── email_templates/       Token-based email body templates
│   ├── helpers/               ApplicationHelper.bxm — global view helpers
│   └── interceptors/           AuditLogger, RateLimiter, SSOAuthorization
├── public/
│   ├── Application.bx         Entry point — ColdBox + ORM bootstrap
│   ├── index.bxm               Front controller placeholder
│   └── includes/               Vite production build output
├── resources/
│   ├── assets/js/              Alpine entry, stores, components
│   ├── assets/scss/            Bootstrap + custom SCSS
│   └── database/
│       ├── migrations/         Schema migrations (cfmigrations)
│       └── seeds/              AdminData seeder
├── tests/
│   ├── specs/integration/      Full HTTP-level specs
│   └── specs/unit/             Entity + service specs
├── lib/                        Dependencies (gitignored, installed by `box install`)
├── runtime/                    BoxLang engine config (boxlang.json)
├── server.json                 CommandBox server config (engine, webroot, aliases)
├── box.json                    Package manifest — deps, scripts
├── package.json                 NPM — Alpine, Bootstrap, Vite, ESLint
├── vite.config.mjs              Vite + coldbox-vite-plugin
└── .env.example                  Environment template

La pile technique

CoucheTechnologie
RuntimeBoxLang 1.0+ (JVM)
FrameworkColdBox HMVC (dernière version)
CLI / ServeurCommandBox + BoxLang MiniServer
Injection de dépendancesWireBox
Sécuritécbsecurity + cbauth (basé sur session + JWT)
Base de donnéesMySQL, MariaDB, PostgreSQL, et MSSQL via Hibernate ORM (cborm) ; les quatre cibles de base de données sont prises en charge et couvertes par le flux de test base de données du projet
Constructeur de requêtesqb (SQL fluide)
Migrationscfmigrations
Validationcbvalidation
Emailcbmailservices
Sérialisationmementifier
FrontendBootstrap 5.3 · Alpine.js 3.x · Vite 6
IcônesPhosphor Duotone
InfobullesTippy.js
Modifier cette page Télécharger le Markdown Dernière mise à jour Oct 1, 2026, 11:06:51 AM