Skip to the content.

Event Schema

Schema version: 4 (AC_SCHEMA_VERSION).

The collector writes UTF-8 JSON Lines. Each line contains one complete JSON object followed by LF. The writer flushes each record before writing the next record.

Envelope

{
  "seq": 12,
  "timestamp": "2026-07-28T10:00:00.000Z",
  "severity": "info",
  "event": "kernel_image_loaded",
  "pid": 1234,
  "details": {},
  "chain": "8f14e45fceea167a5a36dedd4bea2543..."
}
Field Type Contract
seq unsigned integer Collector-local sequence. Starts at 1 for each collector instance.
timestamp string UTC ISO-8601 timestamp with millisecond precision.
severity string info, low, medium, or high.
event string Stable event identifier within the schema version.
pid unsigned integer Target PID, or 0 for collector-wide records.
details object Event-specific payload.
chain string Lowercase 64-character SHA-256 integrity value.

Consumers must order records by seq. Wall-clock timestamps may move backward or forward because of system time changes.

Integrity chain

For exact record body bytes ending immediately before ,"chain":"..."}:

chain[i] = SHA256(chain[i-1] || body[i])

log_segment_opened.details.chain_seed contains the initial chain value for a collector instance. Rotated segments retain sequence and chain continuity. Verify segments from oldest to newest:

python tools\verify_log.py events.jsonl.2 events.jsonl.1 events.jsonl

The chain detects retained-record modification, insertion, removal, and reordering. It does not prevent complete log replacement by a principal that controls the endpoint. Remote systems should persist sequence and chain-head checkpoints during the session.

Severity contract

Severity Technical meaning
info Lifecycle, configuration, health, accounting, or raw telemetry.
low Weak anomaly or operational degradation.
medium Anomaly requiring correlation; known legitimate sources exist.
high Strong process-integrity anomaly; still not an enforcement decision.

Detection records include either "verdict":"signal_only" or "verdict":"telemetry_only".

Collector lifecycle events

log_segment_opened

Severity: info.

Fields:

Field Type
agent string
version string
schema unsigned integer
chain_algorithm "sha256"
chain_seed 64-character hex string
max_bytes unsigned integer
generations unsigned integer
reason optional string; size_limit after rotation

agent_started

Severity: info.

Fields:

Field Type Values
agent string anticheat-collector
version string collector semantic version
schema unsigned integer 4
mode string user_telemetry or hybrid_kernel_user_telemetry
memory_write_access boolean false
terminates_target boolean false
interval_ms unsigned integer configured scan interval
once boolean one-scan mode
scan_budget_ms unsigned integer performance threshold
repeat_interval_ms unsigned integer de-duplication interval
pointer_bits unsigned integer 32 or 64

collector_identity_observed

Severity: info.

Fields:

Deployment must compare the digest with the signed release manifest. If the collector file cannot be identified, collector_identity_unavailable is emitted at medium. This is an identity signal, not in-process attestation; a server nonce remains necessary against collector-process compromise.

waiting_for_process

Severity: info.

Fields:

wait_for_process_timed_out

Severity: info.

Fields:

multiple_process_matches

Severity: low.

Fields:

Use --pid in production integrations to avoid name ambiguity.

target_opened

Severity: info.

Fields:

target_identity_mismatch

Severity: medium.

The image path associated with the opened process does not match the requested executable name. The collector does not scan the process.

allow_root_configured

Severity: info.

Fields:

Directory membership is an operational classification, not cryptographic file identity.

target_exited

Severity: info.

The target process handle entered the signaled state.

agent_stopped

Severity: info.

Fields:

Kernel transport events

kernel_driver_connected

Severity: info.

Fields:

Field Type
protocol_version unsigned integer
event_size unsigned integer
queue_capacity unsigned integer
target_pid unsigned integer

This record confirms protocol validation and successful target registration.

kernel_driver_open_failed

Severity: medium, or high when --require-kernel is active.

Fields:

In --kernel mode the collector continues with user-mode telemetry. In --require-kernel mode it exits.

kernel_target_registration_failed

Severity: high.

The driver rejected IOCTL_AC_SET_TARGET. The payload contains the Win32 error code returned by DeviceIoControl and reason session_registration_rejected.

Kernel callback event envelope

The following event identifiers use the same detail contract:

Fields:

Field Type Contract
driver_sequence unsigned integer Monotonic sequence assigned in the driver.
kernel_timestamp_100ns unsigned integer System time in 100-nanosecond intervals.
type unsigned integer AcDriverEventType.
flags unsigned integer AC_DRIVER_EVENT_FLAG_* bitmask.
parent_pid unsigned integer Available for process creation.
status string NTSTATUS formatted as hexadecimal.
image_base string 64-bit hexadecimal address.
image_size unsigned integer Mapped image size.
path string Bounded image path; may be empty.
source string kernel_callback.
verdict string telemetry_only.

Driver event types:

Value Identifier
1 AC_DRIVER_EVENT_TARGET_CHANGED
2 AC_DRIVER_EVENT_PROCESS_CREATED
3 AC_DRIVER_EVENT_PROCESS_EXITED
4 AC_DRIVER_EVENT_IMAGE_LOADED

kernel_process_created may describe a direct child of the registered target. In that case the envelope pid is the child PID and details.parent_pid is the registered target PID.

Driver event flags:

Bit Identifier
0x00000001 AC_DRIVER_EVENT_FLAG_PATH_TRUNCATED
0x00000002 AC_DRIVER_EVENT_FLAG_SYSTEM_IMAGE
0x00000004 AC_DRIVER_EVENT_FLAG_PATH_UNAVAILABLE

kernel_event_queue_overflow

Severity: medium.

Fields:

The driver overwrites the oldest event when the fixed queue is full.

kernel_event_read_failed

Severity: low.

The IOCTL read or statistics request failed, or the returned protocol data was malformed. The collector closes the driver handle after this record.

User-mode scan events

scan_completed

Severity: info.

Fields:

Field Type
scan_id unsigned integer
duration_ms unsigned integer
modules unsigned integer
module_list_truncated boolean
modules_outside_allowed_roots unsigned integer
regions_visited unsigned integer
executable_regions unsigned integer
suspicious_regions unsigned integer
query_failures unsigned integer
read_failures unsigned integer
probe_bytes unsigned integer
events_emitted unsigned integer
events_suppressed unsigned integer
dedup_entries unsigned integer
dedup_saturated_events unsigned integer
integrity_modules_checked unsigned integer
integrity_modules_unavailable unsigned integer
integrity_blocks_checked unsigned integer
integrity_blocks_modified unsigned integer
integrity_unreadable_blocks unsigned integer
integrity_iat_slots_checked unsigned integer
integrity_iat_hooks unsigned integer
integrity_export_slots_checked unsigned integer
integrity_export_hooks unsigned integer
integrity_modules_partial unsigned integer
integrity_modules_skipped unsigned integer
integrity_file_changes unsigned integer
region_events_omitted unsigned integer
region_scan_truncated boolean
integrity_bytes unsigned integer
integrity_baselines unsigned integer

Consumers should monitor the expected event cadence. Missing scan_completed records indicate a stopped collector, blocked collector, or lost transport.

A sustained integrity_modules_checked of zero while modules is nonzero indicates that module validation is disabled or permanently budget-starved.

scan_coverage_gap

Severity: medium.

Emitted whenever a module or region cap prevents a complete scan. Fields:

scan_budget_exceeded

Severity: low.

Fields:

Operational failure events

Examples:

Win32 failure records contain:

Detection events

module_outside_allowed_roots

Severity: low.

Fields:

Field Type
scan_id unsigned integer
path string
base hexadecimal string
size unsigned integer
file_sha256 string or null
file_size unsigned integer
reason outside_allowed_roots
verdict signal_only
first_seen_scan_id unsigned integer
occurrences unsigned integer
suppressed_since_last_report unsigned integer

suspicious_executable_region

Severity: low, medium, or high.

Fields:

Field Type
scan_id unsigned integer
base hexadecimal string
size unsigned integer
protect unsigned integer
type image, mapped, private, or unknown
backed_by_loaded_module boolean
pe_header boolean
pe_machine hexadecimal string
content_sha256_4k string or null
reason classification identifier
verdict signal_only
first_seen_scan_id unsigned integer
occurrences unsigned integer
suppressed_since_last_report unsigned integer

Classification identifiers:

Reason Default severity Meaning
image_not_in_loader_list high Executable MEM_IMAGE region absent from the loader-visible module index.
mapped_executable_outside_module medium Executable mapped region outside known module ranges.
private_executable medium Executable private memory.
private_writable_executable medium Writable and executable private memory.
writable_executable_inside_module low Writable executable region inside a known module.
executable_memory_unknown_type medium Executable region with an unclassified memory type.

An executable region outside a loader-visible module is emitted as high when the bounded content probe finds a valid PE header.

Module integrity events

The collector reconstructs the bytes the loader is expected to place at each executable section of a loader-visible module, normalises the differences the loader legitimately introduces, and compares 4 KiB blocks by SHA-256.

Normalisation applied before comparison:

The disk-derived baseline is computed once per module load base and cached. Every scan rechecks the file volume, file index, size, and last-write time. Unloaded-module baselines are pruned and unavailable baselines are retried.

module_identity_observed

Severity: info.

Emitted once for every loader-visible module baseline, including modules inside allowed roots. Fields:

The server must compare this identity with the signed application manifest. Directory membership alone is not a trust decision.

module_file_identity_changed

Severity: high.

The file identity changed after its baseline was created. The cached baseline is discarded and rebuilt; the mapped executable bytes are then compared with the new file identity.

module_section_modified

Severity: high.

Fields:

Field Type Contract
path string Module file path.
module_base hexadecimal string Observed load base.
section string Section name, for example .text.
block_rva hexadecimal string RVA of the 4 KiB comparison block.
block_size unsigned integer Compared byte count.
modified_rva hexadecimal string or null RVA of the first differing byte. null when the file changed between baseline and report.
expected_sha256 string Block digest derived from the file on disk.
observed_sha256 string Block digest read from process memory.
expected_bytes string Up to 16 hexadecimal bytes at modified_rva.
observed_bytes string Same window as observed in memory.
reason executable_section_modified  

This is the detection for inline hooks, trampolines, and single-instruction patches that leave the loader module list intact.

Known legitimate producers: packers and DRM that decrypt sections at runtime, debuggers holding software breakpoints, and Windows dynamic value relocations applied to some system images. Validate against a supported build before any rule derived from this event influences a user-facing decision.

import_table_hook

Severity: high.

Fields:

Emitted only when a thunk resolves outside every loader-visible module range. An import redirected into another loaded module is not reported here, because that module is already classified by module_outside_allowed_roots.

export_table_hook

Severity: high.

Fields:

module_integrity_unavailable

Severity: low.

Fields:

A module that cannot be validated is a coverage gap, not a clean result. Unavailable entries are retried periodically. Consumers should track the ratio of unavailable, partial, and skipped modules to checked modules.

De-duplication

The collector emits a finding on first observation. It suppresses equivalent findings until --repeat-interval-ms expires, then emits the finding with updated occurrence counters.

Fingerprints:

The table contains 4096 entries. When saturated, findings are emitted without suppression and dedup_saturated_events increases.

Consumer requirements

Consumers must:

  1. validate the schema version;
  2. parse one line as one record;
  3. order records by seq;
  4. verify the integrity chain before relying on retained local records;
  5. retain unknown event identifiers;
  6. use reason as the stable classifier and severity as a configurable priority;
  7. monitor sequence gaps, kernel dropped-event counters, and scan cadence;
  8. correlate kernel and user-mode records by target PID, session, and time;
  9. keep account or session enforcement outside the collector.