Skip to content

fix(wfctl): accept provider contract descriptor arrays#865

Merged
intel352 merged 1 commit into
mainfrom
fix/issue-862-contract-array
Jun 6, 2026
Merged

fix(wfctl): accept provider contract descriptor arrays#865
intel352 merged 1 commit into
mainfrom
fix/issue-862-contract-array

Conversation

@intel352
Copy link
Copy Markdown
Contributor

@intel352 intel352 commented Jun 6, 2026

Summary

Fixes #862.

wfctl plugin validate-contract now accepts provider contract descriptor arrays in plugin.contracts.json, matching the already-tolerated inline plugin.json.contracts array shape. This keeps strict Workflow plugin contract descriptors supported while ignoring provider descriptor entries such as {id,path,schema} instead of failing the release gate.

Verification

  • GOWORK=off go test ./cmd/wfctl -run TestRunPluginValidateContract_ProviderDescriptorArrayIsIgnoredByStrictContracts -count=1
  • GOWORK=off go run ./cmd/wfctl plugin validate-contract --for-publish --tag v0.1.8 ../../../workflow-plugin-product-capture
  • GOWORK=off go test ./cmd/wfctl -count=1

Regression Proof

With the production parser fix reverted and the new test left in place:

FAIL TestRunPluginValidateContract_ProviderDescriptorArrayIsIgnoredByStrictContracts
invalid_plugin_contract_descriptors: json: cannot unmarshal array into Go value of type main.pluginContractDescriptorFile

With the fix restored:

ok github.com/GoCodeAlone/workflow/cmd/wfctl

Copilot AI review requested due to automatic review settings June 6, 2026 07:46
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 fixes wfctl plugin validate-contract so it can parse plugin.contracts.json when it is a top-level JSON array (provider-style descriptors like {id,path,schema}), matching the already-supported “contracts as array” parsing behavior and preventing publish gate failures.

Changes:

  • Update contract-descriptor parsing to accept either a JSON array of descriptors or the structured { descriptorSetRef, contracts: [...] } file shape.
  • Reuse a shared byte-level parser for both inline plugin.json contracts and plugin.contracts.json file parsing.
  • Add a regression test ensuring provider descriptor arrays are ignored (rather than treated as an invalid strict-contract descriptor file).

Reviewed changes

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

File Description
cmd/wfctl/plugin_audit.go Makes plugin.contracts.json parsing accept either array or object shapes by routing through a shared parser.
cmd/wfctl/plugin_validate_contract_test.go Adds regression coverage for provider-style descriptor arrays so validate-contract --for-publish no longer fails on that shape.

@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 6, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 6, 2026

⏱ Benchmark Results

No significant performance regressions detected.

benchstat comparison (baseline → PR)
## benchstat: baseline → PR
baseline-bench.txt:304: parsing iteration count: invalid syntax
baseline-bench.txt:295589: parsing iteration count: invalid syntax
baseline-bench.txt:632829: parsing iteration count: invalid syntax
baseline-bench.txt:963295: parsing iteration count: invalid syntax
baseline-bench.txt:1272194: parsing iteration count: invalid syntax
baseline-bench.txt:1559220: parsing iteration count: invalid syntax
benchmark-results.txt:304: parsing iteration count: invalid syntax
benchmark-results.txt:355028: parsing iteration count: invalid syntax
benchmark-results.txt:696564: parsing iteration count: invalid syntax
benchmark-results.txt:1031554: parsing iteration count: invalid syntax
benchmark-results.txt:1369757: parsing iteration count: invalid syntax
benchmark-results.txt:1671699: parsing iteration count: invalid syntax
goos: linux
goarch: amd64
pkg: github.com/GoCodeAlone/workflow/dynamic
cpu: AMD EPYC 7763 64-Core Processor                
                            │ benchmark-results.txt │
                            │        sec/op         │
InterpreterCreation-4                  9.013m ± 64%
ComponentLoad-4                        3.667m ±  1%
ComponentExecute-4                     1.956µ ±  0%
PoolContention/workers-1-4             1.098µ ±  1%
PoolContention/workers-2-4             1.102µ ±  2%
PoolContention/workers-4-4             1.108µ ±  4%
PoolContention/workers-8-4             1.103µ ±  1%
PoolContention/workers-16-4            1.102µ ±  1%
ComponentLifecycle-4                   3.643m ±  1%
SourceValidation-4                     2.365µ ±  1%
RegistryConcurrent-4                   795.5n ±  1%
LoaderLoadFromString-4                 3.648m ±  2%
geomean                                19.28µ

                            │ 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

cpu: AMD EPYC 9V74 80-Core Processor                
                            │ baseline-bench.txt │
                            │       sec/op       │
InterpreterCreation-4               8.930m ± 65%
ComponentLoad-4                     3.680m ± 10%
ComponentExecute-4                  1.833µ ±  1%
PoolContention/workers-1-4          1.009µ ±  3%
PoolContention/workers-2-4          1.015µ ±  3%
PoolContention/workers-4-4          1.037µ ±  1%
PoolContention/workers-8-4          1.023µ ±  2%
PoolContention/workers-16-4         1.010µ ±  1%
ComponentLifecycle-4                3.503m ±  2%
SourceValidation-4                  2.087µ ±  1%
RegistryConcurrent-4                738.6n ±  4%
LoaderLoadFromString-4              3.637m ±  3%
geomean                             18.17µ

                            │ 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

pkg: github.com/GoCodeAlone/workflow/middleware
cpu: AMD EPYC 7763 64-Core Processor                
                                  │ benchmark-results.txt │
                                  │        sec/op         │
CircuitBreakerDetection-4                     288.3n ± 5%
CircuitBreakerExecution_Success-4             21.45n ± 0%
CircuitBreakerExecution_Failure-4             65.44n ± 1%
geomean                                       73.96n

                                  │ 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

cpu: AMD EPYC 9V74 80-Core Processor                
                                  │ baseline-bench.txt │
                                  │       sec/op       │
CircuitBreakerDetection-4                  297.2n ± 4%
CircuitBreakerExecution_Success-4          22.65n ± 0%
CircuitBreakerExecution_Failure-4          70.95n ± 0%
geomean                                    78.17n

                                  │ 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

pkg: github.com/GoCodeAlone/workflow/module
cpu: AMD EPYC 7763 64-Core Processor                
                                 │ benchmark-results.txt │
                                 │        sec/op         │
IaCStateBackend_InProcess-4                 307.0n ± 40%
IaCStateBackend_GRPC-4                      9.508m ±  3%
JQTransform_Simple-4                        689.4n ± 35%
JQTransform_ObjectConstruction-4            1.548µ ±  0%
JQTransform_ArraySelect-4                   3.472µ ±  1%
JQTransform_Complex-4                       40.25µ ±  1%
JQTransform_Throughput-4                    1.895µ ±  0%
SSEPublishDelivery-4                        66.69n ±  1%
geomean                                     3.913µ

                                 │ benchmark-results.txt │
                                 │         B/op          │
IaCStateBackend_InProcess-4                 416.0 ± 0%
IaCStateBackend_GRPC-4                    5.926Mi ± 7%
JQTransform_Simple-4                      1.273Ki ± 0%
JQTransform_ObjectConstruction-4          1.773Ki ± 0%
JQTransform_ArraySelect-4                 2.625Ki ± 0%
JQTransform_Complex-4                     16.31Ki ± 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       │
IaCStateBackend_InProcess-4                 2.000 ± 0%
IaCStateBackend_GRPC-4                     6.835k ± 0%
JQTransform_Simple-4                        10.00 ± 0%
JQTransform_ObjectConstruction-4            15.00 ± 0%
JQTransform_ArraySelect-4                   30.00 ± 0%
JQTransform_Complex-4                       328.0 ± 0%
JQTransform_Throughput-4                    17.00 ± 0%
SSEPublishDelivery-4                        0.000 ± 0%
geomean                                                ¹
¹ summaries must be >0 to compute geomean

cpu: AMD EPYC 9V74 80-Core Processor                
                                 │ baseline-bench.txt │
                                 │       sec/op       │
IaCStateBackend_InProcess-4              296.6n ± 35%
IaCStateBackend_GRPC-4                   10.27m ±  8%
JQTransform_Simple-4                     668.0n ± 30%
JQTransform_ObjectConstruction-4         1.474µ ±  2%
JQTransform_ArraySelect-4                3.440µ ±  0%
JQTransform_Complex-4                    41.68µ ±  0%
JQTransform_Throughput-4                 1.782µ ±  2%
SSEPublishDelivery-4                     65.74n ±  3%
geomean                                  3.871µ

                                 │ baseline-bench.txt │
                                 │        B/op        │
IaCStateBackend_InProcess-4             416.0 ±  0%
IaCStateBackend_GRPC-4                5.806Mi ± 15%
JQTransform_Simple-4                  1.273Ki ±  0%
JQTransform_ObjectConstruction-4      1.773Ki ±  0%
JQTransform_ArraySelect-4             2.625Ki ±  0%
JQTransform_Complex-4                 16.31Ki ±  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      │
IaCStateBackend_InProcess-4              2.000 ± 0%
IaCStateBackend_GRPC-4                  6.862k ± 0%
JQTransform_Simple-4                     10.00 ± 0%
JQTransform_ObjectConstruction-4         15.00 ± 0%
JQTransform_ArraySelect-4                30.00 ± 0%
JQTransform_Complex-4                    328.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 7763 64-Core Processor                
                                    │ benchmark-results.txt │
                                    │        sec/op         │
SchemaValidation_Simple-4                      1.104µ ± 29%
SchemaValidation_AllFields-4                   1.654µ ±  1%
SchemaValidation_FormatValidation-4            1.581µ ±  1%
SchemaValidation_ManySchemas-4                 1.775µ ±  2%
geomean                                        1.504µ

                                    │ 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

cpu: AMD EPYC 9V74 80-Core Processor                
                                    │ baseline-bench.txt │
                                    │       sec/op       │
SchemaValidation_Simple-4                   1.125µ ± 14%
SchemaValidation_AllFields-4                1.636µ ±  6%
SchemaValidation_FormatValidation-4         1.644µ ±  4%
SchemaValidation_ManySchemas-4              1.597µ ±  2%
geomean                                     1.482µ

                                    │ 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

pkg: github.com/GoCodeAlone/workflow/store
cpu: AMD EPYC 7763 64-Core Processor                
                                   │ benchmark-results.txt │
                                   │        sec/op         │
EventStoreAppend_InMemory-4                   1.325µ ± 16%
EventStoreAppend_SQLite-4                     1.350m ±  2%
GetTimeline_InMemory/events-10-4              14.54µ ±  3%
GetTimeline_InMemory/events-50-4              80.69µ ±  4%
GetTimeline_InMemory/events-100-4             161.8µ ± 23%
GetTimeline_InMemory/events-500-4             640.6µ ±  0%
GetTimeline_InMemory/events-1000-4            1.311m ±  1%
GetTimeline_SQLite/events-10-4                72.19µ ±  1%
GetTimeline_SQLite/events-50-4                217.1µ ±  1%
GetTimeline_SQLite/events-100-4               393.1µ ±  0%
GetTimeline_SQLite/events-500-4               1.793m ±  1%
GetTimeline_SQLite/events-1000-4              3.534m ±  1%
geomean                                       217.4µ

                                   │ benchmark-results.txt │
                                   │         B/op          │
EventStoreAppend_InMemory-4                     794.0 ± 8%
EventStoreAppend_SQLite-4                     1.986Ki ± 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.38Ki

                                   │ 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

cpu: AMD EPYC 9V74 80-Core Processor                
                                   │ baseline-bench.txt │
                                   │       sec/op       │
EventStoreAppend_InMemory-4                1.076µ ± 26%
EventStoreAppend_SQLite-4                  1.076m ±  6%
GetTimeline_InMemory/events-10-4           13.31µ ±  3%
GetTimeline_InMemory/events-50-4           72.56µ ± 25%
GetTimeline_InMemory/events-100-4          109.1µ ±  1%
GetTimeline_InMemory/events-500-4          557.6µ ±  1%
GetTimeline_InMemory/events-1000-4         1.142m ±  1%
GetTimeline_SQLite/events-10-4             57.64µ ±  0%
GetTimeline_SQLite/events-50-4             190.5µ ±  0%
GetTimeline_SQLite/events-100-4            351.3µ ±  1%
GetTimeline_SQLite/events-500-4            1.630m ±  1%
GetTimeline_SQLite/events-1000-4           3.218m ±  1%
geomean                                    184.7µ

                                   │ baseline-bench.txt │
                                   │        B/op        │
EventStoreAppend_InMemory-4                  807.0 ± 8%
EventStoreAppend_SQLite-4                  1.985Ki ± 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.47Ki

                                   │ 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

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

@intel352 intel352 merged commit 888aa29 into main Jun 6, 2026
23 checks passed
@intel352 intel352 deleted the fix/issue-862-contract-array branch June 6, 2026 08:05
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.

wfctl v0.74.3 validate-contract rejects provider descriptor contracts array

2 participants