Skip to content

Event Archive and Evidence

L2Proxy can retain three complementary views of an observed industrial operation. Each answers a different customer question:

Example industrial evidence flow into archive and investigation views

Figure — Event archive retains correlated industrial evidence for search and investigation.

Evidence layer Customer question Current storage
L2Proxy Dissector evidence What was decoded from the frame? Raw event archive, event=dissection
Rule decision Which policy matched and what verdict was produced? Raw event archive, event=rule_match
Industrial normalization What happened to which site asset, and how important was it? industrial_events

Customer outcome: preserve technical evidence for investigation while presenting concise, searchable operational events for daily use.

This chapter is self-contained for offline and printed review. The operating console provides the described workflow when accessed through the customer's approved management environment, but understanding the capability does not depend on that access.

Customer-facing Event Explorer

The RaymonGate Live Event2 console provides a configurable operational window into the archived parser and Rule Engine records. It is useful during commissioning, policy review, troubleshooting, demonstrations, and incident drill-down.

Console capability Customer value
Database connection selector Explore the approved event source without changing the capture pipeline
Configurable event table Point the explorer at the selected event archive
Dissections / Rules selectors View parser evidence, policy decisions, or both; filtering is applied by the backend query
Live on/off and polling interval Switch between a stable investigation snapshot and continuously refreshed observation
Limit and offset Page through a large archive without loading the full table into the browser
Total, rule, and dissector counts Understand the selected result population at a glance
Event ID and frame number Preserve database identity and packet-level correlation context
Rule verdict emphasis Make accept and drop outcomes immediately visible beside the rule event
Frame-details modal Open the full matching dissection as formatted JSON from a rule or event row
Persisted toolbox settings Retain the analyst's preferred table, filters, interval, page size, and expanded state in the browser

The console renders each event with its type, archive ID, frame identity, and original JSON body. A rule row adds the verdict prominently; selecting its frame opens the full dissection record for technical verification.

Event archive
Dissections only / Rules only / Both
Event row: I# archive identity + F# frame identity
    ↓ select frame
Full decoded frame JSON

Live Event2 currently explores dissection and rule_match event families. The asset-aware, human-readable DNP3 output belongs to the complementary Industrial Event Normalization capability. Keeping these views distinct prevents a policy verdict, a parser tree, and an industrial event from being mistaken for one another.

Raw JSONB event archive

The current raw archive has a deliberately small envelope:

CREATE TABLE l2proxy_dissector_jsonb (
    id          BIGSERIAL PRIMARY KEY,
    body        JSONB NOT NULL,
    ingested_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

body retains the full event schema without forcing every parser field or future rule metadata key into a relational column. A GIN index supports JSONB investigation, while ingested_at and id support ordered batch and tail processing.

dissection: parser evidence

A dissection event contains the frame identity, length, detected layer names, complete protocol/field trees, and optional L2Proxy Connect access-session context. The following technical record is abbreviated; customer views present these fields as access domain, authenticated user, session, and connection type:

{
  "source": "l2proxy-dissector",
  "event": "dissection",
  "frame_number": 111065,
  "length": 246,
  "layers": ["Ethernet", "IPv4", "TCP", "DNP3"],
  "protocols": [
    {
      "name": "DNP3",
      "abbrev": "dnp3",
      "fields": [
        {"name": "Function Code", "abbrev": "dnp3.al.func", "value": 0, "display": "Confirm (0x00)"}
      ]
    }
  ],
  "l2proxy_connect": {
    "hub": "OT-MASTER",
    "user": "Local Bridge",
    "session": "SID-LOCALBRIDGE-1",
    "kind": 1
  }
}

The field list above is abbreviated for readability. The archived record preserves the complete nested parser output, including offsets, lengths, raw values, displays, object trees, reassembly information, and all decoded protocol layers.

rule_match: policy decision evidence

Rule-match records are much smaller and explain a policy outcome:

{
  "source": "rule_engine",
  "event": "rule_match",
  "frame_number": 21180,
  "rule": "dnp3-accept-select-other",
  "order": 110,
  "verdict": "accept",
  "stop": false,
  "src_ip": "10.10.1.10",
  "dst_ip": "10.10.1.100",
  "src_port": 50423,
  "dst_port": 20000,
  "layers": ["Ethernet", "IPv4", "TCP", "DNP3"],
  "meta": {
    "policy": "accept-select-other",
    "function": "select",
    "src": 3,
    "dst": 100,
    "has_crob": true
  },
  "l2proxy_connect": {
    "hub": "OT-FIELD",
    "user": "Local Bridge",
    "session": "SID-LOCALBRIDGE-1",
    "kind_name": "bridge"
  }
}

Fixed fields support common queries; dynamic meta provides customer-selected evidence only when the rule matches and logging is enabled.

Normalized event database

The industrial_events table projects frequently queried fields into indexed columns:

  • timestamp, protocol, event type, category, severity, and frame number;
  • MAC, IP, and transport endpoints;
  • protocol device address, name, role, and location;
  • operation, function code, and function name;
  • asset, point, intent, action, value, unit, criticality, and alarm;
  • unknown-device and unknown-point discovery flags;
  • complete structured process_assets in JSONB.

This structure supports fast operational filtering without discarding the raw dissection. Four provided views cover recent critical events, control summaries, unknown devices, and unknown points.

Correlation across the three views

frame number + timestamp + endpoints
              ├─ dissection: decoded protocol proof
              ├─ rule_match: policy and verdict proof
              └─ industrial_event: asset and operational meaning

frame_number is the primary packet-level correlation key when the records originate from the same capture/engine context. Timestamp, endpoints, protocol addresses, session identity, and rule meta provide additional dimensions. Across several sensors or restarted capture sequences, use a sensor/instance identity in the integration key; frame number alone is not globally unique.

Repetition is expected—noise is optional

Industrial polling, responses, fragments, redundant paths, retries, and repeated status values can produce many similar records. The archive should preserve evidence, while customer-facing views summarize it.

Recommended separation:

  1. Archive every required raw event according to the customer's evidence policy.
  2. Normalize and index operational dimensions for search and reporting.
  3. Group routine events by time bucket, device, category, operation, and description.
  4. Show state changes and control activity prominently; keep periodic steady-state polling available for drill-down.
  5. Do not deduplicate only by frame number until sensor, direction, bridge/session, retransmission, and ingestion behavior are understood.
  6. Alert on transition or threshold, not on every identical monitoring response.

Example summary query:

SELECT
  date_trunc('minute', timestamp) AS minute,
  category,
  event_type,
  src_device_name,
  dst_device_name,
  description,
  count(*) AS occurrences
FROM industrial_events
GROUP BY 1, 2, 3, 4, 5, 6
ORDER BY minute DESC, occurrences DESC;

This reduces visual noise without deleting the underlying records.

Useful archive queries

-- Event-family volume
SELECT body->>'event' AS event, count(*)
FROM l2proxy_dissector_jsonb
GROUP BY 1;

-- Rule outcomes with metadata coverage
SELECT
  body->>'rule' AS rule,
  body->>'verdict' AS verdict,
  count(*) AS matches,
  count(*) FILTER (WHERE body ? 'meta') AS with_meta
FROM l2proxy_dissector_jsonb
WHERE body->>'event' = 'rule_match'
GROUP BY 1, 2
ORDER BY matches DESC;

-- Retrieve parser evidence and decisions for one frame
SELECT id, ingested_at, body
FROM l2proxy_dissector_jsonb
WHERE body->>'frame_number' = '21180'
ORDER BY id;

-- High-value normalized activity
SELECT timestamp, category, severity, src_device_name, dst_device_name,
       asset_id, operation, description
FROM industrial_events
WHERE category IN ('control', 'maintenance', 'configuration')
   OR severity IN ('high', 'critical')
ORDER BY timestamp DESC;

Verified deployment snapshot

The live database was queried read-only while preparing this documentation. At that point it contained:

Dataset Records Detail
Raw archive 41,092 41,019 dissection; 73 rule_match
Dissection frame identities 36,043 4,976 additional records shared an existing frame number
Rule-match frame identities 73 all unique in this snapshot
Normalized DNP3 events 14,981 control, monitoring, response, unsolicited, configuration, confirmation, and fragment categories
Rule matches with dynamic meta 24 customer-selected policy and DNP3 context
Raw dissections with L2Proxy Connect context 22,048 access-domain/user/session context present

The snapshot covered ingestion from 25 July through 30 July 2026. Counts are evidence that the deployed path is active, not fixed product limits or performance claims.

Session-linked investigation with L2Proxy Connect

When L2Proxy Connect is the enforcement path, the archive can link an authenticated user and session to the industrial messages and policy decisions carried by that session. This supports questions such as:

  • Which equipment and operations did a remote engineer access during one session?
  • Which commands were accepted, blocked, or only recorded for that user?
  • Did the same session perform an unexpected configuration or control sequence?
  • Which detailed protocol message supports the human-readable operational event?

The identity context complements protocol evidence; it does not replace equipment, operation, value, sequence, or process-state analysis.

Storage lifecycle and security

The current schema provides storage and queryability; it does not impose a universal retention policy. Each deployment should define:

  • raw versus normalized retention periods;
  • time partitioning and expected storage growth;
  • backup, restore, and integrity verification;
  • database roles and least-privilege access;
  • encryption and network isolation requirements;
  • handling of IP, MAC, username, session, and operational asset information;
  • export to SIEM, historian-adjacent reporting, or long-term evidence storage;
  • approved aggregation and deletion procedures.

Production database credentials should be supplied through deployment secrets and kept out of customer-facing examples, repository files, and generated sites.

Product boundary

This capability is a queryable event archive and normalized operational database. It is not, by itself, a complete SIEM, immutable evidence vault, historian, or automatic data lifecycle platform. Those controls can be integrated or added according to customer requirements without changing the event contracts described here.