Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0ca530b
fix: unify record validation across CLI commands
DavidJBianco Sep 15, 2026
c7a7517
fix: account for incomplete Windows XML wrappers
DavidJBianco Sep 15, 2026
3c4323f
fix: validate all successful CONNECT responses
DavidJBianco Sep 15, 2026
ef7175b
fix: route artifact validation and surface evaluator failures
DavidJBianco Sep 15, 2026
9c89e83
fix: distinguish malformed evidence from evaluator faults
DavidJBianco Sep 15, 2026
cd6463f
fix: decode legacy validation snapshots for checkpoint recovery
DavidJBianco Sep 15, 2026
68cd5dd
fix: parse Splunk web and proxy evidence during evaluation
DavidJBianco Sep 15, 2026
54cf6ac
test: record validation compatibility and readiness evidence
DavidJBianco Sep 15, 2026
2c899b0
fix: normalize anonymous Splunk identities before Snare work
DavidJBianco Sep 15, 2026
1e91cf1
fix: preserve Windows facts in typed Snare projections
DavidJBianco Sep 15, 2026
2526cda
fix: resolve checkpoint scratch paths before mixed-format hydration
DavidJBianco Sep 15, 2026
7b2ea36
test: enforce Snare extraction and generation compatibility
DavidJBianco Sep 15, 2026
e9beeca
docs: record Snare field preservation and compatibility evidence
DavidJBianco Sep 15, 2026
2619b86
fix: preserve failed logon requester semantics
DavidJBianco Sep 15, 2026
1146b5a
fix: normalize host log newlines across checkpoints
DavidJBianco Sep 15, 2026
6ed3c1e
Merge pull request #421 from Cisco-Talos/codex/record-validation
DavidJBianco Sep 15, 2026
d25e71b
fix: update SOF-ELK parser pin
DavidJBianco Sep 16, 2026
5656045
Merge pull request #422 from Cisco-Talos/codex/sof-elk-main-pin
DavidJBianco Sep 16, 2026
d04342f
chore: sync main into dev before 2.1.1 release
DavidJBianco Sep 16, 2026
107c47b
chore: bump version to 2.1.1
DavidJBianco Sep 16, 2026
3961569
test: update SOF-ELK Snare parent digest
DavidJBianco Sep 16, 2026
e876143
chore: finalize 2.1.1 release notes
DavidJBianco Sep 16, 2026
f5847ed
test: update SOF-ELK Sysmon parent digest
DavidJBianco Sep 16, 2026
2279d81
chore: complete 2.1.1 compatibility notes
DavidJBianco Sep 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ handoff details in `docs/worklog/` until they are no longer useful.
and 95%+ for the core generation engine.

**Format Support:**
- json-logic-qubit for format definition validation rules
- Pydantic-validated bounded record predicates for format validation
- Standard library json/csv for text formats
- XML output via string templates (no python-evtx dependency)

Expand Down Expand Up @@ -701,7 +701,7 @@ All emitters inherit from `LogEmitter` ABC (`src/evidenceforge/generation/emitte

### Format Definitions

Format definitions are YAML files in `src/evidenceforge/config/formats/`, not code. Each defines fields, variants, JSON Logic validators, and Jinja2 output templates. Loaded via `formats/loader.py`. Adding a new format requires only a new YAML file.
Format definitions are YAML files in `src/evidenceforge/config/formats/`, not code. Each defines fields, variants, typed record validators, and Jinja2 output templates. Loaded via `formats/loader.py`. Adding a new format requires only a new YAML file.

### YAML Data Directory Convention

Expand Down
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,41 @@ Detailed development history for the EvidenceForge project. Transferred from TOD

## Unreleased

## v2.1.1 (2026-09-16)

This patch release makes record validation representation-aware, preserves complete Windows Snare
facts, corrects failed-logon requester semantics, and updates the external parser harness to the
current validated SOF-ELK rules. Existing authored schemas and public APIs remain unchanged.

**Record validation and evaluation**

- Replace the external JSON-logic dependency with package-owned typed record predicates and apply
the same validation contracts across CLI preflight, generation, and evaluation. Cover incomplete
Windows XML wrappers and every successful proxy CONNECT response (`0ca530b2`, `c7a7517f`,
`3c4323fb`).
- Route artifacts to their native validators, distinguish malformed evidence from evaluator
execution faults, and add reproducible compatibility, mutation, and readiness evidence
(`ef7175b8`, `9c89e83d`, `54cf6ac3`).
- Parse Splunk web and proxy evidence during evaluation and normalize anonymous identities before
applying Windows Snare projections (`68cd5dd8`, `2c899b06`).

**Windows Snare and external parser compatibility**

- Preserve canonical Windows facts through typed Snare projections for all supported event
variants, with frozen compatibility tests and documented field dispositions (`1e91cf1b`,
`7b2ea369`, `e9beeca2`, `39615693`, `f5847ed8`).
- Update the SOF-ELK pin and harness for the newer parser filenames and scoped generic-syslog probe
tags while retaining fatal handling for malformed source records (`d25e71ba`).

**Checkpoint and authentication correctness**

- Decode recognized legacy validation snapshots and resolve checkpoint scratch paths before
mixed-format hydration (`cd6463f7`, `2526cda3`).
- Preserve failed-logon requester identity independently from the authentication target and domain
controller, including coherent optional 4771 and 4776 evidence (`2619b865`).
- Normalize ordinary host-log framing to LF so Windows checkpoint resume matches uninterrupted
generation (`1146b5a3`).

## v2.1.0 (2026-09-14)

This release adds native Windows generation and checkpoint recovery on local NTFS, including
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,12 @@ composition and lifecycle contract, see

## Data Quality Evaluation

Input validation and evidence evaluation are separate. `validate-config`, `validate`, `resolve`,
and `generate` preflight packaged contracts; `eval` checks emitted records. Acceptance requires
100% schema compliance and objective record correctness. Realism diagnostics do not relax these
gates. Existing scenario/overlay/pack interfaces remain supported; rules and thresholds are
package-owned. See [record validation](docs/reference/RECORD_VALIDATION.md).

EvidenceForge can evaluate a generated bundle across four complementary quality pillars:

| Pillar | Weight | What it measures |
Expand Down
15 changes: 15 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ without turning `TODO.md` back into a high-conflict work journal.

### Active and Near-Term

- [x] **P1** Preserve Windows facts in Snare and validate its native representation. All 43 variants
have typed projections and field-level gates against both frozen SOF-ELK revisions; historical
ambiguity remains explicit. See the [validation worklog](docs/worklog/2026-09-15-record-validation.md).
- [ ] **P2** Follow up upstream Snare extraction limitations: ParentImage/CurrentDirectory patterns
require backslashes after the pipeline replaces them, and POSINT patterns omit zero ports.
EvidenceForge preserves these raw values; structured indexing needs upstream parser work and
renewed compatibility gates. No upstream changes are part of this branch.
- [ ] **P1 — deferred** Investigate the existing iteration-scenario temporal-integrity failure
(40/48 visible events, 83.33%, below the unchanged 85% gate). Separate expected-time matching,
ordering, missing traces, and source-observation timing before assigning fixes to their owning
layer. Baseline/candidate evidence bytes match; this predates the validation refactor and is
deferred from this branch by user decision. See the same worklog for the eight findings.
- [ ] **P2** Investigate generation coverage for Zeek packet-filter/reporter/weird diagnostic
sources separately from their dedicated renderer/parser/validator fixture coverage.

- Prepare the 2.1.0 release from `dev` to `main`, including the version/changelog bump and routine,
coverage, slow, and checkpoint portability gates. See the
[release worklog](docs/worklog/2026-09-14-2.1.0-release.md).
Expand Down
2 changes: 1 addition & 1 deletion commands/eforge/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,4 @@ selected. Use composition explanation when pack and overlay precedence matters.

State the project root, whether the operation remained read-only, files changed, directly implied
repairs, validation result, and unresolved pre-existing or semantic decisions. Mention the effective
merge behavior when it could surprise the user.
merge behavior when it could surprise the user. Read `/eforge:references:record-validation` for validation policy and compatibility.
8 changes: 7 additions & 1 deletion commands/eforge/evaluate.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ Treat these exits as distinct outcomes:
- `0`: parse the JSON report; its acceptance verdict may still be `FAIL` or `INDETERMINATE`.
- `1`: input/path error or a legacy dataset missing `--scenario`; correct the invocation.
- `2`: scenario/include, bundle-integrity, or comparison-mismatch error; report it and stop.
- `22`: evaluation engine or capacity failure; report the diagnostic without inventing scores.
- `22`: evaluation engine, scoring-pillar, or capacity failure; no completed report is emitted.
Diagnostics use stderr; successful JSON stdout contains exactly one report object.
- `130`: interrupted; report that no completed evaluation is available.

### Override gates
Expand Down Expand Up @@ -148,3 +149,8 @@ emitter layer.

Finish with the verdict, available score, failed gates, strongest evidence, and smallest useful next
action. Keep recommendations read-only unless the user asks to act.

## Validation policy

Read `/eforge:references:record-validation` when explaining input checks, evidence acceptance,
structured findings, or compatibility with existing projects.
2 changes: 2 additions & 0 deletions commands/eforge/generate.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,5 @@ Read only the smallest relevant reference when exact paths, fields, joins, or li
- `/eforge:references:evidence-network-ids` for Zeek, IDS, and Cisco ASA.
- `/eforge:references:evidence-web-email` for HTTP/files, web, proxy, email, and SMTP.
- `/eforge:references:evidence-endpoint-linux` for eCAR, Linux syslog, and bash history.

Read `/eforge:references:record-validation` for validation policy and compatibility.
5 changes: 5 additions & 0 deletions commands/eforge/industry-pack.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,8 @@ when the user requests an example or regression fixture.
Return the exact reference, version rationale, files and exports authored, final digest, validation
result, consumer-harness result, and specific runtime evidence observed. Identify any intentionally
empty catalog and why it remains empty.

## Validation policy

Read `/eforge:references:record-validation` when explaining input checks, evidence acceptance,
structured findings, or compatibility with existing projects.
5 changes: 5 additions & 0 deletions commands/eforge/organization-pack.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,8 @@ only when the user requests an example or regression fixture.
Return the exact organization reference, exact industry dependencies, version rationale, standalone
or partial status, files and exports authored, final digest, validation result, consumer-harness
result, and representative runtime evidence observed. State what remains scenario-owned.

## Validation policy

Read `/eforge:references:record-validation` when explaining input checks, evidence acceptance,
structured findings, or compatibility with existing projects.
5 changes: 5 additions & 0 deletions commands/eforge/pack-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,8 @@ set`; never derive identity from a username, hostname, repository, or pack name.
`eforge pack hydrate publisher:type:name@version --scope project|user --json`.

`.efpack` files are local release artifacts; this skill does not upload to a registry or remote host.

## Validation policy

Read `/eforge:references:record-validation` when explaining input checks, evidence acceptance,
structured findings, or compatibility with existing projects.
5 changes: 5 additions & 0 deletions commands/eforge/pack.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,8 @@ Return:
5. Final digest and exports.
6. Versioning or dependency decisions.
7. The specialized skill to use next when substantive authoring remains.

## Validation policy

Read `/eforge:references:record-validation` when explaining input checks, evidence acceptance,
structured findings, or compatibility with existing projects.
18 changes: 18 additions & 0 deletions commands/eforge/references/checkpoint-recovery.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ description: "Checkpoint inspection, drift verification, and safe resume referen
Read this reference for interrupted generation, resume compatibility, environment drift, recovery
wheels, OOB authorization, or a verifier that appears idle.

## Contents

- [Preserve first](#preserve-first)
- [Interpret compatibility](#interpret-compatibility)
- [Migration and provenance](#migration-and-provenance)
- [uv tool recovery builds](#uv-tool-recovery-builds)
- [Validation metadata upgrades](#validation-metadata-upgrades)

## Preserve First

Stop the generator before copying or inspecting a bundle. Preserve a filesystem snapshot or backup
Expand Down Expand Up @@ -92,3 +100,13 @@ bundle back.
When a recovery wheel is only an exact-behavior backport, keep using it for that interrupted run.
Do not replace its immutable release tag or infer that a displayed package version alone identifies
the source build; compare the recorded build digest.

## Validation metadata upgrades

Compatible recovery recognizes the exact package-owned validation snapshots from the pre-typed-rule
2.1.0 baseline. It decodes those validation documents in memory only when their native rendering
templates still match. Stored checkpoint and resolved input documents remain immutable; arbitrary
old internal rule syntax remains unsupported. The runtime's exact correctness policy applies when
subsequently evaluating evidence. This decoder does not bypass checkpoint integrity, hydration,
provenance, or resume-policy checks. Dependency/build drift still means `not-guaranteed` output
equivalence, even when a particular resumed run matches uninterrupted evidence byte for byte.
4 changes: 2 additions & 2 deletions commands/eforge/references/config-evaluation.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ engine-owned. `.eforge/config/evaluation`, pack catalogs, scenario YAML, and env
cannot replace them.

Packaged rule files live under `src/evidenceforge/config/evaluation/` and include thresholds,
co-occurrence, distributions, causal/timing checks, and cross-source rules. They must remain aligned
with evaluator code, parsers, ground-truth contracts, observation semantics, and format definitions.
distributions, causal/timing checks, and cross-source rules. They must remain aligned
with typed record rules in `config/formats/`, evaluator code, parsers, ground-truth contracts, observation semantics, and format definitions.

Use the evaluate skill to run or interpret `eforge eval`. A request to change scoring policy is a
source-code development task, not an `eforge-config` overlay task. For an authorized developer
Expand Down
3 changes: 3 additions & 0 deletions commands/eforge/references/config-formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ documentation, and round-trip tests together.

Do not place format YAML under `.eforge/config`, expose it through a pack, or treat a copied package
file as a supported project override.

Field schemas and bounded record predicates are validated with Pydantic at load time. Legacy JSON
Logic is no longer supported. See `/eforge:references:record-validation` for acceptance policy.
67 changes: 67 additions & 0 deletions commands/eforge/references/record-validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Input validation and evidence validation

`validate-config` checks effective supported configuration and packaged record contracts.
`validate`, `resolve`, and `generate` preflight the required package contracts alongside their
existing scenario and configuration checks. Passing input validation does not mean that generated
evidence has been evaluated. `generate` does not automatically run dataset evaluation.

Run `eforge eval <bundle> --format json` to assess evidence. Schema compliance and objective
record correctness require 100%: a single malformed or contradictory record fails acceptance.
A completed report still exits 0 even when `acceptance_passed` is false. Engine failures exit 22
and must never be presented as successful acceptance. Existing report keys remain; sub-scores
also expose bounded `sample_findings` with rule ID, format/variant, fields, category, severity,
outcome, and message. Counts cover all records, not just these diagnostic samples.

Realism diagnostics are separate from objective correctness. Sparse endpoint metadata, zero-duration
observations, and unusual certificate validity intervals can be legitimate evidence. Specialized
lifecycle, collection-visibility, cryptographic, and cross-record evaluators retain their ownership;
partial observation does not excuse contradictions within a visible record.

Rules and thresholds are package-owned developer interfaces. They cannot be overridden in scenario
YAML, `.eforge/config`, pack catalogs, or environment variables. Supported Scenario 1.0/2.0, overlay
syntax and merge precedence, pack/release schemas, and project-root resolution are unchanged.
Do not add a threshold override or weaken a rule to make a dataset pass.


## Validation coverage and execution failures

Every parser source has an explicit package-owned validation route. Native log sources require a
format schema; email artifact manifest entries use structural artifact validation and retain their
specialized email consistency checks. An unknown source or unavailable native schema is an engine
error, never an implicitly passing record. Empty email sections and optional metadata remain valid.

A failed scoring pillar stops evaluation with exit 22 and no quality report. Successful JSON mode
writes one report object to stdout; warnings and progress go to stderr. A completed report may still
fail acceptance and exit 0. Use `--verbose` for an execution-failure traceback. Do not interpret a
partial collection of pillar scores as an overall quality result.

Developer coverage checks reconcile all parser routes, native schemas, emitter registrations, and
rendering paths. Routine tests render, parse, and validate every native format and supported Windows
variant. The slow iteration-scenario gate checks fresh-process byte equality, bundle integrity,
complete evaluation, and exact record validation, including email artifacts and observation gaps.

Returned `evaluation_error` findings abort evaluation just like raised exceptions, including
realism diagnostics and artifact validators. The diagnostic identifies the rule, source, variant,
and fields. The library `validate_event` API still returns `valid=False`, errors, and findings;
the scoring boundary raises the execution error.

Malformed records remain in source counts and exact schema acceptance. After those failures are
recorded, malformed records are omitted from the typed distribution and cross-source indexes used
by later pillars. Those pillar scores describe the usable evidence; they cannot override failed
schema acceptance. Cross-field contradictions in otherwise well-typed records remain available to
specialized evaluators. Missing optional observations and source-native conversions retain their
existing semantics.

## SOF-ELK® Windows Snare

Snare has an explicit representation contract. Current output preserves available canonical Windows
fields and compatible SOF-ELK display aliases; XML requirements remain unchanged for XML. A field
present in raw Snare is not necessarily indexed by SOF-ELK. Historical repeated account labels are
retained without inventing subject/target scope. Inspect `unavailable_check_count` and
`sample_unavailable_findings` for historical coverage limits; do not describe those checks as passed.
Malformed fields and contradictory aliases still fail exact acceptance. Projection definitions,
like rules and thresholds, are package-owned and are not configuration overlays. Temporal-integrity
findings remain independent of representation/schema results.
The frozen upstream parsers do not index zero ports or the preserved ParentImage/CurrentDirectory
paths; do not infer absence of those facts from missing indexed fields. Supplied Sysmon UtcTime
remains distinct from TimeCreated and controls the upstream event timestamp.
2 changes: 2 additions & 0 deletions commands/eforge/scenario.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,5 @@ generated output.

If the user wants logs, hand off to `/eforge generate`. If they want a focused validation or repair
explanation, hand off to `/eforge validate`. Do not silently generate logs as part of authoring.

Read `/eforge:references:record-validation` for validation policy and compatibility.
2 changes: 2 additions & 0 deletions commands/eforge/validate.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,5 @@ eforge validate <scenario> --json --oob-host <exact-host>

Validation makes no callback. A fresh matching flag is independently required for each validate,
resolve, or generate invocation that needs it.

Read `/eforge:references:record-validation` for validation policy and compatibility.
10 changes: 8 additions & 2 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -954,7 +954,7 @@ checkpoint publication.

### Format Definition System

Log formats are defined declaratively in YAML files (`src/evidenceforge/formats/definitions/`), not in code:
Log formats are defined declaratively in YAML files (`src/evidenceforge/config/formats/`), not in code:

```yaml
# Example: zeek_conn.yaml
Expand All @@ -974,10 +974,16 @@ fields:
```

Each format YAML defines fields (name, type, constraints), event variants (for multi-event formats like Windows Security), and Jinja2 output templates. Adding a new log format requires:
1. A new YAML definition in `formats/definitions/`
1. A new YAML definition in `config/formats/`
2. An emitter class in `generation/emitters/`
3. A parser class in `evaluation/parsers/` (for eval support)

Record contracts use Pydantic schemas and a bounded evaluator, with cached field plans per
format/variant. Dotted source field names are literal keys. Findings carry structured categories;
schema/correctness failures gate every record at 100%, while context-dependent realism rules stay
diagnostic. JSON Logic and the separate co-occurrence interpreter have been removed. See
[record validation](reference/RECORD_VALIDATION.md) for the developer contract.

### Evaluation Engine

The evaluation system (`src/evidenceforge/evaluation/`) scores generated data across 4 pillars:
Expand Down
3 changes: 3 additions & 0 deletions docs/design/PRD.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
> Historical design: the JSON Logic sketches below are superseded by
> [the typed record contract](../reference/RECORD_VALIDATION.md).

# PRD: EvidenceForge

> **Naming conventions:** "EvidenceForge" is the product name, `evidenceforge` is the Python package name, `eforge` is the CLI command name.
Expand Down
Loading