Complete MVP implementation including: - PHP 8.4 backend with Front Controller pattern (80+ API endpoints) - Multi-tenant architecture with organization_id isolation - JWT authentication (HS256, 2h access + 7d refresh tokens) - 14 controllers: Auth, Organization, Assessment, Dashboard, Risk, Incident, Policy, SupplyChain, Training, Asset, Audit, Admin - AI Service integration (Anthropic Claude API) for gap analysis, risk suggestions, policy generation, incident classification - NIS2 gap analysis questionnaire (~80 questions, 10 categories) - MySQL schema (20 tables) with NIS2 Art. 21 compliance controls - NIS2 Art. 23 incident reporting workflow (24h/72h/30d) - Frontend: login, register, dashboard, assessment wizard, org setup - Docker configuration (PHP-FPM + Nginx + MySQL) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
82 lines
5.9 KiB
PHP
82 lines
5.9 KiB
PHP
<?php
|
|
/**
|
|
* NIS2 Agile - Configurazione Principale
|
|
*/
|
|
|
|
require_once __DIR__ . '/env.php';
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// APPLICAZIONE
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
define('APP_ENV', Env::get('APP_ENV', 'development'));
|
|
define('APP_DEBUG', APP_ENV === 'development');
|
|
define('APP_NAME', Env::get('APP_NAME', 'NIS2 Agile'));
|
|
define('APP_VERSION', Env::get('APP_VERSION', '1.0.0'));
|
|
define('APP_URL', Env::get('APP_URL', 'http://localhost:8080'));
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// PERCORSI
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
define('BASE_PATH', dirname(dirname(__DIR__)));
|
|
define('APP_PATH', BASE_PATH . '/application');
|
|
define('PUBLIC_PATH', BASE_PATH . '/public');
|
|
define('UPLOAD_PATH', PUBLIC_PATH . '/uploads');
|
|
define('DATA_PATH', APP_PATH . '/data');
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// AUTENTICAZIONE JWT
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
define('JWT_SECRET', APP_ENV === 'production'
|
|
? Env::getRequired('JWT_SECRET')
|
|
: Env::get('JWT_SECRET', 'nis2_dev_jwt_secret'));
|
|
define('JWT_ALGORITHM', 'HS256');
|
|
define('JWT_EXPIRES_IN', Env::int('JWT_EXPIRES_IN', 7200));
|
|
define('JWT_REFRESH_EXPIRES_IN', Env::int('JWT_REFRESH_EXPIRES_IN', 604800));
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// PASSWORD POLICY
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
define('PASSWORD_MIN_LENGTH', Env::int('PASSWORD_MIN_LENGTH', 8));
|
|
define('PASSWORD_REQUIRE_UPPERCASE', Env::bool('PASSWORD_REQUIRE_UPPERCASE', true));
|
|
define('PASSWORD_REQUIRE_NUMBER', Env::bool('PASSWORD_REQUIRE_NUMBER', true));
|
|
define('PASSWORD_REQUIRE_SPECIAL', Env::bool('PASSWORD_REQUIRE_SPECIAL', true));
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// CORS
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
define('CORS_ALLOWED_ORIGINS', array_filter([
|
|
APP_URL,
|
|
APP_ENV !== 'production' ? 'http://localhost:8080' : null,
|
|
APP_ENV !== 'production' ? 'http://localhost:3000' : null,
|
|
]));
|
|
define('CORS_ALLOWED_METHODS', 'GET, POST, PUT, DELETE, OPTIONS');
|
|
define('CORS_ALLOWED_HEADERS', 'Content-Type, Authorization, X-Organization-Id, X-Requested-With');
|
|
define('CORS_MAX_AGE', '86400');
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// RATE LIMITING
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
define('RATE_LIMIT_AUTH_LOGIN', [
|
|
['max' => 5, 'window_seconds' => 60],
|
|
['max' => 20, 'window_seconds' => 3600],
|
|
]);
|
|
define('RATE_LIMIT_AUTH_REGISTER', [
|
|
['max' => 3, 'window_seconds' => 600],
|
|
]);
|
|
define('RATE_LIMIT_AI', [
|
|
['max' => 10, 'window_seconds' => 60],
|
|
['max' => 100, 'window_seconds' => 3600],
|
|
]);
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// AI (ANTHROPIC)
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
define('ANTHROPIC_API_KEY', Env::get('ANTHROPIC_API_KEY', ''));
|
|
define('ANTHROPIC_MODEL', Env::get('ANTHROPIC_MODEL', 'claude-sonnet-4-5-20250929'));
|
|
define('ANTHROPIC_MAX_TOKENS', Env::int('ANTHROPIC_MAX_TOKENS', 4096));
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// TIMEZONE
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
date_default_timezone_set('Europe/Rome');
|