set('AUTOLOAD', $root . '/app/Controllers/;' . $root . '/app/Models/;' . $root . '/app/Services/'); $f3->set('UI', $root . '/app/Views/'); $f3->set('TEMP', $root . '/tmp/'); $f3->set('LOGS', $root . '/logs/'); $f3->mset([ 'paths.db' => $root . '/db/app.sqlite', 'paths.media_dir' => $root . '/public/uploads/media', 'paths.media_base' => '/uploads/media/', ]); $f3->config($root . '/app/config.ini'); $localConfig = $root . '/config.local.ini'; if (is_file($localConfig)) { $f3->config($localConfig); } $f3->set('TZ', app_timezone()); $f3->set('DEBUG', app_is_prod() ? 0 : 3); app_ensure_dir((string) $f3->get('TEMP')); app_ensure_dir((string) $f3->get('LOGS')); app_ensure_dir((string) $f3->get('paths.media_dir')); // Web::receive() utilise UPLOADS directement — le résoudre en absolu. $f3->set('UPLOADS', $root . '/' . ltrim((string) $f3->get('UPLOADS'), '/')); app_ensure_dir(rtrim((string) $f3->get('UPLOADS'), '/')); app_bootstrap_logging(); // ── Base de données ───────────────────────────────────────────────── $dbPath = (string) $f3->get('paths.db'); app_ensure_dir(dirname($dbPath)); $db = new DB\SQL( 'sqlite:' . $dbPath, null, null, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_TIMEOUT => 5, ] ); $db->exec('PRAGMA foreign_keys = ON'); $f3->set('DB', $db); // ── Session ───────────────────────────────────────────────────────── // Derrière Caddy, Apache voit souvent du HTTP interne. // On normalise donc le schéma depuis X-Forwarded-Proto uniquement si // la requête provient d'un proxy explicitement approuvé. $requestScheme = app_request_scheme(); $f3->set('SCHEME', $requestScheme); ini_set('session.use_strict_mode', '1'); ini_set('session.cookie_httponly', '1'); ini_set('session.cookie_samesite', 'Lax'); ini_set('session.cookie_secure', $requestScheme === 'https' ? '1' : '0'); session_name((string) $f3->get('app.session_name')); $f3->set('JAR', [ 'expire' => 0, 'path' => '/', 'secure' => $requestScheme === 'https', 'httponly' => true, 'samesite' => 'Lax', ]); new Session(null, 'CSRF'); // ── Template ──────────────────────────────────────────────────────── Template::instance()->filter('date_fr', 'app_format_datetime_fr'); // ── Erreurs ───────────────────────────────────────────────────────── app_bootstrap_errors($f3); return $f3;