Skip to content

fix(plugin/external): tolerate Unimplemented GetManifest for strict-cutover IaC plugins#627

Merged
intel352 merged 1 commit into
mainfrom
fix/iac-getmanifest-unimplemented
May 10, 2026
Merged

fix(plugin/external): tolerate Unimplemented GetManifest for strict-cutover IaC plugins#627
intel352 merged 1 commit into
mainfrom
fix/iac-getmanifest-unimplemented

Conversation

@intel352

Copy link
Copy Markdown
Contributor

Summary

Why

Observed end-to-end via core-dump strict-contracts-smoke run 25642339926 against staging:

rpc error: code = Unimplemented desc = method GetManifest not implemented
load plugin "digitalocean": get manifest from plugin digitalocean
error: audit-keys: no loaded provider implements EnumeratorAll

The bridge's inline doc explicitly states GetManifest stays Unimplemented; the missing piece is the loader-side relaxation that mirrors the existing GetContractRegistry Unimplemented tolerance (adapter.go:118).

Test plan

  • TestNewExternalPluginAdapter_GetManifestUnimplemented_SynthesizesFromName — passes
  • TestNewExternalPluginAdapter_GetManifestNonUnimplementedError_Fails — passes (non-Unimplemented errors still surface)
  • go test ./plugin/external/... clean
  • core-dump strict-contracts-smoke against v0.51.1 → green

🤖 Generated with Claude Code

…utover IaC plugins

NewExternalPluginAdapter currently fails outright when GetManifest returns
codes.Unimplemented. PR #623 added the iacPluginServiceBridge that wires
GetContractRegistry for strict-cutover IaC plugins (DO v1.0.0+), but the
bridge intentionally leaves GetManifest unimplemented (per the bridge's
inline comment). Loader-side adapter.go didn't get a matching relaxation,
so DO v1.0.1 loads its gRPC server, then immediately fails:

  rpc error: code = Unimplemented desc = method GetManifest not implemented
  load plugin "digitalocean": get manifest from plugin digitalocean

This blocks every consumer running typed-IaC dispatch against a
strict-cutover plugin. Observed end-to-end via core-dump
strict-contracts-smoke run 25642339926 against staging.

Fix: when GetManifest returns codes.Unimplemented, synthesize a minimal
Manifest{Name: name} from the param-passed plugin name. Downstream
accessors (Name/Version/Description/etc.) return sensible values; the
loader already keys off the param-passed name everywhere meaningful
(adapter.go:111). Non-Unimplemented errors still fail as before.

Tests:
- TestNewExternalPluginAdapter_GetManifestUnimplemented_SynthesizesFromName
- TestNewExternalPluginAdapter_GetManifestNonUnimplementedError_Fails

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 10, 2026 23:12

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 updates the external plugin loader to tolerate strict-cutover IaC plugins that intentionally do not implement PluginService.GetManifest, allowing typed-IaC dispatch consumers to load such plugins successfully.

Changes:

  • Treat GetManifest returning codes.Unimplemented as non-fatal and synthesize a minimal pb.Manifest{Name: <plugin name>}.
  • Add regression tests covering both the tolerated Unimplemented case and the still-fatal non-Unimplemented error case.

Reviewed changes

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

File Description
plugin/external/adapter.go Relaxes adapter initialization by tolerating GetManifest being unimplemented and synthesizing a minimal manifest from the passed plugin name.
plugin/external/adapter_test.go Adds tests ensuring Unimplemented is tolerated (manifest synthesized) while other errors still fail adapter creation.

@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:326108: parsing iteration count: invalid syntax
baseline-bench.txt:688197: parsing iteration count: invalid syntax
baseline-bench.txt:1059622: parsing iteration count: invalid syntax
baseline-bench.txt:1371428: parsing iteration count: invalid syntax
baseline-bench.txt:1682832: parsing iteration count: invalid syntax
benchmark-results.txt:262: parsing iteration count: invalid syntax
benchmark-results.txt:343727: parsing iteration count: invalid syntax
benchmark-results.txt:670770: parsing iteration count: invalid syntax
benchmark-results.txt:1007401: parsing iteration count: invalid syntax
benchmark-results.txt:1329821: parsing iteration count: invalid syntax
benchmark-results.txt:1666350: parsing iteration count: invalid syntax
goos: linux
goarch: amd64
pkg: github.com/GoCodeAlone/workflow/dynamic
cpu: AMD EPYC 9V74 80-Core Processor                
                            │ benchmark-results.txt │
                            │        sec/op         │
InterpreterCreation-4                 4.766m ± 112%
ComponentLoad-4                       3.463m ±   6%
ComponentExecute-4                    1.828µ ±   0%
PoolContention/workers-1-4            1.012µ ±   2%
PoolContention/workers-2-4            1.004µ ±   2%
PoolContention/workers-4-4            1.010µ ±   0%
PoolContention/workers-8-4            1.010µ ±   4%
PoolContention/workers-16-4           1.004µ ±   2%
ComponentLifecycle-4                  3.453m ±   0%
SourceValidation-4                    2.076µ ±   2%
RegistryConcurrent-4                  778.7n ±   4%
LoaderLoadFromString-4                3.507m ±   1%
geomean                               17.07µ

                            │ 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: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                            │ baseline-bench.txt │
                            │       sec/op       │
InterpreterCreation-4              4.302m ± 131%
ComponentLoad-4                    3.474m ±  11%
ComponentExecute-4                 1.863µ ±   1%
PoolContention/workers-1-4         1.187µ ±   1%
PoolContention/workers-2-4         1.207µ ±   2%
PoolContention/workers-4-4         1.187µ ±   1%
PoolContention/workers-8-4         1.202µ ±   2%
PoolContention/workers-16-4        1.208µ ±   2%
ComponentLifecycle-4               3.574m ±   3%
SourceValidation-4                 2.292µ ±   0%
RegistryConcurrent-4               950.1n ±   5%
LoaderLoadFromString-4             3.632m ±   1%
geomean                            18.79µ

                            │ 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 9V74 80-Core Processor                
                                  │ benchmark-results.txt │
                                  │        sec/op         │
CircuitBreakerDetection-4                    298.4n ± 18%
CircuitBreakerExecution_Success-4            22.68n ±  2%
CircuitBreakerExecution_Failure-4            70.97n ±  0%
geomean                                      78.32n

                                  │ 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: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                                  │ baseline-bench.txt │
                                  │       sec/op       │
CircuitBreakerDetection-4                  459.4n ± 2%
CircuitBreakerExecution_Success-4          59.75n ± 1%
CircuitBreakerExecution_Failure-4          64.89n ± 0%
geomean                                    121.2n

                                  │ 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 9V74 80-Core Processor                
                                 │ benchmark-results.txt │
                                 │        sec/op         │
JQTransform_Simple-4                        820.3n ± 31%
JQTransform_ObjectConstruction-4            1.389µ ±  0%
JQTransform_ArraySelect-4                   3.398µ ±  0%
JQTransform_Complex-4                       41.60µ ±  1%
JQTransform_Throughput-4                    1.693µ ±  0%
SSEPublishDelivery-4                        64.47n ±  1%
geomean                                     1.612µ

                                 │ 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

cpu: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                                 │ baseline-bench.txt │
                                 │       sec/op       │
JQTransform_Simple-4                     984.6n ± 22%
JQTransform_ObjectConstruction-4         1.505µ ±  4%
JQTransform_ArraySelect-4                3.246µ ±  2%
JQTransform_Complex-4                    35.99µ ±  0%
JQTransform_Throughput-4                 1.818µ ±  1%
SSEPublishDelivery-4                     77.53n ±  1%
geomean                                  1.703µ

                                 │ 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

pkg: github.com/GoCodeAlone/workflow/schema
cpu: AMD EPYC 9V74 80-Core Processor                
                                    │ benchmark-results.txt │
                                    │        sec/op         │
SchemaValidation_Simple-4                      1.075µ ± 21%
SchemaValidation_AllFields-4                   1.627µ ±  1%
SchemaValidation_FormatValidation-4            1.576µ ±  1%
SchemaValidation_ManySchemas-4                 1.594µ ±  4%
geomean                                        1.448µ

                                    │ 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: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                                    │ baseline-bench.txt │
                                    │       sec/op       │
SchemaValidation_Simple-4                    1.069µ ± 9%
SchemaValidation_AllFields-4                 1.538µ ± 2%
SchemaValidation_FormatValidation-4          1.506µ ± 2%
SchemaValidation_ManySchemas-4               1.499µ ± 3%
geomean                                      1.388µ

                                    │ 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 9V74 80-Core Processor                
                                   │ benchmark-results.txt │
                                   │        sec/op         │
EventStoreAppend_InMemory-4                   1.101µ ± 20%
EventStoreAppend_SQLite-4                     1.025m ±  2%
GetTimeline_InMemory/events-10-4              12.82µ ±  4%
GetTimeline_InMemory/events-50-4              70.70µ ±  3%
GetTimeline_InMemory/events-100-4             142.3µ ±  2%
GetTimeline_InMemory/events-500-4             560.9µ ±  0%
GetTimeline_InMemory/events-1000-4            1.141m ±  1%
GetTimeline_SQLite/events-10-4                83.64µ ±  1%
GetTimeline_SQLite/events-50-4                219.6µ ±  0%
GetTimeline_SQLite/events-100-4               382.0µ ±  0%
GetTimeline_SQLite/events-500-4               1.659m ±  1%
GetTimeline_SQLite/events-1000-4              3.241m ±  0%
geomean                                       197.5µ

                                   │ benchmark-results.txt │
                                   │         B/op          │
EventStoreAppend_InMemory-4                    753.5 ± 15%
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.08Ki

                                   │ 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: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz
                                   │ baseline-bench.txt │
                                   │       sec/op       │
EventStoreAppend_InMemory-4                1.093µ ±  9%
EventStoreAppend_SQLite-4                  992.7µ ±  5%
GetTimeline_InMemory/events-10-4           13.46µ ±  5%
GetTimeline_InMemory/events-50-4           75.14µ ± 21%
GetTimeline_InMemory/events-100-4          116.8µ ±  1%
GetTimeline_InMemory/events-500-4          596.3µ ±  1%
GetTimeline_InMemory/events-1000-4         1.215m ±  1%
GetTimeline_SQLite/events-10-4             81.62µ ±  3%
GetTimeline_SQLite/events-50-4             237.4µ ±  1%
GetTimeline_SQLite/events-100-4            431.2µ ±  2%
GetTimeline_SQLite/events-500-4            1.897m ±  4%
GetTimeline_SQLite/events-1000-4           3.735m ±  2%
geomean                                    205.0µ

                                   │ baseline-bench.txt │
                                   │        B/op        │
EventStoreAppend_InMemory-4                  807.5 ± 7%
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 c4564d5 into main May 10, 2026
26 checks passed
@intel352 intel352 deleted the fix/iac-getmanifest-unimplemented branch May 10, 2026 23:25
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