Skip to content

Commit 402d167

Browse files
committed
feat(release): align v1.2 architecture cohesion
1 parent 5622deb commit 402d167

84 files changed

Lines changed: 7454 additions & 6556 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 86 additions & 77 deletions
Large diffs are not rendered by default.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"tool_version": "1.2.0",
3+
"demo_id": "window",
4+
"input_digest": "sha256:e8771283a83c146a2cffce5fe316c1408200b6d7717cbb6d074334aa891672f3",
5+
"config_digest": "sha256:6bffef106b0fcdb04d54e3aac8fe5b4b800bf228ad03fe988861486691c76f65",
6+
"artifact_schema_versions": {
7+
"run_manifest": "run-manifest/v1",
8+
"telemetry_summary": "telemetry-summary/v1"
9+
},
10+
"execution_mode": "synthetic-local"
11+
}
Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,34 @@
1-
{
2-
"input_path": "data/raw/richer_sample_events.jsonl",
3-
"output_dir": "data/processed/richer_sample",
4-
"normalized_event_count": 28,
5-
"window_count": 24,
6-
"feature_row_count": 24,
7-
"alert_count": 8,
8-
"triggered_rule_names": [
9-
"high_error_rate",
10-
"high_severity_spike",
11-
"login_fail_burst",
12-
"persistent_high_error",
13-
"rare_event_repeat_malware_alert",
14-
"rare_event_repeat_policy_denied"
15-
],
16-
"triggered_rule_counts": {
17-
"high_error_rate": 2,
18-
"high_severity_spike": 1,
19-
"login_fail_burst": 1,
20-
"persistent_high_error": 2,
21-
"rare_event_repeat_malware_alert": 1,
22-
"rare_event_repeat_policy_denied": 1
23-
},
24-
"cooldown_seconds": 120,
25-
"generated_artifacts": [
26-
"data/processed/richer_sample/features.csv",
27-
"data/processed/richer_sample/alerts.csv",
28-
"data/processed/richer_sample/summary.json",
29-
"data/processed/richer_sample/event_count_timeline.png",
30-
"data/processed/richer_sample/error_rate_timeline.png",
31-
"data/processed/richer_sample/alerts_timeline.png"
32-
]
33-
}
1+
{
2+
"input_path": "data/raw/richer_sample_events.jsonl",
3+
"output_dir": "data/processed/richer_sample",
4+
"normalized_event_count": 28,
5+
"window_count": 24,
6+
"feature_row_count": 24,
7+
"alert_count": 8,
8+
"triggered_rule_names": [
9+
"high_error_rate",
10+
"high_severity_spike",
11+
"login_fail_burst",
12+
"persistent_high_error",
13+
"rare_event_repeat_malware_alert",
14+
"rare_event_repeat_policy_denied"
15+
],
16+
"triggered_rule_counts": {
17+
"high_error_rate": 2,
18+
"high_severity_spike": 1,
19+
"login_fail_burst": 1,
20+
"persistent_high_error": 2,
21+
"rare_event_repeat_malware_alert": 1,
22+
"rare_event_repeat_policy_denied": 1
23+
},
24+
"cooldown_seconds": 120,
25+
"generated_artifacts": [
26+
"data/processed/richer_sample/features.csv",
27+
"data/processed/richer_sample/alerts.csv",
28+
"data/processed/richer_sample/summary.json",
29+
"data/processed/richer_sample/run_manifest.json",
30+
"data/processed/richer_sample/event_count_timeline.png",
31+
"data/processed/richer_sample/error_rate_timeline.png",
32+
"data/processed/richer_sample/alerts_timeline.png"
33+
]
34+
}

data/processed/run_manifest.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"tool_version": "1.2.0",
3+
"demo_id": "window",
4+
"input_digest": "sha256:c08795a6a3c361a3339414c5a8441fb74c58f027c96931dbdc0da28560e132ac",
5+
"config_digest": "sha256:a6107a2a732e8f4bf03572e9e86697ce1daa0eed1871724d0b44ec677f924b37",
6+
"artifact_schema_versions": {
7+
"run_manifest": "run-manifest/v1",
8+
"telemetry_summary": "telemetry-summary/v1"
9+
},
10+
"execution_mode": "synthetic-local"
11+
}

data/processed/summary.json

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,34 @@
1-
{
2-
"input_path": "data/raw/sample_events.jsonl",
3-
"output_dir": "data/processed",
4-
"normalized_event_count": 41,
5-
"window_count": 24,
6-
"feature_row_count": 24,
7-
"alert_count": 12,
8-
"triggered_rule_names": [
9-
"high_error_rate",
10-
"high_severity_spike",
11-
"login_fail_burst",
12-
"persistent_high_error",
13-
"rare_event_repeat_malware_alert",
14-
"source_spread_spike"
15-
],
16-
"triggered_rule_counts": {
17-
"high_error_rate": 3,
18-
"high_severity_spike": 2,
19-
"login_fail_burst": 2,
20-
"persistent_high_error": 3,
21-
"rare_event_repeat_malware_alert": 1,
22-
"source_spread_spike": 1
23-
},
24-
"cooldown_seconds": 60,
25-
"generated_artifacts": [
26-
"data/processed/features.csv",
27-
"data/processed/alerts.csv",
28-
"data/processed/summary.json",
29-
"data/processed/event_count_timeline.png",
30-
"data/processed/error_rate_timeline.png",
31-
"data/processed/alerts_timeline.png"
32-
]
33-
}
1+
{
2+
"input_path": "data/raw/sample_events.jsonl",
3+
"output_dir": "data/processed",
4+
"normalized_event_count": 41,
5+
"window_count": 24,
6+
"feature_row_count": 24,
7+
"alert_count": 12,
8+
"triggered_rule_names": [
9+
"high_error_rate",
10+
"high_severity_spike",
11+
"login_fail_burst",
12+
"persistent_high_error",
13+
"rare_event_repeat_malware_alert",
14+
"source_spread_spike"
15+
],
16+
"triggered_rule_counts": {
17+
"high_error_rate": 3,
18+
"high_severity_spike": 2,
19+
"login_fail_burst": 2,
20+
"persistent_high_error": 3,
21+
"rare_event_repeat_malware_alert": 1,
22+
"source_spread_spike": 1
23+
},
24+
"cooldown_seconds": 60,
25+
"generated_artifacts": [
26+
"data/processed/features.csv",
27+
"data/processed/alerts.csv",
28+
"data/processed/summary.json",
29+
"data/processed/run_manifest.json",
30+
"data/processed/event_count_timeline.png",
31+
"data/processed/error_rate_timeline.png",
32+
"data/processed/alerts_timeline.png"
33+
]
34+
}
Lines changed: 99 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,78 @@
1-
# AI-Assisted Detection Demo
2-
3-
This demo is part of `telemetry-lab` and is intentionally framed as a portfolio-grade security engineering prototype.
4-
5-
It demonstrates constrained AI-assisted case drafting for SOC-style workflows, not autonomous detection or response.
6-
7-
It combines deterministic detections with a tightly constrained LLM stage:
8-
9-
- the rules decide which activity is interesting
10-
- the grouping logic decides which hits belong in the same case
11-
- the LLM is limited to structured summaries, likely causes, uncertainty notes, and suggested next steps
12-
13-
The LLM does **not** make final incident decisions, modify rules, call tools, or execute response actions. Human verification is always required.
14-
1+
# AI-Assisted Detection Demo
2+
3+
This demo is part of `telemetry-lab` and is intentionally framed as a portfolio-grade security engineering prototype.
4+
5+
It demonstrates constrained AI-assisted case drafting for SOC-style workflows, not autonomous detection or response.
6+
7+
It combines deterministic detections with a tightly constrained LLM stage:
8+
9+
- the rules decide which activity is interesting
10+
- the grouping logic decides which hits belong in the same case
11+
- the LLM is limited to structured summaries, likely causes, uncertainty notes, and suggested next steps
12+
13+
The LLM does **not** make final incident decisions, modify rules, call tools, or execute response actions. Human verification is always required.
14+
1515
## Purpose
1616

1717
The goal is to show a credible bridge between deterministic telemetry analytics and safe analyst assistance.
1818

1919
This is not an autonomous SOC. It is a constrained drafting pipeline that keeps rule logic, ATT&CK mapping, case grouping, and evidence handling deterministic.
2020

2121
For a no-run reviewer pack, see [docs/ai-assisted-detection-examples.md](../../docs/ai-assisted-detection-examples.md).
22-
23-
## Pipeline
24-
25-
1. ingest sample auth, web, and process events from JSONL
26-
2. normalize them into a shared internal schema
27-
3. apply deterministic detection rules
28-
4. group rule hits into cases by shared entities and time proximity
29-
5. attach ATT&CK mappings from rule metadata
30-
6. build a case bundle with raw evidence, rule hits, severity, and evidence highlights
31-
7. pass the case bundle to a constrained local demo LLM adapter with strict instruction and data separation
32-
8. require JSON-only output against a local schema
33-
9. validate the response and reject invalid output
34-
10. emit analyst-facing artifacts and audit traces
35-
36-
## Guardrails
37-
38-
- telemetry content is marked as untrusted data
39-
- system instructions are separated from the evidence payload
40-
- the response must pass local JSON schema validation
41-
- the response must pass a semantic validation layer after schema validation
42-
- `human_verification` is required and must be `required`
43-
- no external tool use is allowed in the LLM stage
44-
- no automated response actions are allowed
45-
- forbidden action-taking or final-verdict language is rejected and recorded
46-
- summaries are rejected if the returned `case_id` does not exactly match the input case bundle
47-
- a prompt-injection-like sample event is included and treated as telemetry, not instruction
48-
- rejected summaries are fail-closed: they do not enter `case_summaries.json`
49-
- accepted and rejected outcomes are both recorded in `audit_traces.jsonl`
50-
51-
## Quick start
52-
53-
From the repository root:
54-
55-
```bash
56-
python -m pip install -e .
57-
python -m telemetry_window_demo.cli run-ai-demo
58-
```
59-
60-
Generated artifacts are written to `demos/ai-assisted-detection-demo/artifacts/`.
61-
62-
## Demo inputs
63-
64-
- sample data: `data/raw/sample_security_events.jsonl`
65-
- deterministic rules: `config/rules.yaml`
66-
- structured output schema: `config/llm_case_output_schema.json`
67-
22+
23+
## Pipeline
24+
25+
1. ingest sample auth, web, and process events from JSONL
26+
2. normalize them into a shared internal schema
27+
3. apply deterministic detection rules
28+
4. group rule hits into cases by shared entities and time proximity
29+
5. attach ATT&CK mappings from rule metadata
30+
6. build a case bundle with raw evidence, rule hits, severity, and evidence highlights
31+
7. pass the case bundle to a constrained local demo LLM adapter with strict instruction and data separation
32+
8. require JSON-only output against a local schema
33+
9. validate the response and reject invalid output
34+
10. emit analyst-facing artifacts and audit traces
35+
36+
## Guardrails
37+
38+
- telemetry content is marked as untrusted data
39+
- system instructions are separated from the evidence payload
40+
- the response must pass local JSON schema validation
41+
- the response must pass a semantic validation layer after schema validation
42+
- `human_verification` is required and must be `required`
43+
- no external tool use is allowed in the LLM stage
44+
- no automated response actions are allowed
45+
- forbidden action-taking or final-verdict language is rejected and recorded
46+
- summaries are rejected if the returned `case_id` does not exactly match the input case bundle
47+
- a prompt-injection-like sample event is included and treated as telemetry, not instruction
48+
- rejected summaries are fail-closed: they do not enter `case_summaries.json`
49+
- accepted and rejected outcomes are both recorded in `audit_traces.jsonl`
50+
51+
## Quick start
52+
53+
From the repository root:
54+
55+
```bash
56+
python -m pip install -e ".[dev]"
57+
telemetry-lab run ai-assisted
58+
```
59+
60+
Generated artifacts are written to `demos/ai-assisted-detection-demo/artifacts/`.
61+
62+
## Demo inputs
63+
64+
- sample data: `data/raw/sample_security_events.jsonl`
65+
- deterministic rules: `config/rules.yaml`
66+
- structured output schema: `config/llm_case_output_schema.json`
67+
6868
## Expected artifacts
6969

7070
- `artifacts/rule_hits.json`
7171
- `artifacts/case_bundles.json`
7272
- `artifacts/case_summaries.json`
7373
- `artifacts/case_report.md`
7474
- `artifacts/audit_traces.jsonl`
75+
- `artifacts/run_manifest.json`
7576

7677
## Expected run summary
7778

@@ -85,33 +86,34 @@ The bundled sample run should report:
8586
- `3` audit records
8687

8788
## Artifact semantics
88-
89-
- `rule_hits.json`: deterministic rule hits with rule metadata, ATT&CK mapping, entities, and evidence highlights
90-
- `case_bundles.json`: grouped cases with severity, rule hits, ATT&CK mappings, raw evidence, and untrusted-data marking
91-
- `case_summaries.json`: only accepted JSON summaries that passed schema and semantic validation
89+
90+
- `rule_hits.json`: deterministic rule hits with rule metadata, ATT&CK mapping, entities, and evidence highlights
91+
- `case_bundles.json`: grouped cases with severity, rule hits, ATT&CK mappings, raw evidence, and untrusted-data marking
92+
- `case_summaries.json`: only accepted JSON summaries that passed schema and semantic validation
9293
- `case_report.md`: analyst-facing report with run counts, accepted summaries, and explicit notes for rejected case summaries
9394
- `case_report.md`: includes a top-level run integrity section that surfaces rule/config degradation
94-
- `audit_traces.jsonl`: stable per-record audit log for accepted and rejected paths, using `schema_version = ai-assisted-detection-audit/v1` and including `ts`, `case_id`, `validation_status`, `rejection_reason`, `rule_ids`, `prompt_input_digest`, `evidence_digest`, and bounded response excerpts
95-
96-
## Rejection behavior
97-
98-
- non-JSON or malformed JSON responses are rejected and recorded
99-
- missing required fields or invalid enum values are rejected and recorded
100-
- schema-valid summaries with the wrong `case_id` are rejected and recorded
101-
- action-taking language is rejected
102-
- final-verdict or confirmed-compromise language is rejected
103-
- malformed rule or ATT&CK metadata is rejected before detection logic uses it
104-
105-
Rejected outputs do not become analyst summaries. Analysts can still inspect deterministic evidence through `case_bundles.json`, `case_report.md`, and `audit_traces.jsonl`.
106-
95+
- `audit_traces.jsonl`: stable per-record audit log for accepted and rejected paths, using `schema_version = ai-assisted-detection-audit/v1` and including `ts`, `case_id`, `validation_status`, `rejection_reason`, `rule_ids`, `prompt_input_digest`, `evidence_digest`, and bounded response excerpts
96+
- `run_manifest.json`: synthetic-local run manifest with tool version, input/config digests, and artifact schema versions
97+
98+
## Rejection behavior
99+
100+
- non-JSON or malformed JSON responses are rejected and recorded
101+
- missing required fields or invalid enum values are rejected and recorded
102+
- schema-valid summaries with the wrong `case_id` are rejected and recorded
103+
- action-taking language is rejected
104+
- final-verdict or confirmed-compromise language is rejected
105+
- malformed rule or ATT&CK metadata is rejected before detection logic uses it
106+
107+
Rejected outputs do not become analyst summaries. Analysts can still inspect deterministic evidence through `case_bundles.json`, `case_report.md`, and `audit_traces.jsonl`.
108+
107109
## Reviewer walkthrough
108110

109111
### Accepted summary path
110-
111-
Use the default sample run artifacts in `artifacts/case_summaries.json`, `artifacts/case_report.md`, and `artifacts/audit_traces.jsonl`.
112-
113-
Verify that `CASE-001` appears in all three places, that the `case_id` matches exactly, that `human_verification` is `required`, and that the audit record shows `validation_status = accepted` with `schema_version = ai-assisted-detection-audit/v1`.
114-
112+
113+
Use the default sample run artifacts in `artifacts/case_summaries.json`, `artifacts/case_report.md`, and `artifacts/audit_traces.jsonl`.
114+
115+
Verify that `CASE-001` appears in all three places, that the `case_id` matches exactly, that `human_verification` is `required`, and that the audit record shows `validation_status = accepted` with `schema_version = ai-assisted-detection-audit/v1`.
116+
115117
### Rejected summary path
116118

117119
Run:
@@ -121,9 +123,9 @@ pytest tests/test_ai_assisted_detection_demo.py -k "audit_traces_capture_accepte
121123
```
122124

123125
Then inspect the `case_report.md`, `case_summaries.json`, and `audit_traces.jsonl` files under `.pytest-artifacts-ai-demo-rejections/test_*/artifacts/`.
124-
125-
Verify that the rejected case is absent from `case_summaries.json`, appears in `case_report.md` as `Summary status: rejected`, and has an audit record with `validation_status = rejected` plus a concrete `rejection_reason` such as `missing_required_fields`, `semantic_validation_failed`, or `case_id_mismatch`.
126-
126+
127+
Verify that the rejected case is absent from `case_summaries.json`, appears in `case_report.md` as `Summary status: rejected`, and has an audit record with `validation_status = rejected` plus a concrete `rejection_reason` such as `missing_required_fields`, `semantic_validation_failed`, or `case_id_mismatch`.
128+
127129
### Degraded coverage path
128130

129131
Run:
@@ -133,15 +135,15 @@ pytest tests/test_ai_assisted_detection_demo.py -k malformed_attack_metadata_is_
133135
```
134136

135137
Then inspect the generated `case_report.md` and `audit_traces.jsonl` files under `.pytest-artifacts-ai-demo-degraded/test_*/artifacts/`.
136-
137-
Verify that `case_report.md` exposes `## Run Integrity`, `coverage_degraded: yes`, and the rejected rule id, and that `audit_traces.jsonl` contains a global rejection record with `case_id = null` and `rejection_reason = rule_metadata_validation_failed`.
138-
139-
## Limitations
140-
141-
- the LLM stage is a constrained local demo adapter, not a production model integration
142-
- detections are intentionally small and rule-based
143-
- grouping is simple and optimized for readability over recall
144-
- sample telemetry is synthetic and limited in volume
145-
- there is no ticketing, SOAR, sandboxing, or live data ingestion
146-
- artifacts are for analyst review only and do not represent final incident disposition
147-
- rejection logic is intentionally conservative and favors fail-closed behavior over model flexibility
138+
139+
Verify that `case_report.md` exposes `## Run Integrity`, `coverage_degraded: yes`, and the rejected rule id, and that `audit_traces.jsonl` contains a global rejection record with `case_id = null` and `rejection_reason = rule_metadata_validation_failed`.
140+
141+
## Limitations
142+
143+
- the LLM stage is a constrained local demo adapter, not a production model integration
144+
- detections are intentionally small and rule-based
145+
- grouping is simple and optimized for readability over recall
146+
- sample telemetry is synthetic and limited in volume
147+
- there is no ticketing, SOAR, sandboxing, or live data ingestion
148+
- artifacts are for analyst review only and do not represent final incident disposition
149+
- rejection logic is intentionally conservative and favors fail-closed behavior over model flexibility

0 commit comments

Comments
 (0)