nis2-agile/application/config/config.php
DevEnv nis2-agile fe77ee8679 [SEC] EmailService: kill-switch invio email (EMAIL_SENDING_ENABLED)
Ambiente con soli dati demo: NESSUNA email deve partire. Aggiunto guard
all'inizio di sendViaRelay() e sendViaTemplate() (gli UNICI due punti che fanno
HTTP al relay -> copre tutti i canali: incidenti, training, inviti, reminder,
welcome, password reset, feedback, OTP portale fornitori).

EMAIL_SENDING_ENABLED in config: default false in sviluppo, true in produzione,
override via .env. Quando false l'invio viene loggato e scartato (return false),
nessuna chiamata di rete.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 18:46:55 +02:00

123 lines
9.5 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'));
// ─────────────────────────────────────────────────────────────────────────────
// KILL-SWITCH INVIO EMAIL (ambiente con soli dati demo)
// ─────────────────────────────────────────────────────────────────────────────
// Quando true, EmailService NON effettua NESSUNA chiamata HTTP al relay: ogni
// invio (incidenti, training, inviti, reminder, OTP portale fornitori, ecc.)
// viene registrato a log e scartato. Difesa contro invii accidentali a indirizzi
// reali finche' l'ambiente contiene solo dati demo.
// DEFAULT: in sviluppo le email sono DISABILITATE (true). In produzione abilitate
// (false) salvo override esplicito EMAIL_SENDING_ENABLED nel .env.
define('EMAIL_SENDING_ENABLED', filter_var(
Env::get('EMAIL_SENDING_ENABLED', APP_ENV === 'production' ? 'true' : 'false'),
FILTER_VALIDATE_BOOLEAN
));
// ═══════════════════════════════════════════════════════════════════════════
// 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));
// ═══════════════════════════════════════════════════════════════════════════
// PROVISIONING (B2B — lg231 e altri sistemi Agile)
// ═══════════════════════════════════════════════════════════════════════════
// Secret master per provisioning automatico da sistemi Agile partner.
// lg231 lo usa per POST /api/services/provision (onboarding automatico tenant).
define('PROVISION_SECRET', Env::get('PROVISION_SECRET', 'nis2_prov_dev_secret'));
// ═══════════════════════════════════════════════════════════════════════════
// 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],
]);
// Password reset (Fase 3 / G08): 3 richieste/h per IP+email
define('RATE_LIMIT_AUTH_FORGOT', [
['max' => 3, 'window_seconds' => 3600],
]);
// TTL token reset password (decisione utente §10.4: 30 min)
define('PASSWORD_RESET_TTL_SECONDS', 1800);
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));
// ═══════════════════════════════════════════════════════════════════════════
// CERTISOURCE (atti-service.php)
// ═══════════════════════════════════════════════════════════════════════════
define('CERTISOURCE_API_URL', Env::get('CERTISOURCE_API_URL', 'https://certisource.it/atti-service.php'));
define('CERTISOURCE_API_KEY', Env::get('CERTISOURCE_API_KEY', '')); // cs_pat_...
define('CERTISOURCE_POLL_MAX', Env::int('CERTISOURCE_POLL_MAX', 30)); // max tentativi polling
define('CERTISOURCE_POLL_SEC', Env::int('CERTISOURCE_POLL_SEC', 3)); // secondi tra poll
// ═══════════════════════════════════════════════════════════════════════════
// FEEDBACK & SEGNALAZIONI
// ═══════════════════════════════════════════════════════════════════════════
define('FEEDBACK_RESOLVE_PASSWORD', Env::get('FEEDBACK_RESOLVE_PASSWORD', ''));
define('FEEDBACK_WORKER_LOG', Env::get('FEEDBACK_WORKER_LOG', '/var/log/nis2/feedback-worker.log'));
// ═══════════════════════════════════════════════════════════════════════════
// TIMEZONE
// ═══════════════════════════════════════════════════════════════════════════
date_default_timezone_set('Europe/Rome');