# logcorrelator RPM spec file
# Compatible with CentOS 7, Rocky Linux 8, 9, 10
# Built with rpmbuild (not FPM)

Name:           logcorrelator
Version:        %{spec_version}
Release:        1%{?dist}
Summary:        Log correlation service for HTTP and network events

License:        MIT
URL:            https://github.com/logcorrelator/logcorrelator
Vendor:         logcorrelator <dev@example.com>
Packager:       logcorrelator <dev@example.com>

BuildArch:      x86_64

# Version macro with safe fallback
%if %{defined version}
%define spec_version %{version}
%else
%define spec_version 1.1.22
%endif

# Dependencies
Requires:          systemd
Requires(pre):     shadow-utils
Requires(post):    systemd
Requires(preun):   systemd
Requires(postun):  systemd
BuildRequires:     systemd-rpm-macros

%description
logcorrelator est un service système écrit en Go qui reçoit deux flux de logs JSON
via des sockets Unix, corrèle les événements HTTP applicatifs avec des événements
réseau, et produit des logs corrélés en temps réel vers ClickHouse et/ou fichier local.

Notes de sécurité :
- Le service s'exécute sous l'utilisateur logcorrelator (non-root)
- Les sockets Unix sont créés avec des permissions 0666 (world read/write)
- Les répertoires critiques sont protégés : /var/log (750), /var/lib (750), /etc (750)
- /var/run/logcorrelator est en 755 pour permettre la création de sockets

%prep
# Files are already in BUILD directory (copied by build-rpm.sh)
# No extraction needed
echo "Files available in BUILD directory:"
ls -la %{_builddir}/

%install
# Create directory structure in buildroot
mkdir -p %{buildroot}/usr/bin
mkdir -p %{buildroot}/etc/logcorrelator
mkdir -p %{buildroot}/var/log/logcorrelator
mkdir -p %{buildroot}/var/lib/logcorrelator
mkdir -p %{buildroot}%{_unitdir}
mkdir -p %{buildroot}/etc/logrotate.d

# Install binary (from BUILD directory)
install -m 0755 %{_builddir}/usr/bin/logcorrelator %{buildroot}/usr/bin/logcorrelator

# Install config files
install -m 0640 %{_builddir}/etc/logcorrelator/logcorrelator.yml %{buildroot}/etc/logcorrelator/logcorrelator.yml
install -m 0640 %{_builddir}/etc/logcorrelator/logcorrelator.yml.example %{buildroot}/etc/logcorrelator/logcorrelator.yml.example

# Install systemd service — destination is %{_unitdir} (/usr/lib/systemd/system), never /etc/
install -m 0644 %{_builddir}/etc/systemd/system/logcorrelator.service %{buildroot}%{_unitdir}/logcorrelator.service

# Install logrotate config
install -m 0644 %{_builddir}/etc/logrotate.d/logcorrelator %{buildroot}/etc/logrotate.d/logcorrelator

%pre
# Create service user and group before file installation so %attr() works correctly
if ! getent group logcorrelator >/dev/null 2>&1; then
    groupadd --system logcorrelator
fi
if ! getent passwd logcorrelator >/dev/null 2>&1; then
    useradd --system \
        --gid logcorrelator \
        --home-dir /var/lib/logcorrelator \
        --no-create-home \
        --shell /usr/sbin/nologin \
        logcorrelator
fi

%post
# Use standard systemd RPM macros (daemon-reload, preset, no-op in containers)
%systemd_post logcorrelator.service
# Explicitly enable+start on fresh install
if [ $1 -eq 1 ] && [ -x /usr/bin/systemctl ] && [ -d /run/systemd/system ]; then
    /usr/bin/systemctl enable logcorrelator.service 2>/dev/null || :
    /usr/bin/systemctl start logcorrelator.service 2>/dev/null || :
fi

# Set ownership and permissions (idempotent — safe on both install and upgrade)
chown -R logcorrelator:logcorrelator /var/lib/logcorrelator 2>/dev/null || true
chown -R logcorrelator:logcorrelator /var/log/logcorrelator 2>/dev/null || true
chown -R logcorrelator:logcorrelator /etc/logcorrelator 2>/dev/null || true
chmod 750 /var/lib/logcorrelator 2>/dev/null || true
chmod 750 /var/log/logcorrelator 2>/dev/null || true
chmod 750 /etc/logcorrelator 2>/dev/null || true

# Copy default config if not exists
if [ ! -f /etc/logcorrelator/logcorrelator.yml ]; then
    cp /etc/logcorrelator/logcorrelator.yml.example /etc/logcorrelator/logcorrelator.yml
    chown logcorrelator:logcorrelator /etc/logcorrelator/logcorrelator.yml
    chmod 640 /etc/logcorrelator/logcorrelator.yml
fi

%preun
%systemd_preun logcorrelator.service

%postun
%systemd_postun_with_restart logcorrelator.service

%files
/usr/bin/logcorrelator
%config(noreplace) /etc/logcorrelator/logcorrelator.yml
/etc/logcorrelator/logcorrelator.yml.example
%dir /var/log/logcorrelator
%dir /var/lib/logcorrelator
%{_unitdir}/logcorrelator.service
%config(noreplace) /etc/logrotate.d/logcorrelator

%changelog
* Wed Mar 11 2026 logcorrelator <dev@example.com> - 1.1.22-1
- Feat(outputs): file output enabled/disabled toggle
  Ajout du champ enabled: true/false dans outputs.file de la configuration.
  Le sink fichier n'est cree que si enabled: true ET path: defini.
  Permet de desactiver completement la sortie fichier tout en gardant stdout/clickhouse.
  Tests: TestValidate_FileOutputDisabled, TestLoadConfig_FileOutputDisabled

- Fix(systemd): arret immediat sans vidage de queue
  orchestrator.Stop() ne vide plus les buffers (events en transit perdus).
  Suppression de ShutdownTimeout et de la logique de flush/attente.
  systemd TimeoutStopSec=30 gere l'arret force si besoin.
  Simplification: cancel() + Close() uniquement.

- Feat(sql): TTL et compression ZSTD sur tables ClickHouse
  http_logs_raw: TTL 1 jour, compression ZSTD sur raw_json
  http_logs: TTL 7 jours, compression ZSTD sur champs texte volumineux
  Parametre ttl_only_drop_parts = 1 pour optimiser les suppressions

* Mon Mar 09 2026 logcorrelator <dev@example.com> - 1.1.21-1
- Update: vues ClickHouse et schema SQL
  Ajout de bots.sql pour l'identification des bots (User-Agent parsing)
  Ajout de tables.sql pour les tables de reference
  Mise a jour de mv1.sql (vue materialisee) avec nouvelle structure de correlation
  Documentation views.md enrichie avec exemples de requetes et schema complet

* Mon Mar 09 2026 logcorrelator <dev@example.com> - 1.1.20-1
- Fix(rpm): suppression de systemd-tmpfiles.conf redondant
  RuntimeDirectory=logcorrelator dans le service systemd gere deja /run/logcorrelator
  automatiquement. La commande systemd-tmpfiles --create causait des erreurs sur
  les systemes avec /var/lib/mysql existant (fichier au lieu de repertoire).
  Suppression de /usr/lib/tmpfiles.d/logcorrelator.conf et de systemd-tmpfiles --create.

* Mon Mar 09 2026 logcorrelator <dev@example.com> - 1.1.19-1
- Fix(systemd): stop/restart immediat sans attendre vidage queue
  L'arret du service ne vide plus les buffers (events en transit perdus).
  systemd TimeoutStopSec=30 gere deja l'arret force si besoin.
  Simplification de orchestrator.Stop() : cancel() + Close() uniquement.
  Suppression de ShutdownTimeout devenu inutile.

* Mon Mar 09 2026 logcorrelator <dev@example.com> - 1.1.18-1
- Fix(outputs): file output enabled: false ne coupait pas l ecriture du fichier
  Le champ Enabled manquait dans FileOutputConfig. Le sink fichier etait cree
  meme avec enabled: false tant que path etait defini. Desormais, la condition
  verifie explicitement enabled && path != "" dans main.go et Validate().
  Test: TestValidate_FileOutputDisabled et TestLoadConfig_FileOutputDisabled ajoutes.

* Fri Mar 06 2026 logcorrelator <dev@example.com> - 1.1.17-1
- Fix(correlation): champ keepalives non peuple dans ClickHouse
  Le champ KeepAliveSeq de NormalizedEvent n'etait pas transfere dans les Fields
  de CorrelatedLog. La vue materialisee ClickHouse extrayait keepalives du JSON
  mais trouvait toujours 0. Desormais, NewCorrelatedLog et NewCorrelatedLogFromEvent
  ajoutent explicitement keepalives = KeepAliveSeq dans les Fields.

* Fri Mar 06 2026 logcorrelator <dev@example.com> - 1.1.16-1
- Feat(correlation): emettre les evenements A filtrés par include_dest_ports vers ClickHouse
  Quand un evenement A (HTTP) etait exclu par le filtre include_dest_ports, il etait
  silencieusement ignore. Desormais, si ApacheAlwaysEmit=true, l evenement est emis comme
  non-correle (orphan_side=A) afin d apparaitre dans ClickHouse. Les evenements B restent
  ignores. Test: TestCorrelationService_IncludeDestPorts_FilteredPort mis a jour +
  TestCorrelationService_IncludeDestPorts_FilteredPort_NoAlwaysEmit ajoute.

* Thu Mar 05 2026 logcorrelator <dev@example.com> - 1.1.15-1
- Fix(correlation/bug3): perte de donnees quand B expire avec des orphelins en attente
  cleanNetworkBufferByTTL supprimait les pendingOrphans sans les emettre (perte silencieuse).
  Desormais, les orphelins A sont retournes immediatement a l'appelant quand B expire,
  et cleanExpired/ProcessEvent propagent ces resultats vers le sink.
  Test: TestBTTLExpiry_PurgesPendingOrphans etendu pour verifier l'emission effective.

* Thu Mar 05 2026 logcorrelator <dev@example.com> - 1.1.14-1
- Fix(correlation/bug1): Keep-Alive sessions au-dela de TimeWindow ne correlent plus en orphelins
  Le matcher dans processSourceA utilisait eventsMatch (comparaison de timestamps) en mode
  one_to_many. Apres ~10s, B.Timestamp_original depasse la TimeWindow et toutes les requetes
  suivantes devenaient orphelines. Nouveau matcher bEventHasValidTTL : un B event est valide
  tant que son TTL n'a pas expire (le TTL est reset a chaque correlation Keep-Alive).
- Fix(correlation/bug4): checkPendingOrphansForCorrelation utilisait eventsMatch (meme bug)
  En mode one_to_many, un B arrivant avec un vieux timestamp ne matchait plus les pending orphans
  pour la meme cle. Remplace par une verification de cle uniquement (meme cle = meme connexion).
- Fix(correlation/bug3): pendingOrphans non purges quand le B expire (cleanNetworkBufferByTTL)
  Quand un B event expirait (TTL), les pending orphan A associes etaient bloques indefiniment.
  Ils sont desormais emis immediatement lors de l'expiration du B correspondant.
- Fix(correlation/bug2): orphans emis uniquement sur reception d'evenement (pas de timer dedie)
  EmitPendingOrphans() est maintenant une methode publique thread-safe. L'Orchestrateur
  demarre un goroutine ticker (250ms) qui appelle EmitPendingOrphans() independamment du flux,
  garantissant l'emission meme en l'absence de nouveaux evenements.
- Feat(ports): ajout de EmitPendingOrphans() dans l'interface CorrelationProcessor
- Test: 4 nouveaux tests de non-regression (Bug #1, #2, #3, #4)

* Thu Mar 05 2026 logcorrelator <dev@example.com> - 1.1.13-1
- Fix: Unix sockets ne passent plus en root:root lors des restarts du service
- Fix: Ajout de RuntimeDirectory=logcorrelator dans le service systemd (systemd gère /run/logcorrelator avec le bon propriétaire à chaque démarrage/restart)
- Fix: Ajout de /usr/lib/tmpfiles.d/logcorrelator.conf pour recréer /run/logcorrelator au boot
- Chore: Retrait de /var/run/logcorrelator du RPM %files (géré par tmpfiles.d)
- Fix(correlation): emitPendingOrphans - corruption de slice lors de l expiration simultanée de plusieurs orphelins pour la même clé (slice aliasing bug, émissions en double)
- Fix(correlation): rotateOldestA - l événement rotaté était perdu silencieusement même avec ApacheAlwaysEmit=true (retourne désormais le CorrelatedLog)
- Fix(correlation): Keep-Alive cassé dans le chemin pending-orphan-then-B - le B event n était pas bufferisé en mode one_to_many, bloquant la corrélation des requêtes A2+ du même Keep-Alive
- Chore(correlation): suppression du champ mort timer *time.Timer dans pendingOrphan
- Feat(correlation): ajout de keepalive_seq dans les logs orphelins pour faciliter le debug (numéro de requête dans la connexion Keep-Alive, 1-based)
- Test: 4 nouveaux tests de non-régression pour les bugs de corrélation

* Thu Mar 05 2026 logcorrelator <dev@example.com> - 1.1.12-1
- Feat: New config directive include_dest_ports - restrict correlation to specific destination ports
- Feat: If include_dest_ports is non-empty, events on unlisted ports are silently ignored (not correlated, not emitted as orphan)
- Feat: New metric failed_dest_port_filtered for monitoring filtered traffic
- Feat: Debug log for filtered events: "event excluded by dest port filter: source=A dst_port=22"
- Test: New unit tests for include_dest_ports (allowed port, filtered port, empty=all)
- Docs: README.md updated with include_dest_ports section and current version references
- Docs: architecture.yml updated with include_dest_ports
- Fix: config.example.yml - removed obsolete stdout.level field

* Thu Mar 05 2026 logcorrelator <dev@example.com> - 1.1.11-1
- Fix: StdoutSink no longer writes correlated/orphan JSON to stdout
- Fix: stdout sink is now a no-op for data; operational logs go to stderr via logger
- Fix: ClickHouse sink had no logger - all flush errors were silently discarded
- Fix: Periodic, batch and final-close flush errors are now logged at ERROR level
- Fix: Buffer overflow with DropOnOverflow=true is now logged at WARN level
- Fix: Retry attempts are now logged at WARN level with attempt number, delay and error
- Feat: ClickHouse connection success logged at INFO (table, batch_size, flush_interval_ms)
- Feat: Successful batch sends logged at DEBUG (rows count, table)
- Feat: SetLogger() method added to ClickHouseSink for external logger injection
- Test: New unit tests for StdoutSink asserting stdout remains empty for all log types

* Wed Mar 04 2026 logcorrelator <dev@example.com> - 1.1.10-1
- Feat: IP exclusion filter - exclude specific source IPs or CIDR ranges
- Feat: Configuration exclude_source_ips supports single IPs and CIDR notation
- Feat: Debug logging for excluded IPs
- Feat: New metric failed_ip_excluded for monitoring filtered traffic
- Feat: Architecture documentation updated with observability section
- Use cases: exclude health checks, internal traffic, known bad actors
- Docs: README.md updated with IP exclusion documentation
- Docs: architecture.yml updated with metrics and troubleshooting guide

* Wed Mar 04 2026 logcorrelator <dev@example.com> - 1.1.9-1
- Feat: Debug logging - detailed DEBUG logs for correlation troubleshooting
- Feat: Correlation metrics server (HTTP endpoint /metrics and /health)
- Feat: New metrics: events_received, correlations_success/failed, failure reasons
- Feat: Failure reason tracking: no_match_key, time_window, buffer_eviction, ttl_expired
- Feat: Buffer size monitoring (buffer_a_size, buffer_b_size)
- Feat: Orphan tracking (orphans_emitted, orphans_pending, pending_orphan_match)
- Feat: Keep-Alive reset counter for connection tracking
- Feat: Test scripts added (test-correlation.sh, test-correlation-advanced.py)
- Change: Config example updated with metrics section
- Docs: README.md updated with debugging guide and troubleshooting table

* Tue Mar 03 2026 logcorrelator <dev@example.com> - 1.1.8-1
- Migrated from FPM to rpmbuild (native RPM build)
- Reduced build image size by 200MB (-40%)
- Removed FPM gem dependency (use rpmbuild directly)
- Scripts post/preun/postun now inline in spec file
- Build image: rockylinux:8 instead of ruby:3.2-bookworm

* Tue Mar 03 2026 logcorrelator <dev@example.com> - 1.1.7-1
- Fix: Critical Keep-Alive bug - network events evicted based on original timestamp instead of reset TTL
- Fix: Correlation time window increased from 1s to 10s for HTTP Keep-Alive support
- Fix: Network source now uses payload timestamp if available (fallback to reception time)
- Change: Default network TTL increased from 30s to 120s for long Keep-Alive sessions
- Test: Added comprehensive Keep-Alive tests (TTL reset, long session scenarios)

* Tue Mar 03 2026 logcorrelator <dev@example.com> - 1.1.6-1
- Docs: Update ClickHouse schema documentation (http_logs_raw + http_logs tables)
- Fix: ClickHouse insertion uses single raw_json column (FORMAT JSONEachRow)
- Fix: ClickHouse native API (clickhouse-go/v2 PrepareBatch + Append + Send)

* Tue Mar 03 2026 logcorrelator <dev@example.com> - 1.1.5-1
- Fix: ClickHouse insertion using native clickhouse-go/v2 API (PrepareBatch + Append + Send)
- Fix: Replaced database/sql wrapper with clickhouse.Open() and clickhouse.Conn
- Fix: Proper batch sending to avoid ATTEMPT_TO_READ_AFTER_EOF errors
- Fix: Set correct permissions (755) on /var/run/logcorrelator in RPM post-install

* Mon Mar 02 2026 logcorrelator <dev@example.com> - 1.1.4-1
- Fix: Log raw JSON data on parse errors for debugging

* Mon Mar 02 2026 logcorrelator <dev@example.com> - 1.1.3-1
- Refactor: Switch Unix sockets from STREAM to DGRAM mode (SOCK_DGRAM)
- Test: Comprehensive tests added - coverage improved to 74.4%
- Fix: Example config file installed to /etc/logcorrelator/logcorrelator.yml.example
- Change: Default socket permissions from 0660 to 0666 (world read/write)

* Mon Mar 02 2026 logcorrelator <dev@example.com> - 1.1.2-1
- Fix: Example config file installed to /etc/logcorrelator/logcorrelator.yml.example
- Change: Default socket permissions from 0660 to 0666 (world read/write)

* Mon Mar 02 2026 logcorrelator <dev@example.com> - 1.1.1-1
- Fix: Move logcorrelator.yml.example from /usr/share/logcorrelator/ to /etc/logcorrelator/

* Mon Mar 02 2026 logcorrelator <dev@example.com> - 1.1.0-1
- Feat: Keep-Alive support (one-to-many correlation mode)
- Feat: Dynamic TTL for network events (source B)
- Feat: Separate buffer sizes for HTTP and network events
- Feat: SIGHUP signal handling for log rotation
- Feat: File sink Reopen() method for log rotation
- Feat: logrotate configuration included
- Feat: ExecReload added to systemd service
- Feat: New YAML config structure (time_window, orphan_policy, matching, buffers, ttl)
- Docs: Updated architecture.yml and config.example.yml

* Sat Feb 28 2026 logcorrelator <dev@example.com> - 1.0.7-1
- Added: Log levels DEBUG, INFO, WARN, ERROR configurable via log.level
- Added: Warn and Warnf methods for warning messages
- Added: Debug logs for events received from sockets and correlations
- Added: Warning logs for orphan events and buffer overflow
- Changed: Configuration log.enabled replaced by log.level
- Changed: Orphan events and buffer overflow now logged as WARN instead of DEBUG

* Sat Feb 28 2026 logcorrelator <dev@example.com> - 1.0.6-1
- Changed: Configuration YAML simplified, removed service.name, service.language
- Changed: Correlation config simplified, time_window_s instead of nested object
- Changed: Orphan policy simplified to emit_orphans boolean
- Changed: Apache socket renamed to http.socket
- Added: socket_permissions option on unix sockets

* Sat Feb 28 2026 logcorrelator <dev@example.com> - 1.0.5-1
- Added: Systemd service auto-start after RPM installation
- Added: Systemd service hardening (TimeoutStartSec, TimeoutStopSec, ReadWritePaths)
- Fixed: Systemd service unit correct config path (.yml instead of .conf)
- Fixed: CI workflow branch name main to master
- Changed: RPM packaging generic el8/el9/el10 directory naming

* Sat Feb 28 2026 logcorrelator <dev@example.com> - 1.0.4-1
- Breaking: Flattened JSON output structure - removed apache and network subdivisions
- All log fields now merged into single-level JSON structure
- ClickHouse schema: replaced apache JSON and network JSON columns with fields JSON column
- Custom MarshalJSON() implementation for flat output

* Sat Feb 28 2026 logcorrelator <dev@example.com> - 1.0.3-1
- Fix: Added missing ClickHouse driver dependency
- Fix: Fixed race condition in orchestrator
- Security: Added explicit source_type configuration for Unix socket sources
- Added: Comprehensive test suite improvements
- Added: Test coverage improved from 50.6% to 62.0%

* Sat Feb 28 2026 logcorrelator <dev@example.com> - 1.0.2-1
- Added: Initial RPM packaging support for Rocky Linux 8/9 and AlmaLinux 10
- Added: Docker multi-stage build pipeline
- Added: Hexagonal architecture implementation
- Added: Unix socket input sources (JSON line protocol)
- Added: File output sink (JSON lines)
- Added: ClickHouse output sink with batching and retry logic
- Added: Time-window based correlation on src_ip + src_port
- Added: Graceful shutdown with signal handling (SIGINT, SIGTERM)

* Sat Feb 28 2026 logcorrelator <dev@example.com> - 1.0.1-1
- Initial package for CentOS 7, Rocky Linux 8, 9, 10
