Compare commits

...

5 Commits

Author SHA1 Message Date
Marco Lanzara
21ff8c0c4b 🚀 Release v1.0.97
- Tipo: patch
- Database schema: database-schema/schema.sql (solo struttura)
- Data: 2026-01-02 14:50:15
2026-01-02 14:50:15 +00:00
marco370
d966d26784 Saved progress at the end of the loop
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 3b2f0862-1651-467b-b1ad-4392772a05a5
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/rDib6Pq
2026-01-02 14:46:04 +00:00
marco370
73ad653cb0 Update database management to version 8 for improved network matching
Update database management to version 8, forcing INET/CIDR column types for network range matching and recreating INET columns to resolve type mismatches.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 98e331cf-16db-40fc-a572-755928117e82
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/rDib6Pq
2026-01-02 14:45:44 +00:00
marco370
3574ff0274 Update database schema and migrations to correctly handle IP address data types
Introduce migration 008 to force INET and CIDR types for IP-related columns in `whitelist` and `public_blacklist_ips` tables, and update `shared/schema.ts` with comments clarifying production type handling.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 1d0f629d-65cf-420d-86d9-a51b24caffa4
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/rDib6Pq
2026-01-02 14:44:54 +00:00
marco370
0301a42825 Update IP address parsing to ensure uniqueness and fix duplicates
Update `normalize_cidr` function in `parsers.py` to use the full CIDR notation as the IP address for uniqueness, addressing duplicate entry errors during Spamhaus IP sync and resolving the `operator does not exist: inet = text` error related to the `whitelist` table by ensuring proper IP type handling.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 7a657272-55ba-4a79-9a2e-f1ed9bc7a528
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 478f21ca-de02-4a5b-9eec-f73a3e16d0f0
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/449cf7c4-c97a-45ae-8234-e5c5b8d6a84f/7a657272-55ba-4a79-9a2e-f1ed9bc7a528/rDib6Pq
2026-01-02 11:56:47 +00:00
8 changed files with 216 additions and 16 deletions

View File

@ -0,0 +1,51 @@
journalctl -u ids-list-fetcher -n 50 --no-pager
Jan 02 15:30:01 ids.alfacom.it ids-list-fetcher[9296]: Skipped (whitelisted): 0
Jan 02 15:30:01 ids.alfacom.it ids-list-fetcher[9296]: ============================================================
Jan 02 15:30:01 ids.alfacom.it systemd[1]: ids-list-fetcher.service: Deactivated successfully.
Jan 02 15:30:01 ids.alfacom.it systemd[1]: Finished IDS Public Lists Fetcher Service.
Jan 02 15:40:00 ids.alfacom.it systemd[1]: Starting IDS Public Lists Fetcher Service...
Jan 02 15:40:00 ids.alfacom.it ids-list-fetcher[9493]: ============================================================
Jan 02 15:40:00 ids.alfacom.it ids-list-fetcher[9493]: [2026-01-02 15:40:00] PUBLIC LISTS SYNC
Jan 02 15:40:00 ids.alfacom.it ids-list-fetcher[9493]: ============================================================
Jan 02 15:40:00 ids.alfacom.it ids-list-fetcher[9493]: Found 2 enabled lists
Jan 02 15:40:00 ids.alfacom.it ids-list-fetcher[9493]: [15:40:00] Downloading Spamhaus from https://www.spamhaus.org/drop/drop_v4.json...
Jan 02 15:40:00 ids.alfacom.it ids-list-fetcher[9493]: [15:40:00] Downloading AWS from https://ip-ranges.amazonaws.com/ip-ranges.json...
Jan 02 15:40:00 ids.alfacom.it ids-list-fetcher[9493]: [15:40:00] Parsing AWS...
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: [15:40:01] Found 9548 IPs, syncing to database...
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: [15:40:01] ✓ AWS: +0 -0 ~9511
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: [15:40:01] Parsing Spamhaus...
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: [15:40:01] Found 1468 IPs, syncing to database...
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: [15:40:01] ✓ Spamhaus: +0 -0 ~1464
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: ============================================================
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: SYNC SUMMARY
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: ============================================================
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: Success: 2/2
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: Errors: 0/2
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: Total IPs Added: 0
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: Total IPs Removed: 0
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: ============================================================
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: ============================================================
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: RUNNING MERGE LOGIC
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: ============================================================
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: ERROR:merge_logic:Failed to cleanup detections: operator does not exist: inet = text
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: LINE 9: d.source_ip::inet = wl.ip_inet
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: ^
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: ERROR:merge_logic:Failed to sync detections: operator does not exist: inet = text
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: LINE 29: bl.ip_inet = wl.ip_inet
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: ^
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: Traceback (most recent call last):
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: File "/opt/ids/python_ml/merge_logic.py", line 264, in sync_public_blacklist_detections
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: cur.execute("""
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: psycopg2.errors.UndefinedFunction: operator does not exist: inet = text
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: LINE 29: bl.ip_inet = wl.ip_inet
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: ^
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: Merge Logic Stats:
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: Created detections: 0
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: Cleaned invalid detections: 0
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: Skipped (whitelisted): 0
Jan 02 15:40:01 ids.alfacom.it ids-list-fetcher[9493]: ============================================================
Jan 02 15:40:01 ids.alfacom.it systemd[1]: ids-list-fetcher.service: Deactivated successfully.
Jan 02 15:40:01 ids.alfacom.it systemd[1]: Finished IDS Public Lists Fetcher Service.

View File

@ -0,0 +1,51 @@
journalctl -u ids-list-fetcher -n 50 --no-pager
Jan 02 12:50:02 ids.alfacom.it ids-list-fetcher[5900]: ============================================================
Jan 02 12:50:02 ids.alfacom.it systemd[1]: ids-list-fetcher.service: Deactivated successfully.
Jan 02 12:50:02 ids.alfacom.it systemd[1]: Finished IDS Public Lists Fetcher Service.
Jan 02 12:54:56 ids.alfacom.it systemd[1]: Starting IDS Public Lists Fetcher Service...
Jan 02 12:54:56 ids.alfacom.it ids-list-fetcher[6290]: ============================================================
Jan 02 12:54:56 ids.alfacom.it ids-list-fetcher[6290]: [2026-01-02 12:54:56] PUBLIC LISTS SYNC
Jan 02 12:54:56 ids.alfacom.it ids-list-fetcher[6290]: ============================================================
Jan 02 12:54:56 ids.alfacom.it ids-list-fetcher[6290]: Found 2 enabled lists
Jan 02 12:54:56 ids.alfacom.it ids-list-fetcher[6290]: [12:54:56] Downloading Spamhaus from https://www.spamhaus.org/drop/drop_v4.json...
Jan 02 12:54:56 ids.alfacom.it ids-list-fetcher[6290]: [12:54:56] Downloading AWS from https://ip-ranges.amazonaws.com/ip-ranges.json...
Jan 02 12:54:56 ids.alfacom.it ids-list-fetcher[6290]: [12:54:56] Parsing AWS...
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: [12:54:57] Found 9548 IPs, syncing to database...
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: [12:54:57] ✓ AWS: +0 -0 ~9511
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: [12:54:57] Parsing Spamhaus...
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: [12:54:57] Found 1468 IPs, syncing to database...
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: [12:54:57] ✗ Spamhaus: ON CONFLICT DO UPDATE command cannot affect row a second time
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: HINT: Ensure that no rows proposed for insertion within the same command have duplicate constrained values.
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: ============================================================
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: SYNC SUMMARY
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: ============================================================
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: Success: 1/2
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: Errors: 1/2
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: Total IPs Added: 0
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: Total IPs Removed: 0
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: ============================================================
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: ============================================================
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: RUNNING MERGE LOGIC
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: ============================================================
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: ERROR:merge_logic:Failed to cleanup detections: operator does not exist: inet = text
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: LINE 9: d.source_ip::inet = wl.ip_inet
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: ^
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: ERROR:merge_logic:Failed to sync detections: operator does not exist: text <<= text
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: LINE 30: OR bl.ip_inet <<= wl.ip_inet
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: ^
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: Traceback (most recent call last):
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: File "/opt/ids/python_ml/merge_logic.py", line 264, in sync_public_blacklist_detections
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: cur.execute("""
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: psycopg2.errors.UndefinedFunction: operator does not exist: text <<= text
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: LINE 30: OR bl.ip_inet <<= wl.ip_inet
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: ^
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: Merge Logic Stats:
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: Created detections: 0
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: Cleaned invalid detections: 0
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: Skipped (whitelisted): 0
Jan 02 12:54:57 ids.alfacom.it ids-list-fetcher[6290]: ============================================================
Jan 02 12:54:57 ids.alfacom.it systemd[1]: ids-list-fetcher.service: Deactivated successfully.
Jan 02 12:54:57 ids.alfacom.it systemd[1]: Finished IDS Public Lists Fetcher Service.

View File

@ -2,7 +2,7 @@
-- PostgreSQL database dump -- PostgreSQL database dump
-- --
\restrict 1YQEYYblTjhEF1oaDcpZ6W1vr63857XpsHsgqbm4Hu9qkogTgJA6Ph6OgNkIj16 \restrict bpBxNz70Ka0m0tyhrhacCuMK1bx7vbLdZerc7LHt1LG4ZFdy4h6aJ0zgCj4XJhK
-- Dumped from database version 16.11 (74c6bb6) -- Dumped from database version 16.11 (74c6bb6)
-- Dumped by pg_dump version 16.10 -- Dumped by pg_dump version 16.10
@ -387,5 +387,5 @@ ALTER TABLE ONLY public.public_blacklist_ips
-- PostgreSQL database dump complete -- PostgreSQL database dump complete
-- --
\unrestrict 1YQEYYblTjhEF1oaDcpZ6W1vr63857XpsHsgqbm4Hu9qkogTgJA6Ph6OgNkIj16 \unrestrict bpBxNz70Ka0m0tyhrhacCuMK1bx7vbLdZerc7LHt1LG4ZFdy4h6aJ0zgCj4XJhK

View File

@ -0,0 +1,92 @@
-- Migration 008: Force INET/CIDR types (unconditional)
-- Fixes issues where columns remained TEXT after conditional migration 007
-- Date: 2026-01-02
BEGIN;
-- ============================================================================
-- FORCE DROP AND RECREATE ALL INET COLUMNS
-- This is unconditional - always executes regardless of current state
-- ============================================================================
-- Drop indexes first (if exist)
DROP INDEX IF EXISTS public_blacklist_ip_inet_idx;
DROP INDEX IF EXISTS public_blacklist_cidr_inet_idx;
DROP INDEX IF EXISTS whitelist_ip_inet_idx;
-- ============================================================================
-- FIX public_blacklist_ips TABLE
-- ============================================================================
-- Drop columns unconditionally
ALTER TABLE public_blacklist_ips DROP COLUMN IF EXISTS ip_inet;
ALTER TABLE public_blacklist_ips DROP COLUMN IF EXISTS cidr_inet;
-- Recreate with correct INET/CIDR types
ALTER TABLE public_blacklist_ips ADD COLUMN ip_inet inet;
ALTER TABLE public_blacklist_ips ADD COLUMN cidr_inet cidr;
-- Populate from existing text data
UPDATE public_blacklist_ips
SET
ip_inet = CASE
WHEN ip_address ~ '/' THEN ip_address::inet
ELSE ip_address::inet
END,
cidr_inet = CASE
WHEN cidr_range IS NOT NULL AND cidr_range != '' THEN cidr_range::cidr
WHEN ip_address ~ '/' THEN ip_address::cidr
ELSE (ip_address || '/32')::cidr
END
WHERE ip_inet IS NULL;
-- Create GiST indexes for fast INET/CIDR containment operators
CREATE INDEX public_blacklist_ip_inet_idx ON public_blacklist_ips USING gist(ip_inet inet_ops);
CREATE INDEX public_blacklist_cidr_inet_idx ON public_blacklist_ips USING gist(cidr_inet inet_ops);
-- ============================================================================
-- FIX whitelist TABLE
-- ============================================================================
-- Drop column unconditionally
ALTER TABLE whitelist DROP COLUMN IF EXISTS ip_inet;
-- Recreate with correct INET type
ALTER TABLE whitelist ADD COLUMN ip_inet inet;
-- Populate from existing text data
UPDATE whitelist
SET ip_inet = CASE
WHEN ip_address ~ '/' THEN ip_address::inet
ELSE ip_address::inet
END
WHERE ip_inet IS NULL;
-- Create index for whitelist
CREATE INDEX whitelist_ip_inet_idx ON whitelist USING gist(ip_inet inet_ops);
-- ============================================================================
-- UPDATE SCHEMA VERSION
-- ============================================================================
UPDATE schema_version SET version = 8, applied_at = NOW() WHERE id = 1;
COMMIT;
-- ============================================================================
-- VERIFICATION
-- ============================================================================
SELECT 'Migration 008 completed successfully' as status;
SELECT version, applied_at FROM schema_version WHERE id = 1;
-- Verify column types
SELECT
table_name,
column_name,
data_type
FROM information_schema.columns
WHERE
(table_name = 'public_blacklist_ips' AND column_name IN ('ip_inet', 'cidr_inet'))
OR (table_name = 'whitelist' AND column_name = 'ip_inet')
ORDER BY table_name, column_name;

View File

@ -21,13 +21,15 @@ class ListParser:
def normalize_cidr(ip_str: str) -> tuple[str, Optional[str]]: def normalize_cidr(ip_str: str) -> tuple[str, Optional[str]]:
""" """
Normalize IP/CIDR to (ip_address, cidr_range) Normalize IP/CIDR to (ip_address, cidr_range)
Example: '1.2.3.0/24' -> ('1.2.3.0', '1.2.3.0/24') For CIDR ranges, use the full CIDR notation as ip_address to ensure uniqueness
Example: '1.2.3.0/24' -> ('1.2.3.0/24', '1.2.3.0/24')
'1.2.3.4' -> ('1.2.3.4', None) '1.2.3.4' -> ('1.2.3.4', None)
""" """
try: try:
network = ipaddress.ip_network(ip_str, strict=False) network = ipaddress.ip_network(ip_str, strict=False)
if '/' in ip_str: if '/' in ip_str:
return (str(network.network_address), str(network)) normalized_cidr = str(network)
return (normalized_cidr, normalized_cidr)
else: else:
return (ip_str, None) return (ip_str, None)
except ValueError: except ValueError:

View File

@ -30,7 +30,7 @@ The IDS employs a React-based frontend for real-time monitoring, detection visua
- **Automatic Cleanup**: An hourly systemd timer (`cleanup_detections.py`) removes old detections (48h) and auto-unblocks IPs (2h). - **Automatic Cleanup**: An hourly systemd timer (`cleanup_detections.py`) removes old detections (48h) and auto-unblocks IPs (2h).
- **Service Monitoring & Management**: A dashboard provides real-time status (ML Backend, Database, Syslog Parser). API endpoints, secured with API key authentication and Systemd integration, allow for service management (start/stop/restart) of Python services. - **Service Monitoring & Management**: A dashboard provides real-time status (ML Backend, Database, Syslog Parser). API endpoints, secured with API key authentication and Systemd integration, allow for service management (start/stop/restart) of Python services.
- **IP Geolocation**: Integration with `ip-api.com` enriches detection data with geographical and AS information, utilizing intelligent caching. - **IP Geolocation**: Integration with `ip-api.com` enriches detection data with geographical and AS information, utilizing intelligent caching.
- **Database Management**: PostgreSQL is used for all persistent data. An intelligent database versioning system ensures efficient SQL migrations (v7 with INET/CIDR columns for network range matching). Dual-mode database drivers (`@neondatabase/serverless` for Replit, `pg` for AlmaLinux) ensure environment compatibility. - **Database Management**: PostgreSQL is used for all persistent data. An intelligent database versioning system ensures efficient SQL migrations (v8 with forced INET/CIDR column types for network range matching). Migration 008 unconditionally recreates INET columns to fix type mismatches. Dual-mode database drivers (`@neondatabase/serverless` for Replit, `pg` for AlmaLinux) ensure environment compatibility.
- **Microservices**: Clear separation of concerns between the Python ML backend and the Node.js API backend. - **Microservices**: Clear separation of concerns between the Python ML backend and the Node.js API backend.
- **UI/UX**: Utilizes ShadCN UI for a modern component library and `react-hook-form` with Zod for robust form validation. Analytics dashboards provide visualizations of normal and attack traffic, including real-time and historical data. - **UI/UX**: Utilizes ShadCN UI for a modern component library and `react-hook-form` with Zod for robust form validation. Analytics dashboards provide visualizations of normal and attack traffic, including real-time and historical data.

View File

@ -70,10 +70,12 @@ export const detections = pgTable("detections", {
})); }));
// Whitelist per IP fidati // Whitelist per IP fidati
// NOTE: ip_inet is INET type in production (managed by SQL migrations)
// Drizzle lacks native INET support, so we use text() here
export const whitelist = pgTable("whitelist", { export const whitelist = pgTable("whitelist", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`), id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
ipAddress: text("ip_address").notNull().unique(), ipAddress: text("ip_address").notNull().unique(),
ipInet: text("ip_inet"), ipInet: text("ip_inet"), // Actually INET in production - see migration 008
comment: text("comment"), comment: text("comment"),
reason: text("reason"), reason: text("reason"),
createdBy: text("created_by"), createdBy: text("created_by"),
@ -156,12 +158,14 @@ export const publicLists = pgTable("public_lists", {
})); }));
// Public blacklist IPs from external sources // Public blacklist IPs from external sources
// NOTE: ip_inet/cidr_inet are INET/CIDR types in production (managed by SQL migrations)
// Drizzle lacks native INET/CIDR support, so we use text() here
export const publicBlacklistIps = pgTable("public_blacklist_ips", { export const publicBlacklistIps = pgTable("public_blacklist_ips", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`), id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
ipAddress: text("ip_address").notNull(), ipAddress: text("ip_address").notNull(),
cidrRange: text("cidr_range"), cidrRange: text("cidr_range"),
ipInet: text("ip_inet"), ipInet: text("ip_inet"), // Actually INET in production - see migration 008
cidrInet: text("cidr_inet"), cidrInet: text("cidr_inet"), // Actually CIDR in production - see migration 008
listId: varchar("list_id").notNull().references(() => publicLists.id, { onDelete: 'cascade' }), listId: varchar("list_id").notNull().references(() => publicLists.id, { onDelete: 'cascade' }),
firstSeen: timestamp("first_seen").defaultNow().notNull(), firstSeen: timestamp("first_seen").defaultNow().notNull(),
lastSeen: timestamp("last_seen").defaultNow().notNull(), lastSeen: timestamp("last_seen").defaultNow().notNull(),

View File

@ -1,7 +1,13 @@
{ {
"version": "1.0.96", "version": "1.0.97",
"lastUpdate": "2026-01-02T11:49:34.922Z", "lastUpdate": "2026-01-02T14:50:15.450Z",
"changelog": [ "changelog": [
{
"version": "1.0.97",
"date": "2026-01-02",
"type": "patch",
"description": "Deployment automatico v1.0.97"
},
{ {
"version": "1.0.96", "version": "1.0.96",
"date": "2026-01-02", "date": "2026-01-02",
@ -295,12 +301,6 @@
"date": "2025-11-24", "date": "2025-11-24",
"type": "patch", "type": "patch",
"description": "Deployment automatico v1.0.48" "description": "Deployment automatico v1.0.48"
},
{
"version": "1.0.47",
"date": "2025-11-24",
"type": "patch",
"description": "Deployment automatico v1.0.47"
} }
] ]
} }