Skip to content

feat: endpoint API supports lf-endpoint-version header#3648

Open
msmithstubbs wants to merge 3 commits into
Logflare:mainfrom
msmithstubbs:feat/O11Y-1064
Open

feat: endpoint API supports lf-endpoint-version header#3648
msmithstubbs wants to merge 3 commits into
Logflare:mainfrom
msmithstubbs:feat/O11Y-1064

Conversation

@msmithstubbs

Copy link
Copy Markdown
Contributor

Adds version selection to the endpoint API with the lf-endpoint-version header

  • Adds endpoint query caching based on endpoint version
  • Endpoint queries will include endpoint_version label
  • If no lf-endpoint-version header is set the current version of the endpoint query is used.

Fixes O11Y-1064

@msmithstubbs
msmithstubbs force-pushed the feat/O11Y-1064 branch 3 times, most recently from ed7d994 to 34893b4 Compare June 29, 2026 21:44
Comment thread lib/logflare/endpoints/results_cache.ex Outdated
{:via, :syn, {partition, {query_id, param_hash}}}

{key, partition_key} =
case version_number do

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Caching on version number does mean results for the latest endpoint version can be cached twice: once with the version number, and once without.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think to avoid ambiguity, we should always set the version number. If no version created yet for existing endpoints then 0 or nil will work.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It also means that we essentially can remove cache invalidation on updates as the version number will always change so we don't need to be worried of config drift.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We would still have to invalidate the cache on update, right?

If I'm requesting an endpoint without specifying a version I'll get cached version 0. If the endpoint is updated the default endpoint served will still be version 0 without the updated config.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated to use :latest as the version number when no version is specified. Think this is clearer. That work?

@msmithstubbs
msmithstubbs marked this pull request as ready for review June 29, 2026 23:16
Comment thread lib/logflare/endpoints.ex Outdated
Comment thread lib/logflare/endpoints/results_cache.ex Outdated
{:via, :syn, {partition, {query_id, param_hash}}}

{key, partition_key} =
case version_number do

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think to avoid ambiguity, we should always set the version number. If no version created yet for existing endpoints then 0 or nil will work.

Comment thread lib/logflare/endpoints/results_cache.ex Outdated
{:via, :syn, {partition, {query_id, param_hash}}}

{key, partition_key} =
case version_number do

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It also means that we essentially can remove cache invalidation on updates as the version number will always change so we don't need to be worried of config drift.

Comment thread test/logflare/endpoints/cache_test.exs Outdated
{:ok, version_number} <- parse_endpoint_version(version_str),
{:ok, endpoint_query} <-
Endpoints.get_endpoint_query_at_version(endpoint, version_number) do
assign(conn, :endpoint_query, endpoint_query)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Severity: MEDIUM

The versioned endpoint_query loaded here preserves sandboxable: true from the historical snapshot. If a previous version had sandboxable: true and the owner later disabled it, any caller can use LF-ENDPOINT-VERSION: <old> to re-enable arbitrary SQL execution via the sql/lql params, bypassing the owner's security intent.
Helpful? Add 👍 / 👎

💡 Fix Suggestion

Suggestion: After loading the versioned endpoint_query, override its sandboxable field with the value from the current live endpoint (already in scope from the function head pattern match). This ensures that if the owner has since disabled sandboxing, the historical snapshot cannot be used to re-enable the custom SQL/LQL execution path. Replace the bare assign/3 call with one that explicitly pins sandboxable to the current endpoint's value.

⚠️ Experimental Feature: This code suggestion is automatically generated. Please review carefully.

Suggested change
assign(conn, :endpoint_query, endpoint_query)
assign(conn, :endpoint_query, %{endpoint_query | sandboxable: endpoint.sandboxable})

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is true, but I'm not sure if it falls within the intent of this feature. Please advise, @Ziinc

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants