Skip to content

Surface deprecated prebuilt detection rules as a sibling nav page#3167

Open
Mpdreamz wants to merge 56 commits into
mainfrom
feature/deprecated-detection-rules
Open

Surface deprecated prebuilt detection rules as a sibling nav page#3167
Mpdreamz wants to merge 56 commits into
mainfrom
feature/deprecated-detection-rules

Conversation

@Mpdreamz
Copy link
Copy Markdown
Member

@Mpdreamz Mpdreamz commented Apr 22, 2026

Why

Elastic's prebuilt detection rules repo contains a _deprecated/ folder of rules that have been retired. These rules were previously invisible to users browsing the docs — there was no way to discover them, understand why they exist, or know what replaced them. Users navigating directly to a deprecated rule page (e.g. from a bookmark or external link) also lost their nav context entirely: nothing in the sidebar was highlighted.

What

Deprecated rules page

When the detection-rules plugin processes a rule folder that contains a _deprecated/ subfolder, it automatically generates a sibling "Deprecated prebuilt detection rules" page in the navigation alongside the active rules overview. No docset.yml changes are required for the page to appear.

The page lists all deprecated rules alphabetically by domain, linking to individual rule pages. Each individual rule page shows a deprecation warning admonition with the date the rule was deprecated.

Optional preface

The security team can supply introductory content for the deprecated rules page by adding a markdown file to the detection-rules docs folder and referencing it in docset.yml:

- file: index.md
  detection_rules: ['../rules', '../rules_building_block']
  deprecated_file: deprecated-rules.md   # optional

When deprecated_file is set, the content of that file prefixes the auto-generated rules listing. This lets the team explain what deprecated rules are, what users should do with them, and link to related guidance — all without touching the docs-builder codebase.

Follow-up: elastic/detection-rules#5968 adds this preface file (draft, cannot merge until this PR is released to production).

Nav active state for hidden pages

Individual rule pages (both active and deprecated) are hidden nav leaves — they exist in the nav tree for ordering/breadcrumb purposes but don't appear as visible links in the sidebar. Before this change, landing on a rule page left the sidebar with nothing selected.

The fix emits a <meta name="docs:nav-active" content="{parentUrl}"> tag server-side when the current page is a hidden nav item. The client reads this and highlights the nearest visible ancestor instead. This restores nav context for rule pages and fixes the same issue on the live site for any hidden page.

Verification

Run locally against the detection-rules repo:

dotnet run --project src/tooling/docs-builder -- serve --path /path/to/detection-rules
  • http://localhost:3000/deprecated-detection-rules — lists deprecated rules
  • http://localhost:3000/rules/_deprecated/<rule> — deprecation warning, sidebar highlights deprecated rules page
  • http://localhost:3000/rules/<category>/<rule> — sidebar highlights prebuilt rules overview

Mpdreamz and others added 2 commits April 22, 2026 20:52
- Auto-detects _deprecated/ subfolders in detection rule folders and generates
  a sibling "Deprecated prebuilt detection rules" page in the nav
- Optional deprecated_file: field in docset.yml names a .md file whose content
  prefixes the auto-generated deprecated rules listing
- Each deprecated rule page shows a deprecation warning with the deprecation date
- Fixed stateful TomlParser causing serve-mode parse failures on repeated builds
- Fixed serve --path scope: in-memory write FS now scoped to git root of --path
  so output at {externalRepo}/.artifacts is within allowed write scope
- Fixed serve sourcePath: ReloadGeneratorService now passes DocumentationCheckoutDirectory
  (git root) rather than DocumentationSourceDirectory (docs/ subfolder)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
When a page is a hidden nav leaf (e.g. individual detection rule pages),
the JavaScript active-state logic couldn't find a matching nav link and
left the sidebar with nothing selected.

Fix: emit <meta name="docs:nav-active" content="{parentUrl}"> in the
page <head> when current.Hidden is true, pointing to the nearest visible
ancestor. pages-nav.ts reads this tag and uses that URL to mark the
correct nav item as current instead of window.location.pathname.

This works for both deprecated rules (/deprecated-detection-rules parent)
and active prebuilt rules (/ parent = detection rules overview at index.md).
Visible pages are unaffected (no meta tag emitted).

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@Mpdreamz Mpdreamz requested a review from a team as a code owner April 22, 2026 19:43
@Mpdreamz Mpdreamz requested a review from technige April 22, 2026 19:43
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR migrates detection-rule TOML parsing from Tomlet to Tomlyn, introduces deprecation metadata (maturity and date fields), adds dedicated TOC discovery and rendering for deprecated rules within _deprecated subdirectories, and implements navigation state propagation to highlight the correct nav item when viewing pages that are hidden from the navigation tree (such as individual detection rule pages).

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and clearly describes the main change: surfacing deprecated detection rules as a sibling navigation page.
Description check ✅ Passed The description comprehensively explains the motivation, implementation details, and verification steps for the feature.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feature/deprecated-detection-rules

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Elastic.Documentation.Configuration/Toc/TableOfContentsYamlConverters.cs (1)

75-87: ⚠️ Potential issue | 🟡 Minor

Remove unused deprecated_detection_rules from parsing logic.

The deprecated_detection_rules key is parsed into the dictionary but never read anywhere in the codebase. The PR auto-discovers deprecated rules via folder scanning, making this key dead code. Remove it from the condition or document why it's retained.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Elastic.Documentation.Configuration/Toc/TableOfContentsYamlConverters.cs`
around lines 75 - 87, In the YAML parsing branch inside
TableOfContentsYamlConverters (the else-if that checks key.Value against
"detection_rules" or "exclude" or "deprecated_detection_rules"), remove
"deprecated_detection_rules" from that condition and any related parsing branch
so the parser no longer adds that key into the dictionary; if you intentionally
want to keep it, add a comment explaining why and where it's consumed. Update or
remove any tests or usages that expect deprecated_detection_rules to be present
and ensure the parsing of the remaining keys ("detection_rules", "exclude") is
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@src/Elastic.Documentation.Configuration/Toc/TableOfContentsYamlConverters.cs`:
- Around line 75-87: In the YAML parsing branch inside
TableOfContentsYamlConverters (the else-if that checks key.Value against
"detection_rules" or "exclude" or "deprecated_detection_rules"), remove
"deprecated_detection_rules" from that condition and any related parsing branch
so the parser no longer adds that key into the dictionary; if you intentionally
want to keep it, add a comment explaining why and where it's consumed. Update or
remove any tests or usages that expect deprecated_detection_rules to be present
and ensure the parsing of the remaining keys ("detection_rules", "exclude") is
unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 81e46472-e23f-4459-8cba-6b14b17737ff

📥 Commits

Reviewing files that changed from the base of the PR and between b94fd12 and 9042a9a.

📒 Files selected for processing (15)
  • src/Elastic.Documentation.Configuration/FileSystemFactory.cs
  • src/Elastic.Documentation.Configuration/Toc/DetectionRules/DetectionRuleOverviewRef.cs
  • src/Elastic.Documentation.Configuration/Toc/DocumentationSetFile.cs
  • src/Elastic.Documentation.Configuration/Toc/TableOfContentsYamlConverters.cs
  • src/Elastic.Documentation.Site/Assets/pages-nav.ts
  • src/Elastic.Documentation.Site/Layout/_Head.cshtml
  • src/Elastic.Documentation.Site/_ViewModels.cs
  • src/Elastic.Markdown/Extensions/DetectionRules/DetectionRule.cs
  • src/Elastic.Markdown/Extensions/DetectionRules/DetectionRuleFile.cs
  • src/Elastic.Markdown/Extensions/DetectionRules/DetectionRulesDocsBuilderExtension.cs
  • src/Elastic.Markdown/HtmlWriter.cs
  • src/Elastic.Markdown/Page/Index.cshtml
  • src/Elastic.Markdown/Page/IndexViewModel.cs
  • src/tooling/docs-builder/Http/InMemoryBuildState.cs
  • src/tooling/docs-builder/Http/ReloadGeneratorService.cs

GHSA-g94r-2vxg-569j  OpenTelemetry.Api 1.13.1
GHSA-mr8r-92fq-pj8p  OpenTelemetry.Exporter.OpenTelemetryProtocol 1.13.1
GHSA-q834-8qmm-v933  OpenTelemetry.Exporter.OpenTelemetryProtocol 1.13.1

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
cotti
cotti previously approved these changes Apr 30, 2026
@cotti cotti self-requested a review April 30, 2026 03:52
@cotti cotti dismissed their stale review April 30, 2026 03:53

Saw an issue with TOML parsing unrelated to these changes, but still affecting parsing as a whole

@cotti
Copy link
Copy Markdown
Contributor

cotti commented Apr 30, 2026

I sent #3214 as a possible fix - it works better as a PR for this branch.

coderabbitai[bot]
coderabbitai Bot previously requested changes Apr 30, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/Elastic.Markdown/Extensions/DetectionRules/DetectionRule.cs (1)

292-293: 💤 Low value

GetString throws unhelpful exception on missing keys.

Direct indexing table[key] throws KeyNotFoundException without context about which field is missing. For better debuggability in malformed TOML, consider wrapping with a clearer message.

Optional improvement
-private static string GetString(TomlTable table, string key) =>
-    (string)table[key];
+private static string GetString(TomlTable table, string key) =>
+    table.TryGetValue(key, out var value) && value is string s
+        ? s
+        : throw new InvalidOperationException($"Required field '{key}' is missing or not a string");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Elastic.Markdown/Extensions/DetectionRules/DetectionRule.cs` around lines
292 - 293, The GetString helper currently indexes TomlTable directly causing a
KeyNotFoundException with no context; update GetString (the private static
method) to first check for the key (e.g. ContainsKey or TryGetValue) and if
missing throw an ArgumentException or KeyNotFoundException with a clear message
that includes the missing key name (and optionally the table name/context) and,
when present, safely convert the value to string (with null checks) so malformed
or null values produce a descriptive error instead of an unhelpful exception.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Elastic.Markdown/Extensions/DetectionRules/DetectionRule.cs`:
- Around line 281-290: ReadTactic currently indexes threatTable["tactic"] and
will throw if the key is missing; change it to use
threatTable.TryGetValue("tactic", out var t) and ensure t is a TomlTable before
casting, returning null (or a safe default) if the key is absent or not a
TomlTable; then call GetString(tacticTable, "...") only when tacticTable is
non-null so DetectionRuleTactic construction and GetString calls are guarded
against missing or malformed tactic entries.

---

Nitpick comments:
In `@src/Elastic.Markdown/Extensions/DetectionRules/DetectionRule.cs`:
- Around line 292-293: The GetString helper currently indexes TomlTable directly
causing a KeyNotFoundException with no context; update GetString (the private
static method) to first check for the key (e.g. ContainsKey or TryGetValue) and
if missing throw an ArgumentException or KeyNotFoundException with a clear
message that includes the missing key name (and optionally the table
name/context) and, when present, safely convert the value to string (with null
checks) so malformed or null values produce a descriptive error instead of an
unhelpful exception.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 87f9e368-6350-4e26-af0d-9198120ce3a6

📥 Commits

Reviewing files that changed from the base of the PR and between 9042a9a and 256f308.

📒 Files selected for processing (7)
  • Directory.Packages.props
  • src/Elastic.Documentation.Configuration/Elastic.Documentation.Configuration.csproj
  • src/Elastic.Documentation.Configuration/Toc/DocumentationSetFile.cs
  • src/Elastic.Markdown/Elastic.Markdown.csproj
  • src/Elastic.Markdown/Extensions/DetectionRules/DetectionRule.cs
  • src/Elastic.Markdown/HtmlWriter.cs
  • tests/Elastic.Markdown.Tests/DetectionRules/DetectionRuleParsingTests.cs
✅ Files skipped from review due to trivial changes (1)
  • src/Elastic.Documentation.Configuration/Elastic.Documentation.Configuration.csproj
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Elastic.Markdown/HtmlWriter.cs

Comment thread src/Elastic.Markdown/Extensions/DetectionRules/DetectionRule.cs
Mpdreamz and others added 13 commits May 11, 2026 09:38
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Martijn Laarman <Mpdreamz@gmail.com>
Snyk has created this PR to upgrade @tanstack/react-query from 5.97.0 to 5.99.0.

See this package in npm:
@tanstack/react-query

See this project in Snyk:
https://app.snyk.io/org/docs-wmk/project/69782e43-c85b-4c27-afd1-ad863be7a38a?utm_source=github&utm_medium=referral&page=upgrade-pr

Co-authored-by: snyk-bot <snyk-bot@snyk.io>
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Made with ❤️️ by updatecli

Co-authored-by: elastic-observability-automation[bot] <180520183+elastic-observability-automation[bot]@users.noreply.github.com>
Snyk has created this PR to upgrade @tanstack/react-query from 5.99.0 to 5.99.1.

See this package in npm:
@tanstack/react-query

See this project in Snyk:
https://app.snyk.io/org/docs-wmk/project/69782e43-c85b-4c27-afd1-ad863be7a38a?utm_source=github&utm_medium=referral&page=upgrade-pr

Co-authored-by: snyk-bot <snyk-bot@snyk.io>
Bumps [@babel/plugin-transform-modules-systemjs](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-modules-systemjs) from 7.29.0 to 7.29.4.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.29.4/packages/babel-plugin-transform-modules-systemjs)

---
updated-dependencies:
- dependency-name: "@babel/plugin-transform-modules-systemjs"
  dependency-version: 7.29.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@Mpdreamz Mpdreamz requested review from a team as code owners May 11, 2026 07:40
…om main

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@eric-forte-elastic
Copy link
Copy Markdown

@Mpdreamz just checking, can we merge this to resolve ongoing issues like https://github.com/elastic/detection-rules/actions/runs/25744929992/job/75605440043?

Thanks!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/tooling/docs-builder/Http/ReloadGeneratorService.cs`:
- Around line 51-52: StartAsync resolves sourcePath using
ReloadableGenerator.Generator.Context.DocumentationCheckoutDirectory?.FullName
?? ReloadableGenerator.Generator.Context.DocumentationSourceDirectory.FullName,
but Reload still uses DocumentationSourceDirectory directly causing inconsistent
targets; update the Reload method to compute sourcePath the same way (use the
nullable DocumentationCheckoutDirectory fallback to
DocumentationSourceDirectory) so both StartAsync and Reload use the identical
sourcePath resolution (reference ReloadableGenerator, Reload method, and
StartAsync).
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 94706b4d-f98f-48e0-9d6c-95b8077ef089

📥 Commits

Reviewing files that changed from the base of the PR and between ba70441 and b136e63.

📒 Files selected for processing (11)
  • Directory.Packages.props
  • src/Elastic.Documentation.Configuration/Elastic.Documentation.Configuration.csproj
  • src/Elastic.Documentation.Configuration/Toc/DocumentationSetFile.cs
  • src/Elastic.Documentation.Configuration/Toc/TableOfContentsYamlConverters.cs
  • src/Elastic.Documentation.Site/Layout/_Head.cshtml
  • src/Elastic.Documentation.Site/_ViewModels.cs
  • src/Elastic.Markdown/HtmlWriter.cs
  • src/Elastic.Markdown/Page/Index.cshtml
  • src/Elastic.Markdown/Page/IndexViewModel.cs
  • src/tooling/docs-builder/Http/InMemoryBuildState.cs
  • src/tooling/docs-builder/Http/ReloadGeneratorService.cs
✅ Files skipped from review due to trivial changes (2)
  • src/tooling/docs-builder/Http/InMemoryBuildState.cs
  • Directory.Packages.props
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/Elastic.Markdown/HtmlWriter.cs
  • src/Elastic.Markdown/Page/Index.cshtml
  • src/Elastic.Documentation.Site/Layout/_Head.cshtml
  • src/Elastic.Documentation.Configuration/Toc/TableOfContentsYamlConverters.cs
  • src/Elastic.Markdown/Page/IndexViewModel.cs
  • src/Elastic.Documentation.Configuration/Toc/DocumentationSetFile.cs
  • src/Elastic.Documentation.Configuration/Elastic.Documentation.Configuration.csproj
  • src/Elastic.Documentation.Site/_ViewModels.cs

Comment thread src/tooling/docs-builder/Http/ReloadGeneratorService.cs
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 1 file(s) based on 1 unresolved review comment.

Files modified:

  • src/tooling/docs-builder/Http/ReloadGeneratorService.cs

Commit: 3aa8e7a67f326a08037df72527774a435b498f00

The changes have been pushed to the feature/deprecated-detection-rules branch.

Time taken: 1m 54s

@cla-checker-service
Copy link
Copy Markdown

cla-checker-service Bot commented May 18, 2026

💚 CLA has been signed

Fixed 1 file(s) based on 1 unresolved review comment.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.