CREATE TABLE IF NOT EXISTS schema_migrations ( version BIGINT UNSIGNED NOT NULL PRIMARY KEY, applied_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS technician_sessions ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, token_hash BINARY(32) NOT NULL UNIQUE, csrf_token VARCHAR(64) NOT NULL, gitea_login VARCHAR(255) NOT NULL, display_name VARCHAR(255) NOT NULL, created_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), expires_at TIMESTAMP(6) NOT NULL, last_seen_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), INDEX idx_technician_sessions_expires (expires_at) ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS packages ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, slug VARCHAR(100) NOT NULL UNIQUE, display_name VARCHAR(255) NOT NULL, package_name VARCHAR(255) NOT NULL, package_version VARCHAR(100) NOT NULL, file_name VARCHAR(255) NOT NULL, sha256 CHAR(64) NOT NULL, enabled BOOLEAN NOT NULL DEFAULT FALSE, created_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), updated_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS authorizations ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, code_hash BINARY(32) NOT NULL UNIQUE, code_hint VARCHAR(8) NOT NULL, created_by VARCHAR(255) NOT NULL, customer_label VARCHAR(255) NOT NULL DEFAULT '', host_limit INT UNSIGNED NOT NULL, created_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), expires_at TIMESTAMP(6) NOT NULL, revoked_at TIMESTAMP(6) NULL, INDEX idx_authorizations_expires (expires_at), INDEX idx_authorizations_created_by (created_by, created_at) ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS authorization_packages ( authorization_id BIGINT UNSIGNED NOT NULL, package_id BIGINT UNSIGNED NOT NULL, PRIMARY KEY (authorization_id, package_id), CONSTRAINT fk_authorization_packages_authorization FOREIGN KEY (authorization_id) REFERENCES authorizations(id) ON DELETE CASCADE, CONSTRAINT fk_authorization_packages_package FOREIGN KEY (package_id) REFERENCES packages(id) ON DELETE RESTRICT ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS authorization_hosts ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, authorization_id BIGINT UNSIGNED NOT NULL, host_fingerprint BINARY(32) NOT NULL, hostname VARCHAR(255) NOT NULL, first_seen_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), last_seen_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), UNIQUE KEY uq_authorization_host (authorization_id, host_fingerprint), CONSTRAINT fk_authorization_hosts_authorization FOREIGN KEY (authorization_id) REFERENCES authorizations(id) ON DELETE CASCADE ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS download_sessions ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, token_hash BINARY(32) NOT NULL UNIQUE, authorization_id BIGINT UNSIGNED NOT NULL, authorization_host_id BIGINT UNSIGNED NOT NULL, created_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), expires_at TIMESTAMP(6) NOT NULL, revoked_at TIMESTAMP(6) NULL, INDEX idx_download_sessions_expires (expires_at), CONSTRAINT fk_download_sessions_authorization FOREIGN KEY (authorization_id) REFERENCES authorizations(id) ON DELETE CASCADE, CONSTRAINT fk_download_sessions_host FOREIGN KEY (authorization_host_id) REFERENCES authorization_hosts(id) ON DELETE CASCADE ) ENGINE=InnoDB; CREATE TABLE IF NOT EXISTS audit_events ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, event_type VARCHAR(100) NOT NULL, actor VARCHAR(255) NOT NULL DEFAULT '', authorization_id BIGINT UNSIGNED NULL, hostname VARCHAR(255) NOT NULL DEFAULT '', package_slug VARCHAR(100) NOT NULL DEFAULT '', source_ip VARCHAR(64) NOT NULL DEFAULT '', details TEXT NOT NULL, created_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), INDEX idx_audit_created (created_at), INDEX idx_audit_authorization (authorization_id, created_at), INDEX idx_audit_exchange_limit (event_type, source_ip, created_at) ) ENGINE=InnoDB; INSERT IGNORE INTO schema_migrations (version) VALUES (1);