You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
**Release posture:** Early reviewer-stable release with a narrow Linux authentication evidence contract. Parser and detection coverage remain intentionally narrow.
33
35
34
-
Reviewing the project quickly? Start with [`docs/reviewer-path.md`](./docs/reviewer-path.md), [`docs/reviewer-brief.md`](./docs/reviewer-brief.md), and the [`v0.5 Evidence Explainability release note`](./docs/release-v0.5.0.md). The [`quality gates map`](./docs/quality-gates.md) links claims to tests and fixtures. For detection reasoning, follow the [`one-page incident-style case`](./docs/incident-style-case.md), then use the full [`Linux auth brute-force case study`](./docs/case-study-linux-auth-bruteforce.md), [`rule catalog`](./docs/rule-catalog.md), and [`false-positive taxonomy`](./docs/false-positive-taxonomy.md) for depth. For local scale expectations, see the [`performance envelope`](./docs/performance-envelope.md).
36
+
Reviewing the project quickly? Start with [`docs/reviewer-path.md`](./docs/reviewer-path.md), [`docs/reviewer-brief.md`](./docs/reviewer-brief.md), the [`v0.5 Evidence Explainability release note`](./docs/release-v0.5.0.md), and the [`v0.6 Detection Episode Semantics release note`](./docs/release-v0.6.0.md). The [`quality gates map`](./docs/quality-gates.md) links claims to tests and fixtures. For detection reasoning, follow the [`one-page incident-style case`](./docs/incident-style-case.md), then use the full [`Linux auth brute-force case study`](./docs/case-study-linux-auth-bruteforce.md), [`rule catalog`](./docs/rule-catalog.md), and [`false-positive taxonomy`](./docs/false-positive-taxonomy.md) for depth. For local scale expectations, see the [`performance envelope`](./docs/performance-envelope.md).
35
37
36
38
For a shorter external review entry point focused on uncertainty handling, read
37
39
[How LogLens Treats Parser Uncertainty as Evidence](./docs/case-study-parser-uncertainty-as-evidence.md).
@@ -62,7 +64,7 @@ LogLens includes two minimal GitHub Actions workflows:
62
64
-`CI` builds and tests the project on `ubuntu-latest` and `windows-latest`
63
65
-`CodeQL` runs GitHub code scanning for C/C++ on pushes, pull requests, and a weekly schedule
64
66
65
-
Both workflows are intended to stay stable enough to require on pull requests to `main`. Regression coverage is backed by sanitized parser fixture matrices plus golden report-contract fixtures for `report.md`, `report.json`, and optional CSV outputs. Release-facing documentation is split across [`CHANGELOG.md`](./CHANGELOG.md), [`docs/release-process.md`](./docs/release-process.md), [`docs/release-v0.1.0.md`](./docs/release-v0.1.0.md), [`docs/release-v0.3.0.md`](./docs/release-v0.3.0.md), [`docs/release-v0.5.0.md`](./docs/release-v0.5.0.md), and the repository's GitHub release notes. The repository hardening note is in [`docs/repo-hardening.md`](./docs/repo-hardening.md), and vulnerability reporting guidance is in [`SECURITY.md`](./SECURITY.md).
67
+
Both workflows are intended to stay stable enough to require on pull requests to `main`. Regression coverage is backed by sanitized parser fixture matrices plus golden report-contract fixtures for `report.md`, `report.json`, and optional CSV outputs. Release-facing documentation is split across [`CHANGELOG.md`](./CHANGELOG.md), [`docs/release-process.md`](./docs/release-process.md), [`docs/release-v0.1.0.md`](./docs/release-v0.1.0.md), [`docs/release-v0.3.0.md`](./docs/release-v0.3.0.md), [`docs/release-v0.5.0.md`](./docs/release-v0.5.0.md), [`docs/release-v0.6.0.md`](./docs/release-v0.6.0.md), and the repository's GitHub release notes. The repository hardening note is in [`docs/repo-hardening.md`](./docs/repo-hardening.md), and vulnerability reporting guidance is in [`SECURITY.md`](./SECURITY.md).
66
68
67
69
## Threat Model
68
70
@@ -86,8 +88,9 @@ LogLens currently detects:
86
88
87
89
Each rule can emit multiple findings for the same subject when matching
88
90
evidence appears in time-separated detector episodes. Report consumers should
89
-
use `window_start`, `window_end`, and `evidence_event_ids` rather than assuming
90
-
one finding per `rule_id` and subject.
91
+
use `finding_id`, `episode_index`, `window_start`, `window_end`, and
92
+
`evidence_event_ids` rather than assuming one finding per `rule_id` and
93
+
subject.
91
94
92
95
LogLens currently parses and reports these additional auth patterns beyond the core detector inputs:
Copy file name to clipboardExpand all lines: docs/quality-gates.md
+4-1Lines changed: 4 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,7 +15,8 @@ The main review principle is:
15
15
| Parser coverage is visible |[`parser-coverage-notes.md`](./parser-coverage-notes.md), [`tests/fixtures/parser_matrix/noisy_auth_expected.json`](../tests/fixtures/parser_matrix/noisy_auth_expected.json)|`test_parser` compares noisy-auth coverage output to the checked-in expected summary | Reviewer can see parsed lines, skipped blanks, warnings, failure categories, and unknown-pattern buckets |
16
16
| Unsupported evidence does not silently become detector evidence |[`parser-contract.md`](./parser-contract.md), [`rule-catalog.md`](./rule-catalog.md), [`case-study-linux-auth-bruteforce.md`](./case-study-linux-auth-bruteforce.md)|`test_parser` covers unknown-pattern warnings; `test_detector` covers signal-boundary behavior | Reviewer can explain why unsupported lines remain warnings instead of findings |
17
17
| Report artifacts are deterministic |[`report-artifacts.md`](./report-artifacts.md), report-contract fixtures under [`tests/fixtures/report_contracts`](../tests/fixtures/report_contracts)|`test_report_contracts` compares generated `report.md`, `report.json`, `findings.csv`, and `warnings.csv` against golden fixtures | Reviewer can regenerate reports and see schema or text changes as explicit snapshot diffs |
18
-
| Findings are explainable |[`rule-catalog.md`](./rule-catalog.md), [`report-artifacts.md`](./report-artifacts.md)|`test_report` checks JSON finding fields; report-contract fixtures lock `rule_id`, `window_start`, `window_end`, `threshold`, `observed_count`, `grouping_key`, `evidence_event_ids`, and `verdict_boundary`| Reviewer can trace a finding from rule context back to source line IDs and see the non-verdict boundary |
18
+
| Findings are explainable |[`rule-catalog.md`](./rule-catalog.md), [`report-artifacts.md`](./report-artifacts.md)|`test_report` checks JSON finding fields; report-contract fixtures lock `finding_id`, `episode_index`, `rule_id`, `window_start`, `window_end`, `threshold`, `observed_count`, `grouping_key`, `evidence_event_ids`, and `verdict_boundary`| Reviewer can trace a finding from rule context back to source line IDs and see the non-verdict boundary |
19
+
| Detection episodes are explicit |[`release-v0.6.0.md`](./release-v0.6.0.md), [`rule-catalog.md`](./rule-catalog.md#detection-episode-semantics), [`separated_bursts_syslog`](../tests/fixtures/report_contracts/separated_bursts_syslog)|`test_detector` covers separated episodes, stable identity under unsorted input order, and inclusive boundary windows; `test_report_contracts` locks the two-finding separated-burst report | Reviewer can see one rule and subject emit two non-overlapping findings without treating either as an incident verdict |
19
20
| False-positive boundaries are visible |[`rule-catalog.md`](./rule-catalog.md), [`case-study-linux-auth-bruteforce.md`](./case-study-linux-auth-bruteforce.md)| Documentation review gate; detector tests ensure unsupported evidence does not inflate counts | Reviewer can state NAT, internal scanner, lab replay, shared bastion, scheduled admin task, and malformed replay boundaries |
20
21
| Parser failure taxonomy is exposed |[`parser-contract.md`](./parser-contract.md), [`parser-conformance-matrix.md`](./parser-conformance-matrix.md), [`report-artifacts.md`](./report-artifacts.md)|`test_parser`, `test_report`, `test_cli`, and `test_report_contracts` cover `failure_categories` and warning `category` output | Reviewer can distinguish timestamp, program, known-program unknown-message, malformed-source-IP, and unsupported-PAM failures |
21
22
| Local scale expectations are reproducible |[`performance-envelope.md`](./performance-envelope.md), [`scripts/benchmark-performance-envelope.ps1`](../scripts/benchmark-performance-envelope.ps1)|`pwsh -File scripts/benchmark-performance-envelope.ps1` regenerates sanitized benchmark inputs and local summary artifacts | Reviewer can reproduce the 1k/10k/100k-line envelope and understand its caveats |
@@ -41,6 +42,8 @@ update the matching evidence surface in the same pull request:
This release note describes the v0.6 report and detector contract. It does not
6
+
add new detection rules. It makes repeated time-separated findings for the same
7
+
rule subject explicit and reviewable.
8
+
9
+
## What Changed
10
+
11
+
- A single `rule_id`, `subject_kind`, and `subject` can emit multiple
12
+
non-overlapping findings when evidence appears in separated detector
13
+
episodes.
14
+
- JSON reports now use `schema: loglens.report.v3` and `schema_version: 3`.
15
+
- JSON findings include stable finding identity fields:
16
+
-`finding_id`
17
+
-`episode_index`
18
+
- The separated-burst contract fixture demonstrates one source IP producing two
19
+
distinct brute-force findings in one report.
20
+
21
+
## Stable JSON Contract
22
+
23
+
`loglens.report.v3` keeps the v0.5 explainability fields and adds:
24
+
25
+
| Field | Meaning |
26
+
| --- | --- |
27
+
|`finding_id`| Deterministic report-local identifier for the selected finding, derived from the rule, subject, selected window, counts, and evidence event IDs. |
28
+
|`episode_index`| 1-based sequence number within the same `rule_id`, `subject_kind`, and `subject`. |
29
+
30
+
Existing v2 finding fields remain part of the stable explainability surface:
| First threshold crossing | Used to decide that an episode candidate is eligible to emit a finding. It is not necessarily the reported window. |
52
+
| Maximal window | The reported window is the highest-signal sliding window within the episode candidate. |
53
+
| Non-overlapping windows | One rule and subject can emit multiple findings, but selected episode candidates do not reuse the same matching signals. |
54
+
| Cooldown merge | Signals separated by an idle gap less than or equal to the rule window stay in the same episode candidate. A larger gap starts a new candidate. |
55
+
56
+
Episode splitting is a reporting model. It is not an incident boundary.
The stable finding explainability surface for `loglens.report.v2` is:
45
+
The stable finding explainability surface for `loglens.report.v3` is:
46
46
47
+
-`finding_id`
47
48
-`rule_id`
49
+
-`episode_index`
48
50
-`subject_kind`
49
51
-`subject`
50
52
-`grouping_key`
@@ -61,10 +63,20 @@ fixtures explicitly.
61
63
62
64
`evidence_event_ids` are deterministic local event identifiers derived from the source line number, formatted as `line:<number>`. They let reviewers trace a finding back to the normalized input events that satisfied the rule window without implying global event identity.
63
65
66
+
`finding_id` is a deterministic report-local finding identifier derived from
67
+
the rule, subject, selected window, counts, and evidence event IDs. It is
68
+
stable for the same normalized evidence and rule output, but it is not a global
69
+
case identifier.
70
+
71
+
`episode_index` is a 1-based sequence number within one `rule_id`,
72
+
`subject_kind`, and `subject`. It is meant for reviewer navigation when a rule
73
+
emits more than one finding for the same subject.
74
+
64
75
Consumers should not assume that `rule_id` plus `subject` is unique within a
65
76
report. A rule can emit multiple findings for the same subject when matching
66
-
evidence appears in time-separated detector episodes. Use `window_start`,
67
-
`window_end`, and `evidence_event_ids` to distinguish episode-level findings.
77
+
evidence appears in time-separated detector episodes. Use `finding_id`,
78
+
`episode_index`, `window_start`, `window_end`, and `evidence_event_ids` to
79
+
distinguish episode-level findings.
68
80
69
81
`verdict_boundary` is a stable token that states what the finding must not be
70
82
read as. It keeps machine-readable findings aligned with LogLens's triage
@@ -79,7 +91,20 @@ Warning objects contain the original `line_number`, parser `category`, and parse
79
91
`schema` and `schema_version` identify the report artifact contract, not the
80
92
application release. They are intended for downstream tooling that needs a
81
93
stable way to reject incompatible report shapes. The current JSON contract is
82
-
`loglens.report.v2` with `schema_version` set to `2`.
94
+
`loglens.report.v3` with `schema_version` set to `3`.
95
+
96
+
### Schema v2 to v3 Migration
97
+
98
+
`loglens.report.v3` keeps the v2 finding explainability fields and adds:
99
+
100
+
-`finding_id`
101
+
-`episode_index`
102
+
103
+
Downstream consumers should treat `schema` and `schema_version` as the report
104
+
shape gate. Consumers that keyed findings by `rule_id` and `subject` should
105
+
move to `finding_id`, or include `episode_index`, `window_start`, `window_end`,
106
+
and `evidence_event_ids` in their own composite key. The optional CSV contract
107
+
is unchanged in v3.
83
108
84
109
Parser failure categories are stable reviewer-facing buckets for unsupported
85
110
lines: `unknown_timestamp`, `unknown_program`,
@@ -111,6 +136,7 @@ The report contracts are backed by generated fixture artifacts:
The enforcement lives in [`tests/test_report_contracts.cpp`](../tests/test_report_contracts.cpp). Parser or rule changes that alter report artifacts must update these snapshots explicitly. This includes changes to stable finding explainability fields, parser coverage fields, warning categories, CSV columns, or Markdown report layout. The focused report writer tests live in [`tests/test_report.cpp`](../tests/test_report.cpp).
0 commit comments