From fed6a758842d06fa1f3428b5a3d5fb69e502a73a Mon Sep 17 00:00:00 2001 From: stacknil Date: Tue, 30 Jun 2026 23:22:20 +0800 Subject: [PATCH] docs(release): finalize v1 reviewer contract --- README.md | 12 +- docs/README.md | 6 +- docs/evidence-pipeline-contract.md | 12 +- docs/release-v1.0.md | 10 +- docs/reviewer-pack.md | 14 +- docs/roadmap.md | 4 +- docs/v0.6-to-v1-artifact-diff.md | 19 +-- docs/v1-contract-freeze.md | 32 +++-- docs/v1-readiness-gate.md | 14 +- schemas/ai_audit_traces.schema.json | 75 +++++++++++ schemas/case_summaries.schema.json | 47 +++++++ .../cloudtrail_normalized_events.schema.json | 61 +++++++++ schemas/config_change_events.schema.json | 34 +++++ schemas/config_investigation_hits.schema.json | 122 ++++++++++++++++++ schemas/dedup_rule_hits.schema.json | 100 ++++++++++++++ tests/test_evidence_pipeline_schemas.py | 84 +++++++++++- tests/test_reviewer_docs.py | 25 +++- 17 files changed, 608 insertions(+), 63 deletions(-) create mode 100644 schemas/ai_audit_traces.schema.json create mode 100644 schemas/case_summaries.schema.json create mode 100644 schemas/cloudtrail_normalized_events.schema.json create mode 100644 schemas/config_change_events.schema.json create mode 100644 schemas/config_investigation_hits.schema.json create mode 100644 schemas/dedup_rule_hits.schema.json diff --git a/README.md b/README.md index 1e82fbe..95e5aa4 100644 --- a/README.md +++ b/README.md @@ -6,20 +6,18 @@ A local, file-based detection workflow lab for reviewer-verifiable telemetry and Current focus: v1 reviewer contract stabilization for the five-demo matrix, with v1.0 treated as a five-demo contract freeze. -Latest tagged release: [v0.6.0 — fourth demo and config-change investigation](https://github.com/stacknil/telemetry-lab/releases/latest). - -Release drift note: current `main` is ahead of `v0.6.0` and contains the five-demo matrix plus v1 contract-freeze docs. Until a `v1.0` tag exists, use [`docs/v1-contract-freeze.md`](docs/v1-contract-freeze.md) and [`docs/reviewer-pack.md`](docs/reviewer-pack.md) for current main-branch review. +Latest tagged release: [v1.0 — reviewer contract release](https://github.com/stacknil/telemetry-lab/releases/tag/v1.0). ## Reviewer Start - [`docs/reviewer-brief.md`](docs/reviewer-brief.md): scope, value, evidence, and boundaries - [`docs/reviewer-path.md`](docs/reviewer-path.md): choose the right demo by review question - [`docs/reviewer-pack.md`](docs/reviewer-pack.md): demo matrix, artifact contract, and v1 readiness gate -- [`docs/v1-contract-freeze.md`](docs/v1-contract-freeze.md): v1.0 five-demo contract freeze and release drift note +- [`docs/v1-contract-freeze.md`](docs/v1-contract-freeze.md): v1.0 five-demo contract freeze, release status, and contract scope - [`docs/v1-readiness-gate.md`](docs/v1-readiness-gate.md): fixed inputs, fixed outputs, schema validation, artifact regeneration, and test pass requirements -- [`docs/release-v1.0.md`](docs/release-v1.0.md): draft v1.0 reviewer-contract release notes and explicit non-SIEM boundary +- [`docs/release-v1.0.md`](docs/release-v1.0.md): v1.0 reviewer-contract release notes and explicit non-SIEM boundary - [`docs/v0.6-to-v1-artifact-diff.md`](docs/v0.6-to-v1-artifact-diff.md): fourth-to-fifth-demo artifact contract and compatibility diff -- [`docs/evidence-pipeline-contract.md`](docs/evidence-pipeline-contract.md): JSON schema contracts for reviewer-facing evidence artifacts +- [`docs/evidence-pipeline-contract.md`](docs/evidence-pipeline-contract.md): JSON/JSONL schema contracts for reviewer-facing evidence artifacts - [`docs/reviewer-artifact-diff.md`](docs/reviewer-artifact-diff.md): release artifact diff contract for reviewer-facing outputs - [`docs/vocabulary.md`](docs/vocabulary.md): cross-demo vocabulary for events, hits, signals, bounded correlation, findings, summaries, reports, and audit traces - [`docs/README.md`](docs/README.md): current route, supporting docs, and historical release evidence @@ -195,7 +193,7 @@ Cooldown behavior: - treat v1.0 as a five-demo contract freeze, not a feature expansion - stabilize the five-demo matrix and avoid broad platform expansion - freeze reviewer-visible artifact names unless a rename is intentionally coordinated across docs, tests, and sample outputs -- keep JSON schema contracts aligned with reviewer-facing JSON evidence artifacts across the five-demo matrix +- keep JSON schema contracts aligned with reviewer-facing JSON and JSONL evidence artifacts across the five-demo matrix - keep committed artifacts aligned with regenerated pipeline output through `python scripts/regenerate_artifacts.py --check` - add a reviewer-facing artifact diff for each release, using `no-artifact-change` when committed reviewer artifacts are unchanged - use [`docs/reviewer-pack.md`](docs/reviewer-pack.md) and [`docs/architecture.md`](docs/architecture.md) as the consolidation entrypoints diff --git a/docs/README.md b/docs/README.md index 989609b..015d72f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,11 +7,11 @@ This directory separates the current reviewer route from supporting design notes - [`reviewer-pack.md`](reviewer-pack.md): top-level reviewer pack, demo matrix, artifact naming contract, and v1 readiness gate - [`reviewer-path.md`](reviewer-path.md): choose a demo by review question - [`reviewer-brief.md`](reviewer-brief.md): short problem, value, evidence, and boundary summary -- [`v1-contract-freeze.md`](v1-contract-freeze.md): v1.0 five-demo contract freeze and release drift note +- [`v1-contract-freeze.md`](v1-contract-freeze.md): v1.0 five-demo contract freeze, release status, and contract scope - [`v1-readiness-gate.md`](v1-readiness-gate.md): fixed inputs, fixed outputs, schema validation, artifact regeneration, and test pass requirements -- [`release-v1.0.md`](release-v1.0.md): draft reviewer-contract release notes with the explicit non-SIEM boundary +- [`release-v1.0.md`](release-v1.0.md): v1.0 reviewer-contract release notes with the explicit non-SIEM boundary - [`v0.6-to-v1-artifact-diff.md`](v0.6-to-v1-artifact-diff.md): additive artifact contract and compatibility diff from the fourth demo to the fifth -- [`evidence-pipeline-contract.md`](evidence-pipeline-contract.md): JSON schema contracts for reviewer-facing evidence artifacts +- [`evidence-pipeline-contract.md`](evidence-pipeline-contract.md): JSON/JSONL schema contracts for reviewer-facing evidence artifacts - [`reviewer-artifact-diff.md`](reviewer-artifact-diff.md): release diff contract for reviewer-facing artifact changes - [`vocabulary.md`](vocabulary.md): cross-demo vocabulary for evidence workflow terms and bounded correlation - [`architecture.md`](architecture.md): local file-based workflow diagram diff --git a/docs/evidence-pipeline-contract.md b/docs/evidence-pipeline-contract.md index 971349d..29623de 100644 --- a/docs/evidence-pipeline-contract.md +++ b/docs/evidence-pipeline-contract.md @@ -1,6 +1,6 @@ # Evidence Pipeline Contract -`telemetry-lab` v1.0 treats reviewer-facing JSON artifacts as evidence pipeline contracts. The schemas below define the current machine-readable artifact shapes across the five-demo matrix without turning the repo into a SIEM, dashboard, or monitoring platform. +`telemetry-lab` v1.0 treats reviewer-facing JSON and JSONL artifacts as evidence pipeline contracts. The schemas below define the current machine-readable artifact shapes across the five-demo matrix without turning the repo into a SIEM, dashboard, or monitoring platform. Use [`docs/vocabulary.md`](vocabulary.md) for the cross-demo meaning of `event`, `signal`, `hit`, `finding`, `case_bundle`, `summary`, `report`, and `audit_trace`. @@ -8,7 +8,7 @@ The contract is intentionally local and file-based: - schemas live under `schemas/` - committed artifacts live under `demos/*/artifacts/` -- tests validate the schemas against the committed artifacts +- tests validate the schemas against the committed JSON artifacts and JSONL records - raw evidence payloads may preserve source-specific fields, but deterministic wrapper fields stay explicit ## Schema Matrix @@ -18,8 +18,14 @@ The contract is intentionally local and file-based: | `schemas/telemetry_summary.schema.json` | `data/processed/summary.json`, `data/processed/richer_sample/summary.json` | telemetry-window run counts, rule counts, cooldown, and generated artifact references | | `schemas/rule_hits.schema.json` | `demos/ai-assisted-detection-demo/artifacts/rule_hits.json` | deterministic rule-hit fields before case grouping | | `schemas/case_bundles.schema.json` | `demos/ai-assisted-detection-demo/artifacts/case_bundles.json` | bounded case bundles passed to JSON-only drafting | +| `schemas/case_summaries.schema.json` | `demos/ai-assisted-detection-demo/artifacts/case_summaries.json` | accepted case summaries after schema and semantic validation | +| `schemas/ai_audit_traces.schema.json` | `demos/ai-assisted-detection-demo/artifacts/audit_traces.jsonl` | JSONL audit records for accepted and rejected AI-assisted drafting paths | +| `schemas/dedup_rule_hits.schema.json` | `demos/rule-evaluation-and-dedup-demo/artifacts/rule_hits_before_dedup.json`, `demos/rule-evaluation-and-dedup-demo/artifacts/rule_hits_after_dedup.json` | raw rule hits before deduplication and retained alert records after cooldown handling | | `schemas/dedup_explanations.schema.json` | `demos/rule-evaluation-and-dedup-demo/artifacts/dedup_explanations.json` | retained/suppressed cooldown explanations | +| `schemas/config_change_events.schema.json` | `demos/config-change-investigation-demo/artifacts/change_events_normalized.json` | normalized risky-change input context before rule matching | +| `schemas/config_investigation_hits.schema.json` | `demos/config-change-investigation-demo/artifacts/investigation_hits.json` | full config-change investigation records with triggering changes and attached bounded evidence | | `schemas/investigation_summary.schema.json` | `demos/config-change-investigation-demo/artifacts/investigation_summary.json` | config-change investigation summaries and bounded evidence counts | +| `schemas/cloudtrail_normalized_events.schema.json` | `demos/cloud-iam-change-investigation-demo/artifacts/normalized_cloudtrail_events.json` | normalized synthetic CloudTrail-like event records | | `schemas/cloud_iam_findings.schema.json` | `demos/cloud-iam-change-investigation-demo/artifacts/investigation_signals.json` | bounded CloudTrail-like IAM findings | | `schemas/cloud_iam_summary.schema.json` | `demos/cloud-iam-change-investigation-demo/artifacts/investigation_summary.json` | Cloud IAM investigation summary and time-model metadata | @@ -43,7 +49,7 @@ python -m pytest tests/test_evidence_pipeline_schemas.py The regeneration check compares byte-stable CSV, JSON, JSONL, and Markdown artifacts with fresh pipeline output. It also regenerates PNG visual snapshots to verify that the plotting path still runs, but it does not byte-compare those images because Matplotlib rendering can vary across platforms. -The schema test validates each schema file and checks that the committed artifact listed in the schema matrix conforms to it. +The schema test validates each schema file and checks that every committed JSON artifact and JSONL record listed in the schema matrix conforms to it. ## Release Artifact Diff diff --git a/docs/release-v1.0.md b/docs/release-v1.0.md index 7b7a802..a6b5d31 100644 --- a/docs/release-v1.0.md +++ b/docs/release-v1.0.md @@ -1,9 +1,8 @@ -# v1.0 Reviewer Contract Release Notes (Draft) +# v1.0 Reviewer Contract Release Notes **This is a reviewer-contract release, not a production SIEM.** -Release status: Draft. This document does not create a `v1.0` tag or GitHub -release. Final publication remains gated by +Release status: v1.0 reviewer-contract release. Publication is gated by [`docs/v1-readiness-gate.md`](v1-readiness-gate.md). ## Release Scope @@ -26,7 +25,7 @@ The v1.0 release contract requires: - fixed synthetic inputs for the five demos - fixed reviewer-visible output paths -- JSON Schema validation for contracted evidence artifacts +- JSON Schema validation for reviewer-facing JSON and JSONL evidence artifacts - reproducible committed artifacts - a passing full test suite @@ -51,8 +50,7 @@ field-level and semantic diff. Future release diffs follow ## Validation Snapshot -Current draft validation snapshot; refresh these results from the release -candidate commit before publication: +Validation snapshot from the release candidate commit: ```bash python scripts/regenerate_artifacts.py --check diff --git a/docs/reviewer-pack.md b/docs/reviewer-pack.md index bc2e9f0..4ae70c9 100644 --- a/docs/reviewer-pack.md +++ b/docs/reviewer-pack.md @@ -41,7 +41,7 @@ The current artifact names are reviewer-facing contracts for the v1 reviewer con ## Evidence Pipeline Contract -See [`docs/evidence-pipeline-contract.md`](evidence-pipeline-contract.md) for the v1 JSON schema contract covering reviewer-facing JSON evidence artifacts across the five-demo matrix. +See [`docs/evidence-pipeline-contract.md`](evidence-pipeline-contract.md) for the v1 JSON schema contract covering reviewer-facing JSON and JSONL evidence artifacts across the five-demo matrix. See [`docs/vocabulary.md`](vocabulary.md) for the cross-demo meaning of `event`, `signal`, `hit`, `finding`, `case_bundle`, `summary`, `report`, and `audit_trace`. @@ -51,8 +51,14 @@ The current schema contract covers: - `schemas/rule_hits.schema.json` - `schemas/case_bundles.schema.json` +- `schemas/case_summaries.schema.json` +- `schemas/ai_audit_traces.schema.json` +- `schemas/dedup_rule_hits.schema.json` - `schemas/dedup_explanations.schema.json` +- `schemas/config_change_events.schema.json` +- `schemas/config_investigation_hits.schema.json` - `schemas/investigation_summary.schema.json` +- `schemas/cloudtrail_normalized_events.schema.json` - `schemas/cloud_iam_findings.schema.json` - `schemas/cloud_iam_summary.schema.json` - `schemas/telemetry_summary.schema.json` @@ -106,11 +112,11 @@ Use the same Python interpreter for install, tests, and demo commands. - [`docs/README.md`](README.md): docs index for the current route, supporting docs, and historical release evidence - [`docs/reviewer-brief.md`](reviewer-brief.md): short problem / value summary - [`docs/reviewer-path.md`](reviewer-path.md): demo choice by review question -- [`docs/v1-contract-freeze.md`](v1-contract-freeze.md): v1.0 five-demo contract freeze and release drift note +- [`docs/v1-contract-freeze.md`](v1-contract-freeze.md): v1.0 five-demo contract freeze, release status, and contract scope - [`docs/v1-readiness-gate.md`](v1-readiness-gate.md): v1.0 readiness gate for fixed inputs, fixed outputs, schema validation, artifact regeneration, and test pass -- [`docs/release-v1.0.md`](release-v1.0.md): draft v1.0 reviewer-contract release notes and explicit non-SIEM boundary +- [`docs/release-v1.0.md`](release-v1.0.md): v1.0 reviewer-contract release notes and explicit non-SIEM boundary - [`docs/v0.6-to-v1-artifact-diff.md`](v0.6-to-v1-artifact-diff.md): fourth-to-fifth-demo artifact contract and compatibility diff -- [`docs/evidence-pipeline-contract.md`](evidence-pipeline-contract.md): JSON schema contracts for five-demo evidence artifacts +- [`docs/evidence-pipeline-contract.md`](evidence-pipeline-contract.md): JSON/JSONL schema contracts for five-demo evidence artifacts - [`docs/reviewer-artifact-diff.md`](reviewer-artifact-diff.md): release diff contract for reviewer-facing artifact changes - [`docs/vocabulary.md`](vocabulary.md): cross-demo evidence workflow vocabulary - [`docs/architecture.md`](architecture.md): local file-based workflow diagram diff --git a/docs/roadmap.md b/docs/roadmap.md index 4077b91..fc4969f 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -6,7 +6,7 @@ Next phase: v1 reviewer contract stabilization. The concrete milestone is [`v1.0 Five-Demo Contract Freeze`](v1-contract-freeze.md). -The repo now has five reviewer-verifiable demos and a clear [`docs/reviewer-path.md`](reviewer-path.md). The priority is to keep the demo matrix stable, preserve artifact names, make release drift explicit, and make review faster without implying a SIEM, dashboard, or production monitoring platform. +The repo now has five reviewer-verifiable demos and a clear [`docs/reviewer-path.md`](reviewer-path.md). The priority is to keep the demo matrix stable, preserve artifact names, keep release evidence explicit, and make review faster without implying a SIEM, dashboard, or production monitoring platform. Recently added: @@ -26,7 +26,7 @@ Recently added: 1. Stabilize the demo matrix. 2. Treat v1.0 as a five-demo contract freeze, not a feature expansion. 3. Freeze reviewer-visible artifact names unless a rename is intentional and documented across README, reviewer docs, demo docs, tests, and sample outputs. -4. Keep JSON schema contracts aligned with reviewer-facing JSON evidence artifacts across the five-demo matrix. +4. Keep JSON schema contracts aligned with reviewer-facing JSON and JSONL evidence artifacts across the five-demo matrix. 5. Keep committed evidence artifacts aligned with regenerated pipeline output through `python scripts/regenerate_artifacts.py --check`. 6. Keep cross-demo vocabulary stable for evidence workflow terms. 7. Include reviewer-facing artifact diffs in every release, including explicit `no-artifact-change` notes when committed reviewer artifacts are unchanged. diff --git a/docs/v0.6-to-v1-artifact-diff.md b/docs/v0.6-to-v1-artifact-diff.md index 0d0c806..da1a3c5 100644 --- a/docs/v0.6-to-v1-artifact-diff.md +++ b/docs/v0.6-to-v1-artifact-diff.md @@ -39,14 +39,16 @@ These `v0.6.0` artifacts remain stable in the v1 target: | Artifact | Added fields | Removed fields | Semantic changes | Compatibility notes | | --- | --- | --- | --- | --- | -| `demos/config-change-investigation-demo/artifacts/change_events_normalized.json` | none | none | none | `no-artifact-change` | -| `demos/config-change-investigation-demo/artifacts/investigation_hits.json` | none | none | none | `no-artifact-change` | +| `demos/config-change-investigation-demo/artifacts/change_events_normalized.json` | none | none | none | `no-artifact-change`; validated by `schemas/config_change_events.schema.json`. | +| `demos/config-change-investigation-demo/artifacts/investigation_hits.json` | none | none | none | `no-artifact-change`; validated by `schemas/config_investigation_hits.schema.json`. | | `demos/config-change-investigation-demo/artifacts/investigation_summary.json` | none | none | none | `no-artifact-change`; v1 adds schema validation without changing the committed artifact. | | `demos/config-change-investigation-demo/artifacts/investigation_report.md` | none | none | none | `no-artifact-change` | -The fourth-demo summary is now locked by -`schemas/investigation_summary.schema.json`. It remains an array of reduced -investigation records with: +The fourth-demo machine-readable artifacts are now locked by +`schemas/config_change_events.schema.json`, +`schemas/config_investigation_hits.schema.json`, and +`schemas/investigation_summary.schema.json`. The summary remains an array of +reduced investigation records with: - `investigation_id` - `severity` @@ -62,7 +64,7 @@ All fifth-demo artifact paths are new relative to `v0.6.0`: | Artifact | Added fields or sections | Removed fields | Semantic changes | Compatibility notes | | --- | --- | --- | --- | --- | -| `demos/cloud-iam-change-investigation-demo/artifacts/normalized_cloudtrail_events.json` | `eventID`, `event_time`, `observed_time`, `eventTime`, `actor`, `identityType`, `eventSource`, `eventName`, `awsRegion`, `sourceIPAddress`, `userAgent`, `errorCode`, `requestParameters`, `responseElements`, `userIdentity`, `outcome` | none | New CloudTrail-like normalization contract. `eventTime` drives ordering; optional `observedTime` is preserved as `observed_time`. | `non-contract-artifact`; stable reviewer-visible path, but not currently covered by a JSON Schema. | +| `demos/cloud-iam-change-investigation-demo/artifacts/normalized_cloudtrail_events.json` | `eventID`, `event_time`, `observed_time`, `eventTime`, `actor`, `identityType`, `eventSource`, `eventName`, `awsRegion`, `sourceIPAddress`, `userAgent`, `errorCode`, `requestParameters`, `responseElements`, `userIdentity`, `outcome` | none | New CloudTrail-like normalization contract. `eventTime` drives ordering; optional `observedTime` is preserved as `observed_time`. | `additive-compatible`; validated by `schemas/cloudtrail_normalized_events.schema.json`. | | `demos/cloud-iam-change-investigation-demo/artifacts/investigation_signals.json` | `signal_id`, rule identity, severity, `signal_time`, actor, primary/evidence event IDs, source IPs, embedded evidence, ATT&CK mappings, bounded-correlation reason, and review scope | none | Introduces `signal` for bounded multi-event cloud correlation. A signal is reviewer evidence, not a production alert or incident verdict. | `additive-compatible`; validated by `schemas/cloud_iam_findings.schema.json`. | | `demos/cloud-iam-change-investigation-demo/artifacts/investigation_summary.json` | `schema_version`, `source_type`, event/signal counts, per-rule counts, ATT&CK mapping count, time-model metadata, and explicit boundaries | none | Adds a run-level summary object. It is not shape-compatible with the fourth demo's per-investigation summary array. | `additive-compatible`; validated by `schemas/cloud_iam_summary.schema.json`. Dispatch by full path or schema. | | `demos/cloud-iam-change-investigation-demo/artifacts/investigation_report.md` | `Run Summary`, `Signals`, per-signal evidence and ATT&CK context, and `Boundaries` sections | none | Adds a cloud-specific reviewer narrative tied to signal and event IDs. | `non-contract-artifact`; stable reviewer-visible Markdown, not a JSON Schema contract. | @@ -93,8 +95,9 @@ reviewer-verifiable controls around both demos: 1. **Stable paths:** all eight investigation-demo artifacts above are listed in [`docs/reviewer-pack.md`](reviewer-pack.md#stable-reviewer-visible-artifacts). -2. **Schema validation:** the fourth-demo summary and the fifth-demo signals and - summary validate against separate JSON Schema Draft 2020-12 contracts. +2. **Schema validation:** every stable reviewer-facing JSON and JSONL artifact + in the five-demo matrix validates against a JSON Schema Draft 2020-12 + contract. 3. **Regeneration:** committed artifacts must match fresh deterministic output through `python scripts/regenerate_artifacts.py --check`. 4. **Regression checks:** tests keep the demo matrix, artifact links, schema diff --git a/docs/v1-contract-freeze.md b/docs/v1-contract-freeze.md index a5d7c9f..ac884d6 100644 --- a/docs/v1-contract-freeze.md +++ b/docs/v1-contract-freeze.md @@ -1,27 +1,25 @@ # v1.0 Five-Demo Contract Freeze -`telemetry-lab` is preparing a v1.0 contract freeze around the current -five-demo matrix. This milestone is not about adding another demo or expanding -the project into a SIEM, dashboard, or monitoring platform. It is about making -the current local, file-based detection workflow lab reviewer-verifiable from a +`telemetry-lab` v1.0 freezes the reviewer contract around the current five-demo +matrix. This milestone is not about adding another demo or expanding the +project into a SIEM, dashboard, or monitoring platform. It is about making the +current local, file-based detection workflow lab reviewer-verifiable from a stable contract surface. -## Release Drift +## Release Status -The latest tagged release is `v0.6.0`, published as -`v0.6.0 - fourth demo and config-change investigation`. Current `main` is ahead -of that release: it includes the five-demo matrix, the synthetic CloudTrail-like -IAM investigation demo, and the v1 reviewer contract stabilization docs and -checks. +The latest tagged release is `v1.0`, published as a reviewer-contract release +for the five-demo matrix. It includes the synthetic CloudTrail-like IAM +investigation demo, the v1 reviewer contract stabilization docs, schema +coverage for reviewer-facing JSON and JSONL artifacts, and the artifact +regeneration gate. -Until a `v1.0` tag is created, reviewers who inspect current `main` should use -this document, [`docs/reviewer-pack.md`](reviewer-pack.md), and -[`docs/reviewer-path.md`](reviewer-path.md) instead of treating `v0.6.0` release -notes as the complete current capability set. +`v0.6.0` remains the fourth-demo compatibility baseline. It was published as +`v0.6.0 - fourth demo and config-change investigation`. Use [`docs/v0.6-to-v1-artifact-diff.md`](v0.6-to-v1-artifact-diff.md) for the concrete artifact and compatibility change from the fourth demo in `v0.6.0` to -the fifth demo in the v1 freeze target. +the fifth demo in the v1 release. ## Freeze Scope @@ -79,8 +77,8 @@ committed sample outputs in the same change. ## Release Notes Requirement -Use [`docs/release-v1.0.md`](release-v1.0.md) as the maintained v1.0 release-note -draft. The final release notes must state exactly: +Use [`docs/release-v1.0.md`](release-v1.0.md) as the maintained v1.0 release +notes. The release notes must state exactly: > This is a reviewer-contract release, not a production SIEM. diff --git a/docs/v1-readiness-gate.md b/docs/v1-readiness-gate.md index 11dd5bc..9b492b9 100644 --- a/docs/v1-readiness-gate.md +++ b/docs/v1-readiness-gate.md @@ -4,6 +4,16 @@ This gate is a release-readiness checklist, not a feature roadmap. It does not authorize new demos, live ingestion, dashboards, alert routing, case management, autonomous response, or final incident verdicts. +## Five-Demo Matrix + +The fixed v1.0 matrix is: + +1. `telemetry-window-demo` +2. `ai-assisted-detection-demo` +3. `rule-evaluation-and-dedup-demo` +4. `config-change-investigation-demo` +5. `cloud-iam-change-investigation-demo` + ## Required Conditions v1.0 requires all of the following: @@ -41,7 +51,7 @@ Before v1.0: ## Schema Validation -Reviewer-facing JSON evidence artifacts must validate against schemas under `schemas/`. +Reviewer-facing JSON and JSONL evidence artifacts must validate against schemas under `schemas/`. Before v1.0: @@ -49,7 +59,7 @@ Before v1.0: python -m pytest tests/test_evidence_pipeline_schemas.py ``` -This verifies that schema files are valid JSON Schema Draft 2020-12 documents and that committed JSON artifacts conform to the schema matrix. +This verifies that schema files are valid JSON Schema Draft 2020-12 documents and that committed JSON artifacts and JSONL records conform to the schema matrix. ## Artifact Regeneration diff --git a/schemas/ai_audit_traces.schema.json b/schemas/ai_audit_traces.schema.json new file mode 100644 index 0000000..484abc0 --- /dev/null +++ b/schemas/ai_audit_traces.schema.json @@ -0,0 +1,75 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/stacknil/telemetry-lab/schemas/ai_audit_traces.schema.json", + "title": "AI-assisted detection audit trace records", + "description": "Schema for each JSONL record in demos/ai-assisted-detection-demo/artifacts/audit_traces.jsonl.", + "type": "object", + "additionalProperties": false, + "required": [ + "ts", + "case_id", + "schema_version", + "output_schema_version", + "stage", + "validation_status", + "rejection_reason", + "rule_ids", + "prompt_input_digest", + "evidence_digest", + "raw_response_excerpt", + "validation_errors", + "telemetry_classification" + ], + "properties": { + "ts": { "type": "string", "format": "date-time" }, + "case_id": { + "type": ["string", "null"], + "pattern": "^CASE-[0-9]{3}$" + }, + "schema_version": { + "type": "string", + "const": "ai-assisted-detection-audit/v1" + }, + "output_schema_version": { + "type": "string", + "minLength": 1 + }, + "stage": { + "type": "string", + "enum": ["case_summary_validation", "rule_metadata_validation"] + }, + "validation_status": { + "type": "string", + "enum": ["accepted", "rejected"] + }, + "rejection_reason": { + "type": ["string", "null"], + "minLength": 1 + }, + "rule_ids": { + "type": "array", + "items": { "type": "string", "minLength": 1 }, + "uniqueItems": true + }, + "prompt_input_digest": { + "type": ["string", "null"], + "pattern": "^[0-9a-f]{64}$" + }, + "evidence_digest": { + "type": ["string", "null"], + "pattern": "^[0-9a-f]{64}$" + }, + "raw_response_excerpt": { + "type": ["string", "null"], + "minLength": 1 + }, + "validation_errors": { + "type": "array", + "items": { "type": "string", "minLength": 1 } + }, + "telemetry_classification": { + "type": "string", + "const": "untrusted_data" + } + } +} diff --git a/schemas/case_summaries.schema.json b/schemas/case_summaries.schema.json new file mode 100644 index 0000000..b184f5d --- /dev/null +++ b/schemas/case_summaries.schema.json @@ -0,0 +1,47 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/stacknil/telemetry-lab/schemas/case_summaries.schema.json", + "title": "AI-assisted detection case summaries", + "description": "Schema for demos/ai-assisted-detection-demo/artifacts/case_summaries.json.", + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "case_id", + "summary", + "likely_causes", + "uncertainty_notes", + "suggested_next_steps", + "human_verification", + "scope_guardrail" + ], + "properties": { + "case_id": { "type": "string", "pattern": "^CASE-[0-9]{3}$" }, + "summary": { "type": "string", "minLength": 1 }, + "likely_causes": { + "type": "array", + "minItems": 1, + "maxItems": 3, + "items": { "type": "string", "minLength": 1 } + }, + "uncertainty_notes": { + "type": "array", + "minItems": 1, + "items": { "type": "string", "minLength": 1 } + }, + "suggested_next_steps": { + "type": "array", + "minItems": 1, + "maxItems": 4, + "items": { "type": "string", "minLength": 1 } + }, + "human_verification": { "type": "string", "const": "required" }, + "scope_guardrail": { + "type": "string", + "const": "no_final_incident_decision|no_rule_changes|no_automated_actions" + } + } + } +} diff --git a/schemas/cloudtrail_normalized_events.schema.json b/schemas/cloudtrail_normalized_events.schema.json new file mode 100644 index 0000000..bdec590 --- /dev/null +++ b/schemas/cloudtrail_normalized_events.schema.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/stacknil/telemetry-lab/schemas/cloudtrail_normalized_events.schema.json", + "title": "CloudTrail-like normalized events", + "description": "Schema for demos/cloud-iam-change-investigation-demo/artifacts/normalized_cloudtrail_events.json.", + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "eventID", + "event_time", + "observed_time", + "eventTime", + "actor", + "identityType", + "eventSource", + "eventName", + "awsRegion", + "sourceIPAddress", + "userAgent", + "errorCode", + "requestParameters", + "responseElements", + "userIdentity", + "outcome" + ], + "properties": { + "eventID": { "type": "string", "minLength": 1 }, + "event_time": { "type": "string", "format": "date-time" }, + "observed_time": { "type": ["string", "null"], "format": "date-time" }, + "eventTime": { "type": "string", "format": "date-time" }, + "actor": { "type": "string", "minLength": 1 }, + "identityType": { "type": ["string", "null"], "minLength": 1 }, + "eventSource": { "type": "string", "minLength": 1 }, + "eventName": { "type": "string", "minLength": 1 }, + "awsRegion": { "type": "string", "minLength": 1 }, + "sourceIPAddress": { "type": "string", "minLength": 1 }, + "userAgent": { "type": "string", "minLength": 1 }, + "errorCode": { "type": ["string", "null"], "minLength": 1 }, + "requestParameters": { + "type": "object", + "additionalProperties": true + }, + "responseElements": { + "type": "object", + "additionalProperties": true + }, + "userIdentity": { + "type": "object", + "additionalProperties": true, + "required": ["type"], + "properties": { + "type": { "type": "string", "minLength": 1 } + } + }, + "outcome": { "type": "string", "enum": ["success", "failure"] } + } + } +} diff --git a/schemas/config_change_events.schema.json b/schemas/config_change_events.schema.json new file mode 100644 index 0000000..61430fd --- /dev/null +++ b/schemas/config_change_events.schema.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/stacknil/telemetry-lab/schemas/config_change_events.schema.json", + "title": "Config-change normalized events", + "description": "Schema for demos/config-change-investigation-demo/artifacts/change_events_normalized.json.", + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "change_id", + "timestamp", + "actor", + "target_system", + "config_key", + "old_value", + "new_value", + "change_result", + "change_ticket" + ], + "properties": { + "change_id": { "type": "string", "minLength": 1 }, + "timestamp": { "type": "string", "format": "date-time" }, + "actor": { "type": "string", "minLength": 1 }, + "target_system": { "type": "string", "minLength": 1 }, + "config_key": { "type": "string", "minLength": 1 }, + "old_value": { "type": "string" }, + "new_value": { "type": "string" }, + "change_result": { "type": "string", "minLength": 1 }, + "change_ticket": { "type": "string", "minLength": 1 } + } + } +} diff --git a/schemas/config_investigation_hits.schema.json b/schemas/config_investigation_hits.schema.json new file mode 100644 index 0000000..3d2c10b --- /dev/null +++ b/schemas/config_investigation_hits.schema.json @@ -0,0 +1,122 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/stacknil/telemetry-lab/schemas/config_investigation_hits.schema.json", + "title": "Config-change investigation hits", + "description": "Schema for demos/config-change-investigation-demo/artifacts/investigation_hits.json.", + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "investigation_id", + "severity", + "rule_id", + "target_system", + "actor", + "triggering_change", + "trigger_reason", + "correlation_window_minutes", + "bounded_correlation_reason", + "attached_policy_denials", + "attached_follow_on_events", + "evidence_counts" + ], + "properties": { + "investigation_id": { "type": "string", "pattern": "^CCI-[0-9]{3}$" }, + "severity": { "type": "string", "enum": ["low", "medium", "high", "critical"] }, + "rule_id": { "type": "string", "minLength": 1 }, + "target_system": { "type": "string", "minLength": 1 }, + "actor": { "type": "string", "minLength": 1 }, + "triggering_change": { "$ref": "#/$defs/config_change" }, + "trigger_reason": { "type": "string", "minLength": 1 }, + "correlation_window_minutes": { "type": "integer", "minimum": 1 }, + "bounded_correlation_reason": { "type": "string", "minLength": 1 }, + "attached_policy_denials": { + "type": "array", + "items": { "$ref": "#/$defs/policy_denial" } + }, + "attached_follow_on_events": { + "type": "array", + "items": { "$ref": "#/$defs/follow_on_event" } + }, + "evidence_counts": { + "type": "object", + "additionalProperties": false, + "required": ["policy_denials", "follow_on_events"], + "properties": { + "policy_denials": { "type": "integer", "minimum": 0 }, + "follow_on_events": { "type": "integer", "minimum": 0 } + } + } + } + }, + "$defs": { + "config_change": { + "type": "object", + "additionalProperties": false, + "required": [ + "change_id", + "timestamp", + "actor", + "target_system", + "config_key", + "old_value", + "new_value", + "change_result", + "change_ticket" + ], + "properties": { + "change_id": { "type": "string", "minLength": 1 }, + "timestamp": { "type": "string", "format": "date-time" }, + "actor": { "type": "string", "minLength": 1 }, + "target_system": { "type": "string", "minLength": 1 }, + "config_key": { "type": "string", "minLength": 1 }, + "old_value": { "type": "string" }, + "new_value": { "type": "string" }, + "change_result": { "type": "string", "minLength": 1 }, + "change_ticket": { "type": "string", "minLength": 1 } + } + }, + "policy_denial": { + "type": "object", + "additionalProperties": false, + "required": [ + "denial_id", + "timestamp", + "actor", + "target_system", + "policy_name", + "decision", + "reason" + ], + "properties": { + "denial_id": { "type": "string", "minLength": 1 }, + "timestamp": { "type": "string", "format": "date-time" }, + "actor": { "type": "string", "minLength": 1 }, + "target_system": { "type": "string", "minLength": 1 }, + "policy_name": { "type": "string", "minLength": 1 }, + "decision": { "type": "string", "minLength": 1 }, + "reason": { "type": "string", "minLength": 1 } + } + }, + "follow_on_event": { + "type": "object", + "additionalProperties": false, + "required": [ + "event_id", + "timestamp", + "target_system", + "event_type", + "details" + ], + "properties": { + "event_id": { "type": "string", "minLength": 1 }, + "timestamp": { "type": "string", "format": "date-time" }, + "target_system": { "type": "string", "minLength": 1 }, + "event_type": { "type": "string", "minLength": 1 }, + "details": { "type": "string", "minLength": 1 } + } + } + } +} diff --git a/schemas/dedup_rule_hits.schema.json b/schemas/dedup_rule_hits.schema.json new file mode 100644 index 0000000..d9e4cb8 --- /dev/null +++ b/schemas/dedup_rule_hits.schema.json @@ -0,0 +1,100 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/stacknil/telemetry-lab/schemas/dedup_rule_hits.schema.json", + "title": "Rule evaluation dedup hits", + "description": "Schema for rule_hits_before_dedup.json and rule_hits_after_dedup.json.", + "type": "array", + "minItems": 1, + "items": { + "oneOf": [ + { "$ref": "#/$defs/raw_hit" }, + { "$ref": "#/$defs/retained_hit" } + ] + }, + "$defs": { + "base_hit": { + "type": "object", + "required": [ + "hit_id", + "rule_name", + "severity", + "alert_time", + "window_start", + "window_end", + "message", + "entity", + "source", + "target", + "host", + "cooldown_scope", + "scope_source", + "cooldown_key" + ], + "properties": { + "hit_id": { "type": "string", "pattern": "^RH-[0-9]{3}$" }, + "rule_name": { "type": "string", "minLength": 1 }, + "severity": { "type": "string", "enum": ["low", "medium", "high", "critical"] }, + "alert_time": { "type": "string", "format": "date-time" }, + "window_start": { "type": "string", "format": "date-time" }, + "window_end": { "type": "string", "format": "date-time" }, + "message": { "type": "string", "minLength": 1 }, + "entity": { "type": ["string", "null"], "minLength": 1 }, + "source": { "type": ["string", "null"], "minLength": 1 }, + "target": { "type": ["string", "null"], "minLength": 1 }, + "host": { "type": ["string", "null"], "minLength": 1 }, + "cooldown_scope": { "type": ["string", "null"], "minLength": 1 }, + "scope_source": { "type": "string", "minLength": 1 }, + "cooldown_key": { "type": "string", "minLength": 1 } + } + }, + "raw_hit": { + "allOf": [ + { "$ref": "#/$defs/base_hit" } + ], + "unevaluatedProperties": false + }, + "retained_hit": { + "allOf": [ + { "$ref": "#/$defs/base_hit" }, + { + "type": "object", + "required": [ + "retained_because", + "group_position", + "group_size", + "suppressed_hit_ids", + "suppression_reasons", + "suppressed_count", + "represented_hit_ids", + "represented_raw_hit_count", + "group_raw_hit_count", + "group_retained_alert_count" + ], + "properties": { + "retained_because": { "type": "string", "minLength": 1 }, + "group_position": { "type": "integer", "minimum": 1 }, + "group_size": { "type": "integer", "minimum": 1 }, + "suppressed_hit_ids": { + "type": "array", + "items": { "type": "string", "pattern": "^RH-[0-9]{3}$" } + }, + "suppression_reasons": { + "type": "array", + "items": { "type": "string", "minLength": 1 } + }, + "suppressed_count": { "type": "integer", "minimum": 0 }, + "represented_hit_ids": { + "type": "array", + "minItems": 1, + "items": { "type": "string", "pattern": "^RH-[0-9]{3}$" } + }, + "represented_raw_hit_count": { "type": "integer", "minimum": 1 }, + "group_raw_hit_count": { "type": "integer", "minimum": 1 }, + "group_retained_alert_count": { "type": "integer", "minimum": 1 } + } + } + ], + "unevaluatedProperties": false + } + } +} diff --git a/tests/test_evidence_pipeline_schemas.py b/tests/test_evidence_pipeline_schemas.py index a61bf3d..29edfc2 100644 --- a/tests/test_evidence_pipeline_schemas.py +++ b/tests/test_evidence_pipeline_schemas.py @@ -19,12 +19,31 @@ "schemas/case_bundles.schema.json": [ "demos/ai-assisted-detection-demo/artifacts/case_bundles.json", ], + "schemas/case_summaries.schema.json": [ + "demos/ai-assisted-detection-demo/artifacts/case_summaries.json", + ], + "schemas/ai_audit_traces.schema.json": [ + "demos/ai-assisted-detection-demo/artifacts/audit_traces.jsonl", + ], + "schemas/dedup_rule_hits.schema.json": [ + "demos/rule-evaluation-and-dedup-demo/artifacts/rule_hits_before_dedup.json", + "demos/rule-evaluation-and-dedup-demo/artifacts/rule_hits_after_dedup.json", + ], "schemas/dedup_explanations.schema.json": [ "demos/rule-evaluation-and-dedup-demo/artifacts/dedup_explanations.json", ], + "schemas/config_change_events.schema.json": [ + "demos/config-change-investigation-demo/artifacts/change_events_normalized.json", + ], + "schemas/config_investigation_hits.schema.json": [ + "demos/config-change-investigation-demo/artifacts/investigation_hits.json", + ], "schemas/investigation_summary.schema.json": [ "demos/config-change-investigation-demo/artifacts/investigation_summary.json", ], + "schemas/cloudtrail_normalized_events.schema.json": [ + "demos/cloud-iam-change-investigation-demo/artifacts/normalized_cloudtrail_events.json", + ], "schemas/cloud_iam_findings.schema.json": [ "demos/cloud-iam-change-investigation-demo/artifacts/investigation_signals.json", ], @@ -40,24 +59,62 @@ "ai-assisted-detection-demo": [ "schemas/rule_hits.schema.json", "schemas/case_bundles.schema.json", + "schemas/case_summaries.schema.json", + "schemas/ai_audit_traces.schema.json", ], "rule-evaluation-and-dedup-demo": [ + "schemas/dedup_rule_hits.schema.json", "schemas/dedup_explanations.schema.json", ], "config-change-investigation-demo": [ + "schemas/config_change_events.schema.json", + "schemas/config_investigation_hits.schema.json", "schemas/investigation_summary.schema.json", ], "cloud-iam-change-investigation-demo": [ + "schemas/cloudtrail_normalized_events.schema.json", "schemas/cloud_iam_findings.schema.json", "schemas/cloud_iam_summary.schema.json", ], } +REVIEWER_JSON_ARTIFACTS = { + "data/processed/summary.json", + "data/processed/richer_sample/summary.json", + "demos/ai-assisted-detection-demo/artifacts/rule_hits.json", + "demos/ai-assisted-detection-demo/artifacts/case_bundles.json", + "demos/ai-assisted-detection-demo/artifacts/case_summaries.json", + "demos/ai-assisted-detection-demo/artifacts/audit_traces.jsonl", + "demos/rule-evaluation-and-dedup-demo/artifacts/rule_hits_before_dedup.json", + "demos/rule-evaluation-and-dedup-demo/artifacts/rule_hits_after_dedup.json", + "demos/rule-evaluation-and-dedup-demo/artifacts/dedup_explanations.json", + "demos/config-change-investigation-demo/artifacts/change_events_normalized.json", + "demos/config-change-investigation-demo/artifacts/investigation_hits.json", + "demos/config-change-investigation-demo/artifacts/investigation_summary.json", + "demos/cloud-iam-change-investigation-demo/artifacts/normalized_cloudtrail_events.json", + "demos/cloud-iam-change-investigation-demo/artifacts/investigation_signals.json", + "demos/cloud-iam-change-investigation-demo/artifacts/investigation_summary.json", +} + def _load_json(relative_path: str) -> object: return json.loads((REPO_ROOT / relative_path).read_text(encoding="utf-8")) +def _load_jsonl(relative_path: str) -> list[object]: + return [ + json.loads(line) + for line in (REPO_ROOT / relative_path).read_text(encoding="utf-8").splitlines() + if line.strip() + ] + + +def _load_artifact(relative_path: str) -> object: + if relative_path.endswith(".jsonl"): + return _load_jsonl(relative_path) + return _load_json(relative_path) + + def _error_summary(errors: list[object]) -> str: lines: list[str] = [] for error in errors[:5]: @@ -73,10 +130,20 @@ def test_evidence_pipeline_schemas_validate_committed_artifacts() -> None: validator = Draft202012Validator(schema, format_checker=FormatChecker()) for artifact_path in artifact_paths: - errors = sorted( - validator.iter_errors(_load_json(artifact_path)), - key=lambda error: list(error.absolute_path), - ) + artifact = _load_artifact(artifact_path) + if artifact_path.endswith(".jsonl"): + assert isinstance(artifact, list) + errors = [ + error + for record in artifact + for error in validator.iter_errors(record) + ] + errors.sort(key=lambda error: list(error.absolute_path)) + else: + errors = sorted( + validator.iter_errors(artifact), + key=lambda error: list(error.absolute_path), + ) assert errors == [], f"{schema_path} failed for {artifact_path}\n{_error_summary(errors)}" @@ -106,6 +173,11 @@ def test_evidence_pipeline_contract_docs_reference_schemas_and_artifacts() -> No def test_schema_contracts_cover_all_five_demos_and_named_artifacts() -> None: contract_schema_paths = set(SCHEMA_CONTRACTS) + contracted_artifact_paths = { + artifact_path + for artifact_paths in SCHEMA_CONTRACTS.values() + for artifact_path in artifact_paths + } assert set(DEMO_SCHEMA_COVERAGE) == { "telemetry-window-demo", @@ -128,3 +200,7 @@ def test_schema_contracts_cover_all_five_demos_and_named_artifacts() -> None: "schemas/cloud_iam_findings.schema.json", ]: assert required_schema in contract_schema_paths + + assert contracted_artifact_paths == REVIEWER_JSON_ARTIFACTS + for artifact_path in REVIEWER_JSON_ARTIFACTS: + assert (REPO_ROOT / artifact_path).is_file(), artifact_path diff --git a/tests/test_reviewer_docs.py b/tests/test_reviewer_docs.py index 1cdc1e3..5c14943 100644 --- a/tests/test_reviewer_docs.py +++ b/tests/test_reviewer_docs.py @@ -135,7 +135,7 @@ def test_readme_links_reviewer_path_and_uses_lab_framing() -> None: assert "[`docs/v1-contract-freeze.md`](docs/v1-contract-freeze.md)" in readme assert "[`docs/v1-readiness-gate.md`](docs/v1-readiness-gate.md)" in readme assert "[`docs/architecture.md`](docs/architecture.md)" in readme - assert "Release drift note" in readme + assert "Latest tagged release: [v1.0" in readme assert "portfolio prototype" not in normalized assert "mvp only" not in normalized @@ -337,9 +337,9 @@ def test_v1_contract_freeze_documents_release_drift_and_gate() -> None: roadmap = _read_repo_file("docs/roadmap.md") assert "# v1.0 Five-Demo Contract Freeze" in freeze_doc - assert "## Release Drift" in freeze_doc - assert "latest tagged release is `v0.6.0`" in freeze_doc - assert "Current `main` is ahead" in freeze_doc + assert "## Release Status" in freeze_doc + assert "latest tagged release is `v1.0`" in freeze_doc + assert "`v0.6.0` remains the fourth-demo compatibility baseline" in freeze_doc assert "No new demo should be added for v1.0" in freeze_doc assert "python scripts/regenerate_artifacts.py --check" in freeze_doc assert "v1.0 artifact drift gate" in freeze_doc @@ -358,7 +358,6 @@ def test_v1_contract_freeze_documents_release_drift_and_gate() -> None: for text in [docs_index, reviewer_pack, readme, roadmap]: assert "v1-contract-freeze.md" in text - assert "Release drift note" in readme assert "v1.0 Five-Demo Contract Freeze" in roadmap @@ -396,6 +395,15 @@ def test_v1_readiness_gate_defines_required_release_conditions() -> None: for text in [docs_index, reviewer_pack, readme]: assert "v1-readiness-gate.md" in text + for demo_name in [ + "telemetry-window-demo", + "ai-assisted-detection-demo", + "rule-evaluation-and-dedup-demo", + "config-change-investigation-demo", + "cloud-iam-change-investigation-demo", + ]: + assert f"`{demo_name}`" in readiness_gate + def test_v06_to_v1_artifact_diff_documents_additive_fifth_demo_contract() -> None: artifact_diff = _read_repo_file("docs/v0.6-to-v1-artifact-diff.md") @@ -418,6 +426,9 @@ def test_v06_to_v1_artifact_diff_documents_additive_fifth_demo_contract() -> Non assert "## Verification" in artifact_diff assert "`investigation_hits.json`" in artifact_diff assert "`investigation_signals.json`" in artifact_diff + assert "`schemas/config_change_events.schema.json`" in artifact_diff + assert "`schemas/config_investigation_hits.schema.json`" in artifact_diff + assert "`schemas/cloudtrail_normalized_events.schema.json`" in artifact_diff assert "`schemas/investigation_summary.schema.json`" in artifact_diff assert "`schemas/cloud_iam_findings.schema.json`" in artifact_diff assert "`schemas/cloud_iam_summary.schema.json`" in artifact_diff @@ -446,9 +457,9 @@ def test_v1_release_note_states_reviewer_contract_boundary() -> None: boundary = "This is a reviewer-contract release, not a production SIEM." - assert "# v1.0 Reviewer Contract Release Notes (Draft)" in release_note + assert "# v1.0 Reviewer Contract Release Notes" in release_note assert boundary in release_note - assert "This document does not create a `v1.0` tag or GitHub" in release_note + assert "Release status: v1.0 reviewer-contract release." in release_note assert "## Release Scope" in release_note assert "## Reviewer Contract" in release_note assert "## Artifact Compatibility" in release_note