Event Archive and Evidence¶
L2Proxy can retain three complementary views of an observed industrial operation. Each answers a different customer question:

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_assetsin 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:
- Archive every required raw event according to the customer's evidence policy.
- Normalize and index operational dimensions for search and reporting.
- Group routine events by time bucket, device, category, operation, and description.
- Show state changes and control activity prominently; keep periodic steady-state polling available for drill-down.
- Do not deduplicate only by frame number until sensor, direction, bridge/session, retransmission, and ingestion behavior are understood.
- 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.