Skip to content

feat(iac): provider service-registration + IaCProviderRegionLister (infra-admin migration PR-1)#836

Merged
intel352 merged 4 commits into
mainfrom
feat/iac-provider-service-reg-2026-06-02T0104
Jun 2, 2026
Merged

feat(iac): provider service-registration + IaCProviderRegionLister (infra-admin migration PR-1)#836
intel352 merged 4 commits into
mainfrom
feat/iac-provider-service-reg-2026-06-02T0104

Conversation

@intel352
Copy link
Copy Markdown
Contributor

@intel352 intel352 commented Jun 2, 2026

PR-1 of the infra-admin plugin migration (design + plan + ADRs, merged). Foundational core capability — this is the gap that made v1/v1.1 infra-admin never function at runtime (an external iac.provider plugin was never registered as an interfaces.IaCProvider service).

Tasks (TDD, one commit each)

  • T1 interfaces.IaCProviderRegionLister — new optional sub-interface (type-asserted), mirrors Enumerator/DriftDetector.
  • T2 iac/providerclient — core-importable adapter wrapping the plugin/external/proto IaC gRPC clients (IaCProviderRequired + optional RegionLister/DriftDetector) as interfaces.IaCProvider. Tested against an in-proc gRPC server.
  • T3 ExternalPluginAdapter.WiringHooks() (was nil) now detects iac.provider plugins via diskManifest.IaCServices and returns a hook that app.RegisterService(<moduleName>, providerclient.New(conn)) (precedent: module/iac_module.go:94). Registers before any step executes (hook runs in buildFromConfig, after Init, before Start).

ADR 0013 (steps bind interfaces.IaCProvider) + ADR 0014 (this registration mechanism). No new IaCProviderProvider interface; existing PlatformProvider step.iac_* untouched.

Lead-verified: GOWORK=off go build ./... green; interfaces/iac/providerclient/plugin/external tests pass; golangci-lint --new-from-rev=origin/main 0 issues.

🤖 Generated with Claude Code

intel352 and others added 3 commits June 2, 2026 02:04
Mirrors the Enumerator/DriftDetector/ProviderValidator optional-interface
pattern. Callers type-assert and fall back to a static catalog when the
provider doesn't implement it. Foundational for step.iac_provider_catalog
and the core gRPC-client adapter (Task 2).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
….IaCProvider

Core-importable adapter wrapping pb.IaCProviderRequiredClient +
pb.IaCProviderRegionListerClient as interfaces.IaCProvider +
interfaces.IaCProviderRegionLister. Replicates the proto↔interfaces
conversion helpers from cmd/wfctl/iac_typed_adapter.go (package main,
not importable). Enables WiringHook service registration in Task 3 so
engine steps can resolve external iac.provider plugins via app.GetService.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…CProvider services via WiringHook

ExternalPluginAdapter.WiringHooks() now detects iac.provider plugins by
inspecting the ContractRegistry (and diskManifest.IaCServices fallback)
for the IaCProviderRequired service name — the analog of IaCStateBackend
detection. For each such plugin, a WiringHook is returned whose closure
captures adapter.Conn() and calls app.RegisterService(<pluginName>,
providerclient.New(conn)) when the engine runs hooks during BuildFromConfig
(after app.Init(), before app.Start()). Steps resolve the provider via
app.GetService(cfg.Provider, &provider) under the plugin name.

This is the foundational gap that v1/v1.1 infra-admin silently lacked:
external iac.provider plugins were loaded but never registered as services,
so app.GetService(name, &provider) found nothing at step execution time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 2, 2026 06:19
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

PR-1 of the infra-admin plugin migration: adds the foundational core capability that lets external iac.provider plugins be registered as interfaces.IaCProvider services in the modular DI graph. Introduces a new optional sub-interface, a core-importable gRPC-client adapter, and a WiringHook on ExternalPluginAdapter that performs the registration before any pipeline step runs.

Changes:

  • New optional interfaces.IaCProviderRegionLister sub-interface (type-asserted; mirrors Enumerator/DriftDetector).
  • New iac/providerclient package wrapping the proto IaC gRPC clients as interfaces.IaCProvider (+ optional region lister), with bufconn-based tests.
  • ExternalPluginAdapter.WiringHooks() now detects iac.provider plugins via contract-registry / disk-manifest and registers a providerclient.Adapter under the plugin name.

Reviewed changes

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

Show a summary per file
File Description
interfaces/iac_provider.go Adds optional IaCProviderRegionLister interface.
interfaces/iac_provider_test.go Asserts the new optional interface is genuinely optional.
iac/providerclient/adapter.go New core-importable proto↔interfaces adapter implementing IaCProvider + IaCProviderRegionLister.
iac/providerclient/adapter_test.go In-proc gRPC tests for the adapter and compile-time interface assertions.
plugin/external/adapter.go Implements WiringHooks() to register iac.provider adapters as services.
plugin/external/iac_provider_wiring_test.go Tests the new wiring hook against a fake gRPC server and the modular app.

Comment thread iac/providerclient/adapter.go Outdated
Comment on lines +52 to +58
func New(conn grpc.ClientConnInterface) *Adapter {
return &Adapter{
conn: conn,
required: pb.NewIaCProviderRequiredClient(conn),
regionLister: pb.NewIaCProviderRegionListerClient(conn),
}
}
Comment thread iac/providerclient/adapter.go Outdated
Comment on lines +145 to +152
// DetectDrift calls IaCProviderRequired.Status to satisfy the IaCProvider interface.
// This is a stub implementation — the required interface needs DetectDrift, so we
// surface a not-implemented error. Full drift detection is available via the
// IaCProviderDriftDetector optional service, which is not in scope for PR-1.
func (a *Adapter) DetectDrift(ctx context.Context, resources []interfaces.ResourceRef) ([]interfaces.DriftResult, error) {
return nil, fmt.Errorf("%w: DetectDrift optional service not wired in PR-1 adapter",
interfaces.ErrProviderMethodUnimplemented)
}
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 2, 2026

Codecov Report

❌ Patch coverage is 38.03132% with 277 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
iac/providerclient/adapter.go 36.45% 234 Missing and 24 partials ⚠️
plugin/external/adapter.go 53.65% 11 Missing and 8 partials ⚠️

📢 Thoughts on this report? Let us know!

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

⏱ Benchmark Results

No significant performance regressions detected.

benchstat comparison (baseline → PR)
## benchstat: baseline → PR
baseline-bench.txt:306: parsing iteration count: invalid syntax
baseline-bench.txt:337870: parsing iteration count: invalid syntax
baseline-bench.txt:641414: parsing iteration count: invalid syntax
baseline-bench.txt:948747: parsing iteration count: invalid syntax
baseline-bench.txt:1280773: parsing iteration count: invalid syntax
baseline-bench.txt:1600274: parsing iteration count: invalid syntax
benchmark-results.txt:308: parsing iteration count: invalid syntax
benchmark-results.txt:299106: parsing iteration count: invalid syntax
benchmark-results.txt:584458: parsing iteration count: invalid syntax
benchmark-results.txt:918614: parsing iteration count: invalid syntax
benchmark-results.txt:1256550: parsing iteration count: invalid syntax
benchmark-results.txt:1530505: parsing iteration count: invalid syntax
goos: linux
goarch: amd64
pkg: github.com/GoCodeAlone/workflow/dynamic
cpu: AMD EPYC 7763 64-Core Processor                
                            │ baseline-bench.txt │       benchmark-results.txt        │
                            │       sec/op       │    sec/op     vs base              │
InterpreterCreation-4               10.24m ± 63%   10.33m ± 65%       ~ (p=0.937 n=6)
ComponentLoad-4                     3.544m ±  1%   3.584m ± 11%  +1.12% (p=0.004 n=6)
ComponentExecute-4                  1.917µ ±  1%   1.905µ ±  1%       ~ (p=0.180 n=6)
PoolContention/workers-1-4          1.070µ ±  3%   1.075µ ±  1%       ~ (p=0.372 n=6)
PoolContention/workers-2-4          1.075µ ±  3%   1.104µ ±  3%       ~ (p=0.167 n=6)
PoolContention/workers-4-4          1.070µ ±  0%   1.122µ ±  1%  +4.86% (p=0.002 n=6)
PoolContention/workers-8-4          1.086µ ±  2%   1.124µ ±  1%  +3.45% (p=0.004 n=6)
PoolContention/workers-16-4         1.089µ ±  2%   1.086µ ±  3%       ~ (p=0.667 n=6)
ComponentLifecycle-4                3.607m ±  0%   3.634m ±  3%       ~ (p=1.000 n=6)
SourceValidation-4                  2.344µ ±  0%   2.330µ ±  1%       ~ (p=0.457 n=6)
RegistryConcurrent-4                845.4n ±  6%   796.3n ±  3%  -5.81% (p=0.015 n=6)
LoaderLoadFromString-4              3.565m ±  1%   3.597m ±  1%  +0.90% (p=0.015 n=6)
geomean                             19.25µ         19.36µ        +0.61%

                            │ baseline-bench.txt │        benchmark-results.txt         │
                            │        B/op        │     B/op      vs base                │
InterpreterCreation-4               2.027Mi ± 0%   2.027Mi ± 0%       ~ (p=0.457 n=6)
ComponentLoad-4                     2.180Mi ± 0%   2.180Mi ± 0%       ~ (p=0.420 n=6)
ComponentExecute-4                  1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-1-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-2-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-4-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-8-4          1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-16-4         1.203Ki ± 0%   1.203Ki ± 0%       ~ (p=1.000 n=6) ¹
ComponentLifecycle-4                2.183Mi ± 0%   2.183Mi ± 0%       ~ (p=0.145 n=6)
SourceValidation-4                  1.984Ki ± 0%   1.984Ki ± 0%       ~ (p=1.000 n=6) ¹
RegistryConcurrent-4                1.133Ki ± 0%   1.133Ki ± 0%       ~ (p=1.000 n=6) ¹
LoaderLoadFromString-4              2.182Mi ± 0%   2.182Mi ± 0%       ~ (p=0.162 n=6)
geomean                             15.25Ki        15.25Ki       +0.00%
¹ all samples are equal

                            │ baseline-bench.txt │        benchmark-results.txt        │
                            │     allocs/op      │  allocs/op   vs base                │
InterpreterCreation-4                15.68k ± 0%   15.68k ± 0%       ~ (p=1.000 n=6)
ComponentLoad-4                      18.02k ± 0%   18.02k ± 0%       ~ (p=1.000 n=6)
ComponentExecute-4                    25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-1-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-2-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-4-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-8-4            25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
PoolContention/workers-16-4           25.00 ± 0%    25.00 ± 0%       ~ (p=1.000 n=6) ¹
ComponentLifecycle-4                 18.07k ± 0%   18.07k ± 0%       ~ (p=1.000 n=6) ¹
SourceValidation-4                    32.00 ± 0%    32.00 ± 0%       ~ (p=1.000 n=6) ¹
RegistryConcurrent-4                  2.000 ± 0%    2.000 ± 0%       ~ (p=1.000 n=6) ¹
LoaderLoadFromString-4               18.06k ± 0%   18.06k ± 0%       ~ (p=1.000 n=6) ¹
geomean                               183.3         183.3       +0.00%
¹ all samples are equal

pkg: github.com/GoCodeAlone/workflow/middleware
                                  │ baseline-bench.txt │       benchmark-results.txt       │
                                  │       sec/op       │   sec/op     vs base              │
CircuitBreakerDetection-4                  284.2n ± 4%   285.2n ± 2%       ~ (p=0.457 n=6)
CircuitBreakerExecution_Success-4          21.51n ± 1%   21.53n ± 2%       ~ (p=0.719 n=6)
CircuitBreakerExecution_Failure-4          66.07n ± 0%   65.78n ± 0%  -0.44% (p=0.002 n=6)
geomean                                    73.92n        73.92n       -0.00%

                                  │ baseline-bench.txt │       benchmark-results.txt        │
                                  │        B/op        │    B/op     vs base                │
CircuitBreakerDetection-4                 144.0 ± 0%     144.0 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Success-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Failure-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                              ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                  │ baseline-bench.txt │       benchmark-results.txt        │
                                  │     allocs/op      │ allocs/op   vs base                │
CircuitBreakerDetection-4                 1.000 ± 0%     1.000 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Success-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
CircuitBreakerExecution_Failure-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                              ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/module
                                 │ baseline-bench.txt │       benchmark-results.txt        │
                                 │       sec/op       │    sec/op     vs base              │
IaCStateBackend_InProcess-4              345.7n ± 14%   346.0n ± 16%       ~ (p=1.000 n=6)
IaCStateBackend_GRPC-4                   9.465m ±  4%   9.541m ±  3%       ~ (p=0.394 n=6)
JQTransform_Simple-4                     676.8n ± 34%   714.9n ± 27%       ~ (p=0.310 n=6)
JQTransform_ObjectConstruction-4         1.502µ ±  1%   1.472µ ±  1%  -2.00% (p=0.002 n=6)
JQTransform_ArraySelect-4                3.331µ ±  0%   3.396µ ±  1%  +1.94% (p=0.002 n=6)
JQTransform_Complex-4                    38.36µ ±  1%   39.35µ ±  1%  +2.57% (p=0.002 n=6)
JQTransform_Throughput-4                 1.815µ ±  0%   1.798µ ±  2%       ~ (p=0.058 n=6)
SSEPublishDelivery-4                     65.10n ±  2%   65.00n ±  0%       ~ (p=0.331 n=6)
geomean                                  3.869µ         3.906µ        +0.97%

                                 │ baseline-bench.txt │        benchmark-results.txt         │
                                 │        B/op        │     B/op      vs base                │
IaCStateBackend_InProcess-4             416.0 ±  0%       416.0 ± 0%       ~ (p=1.000 n=6) ¹
IaCStateBackend_GRPC-4                5.847Mi ± 10%     5.844Mi ± 9%       ~ (p=0.818 n=6)
JQTransform_Simple-4                  1.273Ki ±  0%     1.273Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ObjectConstruction-4      1.773Ki ±  0%     1.773Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ArraySelect-4             2.625Ki ±  0%     2.625Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Complex-4                 16.31Ki ±  0%     16.31Ki ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Throughput-4              1.984Ki ±  0%     1.984Ki ± 0%       ~ (p=1.000 n=6) ¹
SSEPublishDelivery-4                    0.000 ±  0%       0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                             ²                 -0.01%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                 │ baseline-bench.txt │        benchmark-results.txt        │
                                 │     allocs/op      │  allocs/op   vs base                │
IaCStateBackend_InProcess-4              2.000 ± 0%      2.000 ± 0%       ~ (p=1.000 n=6) ¹
IaCStateBackend_GRPC-4                  6.835k ± 0%     6.833k ± 0%       ~ (p=0.669 n=6)
JQTransform_Simple-4                     10.00 ± 0%      10.00 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ObjectConstruction-4         15.00 ± 0%      15.00 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_ArraySelect-4                30.00 ± 0%      30.00 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Complex-4                    328.0 ± 0%      328.0 ± 0%       ~ (p=1.000 n=6) ¹
JQTransform_Throughput-4                 17.00 ± 0%      17.00 ± 0%       ~ (p=1.000 n=6) ¹
SSEPublishDelivery-4                     0.000 ± 0%      0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                             ²                -0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/schema
                                    │ baseline-bench.txt │       benchmark-results.txt        │
                                    │       sec/op       │    sec/op     vs base              │
SchemaValidation_Simple-4                    1.088µ ± 5%   1.107µ ± 14%  +1.79% (p=0.041 n=6)
SchemaValidation_AllFields-4                 1.665µ ± 1%   1.650µ ±  7%       ~ (p=0.589 n=6)
SchemaValidation_FormatValidation-4          1.596µ ± 4%   1.589µ ±  2%       ~ (p=0.732 n=6)
SchemaValidation_ManySchemas-4               1.853µ ± 3%   1.846µ ±  2%       ~ (p=0.818 n=6)
geomean                                      1.521µ        1.521µ        -0.01%

                                    │ baseline-bench.txt │       benchmark-results.txt        │
                                    │        B/op        │    B/op     vs base                │
SchemaValidation_Simple-4                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_AllFields-4                0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_FormatValidation-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_ManySchemas-4              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                                ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                    │ baseline-bench.txt │       benchmark-results.txt        │
                                    │     allocs/op      │ allocs/op   vs base                │
SchemaValidation_Simple-4                   0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_AllFields-4                0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_FormatValidation-4         0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
SchemaValidation_ManySchemas-4              0.000 ± 0%     0.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                                                ²               +0.00%               ²
¹ all samples are equal
² summaries must be >0 to compute geomean

pkg: github.com/GoCodeAlone/workflow/store
                                   │ baseline-bench.txt │        benchmark-results.txt        │
                                   │       sec/op       │    sec/op     vs base               │
EventStoreAppend_InMemory-4                1.073µ ± 38%   1.179µ ± 28%        ~ (p=0.240 n=6)
EventStoreAppend_SQLite-4                  1.387m ±  1%   1.545m ±  4%  +11.40% (p=0.002 n=6)
GetTimeline_InMemory/events-10-4           14.08µ ±  7%   13.96µ ±  7%        ~ (p=0.589 n=6)
GetTimeline_InMemory/events-50-4           77.59µ ±  3%   76.31µ ±  5%        ~ (p=0.310 n=6)
GetTimeline_InMemory/events-100-4          161.0µ ±  1%   121.4µ ± 33%  -24.63% (p=0.015 n=6)
GetTimeline_InMemory/events-500-4          636.7µ ± 33%   622.4µ ±  1%   -2.26% (p=0.002 n=6)
GetTimeline_InMemory/events-1000-4         1.306m ±  1%   1.282m ±  1%   -1.82% (p=0.002 n=6)
GetTimeline_SQLite/events-10-4             113.6µ ±  1%   104.3µ ±  1%   -8.25% (p=0.002 n=6)
GetTimeline_SQLite/events-50-4             254.4µ ±  1%   244.1µ ±  1%   -4.05% (p=0.002 n=6)
GetTimeline_SQLite/events-100-4            417.9µ ±  0%   414.4µ ±  1%   -0.85% (p=0.041 n=6)
GetTimeline_SQLite/events-500-4            1.786m ±  1%   1.763m ±  1%   -1.32% (p=0.002 n=6)
GetTimeline_SQLite/events-1000-4           3.480m ±  0%   3.449m ±  2%        ~ (p=0.180 n=6)
geomean                                    224.4µ         218.8µ         -2.51%

                                   │ baseline-bench.txt │        benchmark-results.txt         │
                                   │        B/op        │     B/op      vs base                │
EventStoreAppend_InMemory-4                  752.0 ± 5%     800.0 ± 6%  +6.38% (p=0.011 n=6)
EventStoreAppend_SQLite-4                  1.986Ki ± 2%   1.982Ki ± 2%       ~ (p=0.870 n=6)
GetTimeline_InMemory/events-10-4           7.953Ki ± 0%   7.953Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-50-4           46.62Ki ± 0%   46.62Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-100-4          94.48Ki ± 0%   94.48Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-500-4          472.8Ki ± 0%   472.8Ki ± 0%       ~ (p=1.000 n=6)
GetTimeline_InMemory/events-1000-4         944.3Ki ± 0%   944.3Ki ± 0%       ~ (p=0.773 n=6)
GetTimeline_SQLite/events-10-4             16.74Ki ± 0%   16.74Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-50-4             87.14Ki ± 0%   87.14Ki ± 0%       ~ (p=1.000 n=6)
GetTimeline_SQLite/events-100-4            175.4Ki ± 0%   175.4Ki ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-500-4            846.1Ki ± 0%   846.1Ki ± 0%       ~ (p=0.424 n=6)
GetTimeline_SQLite/events-1000-4           1.639Mi ± 0%   1.639Mi ± 0%       ~ (p=0.340 n=6)
geomean                                    67.07Ki        67.41Ki       +0.50%
¹ all samples are equal

                                   │ baseline-bench.txt │        benchmark-results.txt        │
                                   │     allocs/op      │  allocs/op   vs base                │
EventStoreAppend_InMemory-4                  7.000 ± 0%    7.000 ± 0%       ~ (p=1.000 n=6) ¹
EventStoreAppend_SQLite-4                    53.00 ± 0%    53.00 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-10-4             125.0 ± 0%    125.0 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-50-4             653.0 ± 0%    653.0 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-100-4           1.306k ± 0%   1.306k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-500-4           6.514k ± 0%   6.514k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_InMemory/events-1000-4          13.02k ± 0%   13.02k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-10-4               382.0 ± 0%    382.0 ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-50-4              1.852k ± 0%   1.852k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-100-4             3.681k ± 0%   3.681k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-500-4             18.54k ± 0%   18.54k ± 0%       ~ (p=1.000 n=6) ¹
GetTimeline_SQLite/events-1000-4            37.29k ± 0%   37.29k ± 0%       ~ (p=1.000 n=6) ¹
geomean                                     1.162k        1.162k       +0.00%
¹ all samples are equal

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

…tDetector + fix Endpoint

Addresses all PR-1 review fixes:

1. Advertisement-gated optional clients (THE key fix): New() now accepts
   advertisedServices map[string]bool; IaCProviderRegionLister and
   IaCProviderDriftDetector gRPC clients are constructed ONLY when their
   service name appears in the map. *Adapter no longer unconditionally
   satisfies interfaces.IaCProviderRegionLister — the RegionLister()
   accessor returns nil for unadvertised plugins, enabling catalog steps'
   static-fallback path to fire correctly. Accessor interfaces
   RegionListerProvider and DriftDetectorProvider defined in
   iac/providerclient for consuming steps. Negative-path test added:
   TestAdapter_RegionLister_Unadvertised confirms nil return + that
   *Adapter does NOT satisfy IaCProviderRegionLister directly.

2. DriftDetector wired: pb.NewIaCProviderDriftDetectorClient constructed
   when advertised; DetectDrift() routes through it (returns
   ErrProviderMethodUnimplemented when unadvertised); driftDetectorAdapter
   satisfies interfaces.DriftConfigDetector for DetectDriftWithSpecs.

3. BootstrapResult.Endpoint mapped: r.GetEndpoint() now included in the
   returned BootstrapResult literal (DO Spaces endpoint was silently lost).

4. Capabilities cached via sync.Once: SupportedCanonicalKeys() reuses
   fetchCapabilities() instead of issuing a second RPC.

5. plugin/external/adapter.go WiringHooks: collects optional service names
   via advertisedOptionalIaCServices() and forwards them to
   providerclient.New; adds diskManifest fallback rationale comment on
   advertisesIaCProviderRequiredService().

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@intel352 intel352 merged commit d57ade6 into main Jun 2, 2026
28 checks passed
@intel352 intel352 deleted the feat/iac-provider-service-reg-2026-06-02T0104 branch June 2, 2026 06:52
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