Skip to content

feat(engine): event normalizer#16

Merged
sepehr-safari merged 1 commit into
mainfrom
feat/engine-normalizer
Jul 11, 2026
Merged

feat(engine): event normalizer#16
sepehr-safari merged 1 commit into
mainfrom
feat/engine-normalizer

Conversation

@sepehr-safari

Copy link
Copy Markdown
Member

What & why

Second slice of S1 — Engine core: src/ocpp/normalizer.zig, which turns raw
TraceEventInput entries into canonical Events. Mirrors the toolkit's
core/normalizer.ts — the shared conformance contract — including its exact
action tables and the 10^12 epoch threshold, so the two implementations agree.

Changes

  • Message classification / field extractionclassifyMessageType plus
    extractAction / extractPayload / extractErrorCode /
    extractErrorDescription, reading [typeId, uniqueId, …] off the
    std.json.Value boundary.
  • Timestamp normalizationnormalizeTimestamp handles ISO 8601 (UTC and
    ±hh:mm offset, with optional fractional seconds) via a self-contained
    days-from-civil parser, plus epoch seconds / milliseconds (as JSON number or
    numeric string) split on the 10^12 threshold. Missing zone ⇒ UTC, so results
    don't depend on the host's local time.
  • DirectioninferDirection from the CS→CSMS / CSMS→CS action tables
    (DataTransfer, present in both, resolves CS→CSMS), reverseDirection, and a
    two-pass normalizeEvents that resolves each response's direction from its
    matched Call. Explicit input direction (even unknown) is respected;
    sequential evt-0001 ids; input order preserved.

Security (untrusted input)

Timestamps come from untrusted traces, so the numeric paths guard against
overflow: seconds→ms multiplication uses checked std.math.mul, and the
float→int cast is range-checked. Absurd magnitudes (e.g. 1e300) return null
instead of panicking — covered by a test.

Testing

  • native test -Dplatform=null17/17 pass (9 new normalizer tests ported
    from the toolkit: timestamp variants, direction inference/reversal, field
    extraction, response matching, explicit-direction respect, empty input).
  • The ISO instant 2024-01-15T10:00:00Z and its +02:00 equivalent both resolve
    to 1_705_312_800_000, matching the toolkit's Date.parse.
  • native check --strict and zig fmt --check clean.

Closes #12

Add `src/ocpp/normalizer.zig` — the second S1 engine module — turning raw
trace inputs into canonical `Event`s. Mirrors the toolkit's normalizer
behavior (the shared conformance contract), not its source.

- Message classification and field extraction (action, payload, error
  code / description) over the `std.json.Value` boundary.
- Timestamp normalization: ISO 8601 (UTC and ±hh:mm offset, via a
  self-contained days-from-civil parser) and epoch seconds / milliseconds
  with the 10^12 threshold. Untrusted magnitudes are guarded against
  integer overflow and out-of-range float casts.
- Direction inference from the CS→CSMS / CSMS→CS action tables
  (DataTransfer resolves CS→CSMS), plus two-pass resolution of response
  directions from their matched Call.

The toolkit's normalizer test cases are ported.

Closes #12
@sepehr-safari sepehr-safari added this to the S1 — Engine core milestone Jul 11, 2026
@sepehr-safari sepehr-safari added type:feature New capability area:engine Pure Zig OCPP engine priority:high labels Jul 11, 2026
@sepehr-safari sepehr-safari merged commit 3a17a80 into main Jul 11, 2026
3 checks passed
@sepehr-safari sepehr-safari deleted the feat/engine-normalizer branch July 11, 2026 10:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:engine Pure Zig OCPP engine priority:high type:feature New capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(engine): event normalizer (classification, timestamps, direction)

1 participant