[CORE] Initial project scaffold - NIS2 Agile Compliance Platform
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>
This commit is contained in:
@@ -0,0 +1,490 @@
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
-- NIS2 Agile - Schema Database Iniziale
|
||||
-- Database: nis2_agile_db
|
||||
-- Versione: 1.0.0
|
||||
-- Data: 2026-02-17
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
CREATE DATABASE IF NOT EXISTS nis2_agile_db
|
||||
CHARACTER SET utf8mb4
|
||||
COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
USE nis2_agile_db;
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
-- CORE: Organizzazioni e Utenti
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
CREATE TABLE organizations (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
vat_number VARCHAR(20),
|
||||
fiscal_code VARCHAR(16),
|
||||
sector ENUM(
|
||||
'energy','transport','banking','health','water','digital_infra',
|
||||
'public_admin','manufacturing','postal','chemical','food',
|
||||
'waste','ict_services','digital_providers','space','research','other'
|
||||
) NOT NULL DEFAULT 'other',
|
||||
entity_type ENUM('essential','important','not_applicable') DEFAULT 'not_applicable',
|
||||
employee_count INT,
|
||||
annual_turnover_eur DECIMAL(15,2),
|
||||
country VARCHAR(2) DEFAULT 'IT',
|
||||
city VARCHAR(100),
|
||||
address VARCHAR(255),
|
||||
website VARCHAR(255),
|
||||
contact_email VARCHAR(255),
|
||||
contact_phone VARCHAR(30),
|
||||
subscription_plan ENUM('free','professional','enterprise') DEFAULT 'free',
|
||||
is_active TINYINT(1) DEFAULT 1,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX idx_sector (sector),
|
||||
INDEX idx_entity_type (entity_type),
|
||||
INDEX idx_subscription (subscription_plan)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE users (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
full_name VARCHAR(255) NOT NULL,
|
||||
phone VARCHAR(30),
|
||||
role ENUM(
|
||||
'super_admin','org_admin','compliance_manager',
|
||||
'board_member','auditor','employee','consultant'
|
||||
) NOT NULL DEFAULT 'employee',
|
||||
preferred_language VARCHAR(5) DEFAULT 'it',
|
||||
is_active TINYINT(1) DEFAULT 1,
|
||||
email_verified_at DATETIME,
|
||||
last_login_at DATETIME,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX idx_email (email),
|
||||
INDEX idx_role (role),
|
||||
INDEX idx_active (is_active)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE user_organizations (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
organization_id INT NOT NULL,
|
||||
role ENUM('org_admin','compliance_manager','board_member','auditor','employee') NOT NULL DEFAULT 'employee',
|
||||
is_primary TINYINT(1) DEFAULT 0,
|
||||
joined_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
UNIQUE KEY uk_user_org (user_id, organization_id),
|
||||
INDEX idx_user (user_id),
|
||||
INDEX idx_org (organization_id)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE refresh_tokens (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
token VARCHAR(255) NOT NULL,
|
||||
expires_at DATETIME NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
INDEX idx_token (token),
|
||||
INDEX idx_expires (expires_at)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
-- GAP ANALYSIS & ASSESSMENT
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
CREATE TABLE assessments (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
organization_id INT NOT NULL,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
assessment_type ENUM('initial','periodic','post_incident') DEFAULT 'initial',
|
||||
status ENUM('draft','in_progress','completed') DEFAULT 'draft',
|
||||
overall_score DECIMAL(5,2),
|
||||
category_scores JSON,
|
||||
completed_by INT,
|
||||
completed_at DATETIME,
|
||||
ai_summary TEXT,
|
||||
ai_recommendations JSON,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (completed_by) REFERENCES users(id) ON DELETE SET NULL,
|
||||
INDEX idx_org (organization_id),
|
||||
INDEX idx_status (status)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE assessment_responses (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
assessment_id INT NOT NULL,
|
||||
question_code VARCHAR(50) NOT NULL,
|
||||
nis2_article VARCHAR(20),
|
||||
iso27001_control VARCHAR(20),
|
||||
category VARCHAR(100),
|
||||
question_text TEXT NOT NULL,
|
||||
response_value ENUM('not_implemented','partial','implemented','not_applicable'),
|
||||
maturity_level TINYINT,
|
||||
evidence_description TEXT,
|
||||
notes TEXT,
|
||||
answered_by INT,
|
||||
answered_at DATETIME,
|
||||
FOREIGN KEY (assessment_id) REFERENCES assessments(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (answered_by) REFERENCES users(id) ON DELETE SET NULL,
|
||||
INDEX idx_assessment (assessment_id),
|
||||
INDEX idx_category (category),
|
||||
UNIQUE KEY uk_assessment_question (assessment_id, question_code)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
-- RISK MANAGEMENT
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
CREATE TABLE risks (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
organization_id INT NOT NULL,
|
||||
risk_code VARCHAR(20),
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
category ENUM('cyber','operational','compliance','supply_chain','physical','human') NOT NULL,
|
||||
threat_source VARCHAR(255),
|
||||
vulnerability VARCHAR(255),
|
||||
affected_assets JSON,
|
||||
likelihood TINYINT,
|
||||
impact TINYINT,
|
||||
inherent_risk_score TINYINT,
|
||||
treatment ENUM('mitigate','accept','transfer','avoid') DEFAULT 'mitigate',
|
||||
residual_likelihood TINYINT,
|
||||
residual_impact TINYINT,
|
||||
residual_risk_score TINYINT,
|
||||
status ENUM('identified','analyzing','treating','monitored','closed') DEFAULT 'identified',
|
||||
owner_user_id INT,
|
||||
review_date DATE,
|
||||
nis2_article VARCHAR(20),
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (owner_user_id) REFERENCES users(id) ON DELETE SET NULL,
|
||||
INDEX idx_org (organization_id),
|
||||
INDEX idx_status (status),
|
||||
INDEX idx_category (category),
|
||||
UNIQUE KEY uk_org_risk_code (organization_id, risk_code)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE risk_treatments (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
risk_id INT NOT NULL,
|
||||
action_description TEXT NOT NULL,
|
||||
responsible_user_id INT,
|
||||
due_date DATE,
|
||||
status ENUM('planned','in_progress','completed','overdue') DEFAULT 'planned',
|
||||
completion_date DATE,
|
||||
notes TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (risk_id) REFERENCES risks(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (responsible_user_id) REFERENCES users(id) ON DELETE SET NULL,
|
||||
INDEX idx_risk (risk_id),
|
||||
INDEX idx_status (status)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
-- INCIDENT MANAGEMENT (Art. 23)
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
CREATE TABLE incidents (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
organization_id INT NOT NULL,
|
||||
incident_code VARCHAR(20),
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
classification ENUM(
|
||||
'cyber_attack','data_breach','system_failure',
|
||||
'human_error','natural_disaster','supply_chain','other'
|
||||
) NOT NULL,
|
||||
severity ENUM('low','medium','high','critical') NOT NULL,
|
||||
is_significant TINYINT(1) DEFAULT 0,
|
||||
status ENUM(
|
||||
'detected','analyzing','containing','eradicating',
|
||||
'recovering','closed','post_mortem'
|
||||
) DEFAULT 'detected',
|
||||
detected_at DATETIME NOT NULL,
|
||||
-- NIS2 Art.23 milestones
|
||||
early_warning_due DATETIME,
|
||||
early_warning_sent_at DATETIME,
|
||||
notification_due DATETIME,
|
||||
notification_sent_at DATETIME,
|
||||
final_report_due DATETIME,
|
||||
final_report_sent_at DATETIME,
|
||||
-- Impact
|
||||
affected_services TEXT,
|
||||
affected_users_count INT,
|
||||
cross_border_impact TINYINT(1) DEFAULT 0,
|
||||
malicious_action TINYINT(1) DEFAULT 0,
|
||||
-- Resolution
|
||||
root_cause TEXT,
|
||||
remediation_actions TEXT,
|
||||
lessons_learned TEXT,
|
||||
reported_by INT,
|
||||
assigned_to INT,
|
||||
closed_at DATETIME,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (reported_by) REFERENCES users(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (assigned_to) REFERENCES users(id) ON DELETE SET NULL,
|
||||
INDEX idx_org (organization_id),
|
||||
INDEX idx_status (status),
|
||||
INDEX idx_severity (severity),
|
||||
UNIQUE KEY uk_org_incident_code (organization_id, incident_code)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE incident_timeline (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
incident_id INT NOT NULL,
|
||||
event_type ENUM('detection','escalation','notification','action','update','resolution') NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
created_by INT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (incident_id) REFERENCES incidents(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL,
|
||||
INDEX idx_incident (incident_id)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
-- POLICY & PROCEDURE MANAGEMENT
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
CREATE TABLE policies (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
organization_id INT NOT NULL,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
category ENUM(
|
||||
'information_security','access_control','incident_response',
|
||||
'business_continuity','supply_chain','encryption','hr_security',
|
||||
'asset_management','network_security','vulnerability_management'
|
||||
) NOT NULL,
|
||||
nis2_article VARCHAR(20),
|
||||
version VARCHAR(10) DEFAULT '1.0',
|
||||
status ENUM('draft','review','approved','published','archived') DEFAULT 'draft',
|
||||
content LONGTEXT,
|
||||
approved_by INT,
|
||||
approved_at DATETIME,
|
||||
next_review_date DATE,
|
||||
ai_generated TINYINT(1) DEFAULT 0,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (approved_by) REFERENCES users(id) ON DELETE SET NULL,
|
||||
INDEX idx_org (organization_id),
|
||||
INDEX idx_status (status),
|
||||
INDEX idx_category (category)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
-- SUPPLY CHAIN SECURITY (Art. 21.2.d)
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
CREATE TABLE suppliers (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
organization_id INT NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
vat_number VARCHAR(20),
|
||||
contact_email VARCHAR(255),
|
||||
contact_name VARCHAR(255),
|
||||
service_type VARCHAR(255),
|
||||
service_description TEXT,
|
||||
criticality ENUM('low','medium','high','critical') DEFAULT 'medium',
|
||||
risk_score TINYINT,
|
||||
last_assessment_date DATE,
|
||||
next_assessment_date DATE,
|
||||
contract_start_date DATE,
|
||||
contract_expiry_date DATE,
|
||||
security_requirements_met TINYINT(1) DEFAULT 0,
|
||||
assessment_responses JSON,
|
||||
notes TEXT,
|
||||
status ENUM('active','under_review','suspended','terminated') DEFAULT 'active',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
INDEX idx_org (organization_id),
|
||||
INDEX idx_criticality (criticality),
|
||||
INDEX idx_status (status)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
-- TRAINING & AWARENESS (Art. 20)
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
CREATE TABLE training_courses (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
organization_id INT,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
target_role ENUM('all','board_member','compliance_manager','employee','technical') DEFAULT 'all',
|
||||
nis2_article VARCHAR(20),
|
||||
is_mandatory TINYINT(1) DEFAULT 0,
|
||||
duration_minutes INT,
|
||||
content JSON,
|
||||
quiz JSON,
|
||||
passing_score TINYINT DEFAULT 70,
|
||||
is_active TINYINT(1) DEFAULT 1,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
INDEX idx_org (organization_id),
|
||||
INDEX idx_role (target_role)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE training_assignments (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
course_id INT NOT NULL,
|
||||
user_id INT NOT NULL,
|
||||
organization_id INT NOT NULL,
|
||||
status ENUM('assigned','in_progress','completed','overdue') DEFAULT 'assigned',
|
||||
due_date DATE,
|
||||
started_at DATETIME,
|
||||
completed_at DATETIME,
|
||||
quiz_score TINYINT,
|
||||
certificate_url VARCHAR(255),
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (course_id) REFERENCES training_courses(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
INDEX idx_user (user_id),
|
||||
INDEX idx_org (organization_id),
|
||||
INDEX idx_status (status),
|
||||
UNIQUE KEY uk_course_user (course_id, user_id)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
-- ASSET MANAGEMENT (Art. 21.2.i)
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
CREATE TABLE assets (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
organization_id INT NOT NULL,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
asset_type ENUM('hardware','software','network','data','service','personnel','facility') NOT NULL,
|
||||
category VARCHAR(100),
|
||||
description TEXT,
|
||||
criticality ENUM('low','medium','high','critical') DEFAULT 'medium',
|
||||
owner_user_id INT,
|
||||
location VARCHAR(255),
|
||||
ip_address VARCHAR(45),
|
||||
vendor VARCHAR(255),
|
||||
version VARCHAR(50),
|
||||
serial_number VARCHAR(100),
|
||||
purchase_date DATE,
|
||||
warranty_expiry DATE,
|
||||
status ENUM('active','maintenance','decommissioned') DEFAULT 'active',
|
||||
dependencies JSON,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (owner_user_id) REFERENCES users(id) ON DELETE SET NULL,
|
||||
INDEX idx_org (organization_id),
|
||||
INDEX idx_type (asset_type),
|
||||
INDEX idx_criticality (criticality),
|
||||
INDEX idx_status (status)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
-- AUDIT & COMPLIANCE TRACKING
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
CREATE TABLE compliance_controls (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
organization_id INT NOT NULL,
|
||||
control_code VARCHAR(50) NOT NULL,
|
||||
framework ENUM('nis2','iso27001','both') DEFAULT 'nis2',
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
status ENUM('not_started','in_progress','implemented','verified') DEFAULT 'not_started',
|
||||
implementation_percentage TINYINT DEFAULT 0,
|
||||
evidence_description TEXT,
|
||||
responsible_user_id INT,
|
||||
last_verified_at DATETIME,
|
||||
next_review_date DATE,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (responsible_user_id) REFERENCES users(id) ON DELETE SET NULL,
|
||||
INDEX idx_org (organization_id),
|
||||
INDEX idx_framework (framework),
|
||||
INDEX idx_status (status),
|
||||
UNIQUE KEY uk_org_control (organization_id, control_code)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE evidence_files (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
organization_id INT NOT NULL,
|
||||
control_id INT,
|
||||
entity_type VARCHAR(50),
|
||||
entity_id INT,
|
||||
file_name VARCHAR(255) NOT NULL,
|
||||
file_path VARCHAR(500) NOT NULL,
|
||||
file_size INT,
|
||||
mime_type VARCHAR(100),
|
||||
uploaded_by INT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (control_id) REFERENCES compliance_controls(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (uploaded_by) REFERENCES users(id) ON DELETE SET NULL,
|
||||
INDEX idx_org (organization_id),
|
||||
INDEX idx_entity (entity_type, entity_id)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
CREATE TABLE audit_logs (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT,
|
||||
organization_id INT,
|
||||
action VARCHAR(255) NOT NULL,
|
||||
entity_type VARCHAR(100),
|
||||
entity_id INT,
|
||||
details JSON,
|
||||
ip_address VARCHAR(45),
|
||||
user_agent VARCHAR(500),
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_user (user_id),
|
||||
INDEX idx_org (organization_id),
|
||||
INDEX idx_action (action),
|
||||
INDEX idx_entity (entity_type, entity_id),
|
||||
INDEX idx_created (created_at)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
-- AI INTERACTIONS LOG
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
CREATE TABLE ai_interactions (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
organization_id INT NOT NULL,
|
||||
user_id INT NOT NULL,
|
||||
interaction_type ENUM(
|
||||
'gap_analysis','risk_suggestion','policy_draft',
|
||||
'incident_classification','qa','report_generation'
|
||||
) NOT NULL,
|
||||
prompt_summary VARCHAR(500),
|
||||
response_summary TEXT,
|
||||
tokens_used INT,
|
||||
model_used VARCHAR(50),
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
INDEX idx_org (organization_id),
|
||||
INDEX idx_type (interaction_type)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
-- RATE LIMITING
|
||||
-- ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
CREATE TABLE rate_limits (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
rate_key VARCHAR(255) NOT NULL,
|
||||
ip_address VARCHAR(45) NOT NULL,
|
||||
attempts INT DEFAULT 1,
|
||||
window_start DATETIME NOT NULL,
|
||||
INDEX idx_key_ip (rate_key, ip_address),
|
||||
INDEX idx_window (window_start)
|
||||
) ENGINE=InnoDB;
|
||||
Reference in New Issue
Block a user