Skip to content

[Greenhouse] Add agentless mode and simplify CEL cursor handling#18345

Draft
narph wants to merge 3 commits intoelastic:mainfrom
narph:update-greenhouse
Draft

[Greenhouse] Add agentless mode and simplify CEL cursor handling#18345
narph wants to merge 3 commits intoelastic:mainfrom
narph:update-greenhouse

Conversation

@narph
Copy link
Copy Markdown
Contributor

@narph narph commented Apr 10, 2026

Summary

  • Add agentless deployment mode to the greenhouse policy template, enabling serverless collection alongside the default agent mode (using security-service-integrations team).
  • Simplify CEL cursor handling by replacing empty-string sentinels in cursor fields (pit_id, search_after, max_event_time) with genuine absence using optional map entries. This reduces nesting depth, removes 4 .as() bindings in the success path, and makes the cursor semantics explicit.
  • Preserve auth_token in the 429 rate-limit handler to avoid an unnecessary token refresh on the next poll when rate-limited.

CEL cursor changes in detail

Production sites (cursor map):

  • Use ?"key": has_more ? optional.of(v) : optional.none() instead of "key": has_more ? v : "" for max_event_time, pit_id, search_after.
  • In the PIT expiry path, omit pit_id and search_after entirely instead of setting them to "".

Consumption sites:

  • window_start_time: collapse 5-line ternary to orValue() with initial_interval default.
  • Pit-Id / Search-After headers: optFlatMap with "" guard becomes optMap(v, [v]).
  • next_max_event_time: 4 .as() bindings collapse to 2 using optMap/orValue.
  • Use !body.?results[0].hasValue() for empty-results early return.

Test plan

  • Pipeline tests pass (elastic-package test pipeline)
  • System tests pass (elastic-package test system) — 2 hits asserted and found
  • Package builds successfully (elastic-package build)
  • Verified CEL program alignment with Greenhouse Audit Log API docs
  • CI passes

Made with Cursor

narph added 2 commits April 10, 2026 18:33
- Add agentless deployment mode to the greenhouse policy template,
  enabling serverless collection alongside the default agent mode.
- Simplify CEL cursor handling by replacing empty-string sentinels in
  cursor fields (pit_id, search_after, max_event_time) with genuine
  absence using optional map entries.
- Preserve auth_token in the 429 rate-limit handler to avoid
  unnecessary token refresh on the next poll.

Made-with: Cursor
@narph narph added Team:Security-Service Integrations Security Service Integrations team [elastic/security-service-integrations] Integration:greenhouse Greenhouse (Community supported) labels Apr 10, 2026
@elastic-vault-github-plugin-prod
Copy link
Copy Markdown

🚀 Benchmarks report

To see the full report comment with /test benchmark fullreport

@elasticmachine
Copy link
Copy Markdown

💚 Build Succeeded

The empty last page (results=0, next_search_after=null) returned 0
events, so the cursor was never persisted and window_start_time never
advanced. Emit a retry placeholder event on the empty last page so
the cursor update (advancing window_start_time to max_event_time) is
persisted. This prevents re-fetching the entire time window on every
poll cycle.

Made-with: Cursor
Comment on lines +145 to +146
?"Pit-Id": state.?cursor.pit_id.optMap(v, [v]),
?"Search-After": state.?cursor.search_after.optMap(v, [v]),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 High stream/cel.yml.hbs:145

The migration from optFlatMap to optMap at lines 145-146 removes empty-string filtering for Pit-Id and Search-After headers. Cursors created before this upgrade may contain pit_id: "" and search_after: "" (the old code at lines 179-180 set these to empty strings between windows). After upgrade, optMap transforms empty strings to [""] and sends Pit-Id: "" and Search-After: "" headers to the API, causing API errors instead of omitting the headers. This breaks data collection for users with existing cursor state until it expires or is manually cleared.

-              ?"Pit-Id": state.?cursor.pit_id.optMap(v, [v]),
-              ?"Search-After": state.?cursor.search_after.optMap(v, [v]),
🤖 Copy this AI Prompt to have your agent fix this:
In file packages/greenhouse/data_stream/audit/agent/stream/cel.yml.hbs around lines 145-146:

The migration from `optFlatMap` to `optMap` at lines 145-146 removes empty-string filtering for `Pit-Id` and `Search-After` headers. Cursors created before this upgrade may contain `pit_id: ""` and `search_after: ""` (the old code at lines 179-180 set these to empty strings between windows). After upgrade, `optMap` transforms empty strings to `[""]` and sends `Pit-Id: ""` and `Search-After: ""` headers to the API, causing API errors instead of omitting the headers. This breaks data collection for users with existing cursor state until it expires or is manually cleared.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Integration:greenhouse Greenhouse (Community supported) Team:Security-Service Integrations Security Service Integrations team [elastic/security-service-integrations]

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants