Skip to content

docs(tutorials): Eventum Learn — full 5-track course (Foundations, Formats, Realism, Delivery, Scenarios)#45

Open
rnv812 wants to merge 80 commits into
developfrom
feat/learning-course
Open

docs(tutorials): Eventum Learn — full 5-track course (Foundations, Formats, Realism, Delivery, Scenarios)#45
rnv812 wants to merge 80 commits into
developfrom
feat/learning-course

Conversation

@rnv812

@rnv812 rnv812 commented Jul 11, 2026

Copy link
Copy Markdown
Member

What

Eventum Learn — the tutorials/ section reshaped into an SEO-driven learning course. Each page pairs a domain explainer (a log format, a delivery backend, a realism technique, an applied scenario) with hands-on Eventum practice, so the docs rank on the queries practitioners actually search and funnel readers to the product natively. Full design and phased lesson map live in specs/.

This PR now contains the complete course — Phases 1 + 2 + 3, the full five-track arc built out end to end.

The arc

Foundations → Formats → Realism → Delivery → Scenarios, wired as pillar + cluster: five track pillars (each an index.mdx + meta.json, grouped in the sidebar), Course JSON-LD on the six pillar pages only, and cluster↔pillar + cluster↔cluster interlinking throughout. Existing tutorials keep their URLs.

Lessons

Foundations (3) — Logs vs metrics vs events (the three telemetry shapes), Structured logging (plain text vs JSON), Streaming vs bulk (live vs sample mode).

Formats (11) — Windows Event Log & Sysmon, CEF, LEEF, syslog (RFC 5424 vs 3164), NDJSON, OCSF, ECS, Apache/Nginx access logs (CLF/Combined), AWS CloudTrail, Suricata EVE JSON, Linux auditd. Each pairs a raw-wire-format explainer with "generate it in Eventum". For the security/audit formats whose Hub generators emit the ECS-parsed shape, the lesson teaches the raw format from the vendor spec and links the Hub generator for the parsed variant.

Realism (5) — Timing (time_patterns), Sessions (FSM + state), Correlated events (event.sequence + concurrent keyed pools), Values (distributions, weighted picks), Replay (real logs with fresh timestamps).

Delivery (6) — OpenSearch (log generator for opensearch), Kafka, ClickHouse (clickhouse test data), HTTP endpoint (send test data to api), syslog over TCP/UDP to collectors & SIEM (send syslog to collector), and output formatters (shaping the stream per destination).

Scenarios (8) — pillar (a general applied umbrella) + Test your data pipeline (⭐ end-to-end hub: generate → deliver → confirm receipt), Detection testing (test sigma rules, Sigma correlation rules + ATT&CK), SIEM test data, Load testing (load test data), Seeding (seed database test data), Clickstream → ClickHouse (clickstream data), IoT test data, Alert simulation (Telegram). Phase 3 rewrote the last three into the course voice.

Verification

  • pnpm types:check and a full pnpm build clean — 255 static HTML pages (~699 build routes including OG images), static export succeeds, and a final integrity sweep found 0 broken links across 380 internal links on the new/rewritten pages. Course JSON-LD scoped to exactly the 6 pillar paths (absent on lessons/root).
  • Facts verified against primary sources: IETF RFCs (5424/3164/5426/6587/5425), ArcSight/IBM specs, Microsoft Learn, ECS, OCSF, the Suricata EVE JSON spec, AWS CloudTrail record contents, Red Hat auditd docs, Apache/Nginx log-format docs, SigmaHQ correlation-rules spec, MITRE ATT&CK. Every Eventum config checked against the plugin reference and, where a broker/cluster wasn't required, validated through the real eventum CLI.
  • Per-task reviews plus a final whole-branch review (verdict: ready to merge); all findings resolved. Along the way this also corrected real drift already shipped in the docs — wrong stats endpoint/metric names and a fabricated exit-summary in the load-testing lesson, a Jinja whitespace bug in the CSV lesson (was silently producing 4× the rows), the glossary's incorrect "chance must sum to 1.0", and several stale cross-references and dead anchors.
  • Fixed the eventum#178-breaking FSM pattern (comparison conditions on dotted state keys, which fail validation) everywhere it appeared in the course — web-clickstream and siem-events — rewriting both to the working "compute the threshold in the template, set a boolean flag, branch on defined" pattern. The course now teaches and uses that pattern uniformly.

Scope

The complete Eventum Learn course — Foundations, Formats, Realism, Delivery, Scenarios. Design + per-phase implementation plans are in specs/. Files under content/docs/tutorials/**.

rnv812 and others added 30 commits July 11, 2026 13:01
Design for reshaping the tutorials section into a phased, SEO-driven
learning course: narrative arc, 5 tracks, ~35-lesson map, lesson
anatomy, on-page SEO mechanics, and Fumadocs IA.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Navigation scaffold (Learn rename, Formats/Delivery/Scenarios track pillars, Course JSON-LD) plus briefs for the 7 Phase 1 lessons, executed via new-docs-page.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Smoke-testing the example generator through the actual eventum CLI
showed samples.usernames | random returns a Row wrapper even for
items-type samples with no field names, rendering as the Python repr
instead of the plain username. Index into the row: (... | random)[0].

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ular window, Sysmon file-create, Hub numbers)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Self-review fix: RFC 6587 explicitly declines to assign a port for
syslog over TCP and notes 514/TCP is actually allocated to the Shell
protocol, so the FAQ answer overstated RFC 6587's role in port 514.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Self-review: syslog-ng's default-network-drivers() commonly separates
RFC 3164 from RFC 5424 by port rather than content-sniffing the way
rsyslog does. Could not verify a specific mechanism from a primary
source, so the FAQ now points to the driver config instead of
asserting 'equivalent detection'.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…oc envelope

Soften the batch/bulk-request correspondence claim (batch composition
depends on unshown defaults) and fix an inaccurate comparison to
default search hits, which return _score, not _version.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…a query

- Prepend a short theory paragraph on what SIEM test data is and why
  it's generated (detection development, parser/ingestion validation,
  analyst training) without touching production or live attacks.
- Tune frontmatter title/description (and thus the H1) for the
  siem test data query while keeping the Windows -> OpenSearch scope
  honest.
- Add an FAQ (live SIEM/attacks, other log sources, Elasticsearch/
  other backends, adding event types).
- Add a Related section linking to the scenarios pillar, the Windows
  Event Log format lesson, the OpenSearch delivery lesson, and the
  Hub's windows-security generator.
- Fix two pre-existing dead links left stale by an unrelated
  plugins/event/template reference-docs restructuring: #samples and
  producing#state now point at the current template/samples and
  template/state pages.

Build steps (generator.yml, templates, FSM, OpenSearch config,
commands) are untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pillar page for track A (Foundations) of the Eventum Learn course:
what synthetic event and log data is, how it differs from a flat
Faker/Mockaroo export, where it is used, and how Eventum's pipeline
generates it. Links out to the structured-logging cluster lesson
(Task 1.2) and the Realism pillar (Task 1.3) - both forward links
within this wave, resolved by its checkpoint.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds content/docs/tutorials/foundations/structured-logging.mdx, the
first cluster lesson in the Foundations track of Eventum Learn.

Covers plain-text vs structured (key-value/JSON) logging, why
structure matters for parsing, search, and detections, and the
format-vs-schema distinction that bridges to the upcoming ECS lesson.
Includes a template + JSON formatter generator.yml validated through
the real CLI, with a real generated event as the result block.
Add the pillar page for track C (Realism) of the Eventum Learn
course, targeting the primary query 'realistic test data'.

Frames three axes of realistic synthetic data - timing, sessions
and state, and value distributions - each linking forward to its
own cluster lesson (timing, sessions, values - Tasks 1.4-1.6).
Cross-links the Formats and Delivery pillars.

Mechanisms named are grounded in the time_patterns input plugin,
the template event plugin's fsm mode and state scopes, and
module.rand distributions / weighted_choice / Faker / Mimesis /
samples.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds the Realism track's timing cluster lesson: simulating diurnal
peaks, bursts, and quiet periods with the time_patterns input plugin,
targeting "simulate traffic patterns".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cluster lesson for the Realism track: simulate user sessions (login,
activity, logout) as a finite state machine with shared template
state carrying the session id and step count. Config and result are
CLI-verified against the real eventum package.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
rnv812 and others added 28 commits July 17, 2026 01:05
…s full-width

- Format/foundations lesson titles no longer repeat 'and how to generate it/one/both' (dead weight in the sidebar, not unique for SEO).
- Overview and Foundations pillar wrap a single Card in <Cards> (2-col grid), leaving it stranded at half width. Drop the grid wrapper so the lone card spans full width.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ints

- Spreader: triangular -> beta (a:4, b:4) - a smooth symmetric bell is a better business-hours shape than a triangle's linear slopes, and it matches the realism/timing lesson which already teaches beta for this.
- Remove the stdout-swap Callout and the cron-vs-daily-curve aside; trim the 'Do I need a Windows host?' FAQ.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Self-review pass: align table timestamp format with the rest of the
page, fix an imprecise transition sentence, and name the json
formatter explicitly in the metric snippet to match the other two
Generate each subsections and back up the FAQ's formatter claim.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add Task 1.3 of the Eventum Learn course (Realism track): a lesson
on correlating log events across a stream via a shared correlation
id and a per-host event.sequence counter, for concurrent flows and
request-response pairs - distinct from the single sequential
session covered by realism/sessions.

The example generator keeps a pool of in-flight network flows in
shared state (a dict keyed by flow_id), advances a per-host
sequence counter, and caps the pool size - deliberately avoiding
mode: fsm dotted-key comparisons (eventum#178). Verified end to
end: pnpm types:check passes, and the generator was run through
eventum generate in sample mode, confirming it validates and
produces a shared flow_id with a strictly increasing event.sequence
per host.

Cross-cutting: realism/meta.json gains the new slug, realism/index
gets a fourth card with count-agnostic pillar framing, and
sessions.mdx gets a bidirectional cross-link.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e count

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…sm siblings

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- New formats-track lesson at content/docs/tutorials/formats/apache-nginx-access-logs.mdx:
  Common Log Format and Combined Log Format field-by-field, Apache vs nginx
  default comparison with the ident/zero-byte/header-inclusive caveats, a
  generated Combined-format access-log stream (template + file + plain
  formatter), FAQ, and Related links.
- formats/meta.json: register the new page.
- formats/index.mdx: add its Card and extend the pillar description.
- tutorials/index.mdx: extend the Formats & schemas blurb.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…authuser

- Rescope the shared-template claim in 'Generate an access log with
  Eventum' to name the zero-byte exception instead of overclaiming
  full sameness between Apache Combined and nginx combined.
- Add a manual nginx-flavored illustration of the captured 304 line
  (0 substituted for the Apache -) so the divergence is shown, not
  only described.
- Split the ident/authuser hardcoding claim: 'matches the caveat
  above' now attaches to ident alone; authuser gets its own
  justification (no HTTP auth modeled) without implying the same
  real-vs-literal vendor split.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add content/docs/tutorials/formats/cloudtrail.mdx (Formats track,
Phase 3, Task 2.2): the Records envelope AWS CloudTrail delivers to
S3, the flat camelCase event fields, and the userIdentity element -
verified against AWS's CloudTrail record contents and userIdentity
references. Teaches the raw schema via two Eventum-generated
templates (AssumeRole, ConsoleLogin), the json formatter for a
per-record stream, and template-batch for reproducing the named
Records array (json-batch cannot produce a named key). Notes that
the cloud-aws-cloudtrail Hub generator emits the downstream
ECS-mapped shape, not this raw one.

Cross-cutting: append cloudtrail to formats/meta.json, add a Card
and update the pillar description in formats/index.mdx, update the
Formats blurb in tutorials/index.mdx.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… claim

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds content/docs/tutorials/formats/auditd.mdx, the last Wave 2 format
lesson: the type=/msg=audit(epoch.ms:serial) record syntax, the
multi-record SYSCALL+EXECVE+CWD+PATH+PROCTITLE event sharing one audit
ID, and hex-encoded fields (SYSCALL a0-a3 raw registers, conditional
EXECVE argument hex, unconditional PROCTITLE hex). Generated via the
template plugin rendering a six-line multi-record block per event with
the file output's plain formatter (not json, since auditd is raw text).
Notes the linux-auditd Hub generator emits the downstream ECS/Auditbeat
shape instead of raw audit.log syntax.

Cross-cutting: registers the page in formats/meta.json, adds a Card and
description update to formats/index.mdx, and updates the Formats blurb
in tutorials/index.mdx.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add the delivery-track lesson for shipping generated syslog to a
collector or SIEM over UDP or TCP: RFC 5426 (UDP, fire-and-forget)
and RFC 6587 (TCP, octet-counting vs non-transparent framing) on the
wire, RFC 5425 TLS, and the eager (tcp) vs fire-and-forget (udp)
failure-mode contrast verified against the plugin source and a local
listener.

Cross-cutting: register in delivery/meta.json, add a card and update
the pillar description in delivery/index.mdx, update the Delivery
blurb in tutorials/index.mdx, and add a reciprocal link from
formats/syslog.mdx's Related section.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…fix log shape

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reframe title/description/hook around the clickstream-data primary
query, add a funnel/bounce theory section with a Mermaid diagram, and
add a FAQ.

Fix eventum#178: the shipped FSM transitions used lt/ge/and comparison
conditions on dotted shared.* keys, which config_loader's
expand_dotted_keys mangles into a nested shape the condition models
reject at validation - the example never actually ran. Rewrite every
transition to the defined-flag pattern already used in
realism/sessions.mdx: each threshold is computed inside the template
and recorded as a boolean flag in shared state (session_done,
ready_to_add, ready_to_checkout); transitions check only defined/
always. Funnel semantics are preserved - landing -> browse (loop) ->
add-to-cart -> checkout -> exit, plus a bounce path for long browsing
with an empty cart - and CLI-verified end to end with no #178 error.

Also fixes two latent inaccuracies found while rewriting: the 'What
you'\''ll build' bullet claimed locals state though the templates
always used shared, and the landing template's faker locale ('en')
wasn'\''t a real Faker locale code (now 'en_US').

Add reciprocal interlinks to realism/sessions, realism/correlated-
events, delivery/clickhouse, and foundations/streaming-vs-bulk,
including small back-links from correlated-events.mdx and
streaming-vs-bulk.mdx, which didn't point back yet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The process state's transitions used lt/ge comparison conditions on
the dotted shared.process_count key, which config_loader's
expand_dotted_keys mangles into a nested {shared: {process_count: N}}
shape the condition models reject at validation - the example never
actually ran.

Rewrite to the defined-flag pattern already used in
realism/sessions.mdx and web-clickstream.mdx: process.jinja computes
the threshold itself and sets a logoff_ready flag in shared once the
counter reaches 4; logon.jinja clears the flag for the next session;
transitions check only defined/always. Session semantics are
unchanged - logon -> privilege -> 4 processes -> logoff, looping with
a new user each cycle - and CLI-verified end to end with no #178
error. Also updates the process-loop description, the transitions
table, and the "Vary session length" going-further bullet, which
suggested building another comparison-based transition.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Telegram lesson's `0 */2 * * * *` put the seconds first, so it fired
60 alerts in the same second every two hours instead of one alert every
two minutes. Use the engine's order, `*/2 * * * * 0`, and say where the
seconds field sits.

The auditd lesson described its cron as ticking once a second without
mentioning `count: 5`, leaving the reader to expect one audit event per
second instead of five.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant