Skip to content

fix(plugin/external): pre-coerce string scalars before STRICT_PROTO protojson decode#652

Merged
intel352 merged 1 commit into
mainfrom
fix/strict-proto-scalar-coerce
May 13, 2026
Merged

fix(plugin/external): pre-coerce string scalars before STRICT_PROTO protojson decode#652
intel352 merged 1 commit into
mainfrom
fix/strict-proto-scalar-coerce

Conversation

@intel352
Copy link
Copy Markdown
Contributor

Summary

  • Adds coerceMapScalars in plugin/external/convert.go to pre-parse string-typed values into Go bool/int/uint/float before the protojson decoder rejects them.
  • Closes the BMW v0.51.4 image-launch blocker on step.auth_methods_policy config: workflow template expansion via {{ config "password_auth_enabled" }} emits the string "false", which strict-proto's protojson decoder rejected with invalid value for bool field passwordAuthEnabled: "false".
  • 8 unit tests + 1 integration regression test cover every coercible kind, JSON-name vs proto-name keying, empty-string-drop, invalid-passthrough, nil/empty input guards, and the BMW-shaped string-false-for-bool-default case.

Why

Workflow template ({{ config "..." }}) always emits string output even when the underlying config default is a scalar. Engine v0.51.x strict_proto routes typed configs through protojson.UnmarshalOptions{DiscardUnknown: false} which is strict on field types — so every template-driven scalar field broke at engine build time without this coercion.

Without coercion, the fix would have to be replicated by every plugin (publish a coerce-aware contract) or every consumer (rewrite every template + YAML to dodge the issue per field type) — neither is sustainable. Coercing at the gateway keeps the contract clean.

Coverage

  • bool field: true/false/1/0/yes/no/on/off (case-insensitive)
  • int*/sint*: strconv.ParseInt(value, 10, 64)
  • uint*/fixed: strconv.ParseUint(value, 10, 64)
  • float*/dbl: strconv.ParseFloat(value, 64)
  • empty string for scalar: dropped (proto3 default)
  • unparseable string: passthrough so protojson surfaces canonical "invalid value for " error on user typos
  • non-string + unknown field: passthrough
  • list/map fields: passthrough (nested coercion deferred to first downstream caller)

Copy-on-coerce; caller's map is not mutated.

Test plan

  • go test ./plugin/external/... -run Coerce|StringFalse — 9 new tests pass
  • Full external package suite: go test ./plugin/external/... — green
  • CI: full repo test matrix
  • After merge: tag v0.51.5 → bump BMW PR 278 v0.51.4 → v0.51.5 → image-launch unblocked

🤖 Generated with Claude Code

…rotojson decode

Workflow template expansion via {{ config "..." }} always emits strings,
even when the underlying config value is a scalar (bool / int / float).
Engine v0.51.x routes strict-proto step + module configs through
protojson.Unmarshal, which is strict: it rejects a string value for a
bool/int/float proto field with the canonical "invalid value for <type>
field X: \"<string>\"" error.

Before this fix, BMW (and any consumer with template-driven scalar
fields) hit:

  Setup error: failed to build engine: ... STRICT_PROTO contract for
  config message "workflow.plugins.auth.v1.AuthMethodsPolicyConfig"
  cannot use legacy Struct fallback: decode AuthMethodsPolicyConfig
  input as protobuf JSON: proto: invalid value for bool field
  passwordAuthEnabled: "false"

Adds `coerceMapScalars` that walks the input map + proto field
descriptor and parses string values into the matching Go scalar
type before json.Marshal is called. Coverage:

  - bool field:   "true"/"false"/"1"/"0"/"yes"/"no"/"on"/"off" (CI)
  - int* / sint*: strconv.ParseInt(value, 10, 64)
  - uint* / fixed: strconv.ParseUint(value, 10, 64)
  - float* / dbl: strconv.ParseFloat(value, 64)
  - empty string for scalar: dropped (proto3 default)
  - unparseable string:  passthrough so protojson surfaces canonical
                         "invalid value for <type>" error on user typos
  - non-string + unknown field: passthrough
  - list/map fields: passthrough (nested coercion deferred)

Copy-on-coerce: the caller's map is not mutated.

Tests cover every kind, JSON-name vs proto-name keying, empty-string
drop, invalid passthrough, nil/empty input guards, and the BMW-shaped
regression (string "false" for bool default-valued field).

Closes the BMW PR 278 image-launch blocker on
\`step.auth_methods_policy\` + \`auth.credential\` configs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 13, 2026 06:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 hardens the external plugin STRICT_PROTO config decoding path by coercing template-emitted string scalars (e.g., "false") into the protobuf field’s expected scalar type before protojson.Unmarshal runs, preventing strict type-rejection during decode.

Changes:

  • Added a coerceMapScalars pre-pass in mapToTypedAnyWithOptions to parse string → bool/int/uint/float based on the target protobuf field kind (dropping empty-string scalars to preserve proto3 defaults).
  • Implemented coerceStringToScalar to handle the supported coercions and intentionally pass through unparseable strings so protojson surfaces the canonical error.
  • Added unit + regression tests covering coercion behavior, keying by proto vs JSON name, nil/empty guards, and the "false"-for-bool template regression.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
plugin/external/convert.go Adds scalar string coercion before STRICT_PROTO protojson decoding in mapToTypedAnyWithOptions.
plugin/external/coerce_test.go Adds focused tests for scalar coercion and a regression test for template-emitted "false" on bool fields.

Comment on lines +149 to +153
}
out := make(map[string]any, len(values))
for k, v := range values {
out[k] = v
field, ok := fieldByKey[k]
Comment on lines +255 to +257
// Ensure unused import in test stays referenced (anypb is reachable via
// mapToTypedAny in TestMapToTypedAny_*).
var _ = anypb.Any{}
@github-actions
Copy link
Copy Markdown

⏱ Benchmark Results

No significant performance regressions detected.

benchstat comparison (baseline → PR)
## benchstat: baseline → PR
baseline-bench.txt:262: parsing iteration count: invalid syntax
baseline-bench.txt:342596: parsing iteration count: invalid syntax
baseline-bench.txt:645243: parsing iteration count: invalid syntax
baseline-bench.txt:936352: parsing iteration count: invalid syntax
baseline-bench.txt:1215566: parsing iteration count: invalid syntax
baseline-bench.txt:1528113: parsing iteration count: invalid syntax
benchmark-results.txt:262: parsing iteration count: invalid syntax
benchmark-results.txt:402068: parsing iteration count: invalid syntax
benchmark-results.txt:748350: parsing iteration count: invalid syntax
benchmark-results.txt:1099726: parsing iteration count: invalid syntax
benchmark-results.txt:1458605: parsing iteration count: invalid syntax
benchmark-results.txt:2056884: parsing iteration count: invalid syntax
goos: linux
goarch: amd64
pkg: github.com/GoCodeAlone/workflow/dynamic
cpu: AMD EPYC 9V74 80-Core Processor                
                            │ baseline-bench.txt │
                            │       sec/op       │
InterpreterCreation-4              3.266m ± 183%
ComponentLoad-4                    3.496m ±   0%
ComponentExecute-4                 1.839µ ±   0%
PoolContention/workers-1-4         1.022µ ±   2%
PoolContention/workers-2-4         1.020µ ±   2%
PoolContention/workers-4-4         1.022µ ±   1%
PoolContention/workers-8-4         1.027µ ±   1%
PoolContention/workers-16-4        1.051µ ±   3%
ComponentLifecycle-4               3.604m ±   1%
SourceValidation-4                 2.203µ ±   1%
RegistryConcurrent-4               833.1n ±   2%
LoaderLoadFromString-4             3.616m ±   0%
geomean                            16.99µ

                            │ baseline-bench.txt │
                            │        B/op        │
InterpreterCreation-4               2.027Mi ± 0%
ComponentLoad-4                     2.180Mi ± 0%
ComponentExecute-4                  1.203Ki ± 0%
PoolContention/workers-1-4          1.203Ki ± 0%
PoolContention/workers-2-4          1.203Ki ± 0%
PoolContention/workers-4-4          1.203Ki ± 0%
PoolContention/workers-8-4          1.203Ki ± 0%
PoolContention/workers-16-4         1.203Ki ± 0%
ComponentLifecycle-4                2.183Mi ± 0%
SourceValidation-4                  1.984Ki ± 0%
RegistryConcurrent-4                1.133Ki ± 0%
LoaderLoadFromString-4              2.182Mi ± 0%
geomean                             15.25Ki

                            │ baseline-bench.txt │
                            │     allocs/op      │
InterpreterCreation-4                15.68k ± 0%
ComponentLoad-4                      18.02k ± 0%
ComponentExecute-4                    25.00 ± 0%
PoolContention/workers-1-4            25.00 ± 0%
PoolContention/workers-2-4            25.00 ± 0%
PoolContention/workers-4-4            25.00 ± 0%
PoolContention/workers-8-4            25.00 ± 0%
PoolContention/workers-16-4           25.00 ± 0%
ComponentLifecycle-4                 18.07k ± 0%
SourceValidation-4                    32.00 ± 0%
RegistryConcurrent-4                  2.000 ± 0%
LoaderLoadFromString-4               18.06k ± 0%
geomean                               183.3

cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                            │ benchmark-results.txt │
                            │        sec/op         │
InterpreterCreation-4                 3.268m ± 220%
ComponentLoad-4                       3.564m ±  16%
ComponentExecute-4                    1.904µ ±   1%
PoolContention/workers-1-4            1.215µ ±   1%
PoolContention/workers-2-4            1.206µ ±   2%
PoolContention/workers-4-4            1.212µ ±   1%
PoolContention/workers-8-4            1.214µ ±   2%
PoolContention/workers-16-4           1.218µ ±   3%
ComponentLifecycle-4                  3.621m ±   2%
SourceValidation-4                    2.249µ ±   1%
RegistryConcurrent-4                  901.1n ±   2%
LoaderLoadFromString-4                3.641m ±   2%
geomean                               18.45µ

                            │ benchmark-results.txt │
                            │         B/op          │
InterpreterCreation-4                  2.027Mi ± 0%
ComponentLoad-4                        2.180Mi ± 0%
ComponentExecute-4                     1.203Ki ± 0%
PoolContention/workers-1-4             1.203Ki ± 0%
PoolContention/workers-2-4             1.203Ki ± 0%
PoolContention/workers-4-4             1.203Ki ± 0%
PoolContention/workers-8-4             1.203Ki ± 0%
PoolContention/workers-16-4            1.203Ki ± 0%
ComponentLifecycle-4                   2.183Mi ± 0%
SourceValidation-4                     1.984Ki ± 0%
RegistryConcurrent-4                   1.133Ki ± 0%
LoaderLoadFromString-4                 2.182Mi ± 0%
geomean                                15.25Ki

                            │ benchmark-results.txt │
                            │       allocs/op       │
InterpreterCreation-4                   15.68k ± 0%
ComponentLoad-4                         18.02k ± 0%
ComponentExecute-4                       25.00 ± 0%
PoolContention/workers-1-4               25.00 ± 0%
PoolContention/workers-2-4               25.00 ± 0%
PoolContention/workers-4-4               25.00 ± 0%
PoolContention/workers-8-4               25.00 ± 0%
PoolContention/workers-16-4              25.00 ± 0%
ComponentLifecycle-4                    18.07k ± 0%
SourceValidation-4                       32.00 ± 0%
RegistryConcurrent-4                     2.000 ± 0%
LoaderLoadFromString-4                  18.06k ± 0%
geomean                                  183.3

pkg: github.com/GoCodeAlone/workflow/middleware
cpu: AMD EPYC 9V74 80-Core Processor                
                                  │ baseline-bench.txt │
                                  │       sec/op       │
CircuitBreakerDetection-4                 302.4n ± 13%
CircuitBreakerExecution_Success-4         22.65n ±  0%
CircuitBreakerExecution_Failure-4         70.93n ±  0%
geomean                                   78.62n

                                  │ baseline-bench.txt │
                                  │        B/op        │
CircuitBreakerDetection-4                 144.0 ± 0%
CircuitBreakerExecution_Success-4         0.000 ± 0%
CircuitBreakerExecution_Failure-4         0.000 ± 0%
geomean                                              ¹
¹ summaries must be >0 to compute geomean

                                  │ baseline-bench.txt │
                                  │     allocs/op      │
CircuitBreakerDetection-4                 1.000 ± 0%
CircuitBreakerExecution_Success-4         0.000 ± 0%
CircuitBreakerExecution_Failure-4         0.000 ± 0%
geomean                                              ¹
¹ summaries must be >0 to compute geomean

cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                                  │ benchmark-results.txt │
                                  │        sec/op         │
CircuitBreakerDetection-4                     457.6n ± 1%
CircuitBreakerExecution_Success-4             59.73n ± 1%
CircuitBreakerExecution_Failure-4             64.79n ± 0%
geomean                                       121.0n

                                  │ benchmark-results.txt │
                                  │         B/op          │
CircuitBreakerDetection-4                    144.0 ± 0%
CircuitBreakerExecution_Success-4            0.000 ± 0%
CircuitBreakerExecution_Failure-4            0.000 ± 0%
geomean                                                 ¹
¹ summaries must be >0 to compute geomean

                                  │ benchmark-results.txt │
                                  │       allocs/op       │
CircuitBreakerDetection-4                    1.000 ± 0%
CircuitBreakerExecution_Success-4            0.000 ± 0%
CircuitBreakerExecution_Failure-4            0.000 ± 0%
geomean                                                 ¹
¹ summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/module
cpu: AMD EPYC 9V74 80-Core Processor                
                                 │ baseline-bench.txt │
                                 │       sec/op       │
JQTransform_Simple-4                     827.4n ± 27%
JQTransform_ObjectConstruction-4         1.389µ ±  2%
JQTransform_ArraySelect-4                3.415µ ±  2%
JQTransform_Complex-4                    41.69µ ±  1%
JQTransform_Throughput-4                 1.708µ ±  0%
SSEPublishDelivery-4                     64.75n ±  1%
geomean                                  1.620µ

                                 │ baseline-bench.txt │
                                 │        B/op        │
JQTransform_Simple-4                   1.273Ki ± 0%
JQTransform_ObjectConstruction-4       1.773Ki ± 0%
JQTransform_ArraySelect-4              2.625Ki ± 0%
JQTransform_Complex-4                  16.22Ki ± 0%
JQTransform_Throughput-4               1.984Ki ± 0%
SSEPublishDelivery-4                     0.000 ± 0%
geomean                                             ¹
¹ summaries must be >0 to compute geomean

                                 │ baseline-bench.txt │
                                 │     allocs/op      │
JQTransform_Simple-4                     10.00 ± 0%
JQTransform_ObjectConstruction-4         15.00 ± 0%
JQTransform_ArraySelect-4                30.00 ± 0%
JQTransform_Complex-4                    324.0 ± 0%
JQTransform_Throughput-4                 17.00 ± 0%
SSEPublishDelivery-4                     0.000 ± 0%
geomean                                             ¹
¹ summaries must be >0 to compute geomean

cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                                 │ benchmark-results.txt │
                                 │        sec/op         │
JQTransform_Simple-4                        989.6n ± 21%
JQTransform_ObjectConstruction-4            1.557µ ±  0%
JQTransform_ArraySelect-4                   3.300µ ±  1%
JQTransform_Complex-4                       36.52µ ±  1%
JQTransform_Throughput-4                    1.881µ ±  1%
SSEPublishDelivery-4                        77.69n ±  0%
geomean                                     1.733µ

                                 │ benchmark-results.txt │
                                 │         B/op          │
JQTransform_Simple-4                      1.273Ki ± 0%
JQTransform_ObjectConstruction-4          1.773Ki ± 0%
JQTransform_ArraySelect-4                 2.625Ki ± 0%
JQTransform_Complex-4                     16.22Ki ± 0%
JQTransform_Throughput-4                  1.984Ki ± 0%
SSEPublishDelivery-4                        0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

                                 │ benchmark-results.txt │
                                 │       allocs/op       │
JQTransform_Simple-4                        10.00 ± 0%
JQTransform_ObjectConstruction-4            15.00 ± 0%
JQTransform_ArraySelect-4                   30.00 ± 0%
JQTransform_Complex-4                       324.0 ± 0%
JQTransform_Throughput-4                    17.00 ± 0%
SSEPublishDelivery-4                        0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/schema
cpu: AMD EPYC 9V74 80-Core Processor                
                                    │ baseline-bench.txt │
                                    │       sec/op       │
SchemaValidation_Simple-4                   1.113µ ± 28%
SchemaValidation_AllFields-4                1.651µ ±  2%
SchemaValidation_FormatValidation-4         1.588µ ±  8%
SchemaValidation_ManySchemas-4              1.592µ ±  2%
geomean                                     1.468µ

                                    │ baseline-bench.txt │
                                    │        B/op        │
SchemaValidation_Simple-4                   0.000 ± 0%
SchemaValidation_AllFields-4                0.000 ± 0%
SchemaValidation_FormatValidation-4         0.000 ± 0%
SchemaValidation_ManySchemas-4              0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

                                    │ baseline-bench.txt │
                                    │     allocs/op      │
SchemaValidation_Simple-4                   0.000 ± 0%
SchemaValidation_AllFields-4                0.000 ± 0%
SchemaValidation_FormatValidation-4         0.000 ± 0%
SchemaValidation_ManySchemas-4              0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                                    │ benchmark-results.txt │
                                    │        sec/op         │
SchemaValidation_Simple-4                      1.044µ ±  8%
SchemaValidation_AllFields-4                   1.541µ ± 36%
SchemaValidation_FormatValidation-4            1.498µ ±  1%
SchemaValidation_ManySchemas-4                 1.488µ ±  2%
geomean                                        1.376µ

                                    │ benchmark-results.txt │
                                    │         B/op          │
SchemaValidation_Simple-4                      0.000 ± 0%
SchemaValidation_AllFields-4                   0.000 ± 0%
SchemaValidation_FormatValidation-4            0.000 ± 0%
SchemaValidation_ManySchemas-4                 0.000 ± 0%
geomean                                                   ¹
¹ summaries must be >0 to compute geomean

                                    │ benchmark-results.txt │
                                    │       allocs/op       │
SchemaValidation_Simple-4                      0.000 ± 0%
SchemaValidation_AllFields-4                   0.000 ± 0%
SchemaValidation_FormatValidation-4            0.000 ± 0%
SchemaValidation_ManySchemas-4                 0.000 ± 0%
geomean                                                   ¹
¹ summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/store
cpu: AMD EPYC 9V74 80-Core Processor                
                                   │ baseline-bench.txt │
                                   │       sec/op       │
EventStoreAppend_InMemory-4                1.190µ ± 17%
EventStoreAppend_SQLite-4                  1.015m ±  2%
GetTimeline_InMemory/events-10-4           12.86µ ±  2%
GetTimeline_InMemory/events-50-4           71.52µ ± 23%
GetTimeline_InMemory/events-100-4          109.6µ ±  1%
GetTimeline_InMemory/events-500-4          561.6µ ±  1%
GetTimeline_InMemory/events-1000-4         1.140m ±  0%
GetTimeline_SQLite/events-10-4             82.66µ ±  1%
GetTimeline_SQLite/events-50-4             218.6µ ±  1%
GetTimeline_SQLite/events-100-4            379.3µ ±  1%
GetTimeline_SQLite/events-500-4            1.655m ±  1%
GetTimeline_SQLite/events-1000-4           3.219m ±  0%
geomean                                    194.0µ

                                   │ baseline-bench.txt │
                                   │        B/op        │
EventStoreAppend_InMemory-4                 779.5 ± 11%
EventStoreAppend_SQLite-4                 1.983Ki ±  2%
GetTimeline_InMemory/events-10-4          7.953Ki ±  0%
GetTimeline_InMemory/events-50-4          46.62Ki ±  0%
GetTimeline_InMemory/events-100-4         94.48Ki ±  0%
GetTimeline_InMemory/events-500-4         472.8Ki ±  0%
GetTimeline_InMemory/events-1000-4        944.3Ki ±  0%
GetTimeline_SQLite/events-10-4            16.74Ki ±  0%
GetTimeline_SQLite/events-50-4            87.14Ki ±  0%
GetTimeline_SQLite/events-100-4           175.4Ki ±  0%
GetTimeline_SQLite/events-500-4           846.1Ki ±  0%
GetTimeline_SQLite/events-1000-4          1.639Mi ±  0%
geomean                                   67.27Ki

                                   │ baseline-bench.txt │
                                   │     allocs/op      │
EventStoreAppend_InMemory-4                  7.000 ± 0%
EventStoreAppend_SQLite-4                    53.00 ± 0%
GetTimeline_InMemory/events-10-4             125.0 ± 0%
GetTimeline_InMemory/events-50-4             653.0 ± 0%
GetTimeline_InMemory/events-100-4           1.306k ± 0%
GetTimeline_InMemory/events-500-4           6.514k ± 0%
GetTimeline_InMemory/events-1000-4          13.02k ± 0%
GetTimeline_SQLite/events-10-4               382.0 ± 0%
GetTimeline_SQLite/events-50-4              1.852k ± 0%
GetTimeline_SQLite/events-100-4             3.681k ± 0%
GetTimeline_SQLite/events-500-4             18.54k ± 0%
GetTimeline_SQLite/events-1000-4            37.29k ± 0%
geomean                                     1.162k

cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                                   │ benchmark-results.txt │
                                   │        sec/op         │
EventStoreAppend_InMemory-4                   1.123µ ± 16%
EventStoreAppend_SQLite-4                     943.3µ ±  3%
GetTimeline_InMemory/events-10-4              13.75µ ±  4%
GetTimeline_InMemory/events-50-4              77.89µ ±  3%
GetTimeline_InMemory/events-100-4             158.0µ ±  2%
GetTimeline_InMemory/events-500-4             784.0µ ± 18%
GetTimeline_InMemory/events-1000-4            1.303m ±  1%
GetTimeline_SQLite/events-10-4                83.73µ ±  1%
GetTimeline_SQLite/events-50-4                244.8µ ±  1%
GetTimeline_SQLite/events-100-4               440.7µ ±  2%
GetTimeline_SQLite/events-500-4               1.972m ±  1%
GetTimeline_SQLite/events-1000-4              3.836m ±  1%
geomean                                       219.5µ

                                   │ benchmark-results.txt │
                                   │         B/op          │
EventStoreAppend_InMemory-4                    749.0 ± 13%
EventStoreAppend_SQLite-4                    1.984Ki ±  1%
GetTimeline_InMemory/events-10-4             7.953Ki ±  0%
GetTimeline_InMemory/events-50-4             46.62Ki ±  0%
GetTimeline_InMemory/events-100-4            94.48Ki ±  0%
GetTimeline_InMemory/events-500-4            472.8Ki ±  0%
GetTimeline_InMemory/events-1000-4           944.3Ki ±  0%
GetTimeline_SQLite/events-10-4               16.74Ki ±  0%
GetTimeline_SQLite/events-50-4               87.14Ki ±  0%
GetTimeline_SQLite/events-100-4              175.4Ki ±  0%
GetTimeline_SQLite/events-500-4              846.1Ki ±  0%
GetTimeline_SQLite/events-1000-4             1.639Mi ±  0%
geomean                                      67.05Ki

                                   │ benchmark-results.txt │
                                   │       allocs/op       │
EventStoreAppend_InMemory-4                     7.000 ± 0%
EventStoreAppend_SQLite-4                       53.00 ± 0%
GetTimeline_InMemory/events-10-4                125.0 ± 0%
GetTimeline_InMemory/events-50-4                653.0 ± 0%
GetTimeline_InMemory/events-100-4              1.306k ± 0%
GetTimeline_InMemory/events-500-4              6.514k ± 0%
GetTimeline_InMemory/events-1000-4             13.02k ± 0%
GetTimeline_SQLite/events-10-4                  382.0 ± 0%
GetTimeline_SQLite/events-50-4                 1.852k ± 0%
GetTimeline_SQLite/events-100-4                3.681k ± 0%
GetTimeline_SQLite/events-500-4                18.54k ± 0%
GetTimeline_SQLite/events-1000-4               37.29k ± 0%
geomean                                        1.162k

Benchmarks run with go test -bench=. -benchmem -count=6.
Regressions ≥ 20% are flagged. Results compared via benchstat.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 13, 2026

Codecov Report

❌ Patch coverage is 81.53846% with 12 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
plugin/external/convert.go 81.53% 6 Missing and 6 partials ⚠️

📢 Thoughts on this report? Let us know!

@intel352 intel352 merged commit 710af7f into main May 13, 2026
27 checks passed
@intel352 intel352 deleted the fix/strict-proto-scalar-coerce branch May 13, 2026 06:57
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