Skip to content

feat(middleware): gojq improvements — caching, panic-on-broken-init, secureCompileOpts#8280

Merged
lpcox merged 4 commits into
mainfrom
copilot/go-fan-go-module-review-itchyny-gojq
Jun 29, 2026
Merged

feat(middleware): gojq improvements — caching, panic-on-broken-init, secureCompileOpts#8280
lpcox merged 4 commits into
mainfrom
copilot/go-fan-go-module-review-itchyny-gojq

Conversation

Copilot AI commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Four improvements to gojq usage identified by the go-fan module review. The most impactful is eliminating repeated Parse+Compile on the parameterized-filter hot path; the most correctness-critical is replacing a silent-failure init() with a proper panic.

Changes

  • P1 – Cache CompileToolResponseFilterWithVars (internal/middleware/jqschema.go)
    Adds composite-key caching: filter + "\x00" + strings.Join(varNames, "\x00"). Previously every tool invocation re-parsed and re-compiled the same expression; now it's compile-once-run-many like the no-vars path.

  • P2 – init() panics instead of logging FATAL (internal/middleware/jqschema.go)
    Old code called log.Printf("FATAL: …") then returned, letting the binary start with jqSchemaCode == nil and silently returning errors on every schema call. jqSchemaFilter is a hardcoded constant — a compile failure means a broken binary, not a recoverable runtime condition.

    // before
    log.Printf("FATAL: Failed to compile jq schema filter at init (application will not start): %v", err)
    return
    // after
    panic(fmt.Sprintf("built-in jq schema filter failed to compile: %v", err))
  • P3 – secureCompileOpts package-level variable (internal/middleware/jqschema.go, internal/config/validation.go)
    Extracts the repeated gojq.WithEnvironLoader(func() []string { return nil }) into a shared slice in each package. All gojq.Compile call sites now reference it (or append to it), making the $ENV-disabled intent explicit and preventing future omissions.

  • P4 – TODO on filterCodeCache
    Documents that the unbounded sync.Map should become a bounded LRU if config hot-reload is ever added.

Tests

Added TestCompileToolResponseFilterWithVars_CacheHit (pointer equality on repeated identical calls) and TestCompileToolResponseFilterWithVars_DifferentVarsCacheMiss (same filter, different varNames → distinct *gojq.Code).

GitHub Advanced Security started work on behalf of lpcox June 29, 2026 13:56 View session
GitHub Advanced Security finished work on behalf of lpcox June 29, 2026 13:57
Copilot AI added 2 commits June 29, 2026 14:02
- P1: Cache CompileToolResponseFilterWithVars with composite key
  (filter + "\x00" + strings.Join(varNames, "\x00")) to eliminate
  repeated gojq.Parse+gojq.Compile on the parameterized-filter hot path
- P2: Replace misleading log.Printf("FATAL: ...") + return in init()
  with panic() — the binary is broken if the hardcoded filter fails,
  and the old code silently continued running with a nil jqSchemaCode
- P3: Consolidate gojq.WithEnvironLoader into a package-level
  secureCompileOpts slice in both middleware and config packages,
  preventing future compile sites from accidentally omitting the
  $ENV-disabled defense-in-depth option
- P4: Add TODO comment on filterCodeCache re: hot-reload bounded caching

Also removes the now-unused "log" import from jqschema.go and adds
tests for the new WithVars cache hit/miss behaviour.
…nt varNames

The test previously used different filter strings to prove a cache miss.
It now uses the same filter string with different varNames slices, which
is the actual behavior being documented (composite cache key includes varNames).
GitHub Advanced Security started work on behalf of lpcox June 29, 2026 14:04 View session
Copilot AI changed the title [WIP] Review go module itchyny/gojq for performance and usage feat(middleware): gojq improvements — caching, panic-on-broken-init, secureCompileOpts Jun 29, 2026
GitHub Advanced Security finished work on behalf of lpcox June 29, 2026 14:04
Copilot finished work on behalf of lpcox June 29, 2026 14:04
Copilot AI requested a review from lpcox June 29, 2026 14:04
GitHub Advanced Security started work on behalf of lpcox June 29, 2026 14:05 View session
GitHub Advanced Security finished work on behalf of lpcox June 29, 2026 14:06
@lpcox lpcox marked this pull request as ready for review June 29, 2026 14:33
Copilot AI review requested due to automatic review settings June 29, 2026 14:33

Copilot AI left a comment

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.

Pull request overview

This PR improves gojq usage in the middleware/config layers by making tool-response filter compilation faster (compile-once, reuse), more fail-fast for built-in filters (panic on broken init), and more consistently secure ($ENV disabled via shared compile options).

Changes:

  • Add caching for CompileToolResponseFilterWithVars using a composite key to avoid repeated Parse+Compile on hot paths.
  • Change init() behavior for the built-in jq schema filter to panic on parse/compile failure (broken binary should not start).
  • Centralize $ENV-disabled gojq compiler options (secureCompileOpts) and apply them consistently; add tests validating cache hit/miss behavior for var-based compilation.
Show a summary per file
File Description
internal/middleware/jqschema.go Adds secure compile opts, fail-fast init compilation, and caching for var-based filter compilation.
internal/middleware/jqschema_coverage_test.go Adds tests validating cache behavior for CompileToolResponseFilterWithVars.
internal/config/validation.go Centralizes secure compile opts and reuses them when validating jq filters with variables.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 3/3 changed files
  • Comments generated: 2
  • Review effort level: Low

// In practice this is bounded by the number of distinct filter strings in the
// gateway configuration, which is typically small (one per tool).
//
// TODO: if config hot-reload is added, replace sync.Map with a bounded LRU cache.
Comment thread internal/middleware/jqschema.go Outdated
Comment on lines +285 to +289
cacheKey := filter + "\x00" + strings.Join(varNames, "\x00")
if cached, ok := filterCodeCache.Load(cacheKey); ok {
code, ok := cached.(*gojq.Code)
if !ok {
// Should never happen; the cache only stores *gojq.Code values.
@lpcox

lpcox commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

@copilot address review feedback

Copilot AI commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address review feedback

Addressed in 397966d.

Changes made:

  • Updated filterCodeCache docs to reflect both cache key shapes.
  • Replaced NUL-concatenated var-filter cache keys with a structured toolResponseFilterVarsCacheKey to avoid collision risk.
  • Stopped appending directly to shared secureCompileOpts by using a dedicated options builder.
  • Added tests covering separator-collision safety and shared compile-option immutability.

GitHub Advanced Security started work on behalf of lpcox June 29, 2026 15:34 View session
Copilot finished work on behalf of lpcox June 29, 2026 15:34
GitHub Advanced Security finished work on behalf of lpcox June 29, 2026 15:34
@lpcox lpcox merged commit 8deee76 into main Jun 29, 2026
23 checks passed
@lpcox lpcox deleted the copilot/go-fan-go-module-review-itchyny-gojq branch June 29, 2026 15:35
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.

3 participants