From 8dbcfedc4bea13869758b8595b76644f1b930818 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 00:01:53 -0400 Subject: [PATCH 01/15] docs: design iac derived requirements --- decisions/0043-iac-derived-requirements.md | 38 ++ ...6-05-25-iac-derived-requirements-design.md | 362 ++++++++++++++++++ 2 files changed, 400 insertions(+) create mode 100644 decisions/0043-iac-derived-requirements.md create mode 100644 docs/plans/2026-05-25-iac-derived-requirements-design.md diff --git a/decisions/0043-iac-derived-requirements.md b/decisions/0043-iac-derived-requirements.md new file mode 100644 index 00000000..efd45a7a --- /dev/null +++ b/decisions/0043-iac-derived-requirements.md @@ -0,0 +1,38 @@ +# 0043. Derive IaC Through Provider Requirements + +**Status:** Accepted +**Date:** 2026-05-25 +**Decision-makers:** Workflow maintainers, autonomous pipeline +**Related:** `docs/plans/2026-05-25-iac-derived-requirements-design.md` + +## Context + +Workflow needs to derive infrastructure for higher-level application and +observability declarations without hard-coding DigitalOcean, AWS, GCP, Azure, +Datadog, Grafana, Prometheus, or Loki behavior in core. Existing +`moduleInfraRequirements` is useful but static and manifest-only. Existing IaC +provider plugins already expose strict typed gRPC services, with optional +services advertised by registration. The user also requires explicit YAML keys +for user-provided overrides and strict proto compatibility where possible. + +## Decision + +We will add a core requirement model and `wfctl infra derive`, but provider +plugins will own requirement-to-resource mapping through an optional strict-proto +IaC service. Generated modules will include `satisfies` keys, and manually +written modules can use the same keys to suppress derivation. We reject a +provider-specific CLI plugin command because YAML mutation and cross-provider +plugin discovery belong in `wfctl` core. We reject apply-time derivation because +it hides generated infrastructure from review and CI. We reject core-owned +provider mapping because it would recreate provider-specific assumptions in the +framework. + +## Consequences + +Derivation becomes reviewable, idempotent, and reusable for observability, web +apps, message brokers, databases, caches, and storage. Provider plugins gain a +small but real new compatibility surface and must test their mappings. Workflow +core must maintain a YAML node editor and a stable requirement proto. Older +provider plugins keep working for explicit `infra.*` YAML but cannot derive +resources until they implement the optional mapper service. + diff --git a/docs/plans/2026-05-25-iac-derived-requirements-design.md b/docs/plans/2026-05-25-iac-derived-requirements-design.md new file mode 100644 index 00000000..2a783491 --- /dev/null +++ b/docs/plans/2026-05-25-iac-derived-requirements-design.md @@ -0,0 +1,362 @@ +# IaC Derived Requirements Design + +**Date:** 2026-05-25 +**Status:** Draft +**Owner:** autonomous pipeline +**Related:** `decisions/0043-iac-derived-requirements.md` + +## Problem + +Workflow configs increasingly describe application intent at a higher level than +the concrete infrastructure needed to run it. A user can declare an API app, a +NATS broker, or observability for OTel, Prometheus, Loki, Grafana, or Datadog, +but today the user or an agent still has to hand-write the matching `infra.*` +modules. That is error-prone and provider-specific. + +The target behavior is explicit and reviewable: + +1. Application and plugin declarations emit provider-neutral requirements. +2. IaC provider plugins map those requirements to provider/runtime-specific + `infra.*` modules. +3. `wfctl` expands the YAML before apply, so the resulting config is visible in + review and CI. +4. Users can satisfy a requirement manually by declaring a stable key in YAML; + `wfctl` must not guess by resource similarity. + +## Current Inventory + +- `config.PluginManifestFile.ModuleInfraRequirements` and + `cmd/wfctl/plugin_infra.go` already provide a static manifest-only dependency + detector. It is too weak for provider/runtime mapping, explicit satisfaction, + or observability variants. +- `cmd/wfctl/infra.go` plans and applies `infra.*` and `platform.*` modules + from the top-level `modules:` list. The old `infrastructure:` block is + preserved by config round-trips but is not the active provisioning path. +- IaC plugins already expose strict typed gRPC services through + `plugin/external/proto/iac.proto`. That proto explicitly avoids + `google.protobuf.Struct` and `Any`; provider-specific free-form payloads use + JSON bytes fields. +- `workflow-editor` uses `js-yaml` and preserves top-level ordering plus unknown + top-level keys, but it is not an AST-preserving comment-safe YAML mutator. + `wfctl` should use Go's existing `gopkg.in/yaml.v3` node API for targeted + edits instead of importing editor code. +- DigitalOcean, AWS, GCP, and Azure plugins all expose typed IaC capabilities + for common canonical resource types such as `infra.container_service`, + `infra.k8s_cluster`, `infra.database`, `infra.cache`, and `infra.storage`. + +## Goals + +1. Add a provider-neutral requirement model that can represent observability, + web/API apps, message brokers, databases, caches, storage, and future + support resources without provider names leaking into application config. +2. Add `wfctl infra derive` to calculate missing requirements and write the + expanded YAML before `infra plan` / `infra apply`. +3. Add deterministic explicit overrides through `modules[].satisfies`. +4. Add a strict-proto provider mapping surface so provider plugins can describe + how requirements map to their supported resource types. +5. Support observability choices across OTel first, plus Prometheus, Loki, + Grafana, and Datadog without baking those products into Workflow core + provider logic. +6. Keep the first implementation small: generate concrete modules and leave + provisioning to the existing IaC pipeline. + +## Non-Goals + +- Do not derive at apply time. `infra plan` and `infra apply` should consume the + already-expanded YAML. +- Do not infer that an arbitrary existing resource satisfies a requirement by + comparing config. Only explicit `satisfies` keys count. +- Do not build a full policy engine or Terraform-style expression language. +- Do not make Workflow core own AWS, GCP, Azure, DigitalOcean, Datadog, or + Grafana resource mapping rules. +- Do not commit application-specific names such as `cms_*` or `multisite_*` to + generic observability or IaC plugins. +- Do not require the visual editor to preserve every comment before this can + ship. The CLI owns YAML expansion; editor preservation improvements can follow. + +## Approaches Considered + +### Approach A: Core derivation engine, provider plugin mappers + +`wfctl` gathers requirements from workflow config, installed plugin metadata, +and optional plugin/provider typed services. It asks the selected IaC provider +plugin to map the unsatisfied requirements to concrete `infra.*` module +stubs, then writes those modules into YAML with `satisfies` keys. + +Pros: clear ownership boundary; works across DO/AWS/GCP/Azure; keeps provider +specifics out of core; produces reviewable YAML. Cons: adds a new provider +optional service and a YAML mutator. + +This is the recommended approach. + +### Approach B: Observability plugin directly writes provider YAML + +The observability plugin could expose a CLI command that edits config for OTel, +Datadog, Prometheus, Loki, and Grafana. + +Pros: fast for observability. Cons: repeats the same problem for NATS, web/API, +databases, caches, and provider runtimes; plugin CLI commands do not naturally +own cross-provider IaC mapping or core YAML ordering rules. + +Rejected. + +### Approach C: Derive inside `infra apply` + +`infra apply` could synthesize missing resources in memory just before planning. + +Pros: smallest command surface. Cons: hides generated infrastructure from review, +CI diffs, and agents; makes user overrides fuzzy; conflicts with the user's +explicit request for a YAML-expanding command. + +Rejected. + +## Design + +### Requirement Model + +Add a small Workflow-owned requirement model in `interfaces` or a new `iac/derive` +package, mirrored in `plugin/external/proto/iac.proto`. + +Core fields: + +- `key`: stable requirement identifier, for example + `observability.telemetry.default` or `messaging.nats.events`. +- `kind`: enum-like string for the broad category, for example + `observability`, `web_api`, `message_broker`, `database`, `cache`, `storage`. +- `source`: module/service/plugin path that produced the requirement. +- `resource_type_hint`: optional canonical target such as + `infra.container_service`, `infra.k8s_cluster`, or `infra.database`. +- `environment`: optional target environment. +- `runtime`: optional runtime hint such as `kubernetes`, `ecs`, `cloud_run`, + `azure_container_apps`, or `do_app_platform`. +- `features`: typed strings for portable behavior, such as + `signals.traces`, `signals.metrics`, `signals.logs`, `backend.otel`, + `backend.datadog`, `backend.prometheus`, `backend.loki`, + `backend.grafana`, `deployment.sidecar`, `deployment.daemonset`, + `deployment.managed`. +- `parameters_json`: JSON bytes only for data that cannot be modeled + generically without provider or product leakage. + +`parameters_json` is a deliberate exception to pure scalar proto fields. It +follows the existing strict IaC proto pattern for provider-specific +`config_json` and avoids `Struct` / `Any`. + +### Satisfaction Keys + +Add `satisfies` to module config as a top-level field on `config.ModuleConfig`: + +```yaml +modules: + - name: app-telemetry + type: infra.container_service + satisfies: + - observability.telemetry.default + config: + image: otel/opentelemetry-collector-contrib:latest +``` + +The derivation engine considers a requirement satisfied when any module lists +that key. It does not inspect resource type, name, labels, sidecars, or provider +config to infer equivalence. + +Generated modules must include `satisfies` so repeated runs are idempotent. + +### Provider Mapping Service + +Add an optional strict-proto service to `plugin/external/proto/iac.proto`: + +```proto +service IaCProviderRequirementMapper { + rpc MapRequirements(MapRequirementsRequest) returns (MapRequirementsResponse); +} +``` + +The request contains typed requirement messages plus provider/runtime/environment +context. The response returns: + +- accepted requirement keys, +- rejected requirement diagnostics, +- concrete `ResourceSpec` messages to write as `modules:` entries, +- optional ordered notes for interactive display. + +Provider plugins register this service only when they support mapping. Absence +means the provider can still plan/apply explicit `infra.*` modules, but `wfctl +infra derive` cannot ask it to synthesize provider-specific modules. + +This matches the existing typed-IaC optional-service pattern: registration is +the capability signal, not a boolean flag or an unimplemented response field. + +### Requirement Sources + +Initial requirement sources: + +- Built-in config shape: web/API modules, `services:`, and common broker/cache + module types can produce neutral requirements. +- Plugin static declarations: evolve `moduleInfraRequirements` into a v2 shape + that can carry `key`, `kind`, `features`, and `resource_type_hint` while + preserving the existing v1 fields. +- Observability plugin declarations: `observability.telemetry` and + `observability.collector` declare observability requirements and supported + backends without application-specific names. + +Future source: + +- Optional plugin-side requirement provider service for dynamic requirements + that depend on module config. If added, it must be strict-proto and should + return the same requirement messages as provider mapping consumes. + +### `wfctl infra derive` + +Add: + +```sh +wfctl infra derive --config workflow.yaml --provider aws --env staging --runtime ecs --write +wfctl infra derive --config workflow.yaml --provider digitalocean --env prod --runtime do_app_platform --dry-run --format yaml +wfctl infra derive --config workflow.yaml --provider gcp --env prod --non-interactive --write +``` + +Behavior: + +1. Load the workflow YAML as `yaml.Node`. +2. Load the semantic config through `config.LoadFromFile`. +3. Gather requirements. +4. Remove requirements already listed by `modules[].satisfies`. +5. Resolve provider plugin and optional mapper service. +6. In interactive TTY mode, prompt only for ambiguous provider/runtime choices. +7. In non-interactive mode, fail on ambiguity with a deterministic diagnostic. +8. Insert generated modules into `modules:` while preserving existing order, + comments, unknown top-level keys, and unknown module keys where `yaml.v3` + can retain them. +9. Print a summary of added and already-satisfied requirement keys. + +`--dry-run` prints the expanded YAML or a JSON summary without writing. `--write` +updates the file atomically. A later `--output` can write to a separate path. + +### Observability Mapping + +The observability plugin remains generic. Applications choose names and backends +in their own YAML. The requirement features describe intent: + +- OTel collector: `backend.otel`, selected signals, deployment mode. +- Prometheus: prefer OTel metrics exporter or scrape config when possible. +- Loki: prefer OTel logs exporter when possible. +- Grafana: dashboards/datasource requirements only when a provider plugin + supports them; otherwise diagnostics explain the manual external setup. +- Datadog: prefer OTel exporter to Datadog. Direct Datadog agent sidecar or + service is supported when the requirement asks for `backend.datadog` and the + provider mapper has a runtime-specific mapping. + +Examples: + +- Kubernetes provider mapper may produce an OTel Collector deployment/daemonset + and Prometheus/Loki exporter config. +- ECS provider mapper may produce Datadog agent sidecar definitions or an OTel + collector sidecar depending on selected backend. +- DigitalOcean App Platform mapper may produce sibling service components + because its driver already models "sidecars" as sibling services. + +### YAML Mutation + +Use `gopkg.in/yaml.v3` node editing in a new small package, for example +`config/yamledit` or `iac/yamledit`. + +Rules: + +- Keep the original document root and mapping order. +- Create `modules:` if missing. +- Append generated modules after the last existing `infra.*` module; if no + `infra.*` module exists, append at the end of `modules:`. +- Preserve comments and unknown keys by editing nodes rather than unmarshalling + and re-marshalling the full config struct. +- Do not try to preserve comments inside newly generated nodes beyond a concise + generated block comment. +- Add golden tests with comments, anchors, unknown top-level keys, unknown module + keys, empty `modules:`, and repeated derive runs. + +The editor's `js-yaml` ordering behavior is precedent only. It is not sufficient +for CLI mutation because it does not retain comments. + +### CLI Plugin Evaluation + +This should not be implemented as a CLI plugin. A provider or observability +plugin can add convenience commands later, but the derivation command needs +first-class access to config loading, plugin discovery, typed IaC provider +handles, and atomic YAML writes. Those are core `wfctl` responsibilities. + +CLI plugin functionality is still useful for provider-specific diagnostics +after derivation, for example `datadog verify` or `grafana datasource test`, but +not for the generic derivation engine. + +### IaC Plugin Evaluation + +IaC plugin functionality is the right extension point for mapping. Core can +define the neutral requirement model and command behavior; provider plugins own +the translation from requirements to `ResourceSpec` for Kubernetes, ECS, Cloud +Run, Azure Container Apps, DigitalOcean App Platform, and future runtimes. + +This also creates a reusable pattern for non-observability cases: + +- web/API app declaration -> `infra.container_service`, ingress, registry, + certificate, DNS as supported by the provider. +- NATS declaration -> managed broker, Kubernetes workload, ECS sidecar, or + explicit unsupported diagnostic. +- database/cache/storage declaration -> provider-managed resource or local + container for development. + +## Backwards Compatibility + +- Existing configs continue to plan/apply. `satisfies` is optional. +- Existing provider plugins continue to work; only plugins implementing the new + optional mapper service participate in derivation. +- Existing `moduleInfraRequirements` entries remain valid. The v2 fields are + additive. +- `infra plan` and `infra apply` do not auto-derive. + +## Assumptions + +1. `modules:` remains the canonical place for provisioned `infra.*` resources. +2. Provider plugins can map at least common observability and app requirements + without needing live cloud API calls. +3. The strict-proto IaC optional-service pattern is acceptable for another + optional provider capability. +4. `yaml.v3` node mutation can preserve enough source fidelity for safe + machine edits. Tests will define the exact guarantee. +5. Interactive ambiguity is limited to provider/runtime/backend choices; if this + becomes wider, the design should stop and add a richer planning report rather + than more prompts. + +## Rollback + +This affects CLI behavior, plugin contracts, YAML config schema, and provider +plugin loading paths. + +- Core command rollback: revert the `wfctl infra derive` PR. Existing expanded + YAML remains valid because generated resources are normal `infra.*` modules. +- Proto/service rollback: because the provider mapper is optional, reverting + the host support leaves existing provider plugins usable for plan/apply. + Plugins that already implemented the mapper must pin the workflow version that + includes it. +- YAML field rollback: `satisfies` is additive. Older engines ignore the field + once generated YAML contains concrete modules. +- Provider mapper rollback: release a provider patch that stops advertising the + optional service; `wfctl infra derive` will emit an unsupported-provider + diagnostic instead of generating modules. + +## Self-Challenge + +1. Laziest plausible solution: extend `moduleInfraRequirements` and add a + scaffold command with no provider plugin RPC. This fails the cross-provider + runtime mapping requirement and would bake provider choices into core. +2. Fragile assumption: provider mapping does not need live cloud calls. If false, + the mapper RPC must accept credentials/config and may become slow. The first + implementation should fail if a mapper tries to perform apply-like work. +3. YAGNI risk: modeling every observability backend upfront could get heavy. + Mitigation: features are strings with a small documented vocabulary, and + provider plugins can reject unsupported combinations. +4. Partial failure: YAML write corruption would be the highest-impact bug. + Mitigation: parse as `yaml.Node`, write atomically, and add golden/idempotence + tests before implementation. +5. Repo precedent conflict: current IaC proto avoids `Struct`/`Any`. This design + follows that precedent; only provider-specific free-form fields use JSON bytes, + matching existing `ResourceSpec.config_json`. + From 4f471b28a18b9237133d2cb3074ab821e7d71984 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 00:03:55 -0400 Subject: [PATCH 02/15] docs: revise iac derivation design review --- decisions/0043-iac-derived-requirements.md | 29 +++-- ...equirements-design.adversarial-review-1.md | 86 +++++++++++++ ...6-05-25-iac-derived-requirements-design.md | 119 +++++++++++++++--- 3 files changed, 202 insertions(+), 32 deletions(-) create mode 100644 docs/plans/2026-05-25-iac-derived-requirements-design.adversarial-review-1.md diff --git a/decisions/0043-iac-derived-requirements.md b/decisions/0043-iac-derived-requirements.md index efd45a7a..06671fa0 100644 --- a/decisions/0043-iac-derived-requirements.md +++ b/decisions/0043-iac-derived-requirements.md @@ -13,26 +13,31 @@ Datadog, Grafana, Prometheus, or Loki behavior in core. Existing `moduleInfraRequirements` is useful but static and manifest-only. Existing IaC provider plugins already expose strict typed gRPC services, with optional services advertised by registration. The user also requires explicit YAML keys -for user-provided overrides and strict proto compatibility where possible. +for user-provided overrides and strict proto compatibility where possible, +which means portable requirement concepts should use proto enums rather than a +stringly typed vocabulary. ## Decision We will add a core requirement model and `wfctl infra derive`, but provider plugins will own requirement-to-resource mapping through an optional strict-proto -IaC service. Generated modules will include `satisfies` keys, and manually -written modules can use the same keys to suppress derivation. We reject a -provider-specific CLI plugin command because YAML mutation and cross-provider -plugin discovery belong in `wfctl` core. We reject apply-time derivation because -it hides generated infrastructure from review and CI. We reject core-owned -provider mapping because it would recreate provider-specific assumptions in the -framework. +IaC service. Portable requirement fields will be proto enums; JSON bytes and +namespaced string vendor features are allowed only for provider/product +extension data that cannot be modeled generically. Generated modules will +include `satisfies` keys, and manually written modules can use the same keys to +suppress derivation. We reject a provider-specific CLI plugin command because +YAML mutation and cross-provider plugin discovery belong in `wfctl` core. We +reject apply-time derivation because it hides generated infrastructure from +review and CI. We reject core-owned provider mapping because it would recreate +provider-specific assumptions in the framework. ## Consequences Derivation becomes reviewable, idempotent, and reusable for observability, web apps, message brokers, databases, caches, and storage. Provider plugins gain a small but real new compatibility surface and must test their mappings. Workflow -core must maintain a YAML node editor and a stable requirement proto. Older -provider plugins keep working for explicit `infra.*` YAML but cannot derive -resources until they implement the optional mapper service. - +core must maintain a YAML node editor, a stable requirement proto, and secret +safety checks for generated specs. The editor must preserve `modules[].satisfies` +before generated YAML can safely round-trip visually. Older provider plugins keep +working for explicit `infra.*` YAML but cannot derive resources until they +implement the optional mapper service. diff --git a/docs/plans/2026-05-25-iac-derived-requirements-design.adversarial-review-1.md b/docs/plans/2026-05-25-iac-derived-requirements-design.adversarial-review-1.md new file mode 100644 index 00000000..f9f582f8 --- /dev/null +++ b/docs/plans/2026-05-25-iac-derived-requirements-design.adversarial-review-1.md @@ -0,0 +1,86 @@ +### Adversarial Review Report + +**Phase:** design +**Artifact:** `docs/plans/2026-05-25-iac-derived-requirements-design.md` +**Status:** FAIL + +**Findings (Critical):** +- None. + +**Findings (Important):** +- [Repo-precedent conflicts / strict proto] `Requirement Model` lines 124-138: + the design says `kind`, `runtime`, and `features` are strings, even though the + user explicitly asked to be strict-proto compatible where possible and the IaC + proto already uses enums for wire-stable concepts such as drift class. A + string vocabulary is easy to typo and hard for provider plugins to validate + compatibly. Recommendation: make category, signal, backend, deployment mode, + and runtime typed proto enums; reserve repeated string extensions only for + vendor-specific features with a documented non-strict reason. +- [Missing failure modes] `wfctl infra derive` lines 220-229: config loading + resolves imports, but YAML mutation edits one file. If a requirement comes + from an imported module, the design does not say whether generated modules go + to the root file, the source file, or a new derived file. This can corrupt + ownership boundaries in multi-file configs. Recommendation: define v1 as + root-file expansion only, with `source` diagnostics and an explicit future + `--target-file`; tests must cover imported configs. +- [User-intent drift / plugin interface] `Requirement Sources` lines 191-206: + dynamic plugin-side requirement providers are deferred to the future, but the + user's Go-interface analogy asks for plugins/modules/steps to satisfy an + interface without hard dependency. Static manifest requirements are not enough + for config-driven observability backends. Recommendation: include a v1 + lightweight Go interface for in-process providers and a strict-proto + external-plugin service, even if the first implementation supports static + manifests too. +- [Security/privacy] `Provider Mapping Service` lines 174-180: provider + mappers return concrete `ResourceSpec` configs, but there is no rule + preventing secret material from being written into YAML. Observability and + Datadog configs frequently involve API keys. Recommendation: require mappers + to emit only secret references or `secrets.generate` requirements; `wfctl` + rejects generated specs containing known secret-looking plaintext values. +- [Repo-precedent conflicts / editor preservation] `Satisfaction Keys` lines + 146-162: adding top-level `modules[].satisfies` to Go config is not enough. + `workflow-editor`'s `ModuleConfig` type does not include that field, and its + `js-yaml` round-trip reconstructs module objects. Editing generated YAML in + the editor can silently drop satisfaction keys. Recommendation: include + workflow-editor type/serialization preservation in the plan or explicitly + block editor round-trip support until it lands. + +**Findings (Minor):** +- [Missing failure modes] `wfctl infra derive` lines 212-216: provider and + runtime are passed as flags, but existing configs already declare + `iac.provider` modules and per-resource `iac_provider`/`provider` refs. + Recommendation: define precedence: explicit flag, then env-specific + provider, then single configured provider, else ambiguity error. +- [YAGNI] `Requirement Model` lines 129-136: modeling every runtime and backend + in the core design risks expanding before the first implementation proves the + shape. Recommendation: enumerate only the required observability/runtime + constants for v1 and keep vendor extension fields for provider plugins. + +**Bug-class scan transcript:** + +| Class | Result | Note | +|---|---|---| +| Unstated assumptions | Finding | The design assumes root-file YAML writes are acceptable after imported config resolution. | +| Repo-precedent conflicts | Finding | The string feature vocabulary conflicts with `plugin/external/proto/iac.proto`'s strict typed-service precedent. | +| YAGNI violations | Finding | The design risks over-modeling future backends/runtimes before the first provider mapper exists. | +| Missing failure modes | Finding | Multi-file imports, provider-precedence ambiguity, and generated secret handling need explicit behavior. | +| Security / privacy | Finding | Provider-generated ResourceSpecs may accidentally write API keys or tokens into YAML. | +| Rollback story | Clean | The rollback section covers CLI, proto, YAML schema, and provider mapper rollback. | +| Simpler alternative not considered | Clean | Static manifest-only scaffolding and apply-time derivation were considered and rejected. | +| User-intent drift | Finding | Deferring the plugin/module interface weakens the user's stated composability requirement. | + +**Options the author may not have considered:** + +1. Root-only generated overlay file: instead of mutating the main config, always + write `workflow.derived.yaml` and add it to `imports:`. This improves review + isolation but requires import-order guarantees and may be surprising when a + user expected in-place expansion. +2. Manifest-v2 first, mapper service later: ship a smaller static-only scaffold + and defer provider RPCs. This is simpler, but it fails the runtime-specific + sidecar/daemonset/ECS/DO mapping requirement and would likely be reworked. + +**Verdict reasoning:** The design direction is sound, but the strict-proto, +multi-file, secret-safety, and plugin-interface gaps are important enough to fix +before writing an implementation plan. No critical flaw requires abandoning the +approach. + diff --git a/docs/plans/2026-05-25-iac-derived-requirements-design.md b/docs/plans/2026-05-25-iac-derived-requirements-design.md index 2a783491..b9b779e9 100644 --- a/docs/plans/2026-05-25-iac-derived-requirements-design.md +++ b/docs/plans/2026-05-25-iac-derived-requirements-design.md @@ -1,7 +1,7 @@ # IaC Derived Requirements Design **Date:** 2026-05-25 -**Status:** Draft +**Status:** Draft — revised after adversarial-review cycle 1 **Owner:** autonomous pipeline **Related:** `decisions/0043-iac-derived-requirements.md` @@ -121,25 +121,37 @@ Core fields: - `key`: stable requirement identifier, for example `observability.telemetry.default` or `messaging.nats.events`. -- `kind`: enum-like string for the broad category, for example - `observability`, `web_api`, `message_broker`, `database`, `cache`, `storage`. +- `kind`: typed proto enum for the broad category, for example + `REQUIREMENT_KIND_OBSERVABILITY`, `REQUIREMENT_KIND_WEB_API`, + `REQUIREMENT_KIND_MESSAGE_BROKER`, `REQUIREMENT_KIND_DATABASE`, + `REQUIREMENT_KIND_CACHE`, and `REQUIREMENT_KIND_STORAGE`. - `source`: module/service/plugin path that produced the requirement. - `resource_type_hint`: optional canonical target such as `infra.container_service`, `infra.k8s_cluster`, or `infra.database`. - `environment`: optional target environment. -- `runtime`: optional runtime hint such as `kubernetes`, `ecs`, `cloud_run`, - `azure_container_apps`, or `do_app_platform`. -- `features`: typed strings for portable behavior, such as - `signals.traces`, `signals.metrics`, `signals.logs`, `backend.otel`, - `backend.datadog`, `backend.prometheus`, `backend.loki`, - `backend.grafana`, `deployment.sidecar`, `deployment.daemonset`, - `deployment.managed`. +- `runtime`: optional typed proto enum such as `RUNTIME_KUBERNETES`, + `RUNTIME_ECS`, `RUNTIME_CLOUD_RUN`, `RUNTIME_AZURE_CONTAINER_APPS`, or + `RUNTIME_DO_APP_PLATFORM`. +- `signals`: repeated typed proto enum for telemetry signals: + `TELEMETRY_SIGNAL_TRACES`, `TELEMETRY_SIGNAL_METRICS`, and + `TELEMETRY_SIGNAL_LOGS`. +- `backends`: repeated typed proto enum for requested observability backends: + `OBSERVABILITY_BACKEND_OTEL`, `OBSERVABILITY_BACKEND_DATADOG`, + `OBSERVABILITY_BACKEND_PROMETHEUS`, `OBSERVABILITY_BACKEND_LOKI`, and + `OBSERVABILITY_BACKEND_GRAFANA`. +- `deployment_modes`: repeated typed proto enum for portable deployment shape: + `DEPLOYMENT_MODE_SIDECAR`, `DEPLOYMENT_MODE_DAEMONSET`, + `DEPLOYMENT_MODE_SIBLING_SERVICE`, and `DEPLOYMENT_MODE_MANAGED`. +- `vendor_features`: repeated strings for provider/product-specific extension + flags that do not justify a Workflow-owned enum. These are non-portable and + must be namespaced, for example `datadog.apm` or `grafana.datasource`. - `parameters_json`: JSON bytes only for data that cannot be modeled generically without provider or product leakage. `parameters_json` is a deliberate exception to pure scalar proto fields. It follows the existing strict IaC proto pattern for provider-specific -`config_json` and avoids `Struct` / `Any`. +`config_json` and avoids `Struct` / `Any`. The default is typed proto enums; +strings are allowed only for explicitly namespaced vendor extensions. ### Satisfaction Keys @@ -193,17 +205,25 @@ Initial requirement sources: - Built-in config shape: web/API modules, `services:`, and common broker/cache module types can produce neutral requirements. - Plugin static declarations: evolve `moduleInfraRequirements` into a v2 shape - that can carry `key`, `kind`, `features`, and `resource_type_hint` while - preserving the existing v1 fields. + that can carry `key`, `kind`, telemetry signals, observability backends, + deployment modes, vendor features, and `resource_type_hint` while preserving + the existing v1 fields. - Observability plugin declarations: `observability.telemetry` and `observability.collector` declare observability requirements and supported backends without application-specific names. -Future source: +Runtime/config-aware source: -- Optional plugin-side requirement provider service for dynamic requirements - that depend on module config. If added, it must be strict-proto and should - return the same requirement messages as provider mapping consumes. +- Add a lightweight Go interface for in-process providers, for example + `IaCRequirementProvider`, that modules, steps, or plugin adapters can satisfy + without Workflow core depending on a concrete observability plugin package. +- Add an optional strict-proto external-plugin service for config-aware + requirement discovery. It returns the same typed requirement messages consumed + by the provider mapper. Absence of service registration means the plugin only + participates through static manifest declarations. +- The first observability implementation should use static declarations when + the module config is simple and the dynamic service when selected backends or + signal sets depend on module config. ### `wfctl infra derive` @@ -232,6 +252,24 @@ Behavior: `--dry-run` prints the expanded YAML or a JSON summary without writing. `--write` updates the file atomically. A later `--output` can write to a separate path. +Provider/runtime precedence: + +1. Explicit `--provider` and `--runtime` flags. +2. Environment-specific provider hints already present in config. +3. A single unambiguous `iac.provider` module. +4. Otherwise an ambiguity diagnostic in non-interactive mode or a prompt in TTY + mode. + +Multi-file behavior for v1: + +- `config.LoadFromFile` still resolves imports to gather requirements. +- `wfctl infra derive --write` mutates only the root `--config` file. +- Generated modules are written to the root file even when the source + requirement came from an imported file. The summary must include the source + path so the user can move the generated module manually if desired. +- A future `--target-file` can direct generated modules into a specific imported + file, but v1 does not guess ownership. + ### Observability Mapping The observability plugin remains generic. Applications choose names and backends @@ -255,6 +293,18 @@ Examples: - DigitalOcean App Platform mapper may produce sibling service components because its driver already models "sidecars" as sibling services. +Secret handling: + +- Requirement mappers must not return plaintext API keys, tokens, connection + strings, or private keys in generated `ResourceSpec.Config`. +- Generated specs may reference secrets through `${SECRET_NAME}` placeholders + or add separate secret-generation/secret-requirement declarations. +- `wfctl infra derive` rejects generated YAML when provider output includes + suspicious plaintext secret-looking keys such as `api_key`, `token`, + `password`, `private_key`, or `secret` unless the value is a placeholder. +- Observability examples that need Datadog, Grafana, Prometheus remote-write, or + Loki credentials must generate secret references, not values. + ### YAML Mutation Use `gopkg.in/yaml.v3` node editing in a new small package, for example @@ -276,6 +326,15 @@ Rules: The editor's `js-yaml` ordering behavior is precedent only. It is not sufficient for CLI mutation because it does not retain comments. +Editor preservation: + +- Add `satisfies?: string[]` to `workflow-editor`'s `ModuleConfig` type and + serialization path in the same implementation plan or a prerequisite PR. +- Until that lands, `wfctl infra derive` should warn when it detects a project + workflow-editor version below the first version that preserves `satisfies`. +- Editor support is preservation-only for v1; the visual UI does not need to + author derived requirements before the CLI command ships. + ### CLI Plugin Evaluation This should not be implemented as a CLI plugin. A provider or observability @@ -324,6 +383,9 @@ This also creates a reusable pattern for non-observability cases: 5. Interactive ambiguity is limited to provider/runtime/backend choices; if this becomes wider, the design should stop and add a richer planning report rather than more prompts. +6. Root-file expansion is acceptable for v1 multi-file configs as long as the + command reports the source path for each generated requirement and remains + idempotent. ## Rollback @@ -357,6 +419,23 @@ plugin loading paths. Mitigation: parse as `yaml.Node`, write atomically, and add golden/idempotence tests before implementation. 5. Repo precedent conflict: current IaC proto avoids `Struct`/`Any`. This design - follows that precedent; only provider-specific free-form fields use JSON bytes, - matching existing `ResourceSpec.config_json`. - + follows that precedent with typed proto enums for portable concepts; only + provider-specific free-form fields use JSON bytes, matching existing + `ResourceSpec.config_json`. + +## Adversarial Review Resolution + +Cycle 1 report: +`docs/plans/2026-05-25-iac-derived-requirements-design.adversarial-review-1.md`. + +Resolved changes: + +- Replaced stringly typed `kind`, `runtime`, and observability `features` with + proto enum fields; kept namespaced strings only for vendor extensions. +- Defined v1 multi-file behavior as root-file expansion with source diagnostics. +- Promoted plugin/module requirement providers into v1 via a Go interface plus + optional strict-proto external-plugin service. +- Added secret-output rules and `wfctl` rejection behavior for generated + plaintext secrets. +- Added workflow-editor preservation work for `modules[].satisfies`. +- Added provider/runtime precedence rules. From 6e00a5eed761fa192419f82707ce9d27f4876c45 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 00:04:45 -0400 Subject: [PATCH 03/15] docs: pass iac derivation design review --- ...equirements-design.adversarial-review-2.md | 48 +++++++++++++++++++ ...6-05-25-iac-derived-requirements-design.md | 5 +- 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 docs/plans/2026-05-25-iac-derived-requirements-design.adversarial-review-2.md diff --git a/docs/plans/2026-05-25-iac-derived-requirements-design.adversarial-review-2.md b/docs/plans/2026-05-25-iac-derived-requirements-design.adversarial-review-2.md new file mode 100644 index 00000000..ccebfed0 --- /dev/null +++ b/docs/plans/2026-05-25-iac-derived-requirements-design.adversarial-review-2.md @@ -0,0 +1,48 @@ +### Adversarial Review Report + +**Phase:** design +**Artifact:** `docs/plans/2026-05-25-iac-derived-requirements-design.md` +**Status:** PASS + +**Findings (Critical):** +- None. + +**Findings (Important):** +- None. + +**Findings (Minor):** +- [YAGNI / wording] `Self-Challenge`: after cycle-1 fixes, the self-challenge + still referred to "features are strings". Recommendation: update the wording + to match the revised enum-first requirement model. Status: fixed before this + report was committed. + +**Bug-class scan transcript:** + +| Class | Result | Note | +|---|---|---| +| Unstated assumptions | Clean | The remaining load-bearing assumptions are explicit, including root-file expansion and no live cloud calls during mapping. | +| Repo-precedent conflicts | Clean | The design now follows `plugin/external/proto/iac.proto`'s strict typed optional-service precedent and avoids `Struct` / `Any`. | +| YAGNI violations | Clean | The feature set traces to the user's stated observability/provider/IaC requirements; vendor extension strings limit enum sprawl. | +| Missing failure modes | Clean | Multi-file imports, provider ambiguity, secret leakage, YAML corruption, and unsupported provider services are now covered. | +| Security / privacy | Clean | The mapper output is constrained to secret references and `wfctl` rejects suspicious generated plaintext secrets. | +| Rollback story | Clean | Rollback covers CLI, proto/service, YAML schema, and provider mapper release rollback. | +| Simpler alternative not considered | Clean | Static manifest-only scaffolding, plugin CLI commands, and apply-time derivation were considered and rejected. | +| User-intent drift | Clean | The design now includes both CLI/IaC evaluation and plugin/module requirement-provider interfaces, matching the user's composability ask. | + +**Options the author may not have considered:** + +1. Require all provider mappers to return a plan summary only, and have core + build `ResourceSpec` locally. This would reduce provider write power but + would move provider-specific config shape back into core, conflicting with + the ownership goal. +2. Make `satisfies` live under `config:` to avoid adding a `ModuleConfig` field. + This preserves old parsers but pollutes provider config and risks provider + canonical-key warnings. The top-level field is cleaner if editor preservation + ships with it. + +**Verdict reasoning:** The revised design addresses the important cycle-1 +issues without changing the core architecture. The remaining risk is execution +discipline: the implementation plan must split core proto/YAML work, editor +preservation, observability declarations, and provider mapper rollout into +reviewable PRs with focused verification. + diff --git a/docs/plans/2026-05-25-iac-derived-requirements-design.md b/docs/plans/2026-05-25-iac-derived-requirements-design.md index b9b779e9..48c39e81 100644 --- a/docs/plans/2026-05-25-iac-derived-requirements-design.md +++ b/docs/plans/2026-05-25-iac-derived-requirements-design.md @@ -413,8 +413,9 @@ plugin loading paths. the mapper RPC must accept credentials/config and may become slow. The first implementation should fail if a mapper tries to perform apply-like work. 3. YAGNI risk: modeling every observability backend upfront could get heavy. - Mitigation: features are strings with a small documented vocabulary, and - provider plugins can reject unsupported combinations. + Mitigation: v1 defines enums only for the required OTel, Datadog, + Prometheus, Loki, and Grafana path, and provider plugins can reject + unsupported combinations. 4. Partial failure: YAML write corruption would be the highest-impact bug. Mitigation: parse as `yaml.Node`, write atomically, and add golden/idempotence tests before implementation. From c5949a10747685474719db91706e0f5606026c52 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 00:09:24 -0400 Subject: [PATCH 04/15] docs: plan iac derived requirements --- .../2026-05-25-iac-derived-requirements.md | 875 ++++++++++++++++++ 1 file changed, 875 insertions(+) create mode 100644 docs/plans/2026-05-25-iac-derived-requirements.md diff --git a/docs/plans/2026-05-25-iac-derived-requirements.md b/docs/plans/2026-05-25-iac-derived-requirements.md new file mode 100644 index 00000000..abe7d91a --- /dev/null +++ b/docs/plans/2026-05-25-iac-derived-requirements.md @@ -0,0 +1,875 @@ +# IaC Derived Requirements Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** Add a lightweight, strict-proto-compatible path for `wfctl` to derive IaC YAML from application and plugin requirements, starting with observability and leaving room for web/api, brokers, databases, caches, and storage. + +**Architecture:** Workflow core owns requirement discovery, explicit satisfaction keys, YAML mutation, and the `wfctl infra derive` command. IaC provider plugins own provider/runtime mapping through a generated protobuf service, so DigitalOcean, AWS, GCP, Azure, and future providers can map the same canonical requirements differently without putting provider assumptions into `wfctl`. + +**Tech Stack:** Go, `gopkg.in/yaml.v3`, existing Workflow config loader, existing external-plugin gRPC/protobuf stack generated by `buf generate`, workflow-editor TypeScript serialization. + +**Base branch:** `main` + +--- + +## Scope Manifest + +**PR Count:** 5 +**Tasks:** 10 +**Estimated Lines of Change:** ~3600 + +**Out of scope:** +- Auto-applying derived IaC at `wfctl infra apply` time; derivation is explicit through `wfctl infra derive`. +- Heuristic comparison of existing IaC resources; explicit `modules[].satisfies` is the only v1 override/satisfaction mechanism. +- Provider-specific dashboard, alert, or monitor creation beyond canonical resource requirements needed to deploy telemetry collection. +- A full workflow-editor comment-preserving YAML rewrite. The editor task only preserves the new `satisfies` field through its existing parse/serialize model. +- Retrofitting every existing `workflow-plugin-*` repo in this plan. Observability plus provider mapper support are the release-blocking targets. + +**PR Grouping:** + +| PR # | Title | Tasks | Branch | +|------|-------|-------|--------| +| 1 | Add typed IaC requirement protocol | Task 1, Task 2, Task 3 | `feat/iac-requirement-proto` | +| 2 | Add derivation engine and YAML editing | Task 4, Task 5, Task 6 | `feat/iac-derive-engine` | +| 3 | Preserve `satisfies` in workflow-editor | Task 7 | `feat/editor-preserve-satisfies` | +| 4 | Emit observability requirements | Task 8 | `feat/observability-iac-requirements` | +| 5 | Map derived requirements in provider plugins | Task 9, Task 10 | `feat/provider-requirement-mappers` | + +**Status:** Draft + +## Design Inputs + +- Design: `docs/plans/2026-05-25-iac-derived-requirements-design.md` +- ADR: `decisions/0043-iac-derived-requirements.md` +- Design review reports: + - `docs/plans/2026-05-25-iac-derived-requirements-design.adversarial-review-1.md` + - `docs/plans/2026-05-25-iac-derived-requirements-design.adversarial-review-2.md` + +## Cross-Cutting Invariants + +- Strict protobuf compatibility is the default. New cross-plugin messages, services, and contracts must be concrete protobuf types/enums. Do not introduce `google.protobuf.Struct`, `Any`, or `map` equivalents. +- JSON byte fields are allowed only for provider-specific payloads that cannot be modeled generically yet, following the existing `config_json` precedent in `plugin/external/proto/iac.proto`. Every such field must have a comment explaining why it is not a proto field. +- `modules[].satisfies` values are stable requirement keys, not display names. Generated IaC modules must include the keys they satisfy. +- `wfctl infra derive` must be idempotent: running it twice with the same input must not append duplicate generated modules. +- Provider selection order is: explicit CLI flags, environment-specific hints, a single unambiguous existing `iac.provider`, then prompt/fail. +- Generated specs must never contain plaintext secrets. Use placeholders such as `${DATADOG_API_KEY}` or existing secret-reference shapes only. + +### Task 1: Extend the Strict IaC Proto + +**Files:** +- Modify: `plugin/external/proto/iac.proto` +- Modify generated: `plugin/external/proto/iac.pb.go` +- Modify generated: `plugin/external/proto/iac_grpc.pb.go` +- Modify: `plugin/external/sdk/contracts_iac_test.go` +- Modify: `plugin/external/sdk/iacserver.go` +- Modify: `plugin/external/adapter.go` + +**Step 1: Write failing contract tests** + +Add tests that assert the new mapper service is in the generated descriptors and contract registry: + +```go +func TestIaCProviderRequirementMapperIsStrictProto(t *testing.T) { + service := pb.IaCProviderRequirementMapper_ServiceDesc.ServiceName + if !strings.HasPrefix(service, "workflow.plugin.external.iac.") { + t.Fatalf("mapper service has unexpected namespace %q", service) + } + registry := sdk.BuildContractRegistry("test", nil) + assertStrictServiceContract(t, registry, service, "MapRequirements") +} +``` + +Add a proto guard test that fails if `iac.proto` imports `google/protobuf/struct.proto` or `google/protobuf/any.proto`. + +**Step 2: Run tests to verify failure** + +Run: + +```sh +GOWORK=off go test ./plugin/external/sdk -run 'TestIaCProviderRequirementMapper|TestIaCProtoRejectsLooseTypes' -count=1 +``` + +Expected: FAIL because `IaCProviderRequirementMapper_ServiceDesc` and the contract registry entry do not exist. + +**Step 3: Add proto types and service** + +Append strict canonical types to `plugin/external/proto/iac.proto`: + +```proto +enum RequirementKind { + REQUIREMENT_KIND_UNSPECIFIED = 0; + REQUIREMENT_KIND_OBSERVABILITY = 1; + REQUIREMENT_KIND_WEB_API = 2; + REQUIREMENT_KIND_MESSAGE_BROKER = 3; + REQUIREMENT_KIND_DATABASE = 4; + REQUIREMENT_KIND_CACHE = 5; + REQUIREMENT_KIND_STORAGE = 6; +} + +enum RequirementRuntime { + REQUIREMENT_RUNTIME_UNSPECIFIED = 0; + REQUIREMENT_RUNTIME_KUBERNETES = 1; + REQUIREMENT_RUNTIME_ECS = 2; + REQUIREMENT_RUNTIME_CLOUD_RUN = 3; + REQUIREMENT_RUNTIME_AZURE_CONTAINER_APPS = 4; + REQUIREMENT_RUNTIME_DIGITALOCEAN_APP_PLATFORM = 5; +} + +enum TelemetrySignal { + TELEMETRY_SIGNAL_UNSPECIFIED = 0; + TELEMETRY_SIGNAL_TRACES = 1; + TELEMETRY_SIGNAL_METRICS = 2; + TELEMETRY_SIGNAL_LOGS = 3; +} + +enum ObservabilityBackend { + OBSERVABILITY_BACKEND_UNSPECIFIED = 0; + OBSERVABILITY_BACKEND_OTEL = 1; + OBSERVABILITY_BACKEND_DATADOG = 2; + OBSERVABILITY_BACKEND_PROMETHEUS = 3; + OBSERVABILITY_BACKEND_LOKI = 4; + OBSERVABILITY_BACKEND_GRAFANA = 5; +} + +enum DeploymentMode { + DEPLOYMENT_MODE_UNSPECIFIED = 0; + DEPLOYMENT_MODE_SIDECAR = 1; + DEPLOYMENT_MODE_DAEMONSET = 2; + DEPLOYMENT_MODE_SIBLING_SERVICE = 3; + DEPLOYMENT_MODE_MANAGED = 4; +} + +message IaCRequirement { + string key = 1; + RequirementKind kind = 2; + repeated RequirementRuntime runtimes = 3; + repeated TelemetrySignal telemetry_signals = 4; + repeated ObservabilityBackend observability_backends = 5; + repeated DeploymentMode deployment_modes = 6; + repeated string vendor_features = 7; + bytes parameters_json = 8; +} + +message MapRequirementsRequest { + string provider = 1; + RequirementRuntime runtime = 2; + string environment = 3; + repeated IaCRequirement requirements = 4; +} + +message DerivedModuleSpec { + string name = 1; + string type = 2; + repeated string satisfies = 3; + bytes config_json = 4; + repeated string depends_on = 5; +} + +message MapRequirementsResponse { + repeated DerivedModuleSpec modules = 1; + repeated string warnings = 2; +} + +service IaCProviderRequirementMapper { + rpc MapRequirements(MapRequirementsRequest) returns (MapRequirementsResponse); +} +``` + +If implementation exposes a shortcoming in this schema, first try to model it as a new enum/message field. Use `parameters_json` only with an inline proto comment and a plan note explaining why strict modeling was not practical. + +**Step 4: Regenerate protobufs** + +Run: + +```sh +GOWORK=off go run github.com/bufbuild/buf/cmd/buf@latest generate +``` + +Expected: `plugin/external/proto/iac.pb.go` and `plugin/external/proto/iac_grpc.pb.go` include `IaCProviderRequirementMapper`. + +**Step 5: Register optional mapper service** + +Update `plugin/external/sdk/iacserver.go` so `RegisterAllIaCProviderServices` type-asserts provider implementations for the generated mapper server interface and registers it. Update the contract registry to advertise `IaCProviderRequirementMapper/MapRequirements` as `CONTRACT_MODE_STRICT_PROTO`. + +**Step 6: Add wfctl-side typed client hook** + +Update `plugin/external/adapter.go` only if the existing typed adapter path needs a convenience method for the mapper. Prefer using the generated `pb.NewIaCProviderRequirementMapperClient` directly where possible; do not add hand-written marshalling when the generated client can be used. + +**Step 7: Verify** + +Run: + +```sh +GOWORK=off go test ./plugin/external/proto ./plugin/external/sdk ./plugin/external -run 'TestIaCProviderRequirementMapper|TestIaCProtoRejectsLooseTypes|TestBuildContractRegistry|TestRegisterAllIaCProviderServices' -count=1 +GOWORK=off go test ./plugin/external/proto ./plugin/external/sdk ./plugin/external -count=1 +``` + +Expected: PASS. Generated service name begins with `workflow.plugin.external.iac.` and the registry advertises strict proto. + +**Rollback:** revert this PR and regenerate protobufs; provider plugins continue using existing IaC services. + +**Step 8: Commit** + +```sh +git add plugin/external/proto/iac.proto plugin/external/proto/iac.pb.go plugin/external/proto/iac_grpc.pb.go plugin/external/sdk plugin/external +git commit -m "feat: add iac requirement mapper protocol" +``` + +### Task 2: Add Local Requirement Model and Manifest v2 + +**Files:** +- Modify: `config/config.go` +- Modify: `config/config_test.go` +- Modify: `config/plugin_manifest.go` +- Test: `config/plugin_manifest_test.go` +- Create: `iac/requirements/types.go` +- Test: `iac/requirements/types_test.go` + +**Step 1: Write failing config and manifest tests** + +Add tests for: + +- `modules[].satisfies` round-trips through `config.LoadFromFile`. +- `plugin.json` can declare `moduleInfraRequirementsV2` with typed requirement fields. +- invalid requirement keys and unknown enum strings fail with actionable errors. + +Expected fixture: + +```yaml +modules: + - name: otel-collector + type: infra.container_service + satisfies: + - observability.telemetry.default + config: + image: otel/opentelemetry-collector-contrib:latest +``` + +**Step 2: Run tests to verify failure** + +Run: + +```sh +GOWORK=off go test ./config ./iac/requirements -run 'TestModuleSatisfies|TestPluginManifestRequirementV2|TestRequirementValidation' -count=1 +``` + +Expected: FAIL because `Satisfies` and the new requirement package do not exist. + +**Step 3: Implement `satisfies` and typed requirement structs** + +Add: + +```go +type ModuleConfig struct { + Name string `yaml:"name" json:"name"` + Type string `yaml:"type" json:"type"` + Satisfies []string `yaml:"satisfies,omitempty" json:"satisfies,omitempty"` + Config map[string]interface{} `yaml:"config,omitempty" json:"config,omitempty"` + DependsOn []string `yaml:"depends_on,omitempty" json:"depends_on,omitempty"` + Branches []string `yaml:"branches,omitempty" json:"branches,omitempty"` + Environments []string `yaml:"environments,omitempty" json:"environments,omitempty"` +} +``` + +Create `iac/requirements` with Go enums/string parsers that mirror the protobuf enums exactly. Include conversion helpers to/from `pb.IaCRequirement`. + +**Step 4: Extend plugin manifest parsing** + +Add `ModuleInfraRequirementsV2 []ModuleInfraRequirementV2` beside the existing v1 field. Keep v1 untouched for compatibility. Validate v2 in the manifest loader and convert to the local requirement model. + +**Step 5: Verify** + +Run: + +```sh +GOWORK=off go test ./config ./iac/requirements -count=1 +``` + +Expected: PASS, including invalid enum fixtures. + +**Rollback:** revert this PR. Existing module config files remain valid because `satisfies` is additive and omitted when empty. + +**Step 6: Commit** + +```sh +git add config iac/requirements +git commit -m "feat: model iac requirements in config" +``` + +### Task 3: Add Requirement Discovery Interfaces + +**Files:** +- Create: `iac/requirements/discovery.go` +- Test: `iac/requirements/discovery_test.go` +- Modify: `cmd/wfctl/plugin_infra.go` +- Test: `cmd/wfctl/plugin_infra_test.go` + +**Step 1: Write failing discovery tests** + +Cover: + +- built-in discovery from config shape emits web/api and broker requirements. +- static manifest v2 requirements are included. +- an in-process module/provider implementing the Go interface contributes requirements without importing a telemetry plugin. +- existing `modules[].satisfies` removes matching requirements from the unresolved set. + +Use an interface shaped like: + +```go +type Provider interface { + IaCRequirements(ctx context.Context, input Input) ([]Requirement, error) +} +``` + +**Step 2: Run tests to verify failure** + +Run: + +```sh +GOWORK=off go test ./iac/requirements ./cmd/wfctl -run 'TestDiscoverRequirements|TestDetectPluginInfraNeedsIncludesV2' -count=1 +``` + +Expected: FAIL because discovery does not exist and static manifest v2 is ignored. + +**Step 3: Implement discovery** + +Implement requirement collection in `iac/requirements` and adapt `cmd/wfctl/plugin_infra.go` so existing `DetectPluginInfraNeeds` can expose v2 requirements without breaking current v1 output. + +**Step 4: Verify** + +Run: + +```sh +GOWORK=off go test ./iac/requirements ./cmd/wfctl -run 'TestDiscoverRequirements|TestDetectPluginInfraNeedsIncludesV2' -count=1 +``` + +Expected: PASS. A requirement satisfied by `modules[].satisfies` is absent from unresolved output. + +**Rollback:** revert this PR; v1 plugin infra detection remains unchanged. + +**Step 5: Commit** + +```sh +git add iac/requirements cmd/wfctl/plugin_infra.go cmd/wfctl/plugin_infra_test.go +git commit -m "feat: discover iac requirements" +``` + +### Task 4: Add YAML Node Editing Package + +**Files:** +- Create: `config/yamledit/module_append.go` +- Test: `config/yamledit/module_append_test.go` +- Testdata: `config/yamledit/testdata/*.yaml` + +**Step 1: Write failing golden tests** + +Create golden cases for: + +- comments and unknown top-level keys preserved. +- unknown per-module keys preserved. +- `modules:` created when absent. +- generated modules appended after the last existing `infra.*` module when present, otherwise at the end of `modules`. +- anchors are parsed and re-emitted without panic. +- running the append operation twice does not duplicate modules with the same `satisfies` key. + +**Step 2: Run tests to verify failure** + +Run: + +```sh +GOWORK=off go test ./config/yamledit -count=1 +``` + +Expected: FAIL because the package does not exist. + +**Step 3: Implement with `yaml.Node`** + +Use `gopkg.in/yaml.v3` node mutation. Do not hand-roll YAML parsing or string insertion. Provide: + +```go +func AppendGeneratedModules(root *yaml.Node, modules []GeneratedModule) (changed bool, err error) +``` + +Sort generated modules by name for deterministic output. Preserve unknown keys by only mutating the `modules` sequence node. + +**Step 4: Verify** + +Run: + +```sh +GOWORK=off go test ./config/yamledit -count=1 +``` + +Expected: PASS, and repeated append golden output equals first output. + +**Rollback:** revert this PR; no runtime behavior changes exist until `wfctl infra derive` calls the package. + +**Step 5: Commit** + +```sh +git add config/yamledit +git commit -m "feat: add yaml editor for derived modules" +``` + +### Task 5: Add Derivation Engine and Provider Mapper Client + +**Files:** +- Create: `iac/derive/engine.go` +- Create: `iac/derive/provider.go` +- Test: `iac/derive/engine_test.go` +- Test: `iac/derive/provider_test.go` +- Modify: `cmd/wfctl/infra_provider_dispatch.go` + +**Step 1: Write failing engine tests** + +Cover: + +- provider/runtime precedence. +- non-interactive ambiguity returns a deterministic error. +- mapper response with plaintext secret-like config is rejected. +- mapper response with `${DATADOG_API_KEY}` is accepted. +- generated modules inherit `satisfies` keys. +- mapper warnings are surfaced. + +**Step 2: Run tests to verify failure** + +Run: + +```sh +GOWORK=off go test ./iac/derive ./cmd/wfctl -run 'TestDerive|TestProviderRuntimePrecedence' -count=1 +``` + +Expected: FAIL because the package and mapper client are absent. + +**Step 3: Implement engine** + +Implement: + +```go +type Options struct { + Provider string + Runtime requirements.Runtime + Environment string + NonInteractive bool +} + +type Result struct { + Requirements []requirements.Requirement + Modules []GeneratedModule + Warnings []string +} + +func Derive(ctx context.Context, cfg *config.WorkflowConfig, plugins []config.PluginManifest, mapper ProviderMapper, opts Options) (Result, error) +``` + +`ProviderMapper` should accept local typed requirements and use generated protobuf types internally when talking to external provider plugins. + +**Step 4: Wire provider dispatch** + +Reuse existing provider discovery in `cmd/wfctl/infra_provider_dispatch.go`. Add only small helpers needed by derivation; do not duplicate provider grouping logic. + +**Step 5: Verify** + +Run: + +```sh +GOWORK=off go test ./iac/derive ./cmd/wfctl -run 'TestDerive|TestProviderRuntimePrecedence' -count=1 +GOWORK=off go test ./iac/derive -count=1 +``` + +Expected: PASS. Secret rejection error includes the offending generated module name and key, not the secret value. + +**Rollback:** revert this PR. Since the CLI command is not wired yet, no user-facing behavior changes are active. + +**Step 6: Commit** + +```sh +git add iac/derive cmd/wfctl/infra_provider_dispatch.go +git commit -m "feat: derive iac modules from requirements" +``` + +### Task 6: Add `wfctl infra derive` + +**Files:** +- Modify: `cmd/wfctl/infra.go` +- Create: `cmd/wfctl/infra_derive.go` +- Test: `cmd/wfctl/infra_derive_test.go` +- Testdata: `cmd/wfctl/testdata/infra_derive/*.yaml` +- Modify docs: `docs/WFCTL.md` + +**Step 1: Write failing CLI tests** + +Use the same command style as existing `cmd/wfctl` tests. Cover: + +- `wfctl infra derive --help` includes `--write`, `--dry-run`, `--provider`, `--runtime`, `--env`, and `--non-interactive`. +- dry-run prints expanded YAML and does not mutate the file. +- write mode atomically updates the root YAML file. +- multi-file config reports imported requirements but mutates only `--config`. +- non-interactive ambiguity exits non-zero with the provider choices. +- second write is a no-op. + +**Step 2: Run tests to verify failure** + +Run: + +```sh +GOWORK=off go test ./cmd/wfctl -run 'TestInfraDerive' -count=1 +``` + +Expected: FAIL because the subcommand is not registered. + +**Step 3: Implement command** + +Add: + +```text +wfctl infra derive --config workflow.yaml --provider digitalocean --runtime do-app-platform --env production --write --non-interactive +wfctl infra derive --config workflow.yaml --provider aws --runtime ecs --dry-run --format yaml --non-interactive +``` + +Default to dry-run unless `--write` is set. `--dry-run` and `--write` are mutually exclusive. Use `config.LoadFromFile` for semantic loading and `yaml.Node` for mutation. + +**Step 4: Document command** + +Update `docs/WFCTL.md` with examples showing explicit `satisfies` override and observability derivation. Include a note that apply-time derivation is intentionally absent. + +**Step 5: Verify CLI behavior** + +Run: + +```sh +GOWORK=off go test ./cmd/wfctl -run 'TestInfraDerive' -count=1 +GOWORK=off go run ./cmd/wfctl infra derive --help +GOWORK=off go run ./cmd/wfctl infra derive --config cmd/wfctl/testdata/infra_derive/observability.yaml --provider digitalocean --runtime do-app-platform --dry-run --non-interactive +``` + +Expected: + +- Tests PASS. +- Help exits 0 and lists the derive flags. +- Representative invocation exits 0 and prints YAML containing `satisfies:`. + +**Rollback:** revert this PR. Existing `wfctl infra plan/apply/bootstrap` commands are unchanged. + +**Step 6: Commit** + +```sh +git add cmd/wfctl docs/WFCTL.md +git commit -m "feat: add wfctl infra derive" +``` + +### Task 7: Preserve `satisfies` in workflow-editor + +**Repository:** `/Users/jon/workspace/workflow-editor` + +**Files:** +- Modify: `src/types/workflow.ts` +- Modify: `src/utils/serialization.ts` +- Test: existing serialization test file or create `src/utils/serialization.satisfies.test.ts` + +**Step 1: Create a feature branch** + +Run: + +```sh +cd /Users/jon/workspace/workflow-editor +git switch -c feat/editor-preserve-satisfies +``` + +Expected: branch created from current `main` or the repo's active base branch. + +**Step 2: Write failing serialization test** + +Fixture: + +```yaml +modules: + - name: otel-collector + type: infra.container_service + satisfies: + - observability.telemetry.default + config: + image: otel/opentelemetry-collector-contrib:latest +``` + +Assert parse and serialize retain `satisfies` on the module. + +**Step 3: Run test to verify failure** + +Run: + +```sh +npm test -- serialization.satisfies +``` + +Expected: FAIL because `satisfies` is dropped. + +**Step 4: Implement preservation** + +Add `satisfies?: string[]` to `ModuleConfig` and pass it through `nodesToConfig`, `parseYaml`, and `configToYaml`. Do not change unrelated YAML formatting behavior. + +**Step 5: Verify** + +Run: + +```sh +npm test -- serialization.satisfies +npm test +``` + +Expected: PASS. Serialized YAML still includes the same `satisfies` entries. + +**Rollback:** revert this PR. Workflow CLI remains usable; editor users may lose `satisfies` until this ships, so Workflow docs should warn if this PR lags. + +**Step 6: Commit and PR** + +```sh +git add src/types/workflow.ts src/utils/serialization.ts src/utils/serialization.satisfies.test.ts +git commit -m "feat: preserve module satisfies metadata" +``` + +### Task 8: Emit Observability IaC Requirements + +**Repository:** `/Users/jon/workspace/workflow-plugin-observability` + +**Files:** +- Modify: `plugin.json` +- Modify or create Go source for strict requirement descriptors, likely `internal/contracts.go` or `internal/requirements.go` +- Test: `internal/requirements_test.go` +- Modify docs: `README.md` + +**Step 1: Create a feature branch** + +Run: + +```sh +cd /Users/jon/workspace/workflow-plugin-observability +git switch -c feat/observability-iac-requirements +``` + +Expected: branch created from `main`. + +**Step 2: Bump Workflow minimum version** + +After the Workflow core PRs merge and release, update `go.mod`, `plugin.json`, and docs to depend on the new minimum Workflow version. Do not guess the version before the Workflow tag exists. + +**Step 3: Write failing tests** + +Test that the plugin emits generic keys only: + +```go +func TestObservabilityRequirementsUseGenericNames(t *testing.T) { + reqs := RequirementsForConfig(Config{Backends: []Backend{BackendOTel}}) + require.NotEmpty(t, reqs) + for _, req := range reqs { + require.NotContains(t, req.Key, "cms") + require.NotContains(t, req.Key, "multisite") + } +} +``` + +Test OTel, Datadog, Prometheus, Loki, and Grafana backend combinations map to typed requirement enums. + +**Step 4: Run tests to verify failure** + +Run: + +```sh +GOWORK=off go test ./internal -run 'TestObservabilityRequirements' -count=1 +``` + +Expected: FAIL because no requirement descriptors are emitted. + +**Step 5: Implement requirements** + +Prefer manifest v2 static descriptors when configuration is static enough. Use a runtime provider only when config-specific backend/signal selection changes required IaC. Requirement keys must be generic, for example: + +```text +observability.telemetry.default +observability.metrics.prometheus +observability.logs.loki +observability.datadog.agent +``` + +Do not add `cms_*`, `multisite_*`, or application-specific names. + +**Step 6: Verify plugin behavior** + +Run: + +```sh +GOWORK=off go test ./... -count=1 +wfctl plugin validate --strict-contracts plugin.json +wfctl plugin verify-capabilities --plugin . +``` + +Expected: PASS. Plugin contracts remain strict proto and no generated names are application-specific. + +**Rollback:** revert this PR and pin consumers to the previous observability plugin release. Existing telemetry SDK behavior remains available without IaC derivation. + +**Step 7: Commit and PR** + +```sh +git add go.mod go.sum plugin.json README.md internal +git commit -m "feat: emit observability iac requirements" +``` + +### Task 9: Add Provider Mapper Conformance Fixtures + +**Repositories:** `/Users/jon/workspace/workflow-plugin-digitalocean`, `/Users/jon/workspace/workflow-plugin-aws`, `/Users/jon/workspace/workflow-plugin-gcp`, `/Users/jon/workspace/workflow-plugin-azure` + +**Files:** +- Add or modify provider conformance tests in each repo. +- Add shared fixture docs or testdata as local repo conventions allow. + +**Step 1: Create feature branches** + +Run in each repo: + +```sh +git switch -c feat/iac-requirement-mapper +``` + +Expected: branch created from each provider repo's `main`. + +**Step 2: Write failing conformance tests** + +For each provider, test at least: + +- OTel-only requirement returns a deployable collector module for the provider/runtime. +- Datadog requirement returns agent sidecar/daemonset/sibling-service mapping when supported. +- Unsupported runtime returns typed warning/error, not a partial malformed module. +- Returned modules include the original `satisfies` key. +- Returned `config_json` contains no plaintext secret values. + +**Step 3: Run tests to verify failure** + +Run in each repo: + +```sh +GOWORK=off go test ./... -run 'TestIaCRequirementMapper' -count=1 +``` + +Expected: FAIL because mapper service is not implemented. + +**Step 4: Implement mapper adapters** + +Implement the generated `IaCProviderRequirementMapperServer` in each provider plugin. Keep mappings provider-owned: + +- DigitalOcean: App Platform sibling service for OTel collector; Datadog sidecar/sibling pattern where existing driver supports it. +- AWS: ECS sidecar or service module for OTel/Datadog; leave Kubernetes daemonset mapping for EKS runtime. +- GCP: Cloud Run sidecar-equivalent/service mapping where supported; emit clear unsupported diagnostics where the platform lacks sidecars. +- Azure: Azure Container Apps sidecar-equivalent/service mapping where supported; emit clear unsupported diagnostics where unavailable. + +If a provider cannot faithfully support a mode, return a typed warning and no malformed replacement. Do not fall back to DigitalOcean-shaped config in non-DO repos. + +**Step 5: Verify each provider** + +Run in each repo: + +```sh +GOWORK=off go test ./... -count=1 +wfctl plugin validate --strict-contracts plugin.json +wfctl plugin verify-capabilities --plugin . +``` + +Expected: PASS. Capability output includes the mapper service when the provider implements it. + +**Rollback:** revert the provider PR. `wfctl infra derive` can still report that no mapper exists for that provider instead of generating invalid IaC. + +**Step 6: Commit and PRs** + +Run in each repo: + +```sh +git add . +git commit -m "feat: map iac requirements" +``` + +### Task 10: End-to-End Workflow Release and Version Bumps + +**Files:** +- Workflow release files according to the current repo release process. +- Provider and observability plugin `go.mod`, `go.sum`, `plugin.json`, release workflow inputs if present. +- Consumer app config that currently used custom `/metrics` or stale telemetry wiring, if discovered in local repos. + +**Step 1: Merge green Workflow PRs** + +After PRs 1 and 2 are green, merge them in order. Verify `main` is green before tagging. + +**Step 2: Tag Workflow release** + +Use the current Workflow release process from repo docs/workflows. Verify whether releases are tag-triggered or GoReleaser-driven before tagging. + +Expected: a new Workflow tag exists and contains `wfctl infra derive`, strict requirement proto, and `modules[].satisfies`. + +**Step 3: Bump plugin minimums** + +Update observability and provider plugins to depend on the new Workflow tag. This is mandatory before releasing mapper implementations. + +**Step 4: Remove custom `/metrics` reliance in owned consumers** + +Search: + +```sh +rg -n '(/metrics|promhttp|prometheus|metrics endpoint|ListenAndServe.*metrics)' /Users/jon/workspace -g'*.go' -g'*.yaml' -g'*.yml' +``` + +For owned apps that were depending on plugin-provided custom `/metrics`, update Workflow YAML to use observability requirements and derived IaC. Do not commit application-specific names into generic plugins. + +**Step 5: End-to-end smoke test** + +Use a temp copy of a representative Workflow YAML: + +```sh +wfctl infra derive --config /tmp/workflow-observability.yaml --provider digitalocean --runtime do-app-platform --write --non-interactive +wfctl validate --config /tmp/workflow-observability.yaml +``` + +Expected: derive exits 0, YAML includes generated modules with `satisfies`, and `wfctl validate` exits 0. + +**Rollback:** if release smoke fails, do not publish provider/observability tags. Revert the release candidate branch or tag a patch release after fixing; consumers stay pinned to the previous minimum Workflow version. + +**Step 6: Commit version bumps and consumer updates** + +Commit separately per repo: + +```sh +git add go.mod go.sum plugin.json README.md +git commit -m "chore: require workflow " +``` + +## Final Verification Matrix + +Run after all PRs in a repo are ready: + +```sh +cd /Users/jon/workspace/workflow/.worktrees/iac-derived-requirements +GOWORK=off go test ./config ./config/yamledit ./iac/... ./plugin/external/proto ./plugin/external/sdk ./plugin/external ./cmd/wfctl -count=1 +GOWORK=off go vet ./config ./config/yamledit ./iac/... ./plugin/external/... ./cmd/wfctl +GOWORK=off go run ./cmd/wfctl infra derive --help +``` + +Expected: + +- All tests PASS. +- `go vet` exits 0. +- Help exits 0 and shows `derive`. + +For each plugin repo touched: + +```sh +GOWORK=off go test ./... -count=1 +wfctl plugin validate --strict-contracts plugin.json +wfctl plugin verify-capabilities --plugin . +``` + +Expected: PASS, with strict proto contracts and mapper capabilities where implemented. + +For workflow-editor: + +```sh +npm test +``` + +Expected: PASS, including the `satisfies` serialization test. From 7f8f44e9aa7af98517fec9613cbe1f9e9558da17 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 00:10:18 -0400 Subject: [PATCH 05/15] docs: review iac derivation plan --- ...rived-requirements.adversarial-review-1.md | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 docs/plans/2026-05-25-iac-derived-requirements.adversarial-review-1.md diff --git a/docs/plans/2026-05-25-iac-derived-requirements.adversarial-review-1.md b/docs/plans/2026-05-25-iac-derived-requirements.adversarial-review-1.md new file mode 100644 index 00000000..76aa4453 --- /dev/null +++ b/docs/plans/2026-05-25-iac-derived-requirements.adversarial-review-1.md @@ -0,0 +1,41 @@ +### Adversarial Review Report + +**Phase:** plan +**Artifact:** `docs/plans/2026-05-25-iac-derived-requirements.md` +**Status:** FAIL + +**Findings (Critical):** +- [under-decomposition / hidden serial dependencies] `docs/plans/2026-05-25-iac-derived-requirements.md:17-36,717-787`: The scope manifest claims 5 PRs, but PR 5 spans four provider repositories and Task 10 also includes workflow release, provider version bumps, observability version bumps, and consumer app edits. That is not one independently reviewable PR and it will confuse scope-lock and execution. Recommendation: split PR grouping by repository and make release/version-bump work explicit follow-up PRs/tasks. + +**Findings (Important):** +- [user-intent drift / missing failure mode] `docs/plans/2026-05-25-iac-derived-requirements.md:299-355` vs `docs/plans/2026-05-25-iac-derived-requirements-design.md:215-226`: The design includes optional strict-proto external-plugin requirement discovery for config-aware plugins, but the plan only implements an in-process Go interface and static manifest v2. That misses the composable plugin requirement path the user asked for. Recommendation: add a task for `IaCRequirementDiscovery` proto service, SDK registration, contract tests, and wfctl collection. +- [design drift] `docs/plans/2026-05-25-iac-derived-requirements.md:142-170` vs `docs/plans/2026-05-25-iac-derived-requirements-design.md:122-149,186-192`: The plan's proto sketch drops `source`, `resource_type_hint`, `environment`, accepted/rejected diagnostics, and ordered notes that the design says are part of the typed exchange. It replaces rejected diagnostics with plain warnings. Recommendation: model these as strict proto fields/messages unless a specific field has a documented reason to defer. +- [verification-class mismatch] `docs/plans/2026-05-25-iac-derived-requirements.md:536-550`: The Workflow CLI representative invocation uses `--provider digitalocean` before provider plugins implement the mapper. This can fail for reasons unrelated to Workflow CLI correctness. Recommendation: verify Workflow CLI with a fake/in-process mapper fixture first, then add provider-backed smoke tests only after provider mapper PRs. +- [missing rollback wiring / hidden dependencies] `docs/plans/2026-05-25-iac-derived-requirements.md:789-840`: Task 10 says to merge, tag, bump plugin minimums, remove consumer `/metrics` reliance, and commit separately per repo, but it is assigned to the provider mapper PR. This mixes release operations with code changes and has no clear rollback for a partially released Workflow tag. Recommendation: split release, plugin min-version bumps, and consumer migrations into separate tasks with explicit prereqs and no shared PR row. + +**Findings (Minor):** +- [repo-precedent conflict] `docs/plans/2026-05-25-iac-derived-requirements.md:597-618`: The editor test command is guessed as `npm test -- serialization.satisfies`; the plan should inspect the repo's package scripts and use the exact Vitest/Jest command. Recommendation: add an exploration step or replace with the verified command after checking `package.json`. +- [verification gap] `docs/plans/2026-05-25-iac-derived-requirements.md:180-188`: The proto generation step uses `go run github.com/bufbuild/buf/cmd/buf@latest`, which is convenient but not pinned. Recommendation: either use existing repo release conventions for Buf or document that this is a tool invocation only and verify generated headers/CI with committed output. + +**Bug-class scan transcript:** + +| Class | Result | Note | +|---|---|---| +| Unstated assumptions | Finding | Assumes provider plugins can be updated and released inside one PR row despite living in separate repos. | +| Repo-precedent conflicts | Finding | The plan's PR manifest is repo-local, but several tasks are cross-repo operations that cannot share one branch/PR. | +| YAGNI violations | Clean | The explicit derive command and provider mapper are justified by the user ask and prior design. | +| Missing failure modes | Finding | Partial release/version-bump failure is not decomposed or rollback-safe. | +| Security / privacy at architecture level | Clean | Secret handling is explicitly tested and rejects plaintext secret-like generated config. | +| Rollback story | Finding | Rollback notes exist per task, but the release/version-bump task has no safe rollback sequence for partially published tags. | +| Simpler alternative not considered | Clean | Manifest-only and apply-time derivation were considered and rejected in the design. | +| User-intent drift | Finding | Missing external-plugin requirement discovery weakens the Go-interface-without-hard-dependency requirement for out-of-process plugins. | +| Over-decomposition / under-decomposition | Finding | Provider and release work is under-decomposed across repos. | +| Verification-class mismatch | Finding | Workflow CLI smoke depends on provider plugin behavior before provider mapper implementation exists. | +| Hidden serial dependencies | Finding | Observability/plugin/provider tasks depend on the Workflow release tag but are grouped as if one PR can contain them. | +| Missing rollback wiring | Finding | Release and consumer migration rollback are not executable steps. | + +**Options the author may not have considered:** +1. Split Workflow into two PRs, editor into one PR, observability into one PR, each provider into its own PR, then one release/version-bump wave. This increases PR count but matches actual repository boundaries and keeps failures revertible. +2. Implement only Workflow core plus a fake mapper in the first wave, then release provider mappers incrementally. This makes `wfctl infra derive` testable without blocking on every provider, but it delays real cross-cloud proof until follow-up PRs. + +**Verdict reasoning:** The design direction is still sound, but the implementation plan is not executable as written. The largest issue is the scope manifest: it describes one provider PR and one release task where the work actually crosses at least six repositories plus consumer migrations. The strict-proto surface also regressed from the design by omitting dynamic external-plugin requirement discovery and typed mapper diagnostics. Revise the plan before alignment-check or execution. From 524748cb665025b87beba4c0a30f5665b6dccc78 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 00:14:20 -0400 Subject: [PATCH 06/15] docs: revise iac derivation plan --- .../2026-05-25-iac-derived-requirements.md | 340 +++++++++++++----- 1 file changed, 251 insertions(+), 89 deletions(-) diff --git a/docs/plans/2026-05-25-iac-derived-requirements.md b/docs/plans/2026-05-25-iac-derived-requirements.md index abe7d91a..a0f9e31a 100644 --- a/docs/plans/2026-05-25-iac-derived-requirements.md +++ b/docs/plans/2026-05-25-iac-derived-requirements.md @@ -14,9 +14,9 @@ ## Scope Manifest -**PR Count:** 5 -**Tasks:** 10 -**Estimated Lines of Change:** ~3600 +**PR Count:** 8 +**Tasks:** 12 +**Estimated Lines of Change:** ~4600 **Out of scope:** - Auto-applying derived IaC at `wfctl infra apply` time; derivation is explicit through `wfctl infra derive`. @@ -33,7 +33,10 @@ | 2 | Add derivation engine and YAML editing | Task 4, Task 5, Task 6 | `feat/iac-derive-engine` | | 3 | Preserve `satisfies` in workflow-editor | Task 7 | `feat/editor-preserve-satisfies` | | 4 | Emit observability requirements | Task 8 | `feat/observability-iac-requirements` | -| 5 | Map derived requirements in provider plugins | Task 9, Task 10 | `feat/provider-requirement-mappers` | +| 5 | Map derived requirements in workflow-plugin-digitalocean | Task 9 | `feat/iac-requirement-mapper` | +| 6 | Map derived requirements in workflow-plugin-aws | Task 10 | `feat/iac-requirement-mapper` | +| 7 | Map derived requirements in workflow-plugin-gcp | Task 11 | `feat/iac-requirement-mapper` | +| 8 | Map derived requirements in workflow-plugin-azure | Task 12 | `feat/iac-requirement-mapper` | **Status:** Draft @@ -81,15 +84,25 @@ func TestIaCProviderRequirementMapperIsStrictProto(t *testing.T) { Add a proto guard test that fails if `iac.proto` imports `google/protobuf/struct.proto` or `google/protobuf/any.proto`. +Add the same strict-contract assertion for the config-aware requirement discovery service: + +```go +func TestIaCRequirementDiscoveryIsStrictProto(t *testing.T) { + service := pb.IaCRequirementDiscovery_ServiceDesc.ServiceName + registry := sdk.BuildContractRegistry("test", nil) + assertStrictServiceContract(t, registry, service, "DiscoverRequirements") +} +``` + **Step 2: Run tests to verify failure** Run: ```sh -GOWORK=off go test ./plugin/external/sdk -run 'TestIaCProviderRequirementMapper|TestIaCProtoRejectsLooseTypes' -count=1 +GOWORK=off go test ./plugin/external/sdk -run 'TestIaCProviderRequirementMapper|TestIaCRequirementDiscovery|TestIaCProtoRejectsLooseTypes' -count=1 ``` -Expected: FAIL because `IaCProviderRequirementMapper_ServiceDesc` and the contract registry entry do not exist. +Expected: FAIL because `IaCProviderRequirementMapper_ServiceDesc`, `IaCRequirementDiscovery_ServiceDesc`, and the contract registry entries do not exist. **Step 3: Add proto types and service** @@ -142,12 +155,25 @@ enum DeploymentMode { message IaCRequirement { string key = 1; RequirementKind kind = 2; - repeated RequirementRuntime runtimes = 3; - repeated TelemetrySignal telemetry_signals = 4; - repeated ObservabilityBackend observability_backends = 5; - repeated DeploymentMode deployment_modes = 6; - repeated string vendor_features = 7; - bytes parameters_json = 8; + string source = 3; + string resource_type_hint = 4; + string environment = 5; + repeated RequirementRuntime runtimes = 6; + repeated TelemetrySignal telemetry_signals = 7; + repeated ObservabilityBackend observability_backends = 8; + repeated DeploymentMode deployment_modes = 9; + repeated string vendor_features = 10; + bytes parameters_json = 11; +} + +message DiscoverRequirementsRequest { + string environment = 1; + bytes workflow_config_json = 2; + bytes module_config_json = 3; +} + +message DiscoverRequirementsResponse { + repeated IaCRequirement requirements = 1; } message MapRequirementsRequest { @@ -166,8 +192,26 @@ message DerivedModuleSpec { } message MapRequirementsResponse { - repeated DerivedModuleSpec modules = 1; - repeated string warnings = 2; + repeated string accepted_keys = 1; + repeated RequirementDiagnostic rejected = 2; + repeated DerivedModuleSpec modules = 3; + repeated RequirementNote notes = 4; +} + +message RequirementDiagnostic { + string key = 1; + string code = 2; + string message = 3; +} + +message RequirementNote { + string key = 1; + string message = 2; + bool interactive = 3; +} + +service IaCRequirementDiscovery { + rpc DiscoverRequirements(DiscoverRequirementsRequest) returns (DiscoverRequirementsResponse); } service IaCProviderRequirementMapper { @@ -175,21 +219,21 @@ service IaCProviderRequirementMapper { } ``` -If implementation exposes a shortcoming in this schema, first try to model it as a new enum/message field. Use `parameters_json` only with an inline proto comment and a plan note explaining why strict modeling was not practical. +If implementation exposes a shortcoming in this schema, first try to model it as a new enum/message field. Use `parameters_json`, `workflow_config_json`, `module_config_json`, or `config_json` only with an inline proto comment and a plan note explaining why strict modeling was not practical. These JSON byte fields are for already-declared Workflow/provider config payloads, not arbitrary cross-plugin schema. **Step 4: Regenerate protobufs** Run: ```sh -GOWORK=off go run github.com/bufbuild/buf/cmd/buf@latest generate +buf generate ``` -Expected: `plugin/external/proto/iac.pb.go` and `plugin/external/proto/iac_grpc.pb.go` include `IaCProviderRequirementMapper`. +Expected: `plugin/external/proto/iac.pb.go` and `plugin/external/proto/iac_grpc.pb.go` include `IaCProviderRequirementMapper` and `IaCRequirementDiscovery`. **Step 5: Register optional mapper service** -Update `plugin/external/sdk/iacserver.go` so `RegisterAllIaCProviderServices` type-asserts provider implementations for the generated mapper server interface and registers it. Update the contract registry to advertise `IaCProviderRequirementMapper/MapRequirements` as `CONTRACT_MODE_STRICT_PROTO`. +Update `plugin/external/sdk/iacserver.go` so `RegisterAllIaCProviderServices` type-asserts provider implementations for the generated mapper and discovery server interfaces and registers them. Update the contract registry to advertise `IaCProviderRequirementMapper/MapRequirements` and `IaCRequirementDiscovery/DiscoverRequirements` as `CONTRACT_MODE_STRICT_PROTO`. **Step 6: Add wfctl-side typed client hook** @@ -200,11 +244,11 @@ Update `plugin/external/adapter.go` only if the existing typed adapter path need Run: ```sh -GOWORK=off go test ./plugin/external/proto ./plugin/external/sdk ./plugin/external -run 'TestIaCProviderRequirementMapper|TestIaCProtoRejectsLooseTypes|TestBuildContractRegistry|TestRegisterAllIaCProviderServices' -count=1 +GOWORK=off go test ./plugin/external/proto ./plugin/external/sdk ./plugin/external -run 'TestIaCProviderRequirementMapper|TestIaCRequirementDiscovery|TestIaCProtoRejectsLooseTypes|TestBuildContractRegistry|TestRegisterAllIaCProviderServices' -count=1 GOWORK=off go test ./plugin/external/proto ./plugin/external/sdk ./plugin/external -count=1 ``` -Expected: PASS. Generated service name begins with `workflow.plugin.external.iac.` and the registry advertises strict proto. +Expected: PASS. Generated service names begin with `workflow.plugin.external.iac.` and the registry advertises strict proto. **Rollback:** revert this PR and regenerate protobufs; provider plugins continue using existing IaC services. @@ -300,7 +344,9 @@ git commit -m "feat: model iac requirements in config" **Files:** - Create: `iac/requirements/discovery.go` +- Create: `iac/requirements/external.go` - Test: `iac/requirements/discovery_test.go` +- Test: `iac/requirements/external_test.go` - Modify: `cmd/wfctl/plugin_infra.go` - Test: `cmd/wfctl/plugin_infra_test.go` @@ -311,6 +357,7 @@ Cover: - built-in discovery from config shape emits web/api and broker requirements. - static manifest v2 requirements are included. - an in-process module/provider implementing the Go interface contributes requirements without importing a telemetry plugin. +- an out-of-process plugin implementing `IaCRequirementDiscovery` contributes typed requirements through the generated protobuf client. - existing `modules[].satisfies` removes matching requirements from the unresolved set. Use an interface shaped like: @@ -326,24 +373,24 @@ type Provider interface { Run: ```sh -GOWORK=off go test ./iac/requirements ./cmd/wfctl -run 'TestDiscoverRequirements|TestDetectPluginInfraNeedsIncludesV2' -count=1 +GOWORK=off go test ./iac/requirements ./cmd/wfctl -run 'TestDiscoverRequirements|TestExternalRequirementDiscovery|TestDetectPluginInfraNeedsIncludesV2' -count=1 ``` -Expected: FAIL because discovery does not exist and static manifest v2 is ignored. +Expected: FAIL because discovery does not exist, static manifest v2 is ignored, and no external discovery adapter exists. **Step 3: Implement discovery** -Implement requirement collection in `iac/requirements` and adapt `cmd/wfctl/plugin_infra.go` so existing `DetectPluginInfraNeeds` can expose v2 requirements without breaking current v1 output. +Implement requirement collection in `iac/requirements` and adapt `cmd/wfctl/plugin_infra.go` so existing `DetectPluginInfraNeeds` can expose v2 requirements without breaking current v1 output. Add an external discovery adapter that uses `pb.NewIaCRequirementDiscoveryClient` directly and converts strict proto messages to the local requirement model. **Step 4: Verify** Run: ```sh -GOWORK=off go test ./iac/requirements ./cmd/wfctl -run 'TestDiscoverRequirements|TestDetectPluginInfraNeedsIncludesV2' -count=1 +GOWORK=off go test ./iac/requirements ./cmd/wfctl -run 'TestDiscoverRequirements|TestExternalRequirementDiscovery|TestDetectPluginInfraNeedsIncludesV2' -count=1 ``` -Expected: PASS. A requirement satisfied by `modules[].satisfies` is absent from unresolved output. +Expected: PASS. A requirement satisfied by `modules[].satisfies` is absent from unresolved output, and the external discovery adapter uses generated protobuf clients rather than a loose map bridge. **Rollback:** revert this PR; v1 plugin infra detection remains unchanged. @@ -429,7 +476,7 @@ Cover: - mapper response with plaintext secret-like config is rejected. - mapper response with `${DATADOG_API_KEY}` is accepted. - generated modules inherit `satisfies` keys. -- mapper warnings are surfaced. +- mapper rejected diagnostics and notes are surfaced. **Step 2: Run tests to verify failure** @@ -456,7 +503,8 @@ type Options struct { type Result struct { Requirements []requirements.Requirement Modules []GeneratedModule - Warnings []string + Rejected []Diagnostic + Notes []Note } func Derive(ctx context.Context, cfg *config.WorkflowConfig, plugins []config.PluginManifest, mapper ProviderMapper, opts Options) (Result, error) @@ -477,7 +525,7 @@ GOWORK=off go test ./iac/derive ./cmd/wfctl -run 'TestDerive|TestProviderRuntime GOWORK=off go test ./iac/derive -count=1 ``` -Expected: PASS. Secret rejection error includes the offending generated module name and key, not the secret value. +Expected: PASS. Secret rejection error includes the offending generated module name and key, not the secret value; rejected mapper diagnostics remain attached to the requirement key that produced them. **Rollback:** revert this PR. Since the CLI command is not wired yet, no user-facing behavior changes are active. @@ -507,6 +555,7 @@ Use the same command style as existing `cmd/wfctl` tests. Cover: - multi-file config reports imported requirements but mutates only `--config`. - non-interactive ambiguity exits non-zero with the provider choices. - second write is a no-op. +- tests use a fake generated-proto mapper fixture so Workflow CLI correctness does not depend on a real provider plugin release. **Step 2: Run tests to verify failure** @@ -540,14 +589,13 @@ Run: ```sh GOWORK=off go test ./cmd/wfctl -run 'TestInfraDerive' -count=1 GOWORK=off go run ./cmd/wfctl infra derive --help -GOWORK=off go run ./cmd/wfctl infra derive --config cmd/wfctl/testdata/infra_derive/observability.yaml --provider digitalocean --runtime do-app-platform --dry-run --non-interactive ``` Expected: - Tests PASS. - Help exits 0 and lists the derive flags. -- Representative invocation exits 0 and prints YAML containing `satisfies:`. +- `TestInfraDeriveDryRunWithFakeMapper` prints YAML containing `satisfies:` without mutating the fixture. **Rollback:** revert this PR. Existing `wfctl infra plan/apply/bootstrap` commands are unchanged. @@ -599,7 +647,7 @@ Assert parse and serialize retain `satisfies` on the module. Run: ```sh -npm test -- serialization.satisfies +npm test -- src/utils/serialization.satisfies.test.ts ``` Expected: FAIL because `satisfies` is dropped. @@ -613,7 +661,7 @@ Add `satisfies?: string[]` to `ModuleConfig` and pass it through `nodesToConfig` Run: ```sh -npm test -- serialization.satisfies +npm test -- src/utils/serialization.satisfies.test.ts npm test ``` @@ -714,58 +762,94 @@ git add go.mod go.sum plugin.json README.md internal git commit -m "feat: emit observability iac requirements" ``` -### Task 9: Add Provider Mapper Conformance Fixtures +### Task 9: Add DigitalOcean Requirement Mapper -**Repositories:** `/Users/jon/workspace/workflow-plugin-digitalocean`, `/Users/jon/workspace/workflow-plugin-aws`, `/Users/jon/workspace/workflow-plugin-gcp`, `/Users/jon/workspace/workflow-plugin-azure` +**Repository:** `/Users/jon/workspace/workflow-plugin-digitalocean` **Files:** -- Add or modify provider conformance tests in each repo. -- Add shared fixture docs or testdata as local repo conventions allow. +- Modify mapper/provider files according to the repo's existing IaC provider structure. +- Test: add `TestIaCRequirementMapperDigitalOcean` near existing IaC provider tests. +- Modify: `go.mod`, `go.sum`, `plugin.json`, docs only after the Workflow release tag exists. -**Step 1: Create feature branches** - -Run in each repo: +**Step 1: Create feature branch** ```sh +cd /Users/jon/workspace/workflow-plugin-digitalocean git switch -c feat/iac-requirement-mapper ``` -Expected: branch created from each provider repo's `main`. +Expected: branch created from `main`. **Step 2: Write failing conformance tests** -For each provider, test at least: +Cover OTel collector on DigitalOcean App Platform, Datadog agent where existing App Platform sidecar/sibling support allows it, unsupported runtime diagnostics, `satisfies` propagation, and no plaintext secrets in `config_json`. + +**Step 3: Run test to verify failure** + +```sh +GOWORK=off go test ./... -run 'TestIaCRequirementMapperDigitalOcean' -count=1 +``` + +Expected: FAIL because the mapper service is not implemented. + +**Step 4: Implement mapper** + +Implement generated `IaCProviderRequirementMapperServer` using DigitalOcean-owned App Platform module shapes. Return typed `RequirementDiagnostic` entries when a requested deployment mode cannot be represented. + +**Step 5: Verify** + +```sh +GOWORK=off go test ./... -count=1 +wfctl plugin validate --strict-contracts plugin.json +wfctl plugin verify-capabilities --plugin . +``` -- OTel-only requirement returns a deployable collector module for the provider/runtime. -- Datadog requirement returns agent sidecar/daemonset/sibling-service mapping when supported. -- Unsupported runtime returns typed warning/error, not a partial malformed module. -- Returned modules include the original `satisfies` key. -- Returned `config_json` contains no plaintext secret values. +Expected: PASS. Capability output includes `IaCProviderRequirementMapper`. -**Step 3: Run tests to verify failure** +**Rollback:** revert this provider PR. Workflow can still derive with other providers or report that no DigitalOcean mapper is available. -Run in each repo: +**Step 6: Commit and PR** ```sh -GOWORK=off go test ./... -run 'TestIaCRequirementMapper' -count=1 +git add . +git commit -m "feat: map iac requirements for digitalocean" ``` -Expected: FAIL because mapper service is not implemented. +### Task 10: Add AWS Requirement Mapper + +**Repository:** `/Users/jon/workspace/workflow-plugin-aws` -**Step 4: Implement mapper adapters** +**Files:** +- Modify mapper/provider files according to the repo's existing IaC provider structure. +- Test: add `TestIaCRequirementMapperAWS` near existing IaC provider tests. +- Modify: `go.mod`, `go.sum`, `plugin.json`, docs only after the Workflow release tag exists. + +**Step 1: Create feature branch** -Implement the generated `IaCProviderRequirementMapperServer` in each provider plugin. Keep mappings provider-owned: +```sh +cd /Users/jon/workspace/workflow-plugin-aws +git switch -c feat/iac-requirement-mapper +``` -- DigitalOcean: App Platform sibling service for OTel collector; Datadog sidecar/sibling pattern where existing driver supports it. -- AWS: ECS sidecar or service module for OTel/Datadog; leave Kubernetes daemonset mapping for EKS runtime. -- GCP: Cloud Run sidecar-equivalent/service mapping where supported; emit clear unsupported diagnostics where the platform lacks sidecars. -- Azure: Azure Container Apps sidecar-equivalent/service mapping where supported; emit clear unsupported diagnostics where unavailable. +Expected: branch created from `main`. -If a provider cannot faithfully support a mode, return a typed warning and no malformed replacement. Do not fall back to DigitalOcean-shaped config in non-DO repos. +**Step 2: Write failing conformance tests** -**Step 5: Verify each provider** +Cover ECS sidecar/service mapping for OTel and Datadog, EKS daemonset diagnostics if Kubernetes runtime is supported, unsupported runtime diagnostics, `satisfies` propagation, and secret placeholder enforcement. -Run in each repo: +**Step 3: Run test to verify failure** + +```sh +GOWORK=off go test ./... -run 'TestIaCRequirementMapperAWS' -count=1 +``` + +Expected: FAIL because the mapper service is not implemented. + +**Step 4: Implement mapper** + +Implement generated `IaCProviderRequirementMapperServer` using AWS-owned ECS/EKS module shapes. Do not copy DigitalOcean config keys into AWS output. + +**Step 5: Verify** ```sh GOWORK=off go test ./... -count=1 @@ -773,72 +857,150 @@ wfctl plugin validate --strict-contracts plugin.json wfctl plugin verify-capabilities --plugin . ``` -Expected: PASS. Capability output includes the mapper service when the provider implements it. +Expected: PASS. Capability output includes `IaCProviderRequirementMapper`. -**Rollback:** revert the provider PR. `wfctl infra derive` can still report that no mapper exists for that provider instead of generating invalid IaC. +**Rollback:** revert this provider PR. Workflow can still derive with other providers or report that no AWS mapper is available. -**Step 6: Commit and PRs** +**Step 6: Commit and PR** -Run in each repo: +```sh +git add . +git commit -m "feat: map iac requirements for aws" +``` + +### Task 11: Add GCP Requirement Mapper + +**Repository:** `/Users/jon/workspace/workflow-plugin-gcp` + +**Files:** +- Modify mapper/provider files according to the repo's existing IaC provider structure. +- Test: add `TestIaCRequirementMapperGCP` near existing IaC provider tests. +- Modify: `go.mod`, `go.sum`, `plugin.json`, docs only after the Workflow release tag exists. + +**Step 1: Create feature branch** + +```sh +cd /Users/jon/workspace/workflow-plugin-gcp +git switch -c feat/iac-requirement-mapper +``` + +Expected: branch created from `main`. + +**Step 2: Write failing conformance tests** + +Cover Cloud Run service/sidecar-equivalent mapping where supported, GKE daemonset mapping where supported, unsupported runtime diagnostics, `satisfies` propagation, and secret placeholder enforcement. + +**Step 3: Run test to verify failure** + +```sh +GOWORK=off go test ./... -run 'TestIaCRequirementMapperGCP' -count=1 +``` + +Expected: FAIL because the mapper service is not implemented. + +**Step 4: Implement mapper** + +Implement generated `IaCProviderRequirementMapperServer` using GCP-owned Cloud Run/GKE module shapes. Return diagnostics instead of malformed modules for runtimes that cannot host the requested mode. + +**Step 5: Verify** + +```sh +GOWORK=off go test ./... -count=1 +wfctl plugin validate --strict-contracts plugin.json +wfctl plugin verify-capabilities --plugin . +``` + +Expected: PASS. Capability output includes `IaCProviderRequirementMapper`. + +**Rollback:** revert this provider PR. Workflow can still derive with other providers or report that no GCP mapper is available. + +**Step 6: Commit and PR** ```sh git add . -git commit -m "feat: map iac requirements" +git commit -m "feat: map iac requirements for gcp" ``` -### Task 10: End-to-End Workflow Release and Version Bumps +### Task 12: Add Azure Requirement Mapper + +**Repository:** `/Users/jon/workspace/workflow-plugin-azure` **Files:** -- Workflow release files according to the current repo release process. -- Provider and observability plugin `go.mod`, `go.sum`, `plugin.json`, release workflow inputs if present. -- Consumer app config that currently used custom `/metrics` or stale telemetry wiring, if discovered in local repos. +- Modify mapper/provider files according to the repo's existing IaC provider structure. +- Test: add `TestIaCRequirementMapperAzure` near existing IaC provider tests. +- Modify: `go.mod`, `go.sum`, `plugin.json`, docs only after the Workflow release tag exists. -**Step 1: Merge green Workflow PRs** +**Step 1: Create feature branch** -After PRs 1 and 2 are green, merge them in order. Verify `main` is green before tagging. +```sh +cd /Users/jon/workspace/workflow-plugin-azure +git switch -c feat/iac-requirement-mapper +``` -**Step 2: Tag Workflow release** +Expected: branch created from `main`. -Use the current Workflow release process from repo docs/workflows. Verify whether releases are tag-triggered or GoReleaser-driven before tagging. +**Step 2: Write failing conformance tests** -Expected: a new Workflow tag exists and contains `wfctl infra derive`, strict requirement proto, and `modules[].satisfies`. +Cover Azure Container Apps sidecar-equivalent/service mapping where supported, AKS daemonset mapping where supported, unsupported runtime diagnostics, `satisfies` propagation, and secret placeholder enforcement. -**Step 3: Bump plugin minimums** +**Step 3: Run test to verify failure** -Update observability and provider plugins to depend on the new Workflow tag. This is mandatory before releasing mapper implementations. +```sh +GOWORK=off go test ./... -run 'TestIaCRequirementMapperAzure' -count=1 +``` + +Expected: FAIL because the mapper service is not implemented. -**Step 4: Remove custom `/metrics` reliance in owned consumers** +**Step 4: Implement mapper** -Search: +Implement generated `IaCProviderRequirementMapperServer` using Azure-owned Container Apps/AKS module shapes. Return diagnostics instead of malformed modules for runtimes that cannot host the requested mode. + +**Step 5: Verify** ```sh -rg -n '(/metrics|promhttp|prometheus|metrics endpoint|ListenAndServe.*metrics)' /Users/jon/workspace -g'*.go' -g'*.yaml' -g'*.yml' +GOWORK=off go test ./... -count=1 +wfctl plugin validate --strict-contracts plugin.json +wfctl plugin verify-capabilities --plugin . ``` -For owned apps that were depending on plugin-provided custom `/metrics`, update Workflow YAML to use observability requirements and derived IaC. Do not commit application-specific names into generic plugins. +Expected: PASS. Capability output includes `IaCProviderRequirementMapper`. -**Step 5: End-to-end smoke test** +**Rollback:** revert this provider PR. Workflow can still derive with other providers or report that no Azure mapper is available. -Use a temp copy of a representative Workflow YAML: +**Step 6: Commit and PR** ```sh -wfctl infra derive --config /tmp/workflow-observability.yaml --provider digitalocean --runtime do-app-platform --write --non-interactive -wfctl validate --config /tmp/workflow-observability.yaml +git add . +git commit -m "feat: map iac requirements for azure" ``` -Expected: derive exits 0, YAML includes generated modules with `satisfies`, and `wfctl validate` exits 0. +## Release and Migration Sequence -**Rollback:** if release smoke fails, do not publish provider/observability tags. Revert the release candidate branch or tag a patch release after fixing; consumers stay pinned to the previous minimum Workflow version. +These steps are operational gates, not scope-manifest PR tasks. -**Step 6: Commit version bumps and consumer updates** +1. Merge Workflow PRs 1 and 2 only after CI is green. +2. Inspect the current Workflow release workflow before tagging. If tag-triggered release is current, create the next semver tag from green `main`; otherwise follow the repo's current documented release command. +3. Verify the release asset or module tag contains `wfctl infra derive`, the strict requirement proto, and `modules[].satisfies`. +4. Start observability/provider PRs only after that Workflow tag exists, then bump each plugin's minimum Workflow version to the new tag before release. +5. Release the observability plugin first, then provider mapper plugins as they go green. +6. Search owned application repos for custom `/metrics` reliance: -Commit separately per repo: +```sh +rg -n '(/metrics|promhttp|prometheus|metrics endpoint|ListenAndServe.*metrics)' /Users/jon/workspace -g'*.go' -g'*.yaml' -g'*.yml' +``` + +7. For each owned application found, create a separate app-repo PR that removes the custom `/metrics` dependency and uses the released observability plugin plus `wfctl infra derive`. Do not commit app-specific names into generic plugins. +8. Smoke test a representative app after provider mapper release: ```sh -git add go.mod go.sum plugin.json README.md -git commit -m "chore: require workflow " +wfctl infra derive --config /tmp/workflow-observability.yaml --provider digitalocean --runtime do-app-platform --write --non-interactive +wfctl validate --config /tmp/workflow-observability.yaml ``` +Expected: derive exits 0, YAML includes generated modules with `satisfies`, and `wfctl validate` exits 0. + +Rollback: if Workflow release smoke fails before plugin PRs merge, do not release plugin tags. If a plugin release fails, keep consumers pinned to the previous plugin release and fix forward with a patch tag. If an app migration fails, revert only that app PR. + ## Final Verification Matrix Run after all PRs in a repo are ready: From f2cc3763b4fc35d3a864a8d7e03a49a7e81d1cf1 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 00:14:47 -0400 Subject: [PATCH 07/15] docs: scope discovery request payload --- .../2026-05-25-iac-derived-requirements.md | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/docs/plans/2026-05-25-iac-derived-requirements.md b/docs/plans/2026-05-25-iac-derived-requirements.md index a0f9e31a..066b1534 100644 --- a/docs/plans/2026-05-25-iac-derived-requirements.md +++ b/docs/plans/2026-05-25-iac-derived-requirements.md @@ -167,9 +167,21 @@ message IaCRequirement { } message DiscoverRequirementsRequest { - string environment = 1; - bytes workflow_config_json = 2; - bytes module_config_json = 3; + RequirementContext context = 1; + bytes module_config_json = 2; +} + +message RequirementContext { + string application = 1; + string environment = 2; + repeated ModuleRef modules = 3; + repeated string plugin_ids = 4; +} + +message ModuleRef { + string name = 1; + string type = 2; + repeated string satisfies = 3; } message DiscoverRequirementsResponse { @@ -219,7 +231,7 @@ service IaCProviderRequirementMapper { } ``` -If implementation exposes a shortcoming in this schema, first try to model it as a new enum/message field. Use `parameters_json`, `workflow_config_json`, `module_config_json`, or `config_json` only with an inline proto comment and a plan note explaining why strict modeling was not practical. These JSON byte fields are for already-declared Workflow/provider config payloads, not arbitrary cross-plugin schema. +If implementation exposes a shortcoming in this schema, first try to model it as a new enum/message field. Use `parameters_json`, `module_config_json`, or `config_json` only with an inline proto comment and a plan note explaining why strict modeling was not practical. These JSON byte fields are for already-declared plugin/provider config payloads, not arbitrary cross-plugin schema. Do not send the full Workflow YAML or resolved secret values to external discovery plugins. **Step 4: Regenerate protobufs** From 1b6d195abc7c43edb340a0bf8589443dc1dbb26b Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 00:15:23 -0400 Subject: [PATCH 08/15] docs: pass iac derivation plan review --- ...rived-requirements.adversarial-review-2.md | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 docs/plans/2026-05-25-iac-derived-requirements.adversarial-review-2.md diff --git a/docs/plans/2026-05-25-iac-derived-requirements.adversarial-review-2.md b/docs/plans/2026-05-25-iac-derived-requirements.adversarial-review-2.md new file mode 100644 index 00000000..3829d0dc --- /dev/null +++ b/docs/plans/2026-05-25-iac-derived-requirements.adversarial-review-2.md @@ -0,0 +1,37 @@ +### Adversarial Review Report + +**Phase:** plan +**Artifact:** `docs/plans/2026-05-25-iac-derived-requirements.md` +**Status:** PASS + +**Findings (Critical):** +- None. + +**Findings (Important):** +- None. + +**Findings (Minor):** +- [rollback story] `docs/plans/2026-05-25-iac-derived-requirements.md:989-1014`: Release and app migration steps are operational gates outside the scope manifest. That is acceptable because they are not `### Task` items and each app migration is explicitly a separate app-repo PR, but execution must not treat them as part of the eight locked implementation PRs. + +**Bug-class scan transcript:** + +| Class | Result | Note | +|---|---|---| +| Unstated assumptions | Clean | Provider plugin work is now split by repository, and the release dependency is explicit. | +| Repo-precedent conflicts | Clean | Proto generation uses the repo's documented `buf generate` path, and CLI/editor test commands match local conventions. | +| YAGNI violations | Clean | The plan keeps derivation explicit, does not add apply-time magic, and avoids policy-engine scope. | +| Missing failure modes | Clean | Provider ambiguity, unsupported runtimes, duplicate generation, malformed mapper output, and partial release failure all have test or rollback coverage. | +| Security / privacy at architecture level | Clean | Discovery requests use typed redacted context plus module-owned config bytes and explicitly forbid full Workflow YAML or resolved secrets. | +| Rollback story | Clean | Each runtime/plugin-loading task has a rollback note; release/app migration rollback is covered separately. | +| Simpler alternative not considered | Clean | Manifest-only and apply-time derivation were considered in the design and remain rejected for stated reasons. | +| User-intent drift | Clean | Strict proto, selectable providers/backends, no generic plugin app names, and external plugin requirement discovery are represented. | +| Over-decomposition / under-decomposition | Clean | Workflow, editor, observability, and each provider plugin now have separate reviewable PR slices. | +| Verification-class mismatch | Clean | Workflow CLI verification uses a fake mapper fixture; provider-backed smoke is delayed until provider mapper releases. | +| Hidden serial dependencies | Clean | Workflow release is called out as a gate before observability/provider min-version bumps. | +| Missing rollback wiring | Clean | Provider and plugin rollbacks are per-repo; app migrations are separate PRs with per-app revert. | + +**Options the author may not have considered:** +1. Ship only Workflow core plus DigitalOcean initially, leaving AWS/GCP/Azure mapper tasks queued. This would reduce first-wave effort but would contradict the user's request that the shape not be DO-limited. +2. Put provider conformance fixtures in Workflow core as golden JSON contracts shared by plugin repos. This could reduce duplicated tests later, but it adds cross-repo fixture versioning now; per-provider local tests are simpler for the first implementation. + +**Verdict reasoning:** The revision resolves the execution blockers from cycle 1. The scope manifest now matches real repository boundaries, strict proto includes both mapping and config-aware discovery services, the discovery payload is not over-broad, and the Workflow CLI can be verified without depending on unreleased provider plugins. Remaining release and app-migration work is explicitly operational and separated from the locked PR tasks. From 70bfaeb606b1c8ed618d151d9c19a046676e6a01 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 00:16:35 -0400 Subject: [PATCH 09/15] docs: align iac derivation plan --- ...-derived-requirements.alignment-check-1.md | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 docs/plans/2026-05-25-iac-derived-requirements.alignment-check-1.md diff --git a/docs/plans/2026-05-25-iac-derived-requirements.alignment-check-1.md b/docs/plans/2026-05-25-iac-derived-requirements.alignment-check-1.md new file mode 100644 index 00000000..52750ffa --- /dev/null +++ b/docs/plans/2026-05-25-iac-derived-requirements.alignment-check-1.md @@ -0,0 +1,59 @@ +### Alignment Report + +**Status:** PASS + +**Coverage:** + +| Design Requirement | Plan Task(s) | Status | +|---|---|---| +| Provider-neutral requirements for observability, web/API, brokers, databases, caches, and storage | Task 1, Task 2, Task 3 | Covered | +| `wfctl infra derive` calculates missing requirements and writes expanded YAML before plan/apply | Task 4, Task 5, Task 6 | Covered | +| Deterministic explicit overrides through `modules[].satisfies` | Task 2, Task 4, Task 5, Task 6, Task 7 | Covered | +| Strict-proto provider mapping surface for provider plugins | Task 1, Task 5, Task 9, Task 10, Task 11, Task 12 | Covered | +| Support OTel first, plus Prometheus, Loki, Grafana, and Datadog without Workflow core provider logic | Task 8, Task 9, Task 10, Task 11, Task 12 | Covered | +| Generate concrete `infra.*` modules and leave provisioning to existing IaC pipeline | Task 4, Task 5, Task 6 | Covered | +| No apply-time derivation | Task 6 and out-of-scope manifest | Covered | +| No heuristic existing-resource matching; only `satisfies` keys count | Task 2, Task 4, Task 5, Task 6 | Covered | +| Do not make Workflow core own provider mapping rules | Task 9, Task 10, Task 11, Task 12 | Covered | +| Do not commit app-specific names such as `cms_*` or `multisite_*` to generic plugins | Task 8 and release/migration sequence | Covered | +| Typed requirement fields, enums, vendor extension strings, and JSON bytes only for justified payload exceptions | Task 1, Task 2 | Covered | +| Config-aware requirement discovery through Go interface plus optional strict-proto external-plugin service | Task 1, Task 3, Task 8 | Covered | +| Provider/runtime precedence and non-interactive ambiguity diagnostics | Task 5, Task 6 | Covered | +| Multi-file v1 behavior mutates only the root `--config` file | Task 6 | Covered | +| Observability mapping preferences for OTel, Prometheus, Loki, Grafana, and Datadog | Task 8, Task 9, Task 10, Task 11, Task 12 | Covered | +| Secret placeholders only; reject plaintext secret-looking generated config | Task 5, Task 8, Task 9, Task 10, Task 11, Task 12 | Covered | +| YAML mutation via `gopkg.in/yaml.v3`, preserving order/comments/unknown keys where possible | Task 4, Task 6 | Covered | +| workflow-editor preserves `modules[].satisfies` | Task 7 | Covered | +| Do not implement derivation as a CLI plugin; use IaC provider plugins for mapping | Task 5, Task 6, Task 9, Task 10, Task 11, Task 12 | Covered | +| Backwards compatibility: existing configs/plugins still work and v1 manifest remains valid | Task 2, Task 3, Task 6 | Covered | +| Rollback paths for CLI, proto/service, YAML field, and provider mapper changes | Per-task rollback notes and release/migration sequence | Covered | + +**Scope Check:** + +| Plan Task | Design Requirement | Status | +|---|---|---| +| Task 1 | Strict-proto requirement/discovery/mapping services and contract registry | Justified | +| Task 2 | Local model, `satisfies`, manifest v2, backwards-compatible manifest parsing | Justified | +| Task 3 | Built-in, manifest, Go-interface, and external-plugin requirement discovery | Justified | +| Task 4 | Safe YAML node mutation and idempotent generated module insertion | Justified | +| Task 5 | Derivation engine, provider/runtime resolution, mapper diagnostics, secret rejection | Justified | +| Task 6 | `wfctl infra derive` CLI behavior, dry-run/write semantics, multi-file root mutation | Justified | +| Task 7 | workflow-editor preservation for `satisfies` | Justified | +| Task 8 | Observability plugin generic requirement emission and backend support | Justified | +| Task 9 | DigitalOcean provider-owned mapping | Justified | +| Task 10 | AWS provider-owned mapping | Justified | +| Task 11 | GCP provider-owned mapping | Justified | +| Task 12 | Azure provider-owned mapping | Justified | + +**Manifest Trace:** + +| Check | Status | +|---|---| +| `## Scope Manifest` exists | PASS | +| PR count matches PR grouping rows | PASS: 8 rows for `PR Count: 8` | +| Task count matches `### Task N` headings | PASS: 12 headings for `Tasks: 12` | +| Every PR row references existing task IDs | PASS | +| Every task appears in exactly one PR row | PASS | +| `tests/plan-scope-check.sh --plan ...` | Not present in this repository; manifest checked manually using the same invariants | + +**Drift Items:** None. From 8cc54c5cba418769e137f6951298da7a1d1ce90a Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 00:17:04 -0400 Subject: [PATCH 10/15] chore: lock scope for iac derived requirements --- docs/plans/2026-05-25-iac-derived-requirements.md | 2 +- docs/plans/2026-05-25-iac-derived-requirements.md.scope-lock | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 docs/plans/2026-05-25-iac-derived-requirements.md.scope-lock diff --git a/docs/plans/2026-05-25-iac-derived-requirements.md b/docs/plans/2026-05-25-iac-derived-requirements.md index 066b1534..2a98b316 100644 --- a/docs/plans/2026-05-25-iac-derived-requirements.md +++ b/docs/plans/2026-05-25-iac-derived-requirements.md @@ -38,7 +38,7 @@ | 7 | Map derived requirements in workflow-plugin-gcp | Task 11 | `feat/iac-requirement-mapper` | | 8 | Map derived requirements in workflow-plugin-azure | Task 12 | `feat/iac-requirement-mapper` | -**Status:** Draft +**Status:** Locked 2026-05-25T04:16:44Z ## Design Inputs diff --git a/docs/plans/2026-05-25-iac-derived-requirements.md.scope-lock b/docs/plans/2026-05-25-iac-derived-requirements.md.scope-lock new file mode 100644 index 00000000..e4c47917 --- /dev/null +++ b/docs/plans/2026-05-25-iac-derived-requirements.md.scope-lock @@ -0,0 +1 @@ +6e7289cee903e2a2b4881a4ea26e2040d1cf450ae9a053997d14f9eb8a95a742 From 0c4c23c712ec32f0246794c84e25b6824e28d9ae Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 00:20:39 -0400 Subject: [PATCH 11/15] feat: add iac requirement mapper protocol --- plugin/external/proto/iac.pb.go | 2194 ++++++++++++++++----- plugin/external/proto/iac.proto | 148 +- plugin/external/proto/iac_grpc.pb.go | 230 +++ plugin/external/sdk/contracts_iac_test.go | 46 + plugin/external/sdk/iacserver.go | 8 + plugin/external/sdk/iacserver_test.go | 36 + 6 files changed, 2115 insertions(+), 547 deletions(-) diff --git a/plugin/external/proto/iac.pb.go b/plugin/external/proto/iac.pb.go index 944a2bec..1058cbd3 100644 --- a/plugin/external/proto/iac.pb.go +++ b/plugin/external/proto/iac.pb.go @@ -101,6 +101,296 @@ func (DriftClass) EnumDescriptor() ([]byte, []int) { return file_iac_proto_rawDescGZIP(), []int{0} } +// RequirementKind is the provider-neutral infrastructure category that wfctl +// and provider plugins exchange for derived IaC. Values are intentionally +// portable and provider-agnostic. +type RequirementKind int32 + +const ( + RequirementKind_REQUIREMENT_KIND_UNSPECIFIED RequirementKind = 0 + RequirementKind_REQUIREMENT_KIND_OBSERVABILITY RequirementKind = 1 + RequirementKind_REQUIREMENT_KIND_WEB_API RequirementKind = 2 + RequirementKind_REQUIREMENT_KIND_MESSAGE_BROKER RequirementKind = 3 + RequirementKind_REQUIREMENT_KIND_DATABASE RequirementKind = 4 + RequirementKind_REQUIREMENT_KIND_CACHE RequirementKind = 5 + RequirementKind_REQUIREMENT_KIND_STORAGE RequirementKind = 6 +) + +// Enum value maps for RequirementKind. +var ( + RequirementKind_name = map[int32]string{ + 0: "REQUIREMENT_KIND_UNSPECIFIED", + 1: "REQUIREMENT_KIND_OBSERVABILITY", + 2: "REQUIREMENT_KIND_WEB_API", + 3: "REQUIREMENT_KIND_MESSAGE_BROKER", + 4: "REQUIREMENT_KIND_DATABASE", + 5: "REQUIREMENT_KIND_CACHE", + 6: "REQUIREMENT_KIND_STORAGE", + } + RequirementKind_value = map[string]int32{ + "REQUIREMENT_KIND_UNSPECIFIED": 0, + "REQUIREMENT_KIND_OBSERVABILITY": 1, + "REQUIREMENT_KIND_WEB_API": 2, + "REQUIREMENT_KIND_MESSAGE_BROKER": 3, + "REQUIREMENT_KIND_DATABASE": 4, + "REQUIREMENT_KIND_CACHE": 5, + "REQUIREMENT_KIND_STORAGE": 6, + } +) + +func (x RequirementKind) Enum() *RequirementKind { + p := new(RequirementKind) + *p = x + return p +} + +func (x RequirementKind) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RequirementKind) Descriptor() protoreflect.EnumDescriptor { + return file_iac_proto_enumTypes[1].Descriptor() +} + +func (RequirementKind) Type() protoreflect.EnumType { + return &file_iac_proto_enumTypes[1] +} + +func (x RequirementKind) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RequirementKind.Descriptor instead. +func (RequirementKind) EnumDescriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{1} +} + +// RequirementRuntime describes the target runtime shape the provider mapper +// should generate for. Provider plugins return diagnostics for unsupported +// runtime/mode combinations instead of emitting malformed modules. +type RequirementRuntime int32 + +const ( + RequirementRuntime_REQUIREMENT_RUNTIME_UNSPECIFIED RequirementRuntime = 0 + RequirementRuntime_REQUIREMENT_RUNTIME_KUBERNETES RequirementRuntime = 1 + RequirementRuntime_REQUIREMENT_RUNTIME_ECS RequirementRuntime = 2 + RequirementRuntime_REQUIREMENT_RUNTIME_CLOUD_RUN RequirementRuntime = 3 + RequirementRuntime_REQUIREMENT_RUNTIME_AZURE_CONTAINER_APPS RequirementRuntime = 4 + RequirementRuntime_REQUIREMENT_RUNTIME_DIGITALOCEAN_APP_PLATFORM RequirementRuntime = 5 +) + +// Enum value maps for RequirementRuntime. +var ( + RequirementRuntime_name = map[int32]string{ + 0: "REQUIREMENT_RUNTIME_UNSPECIFIED", + 1: "REQUIREMENT_RUNTIME_KUBERNETES", + 2: "REQUIREMENT_RUNTIME_ECS", + 3: "REQUIREMENT_RUNTIME_CLOUD_RUN", + 4: "REQUIREMENT_RUNTIME_AZURE_CONTAINER_APPS", + 5: "REQUIREMENT_RUNTIME_DIGITALOCEAN_APP_PLATFORM", + } + RequirementRuntime_value = map[string]int32{ + "REQUIREMENT_RUNTIME_UNSPECIFIED": 0, + "REQUIREMENT_RUNTIME_KUBERNETES": 1, + "REQUIREMENT_RUNTIME_ECS": 2, + "REQUIREMENT_RUNTIME_CLOUD_RUN": 3, + "REQUIREMENT_RUNTIME_AZURE_CONTAINER_APPS": 4, + "REQUIREMENT_RUNTIME_DIGITALOCEAN_APP_PLATFORM": 5, + } +) + +func (x RequirementRuntime) Enum() *RequirementRuntime { + p := new(RequirementRuntime) + *p = x + return p +} + +func (x RequirementRuntime) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RequirementRuntime) Descriptor() protoreflect.EnumDescriptor { + return file_iac_proto_enumTypes[2].Descriptor() +} + +func (RequirementRuntime) Type() protoreflect.EnumType { + return &file_iac_proto_enumTypes[2] +} + +func (x RequirementRuntime) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RequirementRuntime.Descriptor instead. +func (RequirementRuntime) EnumDescriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{2} +} + +type TelemetrySignal int32 + +const ( + TelemetrySignal_TELEMETRY_SIGNAL_UNSPECIFIED TelemetrySignal = 0 + TelemetrySignal_TELEMETRY_SIGNAL_TRACES TelemetrySignal = 1 + TelemetrySignal_TELEMETRY_SIGNAL_METRICS TelemetrySignal = 2 + TelemetrySignal_TELEMETRY_SIGNAL_LOGS TelemetrySignal = 3 +) + +// Enum value maps for TelemetrySignal. +var ( + TelemetrySignal_name = map[int32]string{ + 0: "TELEMETRY_SIGNAL_UNSPECIFIED", + 1: "TELEMETRY_SIGNAL_TRACES", + 2: "TELEMETRY_SIGNAL_METRICS", + 3: "TELEMETRY_SIGNAL_LOGS", + } + TelemetrySignal_value = map[string]int32{ + "TELEMETRY_SIGNAL_UNSPECIFIED": 0, + "TELEMETRY_SIGNAL_TRACES": 1, + "TELEMETRY_SIGNAL_METRICS": 2, + "TELEMETRY_SIGNAL_LOGS": 3, + } +) + +func (x TelemetrySignal) Enum() *TelemetrySignal { + p := new(TelemetrySignal) + *p = x + return p +} + +func (x TelemetrySignal) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (TelemetrySignal) Descriptor() protoreflect.EnumDescriptor { + return file_iac_proto_enumTypes[3].Descriptor() +} + +func (TelemetrySignal) Type() protoreflect.EnumType { + return &file_iac_proto_enumTypes[3] +} + +func (x TelemetrySignal) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use TelemetrySignal.Descriptor instead. +func (TelemetrySignal) EnumDescriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{3} +} + +type ObservabilityBackend int32 + +const ( + ObservabilityBackend_OBSERVABILITY_BACKEND_UNSPECIFIED ObservabilityBackend = 0 + ObservabilityBackend_OBSERVABILITY_BACKEND_OTEL ObservabilityBackend = 1 + ObservabilityBackend_OBSERVABILITY_BACKEND_DATADOG ObservabilityBackend = 2 + ObservabilityBackend_OBSERVABILITY_BACKEND_PROMETHEUS ObservabilityBackend = 3 + ObservabilityBackend_OBSERVABILITY_BACKEND_LOKI ObservabilityBackend = 4 + ObservabilityBackend_OBSERVABILITY_BACKEND_GRAFANA ObservabilityBackend = 5 +) + +// Enum value maps for ObservabilityBackend. +var ( + ObservabilityBackend_name = map[int32]string{ + 0: "OBSERVABILITY_BACKEND_UNSPECIFIED", + 1: "OBSERVABILITY_BACKEND_OTEL", + 2: "OBSERVABILITY_BACKEND_DATADOG", + 3: "OBSERVABILITY_BACKEND_PROMETHEUS", + 4: "OBSERVABILITY_BACKEND_LOKI", + 5: "OBSERVABILITY_BACKEND_GRAFANA", + } + ObservabilityBackend_value = map[string]int32{ + "OBSERVABILITY_BACKEND_UNSPECIFIED": 0, + "OBSERVABILITY_BACKEND_OTEL": 1, + "OBSERVABILITY_BACKEND_DATADOG": 2, + "OBSERVABILITY_BACKEND_PROMETHEUS": 3, + "OBSERVABILITY_BACKEND_LOKI": 4, + "OBSERVABILITY_BACKEND_GRAFANA": 5, + } +) + +func (x ObservabilityBackend) Enum() *ObservabilityBackend { + p := new(ObservabilityBackend) + *p = x + return p +} + +func (x ObservabilityBackend) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ObservabilityBackend) Descriptor() protoreflect.EnumDescriptor { + return file_iac_proto_enumTypes[4].Descriptor() +} + +func (ObservabilityBackend) Type() protoreflect.EnumType { + return &file_iac_proto_enumTypes[4] +} + +func (x ObservabilityBackend) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ObservabilityBackend.Descriptor instead. +func (ObservabilityBackend) EnumDescriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{4} +} + +type DeploymentMode int32 + +const ( + DeploymentMode_DEPLOYMENT_MODE_UNSPECIFIED DeploymentMode = 0 + DeploymentMode_DEPLOYMENT_MODE_SIDECAR DeploymentMode = 1 + DeploymentMode_DEPLOYMENT_MODE_DAEMONSET DeploymentMode = 2 + DeploymentMode_DEPLOYMENT_MODE_SIBLING_SERVICE DeploymentMode = 3 + DeploymentMode_DEPLOYMENT_MODE_MANAGED DeploymentMode = 4 +) + +// Enum value maps for DeploymentMode. +var ( + DeploymentMode_name = map[int32]string{ + 0: "DEPLOYMENT_MODE_UNSPECIFIED", + 1: "DEPLOYMENT_MODE_SIDECAR", + 2: "DEPLOYMENT_MODE_DAEMONSET", + 3: "DEPLOYMENT_MODE_SIBLING_SERVICE", + 4: "DEPLOYMENT_MODE_MANAGED", + } + DeploymentMode_value = map[string]int32{ + "DEPLOYMENT_MODE_UNSPECIFIED": 0, + "DEPLOYMENT_MODE_SIDECAR": 1, + "DEPLOYMENT_MODE_DAEMONSET": 2, + "DEPLOYMENT_MODE_SIBLING_SERVICE": 3, + "DEPLOYMENT_MODE_MANAGED": 4, + } +) + +func (x DeploymentMode) Enum() *DeploymentMode { + p := new(DeploymentMode) + *p = x + return p +} + +func (x DeploymentMode) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DeploymentMode) Descriptor() protoreflect.EnumDescriptor { + return file_iac_proto_enumTypes[5].Descriptor() +} + +func (DeploymentMode) Type() protoreflect.EnumType { + return &file_iac_proto_enumTypes[5] +} + +func (x DeploymentMode) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DeploymentMode.Descriptor instead. +func (DeploymentMode) EnumDescriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{5} +} + // PlanDiagnosticSeverity mirrors interfaces.PlanDiagnosticSeverity. // Wire ordering matches the Go iota: INFO=0, WARNING=1, ERROR=2. type PlanDiagnosticSeverity int32 @@ -136,11 +426,11 @@ func (x PlanDiagnosticSeverity) String() string { } func (PlanDiagnosticSeverity) Descriptor() protoreflect.EnumDescriptor { - return file_iac_proto_enumTypes[1].Descriptor() + return file_iac_proto_enumTypes[6].Descriptor() } func (PlanDiagnosticSeverity) Type() protoreflect.EnumType { - return &file_iac_proto_enumTypes[1] + return &file_iac_proto_enumTypes[6] } func (x PlanDiagnosticSeverity) Number() protoreflect.EnumNumber { @@ -149,7 +439,7 @@ func (x PlanDiagnosticSeverity) Number() protoreflect.EnumNumber { // Deprecated: Use PlanDiagnosticSeverity.Descriptor instead. func (PlanDiagnosticSeverity) EnumDescriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{1} + return file_iac_proto_rawDescGZIP(), []int{6} } // ActionStatus categorizes per-action outcomes for wfctl-side hook dispatch. @@ -204,11 +494,11 @@ func (x ActionStatus) String() string { } func (ActionStatus) Descriptor() protoreflect.EnumDescriptor { - return file_iac_proto_enumTypes[2].Descriptor() + return file_iac_proto_enumTypes[7].Descriptor() } func (ActionStatus) Type() protoreflect.EnumType { - return &file_iac_proto_enumTypes[2] + return &file_iac_proto_enumTypes[7] } func (x ActionStatus) Number() protoreflect.EnumNumber { @@ -217,7 +507,7 @@ func (x ActionStatus) Number() protoreflect.EnumNumber { // Deprecated: Use ActionStatus.Descriptor instead. func (ActionStatus) EnumDescriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{2} + return file_iac_proto_rawDescGZIP(), []int{7} } // ───────────────────────────────────────────────────────────────────────────── @@ -262,11 +552,11 @@ func (x LogCaptureType) String() string { } func (LogCaptureType) Descriptor() protoreflect.EnumDescriptor { - return file_iac_proto_enumTypes[3].Descriptor() + return file_iac_proto_enumTypes[8].Descriptor() } func (LogCaptureType) Type() protoreflect.EnumType { - return &file_iac_proto_enumTypes[3] + return &file_iac_proto_enumTypes[8] } func (x LogCaptureType) Number() protoreflect.EnumNumber { @@ -275,7 +565,7 @@ func (x LogCaptureType) Number() protoreflect.EnumNumber { // Deprecated: Use LogCaptureType.Descriptor instead. func (LogCaptureType) EnumDescriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{3} + return file_iac_proto_rawDescGZIP(), []int{8} } // ResourceSpec mirrors interfaces.ResourceSpec. @@ -1026,28 +1316,717 @@ func (x *DiffResult) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use DiffResult.ProtoReflect.Descriptor instead. -func (*DiffResult) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{9} +// Deprecated: Use DiffResult.ProtoReflect.Descriptor instead. +func (*DiffResult) Descriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{9} +} + +func (x *DiffResult) GetNeedsUpdate() bool { + if x != nil { + return x.NeedsUpdate + } + return false +} + +func (x *DiffResult) GetNeedsReplace() bool { + if x != nil { + return x.NeedsReplace + } + return false +} + +func (x *DiffResult) GetChanges() []*FieldChange { + if x != nil { + return x.Changes + } + return nil +} + +type IaCRequirement struct { + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Kind RequirementKind `protobuf:"varint,2,opt,name=kind,proto3,enum=workflow.plugin.external.iac.RequirementKind" json:"kind,omitempty"` + Source string `protobuf:"bytes,3,opt,name=source,proto3" json:"source,omitempty"` + ResourceTypeHint string `protobuf:"bytes,4,opt,name=resource_type_hint,json=resourceTypeHint,proto3" json:"resource_type_hint,omitempty"` + Environment string `protobuf:"bytes,5,opt,name=environment,proto3" json:"environment,omitempty"` + Runtimes []RequirementRuntime `protobuf:"varint,6,rep,packed,name=runtimes,proto3,enum=workflow.plugin.external.iac.RequirementRuntime" json:"runtimes,omitempty"` + TelemetrySignals []TelemetrySignal `protobuf:"varint,7,rep,packed,name=telemetry_signals,json=telemetrySignals,proto3,enum=workflow.plugin.external.iac.TelemetrySignal" json:"telemetry_signals,omitempty"` + ObservabilityBackends []ObservabilityBackend `protobuf:"varint,8,rep,packed,name=observability_backends,json=observabilityBackends,proto3,enum=workflow.plugin.external.iac.ObservabilityBackend" json:"observability_backends,omitempty"` + DeploymentModes []DeploymentMode `protobuf:"varint,9,rep,packed,name=deployment_modes,json=deploymentModes,proto3,enum=workflow.plugin.external.iac.DeploymentMode" json:"deployment_modes,omitempty"` + VendorFeatures []string `protobuf:"bytes,10,rep,name=vendor_features,json=vendorFeatures,proto3" json:"vendor_features,omitempty"` + // parameters_json is JSON-encoded plugin-owned requirement detail for data + // that is not portable enough to promote to a Workflow-owned proto field. + // Prefer adding enum/message fields for portable concepts. + ParametersJson []byte `protobuf:"bytes,11,opt,name=parameters_json,json=parametersJson,proto3" json:"parameters_json,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *IaCRequirement) Reset() { + *x = IaCRequirement{} + mi := &file_iac_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *IaCRequirement) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IaCRequirement) ProtoMessage() {} + +func (x *IaCRequirement) ProtoReflect() protoreflect.Message { + mi := &file_iac_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IaCRequirement.ProtoReflect.Descriptor instead. +func (*IaCRequirement) Descriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{10} +} + +func (x *IaCRequirement) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *IaCRequirement) GetKind() RequirementKind { + if x != nil { + return x.Kind + } + return RequirementKind_REQUIREMENT_KIND_UNSPECIFIED +} + +func (x *IaCRequirement) GetSource() string { + if x != nil { + return x.Source + } + return "" +} + +func (x *IaCRequirement) GetResourceTypeHint() string { + if x != nil { + return x.ResourceTypeHint + } + return "" +} + +func (x *IaCRequirement) GetEnvironment() string { + if x != nil { + return x.Environment + } + return "" +} + +func (x *IaCRequirement) GetRuntimes() []RequirementRuntime { + if x != nil { + return x.Runtimes + } + return nil +} + +func (x *IaCRequirement) GetTelemetrySignals() []TelemetrySignal { + if x != nil { + return x.TelemetrySignals + } + return nil +} + +func (x *IaCRequirement) GetObservabilityBackends() []ObservabilityBackend { + if x != nil { + return x.ObservabilityBackends + } + return nil +} + +func (x *IaCRequirement) GetDeploymentModes() []DeploymentMode { + if x != nil { + return x.DeploymentModes + } + return nil +} + +func (x *IaCRequirement) GetVendorFeatures() []string { + if x != nil { + return x.VendorFeatures + } + return nil +} + +func (x *IaCRequirement) GetParametersJson() []byte { + if x != nil { + return x.ParametersJson + } + return nil +} + +type DiscoverRequirementsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Context *RequirementContext `protobuf:"bytes,1,opt,name=context,proto3" json:"context,omitempty"` + // module_config_json is JSON-encoded module config owned by the plugin that + // implements IaCRequirementDiscovery. Hosts must not send full Workflow YAML + // or resolved secret values here. + ModuleConfigJson []byte `protobuf:"bytes,2,opt,name=module_config_json,json=moduleConfigJson,proto3" json:"module_config_json,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DiscoverRequirementsRequest) Reset() { + *x = DiscoverRequirementsRequest{} + mi := &file_iac_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DiscoverRequirementsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DiscoverRequirementsRequest) ProtoMessage() {} + +func (x *DiscoverRequirementsRequest) ProtoReflect() protoreflect.Message { + mi := &file_iac_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DiscoverRequirementsRequest.ProtoReflect.Descriptor instead. +func (*DiscoverRequirementsRequest) Descriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{11} +} + +func (x *DiscoverRequirementsRequest) GetContext() *RequirementContext { + if x != nil { + return x.Context + } + return nil +} + +func (x *DiscoverRequirementsRequest) GetModuleConfigJson() []byte { + if x != nil { + return x.ModuleConfigJson + } + return nil +} + +type RequirementContext struct { + state protoimpl.MessageState `protogen:"open.v1"` + Application string `protobuf:"bytes,1,opt,name=application,proto3" json:"application,omitempty"` + Environment string `protobuf:"bytes,2,opt,name=environment,proto3" json:"environment,omitempty"` + Modules []*ModuleRef `protobuf:"bytes,3,rep,name=modules,proto3" json:"modules,omitempty"` + PluginIds []string `protobuf:"bytes,4,rep,name=plugin_ids,json=pluginIds,proto3" json:"plugin_ids,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RequirementContext) Reset() { + *x = RequirementContext{} + mi := &file_iac_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RequirementContext) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequirementContext) ProtoMessage() {} + +func (x *RequirementContext) ProtoReflect() protoreflect.Message { + mi := &file_iac_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequirementContext.ProtoReflect.Descriptor instead. +func (*RequirementContext) Descriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{12} +} + +func (x *RequirementContext) GetApplication() string { + if x != nil { + return x.Application + } + return "" +} + +func (x *RequirementContext) GetEnvironment() string { + if x != nil { + return x.Environment + } + return "" +} + +func (x *RequirementContext) GetModules() []*ModuleRef { + if x != nil { + return x.Modules + } + return nil +} + +func (x *RequirementContext) GetPluginIds() []string { + if x != nil { + return x.PluginIds + } + return nil +} + +type ModuleRef struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` + Satisfies []string `protobuf:"bytes,3,rep,name=satisfies,proto3" json:"satisfies,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ModuleRef) Reset() { + *x = ModuleRef{} + mi := &file_iac_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ModuleRef) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ModuleRef) ProtoMessage() {} + +func (x *ModuleRef) ProtoReflect() protoreflect.Message { + mi := &file_iac_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ModuleRef.ProtoReflect.Descriptor instead. +func (*ModuleRef) Descriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{13} +} + +func (x *ModuleRef) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ModuleRef) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *ModuleRef) GetSatisfies() []string { + if x != nil { + return x.Satisfies + } + return nil +} + +type DiscoverRequirementsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Requirements []*IaCRequirement `protobuf:"bytes,1,rep,name=requirements,proto3" json:"requirements,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DiscoverRequirementsResponse) Reset() { + *x = DiscoverRequirementsResponse{} + mi := &file_iac_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DiscoverRequirementsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DiscoverRequirementsResponse) ProtoMessage() {} + +func (x *DiscoverRequirementsResponse) ProtoReflect() protoreflect.Message { + mi := &file_iac_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DiscoverRequirementsResponse.ProtoReflect.Descriptor instead. +func (*DiscoverRequirementsResponse) Descriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{14} +} + +func (x *DiscoverRequirementsResponse) GetRequirements() []*IaCRequirement { + if x != nil { + return x.Requirements + } + return nil +} + +type MapRequirementsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Provider string `protobuf:"bytes,1,opt,name=provider,proto3" json:"provider,omitempty"` + Runtime RequirementRuntime `protobuf:"varint,2,opt,name=runtime,proto3,enum=workflow.plugin.external.iac.RequirementRuntime" json:"runtime,omitempty"` + Environment string `protobuf:"bytes,3,opt,name=environment,proto3" json:"environment,omitempty"` + Requirements []*IaCRequirement `protobuf:"bytes,4,rep,name=requirements,proto3" json:"requirements,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MapRequirementsRequest) Reset() { + *x = MapRequirementsRequest{} + mi := &file_iac_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MapRequirementsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MapRequirementsRequest) ProtoMessage() {} + +func (x *MapRequirementsRequest) ProtoReflect() protoreflect.Message { + mi := &file_iac_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MapRequirementsRequest.ProtoReflect.Descriptor instead. +func (*MapRequirementsRequest) Descriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{15} +} + +func (x *MapRequirementsRequest) GetProvider() string { + if x != nil { + return x.Provider + } + return "" +} + +func (x *MapRequirementsRequest) GetRuntime() RequirementRuntime { + if x != nil { + return x.Runtime + } + return RequirementRuntime_REQUIREMENT_RUNTIME_UNSPECIFIED +} + +func (x *MapRequirementsRequest) GetEnvironment() string { + if x != nil { + return x.Environment + } + return "" +} + +func (x *MapRequirementsRequest) GetRequirements() []*IaCRequirement { + if x != nil { + return x.Requirements + } + return nil +} + +type DerivedModuleSpec struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` + Satisfies []string `protobuf:"bytes,3,rep,name=satisfies,proto3" json:"satisfies,omitempty"` + // config_json is JSON-encoded provider-owned module config. Provider + // mappers must emit secret placeholders/references, never plaintext secret + // values. + ConfigJson []byte `protobuf:"bytes,4,opt,name=config_json,json=configJson,proto3" json:"config_json,omitempty"` + DependsOn []string `protobuf:"bytes,5,rep,name=depends_on,json=dependsOn,proto3" json:"depends_on,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DerivedModuleSpec) Reset() { + *x = DerivedModuleSpec{} + mi := &file_iac_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DerivedModuleSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DerivedModuleSpec) ProtoMessage() {} + +func (x *DerivedModuleSpec) ProtoReflect() protoreflect.Message { + mi := &file_iac_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DerivedModuleSpec.ProtoReflect.Descriptor instead. +func (*DerivedModuleSpec) Descriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{16} +} + +func (x *DerivedModuleSpec) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *DerivedModuleSpec) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *DerivedModuleSpec) GetSatisfies() []string { + if x != nil { + return x.Satisfies + } + return nil +} + +func (x *DerivedModuleSpec) GetConfigJson() []byte { + if x != nil { + return x.ConfigJson + } + return nil +} + +func (x *DerivedModuleSpec) GetDependsOn() []string { + if x != nil { + return x.DependsOn + } + return nil +} + +type RequirementDiagnostic struct { + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"` + Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RequirementDiagnostic) Reset() { + *x = RequirementDiagnostic{} + mi := &file_iac_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RequirementDiagnostic) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequirementDiagnostic) ProtoMessage() {} + +func (x *RequirementDiagnostic) ProtoReflect() protoreflect.Message { + mi := &file_iac_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequirementDiagnostic.ProtoReflect.Descriptor instead. +func (*RequirementDiagnostic) Descriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{17} +} + +func (x *RequirementDiagnostic) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *RequirementDiagnostic) GetCode() string { + if x != nil { + return x.Code + } + return "" +} + +func (x *RequirementDiagnostic) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +type RequirementNote struct { + state protoimpl.MessageState `protogen:"open.v1"` + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` + Interactive bool `protobuf:"varint,3,opt,name=interactive,proto3" json:"interactive,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RequirementNote) Reset() { + *x = RequirementNote{} + mi := &file_iac_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RequirementNote) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RequirementNote) ProtoMessage() {} + +func (x *RequirementNote) ProtoReflect() protoreflect.Message { + mi := &file_iac_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RequirementNote.ProtoReflect.Descriptor instead. +func (*RequirementNote) Descriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{18} +} + +func (x *RequirementNote) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *RequirementNote) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *RequirementNote) GetInteractive() bool { + if x != nil { + return x.Interactive + } + return false +} + +type MapRequirementsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + AcceptedKeys []string `protobuf:"bytes,1,rep,name=accepted_keys,json=acceptedKeys,proto3" json:"accepted_keys,omitempty"` + Rejected []*RequirementDiagnostic `protobuf:"bytes,2,rep,name=rejected,proto3" json:"rejected,omitempty"` + Modules []*DerivedModuleSpec `protobuf:"bytes,3,rep,name=modules,proto3" json:"modules,omitempty"` + Notes []*RequirementNote `protobuf:"bytes,4,rep,name=notes,proto3" json:"notes,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MapRequirementsResponse) Reset() { + *x = MapRequirementsResponse{} + mi := &file_iac_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MapRequirementsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MapRequirementsResponse) ProtoMessage() {} + +func (x *MapRequirementsResponse) ProtoReflect() protoreflect.Message { + mi := &file_iac_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MapRequirementsResponse.ProtoReflect.Descriptor instead. +func (*MapRequirementsResponse) Descriptor() ([]byte, []int) { + return file_iac_proto_rawDescGZIP(), []int{19} +} + +func (x *MapRequirementsResponse) GetAcceptedKeys() []string { + if x != nil { + return x.AcceptedKeys + } + return nil } -func (x *DiffResult) GetNeedsUpdate() bool { +func (x *MapRequirementsResponse) GetRejected() []*RequirementDiagnostic { if x != nil { - return x.NeedsUpdate + return x.Rejected } - return false + return nil } -func (x *DiffResult) GetNeedsReplace() bool { +func (x *MapRequirementsResponse) GetModules() []*DerivedModuleSpec { if x != nil { - return x.NeedsReplace + return x.Modules } - return false + return nil } -func (x *DiffResult) GetChanges() []*FieldChange { +func (x *MapRequirementsResponse) GetNotes() []*RequirementNote { if x != nil { - return x.Changes + return x.Notes } return nil } @@ -1068,7 +2047,7 @@ type DriftResult struct { func (x *DriftResult) Reset() { *x = DriftResult{} - mi := &file_iac_proto_msgTypes[10] + mi := &file_iac_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1080,7 +2059,7 @@ func (x *DriftResult) String() string { func (*DriftResult) ProtoMessage() {} func (x *DriftResult) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[10] + mi := &file_iac_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1093,7 +2072,7 @@ func (x *DriftResult) ProtoReflect() protoreflect.Message { // Deprecated: Use DriftResult.ProtoReflect.Descriptor instead. func (*DriftResult) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{10} + return file_iac_proto_rawDescGZIP(), []int{20} } func (x *DriftResult) GetName() string { @@ -1157,7 +2136,7 @@ type DriftEntry struct { func (x *DriftEntry) Reset() { *x = DriftEntry{} - mi := &file_iac_proto_msgTypes[11] + mi := &file_iac_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1169,7 +2148,7 @@ func (x *DriftEntry) String() string { func (*DriftEntry) ProtoMessage() {} func (x *DriftEntry) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[11] + mi := &file_iac_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1182,7 +2161,7 @@ func (x *DriftEntry) ProtoReflect() protoreflect.Message { // Deprecated: Use DriftEntry.ProtoReflect.Descriptor instead. func (*DriftEntry) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{11} + return file_iac_proto_rawDescGZIP(), []int{21} } func (x *DriftEntry) GetName() string { @@ -1217,7 +2196,7 @@ type HealthResult struct { func (x *HealthResult) Reset() { *x = HealthResult{} - mi := &file_iac_proto_msgTypes[12] + mi := &file_iac_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1229,7 +2208,7 @@ func (x *HealthResult) String() string { func (*HealthResult) ProtoMessage() {} func (x *HealthResult) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[12] + mi := &file_iac_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1242,7 +2221,7 @@ func (x *HealthResult) ProtoReflect() protoreflect.Message { // Deprecated: Use HealthResult.ProtoReflect.Descriptor instead. func (*HealthResult) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{12} + return file_iac_proto_rawDescGZIP(), []int{22} } func (x *HealthResult) GetHealthy() bool { @@ -1273,7 +2252,7 @@ type Diagnostic struct { func (x *Diagnostic) Reset() { *x = Diagnostic{} - mi := &file_iac_proto_msgTypes[13] + mi := &file_iac_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1285,7 +2264,7 @@ func (x *Diagnostic) String() string { func (*Diagnostic) ProtoMessage() {} func (x *Diagnostic) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[13] + mi := &file_iac_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1298,7 +2277,7 @@ func (x *Diagnostic) ProtoReflect() protoreflect.Message { // Deprecated: Use Diagnostic.ProtoReflect.Descriptor instead. func (*Diagnostic) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{13} + return file_iac_proto_rawDescGZIP(), []int{23} } func (x *Diagnostic) GetId() string { @@ -1349,7 +2328,7 @@ type PlanDiagnostic struct { func (x *PlanDiagnostic) Reset() { *x = PlanDiagnostic{} - mi := &file_iac_proto_msgTypes[14] + mi := &file_iac_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1361,7 +2340,7 @@ func (x *PlanDiagnostic) String() string { func (*PlanDiagnostic) ProtoMessage() {} func (x *PlanDiagnostic) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[14] + mi := &file_iac_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1374,7 +2353,7 @@ func (x *PlanDiagnostic) ProtoReflect() protoreflect.Message { // Deprecated: Use PlanDiagnostic.ProtoReflect.Descriptor instead. func (*PlanDiagnostic) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{14} + return file_iac_proto_rawDescGZIP(), []int{24} } func (x *PlanDiagnostic) GetSeverity() PlanDiagnosticSeverity { @@ -1419,7 +2398,7 @@ type PlanAction struct { func (x *PlanAction) Reset() { *x = PlanAction{} - mi := &file_iac_proto_msgTypes[15] + mi := &file_iac_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1431,7 +2410,7 @@ func (x *PlanAction) String() string { func (*PlanAction) ProtoMessage() {} func (x *PlanAction) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[15] + mi := &file_iac_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1444,7 +2423,7 @@ func (x *PlanAction) ProtoReflect() protoreflect.Message { // Deprecated: Use PlanAction.ProtoReflect.Descriptor instead. func (*PlanAction) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{15} + return file_iac_proto_rawDescGZIP(), []int{25} } func (x *PlanAction) GetAction() string { @@ -1497,7 +2476,7 @@ type IaCPlan struct { func (x *IaCPlan) Reset() { *x = IaCPlan{} - mi := &file_iac_proto_msgTypes[16] + mi := &file_iac_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1509,7 +2488,7 @@ func (x *IaCPlan) String() string { func (*IaCPlan) ProtoMessage() {} func (x *IaCPlan) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[16] + mi := &file_iac_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1522,7 +2501,7 @@ func (x *IaCPlan) ProtoReflect() protoreflect.Message { // Deprecated: Use IaCPlan.ProtoReflect.Descriptor instead. func (*IaCPlan) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{16} + return file_iac_proto_rawDescGZIP(), []int{26} } func (x *IaCPlan) GetId() string { @@ -1579,7 +2558,7 @@ type ActionError struct { func (x *ActionError) Reset() { *x = ActionError{} - mi := &file_iac_proto_msgTypes[17] + mi := &file_iac_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1591,7 +2570,7 @@ func (x *ActionError) String() string { func (*ActionError) ProtoMessage() {} func (x *ActionError) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[17] + mi := &file_iac_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1604,7 +2583,7 @@ func (x *ActionError) ProtoReflect() protoreflect.Message { // Deprecated: Use ActionError.ProtoReflect.Descriptor instead. func (*ActionError) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{17} + return file_iac_proto_rawDescGZIP(), []int{27} } func (x *ActionError) GetResource() string { @@ -1639,7 +2618,7 @@ type DestroyResult struct { func (x *DestroyResult) Reset() { *x = DestroyResult{} - mi := &file_iac_proto_msgTypes[18] + mi := &file_iac_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1651,7 +2630,7 @@ func (x *DestroyResult) String() string { func (*DestroyResult) ProtoMessage() {} func (x *DestroyResult) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[18] + mi := &file_iac_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1664,7 +2643,7 @@ func (x *DestroyResult) ProtoReflect() protoreflect.Message { // Deprecated: Use DestroyResult.ProtoReflect.Descriptor instead. func (*DestroyResult) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{18} + return file_iac_proto_rawDescGZIP(), []int{28} } func (x *DestroyResult) GetDestroyed() []string { @@ -1694,7 +2673,7 @@ type BootstrapResult struct { func (x *BootstrapResult) Reset() { *x = BootstrapResult{} - mi := &file_iac_proto_msgTypes[19] + mi := &file_iac_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1706,7 +2685,7 @@ func (x *BootstrapResult) String() string { func (*BootstrapResult) ProtoMessage() {} func (x *BootstrapResult) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[19] + mi := &file_iac_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1719,7 +2698,7 @@ func (x *BootstrapResult) ProtoReflect() protoreflect.Message { // Deprecated: Use BootstrapResult.ProtoReflect.Descriptor instead. func (*BootstrapResult) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{19} + return file_iac_proto_rawDescGZIP(), []int{29} } func (x *BootstrapResult) GetBucket() string { @@ -1772,7 +2751,7 @@ type MigrationRepairRequest struct { func (x *MigrationRepairRequest) Reset() { *x = MigrationRepairRequest{} - mi := &file_iac_proto_msgTypes[20] + mi := &file_iac_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1784,7 +2763,7 @@ func (x *MigrationRepairRequest) String() string { func (*MigrationRepairRequest) ProtoMessage() {} func (x *MigrationRepairRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[20] + mi := &file_iac_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1797,7 +2776,7 @@ func (x *MigrationRepairRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MigrationRepairRequest.ProtoReflect.Descriptor instead. func (*MigrationRepairRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{20} + return file_iac_proto_rawDescGZIP(), []int{30} } func (x *MigrationRepairRequest) GetAppResourceName() string { @@ -1893,7 +2872,7 @@ type MigrationRepairResult struct { func (x *MigrationRepairResult) Reset() { *x = MigrationRepairResult{} - mi := &file_iac_proto_msgTypes[21] + mi := &file_iac_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1905,7 +2884,7 @@ func (x *MigrationRepairResult) String() string { func (*MigrationRepairResult) ProtoMessage() {} func (x *MigrationRepairResult) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[21] + mi := &file_iac_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1918,7 +2897,7 @@ func (x *MigrationRepairResult) ProtoReflect() protoreflect.Message { // Deprecated: Use MigrationRepairResult.ProtoReflect.Descriptor instead. func (*MigrationRepairResult) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{21} + return file_iac_proto_rawDescGZIP(), []int{31} } func (x *MigrationRepairResult) GetProviderJobId() string { @@ -1966,7 +2945,7 @@ type InitializeRequest struct { func (x *InitializeRequest) Reset() { *x = InitializeRequest{} - mi := &file_iac_proto_msgTypes[22] + mi := &file_iac_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1978,7 +2957,7 @@ func (x *InitializeRequest) String() string { func (*InitializeRequest) ProtoMessage() {} func (x *InitializeRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[22] + mi := &file_iac_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1991,7 +2970,7 @@ func (x *InitializeRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use InitializeRequest.ProtoReflect.Descriptor instead. func (*InitializeRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{22} + return file_iac_proto_rawDescGZIP(), []int{32} } func (x *InitializeRequest) GetConfigJson() []byte { @@ -2009,7 +2988,7 @@ type InitializeResponse struct { func (x *InitializeResponse) Reset() { *x = InitializeResponse{} - mi := &file_iac_proto_msgTypes[23] + mi := &file_iac_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2021,7 +3000,7 @@ func (x *InitializeResponse) String() string { func (*InitializeResponse) ProtoMessage() {} func (x *InitializeResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[23] + mi := &file_iac_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2034,7 +3013,7 @@ func (x *InitializeResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use InitializeResponse.ProtoReflect.Descriptor instead. func (*InitializeResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{23} + return file_iac_proto_rawDescGZIP(), []int{33} } type NameRequest struct { @@ -2045,7 +3024,7 @@ type NameRequest struct { func (x *NameRequest) Reset() { *x = NameRequest{} - mi := &file_iac_proto_msgTypes[24] + mi := &file_iac_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2057,7 +3036,7 @@ func (x *NameRequest) String() string { func (*NameRequest) ProtoMessage() {} func (x *NameRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[24] + mi := &file_iac_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2070,7 +3049,7 @@ func (x *NameRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use NameRequest.ProtoReflect.Descriptor instead. func (*NameRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{24} + return file_iac_proto_rawDescGZIP(), []int{34} } type NameResponse struct { @@ -2082,7 +3061,7 @@ type NameResponse struct { func (x *NameResponse) Reset() { *x = NameResponse{} - mi := &file_iac_proto_msgTypes[25] + mi := &file_iac_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2094,7 +3073,7 @@ func (x *NameResponse) String() string { func (*NameResponse) ProtoMessage() {} func (x *NameResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[25] + mi := &file_iac_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2107,7 +3086,7 @@ func (x *NameResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use NameResponse.ProtoReflect.Descriptor instead. func (*NameResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{25} + return file_iac_proto_rawDescGZIP(), []int{35} } func (x *NameResponse) GetName() string { @@ -2125,7 +3104,7 @@ type VersionRequest struct { func (x *VersionRequest) Reset() { *x = VersionRequest{} - mi := &file_iac_proto_msgTypes[26] + mi := &file_iac_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2137,7 +3116,7 @@ func (x *VersionRequest) String() string { func (*VersionRequest) ProtoMessage() {} func (x *VersionRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[26] + mi := &file_iac_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2150,7 +3129,7 @@ func (x *VersionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VersionRequest.ProtoReflect.Descriptor instead. func (*VersionRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{26} + return file_iac_proto_rawDescGZIP(), []int{36} } type VersionResponse struct { @@ -2162,7 +3141,7 @@ type VersionResponse struct { func (x *VersionResponse) Reset() { *x = VersionResponse{} - mi := &file_iac_proto_msgTypes[27] + mi := &file_iac_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2174,7 +3153,7 @@ func (x *VersionResponse) String() string { func (*VersionResponse) ProtoMessage() {} func (x *VersionResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[27] + mi := &file_iac_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2187,7 +3166,7 @@ func (x *VersionResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use VersionResponse.ProtoReflect.Descriptor instead. func (*VersionResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{27} + return file_iac_proto_rawDescGZIP(), []int{37} } func (x *VersionResponse) GetVersion() string { @@ -2205,7 +3184,7 @@ type CapabilitiesRequest struct { func (x *CapabilitiesRequest) Reset() { *x = CapabilitiesRequest{} - mi := &file_iac_proto_msgTypes[28] + mi := &file_iac_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2217,7 +3196,7 @@ func (x *CapabilitiesRequest) String() string { func (*CapabilitiesRequest) ProtoMessage() {} func (x *CapabilitiesRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[28] + mi := &file_iac_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2230,7 +3209,7 @@ func (x *CapabilitiesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CapabilitiesRequest.ProtoReflect.Descriptor instead. func (*CapabilitiesRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{28} + return file_iac_proto_rawDescGZIP(), []int{38} } type CapabilitiesResponse struct { @@ -2254,7 +3233,7 @@ type CapabilitiesResponse struct { func (x *CapabilitiesResponse) Reset() { *x = CapabilitiesResponse{} - mi := &file_iac_proto_msgTypes[29] + mi := &file_iac_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2266,7 +3245,7 @@ func (x *CapabilitiesResponse) String() string { func (*CapabilitiesResponse) ProtoMessage() {} func (x *CapabilitiesResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[29] + mi := &file_iac_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2279,7 +3258,7 @@ func (x *CapabilitiesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CapabilitiesResponse.ProtoReflect.Descriptor instead. func (*CapabilitiesResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{29} + return file_iac_proto_rawDescGZIP(), []int{39} } func (x *CapabilitiesResponse) GetCapabilities() []*IaCCapabilityDeclaration { @@ -2313,7 +3292,7 @@ type PlanRequest struct { func (x *PlanRequest) Reset() { *x = PlanRequest{} - mi := &file_iac_proto_msgTypes[30] + mi := &file_iac_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2325,7 +3304,7 @@ func (x *PlanRequest) String() string { func (*PlanRequest) ProtoMessage() {} func (x *PlanRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[30] + mi := &file_iac_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2338,7 +3317,7 @@ func (x *PlanRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use PlanRequest.ProtoReflect.Descriptor instead. func (*PlanRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{30} + return file_iac_proto_rawDescGZIP(), []int{40} } func (x *PlanRequest) GetDesired() []*ResourceSpec { @@ -2364,7 +3343,7 @@ type PlanResponse struct { func (x *PlanResponse) Reset() { *x = PlanResponse{} - mi := &file_iac_proto_msgTypes[31] + mi := &file_iac_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2376,7 +3355,7 @@ func (x *PlanResponse) String() string { func (*PlanResponse) ProtoMessage() {} func (x *PlanResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[31] + mi := &file_iac_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2389,7 +3368,7 @@ func (x *PlanResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use PlanResponse.ProtoReflect.Descriptor instead. func (*PlanResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{31} + return file_iac_proto_rawDescGZIP(), []int{41} } func (x *PlanResponse) GetPlan() *IaCPlan { @@ -2408,7 +3387,7 @@ type DestroyRequest struct { func (x *DestroyRequest) Reset() { *x = DestroyRequest{} - mi := &file_iac_proto_msgTypes[32] + mi := &file_iac_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2420,7 +3399,7 @@ func (x *DestroyRequest) String() string { func (*DestroyRequest) ProtoMessage() {} func (x *DestroyRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[32] + mi := &file_iac_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2433,7 +3412,7 @@ func (x *DestroyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DestroyRequest.ProtoReflect.Descriptor instead. func (*DestroyRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{32} + return file_iac_proto_rawDescGZIP(), []int{42} } func (x *DestroyRequest) GetRefs() []*ResourceRef { @@ -2452,7 +3431,7 @@ type DestroyResponse struct { func (x *DestroyResponse) Reset() { *x = DestroyResponse{} - mi := &file_iac_proto_msgTypes[33] + mi := &file_iac_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2464,7 +3443,7 @@ func (x *DestroyResponse) String() string { func (*DestroyResponse) ProtoMessage() {} func (x *DestroyResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[33] + mi := &file_iac_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2477,7 +3456,7 @@ func (x *DestroyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DestroyResponse.ProtoReflect.Descriptor instead. func (*DestroyResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{33} + return file_iac_proto_rawDescGZIP(), []int{43} } func (x *DestroyResponse) GetResult() *DestroyResult { @@ -2496,7 +3475,7 @@ type StatusRequest struct { func (x *StatusRequest) Reset() { *x = StatusRequest{} - mi := &file_iac_proto_msgTypes[34] + mi := &file_iac_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2508,7 +3487,7 @@ func (x *StatusRequest) String() string { func (*StatusRequest) ProtoMessage() {} func (x *StatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[34] + mi := &file_iac_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2521,7 +3500,7 @@ func (x *StatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StatusRequest.ProtoReflect.Descriptor instead. func (*StatusRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{34} + return file_iac_proto_rawDescGZIP(), []int{44} } func (x *StatusRequest) GetRefs() []*ResourceRef { @@ -2540,7 +3519,7 @@ type StatusResponse struct { func (x *StatusResponse) Reset() { *x = StatusResponse{} - mi := &file_iac_proto_msgTypes[35] + mi := &file_iac_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2552,7 +3531,7 @@ func (x *StatusResponse) String() string { func (*StatusResponse) ProtoMessage() {} func (x *StatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[35] + mi := &file_iac_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2565,7 +3544,7 @@ func (x *StatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StatusResponse.ProtoReflect.Descriptor instead. func (*StatusResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{35} + return file_iac_proto_rawDescGZIP(), []int{45} } func (x *StatusResponse) GetStatuses() []*ResourceStatus { @@ -2585,7 +3564,7 @@ type ImportRequest struct { func (x *ImportRequest) Reset() { *x = ImportRequest{} - mi := &file_iac_proto_msgTypes[36] + mi := &file_iac_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2597,7 +3576,7 @@ func (x *ImportRequest) String() string { func (*ImportRequest) ProtoMessage() {} func (x *ImportRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[36] + mi := &file_iac_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2610,7 +3589,7 @@ func (x *ImportRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ImportRequest.ProtoReflect.Descriptor instead. func (*ImportRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{36} + return file_iac_proto_rawDescGZIP(), []int{46} } func (x *ImportRequest) GetProviderId() string { @@ -2636,7 +3615,7 @@ type ImportResponse struct { func (x *ImportResponse) Reset() { *x = ImportResponse{} - mi := &file_iac_proto_msgTypes[37] + mi := &file_iac_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2648,7 +3627,7 @@ func (x *ImportResponse) String() string { func (*ImportResponse) ProtoMessage() {} func (x *ImportResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[37] + mi := &file_iac_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2661,7 +3640,7 @@ func (x *ImportResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ImportResponse.ProtoReflect.Descriptor instead. func (*ImportResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{37} + return file_iac_proto_rawDescGZIP(), []int{47} } func (x *ImportResponse) GetState() *ResourceState { @@ -2682,7 +3661,7 @@ type ResolveSizingRequest struct { func (x *ResolveSizingRequest) Reset() { *x = ResolveSizingRequest{} - mi := &file_iac_proto_msgTypes[38] + mi := &file_iac_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2694,7 +3673,7 @@ func (x *ResolveSizingRequest) String() string { func (*ResolveSizingRequest) ProtoMessage() {} func (x *ResolveSizingRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[38] + mi := &file_iac_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2707,7 +3686,7 @@ func (x *ResolveSizingRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveSizingRequest.ProtoReflect.Descriptor instead. func (*ResolveSizingRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{38} + return file_iac_proto_rawDescGZIP(), []int{48} } func (x *ResolveSizingRequest) GetResourceType() string { @@ -2740,7 +3719,7 @@ type ResolveSizingResponse struct { func (x *ResolveSizingResponse) Reset() { *x = ResolveSizingResponse{} - mi := &file_iac_proto_msgTypes[39] + mi := &file_iac_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2752,7 +3731,7 @@ func (x *ResolveSizingResponse) String() string { func (*ResolveSizingResponse) ProtoMessage() {} func (x *ResolveSizingResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[39] + mi := &file_iac_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2765,7 +3744,7 @@ func (x *ResolveSizingResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResolveSizingResponse.ProtoReflect.Descriptor instead. func (*ResolveSizingResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{39} + return file_iac_proto_rawDescGZIP(), []int{49} } func (x *ResolveSizingResponse) GetSizing() *ProviderSizing { @@ -2785,7 +3764,7 @@ type BootstrapStateBackendRequest struct { func (x *BootstrapStateBackendRequest) Reset() { *x = BootstrapStateBackendRequest{} - mi := &file_iac_proto_msgTypes[40] + mi := &file_iac_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2797,7 +3776,7 @@ func (x *BootstrapStateBackendRequest) String() string { func (*BootstrapStateBackendRequest) ProtoMessage() {} func (x *BootstrapStateBackendRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[40] + mi := &file_iac_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2810,7 +3789,7 @@ func (x *BootstrapStateBackendRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BootstrapStateBackendRequest.ProtoReflect.Descriptor instead. func (*BootstrapStateBackendRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{40} + return file_iac_proto_rawDescGZIP(), []int{50} } func (x *BootstrapStateBackendRequest) GetConfigJson() []byte { @@ -2829,7 +3808,7 @@ type BootstrapStateBackendResponse struct { func (x *BootstrapStateBackendResponse) Reset() { *x = BootstrapStateBackendResponse{} - mi := &file_iac_proto_msgTypes[41] + mi := &file_iac_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2841,7 +3820,7 @@ func (x *BootstrapStateBackendResponse) String() string { func (*BootstrapStateBackendResponse) ProtoMessage() {} func (x *BootstrapStateBackendResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[41] + mi := &file_iac_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2854,7 +3833,7 @@ func (x *BootstrapStateBackendResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use BootstrapStateBackendResponse.ProtoReflect.Descriptor instead. func (*BootstrapStateBackendResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{41} + return file_iac_proto_rawDescGZIP(), []int{51} } func (x *BootstrapStateBackendResponse) GetResult() *BootstrapResult { @@ -2876,7 +3855,7 @@ type EnumerateAllRequest struct { func (x *EnumerateAllRequest) Reset() { *x = EnumerateAllRequest{} - mi := &file_iac_proto_msgTypes[42] + mi := &file_iac_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2888,7 +3867,7 @@ func (x *EnumerateAllRequest) String() string { func (*EnumerateAllRequest) ProtoMessage() {} func (x *EnumerateAllRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[42] + mi := &file_iac_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2901,7 +3880,7 @@ func (x *EnumerateAllRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use EnumerateAllRequest.ProtoReflect.Descriptor instead. func (*EnumerateAllRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{42} + return file_iac_proto_rawDescGZIP(), []int{52} } func (x *EnumerateAllRequest) GetResourceType() string { @@ -2920,7 +3899,7 @@ type EnumerateAllResponse struct { func (x *EnumerateAllResponse) Reset() { *x = EnumerateAllResponse{} - mi := &file_iac_proto_msgTypes[43] + mi := &file_iac_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2932,7 +3911,7 @@ func (x *EnumerateAllResponse) String() string { func (*EnumerateAllResponse) ProtoMessage() {} func (x *EnumerateAllResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[43] + mi := &file_iac_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2945,7 +3924,7 @@ func (x *EnumerateAllResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use EnumerateAllResponse.ProtoReflect.Descriptor instead. func (*EnumerateAllResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{43} + return file_iac_proto_rawDescGZIP(), []int{53} } func (x *EnumerateAllResponse) GetOutputs() []*ResourceOutput { @@ -2964,7 +3943,7 @@ type EnumerateByTagRequest struct { func (x *EnumerateByTagRequest) Reset() { *x = EnumerateByTagRequest{} - mi := &file_iac_proto_msgTypes[44] + mi := &file_iac_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2976,7 +3955,7 @@ func (x *EnumerateByTagRequest) String() string { func (*EnumerateByTagRequest) ProtoMessage() {} func (x *EnumerateByTagRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[44] + mi := &file_iac_proto_msgTypes[54] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2989,7 +3968,7 @@ func (x *EnumerateByTagRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use EnumerateByTagRequest.ProtoReflect.Descriptor instead. func (*EnumerateByTagRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{44} + return file_iac_proto_rawDescGZIP(), []int{54} } func (x *EnumerateByTagRequest) GetTag() string { @@ -3008,7 +3987,7 @@ type EnumerateByTagResponse struct { func (x *EnumerateByTagResponse) Reset() { *x = EnumerateByTagResponse{} - mi := &file_iac_proto_msgTypes[45] + mi := &file_iac_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3020,7 +3999,7 @@ func (x *EnumerateByTagResponse) String() string { func (*EnumerateByTagResponse) ProtoMessage() {} func (x *EnumerateByTagResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[45] + mi := &file_iac_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3033,7 +4012,7 @@ func (x *EnumerateByTagResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use EnumerateByTagResponse.ProtoReflect.Descriptor instead. func (*EnumerateByTagResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{45} + return file_iac_proto_rawDescGZIP(), []int{55} } func (x *EnumerateByTagResponse) GetRefs() []*ResourceRef { @@ -3055,7 +4034,7 @@ type DetectDriftRequest struct { func (x *DetectDriftRequest) Reset() { *x = DetectDriftRequest{} - mi := &file_iac_proto_msgTypes[46] + mi := &file_iac_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3067,7 +4046,7 @@ func (x *DetectDriftRequest) String() string { func (*DetectDriftRequest) ProtoMessage() {} func (x *DetectDriftRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[46] + mi := &file_iac_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3080,7 +4059,7 @@ func (x *DetectDriftRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DetectDriftRequest.ProtoReflect.Descriptor instead. func (*DetectDriftRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{46} + return file_iac_proto_rawDescGZIP(), []int{56} } func (x *DetectDriftRequest) GetRefs() []*ResourceRef { @@ -3099,7 +4078,7 @@ type DetectDriftResponse struct { func (x *DetectDriftResponse) Reset() { *x = DetectDriftResponse{} - mi := &file_iac_proto_msgTypes[47] + mi := &file_iac_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3111,7 +4090,7 @@ func (x *DetectDriftResponse) String() string { func (*DetectDriftResponse) ProtoMessage() {} func (x *DetectDriftResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[47] + mi := &file_iac_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3124,7 +4103,7 @@ func (x *DetectDriftResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DetectDriftResponse.ProtoReflect.Descriptor instead. func (*DetectDriftResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{47} + return file_iac_proto_rawDescGZIP(), []int{57} } func (x *DetectDriftResponse) GetDrifts() []*DriftResult { @@ -3146,7 +4125,7 @@ type DetectDriftWithSpecsRequest struct { func (x *DetectDriftWithSpecsRequest) Reset() { *x = DetectDriftWithSpecsRequest{} - mi := &file_iac_proto_msgTypes[48] + mi := &file_iac_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3158,7 +4137,7 @@ func (x *DetectDriftWithSpecsRequest) String() string { func (*DetectDriftWithSpecsRequest) ProtoMessage() {} func (x *DetectDriftWithSpecsRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[48] + mi := &file_iac_proto_msgTypes[58] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3171,7 +4150,7 @@ func (x *DetectDriftWithSpecsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DetectDriftWithSpecsRequest.ProtoReflect.Descriptor instead. func (*DetectDriftWithSpecsRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{48} + return file_iac_proto_rawDescGZIP(), []int{58} } func (x *DetectDriftWithSpecsRequest) GetRefs() []*ResourceRef { @@ -3197,7 +4176,7 @@ type DetectDriftWithSpecsResponse struct { func (x *DetectDriftWithSpecsResponse) Reset() { *x = DetectDriftWithSpecsResponse{} - mi := &file_iac_proto_msgTypes[49] + mi := &file_iac_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3209,7 +4188,7 @@ func (x *DetectDriftWithSpecsResponse) String() string { func (*DetectDriftWithSpecsResponse) ProtoMessage() {} func (x *DetectDriftWithSpecsResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[49] + mi := &file_iac_proto_msgTypes[59] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3222,7 +4201,7 @@ func (x *DetectDriftWithSpecsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DetectDriftWithSpecsResponse.ProtoReflect.Descriptor instead. func (*DetectDriftWithSpecsResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{49} + return file_iac_proto_rawDescGZIP(), []int{59} } func (x *DetectDriftWithSpecsResponse) GetDrifts() []*DriftResult { @@ -3247,7 +4226,7 @@ type RevokeProviderCredentialRequest struct { func (x *RevokeProviderCredentialRequest) Reset() { *x = RevokeProviderCredentialRequest{} - mi := &file_iac_proto_msgTypes[50] + mi := &file_iac_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3259,7 +4238,7 @@ func (x *RevokeProviderCredentialRequest) String() string { func (*RevokeProviderCredentialRequest) ProtoMessage() {} func (x *RevokeProviderCredentialRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[50] + mi := &file_iac_proto_msgTypes[60] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3272,7 +4251,7 @@ func (x *RevokeProviderCredentialRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RevokeProviderCredentialRequest.ProtoReflect.Descriptor instead. func (*RevokeProviderCredentialRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{50} + return file_iac_proto_rawDescGZIP(), []int{60} } func (x *RevokeProviderCredentialRequest) GetSource() string { @@ -3297,7 +4276,7 @@ type RevokeProviderCredentialResponse struct { func (x *RevokeProviderCredentialResponse) Reset() { *x = RevokeProviderCredentialResponse{} - mi := &file_iac_proto_msgTypes[51] + mi := &file_iac_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3309,7 +4288,7 @@ func (x *RevokeProviderCredentialResponse) String() string { func (*RevokeProviderCredentialResponse) ProtoMessage() {} func (x *RevokeProviderCredentialResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[51] + mi := &file_iac_proto_msgTypes[61] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3322,7 +4301,7 @@ func (x *RevokeProviderCredentialResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RevokeProviderCredentialResponse.ProtoReflect.Descriptor instead. func (*RevokeProviderCredentialResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{51} + return file_iac_proto_rawDescGZIP(), []int{61} } // ───────────────────────────────────────────────────────────────────────────── @@ -3339,7 +4318,7 @@ type FinalizeApplyRequest struct { func (x *FinalizeApplyRequest) Reset() { *x = FinalizeApplyRequest{} - mi := &file_iac_proto_msgTypes[52] + mi := &file_iac_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3351,7 +4330,7 @@ func (x *FinalizeApplyRequest) String() string { func (*FinalizeApplyRequest) ProtoMessage() {} func (x *FinalizeApplyRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[52] + mi := &file_iac_proto_msgTypes[62] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3364,7 +4343,7 @@ func (x *FinalizeApplyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use FinalizeApplyRequest.ProtoReflect.Descriptor instead. func (*FinalizeApplyRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{52} + return file_iac_proto_rawDescGZIP(), []int{62} } func (x *FinalizeApplyRequest) GetPlanId() string { @@ -3399,7 +4378,7 @@ type FinalizeApplyResponse struct { func (x *FinalizeApplyResponse) Reset() { *x = FinalizeApplyResponse{} - mi := &file_iac_proto_msgTypes[53] + mi := &file_iac_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3411,7 +4390,7 @@ func (x *FinalizeApplyResponse) String() string { func (*FinalizeApplyResponse) ProtoMessage() {} func (x *FinalizeApplyResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[53] + mi := &file_iac_proto_msgTypes[63] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3424,7 +4403,7 @@ func (x *FinalizeApplyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use FinalizeApplyResponse.ProtoReflect.Descriptor instead. func (*FinalizeApplyResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{53} + return file_iac_proto_rawDescGZIP(), []int{63} } func (x *FinalizeApplyResponse) GetErrors() []*ActionError { @@ -3446,7 +4425,7 @@ type RepairDirtyMigrationRequest struct { func (x *RepairDirtyMigrationRequest) Reset() { *x = RepairDirtyMigrationRequest{} - mi := &file_iac_proto_msgTypes[54] + mi := &file_iac_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3458,7 +4437,7 @@ func (x *RepairDirtyMigrationRequest) String() string { func (*RepairDirtyMigrationRequest) ProtoMessage() {} func (x *RepairDirtyMigrationRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[54] + mi := &file_iac_proto_msgTypes[64] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3471,7 +4450,7 @@ func (x *RepairDirtyMigrationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RepairDirtyMigrationRequest.ProtoReflect.Descriptor instead. func (*RepairDirtyMigrationRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{54} + return file_iac_proto_rawDescGZIP(), []int{64} } func (x *RepairDirtyMigrationRequest) GetRequest() *MigrationRepairRequest { @@ -3490,7 +4469,7 @@ type RepairDirtyMigrationResponse struct { func (x *RepairDirtyMigrationResponse) Reset() { *x = RepairDirtyMigrationResponse{} - mi := &file_iac_proto_msgTypes[55] + mi := &file_iac_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3502,7 +4481,7 @@ func (x *RepairDirtyMigrationResponse) String() string { func (*RepairDirtyMigrationResponse) ProtoMessage() {} func (x *RepairDirtyMigrationResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[55] + mi := &file_iac_proto_msgTypes[65] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3515,7 +4494,7 @@ func (x *RepairDirtyMigrationResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RepairDirtyMigrationResponse.ProtoReflect.Descriptor instead. func (*RepairDirtyMigrationResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{55} + return file_iac_proto_rawDescGZIP(), []int{65} } func (x *RepairDirtyMigrationResponse) GetResult() *MigrationRepairResult { @@ -3537,7 +4516,7 @@ type ValidatePlanRequest struct { func (x *ValidatePlanRequest) Reset() { *x = ValidatePlanRequest{} - mi := &file_iac_proto_msgTypes[56] + mi := &file_iac_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3549,7 +4528,7 @@ func (x *ValidatePlanRequest) String() string { func (*ValidatePlanRequest) ProtoMessage() {} func (x *ValidatePlanRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[56] + mi := &file_iac_proto_msgTypes[66] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3562,7 +4541,7 @@ func (x *ValidatePlanRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidatePlanRequest.ProtoReflect.Descriptor instead. func (*ValidatePlanRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{56} + return file_iac_proto_rawDescGZIP(), []int{66} } func (x *ValidatePlanRequest) GetPlan() *IaCPlan { @@ -3581,7 +4560,7 @@ type ValidatePlanResponse struct { func (x *ValidatePlanResponse) Reset() { *x = ValidatePlanResponse{} - mi := &file_iac_proto_msgTypes[57] + mi := &file_iac_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3593,7 +4572,7 @@ func (x *ValidatePlanResponse) String() string { func (*ValidatePlanResponse) ProtoMessage() {} func (x *ValidatePlanResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[57] + mi := &file_iac_proto_msgTypes[67] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3606,7 +4585,7 @@ func (x *ValidatePlanResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ValidatePlanResponse.ProtoReflect.Descriptor instead. func (*ValidatePlanResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{57} + return file_iac_proto_rawDescGZIP(), []int{67} } func (x *ValidatePlanResponse) GetDiagnostics() []*PlanDiagnostic { @@ -3632,7 +4611,7 @@ type DetectDriftConfigRequest struct { func (x *DetectDriftConfigRequest) Reset() { *x = DetectDriftConfigRequest{} - mi := &file_iac_proto_msgTypes[58] + mi := &file_iac_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3644,7 +4623,7 @@ func (x *DetectDriftConfigRequest) String() string { func (*DetectDriftConfigRequest) ProtoMessage() {} func (x *DetectDriftConfigRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[58] + mi := &file_iac_proto_msgTypes[68] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3657,7 +4636,7 @@ func (x *DetectDriftConfigRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DetectDriftConfigRequest.ProtoReflect.Descriptor instead. func (*DetectDriftConfigRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{58} + return file_iac_proto_rawDescGZIP(), []int{68} } func (x *DetectDriftConfigRequest) GetRefs() []*ResourceRef { @@ -3683,7 +4662,7 @@ type DetectDriftConfigResponse struct { func (x *DetectDriftConfigResponse) Reset() { *x = DetectDriftConfigResponse{} - mi := &file_iac_proto_msgTypes[59] + mi := &file_iac_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3695,7 +4674,7 @@ func (x *DetectDriftConfigResponse) String() string { func (*DetectDriftConfigResponse) ProtoMessage() {} func (x *DetectDriftConfigResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[59] + mi := &file_iac_proto_msgTypes[69] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3708,7 +4687,7 @@ func (x *DetectDriftConfigResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DetectDriftConfigResponse.ProtoReflect.Descriptor instead. func (*DetectDriftConfigResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{59} + return file_iac_proto_rawDescGZIP(), []int{69} } func (x *DetectDriftConfigResponse) GetDrifts() []*DriftResult { @@ -3735,7 +4714,7 @@ type CaptureLogsRequest struct { func (x *CaptureLogsRequest) Reset() { *x = CaptureLogsRequest{} - mi := &file_iac_proto_msgTypes[60] + mi := &file_iac_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3747,7 +4726,7 @@ func (x *CaptureLogsRequest) String() string { func (*CaptureLogsRequest) ProtoMessage() {} func (x *CaptureLogsRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[60] + mi := &file_iac_proto_msgTypes[70] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3760,7 +4739,7 @@ func (x *CaptureLogsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CaptureLogsRequest.ProtoReflect.Descriptor instead. func (*CaptureLogsRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{60} + return file_iac_proto_rawDescGZIP(), []int{70} } func (x *CaptureLogsRequest) GetResourceName() string { @@ -3837,7 +4816,7 @@ type LogChunk struct { func (x *LogChunk) Reset() { *x = LogChunk{} - mi := &file_iac_proto_msgTypes[61] + mi := &file_iac_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3849,7 +4828,7 @@ func (x *LogChunk) String() string { func (*LogChunk) ProtoMessage() {} func (x *LogChunk) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[61] + mi := &file_iac_proto_msgTypes[71] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3862,7 +4841,7 @@ func (x *LogChunk) ProtoReflect() protoreflect.Message { // Deprecated: Use LogChunk.ProtoReflect.Descriptor instead. func (*LogChunk) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{61} + return file_iac_proto_rawDescGZIP(), []int{71} } func (x *LogChunk) GetData() []byte { @@ -3902,7 +4881,7 @@ type ResourceCreateRequest struct { func (x *ResourceCreateRequest) Reset() { *x = ResourceCreateRequest{} - mi := &file_iac_proto_msgTypes[62] + mi := &file_iac_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3914,7 +4893,7 @@ func (x *ResourceCreateRequest) String() string { func (*ResourceCreateRequest) ProtoMessage() {} func (x *ResourceCreateRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[62] + mi := &file_iac_proto_msgTypes[72] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3927,7 +4906,7 @@ func (x *ResourceCreateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceCreateRequest.ProtoReflect.Descriptor instead. func (*ResourceCreateRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{62} + return file_iac_proto_rawDescGZIP(), []int{72} } func (x *ResourceCreateRequest) GetResourceType() string { @@ -3953,7 +4932,7 @@ type ResourceCreateResponse struct { func (x *ResourceCreateResponse) Reset() { *x = ResourceCreateResponse{} - mi := &file_iac_proto_msgTypes[63] + mi := &file_iac_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3965,7 +4944,7 @@ func (x *ResourceCreateResponse) String() string { func (*ResourceCreateResponse) ProtoMessage() {} func (x *ResourceCreateResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[63] + mi := &file_iac_proto_msgTypes[73] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3978,7 +4957,7 @@ func (x *ResourceCreateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceCreateResponse.ProtoReflect.Descriptor instead. func (*ResourceCreateResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{63} + return file_iac_proto_rawDescGZIP(), []int{73} } func (x *ResourceCreateResponse) GetOutput() *ResourceOutput { @@ -3998,7 +4977,7 @@ type ResourceReadRequest struct { func (x *ResourceReadRequest) Reset() { *x = ResourceReadRequest{} - mi := &file_iac_proto_msgTypes[64] + mi := &file_iac_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4010,7 +4989,7 @@ func (x *ResourceReadRequest) String() string { func (*ResourceReadRequest) ProtoMessage() {} func (x *ResourceReadRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[64] + mi := &file_iac_proto_msgTypes[74] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4023,7 +5002,7 @@ func (x *ResourceReadRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceReadRequest.ProtoReflect.Descriptor instead. func (*ResourceReadRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{64} + return file_iac_proto_rawDescGZIP(), []int{74} } func (x *ResourceReadRequest) GetResourceType() string { @@ -4049,7 +5028,7 @@ type ResourceReadResponse struct { func (x *ResourceReadResponse) Reset() { *x = ResourceReadResponse{} - mi := &file_iac_proto_msgTypes[65] + mi := &file_iac_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4061,7 +5040,7 @@ func (x *ResourceReadResponse) String() string { func (*ResourceReadResponse) ProtoMessage() {} func (x *ResourceReadResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[65] + mi := &file_iac_proto_msgTypes[75] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4074,7 +5053,7 @@ func (x *ResourceReadResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceReadResponse.ProtoReflect.Descriptor instead. func (*ResourceReadResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{65} + return file_iac_proto_rawDescGZIP(), []int{75} } func (x *ResourceReadResponse) GetOutput() *ResourceOutput { @@ -4095,7 +5074,7 @@ type ResourceUpdateRequest struct { func (x *ResourceUpdateRequest) Reset() { *x = ResourceUpdateRequest{} - mi := &file_iac_proto_msgTypes[66] + mi := &file_iac_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4107,7 +5086,7 @@ func (x *ResourceUpdateRequest) String() string { func (*ResourceUpdateRequest) ProtoMessage() {} func (x *ResourceUpdateRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[66] + mi := &file_iac_proto_msgTypes[76] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4120,7 +5099,7 @@ func (x *ResourceUpdateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceUpdateRequest.ProtoReflect.Descriptor instead. func (*ResourceUpdateRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{66} + return file_iac_proto_rawDescGZIP(), []int{76} } func (x *ResourceUpdateRequest) GetResourceType() string { @@ -4153,7 +5132,7 @@ type ResourceUpdateResponse struct { func (x *ResourceUpdateResponse) Reset() { *x = ResourceUpdateResponse{} - mi := &file_iac_proto_msgTypes[67] + mi := &file_iac_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4165,7 +5144,7 @@ func (x *ResourceUpdateResponse) String() string { func (*ResourceUpdateResponse) ProtoMessage() {} func (x *ResourceUpdateResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[67] + mi := &file_iac_proto_msgTypes[77] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4178,7 +5157,7 @@ func (x *ResourceUpdateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceUpdateResponse.ProtoReflect.Descriptor instead. func (*ResourceUpdateResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{67} + return file_iac_proto_rawDescGZIP(), []int{77} } func (x *ResourceUpdateResponse) GetOutput() *ResourceOutput { @@ -4198,7 +5177,7 @@ type ResourceDeleteRequest struct { func (x *ResourceDeleteRequest) Reset() { *x = ResourceDeleteRequest{} - mi := &file_iac_proto_msgTypes[68] + mi := &file_iac_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4210,7 +5189,7 @@ func (x *ResourceDeleteRequest) String() string { func (*ResourceDeleteRequest) ProtoMessage() {} func (x *ResourceDeleteRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[68] + mi := &file_iac_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4223,7 +5202,7 @@ func (x *ResourceDeleteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceDeleteRequest.ProtoReflect.Descriptor instead. func (*ResourceDeleteRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{68} + return file_iac_proto_rawDescGZIP(), []int{78} } func (x *ResourceDeleteRequest) GetResourceType() string { @@ -4248,7 +5227,7 @@ type ResourceDeleteResponse struct { func (x *ResourceDeleteResponse) Reset() { *x = ResourceDeleteResponse{} - mi := &file_iac_proto_msgTypes[69] + mi := &file_iac_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4260,7 +5239,7 @@ func (x *ResourceDeleteResponse) String() string { func (*ResourceDeleteResponse) ProtoMessage() {} func (x *ResourceDeleteResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[69] + mi := &file_iac_proto_msgTypes[79] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4273,7 +5252,7 @@ func (x *ResourceDeleteResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceDeleteResponse.ProtoReflect.Descriptor instead. func (*ResourceDeleteResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{69} + return file_iac_proto_rawDescGZIP(), []int{79} } type ResourceDiffRequest struct { @@ -4287,7 +5266,7 @@ type ResourceDiffRequest struct { func (x *ResourceDiffRequest) Reset() { *x = ResourceDiffRequest{} - mi := &file_iac_proto_msgTypes[70] + mi := &file_iac_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4299,7 +5278,7 @@ func (x *ResourceDiffRequest) String() string { func (*ResourceDiffRequest) ProtoMessage() {} func (x *ResourceDiffRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[70] + mi := &file_iac_proto_msgTypes[80] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4312,7 +5291,7 @@ func (x *ResourceDiffRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceDiffRequest.ProtoReflect.Descriptor instead. func (*ResourceDiffRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{70} + return file_iac_proto_rawDescGZIP(), []int{80} } func (x *ResourceDiffRequest) GetResourceType() string { @@ -4345,7 +5324,7 @@ type ResourceDiffResponse struct { func (x *ResourceDiffResponse) Reset() { *x = ResourceDiffResponse{} - mi := &file_iac_proto_msgTypes[71] + mi := &file_iac_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4357,7 +5336,7 @@ func (x *ResourceDiffResponse) String() string { func (*ResourceDiffResponse) ProtoMessage() {} func (x *ResourceDiffResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[71] + mi := &file_iac_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4370,7 +5349,7 @@ func (x *ResourceDiffResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceDiffResponse.ProtoReflect.Descriptor instead. func (*ResourceDiffResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{71} + return file_iac_proto_rawDescGZIP(), []int{81} } func (x *ResourceDiffResponse) GetResult() *DiffResult { @@ -4391,7 +5370,7 @@ type ResourceScaleRequest struct { func (x *ResourceScaleRequest) Reset() { *x = ResourceScaleRequest{} - mi := &file_iac_proto_msgTypes[72] + mi := &file_iac_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4403,7 +5382,7 @@ func (x *ResourceScaleRequest) String() string { func (*ResourceScaleRequest) ProtoMessage() {} func (x *ResourceScaleRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[72] + mi := &file_iac_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4416,7 +5395,7 @@ func (x *ResourceScaleRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceScaleRequest.ProtoReflect.Descriptor instead. func (*ResourceScaleRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{72} + return file_iac_proto_rawDescGZIP(), []int{82} } func (x *ResourceScaleRequest) GetResourceType() string { @@ -4449,7 +5428,7 @@ type ResourceScaleResponse struct { func (x *ResourceScaleResponse) Reset() { *x = ResourceScaleResponse{} - mi := &file_iac_proto_msgTypes[73] + mi := &file_iac_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4461,7 +5440,7 @@ func (x *ResourceScaleResponse) String() string { func (*ResourceScaleResponse) ProtoMessage() {} func (x *ResourceScaleResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[73] + mi := &file_iac_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4474,7 +5453,7 @@ func (x *ResourceScaleResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceScaleResponse.ProtoReflect.Descriptor instead. func (*ResourceScaleResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{73} + return file_iac_proto_rawDescGZIP(), []int{83} } func (x *ResourceScaleResponse) GetOutput() *ResourceOutput { @@ -4494,7 +5473,7 @@ type ResourceHealthCheckRequest struct { func (x *ResourceHealthCheckRequest) Reset() { *x = ResourceHealthCheckRequest{} - mi := &file_iac_proto_msgTypes[74] + mi := &file_iac_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4506,7 +5485,7 @@ func (x *ResourceHealthCheckRequest) String() string { func (*ResourceHealthCheckRequest) ProtoMessage() {} func (x *ResourceHealthCheckRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[74] + mi := &file_iac_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4519,7 +5498,7 @@ func (x *ResourceHealthCheckRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceHealthCheckRequest.ProtoReflect.Descriptor instead. func (*ResourceHealthCheckRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{74} + return file_iac_proto_rawDescGZIP(), []int{84} } func (x *ResourceHealthCheckRequest) GetResourceType() string { @@ -4545,7 +5524,7 @@ type ResourceHealthCheckResponse struct { func (x *ResourceHealthCheckResponse) Reset() { *x = ResourceHealthCheckResponse{} - mi := &file_iac_proto_msgTypes[75] + mi := &file_iac_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4557,7 +5536,7 @@ func (x *ResourceHealthCheckResponse) String() string { func (*ResourceHealthCheckResponse) ProtoMessage() {} func (x *ResourceHealthCheckResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[75] + mi := &file_iac_proto_msgTypes[85] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4570,7 +5549,7 @@ func (x *ResourceHealthCheckResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ResourceHealthCheckResponse.ProtoReflect.Descriptor instead. func (*ResourceHealthCheckResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{75} + return file_iac_proto_rawDescGZIP(), []int{85} } func (x *ResourceHealthCheckResponse) GetResult() *HealthResult { @@ -4589,7 +5568,7 @@ type SensitiveKeysRequest struct { func (x *SensitiveKeysRequest) Reset() { *x = SensitiveKeysRequest{} - mi := &file_iac_proto_msgTypes[76] + mi := &file_iac_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4601,7 +5580,7 @@ func (x *SensitiveKeysRequest) String() string { func (*SensitiveKeysRequest) ProtoMessage() {} func (x *SensitiveKeysRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[76] + mi := &file_iac_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4614,7 +5593,7 @@ func (x *SensitiveKeysRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SensitiveKeysRequest.ProtoReflect.Descriptor instead. func (*SensitiveKeysRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{76} + return file_iac_proto_rawDescGZIP(), []int{86} } func (x *SensitiveKeysRequest) GetResourceType() string { @@ -4633,7 +5612,7 @@ type SensitiveKeysResponse struct { func (x *SensitiveKeysResponse) Reset() { *x = SensitiveKeysResponse{} - mi := &file_iac_proto_msgTypes[77] + mi := &file_iac_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4645,7 +5624,7 @@ func (x *SensitiveKeysResponse) String() string { func (*SensitiveKeysResponse) ProtoMessage() {} func (x *SensitiveKeysResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[77] + mi := &file_iac_proto_msgTypes[87] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4658,7 +5637,7 @@ func (x *SensitiveKeysResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SensitiveKeysResponse.ProtoReflect.Descriptor instead. func (*SensitiveKeysResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{77} + return file_iac_proto_rawDescGZIP(), []int{87} } func (x *SensitiveKeysResponse) GetKeys() []string { @@ -4679,7 +5658,7 @@ type TroubleshootRequest struct { func (x *TroubleshootRequest) Reset() { *x = TroubleshootRequest{} - mi := &file_iac_proto_msgTypes[78] + mi := &file_iac_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4691,7 +5670,7 @@ func (x *TroubleshootRequest) String() string { func (*TroubleshootRequest) ProtoMessage() {} func (x *TroubleshootRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[78] + mi := &file_iac_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4704,7 +5683,7 @@ func (x *TroubleshootRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use TroubleshootRequest.ProtoReflect.Descriptor instead. func (*TroubleshootRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{78} + return file_iac_proto_rawDescGZIP(), []int{88} } func (x *TroubleshootRequest) GetResourceType() string { @@ -4737,7 +5716,7 @@ type TroubleshootResponse struct { func (x *TroubleshootResponse) Reset() { *x = TroubleshootResponse{} - mi := &file_iac_proto_msgTypes[79] + mi := &file_iac_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4749,7 +5728,7 @@ func (x *TroubleshootResponse) String() string { func (*TroubleshootResponse) ProtoMessage() {} func (x *TroubleshootResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[79] + mi := &file_iac_proto_msgTypes[89] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4762,7 +5741,7 @@ func (x *TroubleshootResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use TroubleshootResponse.ProtoReflect.Descriptor instead. func (*TroubleshootResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{79} + return file_iac_proto_rawDescGZIP(), []int{89} } func (x *TroubleshootResponse) GetDiagnostics() []*Diagnostic { @@ -4796,7 +5775,7 @@ type IaCState struct { func (x *IaCState) Reset() { *x = IaCState{} - mi := &file_iac_proto_msgTypes[80] + mi := &file_iac_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4808,7 +5787,7 @@ func (x *IaCState) String() string { func (*IaCState) ProtoMessage() {} func (x *IaCState) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[80] + mi := &file_iac_proto_msgTypes[90] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4821,7 +5800,7 @@ func (x *IaCState) ProtoReflect() protoreflect.Message { // Deprecated: Use IaCState.ProtoReflect.Descriptor instead. func (*IaCState) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{80} + return file_iac_proto_rawDescGZIP(), []int{90} } func (x *IaCState) GetResourceId() string { @@ -4929,7 +5908,7 @@ type ConfigureRequest struct { func (x *ConfigureRequest) Reset() { *x = ConfigureRequest{} - mi := &file_iac_proto_msgTypes[81] + mi := &file_iac_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4941,7 +5920,7 @@ func (x *ConfigureRequest) String() string { func (*ConfigureRequest) ProtoMessage() {} func (x *ConfigureRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[81] + mi := &file_iac_proto_msgTypes[91] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4954,7 +5933,7 @@ func (x *ConfigureRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfigureRequest.ProtoReflect.Descriptor instead. func (*ConfigureRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{81} + return file_iac_proto_rawDescGZIP(), []int{91} } func (x *ConfigureRequest) GetBackendName() string { @@ -4979,7 +5958,7 @@ type ConfigureResponse struct { func (x *ConfigureResponse) Reset() { *x = ConfigureResponse{} - mi := &file_iac_proto_msgTypes[82] + mi := &file_iac_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4991,7 +5970,7 @@ func (x *ConfigureResponse) String() string { func (*ConfigureResponse) ProtoMessage() {} func (x *ConfigureResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[82] + mi := &file_iac_proto_msgTypes[92] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5004,7 +5983,7 @@ func (x *ConfigureResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ConfigureResponse.ProtoReflect.Descriptor instead. func (*ConfigureResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{82} + return file_iac_proto_rawDescGZIP(), []int{92} } type GetStateRequest struct { @@ -5016,7 +5995,7 @@ type GetStateRequest struct { func (x *GetStateRequest) Reset() { *x = GetStateRequest{} - mi := &file_iac_proto_msgTypes[83] + mi := &file_iac_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5028,7 +6007,7 @@ func (x *GetStateRequest) String() string { func (*GetStateRequest) ProtoMessage() {} func (x *GetStateRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[83] + mi := &file_iac_proto_msgTypes[93] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5041,7 +6020,7 @@ func (x *GetStateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetStateRequest.ProtoReflect.Descriptor instead. func (*GetStateRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{83} + return file_iac_proto_rawDescGZIP(), []int{93} } func (x *GetStateRequest) GetResourceId() string { @@ -5061,7 +6040,7 @@ type GetStateResponse struct { func (x *GetStateResponse) Reset() { *x = GetStateResponse{} - mi := &file_iac_proto_msgTypes[84] + mi := &file_iac_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5073,7 +6052,7 @@ func (x *GetStateResponse) String() string { func (*GetStateResponse) ProtoMessage() {} func (x *GetStateResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[84] + mi := &file_iac_proto_msgTypes[94] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5086,7 +6065,7 @@ func (x *GetStateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetStateResponse.ProtoReflect.Descriptor instead. func (*GetStateResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{84} + return file_iac_proto_rawDescGZIP(), []int{94} } func (x *GetStateResponse) GetState() *IaCState { @@ -5112,7 +6091,7 @@ type SaveStateRequest struct { func (x *SaveStateRequest) Reset() { *x = SaveStateRequest{} - mi := &file_iac_proto_msgTypes[85] + mi := &file_iac_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5124,7 +6103,7 @@ func (x *SaveStateRequest) String() string { func (*SaveStateRequest) ProtoMessage() {} func (x *SaveStateRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[85] + mi := &file_iac_proto_msgTypes[95] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5137,7 +6116,7 @@ func (x *SaveStateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SaveStateRequest.ProtoReflect.Descriptor instead. func (*SaveStateRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{85} + return file_iac_proto_rawDescGZIP(), []int{95} } func (x *SaveStateRequest) GetState() *IaCState { @@ -5155,7 +6134,7 @@ type SaveStateResponse struct { func (x *SaveStateResponse) Reset() { *x = SaveStateResponse{} - mi := &file_iac_proto_msgTypes[86] + mi := &file_iac_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5167,7 +6146,7 @@ func (x *SaveStateResponse) String() string { func (*SaveStateResponse) ProtoMessage() {} func (x *SaveStateResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[86] + mi := &file_iac_proto_msgTypes[96] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5180,7 +6159,7 @@ func (x *SaveStateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SaveStateResponse.ProtoReflect.Descriptor instead. func (*SaveStateResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{86} + return file_iac_proto_rawDescGZIP(), []int{96} } type ListStatesRequest struct { @@ -5192,7 +6171,7 @@ type ListStatesRequest struct { func (x *ListStatesRequest) Reset() { *x = ListStatesRequest{} - mi := &file_iac_proto_msgTypes[87] + mi := &file_iac_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5204,7 +6183,7 @@ func (x *ListStatesRequest) String() string { func (*ListStatesRequest) ProtoMessage() {} func (x *ListStatesRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[87] + mi := &file_iac_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5217,7 +6196,7 @@ func (x *ListStatesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListStatesRequest.ProtoReflect.Descriptor instead. func (*ListStatesRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{87} + return file_iac_proto_rawDescGZIP(), []int{97} } func (x *ListStatesRequest) GetFilter() map[string]string { @@ -5236,7 +6215,7 @@ type ListStatesResponse struct { func (x *ListStatesResponse) Reset() { *x = ListStatesResponse{} - mi := &file_iac_proto_msgTypes[88] + mi := &file_iac_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5248,7 +6227,7 @@ func (x *ListStatesResponse) String() string { func (*ListStatesResponse) ProtoMessage() {} func (x *ListStatesResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[88] + mi := &file_iac_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5261,7 +6240,7 @@ func (x *ListStatesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListStatesResponse.ProtoReflect.Descriptor instead. func (*ListStatesResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{88} + return file_iac_proto_rawDescGZIP(), []int{98} } func (x *ListStatesResponse) GetStates() []*IaCState { @@ -5280,7 +6259,7 @@ type DeleteStateRequest struct { func (x *DeleteStateRequest) Reset() { *x = DeleteStateRequest{} - mi := &file_iac_proto_msgTypes[89] + mi := &file_iac_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5292,7 +6271,7 @@ func (x *DeleteStateRequest) String() string { func (*DeleteStateRequest) ProtoMessage() {} func (x *DeleteStateRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[89] + mi := &file_iac_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5305,7 +6284,7 @@ func (x *DeleteStateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteStateRequest.ProtoReflect.Descriptor instead. func (*DeleteStateRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{89} + return file_iac_proto_rawDescGZIP(), []int{99} } func (x *DeleteStateRequest) GetResourceId() string { @@ -5323,7 +6302,7 @@ type DeleteStateResponse struct { func (x *DeleteStateResponse) Reset() { *x = DeleteStateResponse{} - mi := &file_iac_proto_msgTypes[90] + mi := &file_iac_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5335,7 +6314,7 @@ func (x *DeleteStateResponse) String() string { func (*DeleteStateResponse) ProtoMessage() {} func (x *DeleteStateResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[90] + mi := &file_iac_proto_msgTypes[100] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5348,7 +6327,7 @@ func (x *DeleteStateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteStateResponse.ProtoReflect.Descriptor instead. func (*DeleteStateResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{90} + return file_iac_proto_rawDescGZIP(), []int{100} } type LockRequest struct { @@ -5360,7 +6339,7 @@ type LockRequest struct { func (x *LockRequest) Reset() { *x = LockRequest{} - mi := &file_iac_proto_msgTypes[91] + mi := &file_iac_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5372,7 +6351,7 @@ func (x *LockRequest) String() string { func (*LockRequest) ProtoMessage() {} func (x *LockRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[91] + mi := &file_iac_proto_msgTypes[101] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5385,7 +6364,7 @@ func (x *LockRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use LockRequest.ProtoReflect.Descriptor instead. func (*LockRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{91} + return file_iac_proto_rawDescGZIP(), []int{101} } func (x *LockRequest) GetResourceId() string { @@ -5403,7 +6382,7 @@ type LockResponse struct { func (x *LockResponse) Reset() { *x = LockResponse{} - mi := &file_iac_proto_msgTypes[92] + mi := &file_iac_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5415,7 +6394,7 @@ func (x *LockResponse) String() string { func (*LockResponse) ProtoMessage() {} func (x *LockResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[92] + mi := &file_iac_proto_msgTypes[102] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5428,7 +6407,7 @@ func (x *LockResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use LockResponse.ProtoReflect.Descriptor instead. func (*LockResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{92} + return file_iac_proto_rawDescGZIP(), []int{102} } type UnlockRequest struct { @@ -5440,7 +6419,7 @@ type UnlockRequest struct { func (x *UnlockRequest) Reset() { *x = UnlockRequest{} - mi := &file_iac_proto_msgTypes[93] + mi := &file_iac_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5452,7 +6431,7 @@ func (x *UnlockRequest) String() string { func (*UnlockRequest) ProtoMessage() {} func (x *UnlockRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[93] + mi := &file_iac_proto_msgTypes[103] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5465,7 +6444,7 @@ func (x *UnlockRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UnlockRequest.ProtoReflect.Descriptor instead. func (*UnlockRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{93} + return file_iac_proto_rawDescGZIP(), []int{103} } func (x *UnlockRequest) GetResourceId() string { @@ -5483,7 +6462,7 @@ type UnlockResponse struct { func (x *UnlockResponse) Reset() { *x = UnlockResponse{} - mi := &file_iac_proto_msgTypes[94] + mi := &file_iac_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5495,7 +6474,7 @@ func (x *UnlockResponse) String() string { func (*UnlockResponse) ProtoMessage() {} func (x *UnlockResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[94] + mi := &file_iac_proto_msgTypes[104] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5508,7 +6487,7 @@ func (x *UnlockResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UnlockResponse.ProtoReflect.Descriptor instead. func (*UnlockResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{94} + return file_iac_proto_rawDescGZIP(), []int{104} } // ListBackendNames lets the engine ask a loaded plugin which iac.state backend @@ -5522,7 +6501,7 @@ type ListBackendNamesRequest struct { func (x *ListBackendNamesRequest) Reset() { *x = ListBackendNamesRequest{} - mi := &file_iac_proto_msgTypes[95] + mi := &file_iac_proto_msgTypes[105] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5534,7 +6513,7 @@ func (x *ListBackendNamesRequest) String() string { func (*ListBackendNamesRequest) ProtoMessage() {} func (x *ListBackendNamesRequest) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[95] + mi := &file_iac_proto_msgTypes[105] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5547,7 +6526,7 @@ func (x *ListBackendNamesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListBackendNamesRequest.ProtoReflect.Descriptor instead. func (*ListBackendNamesRequest) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{95} + return file_iac_proto_rawDescGZIP(), []int{105} } type ListBackendNamesResponse struct { @@ -5559,7 +6538,7 @@ type ListBackendNamesResponse struct { func (x *ListBackendNamesResponse) Reset() { *x = ListBackendNamesResponse{} - mi := &file_iac_proto_msgTypes[96] + mi := &file_iac_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -5571,7 +6550,7 @@ func (x *ListBackendNamesResponse) String() string { func (*ListBackendNamesResponse) ProtoMessage() {} func (x *ListBackendNamesResponse) ProtoReflect() protoreflect.Message { - mi := &file_iac_proto_msgTypes[96] + mi := &file_iac_proto_msgTypes[106] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -5584,7 +6563,7 @@ func (x *ListBackendNamesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListBackendNamesResponse.ProtoReflect.Descriptor instead. func (*ListBackendNamesResponse) Descriptor() ([]byte, []int) { - return file_iac_proto_rawDescGZIP(), []int{96} + return file_iac_proto_rawDescGZIP(), []int{106} } func (x *ListBackendNamesResponse) GetBackendNames() []string { @@ -5674,7 +6653,61 @@ const file_iac_proto_rawDesc = "" + "DiffResult\x12!\n" + "\fneeds_update\x18\x01 \x01(\bR\vneedsUpdate\x12#\n" + "\rneeds_replace\x18\x02 \x01(\bR\fneedsReplace\x12C\n" + - "\achanges\x18\x03 \x03(\v2).workflow.plugin.external.iac.FieldChangeR\achanges\"\xed\x01\n" + + "\achanges\x18\x03 \x03(\v2).workflow.plugin.external.iac.FieldChangeR\achanges\"\x8d\x05\n" + + "\x0eIaCRequirement\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12A\n" + + "\x04kind\x18\x02 \x01(\x0e2-.workflow.plugin.external.iac.RequirementKindR\x04kind\x12\x16\n" + + "\x06source\x18\x03 \x01(\tR\x06source\x12,\n" + + "\x12resource_type_hint\x18\x04 \x01(\tR\x10resourceTypeHint\x12 \n" + + "\venvironment\x18\x05 \x01(\tR\venvironment\x12L\n" + + "\bruntimes\x18\x06 \x03(\x0e20.workflow.plugin.external.iac.RequirementRuntimeR\bruntimes\x12Z\n" + + "\x11telemetry_signals\x18\a \x03(\x0e2-.workflow.plugin.external.iac.TelemetrySignalR\x10telemetrySignals\x12i\n" + + "\x16observability_backends\x18\b \x03(\x0e22.workflow.plugin.external.iac.ObservabilityBackendR\x15observabilityBackends\x12W\n" + + "\x10deployment_modes\x18\t \x03(\x0e2,.workflow.plugin.external.iac.DeploymentModeR\x0fdeploymentModes\x12'\n" + + "\x0fvendor_features\x18\n" + + " \x03(\tR\x0evendorFeatures\x12'\n" + + "\x0fparameters_json\x18\v \x01(\fR\x0eparametersJson\"\x97\x01\n" + + "\x1bDiscoverRequirementsRequest\x12J\n" + + "\acontext\x18\x01 \x01(\v20.workflow.plugin.external.iac.RequirementContextR\acontext\x12,\n" + + "\x12module_config_json\x18\x02 \x01(\fR\x10moduleConfigJson\"\xba\x01\n" + + "\x12RequirementContext\x12 \n" + + "\vapplication\x18\x01 \x01(\tR\vapplication\x12 \n" + + "\venvironment\x18\x02 \x01(\tR\venvironment\x12A\n" + + "\amodules\x18\x03 \x03(\v2'.workflow.plugin.external.iac.ModuleRefR\amodules\x12\x1d\n" + + "\n" + + "plugin_ids\x18\x04 \x03(\tR\tpluginIds\"Q\n" + + "\tModuleRef\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x12\n" + + "\x04type\x18\x02 \x01(\tR\x04type\x12\x1c\n" + + "\tsatisfies\x18\x03 \x03(\tR\tsatisfies\"p\n" + + "\x1cDiscoverRequirementsResponse\x12P\n" + + "\frequirements\x18\x01 \x03(\v2,.workflow.plugin.external.iac.IaCRequirementR\frequirements\"\xf4\x01\n" + + "\x16MapRequirementsRequest\x12\x1a\n" + + "\bprovider\x18\x01 \x01(\tR\bprovider\x12J\n" + + "\aruntime\x18\x02 \x01(\x0e20.workflow.plugin.external.iac.RequirementRuntimeR\aruntime\x12 \n" + + "\venvironment\x18\x03 \x01(\tR\venvironment\x12P\n" + + "\frequirements\x18\x04 \x03(\v2,.workflow.plugin.external.iac.IaCRequirementR\frequirements\"\x99\x01\n" + + "\x11DerivedModuleSpec\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x12\n" + + "\x04type\x18\x02 \x01(\tR\x04type\x12\x1c\n" + + "\tsatisfies\x18\x03 \x03(\tR\tsatisfies\x12\x1f\n" + + "\vconfig_json\x18\x04 \x01(\fR\n" + + "configJson\x12\x1d\n" + + "\n" + + "depends_on\x18\x05 \x03(\tR\tdependsOn\"W\n" + + "\x15RequirementDiagnostic\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x12\n" + + "\x04code\x18\x02 \x01(\tR\x04code\x12\x18\n" + + "\amessage\x18\x03 \x01(\tR\amessage\"_\n" + + "\x0fRequirementNote\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x18\n" + + "\amessage\x18\x02 \x01(\tR\amessage\x12 \n" + + "\vinteractive\x18\x03 \x01(\bR\vinteractive\"\x9f\x02\n" + + "\x17MapRequirementsResponse\x12#\n" + + "\raccepted_keys\x18\x01 \x03(\tR\facceptedKeys\x12O\n" + + "\brejected\x18\x02 \x03(\v23.workflow.plugin.external.iac.RequirementDiagnosticR\brejected\x12I\n" + + "\amodules\x18\x03 \x03(\v2/.workflow.plugin.external.iac.DerivedModuleSpecR\amodules\x12C\n" + + "\x05notes\x18\x04 \x03(\v2-.workflow.plugin.external.iac.RequirementNoteR\x05notes\"\xed\x01\n" + "\vDriftResult\x12\x12\n" + "\x04name\x18\x01 \x01(\tR\x04name\x12\x12\n" + "\x04type\x18\x02 \x01(\tR\x04type\x12\x18\n" + @@ -5977,7 +7010,40 @@ const file_iac_proto_rawDesc = "" + "\x13DRIFT_CLASS_UNKNOWN\x10\x00\x12\x17\n" + "\x13DRIFT_CLASS_IN_SYNC\x10\x01\x12\x15\n" + "\x11DRIFT_CLASS_GHOST\x10\x02\x12\x16\n" + - "\x12DRIFT_CLASS_CONFIG\x10\x03*j\n" + + "\x12DRIFT_CLASS_CONFIG\x10\x03*\xf3\x01\n" + + "\x0fRequirementKind\x12 \n" + + "\x1cREQUIREMENT_KIND_UNSPECIFIED\x10\x00\x12\"\n" + + "\x1eREQUIREMENT_KIND_OBSERVABILITY\x10\x01\x12\x1c\n" + + "\x18REQUIREMENT_KIND_WEB_API\x10\x02\x12#\n" + + "\x1fREQUIREMENT_KIND_MESSAGE_BROKER\x10\x03\x12\x1d\n" + + "\x19REQUIREMENT_KIND_DATABASE\x10\x04\x12\x1a\n" + + "\x16REQUIREMENT_KIND_CACHE\x10\x05\x12\x1c\n" + + "\x18REQUIREMENT_KIND_STORAGE\x10\x06*\xfe\x01\n" + + "\x12RequirementRuntime\x12#\n" + + "\x1fREQUIREMENT_RUNTIME_UNSPECIFIED\x10\x00\x12\"\n" + + "\x1eREQUIREMENT_RUNTIME_KUBERNETES\x10\x01\x12\x1b\n" + + "\x17REQUIREMENT_RUNTIME_ECS\x10\x02\x12!\n" + + "\x1dREQUIREMENT_RUNTIME_CLOUD_RUN\x10\x03\x12,\n" + + "(REQUIREMENT_RUNTIME_AZURE_CONTAINER_APPS\x10\x04\x121\n" + + "-REQUIREMENT_RUNTIME_DIGITALOCEAN_APP_PLATFORM\x10\x05*\x89\x01\n" + + "\x0fTelemetrySignal\x12 \n" + + "\x1cTELEMETRY_SIGNAL_UNSPECIFIED\x10\x00\x12\x1b\n" + + "\x17TELEMETRY_SIGNAL_TRACES\x10\x01\x12\x1c\n" + + "\x18TELEMETRY_SIGNAL_METRICS\x10\x02\x12\x19\n" + + "\x15TELEMETRY_SIGNAL_LOGS\x10\x03*\xe9\x01\n" + + "\x14ObservabilityBackend\x12%\n" + + "!OBSERVABILITY_BACKEND_UNSPECIFIED\x10\x00\x12\x1e\n" + + "\x1aOBSERVABILITY_BACKEND_OTEL\x10\x01\x12!\n" + + "\x1dOBSERVABILITY_BACKEND_DATADOG\x10\x02\x12$\n" + + " OBSERVABILITY_BACKEND_PROMETHEUS\x10\x03\x12\x1e\n" + + "\x1aOBSERVABILITY_BACKEND_LOKI\x10\x04\x12!\n" + + "\x1dOBSERVABILITY_BACKEND_GRAFANA\x10\x05*\xaf\x01\n" + + "\x0eDeploymentMode\x12\x1f\n" + + "\x1bDEPLOYMENT_MODE_UNSPECIFIED\x10\x00\x12\x1b\n" + + "\x17DEPLOYMENT_MODE_SIDECAR\x10\x01\x12\x1d\n" + + "\x19DEPLOYMENT_MODE_DAEMONSET\x10\x02\x12#\n" + + "\x1fDEPLOYMENT_MODE_SIBLING_SERVICE\x10\x03\x12\x1b\n" + + "\x17DEPLOYMENT_MODE_MANAGED\x10\x04*j\n" + "\x16PlanDiagnosticSeverity\x12\x18\n" + "\x14PLAN_DIAGNOSTIC_INFO\x10\x00\x12\x1b\n" + "\x17PLAN_DIAGNOSTIC_WARNING\x10\x01\x12\x19\n" + @@ -6025,7 +7091,11 @@ const file_iac_proto_rawDesc = "" + "\x1eIaCProviderDriftConfigDetector\x12\x84\x01\n" + "\x11DetectDriftConfig\x126.workflow.plugin.external.iac.DetectDriftConfigRequest\x1a7.workflow.plugin.external.iac.DetectDriftConfigResponse2\x82\x01\n" + "\x15IaCProviderLogCapture\x12i\n" + - "\vCaptureLogs\x120.workflow.plugin.external.iac.CaptureLogsRequest\x1a&.workflow.plugin.external.iac.LogChunk0\x012\xb5\b\n" + + "\vCaptureLogs\x120.workflow.plugin.external.iac.CaptureLogsRequest\x1a&.workflow.plugin.external.iac.LogChunk0\x012\xa9\x01\n" + + "\x17IaCRequirementDiscovery\x12\x8d\x01\n" + + "\x14DiscoverRequirements\x129.workflow.plugin.external.iac.DiscoverRequirementsRequest\x1a:.workflow.plugin.external.iac.DiscoverRequirementsResponse2\x9e\x01\n" + + "\x1cIaCProviderRequirementMapper\x12~\n" + + "\x0fMapRequirements\x124.workflow.plugin.external.iac.MapRequirementsRequest\x1a5.workflow.plugin.external.iac.MapRequirementsResponse2\xb5\b\n" + "\x0eResourceDriver\x12s\n" + "\x06Create\x123.workflow.plugin.external.iac.ResourceCreateRequest\x1a4.workflow.plugin.external.iac.ResourceCreateResponse\x12m\n" + "\x04Read\x121.workflow.plugin.external.iac.ResourceReadRequest\x1a2.workflow.plugin.external.iac.ResourceReadResponse\x12s\n" + @@ -6059,269 +7129,301 @@ func file_iac_proto_rawDescGZIP() []byte { return file_iac_proto_rawDescData } -var file_iac_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_iac_proto_msgTypes = make([]protoimpl.MessageInfo, 104) +var file_iac_proto_enumTypes = make([]protoimpl.EnumInfo, 9) +var file_iac_proto_msgTypes = make([]protoimpl.MessageInfo, 114) var file_iac_proto_goTypes = []any{ (DriftClass)(0), // 0: workflow.plugin.external.iac.DriftClass - (PlanDiagnosticSeverity)(0), // 1: workflow.plugin.external.iac.PlanDiagnosticSeverity - (ActionStatus)(0), // 2: workflow.plugin.external.iac.ActionStatus - (LogCaptureType)(0), // 3: workflow.plugin.external.iac.LogCaptureType - (*ResourceSpec)(nil), // 4: workflow.plugin.external.iac.ResourceSpec - (*ResourceRef)(nil), // 5: workflow.plugin.external.iac.ResourceRef - (*ResourceHints)(nil), // 6: workflow.plugin.external.iac.ResourceHints - (*ProviderSizing)(nil), // 7: workflow.plugin.external.iac.ProviderSizing - (*IaCCapabilityDeclaration)(nil), // 8: workflow.plugin.external.iac.IaCCapabilityDeclaration - (*ResourceState)(nil), // 9: workflow.plugin.external.iac.ResourceState - (*ResourceOutput)(nil), // 10: workflow.plugin.external.iac.ResourceOutput - (*ResourceStatus)(nil), // 11: workflow.plugin.external.iac.ResourceStatus - (*FieldChange)(nil), // 12: workflow.plugin.external.iac.FieldChange - (*DiffResult)(nil), // 13: workflow.plugin.external.iac.DiffResult - (*DriftResult)(nil), // 14: workflow.plugin.external.iac.DriftResult - (*DriftEntry)(nil), // 15: workflow.plugin.external.iac.DriftEntry - (*HealthResult)(nil), // 16: workflow.plugin.external.iac.HealthResult - (*Diagnostic)(nil), // 17: workflow.plugin.external.iac.Diagnostic - (*PlanDiagnostic)(nil), // 18: workflow.plugin.external.iac.PlanDiagnostic - (*PlanAction)(nil), // 19: workflow.plugin.external.iac.PlanAction - (*IaCPlan)(nil), // 20: workflow.plugin.external.iac.IaCPlan - (*ActionError)(nil), // 21: workflow.plugin.external.iac.ActionError - (*DestroyResult)(nil), // 22: workflow.plugin.external.iac.DestroyResult - (*BootstrapResult)(nil), // 23: workflow.plugin.external.iac.BootstrapResult - (*MigrationRepairRequest)(nil), // 24: workflow.plugin.external.iac.MigrationRepairRequest - (*MigrationRepairResult)(nil), // 25: workflow.plugin.external.iac.MigrationRepairResult - (*InitializeRequest)(nil), // 26: workflow.plugin.external.iac.InitializeRequest - (*InitializeResponse)(nil), // 27: workflow.plugin.external.iac.InitializeResponse - (*NameRequest)(nil), // 28: workflow.plugin.external.iac.NameRequest - (*NameResponse)(nil), // 29: workflow.plugin.external.iac.NameResponse - (*VersionRequest)(nil), // 30: workflow.plugin.external.iac.VersionRequest - (*VersionResponse)(nil), // 31: workflow.plugin.external.iac.VersionResponse - (*CapabilitiesRequest)(nil), // 32: workflow.plugin.external.iac.CapabilitiesRequest - (*CapabilitiesResponse)(nil), // 33: workflow.plugin.external.iac.CapabilitiesResponse - (*PlanRequest)(nil), // 34: workflow.plugin.external.iac.PlanRequest - (*PlanResponse)(nil), // 35: workflow.plugin.external.iac.PlanResponse - (*DestroyRequest)(nil), // 36: workflow.plugin.external.iac.DestroyRequest - (*DestroyResponse)(nil), // 37: workflow.plugin.external.iac.DestroyResponse - (*StatusRequest)(nil), // 38: workflow.plugin.external.iac.StatusRequest - (*StatusResponse)(nil), // 39: workflow.plugin.external.iac.StatusResponse - (*ImportRequest)(nil), // 40: workflow.plugin.external.iac.ImportRequest - (*ImportResponse)(nil), // 41: workflow.plugin.external.iac.ImportResponse - (*ResolveSizingRequest)(nil), // 42: workflow.plugin.external.iac.ResolveSizingRequest - (*ResolveSizingResponse)(nil), // 43: workflow.plugin.external.iac.ResolveSizingResponse - (*BootstrapStateBackendRequest)(nil), // 44: workflow.plugin.external.iac.BootstrapStateBackendRequest - (*BootstrapStateBackendResponse)(nil), // 45: workflow.plugin.external.iac.BootstrapStateBackendResponse - (*EnumerateAllRequest)(nil), // 46: workflow.plugin.external.iac.EnumerateAllRequest - (*EnumerateAllResponse)(nil), // 47: workflow.plugin.external.iac.EnumerateAllResponse - (*EnumerateByTagRequest)(nil), // 48: workflow.plugin.external.iac.EnumerateByTagRequest - (*EnumerateByTagResponse)(nil), // 49: workflow.plugin.external.iac.EnumerateByTagResponse - (*DetectDriftRequest)(nil), // 50: workflow.plugin.external.iac.DetectDriftRequest - (*DetectDriftResponse)(nil), // 51: workflow.plugin.external.iac.DetectDriftResponse - (*DetectDriftWithSpecsRequest)(nil), // 52: workflow.plugin.external.iac.DetectDriftWithSpecsRequest - (*DetectDriftWithSpecsResponse)(nil), // 53: workflow.plugin.external.iac.DetectDriftWithSpecsResponse - (*RevokeProviderCredentialRequest)(nil), // 54: workflow.plugin.external.iac.RevokeProviderCredentialRequest - (*RevokeProviderCredentialResponse)(nil), // 55: workflow.plugin.external.iac.RevokeProviderCredentialResponse - (*FinalizeApplyRequest)(nil), // 56: workflow.plugin.external.iac.FinalizeApplyRequest - (*FinalizeApplyResponse)(nil), // 57: workflow.plugin.external.iac.FinalizeApplyResponse - (*RepairDirtyMigrationRequest)(nil), // 58: workflow.plugin.external.iac.RepairDirtyMigrationRequest - (*RepairDirtyMigrationResponse)(nil), // 59: workflow.plugin.external.iac.RepairDirtyMigrationResponse - (*ValidatePlanRequest)(nil), // 60: workflow.plugin.external.iac.ValidatePlanRequest - (*ValidatePlanResponse)(nil), // 61: workflow.plugin.external.iac.ValidatePlanResponse - (*DetectDriftConfigRequest)(nil), // 62: workflow.plugin.external.iac.DetectDriftConfigRequest - (*DetectDriftConfigResponse)(nil), // 63: workflow.plugin.external.iac.DetectDriftConfigResponse - (*CaptureLogsRequest)(nil), // 64: workflow.plugin.external.iac.CaptureLogsRequest - (*LogChunk)(nil), // 65: workflow.plugin.external.iac.LogChunk - (*ResourceCreateRequest)(nil), // 66: workflow.plugin.external.iac.ResourceCreateRequest - (*ResourceCreateResponse)(nil), // 67: workflow.plugin.external.iac.ResourceCreateResponse - (*ResourceReadRequest)(nil), // 68: workflow.plugin.external.iac.ResourceReadRequest - (*ResourceReadResponse)(nil), // 69: workflow.plugin.external.iac.ResourceReadResponse - (*ResourceUpdateRequest)(nil), // 70: workflow.plugin.external.iac.ResourceUpdateRequest - (*ResourceUpdateResponse)(nil), // 71: workflow.plugin.external.iac.ResourceUpdateResponse - (*ResourceDeleteRequest)(nil), // 72: workflow.plugin.external.iac.ResourceDeleteRequest - (*ResourceDeleteResponse)(nil), // 73: workflow.plugin.external.iac.ResourceDeleteResponse - (*ResourceDiffRequest)(nil), // 74: workflow.plugin.external.iac.ResourceDiffRequest - (*ResourceDiffResponse)(nil), // 75: workflow.plugin.external.iac.ResourceDiffResponse - (*ResourceScaleRequest)(nil), // 76: workflow.plugin.external.iac.ResourceScaleRequest - (*ResourceScaleResponse)(nil), // 77: workflow.plugin.external.iac.ResourceScaleResponse - (*ResourceHealthCheckRequest)(nil), // 78: workflow.plugin.external.iac.ResourceHealthCheckRequest - (*ResourceHealthCheckResponse)(nil), // 79: workflow.plugin.external.iac.ResourceHealthCheckResponse - (*SensitiveKeysRequest)(nil), // 80: workflow.plugin.external.iac.SensitiveKeysRequest - (*SensitiveKeysResponse)(nil), // 81: workflow.plugin.external.iac.SensitiveKeysResponse - (*TroubleshootRequest)(nil), // 82: workflow.plugin.external.iac.TroubleshootRequest - (*TroubleshootResponse)(nil), // 83: workflow.plugin.external.iac.TroubleshootResponse - (*IaCState)(nil), // 84: workflow.plugin.external.iac.IaCState - (*ConfigureRequest)(nil), // 85: workflow.plugin.external.iac.ConfigureRequest - (*ConfigureResponse)(nil), // 86: workflow.plugin.external.iac.ConfigureResponse - (*GetStateRequest)(nil), // 87: workflow.plugin.external.iac.GetStateRequest - (*GetStateResponse)(nil), // 88: workflow.plugin.external.iac.GetStateResponse - (*SaveStateRequest)(nil), // 89: workflow.plugin.external.iac.SaveStateRequest - (*SaveStateResponse)(nil), // 90: workflow.plugin.external.iac.SaveStateResponse - (*ListStatesRequest)(nil), // 91: workflow.plugin.external.iac.ListStatesRequest - (*ListStatesResponse)(nil), // 92: workflow.plugin.external.iac.ListStatesResponse - (*DeleteStateRequest)(nil), // 93: workflow.plugin.external.iac.DeleteStateRequest - (*DeleteStateResponse)(nil), // 94: workflow.plugin.external.iac.DeleteStateResponse - (*LockRequest)(nil), // 95: workflow.plugin.external.iac.LockRequest - (*LockResponse)(nil), // 96: workflow.plugin.external.iac.LockResponse - (*UnlockRequest)(nil), // 97: workflow.plugin.external.iac.UnlockRequest - (*UnlockResponse)(nil), // 98: workflow.plugin.external.iac.UnlockResponse - (*ListBackendNamesRequest)(nil), // 99: workflow.plugin.external.iac.ListBackendNamesRequest - (*ListBackendNamesResponse)(nil), // 100: workflow.plugin.external.iac.ListBackendNamesResponse - nil, // 101: workflow.plugin.external.iac.ResourceOutput.SensitiveEntry - nil, // 102: workflow.plugin.external.iac.IaCPlan.InputSnapshotEntry - nil, // 103: workflow.plugin.external.iac.BootstrapResult.EnvVarsEntry - nil, // 104: workflow.plugin.external.iac.MigrationRepairRequest.EnvEntry - nil, // 105: workflow.plugin.external.iac.DetectDriftWithSpecsRequest.SpecsEntry - nil, // 106: workflow.plugin.external.iac.DetectDriftConfigRequest.SpecsEntry - nil, // 107: workflow.plugin.external.iac.ListStatesRequest.FilterEntry - (*timestamppb.Timestamp)(nil), // 108: google.protobuf.Timestamp + (RequirementKind)(0), // 1: workflow.plugin.external.iac.RequirementKind + (RequirementRuntime)(0), // 2: workflow.plugin.external.iac.RequirementRuntime + (TelemetrySignal)(0), // 3: workflow.plugin.external.iac.TelemetrySignal + (ObservabilityBackend)(0), // 4: workflow.plugin.external.iac.ObservabilityBackend + (DeploymentMode)(0), // 5: workflow.plugin.external.iac.DeploymentMode + (PlanDiagnosticSeverity)(0), // 6: workflow.plugin.external.iac.PlanDiagnosticSeverity + (ActionStatus)(0), // 7: workflow.plugin.external.iac.ActionStatus + (LogCaptureType)(0), // 8: workflow.plugin.external.iac.LogCaptureType + (*ResourceSpec)(nil), // 9: workflow.plugin.external.iac.ResourceSpec + (*ResourceRef)(nil), // 10: workflow.plugin.external.iac.ResourceRef + (*ResourceHints)(nil), // 11: workflow.plugin.external.iac.ResourceHints + (*ProviderSizing)(nil), // 12: workflow.plugin.external.iac.ProviderSizing + (*IaCCapabilityDeclaration)(nil), // 13: workflow.plugin.external.iac.IaCCapabilityDeclaration + (*ResourceState)(nil), // 14: workflow.plugin.external.iac.ResourceState + (*ResourceOutput)(nil), // 15: workflow.plugin.external.iac.ResourceOutput + (*ResourceStatus)(nil), // 16: workflow.plugin.external.iac.ResourceStatus + (*FieldChange)(nil), // 17: workflow.plugin.external.iac.FieldChange + (*DiffResult)(nil), // 18: workflow.plugin.external.iac.DiffResult + (*IaCRequirement)(nil), // 19: workflow.plugin.external.iac.IaCRequirement + (*DiscoverRequirementsRequest)(nil), // 20: workflow.plugin.external.iac.DiscoverRequirementsRequest + (*RequirementContext)(nil), // 21: workflow.plugin.external.iac.RequirementContext + (*ModuleRef)(nil), // 22: workflow.plugin.external.iac.ModuleRef + (*DiscoverRequirementsResponse)(nil), // 23: workflow.plugin.external.iac.DiscoverRequirementsResponse + (*MapRequirementsRequest)(nil), // 24: workflow.plugin.external.iac.MapRequirementsRequest + (*DerivedModuleSpec)(nil), // 25: workflow.plugin.external.iac.DerivedModuleSpec + (*RequirementDiagnostic)(nil), // 26: workflow.plugin.external.iac.RequirementDiagnostic + (*RequirementNote)(nil), // 27: workflow.plugin.external.iac.RequirementNote + (*MapRequirementsResponse)(nil), // 28: workflow.plugin.external.iac.MapRequirementsResponse + (*DriftResult)(nil), // 29: workflow.plugin.external.iac.DriftResult + (*DriftEntry)(nil), // 30: workflow.plugin.external.iac.DriftEntry + (*HealthResult)(nil), // 31: workflow.plugin.external.iac.HealthResult + (*Diagnostic)(nil), // 32: workflow.plugin.external.iac.Diagnostic + (*PlanDiagnostic)(nil), // 33: workflow.plugin.external.iac.PlanDiagnostic + (*PlanAction)(nil), // 34: workflow.plugin.external.iac.PlanAction + (*IaCPlan)(nil), // 35: workflow.plugin.external.iac.IaCPlan + (*ActionError)(nil), // 36: workflow.plugin.external.iac.ActionError + (*DestroyResult)(nil), // 37: workflow.plugin.external.iac.DestroyResult + (*BootstrapResult)(nil), // 38: workflow.plugin.external.iac.BootstrapResult + (*MigrationRepairRequest)(nil), // 39: workflow.plugin.external.iac.MigrationRepairRequest + (*MigrationRepairResult)(nil), // 40: workflow.plugin.external.iac.MigrationRepairResult + (*InitializeRequest)(nil), // 41: workflow.plugin.external.iac.InitializeRequest + (*InitializeResponse)(nil), // 42: workflow.plugin.external.iac.InitializeResponse + (*NameRequest)(nil), // 43: workflow.plugin.external.iac.NameRequest + (*NameResponse)(nil), // 44: workflow.plugin.external.iac.NameResponse + (*VersionRequest)(nil), // 45: workflow.plugin.external.iac.VersionRequest + (*VersionResponse)(nil), // 46: workflow.plugin.external.iac.VersionResponse + (*CapabilitiesRequest)(nil), // 47: workflow.plugin.external.iac.CapabilitiesRequest + (*CapabilitiesResponse)(nil), // 48: workflow.plugin.external.iac.CapabilitiesResponse + (*PlanRequest)(nil), // 49: workflow.plugin.external.iac.PlanRequest + (*PlanResponse)(nil), // 50: workflow.plugin.external.iac.PlanResponse + (*DestroyRequest)(nil), // 51: workflow.plugin.external.iac.DestroyRequest + (*DestroyResponse)(nil), // 52: workflow.plugin.external.iac.DestroyResponse + (*StatusRequest)(nil), // 53: workflow.plugin.external.iac.StatusRequest + (*StatusResponse)(nil), // 54: workflow.plugin.external.iac.StatusResponse + (*ImportRequest)(nil), // 55: workflow.plugin.external.iac.ImportRequest + (*ImportResponse)(nil), // 56: workflow.plugin.external.iac.ImportResponse + (*ResolveSizingRequest)(nil), // 57: workflow.plugin.external.iac.ResolveSizingRequest + (*ResolveSizingResponse)(nil), // 58: workflow.plugin.external.iac.ResolveSizingResponse + (*BootstrapStateBackendRequest)(nil), // 59: workflow.plugin.external.iac.BootstrapStateBackendRequest + (*BootstrapStateBackendResponse)(nil), // 60: workflow.plugin.external.iac.BootstrapStateBackendResponse + (*EnumerateAllRequest)(nil), // 61: workflow.plugin.external.iac.EnumerateAllRequest + (*EnumerateAllResponse)(nil), // 62: workflow.plugin.external.iac.EnumerateAllResponse + (*EnumerateByTagRequest)(nil), // 63: workflow.plugin.external.iac.EnumerateByTagRequest + (*EnumerateByTagResponse)(nil), // 64: workflow.plugin.external.iac.EnumerateByTagResponse + (*DetectDriftRequest)(nil), // 65: workflow.plugin.external.iac.DetectDriftRequest + (*DetectDriftResponse)(nil), // 66: workflow.plugin.external.iac.DetectDriftResponse + (*DetectDriftWithSpecsRequest)(nil), // 67: workflow.plugin.external.iac.DetectDriftWithSpecsRequest + (*DetectDriftWithSpecsResponse)(nil), // 68: workflow.plugin.external.iac.DetectDriftWithSpecsResponse + (*RevokeProviderCredentialRequest)(nil), // 69: workflow.plugin.external.iac.RevokeProviderCredentialRequest + (*RevokeProviderCredentialResponse)(nil), // 70: workflow.plugin.external.iac.RevokeProviderCredentialResponse + (*FinalizeApplyRequest)(nil), // 71: workflow.plugin.external.iac.FinalizeApplyRequest + (*FinalizeApplyResponse)(nil), // 72: workflow.plugin.external.iac.FinalizeApplyResponse + (*RepairDirtyMigrationRequest)(nil), // 73: workflow.plugin.external.iac.RepairDirtyMigrationRequest + (*RepairDirtyMigrationResponse)(nil), // 74: workflow.plugin.external.iac.RepairDirtyMigrationResponse + (*ValidatePlanRequest)(nil), // 75: workflow.plugin.external.iac.ValidatePlanRequest + (*ValidatePlanResponse)(nil), // 76: workflow.plugin.external.iac.ValidatePlanResponse + (*DetectDriftConfigRequest)(nil), // 77: workflow.plugin.external.iac.DetectDriftConfigRequest + (*DetectDriftConfigResponse)(nil), // 78: workflow.plugin.external.iac.DetectDriftConfigResponse + (*CaptureLogsRequest)(nil), // 79: workflow.plugin.external.iac.CaptureLogsRequest + (*LogChunk)(nil), // 80: workflow.plugin.external.iac.LogChunk + (*ResourceCreateRequest)(nil), // 81: workflow.plugin.external.iac.ResourceCreateRequest + (*ResourceCreateResponse)(nil), // 82: workflow.plugin.external.iac.ResourceCreateResponse + (*ResourceReadRequest)(nil), // 83: workflow.plugin.external.iac.ResourceReadRequest + (*ResourceReadResponse)(nil), // 84: workflow.plugin.external.iac.ResourceReadResponse + (*ResourceUpdateRequest)(nil), // 85: workflow.plugin.external.iac.ResourceUpdateRequest + (*ResourceUpdateResponse)(nil), // 86: workflow.plugin.external.iac.ResourceUpdateResponse + (*ResourceDeleteRequest)(nil), // 87: workflow.plugin.external.iac.ResourceDeleteRequest + (*ResourceDeleteResponse)(nil), // 88: workflow.plugin.external.iac.ResourceDeleteResponse + (*ResourceDiffRequest)(nil), // 89: workflow.plugin.external.iac.ResourceDiffRequest + (*ResourceDiffResponse)(nil), // 90: workflow.plugin.external.iac.ResourceDiffResponse + (*ResourceScaleRequest)(nil), // 91: workflow.plugin.external.iac.ResourceScaleRequest + (*ResourceScaleResponse)(nil), // 92: workflow.plugin.external.iac.ResourceScaleResponse + (*ResourceHealthCheckRequest)(nil), // 93: workflow.plugin.external.iac.ResourceHealthCheckRequest + (*ResourceHealthCheckResponse)(nil), // 94: workflow.plugin.external.iac.ResourceHealthCheckResponse + (*SensitiveKeysRequest)(nil), // 95: workflow.plugin.external.iac.SensitiveKeysRequest + (*SensitiveKeysResponse)(nil), // 96: workflow.plugin.external.iac.SensitiveKeysResponse + (*TroubleshootRequest)(nil), // 97: workflow.plugin.external.iac.TroubleshootRequest + (*TroubleshootResponse)(nil), // 98: workflow.plugin.external.iac.TroubleshootResponse + (*IaCState)(nil), // 99: workflow.plugin.external.iac.IaCState + (*ConfigureRequest)(nil), // 100: workflow.plugin.external.iac.ConfigureRequest + (*ConfigureResponse)(nil), // 101: workflow.plugin.external.iac.ConfigureResponse + (*GetStateRequest)(nil), // 102: workflow.plugin.external.iac.GetStateRequest + (*GetStateResponse)(nil), // 103: workflow.plugin.external.iac.GetStateResponse + (*SaveStateRequest)(nil), // 104: workflow.plugin.external.iac.SaveStateRequest + (*SaveStateResponse)(nil), // 105: workflow.plugin.external.iac.SaveStateResponse + (*ListStatesRequest)(nil), // 106: workflow.plugin.external.iac.ListStatesRequest + (*ListStatesResponse)(nil), // 107: workflow.plugin.external.iac.ListStatesResponse + (*DeleteStateRequest)(nil), // 108: workflow.plugin.external.iac.DeleteStateRequest + (*DeleteStateResponse)(nil), // 109: workflow.plugin.external.iac.DeleteStateResponse + (*LockRequest)(nil), // 110: workflow.plugin.external.iac.LockRequest + (*LockResponse)(nil), // 111: workflow.plugin.external.iac.LockResponse + (*UnlockRequest)(nil), // 112: workflow.plugin.external.iac.UnlockRequest + (*UnlockResponse)(nil), // 113: workflow.plugin.external.iac.UnlockResponse + (*ListBackendNamesRequest)(nil), // 114: workflow.plugin.external.iac.ListBackendNamesRequest + (*ListBackendNamesResponse)(nil), // 115: workflow.plugin.external.iac.ListBackendNamesResponse + nil, // 116: workflow.plugin.external.iac.ResourceOutput.SensitiveEntry + nil, // 117: workflow.plugin.external.iac.IaCPlan.InputSnapshotEntry + nil, // 118: workflow.plugin.external.iac.BootstrapResult.EnvVarsEntry + nil, // 119: workflow.plugin.external.iac.MigrationRepairRequest.EnvEntry + nil, // 120: workflow.plugin.external.iac.DetectDriftWithSpecsRequest.SpecsEntry + nil, // 121: workflow.plugin.external.iac.DetectDriftConfigRequest.SpecsEntry + nil, // 122: workflow.plugin.external.iac.ListStatesRequest.FilterEntry + (*timestamppb.Timestamp)(nil), // 123: google.protobuf.Timestamp } var file_iac_proto_depIdxs = []int32{ - 6, // 0: workflow.plugin.external.iac.ResourceSpec.hints:type_name -> workflow.plugin.external.iac.ResourceHints - 108, // 1: workflow.plugin.external.iac.ResourceState.created_at:type_name -> google.protobuf.Timestamp - 108, // 2: workflow.plugin.external.iac.ResourceState.updated_at:type_name -> google.protobuf.Timestamp - 108, // 3: workflow.plugin.external.iac.ResourceState.last_drift_check:type_name -> google.protobuf.Timestamp - 101, // 4: workflow.plugin.external.iac.ResourceOutput.sensitive:type_name -> workflow.plugin.external.iac.ResourceOutput.SensitiveEntry - 12, // 5: workflow.plugin.external.iac.DiffResult.changes:type_name -> workflow.plugin.external.iac.FieldChange - 0, // 6: workflow.plugin.external.iac.DriftResult.class:type_name -> workflow.plugin.external.iac.DriftClass - 108, // 7: workflow.plugin.external.iac.Diagnostic.at:type_name -> google.protobuf.Timestamp - 1, // 8: workflow.plugin.external.iac.PlanDiagnostic.severity:type_name -> workflow.plugin.external.iac.PlanDiagnosticSeverity - 4, // 9: workflow.plugin.external.iac.PlanAction.resource:type_name -> workflow.plugin.external.iac.ResourceSpec - 9, // 10: workflow.plugin.external.iac.PlanAction.current:type_name -> workflow.plugin.external.iac.ResourceState - 12, // 11: workflow.plugin.external.iac.PlanAction.changes:type_name -> workflow.plugin.external.iac.FieldChange - 19, // 12: workflow.plugin.external.iac.IaCPlan.actions:type_name -> workflow.plugin.external.iac.PlanAction - 108, // 13: workflow.plugin.external.iac.IaCPlan.created_at:type_name -> google.protobuf.Timestamp - 102, // 14: workflow.plugin.external.iac.IaCPlan.input_snapshot:type_name -> workflow.plugin.external.iac.IaCPlan.InputSnapshotEntry - 21, // 15: workflow.plugin.external.iac.DestroyResult.errors:type_name -> workflow.plugin.external.iac.ActionError - 103, // 16: workflow.plugin.external.iac.BootstrapResult.env_vars:type_name -> workflow.plugin.external.iac.BootstrapResult.EnvVarsEntry - 104, // 17: workflow.plugin.external.iac.MigrationRepairRequest.env:type_name -> workflow.plugin.external.iac.MigrationRepairRequest.EnvEntry - 17, // 18: workflow.plugin.external.iac.MigrationRepairResult.diagnostics:type_name -> workflow.plugin.external.iac.Diagnostic - 8, // 19: workflow.plugin.external.iac.CapabilitiesResponse.capabilities:type_name -> workflow.plugin.external.iac.IaCCapabilityDeclaration - 4, // 20: workflow.plugin.external.iac.PlanRequest.desired:type_name -> workflow.plugin.external.iac.ResourceSpec - 9, // 21: workflow.plugin.external.iac.PlanRequest.current:type_name -> workflow.plugin.external.iac.ResourceState - 20, // 22: workflow.plugin.external.iac.PlanResponse.plan:type_name -> workflow.plugin.external.iac.IaCPlan - 5, // 23: workflow.plugin.external.iac.DestroyRequest.refs:type_name -> workflow.plugin.external.iac.ResourceRef - 22, // 24: workflow.plugin.external.iac.DestroyResponse.result:type_name -> workflow.plugin.external.iac.DestroyResult - 5, // 25: workflow.plugin.external.iac.StatusRequest.refs:type_name -> workflow.plugin.external.iac.ResourceRef - 11, // 26: workflow.plugin.external.iac.StatusResponse.statuses:type_name -> workflow.plugin.external.iac.ResourceStatus - 9, // 27: workflow.plugin.external.iac.ImportResponse.state:type_name -> workflow.plugin.external.iac.ResourceState - 6, // 28: workflow.plugin.external.iac.ResolveSizingRequest.hints:type_name -> workflow.plugin.external.iac.ResourceHints - 7, // 29: workflow.plugin.external.iac.ResolveSizingResponse.sizing:type_name -> workflow.plugin.external.iac.ProviderSizing - 23, // 30: workflow.plugin.external.iac.BootstrapStateBackendResponse.result:type_name -> workflow.plugin.external.iac.BootstrapResult - 10, // 31: workflow.plugin.external.iac.EnumerateAllResponse.outputs:type_name -> workflow.plugin.external.iac.ResourceOutput - 5, // 32: workflow.plugin.external.iac.EnumerateByTagResponse.refs:type_name -> workflow.plugin.external.iac.ResourceRef - 5, // 33: workflow.plugin.external.iac.DetectDriftRequest.refs:type_name -> workflow.plugin.external.iac.ResourceRef - 14, // 34: workflow.plugin.external.iac.DetectDriftResponse.drifts:type_name -> workflow.plugin.external.iac.DriftResult - 5, // 35: workflow.plugin.external.iac.DetectDriftWithSpecsRequest.refs:type_name -> workflow.plugin.external.iac.ResourceRef - 105, // 36: workflow.plugin.external.iac.DetectDriftWithSpecsRequest.specs:type_name -> workflow.plugin.external.iac.DetectDriftWithSpecsRequest.SpecsEntry - 14, // 37: workflow.plugin.external.iac.DetectDriftWithSpecsResponse.drifts:type_name -> workflow.plugin.external.iac.DriftResult - 21, // 38: workflow.plugin.external.iac.FinalizeApplyResponse.errors:type_name -> workflow.plugin.external.iac.ActionError - 24, // 39: workflow.plugin.external.iac.RepairDirtyMigrationRequest.request:type_name -> workflow.plugin.external.iac.MigrationRepairRequest - 25, // 40: workflow.plugin.external.iac.RepairDirtyMigrationResponse.result:type_name -> workflow.plugin.external.iac.MigrationRepairResult - 20, // 41: workflow.plugin.external.iac.ValidatePlanRequest.plan:type_name -> workflow.plugin.external.iac.IaCPlan - 18, // 42: workflow.plugin.external.iac.ValidatePlanResponse.diagnostics:type_name -> workflow.plugin.external.iac.PlanDiagnostic - 5, // 43: workflow.plugin.external.iac.DetectDriftConfigRequest.refs:type_name -> workflow.plugin.external.iac.ResourceRef - 106, // 44: workflow.plugin.external.iac.DetectDriftConfigRequest.specs:type_name -> workflow.plugin.external.iac.DetectDriftConfigRequest.SpecsEntry - 14, // 45: workflow.plugin.external.iac.DetectDriftConfigResponse.drifts:type_name -> workflow.plugin.external.iac.DriftResult - 3, // 46: workflow.plugin.external.iac.CaptureLogsRequest.log_type:type_name -> workflow.plugin.external.iac.LogCaptureType - 4, // 47: workflow.plugin.external.iac.ResourceCreateRequest.spec:type_name -> workflow.plugin.external.iac.ResourceSpec - 10, // 48: workflow.plugin.external.iac.ResourceCreateResponse.output:type_name -> workflow.plugin.external.iac.ResourceOutput - 5, // 49: workflow.plugin.external.iac.ResourceReadRequest.ref:type_name -> workflow.plugin.external.iac.ResourceRef - 10, // 50: workflow.plugin.external.iac.ResourceReadResponse.output:type_name -> workflow.plugin.external.iac.ResourceOutput - 5, // 51: workflow.plugin.external.iac.ResourceUpdateRequest.ref:type_name -> workflow.plugin.external.iac.ResourceRef - 4, // 52: workflow.plugin.external.iac.ResourceUpdateRequest.spec:type_name -> workflow.plugin.external.iac.ResourceSpec - 10, // 53: workflow.plugin.external.iac.ResourceUpdateResponse.output:type_name -> workflow.plugin.external.iac.ResourceOutput - 5, // 54: workflow.plugin.external.iac.ResourceDeleteRequest.ref:type_name -> workflow.plugin.external.iac.ResourceRef - 4, // 55: workflow.plugin.external.iac.ResourceDiffRequest.desired:type_name -> workflow.plugin.external.iac.ResourceSpec - 10, // 56: workflow.plugin.external.iac.ResourceDiffRequest.current:type_name -> workflow.plugin.external.iac.ResourceOutput - 13, // 57: workflow.plugin.external.iac.ResourceDiffResponse.result:type_name -> workflow.plugin.external.iac.DiffResult - 5, // 58: workflow.plugin.external.iac.ResourceScaleRequest.ref:type_name -> workflow.plugin.external.iac.ResourceRef - 10, // 59: workflow.plugin.external.iac.ResourceScaleResponse.output:type_name -> workflow.plugin.external.iac.ResourceOutput - 5, // 60: workflow.plugin.external.iac.ResourceHealthCheckRequest.ref:type_name -> workflow.plugin.external.iac.ResourceRef - 16, // 61: workflow.plugin.external.iac.ResourceHealthCheckResponse.result:type_name -> workflow.plugin.external.iac.HealthResult - 5, // 62: workflow.plugin.external.iac.TroubleshootRequest.ref:type_name -> workflow.plugin.external.iac.ResourceRef - 17, // 63: workflow.plugin.external.iac.TroubleshootResponse.diagnostics:type_name -> workflow.plugin.external.iac.Diagnostic - 84, // 64: workflow.plugin.external.iac.GetStateResponse.state:type_name -> workflow.plugin.external.iac.IaCState - 84, // 65: workflow.plugin.external.iac.SaveStateRequest.state:type_name -> workflow.plugin.external.iac.IaCState - 107, // 66: workflow.plugin.external.iac.ListStatesRequest.filter:type_name -> workflow.plugin.external.iac.ListStatesRequest.FilterEntry - 84, // 67: workflow.plugin.external.iac.ListStatesResponse.states:type_name -> workflow.plugin.external.iac.IaCState - 4, // 68: workflow.plugin.external.iac.DetectDriftWithSpecsRequest.SpecsEntry.value:type_name -> workflow.plugin.external.iac.ResourceSpec - 4, // 69: workflow.plugin.external.iac.DetectDriftConfigRequest.SpecsEntry.value:type_name -> workflow.plugin.external.iac.ResourceSpec - 26, // 70: workflow.plugin.external.iac.IaCProviderRequired.Initialize:input_type -> workflow.plugin.external.iac.InitializeRequest - 28, // 71: workflow.plugin.external.iac.IaCProviderRequired.Name:input_type -> workflow.plugin.external.iac.NameRequest - 30, // 72: workflow.plugin.external.iac.IaCProviderRequired.Version:input_type -> workflow.plugin.external.iac.VersionRequest - 32, // 73: workflow.plugin.external.iac.IaCProviderRequired.Capabilities:input_type -> workflow.plugin.external.iac.CapabilitiesRequest - 34, // 74: workflow.plugin.external.iac.IaCProviderRequired.Plan:input_type -> workflow.plugin.external.iac.PlanRequest - 36, // 75: workflow.plugin.external.iac.IaCProviderRequired.Destroy:input_type -> workflow.plugin.external.iac.DestroyRequest - 38, // 76: workflow.plugin.external.iac.IaCProviderRequired.Status:input_type -> workflow.plugin.external.iac.StatusRequest - 40, // 77: workflow.plugin.external.iac.IaCProviderRequired.Import:input_type -> workflow.plugin.external.iac.ImportRequest - 42, // 78: workflow.plugin.external.iac.IaCProviderRequired.ResolveSizing:input_type -> workflow.plugin.external.iac.ResolveSizingRequest - 44, // 79: workflow.plugin.external.iac.IaCProviderRequired.BootstrapStateBackend:input_type -> workflow.plugin.external.iac.BootstrapStateBackendRequest - 46, // 80: workflow.plugin.external.iac.IaCProviderEnumerator.EnumerateAll:input_type -> workflow.plugin.external.iac.EnumerateAllRequest - 48, // 81: workflow.plugin.external.iac.IaCProviderEnumerator.EnumerateByTag:input_type -> workflow.plugin.external.iac.EnumerateByTagRequest - 50, // 82: workflow.plugin.external.iac.IaCProviderDriftDetector.DetectDrift:input_type -> workflow.plugin.external.iac.DetectDriftRequest - 52, // 83: workflow.plugin.external.iac.IaCProviderDriftDetector.DetectDriftWithSpecs:input_type -> workflow.plugin.external.iac.DetectDriftWithSpecsRequest - 54, // 84: workflow.plugin.external.iac.IaCProviderCredentialRevoker.RevokeProviderCredential:input_type -> workflow.plugin.external.iac.RevokeProviderCredentialRequest - 56, // 85: workflow.plugin.external.iac.IaCProviderFinalizer.FinalizeApply:input_type -> workflow.plugin.external.iac.FinalizeApplyRequest - 58, // 86: workflow.plugin.external.iac.IaCProviderMigrationRepairer.RepairDirtyMigration:input_type -> workflow.plugin.external.iac.RepairDirtyMigrationRequest - 60, // 87: workflow.plugin.external.iac.IaCProviderValidator.ValidatePlan:input_type -> workflow.plugin.external.iac.ValidatePlanRequest - 62, // 88: workflow.plugin.external.iac.IaCProviderDriftConfigDetector.DetectDriftConfig:input_type -> workflow.plugin.external.iac.DetectDriftConfigRequest - 64, // 89: workflow.plugin.external.iac.IaCProviderLogCapture.CaptureLogs:input_type -> workflow.plugin.external.iac.CaptureLogsRequest - 66, // 90: workflow.plugin.external.iac.ResourceDriver.Create:input_type -> workflow.plugin.external.iac.ResourceCreateRequest - 68, // 91: workflow.plugin.external.iac.ResourceDriver.Read:input_type -> workflow.plugin.external.iac.ResourceReadRequest - 70, // 92: workflow.plugin.external.iac.ResourceDriver.Update:input_type -> workflow.plugin.external.iac.ResourceUpdateRequest - 72, // 93: workflow.plugin.external.iac.ResourceDriver.Delete:input_type -> workflow.plugin.external.iac.ResourceDeleteRequest - 74, // 94: workflow.plugin.external.iac.ResourceDriver.Diff:input_type -> workflow.plugin.external.iac.ResourceDiffRequest - 76, // 95: workflow.plugin.external.iac.ResourceDriver.Scale:input_type -> workflow.plugin.external.iac.ResourceScaleRequest - 78, // 96: workflow.plugin.external.iac.ResourceDriver.HealthCheck:input_type -> workflow.plugin.external.iac.ResourceHealthCheckRequest - 80, // 97: workflow.plugin.external.iac.ResourceDriver.SensitiveKeys:input_type -> workflow.plugin.external.iac.SensitiveKeysRequest - 82, // 98: workflow.plugin.external.iac.ResourceDriver.Troubleshoot:input_type -> workflow.plugin.external.iac.TroubleshootRequest - 85, // 99: workflow.plugin.external.iac.IaCStateBackend.Configure:input_type -> workflow.plugin.external.iac.ConfigureRequest - 87, // 100: workflow.plugin.external.iac.IaCStateBackend.GetState:input_type -> workflow.plugin.external.iac.GetStateRequest - 89, // 101: workflow.plugin.external.iac.IaCStateBackend.SaveState:input_type -> workflow.plugin.external.iac.SaveStateRequest - 91, // 102: workflow.plugin.external.iac.IaCStateBackend.ListStates:input_type -> workflow.plugin.external.iac.ListStatesRequest - 93, // 103: workflow.plugin.external.iac.IaCStateBackend.DeleteState:input_type -> workflow.plugin.external.iac.DeleteStateRequest - 95, // 104: workflow.plugin.external.iac.IaCStateBackend.Lock:input_type -> workflow.plugin.external.iac.LockRequest - 97, // 105: workflow.plugin.external.iac.IaCStateBackend.Unlock:input_type -> workflow.plugin.external.iac.UnlockRequest - 99, // 106: workflow.plugin.external.iac.IaCStateBackend.ListBackendNames:input_type -> workflow.plugin.external.iac.ListBackendNamesRequest - 27, // 107: workflow.plugin.external.iac.IaCProviderRequired.Initialize:output_type -> workflow.plugin.external.iac.InitializeResponse - 29, // 108: workflow.plugin.external.iac.IaCProviderRequired.Name:output_type -> workflow.plugin.external.iac.NameResponse - 31, // 109: workflow.plugin.external.iac.IaCProviderRequired.Version:output_type -> workflow.plugin.external.iac.VersionResponse - 33, // 110: workflow.plugin.external.iac.IaCProviderRequired.Capabilities:output_type -> workflow.plugin.external.iac.CapabilitiesResponse - 35, // 111: workflow.plugin.external.iac.IaCProviderRequired.Plan:output_type -> workflow.plugin.external.iac.PlanResponse - 37, // 112: workflow.plugin.external.iac.IaCProviderRequired.Destroy:output_type -> workflow.plugin.external.iac.DestroyResponse - 39, // 113: workflow.plugin.external.iac.IaCProviderRequired.Status:output_type -> workflow.plugin.external.iac.StatusResponse - 41, // 114: workflow.plugin.external.iac.IaCProviderRequired.Import:output_type -> workflow.plugin.external.iac.ImportResponse - 43, // 115: workflow.plugin.external.iac.IaCProviderRequired.ResolveSizing:output_type -> workflow.plugin.external.iac.ResolveSizingResponse - 45, // 116: workflow.plugin.external.iac.IaCProviderRequired.BootstrapStateBackend:output_type -> workflow.plugin.external.iac.BootstrapStateBackendResponse - 47, // 117: workflow.plugin.external.iac.IaCProviderEnumerator.EnumerateAll:output_type -> workflow.plugin.external.iac.EnumerateAllResponse - 49, // 118: workflow.plugin.external.iac.IaCProviderEnumerator.EnumerateByTag:output_type -> workflow.plugin.external.iac.EnumerateByTagResponse - 51, // 119: workflow.plugin.external.iac.IaCProviderDriftDetector.DetectDrift:output_type -> workflow.plugin.external.iac.DetectDriftResponse - 53, // 120: workflow.plugin.external.iac.IaCProviderDriftDetector.DetectDriftWithSpecs:output_type -> workflow.plugin.external.iac.DetectDriftWithSpecsResponse - 55, // 121: workflow.plugin.external.iac.IaCProviderCredentialRevoker.RevokeProviderCredential:output_type -> workflow.plugin.external.iac.RevokeProviderCredentialResponse - 57, // 122: workflow.plugin.external.iac.IaCProviderFinalizer.FinalizeApply:output_type -> workflow.plugin.external.iac.FinalizeApplyResponse - 59, // 123: workflow.plugin.external.iac.IaCProviderMigrationRepairer.RepairDirtyMigration:output_type -> workflow.plugin.external.iac.RepairDirtyMigrationResponse - 61, // 124: workflow.plugin.external.iac.IaCProviderValidator.ValidatePlan:output_type -> workflow.plugin.external.iac.ValidatePlanResponse - 63, // 125: workflow.plugin.external.iac.IaCProviderDriftConfigDetector.DetectDriftConfig:output_type -> workflow.plugin.external.iac.DetectDriftConfigResponse - 65, // 126: workflow.plugin.external.iac.IaCProviderLogCapture.CaptureLogs:output_type -> workflow.plugin.external.iac.LogChunk - 67, // 127: workflow.plugin.external.iac.ResourceDriver.Create:output_type -> workflow.plugin.external.iac.ResourceCreateResponse - 69, // 128: workflow.plugin.external.iac.ResourceDriver.Read:output_type -> workflow.plugin.external.iac.ResourceReadResponse - 71, // 129: workflow.plugin.external.iac.ResourceDriver.Update:output_type -> workflow.plugin.external.iac.ResourceUpdateResponse - 73, // 130: workflow.plugin.external.iac.ResourceDriver.Delete:output_type -> workflow.plugin.external.iac.ResourceDeleteResponse - 75, // 131: workflow.plugin.external.iac.ResourceDriver.Diff:output_type -> workflow.plugin.external.iac.ResourceDiffResponse - 77, // 132: workflow.plugin.external.iac.ResourceDriver.Scale:output_type -> workflow.plugin.external.iac.ResourceScaleResponse - 79, // 133: workflow.plugin.external.iac.ResourceDriver.HealthCheck:output_type -> workflow.plugin.external.iac.ResourceHealthCheckResponse - 81, // 134: workflow.plugin.external.iac.ResourceDriver.SensitiveKeys:output_type -> workflow.plugin.external.iac.SensitiveKeysResponse - 83, // 135: workflow.plugin.external.iac.ResourceDriver.Troubleshoot:output_type -> workflow.plugin.external.iac.TroubleshootResponse - 86, // 136: workflow.plugin.external.iac.IaCStateBackend.Configure:output_type -> workflow.plugin.external.iac.ConfigureResponse - 88, // 137: workflow.plugin.external.iac.IaCStateBackend.GetState:output_type -> workflow.plugin.external.iac.GetStateResponse - 90, // 138: workflow.plugin.external.iac.IaCStateBackend.SaveState:output_type -> workflow.plugin.external.iac.SaveStateResponse - 92, // 139: workflow.plugin.external.iac.IaCStateBackend.ListStates:output_type -> workflow.plugin.external.iac.ListStatesResponse - 94, // 140: workflow.plugin.external.iac.IaCStateBackend.DeleteState:output_type -> workflow.plugin.external.iac.DeleteStateResponse - 96, // 141: workflow.plugin.external.iac.IaCStateBackend.Lock:output_type -> workflow.plugin.external.iac.LockResponse - 98, // 142: workflow.plugin.external.iac.IaCStateBackend.Unlock:output_type -> workflow.plugin.external.iac.UnlockResponse - 100, // 143: workflow.plugin.external.iac.IaCStateBackend.ListBackendNames:output_type -> workflow.plugin.external.iac.ListBackendNamesResponse - 107, // [107:144] is the sub-list for method output_type - 70, // [70:107] is the sub-list for method input_type - 70, // [70:70] is the sub-list for extension type_name - 70, // [70:70] is the sub-list for extension extendee - 0, // [0:70] is the sub-list for field type_name + 11, // 0: workflow.plugin.external.iac.ResourceSpec.hints:type_name -> workflow.plugin.external.iac.ResourceHints + 123, // 1: workflow.plugin.external.iac.ResourceState.created_at:type_name -> google.protobuf.Timestamp + 123, // 2: workflow.plugin.external.iac.ResourceState.updated_at:type_name -> google.protobuf.Timestamp + 123, // 3: workflow.plugin.external.iac.ResourceState.last_drift_check:type_name -> google.protobuf.Timestamp + 116, // 4: workflow.plugin.external.iac.ResourceOutput.sensitive:type_name -> workflow.plugin.external.iac.ResourceOutput.SensitiveEntry + 17, // 5: workflow.plugin.external.iac.DiffResult.changes:type_name -> workflow.plugin.external.iac.FieldChange + 1, // 6: workflow.plugin.external.iac.IaCRequirement.kind:type_name -> workflow.plugin.external.iac.RequirementKind + 2, // 7: workflow.plugin.external.iac.IaCRequirement.runtimes:type_name -> workflow.plugin.external.iac.RequirementRuntime + 3, // 8: workflow.plugin.external.iac.IaCRequirement.telemetry_signals:type_name -> workflow.plugin.external.iac.TelemetrySignal + 4, // 9: workflow.plugin.external.iac.IaCRequirement.observability_backends:type_name -> workflow.plugin.external.iac.ObservabilityBackend + 5, // 10: workflow.plugin.external.iac.IaCRequirement.deployment_modes:type_name -> workflow.plugin.external.iac.DeploymentMode + 21, // 11: workflow.plugin.external.iac.DiscoverRequirementsRequest.context:type_name -> workflow.plugin.external.iac.RequirementContext + 22, // 12: workflow.plugin.external.iac.RequirementContext.modules:type_name -> workflow.plugin.external.iac.ModuleRef + 19, // 13: workflow.plugin.external.iac.DiscoverRequirementsResponse.requirements:type_name -> workflow.plugin.external.iac.IaCRequirement + 2, // 14: workflow.plugin.external.iac.MapRequirementsRequest.runtime:type_name -> workflow.plugin.external.iac.RequirementRuntime + 19, // 15: workflow.plugin.external.iac.MapRequirementsRequest.requirements:type_name -> workflow.plugin.external.iac.IaCRequirement + 26, // 16: workflow.plugin.external.iac.MapRequirementsResponse.rejected:type_name -> workflow.plugin.external.iac.RequirementDiagnostic + 25, // 17: workflow.plugin.external.iac.MapRequirementsResponse.modules:type_name -> workflow.plugin.external.iac.DerivedModuleSpec + 27, // 18: workflow.plugin.external.iac.MapRequirementsResponse.notes:type_name -> workflow.plugin.external.iac.RequirementNote + 0, // 19: workflow.plugin.external.iac.DriftResult.class:type_name -> workflow.plugin.external.iac.DriftClass + 123, // 20: workflow.plugin.external.iac.Diagnostic.at:type_name -> google.protobuf.Timestamp + 6, // 21: workflow.plugin.external.iac.PlanDiagnostic.severity:type_name -> workflow.plugin.external.iac.PlanDiagnosticSeverity + 9, // 22: workflow.plugin.external.iac.PlanAction.resource:type_name -> workflow.plugin.external.iac.ResourceSpec + 14, // 23: workflow.plugin.external.iac.PlanAction.current:type_name -> workflow.plugin.external.iac.ResourceState + 17, // 24: workflow.plugin.external.iac.PlanAction.changes:type_name -> workflow.plugin.external.iac.FieldChange + 34, // 25: workflow.plugin.external.iac.IaCPlan.actions:type_name -> workflow.plugin.external.iac.PlanAction + 123, // 26: workflow.plugin.external.iac.IaCPlan.created_at:type_name -> google.protobuf.Timestamp + 117, // 27: workflow.plugin.external.iac.IaCPlan.input_snapshot:type_name -> workflow.plugin.external.iac.IaCPlan.InputSnapshotEntry + 36, // 28: workflow.plugin.external.iac.DestroyResult.errors:type_name -> workflow.plugin.external.iac.ActionError + 118, // 29: workflow.plugin.external.iac.BootstrapResult.env_vars:type_name -> workflow.plugin.external.iac.BootstrapResult.EnvVarsEntry + 119, // 30: workflow.plugin.external.iac.MigrationRepairRequest.env:type_name -> workflow.plugin.external.iac.MigrationRepairRequest.EnvEntry + 32, // 31: workflow.plugin.external.iac.MigrationRepairResult.diagnostics:type_name -> workflow.plugin.external.iac.Diagnostic + 13, // 32: workflow.plugin.external.iac.CapabilitiesResponse.capabilities:type_name -> workflow.plugin.external.iac.IaCCapabilityDeclaration + 9, // 33: workflow.plugin.external.iac.PlanRequest.desired:type_name -> workflow.plugin.external.iac.ResourceSpec + 14, // 34: workflow.plugin.external.iac.PlanRequest.current:type_name -> workflow.plugin.external.iac.ResourceState + 35, // 35: workflow.plugin.external.iac.PlanResponse.plan:type_name -> workflow.plugin.external.iac.IaCPlan + 10, // 36: workflow.plugin.external.iac.DestroyRequest.refs:type_name -> workflow.plugin.external.iac.ResourceRef + 37, // 37: workflow.plugin.external.iac.DestroyResponse.result:type_name -> workflow.plugin.external.iac.DestroyResult + 10, // 38: workflow.plugin.external.iac.StatusRequest.refs:type_name -> workflow.plugin.external.iac.ResourceRef + 16, // 39: workflow.plugin.external.iac.StatusResponse.statuses:type_name -> workflow.plugin.external.iac.ResourceStatus + 14, // 40: workflow.plugin.external.iac.ImportResponse.state:type_name -> workflow.plugin.external.iac.ResourceState + 11, // 41: workflow.plugin.external.iac.ResolveSizingRequest.hints:type_name -> workflow.plugin.external.iac.ResourceHints + 12, // 42: workflow.plugin.external.iac.ResolveSizingResponse.sizing:type_name -> workflow.plugin.external.iac.ProviderSizing + 38, // 43: workflow.plugin.external.iac.BootstrapStateBackendResponse.result:type_name -> workflow.plugin.external.iac.BootstrapResult + 15, // 44: workflow.plugin.external.iac.EnumerateAllResponse.outputs:type_name -> workflow.plugin.external.iac.ResourceOutput + 10, // 45: workflow.plugin.external.iac.EnumerateByTagResponse.refs:type_name -> workflow.plugin.external.iac.ResourceRef + 10, // 46: workflow.plugin.external.iac.DetectDriftRequest.refs:type_name -> workflow.plugin.external.iac.ResourceRef + 29, // 47: workflow.plugin.external.iac.DetectDriftResponse.drifts:type_name -> workflow.plugin.external.iac.DriftResult + 10, // 48: workflow.plugin.external.iac.DetectDriftWithSpecsRequest.refs:type_name -> workflow.plugin.external.iac.ResourceRef + 120, // 49: workflow.plugin.external.iac.DetectDriftWithSpecsRequest.specs:type_name -> workflow.plugin.external.iac.DetectDriftWithSpecsRequest.SpecsEntry + 29, // 50: workflow.plugin.external.iac.DetectDriftWithSpecsResponse.drifts:type_name -> workflow.plugin.external.iac.DriftResult + 36, // 51: workflow.plugin.external.iac.FinalizeApplyResponse.errors:type_name -> workflow.plugin.external.iac.ActionError + 39, // 52: workflow.plugin.external.iac.RepairDirtyMigrationRequest.request:type_name -> workflow.plugin.external.iac.MigrationRepairRequest + 40, // 53: workflow.plugin.external.iac.RepairDirtyMigrationResponse.result:type_name -> workflow.plugin.external.iac.MigrationRepairResult + 35, // 54: workflow.plugin.external.iac.ValidatePlanRequest.plan:type_name -> workflow.plugin.external.iac.IaCPlan + 33, // 55: workflow.plugin.external.iac.ValidatePlanResponse.diagnostics:type_name -> workflow.plugin.external.iac.PlanDiagnostic + 10, // 56: workflow.plugin.external.iac.DetectDriftConfigRequest.refs:type_name -> workflow.plugin.external.iac.ResourceRef + 121, // 57: workflow.plugin.external.iac.DetectDriftConfigRequest.specs:type_name -> workflow.plugin.external.iac.DetectDriftConfigRequest.SpecsEntry + 29, // 58: workflow.plugin.external.iac.DetectDriftConfigResponse.drifts:type_name -> workflow.plugin.external.iac.DriftResult + 8, // 59: workflow.plugin.external.iac.CaptureLogsRequest.log_type:type_name -> workflow.plugin.external.iac.LogCaptureType + 9, // 60: workflow.plugin.external.iac.ResourceCreateRequest.spec:type_name -> workflow.plugin.external.iac.ResourceSpec + 15, // 61: workflow.plugin.external.iac.ResourceCreateResponse.output:type_name -> workflow.plugin.external.iac.ResourceOutput + 10, // 62: workflow.plugin.external.iac.ResourceReadRequest.ref:type_name -> workflow.plugin.external.iac.ResourceRef + 15, // 63: workflow.plugin.external.iac.ResourceReadResponse.output:type_name -> workflow.plugin.external.iac.ResourceOutput + 10, // 64: workflow.plugin.external.iac.ResourceUpdateRequest.ref:type_name -> workflow.plugin.external.iac.ResourceRef + 9, // 65: workflow.plugin.external.iac.ResourceUpdateRequest.spec:type_name -> workflow.plugin.external.iac.ResourceSpec + 15, // 66: workflow.plugin.external.iac.ResourceUpdateResponse.output:type_name -> workflow.plugin.external.iac.ResourceOutput + 10, // 67: workflow.plugin.external.iac.ResourceDeleteRequest.ref:type_name -> workflow.plugin.external.iac.ResourceRef + 9, // 68: workflow.plugin.external.iac.ResourceDiffRequest.desired:type_name -> workflow.plugin.external.iac.ResourceSpec + 15, // 69: workflow.plugin.external.iac.ResourceDiffRequest.current:type_name -> workflow.plugin.external.iac.ResourceOutput + 18, // 70: workflow.plugin.external.iac.ResourceDiffResponse.result:type_name -> workflow.plugin.external.iac.DiffResult + 10, // 71: workflow.plugin.external.iac.ResourceScaleRequest.ref:type_name -> workflow.plugin.external.iac.ResourceRef + 15, // 72: workflow.plugin.external.iac.ResourceScaleResponse.output:type_name -> workflow.plugin.external.iac.ResourceOutput + 10, // 73: workflow.plugin.external.iac.ResourceHealthCheckRequest.ref:type_name -> workflow.plugin.external.iac.ResourceRef + 31, // 74: workflow.plugin.external.iac.ResourceHealthCheckResponse.result:type_name -> workflow.plugin.external.iac.HealthResult + 10, // 75: workflow.plugin.external.iac.TroubleshootRequest.ref:type_name -> workflow.plugin.external.iac.ResourceRef + 32, // 76: workflow.plugin.external.iac.TroubleshootResponse.diagnostics:type_name -> workflow.plugin.external.iac.Diagnostic + 99, // 77: workflow.plugin.external.iac.GetStateResponse.state:type_name -> workflow.plugin.external.iac.IaCState + 99, // 78: workflow.plugin.external.iac.SaveStateRequest.state:type_name -> workflow.plugin.external.iac.IaCState + 122, // 79: workflow.plugin.external.iac.ListStatesRequest.filter:type_name -> workflow.plugin.external.iac.ListStatesRequest.FilterEntry + 99, // 80: workflow.plugin.external.iac.ListStatesResponse.states:type_name -> workflow.plugin.external.iac.IaCState + 9, // 81: workflow.plugin.external.iac.DetectDriftWithSpecsRequest.SpecsEntry.value:type_name -> workflow.plugin.external.iac.ResourceSpec + 9, // 82: workflow.plugin.external.iac.DetectDriftConfigRequest.SpecsEntry.value:type_name -> workflow.plugin.external.iac.ResourceSpec + 41, // 83: workflow.plugin.external.iac.IaCProviderRequired.Initialize:input_type -> workflow.plugin.external.iac.InitializeRequest + 43, // 84: workflow.plugin.external.iac.IaCProviderRequired.Name:input_type -> workflow.plugin.external.iac.NameRequest + 45, // 85: workflow.plugin.external.iac.IaCProviderRequired.Version:input_type -> workflow.plugin.external.iac.VersionRequest + 47, // 86: workflow.plugin.external.iac.IaCProviderRequired.Capabilities:input_type -> workflow.plugin.external.iac.CapabilitiesRequest + 49, // 87: workflow.plugin.external.iac.IaCProviderRequired.Plan:input_type -> workflow.plugin.external.iac.PlanRequest + 51, // 88: workflow.plugin.external.iac.IaCProviderRequired.Destroy:input_type -> workflow.plugin.external.iac.DestroyRequest + 53, // 89: workflow.plugin.external.iac.IaCProviderRequired.Status:input_type -> workflow.plugin.external.iac.StatusRequest + 55, // 90: workflow.plugin.external.iac.IaCProviderRequired.Import:input_type -> workflow.plugin.external.iac.ImportRequest + 57, // 91: workflow.plugin.external.iac.IaCProviderRequired.ResolveSizing:input_type -> workflow.plugin.external.iac.ResolveSizingRequest + 59, // 92: workflow.plugin.external.iac.IaCProviderRequired.BootstrapStateBackend:input_type -> workflow.plugin.external.iac.BootstrapStateBackendRequest + 61, // 93: workflow.plugin.external.iac.IaCProviderEnumerator.EnumerateAll:input_type -> workflow.plugin.external.iac.EnumerateAllRequest + 63, // 94: workflow.plugin.external.iac.IaCProviderEnumerator.EnumerateByTag:input_type -> workflow.plugin.external.iac.EnumerateByTagRequest + 65, // 95: workflow.plugin.external.iac.IaCProviderDriftDetector.DetectDrift:input_type -> workflow.plugin.external.iac.DetectDriftRequest + 67, // 96: workflow.plugin.external.iac.IaCProviderDriftDetector.DetectDriftWithSpecs:input_type -> workflow.plugin.external.iac.DetectDriftWithSpecsRequest + 69, // 97: workflow.plugin.external.iac.IaCProviderCredentialRevoker.RevokeProviderCredential:input_type -> workflow.plugin.external.iac.RevokeProviderCredentialRequest + 71, // 98: workflow.plugin.external.iac.IaCProviderFinalizer.FinalizeApply:input_type -> workflow.plugin.external.iac.FinalizeApplyRequest + 73, // 99: workflow.plugin.external.iac.IaCProviderMigrationRepairer.RepairDirtyMigration:input_type -> workflow.plugin.external.iac.RepairDirtyMigrationRequest + 75, // 100: workflow.plugin.external.iac.IaCProviderValidator.ValidatePlan:input_type -> workflow.plugin.external.iac.ValidatePlanRequest + 77, // 101: workflow.plugin.external.iac.IaCProviderDriftConfigDetector.DetectDriftConfig:input_type -> workflow.plugin.external.iac.DetectDriftConfigRequest + 79, // 102: workflow.plugin.external.iac.IaCProviderLogCapture.CaptureLogs:input_type -> workflow.plugin.external.iac.CaptureLogsRequest + 20, // 103: workflow.plugin.external.iac.IaCRequirementDiscovery.DiscoverRequirements:input_type -> workflow.plugin.external.iac.DiscoverRequirementsRequest + 24, // 104: workflow.plugin.external.iac.IaCProviderRequirementMapper.MapRequirements:input_type -> workflow.plugin.external.iac.MapRequirementsRequest + 81, // 105: workflow.plugin.external.iac.ResourceDriver.Create:input_type -> workflow.plugin.external.iac.ResourceCreateRequest + 83, // 106: workflow.plugin.external.iac.ResourceDriver.Read:input_type -> workflow.plugin.external.iac.ResourceReadRequest + 85, // 107: workflow.plugin.external.iac.ResourceDriver.Update:input_type -> workflow.plugin.external.iac.ResourceUpdateRequest + 87, // 108: workflow.plugin.external.iac.ResourceDriver.Delete:input_type -> workflow.plugin.external.iac.ResourceDeleteRequest + 89, // 109: workflow.plugin.external.iac.ResourceDriver.Diff:input_type -> workflow.plugin.external.iac.ResourceDiffRequest + 91, // 110: workflow.plugin.external.iac.ResourceDriver.Scale:input_type -> workflow.plugin.external.iac.ResourceScaleRequest + 93, // 111: workflow.plugin.external.iac.ResourceDriver.HealthCheck:input_type -> workflow.plugin.external.iac.ResourceHealthCheckRequest + 95, // 112: workflow.plugin.external.iac.ResourceDriver.SensitiveKeys:input_type -> workflow.plugin.external.iac.SensitiveKeysRequest + 97, // 113: workflow.plugin.external.iac.ResourceDriver.Troubleshoot:input_type -> workflow.plugin.external.iac.TroubleshootRequest + 100, // 114: workflow.plugin.external.iac.IaCStateBackend.Configure:input_type -> workflow.plugin.external.iac.ConfigureRequest + 102, // 115: workflow.plugin.external.iac.IaCStateBackend.GetState:input_type -> workflow.plugin.external.iac.GetStateRequest + 104, // 116: workflow.plugin.external.iac.IaCStateBackend.SaveState:input_type -> workflow.plugin.external.iac.SaveStateRequest + 106, // 117: workflow.plugin.external.iac.IaCStateBackend.ListStates:input_type -> workflow.plugin.external.iac.ListStatesRequest + 108, // 118: workflow.plugin.external.iac.IaCStateBackend.DeleteState:input_type -> workflow.plugin.external.iac.DeleteStateRequest + 110, // 119: workflow.plugin.external.iac.IaCStateBackend.Lock:input_type -> workflow.plugin.external.iac.LockRequest + 112, // 120: workflow.plugin.external.iac.IaCStateBackend.Unlock:input_type -> workflow.plugin.external.iac.UnlockRequest + 114, // 121: workflow.plugin.external.iac.IaCStateBackend.ListBackendNames:input_type -> workflow.plugin.external.iac.ListBackendNamesRequest + 42, // 122: workflow.plugin.external.iac.IaCProviderRequired.Initialize:output_type -> workflow.plugin.external.iac.InitializeResponse + 44, // 123: workflow.plugin.external.iac.IaCProviderRequired.Name:output_type -> workflow.plugin.external.iac.NameResponse + 46, // 124: workflow.plugin.external.iac.IaCProviderRequired.Version:output_type -> workflow.plugin.external.iac.VersionResponse + 48, // 125: workflow.plugin.external.iac.IaCProviderRequired.Capabilities:output_type -> workflow.plugin.external.iac.CapabilitiesResponse + 50, // 126: workflow.plugin.external.iac.IaCProviderRequired.Plan:output_type -> workflow.plugin.external.iac.PlanResponse + 52, // 127: workflow.plugin.external.iac.IaCProviderRequired.Destroy:output_type -> workflow.plugin.external.iac.DestroyResponse + 54, // 128: workflow.plugin.external.iac.IaCProviderRequired.Status:output_type -> workflow.plugin.external.iac.StatusResponse + 56, // 129: workflow.plugin.external.iac.IaCProviderRequired.Import:output_type -> workflow.plugin.external.iac.ImportResponse + 58, // 130: workflow.plugin.external.iac.IaCProviderRequired.ResolveSizing:output_type -> workflow.plugin.external.iac.ResolveSizingResponse + 60, // 131: workflow.plugin.external.iac.IaCProviderRequired.BootstrapStateBackend:output_type -> workflow.plugin.external.iac.BootstrapStateBackendResponse + 62, // 132: workflow.plugin.external.iac.IaCProviderEnumerator.EnumerateAll:output_type -> workflow.plugin.external.iac.EnumerateAllResponse + 64, // 133: workflow.plugin.external.iac.IaCProviderEnumerator.EnumerateByTag:output_type -> workflow.plugin.external.iac.EnumerateByTagResponse + 66, // 134: workflow.plugin.external.iac.IaCProviderDriftDetector.DetectDrift:output_type -> workflow.plugin.external.iac.DetectDriftResponse + 68, // 135: workflow.plugin.external.iac.IaCProviderDriftDetector.DetectDriftWithSpecs:output_type -> workflow.plugin.external.iac.DetectDriftWithSpecsResponse + 70, // 136: workflow.plugin.external.iac.IaCProviderCredentialRevoker.RevokeProviderCredential:output_type -> workflow.plugin.external.iac.RevokeProviderCredentialResponse + 72, // 137: workflow.plugin.external.iac.IaCProviderFinalizer.FinalizeApply:output_type -> workflow.plugin.external.iac.FinalizeApplyResponse + 74, // 138: workflow.plugin.external.iac.IaCProviderMigrationRepairer.RepairDirtyMigration:output_type -> workflow.plugin.external.iac.RepairDirtyMigrationResponse + 76, // 139: workflow.plugin.external.iac.IaCProviderValidator.ValidatePlan:output_type -> workflow.plugin.external.iac.ValidatePlanResponse + 78, // 140: workflow.plugin.external.iac.IaCProviderDriftConfigDetector.DetectDriftConfig:output_type -> workflow.plugin.external.iac.DetectDriftConfigResponse + 80, // 141: workflow.plugin.external.iac.IaCProviderLogCapture.CaptureLogs:output_type -> workflow.plugin.external.iac.LogChunk + 23, // 142: workflow.plugin.external.iac.IaCRequirementDiscovery.DiscoverRequirements:output_type -> workflow.plugin.external.iac.DiscoverRequirementsResponse + 28, // 143: workflow.plugin.external.iac.IaCProviderRequirementMapper.MapRequirements:output_type -> workflow.plugin.external.iac.MapRequirementsResponse + 82, // 144: workflow.plugin.external.iac.ResourceDriver.Create:output_type -> workflow.plugin.external.iac.ResourceCreateResponse + 84, // 145: workflow.plugin.external.iac.ResourceDriver.Read:output_type -> workflow.plugin.external.iac.ResourceReadResponse + 86, // 146: workflow.plugin.external.iac.ResourceDriver.Update:output_type -> workflow.plugin.external.iac.ResourceUpdateResponse + 88, // 147: workflow.plugin.external.iac.ResourceDriver.Delete:output_type -> workflow.plugin.external.iac.ResourceDeleteResponse + 90, // 148: workflow.plugin.external.iac.ResourceDriver.Diff:output_type -> workflow.plugin.external.iac.ResourceDiffResponse + 92, // 149: workflow.plugin.external.iac.ResourceDriver.Scale:output_type -> workflow.plugin.external.iac.ResourceScaleResponse + 94, // 150: workflow.plugin.external.iac.ResourceDriver.HealthCheck:output_type -> workflow.plugin.external.iac.ResourceHealthCheckResponse + 96, // 151: workflow.plugin.external.iac.ResourceDriver.SensitiveKeys:output_type -> workflow.plugin.external.iac.SensitiveKeysResponse + 98, // 152: workflow.plugin.external.iac.ResourceDriver.Troubleshoot:output_type -> workflow.plugin.external.iac.TroubleshootResponse + 101, // 153: workflow.plugin.external.iac.IaCStateBackend.Configure:output_type -> workflow.plugin.external.iac.ConfigureResponse + 103, // 154: workflow.plugin.external.iac.IaCStateBackend.GetState:output_type -> workflow.plugin.external.iac.GetStateResponse + 105, // 155: workflow.plugin.external.iac.IaCStateBackend.SaveState:output_type -> workflow.plugin.external.iac.SaveStateResponse + 107, // 156: workflow.plugin.external.iac.IaCStateBackend.ListStates:output_type -> workflow.plugin.external.iac.ListStatesResponse + 109, // 157: workflow.plugin.external.iac.IaCStateBackend.DeleteState:output_type -> workflow.plugin.external.iac.DeleteStateResponse + 111, // 158: workflow.plugin.external.iac.IaCStateBackend.Lock:output_type -> workflow.plugin.external.iac.LockResponse + 113, // 159: workflow.plugin.external.iac.IaCStateBackend.Unlock:output_type -> workflow.plugin.external.iac.UnlockResponse + 115, // 160: workflow.plugin.external.iac.IaCStateBackend.ListBackendNames:output_type -> workflow.plugin.external.iac.ListBackendNamesResponse + 122, // [122:161] is the sub-list for method output_type + 83, // [83:122] is the sub-list for method input_type + 83, // [83:83] is the sub-list for extension type_name + 83, // [83:83] is the sub-list for extension extendee + 0, // [0:83] is the sub-list for field type_name } func init() { file_iac_proto_init() } @@ -6334,10 +7436,10 @@ func file_iac_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_iac_proto_rawDesc), len(file_iac_proto_rawDesc)), - NumEnums: 4, - NumMessages: 104, + NumEnums: 9, + NumMessages: 114, NumExtensions: 0, - NumServices: 11, + NumServices: 13, }, GoTypes: file_iac_proto_goTypes, DependencyIndexes: file_iac_proto_depIdxs, diff --git a/plugin/external/proto/iac.proto b/plugin/external/proto/iac.proto index cb23280b..c3d157da 100644 --- a/plugin/external/proto/iac.proto +++ b/plugin/external/proto/iac.proto @@ -4,7 +4,7 @@ // Plan: docs/plans/2026-05-10-strict-contracts-force-cutover.md (Task 3) // // Hard invariants (per cycle 4 §Acceptance criteria): -// - NO google.protobuf.Struct, NO google.protobuf.Any used in any message. +// - NO loose Struct/Any wrapper types used in any message. // - Free-form per-resource Config / Outputs payloads cross the wire as // bytes _json, JSON-encoded by the plugin/host. The plugin owns // the serialization shape; the proto layer carries opaque bytes. @@ -90,6 +90,24 @@ service IaCProviderLogCapture { rpc CaptureLogs(CaptureLogsRequest) returns (stream LogChunk); } +// IaCRequirementDiscovery is an optional service for config-aware plugins that +// need to emit provider-neutral infrastructure requirements from their own +// module configuration. Hosts pass a typed, redacted Workflow context plus the +// plugin-owned module config as JSON bytes. The full Workflow YAML and +// resolved secret values must not cross this boundary. +service IaCRequirementDiscovery { + rpc DiscoverRequirements(DiscoverRequirementsRequest) returns (DiscoverRequirementsResponse); +} + +// IaCProviderRequirementMapper is an optional provider-owned service that maps +// provider-neutral requirements to concrete infra.* module specs for a selected +// provider/runtime/environment. Absence of this registration is the negative +// signal: the provider can still plan/apply explicit modules, but wfctl cannot +// ask it to synthesize derived IaC. +service IaCProviderRequirementMapper { + rpc MapRequirements(MapRequirementsRequest) returns (MapRequirementsResponse); +} + // ───────────────────────────────────────────────────────────────────────────── // ResourceDriver — separate gRPC service for per-resource-type CRUD dispatch. // The driver instance is identified by (resource_type) carried on every RPC. @@ -235,6 +253,134 @@ enum DriftClass { DRIFT_CLASS_CONFIG = 3; } +// RequirementKind is the provider-neutral infrastructure category that wfctl +// and provider plugins exchange for derived IaC. Values are intentionally +// portable and provider-agnostic. +enum RequirementKind { + REQUIREMENT_KIND_UNSPECIFIED = 0; + REQUIREMENT_KIND_OBSERVABILITY = 1; + REQUIREMENT_KIND_WEB_API = 2; + REQUIREMENT_KIND_MESSAGE_BROKER = 3; + REQUIREMENT_KIND_DATABASE = 4; + REQUIREMENT_KIND_CACHE = 5; + REQUIREMENT_KIND_STORAGE = 6; +} + +// RequirementRuntime describes the target runtime shape the provider mapper +// should generate for. Provider plugins return diagnostics for unsupported +// runtime/mode combinations instead of emitting malformed modules. +enum RequirementRuntime { + REQUIREMENT_RUNTIME_UNSPECIFIED = 0; + REQUIREMENT_RUNTIME_KUBERNETES = 1; + REQUIREMENT_RUNTIME_ECS = 2; + REQUIREMENT_RUNTIME_CLOUD_RUN = 3; + REQUIREMENT_RUNTIME_AZURE_CONTAINER_APPS = 4; + REQUIREMENT_RUNTIME_DIGITALOCEAN_APP_PLATFORM = 5; +} + +enum TelemetrySignal { + TELEMETRY_SIGNAL_UNSPECIFIED = 0; + TELEMETRY_SIGNAL_TRACES = 1; + TELEMETRY_SIGNAL_METRICS = 2; + TELEMETRY_SIGNAL_LOGS = 3; +} + +enum ObservabilityBackend { + OBSERVABILITY_BACKEND_UNSPECIFIED = 0; + OBSERVABILITY_BACKEND_OTEL = 1; + OBSERVABILITY_BACKEND_DATADOG = 2; + OBSERVABILITY_BACKEND_PROMETHEUS = 3; + OBSERVABILITY_BACKEND_LOKI = 4; + OBSERVABILITY_BACKEND_GRAFANA = 5; +} + +enum DeploymentMode { + DEPLOYMENT_MODE_UNSPECIFIED = 0; + DEPLOYMENT_MODE_SIDECAR = 1; + DEPLOYMENT_MODE_DAEMONSET = 2; + DEPLOYMENT_MODE_SIBLING_SERVICE = 3; + DEPLOYMENT_MODE_MANAGED = 4; +} + +message IaCRequirement { + string key = 1; + RequirementKind kind = 2; + string source = 3; + string resource_type_hint = 4; + string environment = 5; + repeated RequirementRuntime runtimes = 6; + repeated TelemetrySignal telemetry_signals = 7; + repeated ObservabilityBackend observability_backends = 8; + repeated DeploymentMode deployment_modes = 9; + repeated string vendor_features = 10; + // parameters_json is JSON-encoded plugin-owned requirement detail for data + // that is not portable enough to promote to a Workflow-owned proto field. + // Prefer adding enum/message fields for portable concepts. + bytes parameters_json = 11; +} + +message DiscoverRequirementsRequest { + RequirementContext context = 1; + // module_config_json is JSON-encoded module config owned by the plugin that + // implements IaCRequirementDiscovery. Hosts must not send full Workflow YAML + // or resolved secret values here. + bytes module_config_json = 2; +} + +message RequirementContext { + string application = 1; + string environment = 2; + repeated ModuleRef modules = 3; + repeated string plugin_ids = 4; +} + +message ModuleRef { + string name = 1; + string type = 2; + repeated string satisfies = 3; +} + +message DiscoverRequirementsResponse { + repeated IaCRequirement requirements = 1; +} + +message MapRequirementsRequest { + string provider = 1; + RequirementRuntime runtime = 2; + string environment = 3; + repeated IaCRequirement requirements = 4; +} + +message DerivedModuleSpec { + string name = 1; + string type = 2; + repeated string satisfies = 3; + // config_json is JSON-encoded provider-owned module config. Provider + // mappers must emit secret placeholders/references, never plaintext secret + // values. + bytes config_json = 4; + repeated string depends_on = 5; +} + +message RequirementDiagnostic { + string key = 1; + string code = 2; + string message = 3; +} + +message RequirementNote { + string key = 1; + string message = 2; + bool interactive = 3; +} + +message MapRequirementsResponse { + repeated string accepted_keys = 1; + repeated RequirementDiagnostic rejected = 2; + repeated DerivedModuleSpec modules = 3; + repeated RequirementNote notes = 4; +} + // DriftResult mirrors interfaces.DriftResult. message DriftResult { string name = 1; diff --git a/plugin/external/proto/iac_grpc.pb.go b/plugin/external/proto/iac_grpc.pb.go index 612ce07e..f9d22569 100644 --- a/plugin/external/proto/iac_grpc.pb.go +++ b/plugin/external/proto/iac_grpc.pb.go @@ -1421,6 +1421,236 @@ var IaCProviderLogCapture_ServiceDesc = grpc.ServiceDesc{ Metadata: "iac.proto", } +const ( + IaCRequirementDiscovery_DiscoverRequirements_FullMethodName = "/workflow.plugin.external.iac.IaCRequirementDiscovery/DiscoverRequirements" +) + +// IaCRequirementDiscoveryClient is the client API for IaCRequirementDiscovery service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// IaCRequirementDiscovery is an optional service for config-aware plugins that +// need to emit provider-neutral infrastructure requirements from their own +// module configuration. Hosts pass a typed, redacted Workflow context plus the +// plugin-owned module config as JSON bytes. The full Workflow YAML and +// resolved secret values must not cross this boundary. +type IaCRequirementDiscoveryClient interface { + DiscoverRequirements(ctx context.Context, in *DiscoverRequirementsRequest, opts ...grpc.CallOption) (*DiscoverRequirementsResponse, error) +} + +type iaCRequirementDiscoveryClient struct { + cc grpc.ClientConnInterface +} + +func NewIaCRequirementDiscoveryClient(cc grpc.ClientConnInterface) IaCRequirementDiscoveryClient { + return &iaCRequirementDiscoveryClient{cc} +} + +func (c *iaCRequirementDiscoveryClient) DiscoverRequirements(ctx context.Context, in *DiscoverRequirementsRequest, opts ...grpc.CallOption) (*DiscoverRequirementsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DiscoverRequirementsResponse) + err := c.cc.Invoke(ctx, IaCRequirementDiscovery_DiscoverRequirements_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// IaCRequirementDiscoveryServer is the server API for IaCRequirementDiscovery service. +// All implementations must embed UnimplementedIaCRequirementDiscoveryServer +// for forward compatibility. +// +// IaCRequirementDiscovery is an optional service for config-aware plugins that +// need to emit provider-neutral infrastructure requirements from their own +// module configuration. Hosts pass a typed, redacted Workflow context plus the +// plugin-owned module config as JSON bytes. The full Workflow YAML and +// resolved secret values must not cross this boundary. +type IaCRequirementDiscoveryServer interface { + DiscoverRequirements(context.Context, *DiscoverRequirementsRequest) (*DiscoverRequirementsResponse, error) + mustEmbedUnimplementedIaCRequirementDiscoveryServer() +} + +// UnimplementedIaCRequirementDiscoveryServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedIaCRequirementDiscoveryServer struct{} + +func (UnimplementedIaCRequirementDiscoveryServer) DiscoverRequirements(context.Context, *DiscoverRequirementsRequest) (*DiscoverRequirementsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method DiscoverRequirements not implemented") +} +func (UnimplementedIaCRequirementDiscoveryServer) mustEmbedUnimplementedIaCRequirementDiscoveryServer() { +} +func (UnimplementedIaCRequirementDiscoveryServer) testEmbeddedByValue() {} + +// UnsafeIaCRequirementDiscoveryServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to IaCRequirementDiscoveryServer will +// result in compilation errors. +type UnsafeIaCRequirementDiscoveryServer interface { + mustEmbedUnimplementedIaCRequirementDiscoveryServer() +} + +func RegisterIaCRequirementDiscoveryServer(s grpc.ServiceRegistrar, srv IaCRequirementDiscoveryServer) { + // If the following call panics, it indicates UnimplementedIaCRequirementDiscoveryServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&IaCRequirementDiscovery_ServiceDesc, srv) +} + +func _IaCRequirementDiscovery_DiscoverRequirements_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DiscoverRequirementsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(IaCRequirementDiscoveryServer).DiscoverRequirements(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: IaCRequirementDiscovery_DiscoverRequirements_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(IaCRequirementDiscoveryServer).DiscoverRequirements(ctx, req.(*DiscoverRequirementsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// IaCRequirementDiscovery_ServiceDesc is the grpc.ServiceDesc for IaCRequirementDiscovery service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var IaCRequirementDiscovery_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "workflow.plugin.external.iac.IaCRequirementDiscovery", + HandlerType: (*IaCRequirementDiscoveryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "DiscoverRequirements", + Handler: _IaCRequirementDiscovery_DiscoverRequirements_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "iac.proto", +} + +const ( + IaCProviderRequirementMapper_MapRequirements_FullMethodName = "/workflow.plugin.external.iac.IaCProviderRequirementMapper/MapRequirements" +) + +// IaCProviderRequirementMapperClient is the client API for IaCProviderRequirementMapper service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +// +// IaCProviderRequirementMapper is an optional provider-owned service that maps +// provider-neutral requirements to concrete infra.* module specs for a selected +// provider/runtime/environment. Absence of this registration is the negative +// signal: the provider can still plan/apply explicit modules, but wfctl cannot +// ask it to synthesize derived IaC. +type IaCProviderRequirementMapperClient interface { + MapRequirements(ctx context.Context, in *MapRequirementsRequest, opts ...grpc.CallOption) (*MapRequirementsResponse, error) +} + +type iaCProviderRequirementMapperClient struct { + cc grpc.ClientConnInterface +} + +func NewIaCProviderRequirementMapperClient(cc grpc.ClientConnInterface) IaCProviderRequirementMapperClient { + return &iaCProviderRequirementMapperClient{cc} +} + +func (c *iaCProviderRequirementMapperClient) MapRequirements(ctx context.Context, in *MapRequirementsRequest, opts ...grpc.CallOption) (*MapRequirementsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(MapRequirementsResponse) + err := c.cc.Invoke(ctx, IaCProviderRequirementMapper_MapRequirements_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// IaCProviderRequirementMapperServer is the server API for IaCProviderRequirementMapper service. +// All implementations must embed UnimplementedIaCProviderRequirementMapperServer +// for forward compatibility. +// +// IaCProviderRequirementMapper is an optional provider-owned service that maps +// provider-neutral requirements to concrete infra.* module specs for a selected +// provider/runtime/environment. Absence of this registration is the negative +// signal: the provider can still plan/apply explicit modules, but wfctl cannot +// ask it to synthesize derived IaC. +type IaCProviderRequirementMapperServer interface { + MapRequirements(context.Context, *MapRequirementsRequest) (*MapRequirementsResponse, error) + mustEmbedUnimplementedIaCProviderRequirementMapperServer() +} + +// UnimplementedIaCProviderRequirementMapperServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedIaCProviderRequirementMapperServer struct{} + +func (UnimplementedIaCProviderRequirementMapperServer) MapRequirements(context.Context, *MapRequirementsRequest) (*MapRequirementsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method MapRequirements not implemented") +} +func (UnimplementedIaCProviderRequirementMapperServer) mustEmbedUnimplementedIaCProviderRequirementMapperServer() { +} +func (UnimplementedIaCProviderRequirementMapperServer) testEmbeddedByValue() {} + +// UnsafeIaCProviderRequirementMapperServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to IaCProviderRequirementMapperServer will +// result in compilation errors. +type UnsafeIaCProviderRequirementMapperServer interface { + mustEmbedUnimplementedIaCProviderRequirementMapperServer() +} + +func RegisterIaCProviderRequirementMapperServer(s grpc.ServiceRegistrar, srv IaCProviderRequirementMapperServer) { + // If the following call panics, it indicates UnimplementedIaCProviderRequirementMapperServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&IaCProviderRequirementMapper_ServiceDesc, srv) +} + +func _IaCProviderRequirementMapper_MapRequirements_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MapRequirementsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(IaCProviderRequirementMapperServer).MapRequirements(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: IaCProviderRequirementMapper_MapRequirements_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(IaCProviderRequirementMapperServer).MapRequirements(ctx, req.(*MapRequirementsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// IaCProviderRequirementMapper_ServiceDesc is the grpc.ServiceDesc for IaCProviderRequirementMapper service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var IaCProviderRequirementMapper_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "workflow.plugin.external.iac.IaCProviderRequirementMapper", + HandlerType: (*IaCProviderRequirementMapperServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "MapRequirements", + Handler: _IaCProviderRequirementMapper_MapRequirements_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "iac.proto", +} + const ( ResourceDriver_Create_FullMethodName = "/workflow.plugin.external.iac.ResourceDriver/Create" ResourceDriver_Read_FullMethodName = "/workflow.plugin.external.iac.ResourceDriver/Read" diff --git a/plugin/external/sdk/contracts_iac_test.go b/plugin/external/sdk/contracts_iac_test.go index b67aebaf..380f6810 100644 --- a/plugin/external/sdk/contracts_iac_test.go +++ b/plugin/external/sdk/contracts_iac_test.go @@ -1,6 +1,8 @@ package sdk_test import ( + "os" + "strings" "testing" "google.golang.org/grpc" @@ -40,6 +42,44 @@ func TestBuildContractRegistry_AdvertisesRegisteredIaCServices(t *testing.T) { } } +func TestBuildContractRegistry_AdvertisesRequirementServices(t *testing.T) { + grpcSrv := grpc.NewServer() + provider := &iacRequirementContractProviderStub{} + if err := sdk.RegisterAllIaCProviderServices(grpcSrv, provider); err != nil { + t.Fatalf("register: %v", err) + } + + registry := sdk.BuildContractRegistry(grpcSrv) + services := serviceNamesFromRegistry(registry) + want := []string{ + pb.IaCRequirementDiscovery_ServiceDesc.ServiceName, + pb.IaCProviderRequirementMapper_ServiceDesc.ServiceName, + } + for _, name := range want { + if !services[name] { + t.Errorf("ContractRegistry missing service %q; have: %v", name, services) + } + } +} + +func TestIaCProtoRejectsLooseTypes(t *testing.T) { + body, err := os.ReadFile("../proto/iac.proto") + if err != nil { + t.Fatalf("read iac.proto: %v", err) + } + proto := string(body) + for _, forbidden := range []string{ + `import "google/protobuf/struct.proto"`, + `import "google/protobuf/any.proto"`, + "google.protobuf.Struct", + "google.protobuf.Any", + } { + if strings.Contains(proto, forbidden) { + t.Fatalf("iac.proto must stay strict-proto compatible; found %q", forbidden) + } + } +} + // TestBuildContractRegistry_ServiceContractsUseStrictProtoMode asserts // that auto-emitted IaC service descriptors carry Mode=STRICT_PROTO so // the host can distinguish them from the legacy structpb-mode contracts @@ -93,3 +133,9 @@ type iacContractProviderStub struct { pb.UnimplementedIaCProviderEnumeratorServer pb.UnimplementedIaCProviderDriftDetectorServer } + +type iacRequirementContractProviderStub struct { + pb.UnimplementedIaCProviderRequiredServer + pb.UnimplementedIaCRequirementDiscoveryServer + pb.UnimplementedIaCProviderRequirementMapperServer +} diff --git a/plugin/external/sdk/iacserver.go b/plugin/external/sdk/iacserver.go index 0eed44f8..1e079b69 100644 --- a/plugin/external/sdk/iacserver.go +++ b/plugin/external/sdk/iacserver.go @@ -38,6 +38,8 @@ import ( // pb.IaCProviderValidatorServer // pb.IaCProviderDriftConfigDetectorServer // pb.IaCProviderLogCaptureServer +// pb.IaCRequirementDiscoveryServer +// pb.IaCProviderRequirementMapperServer // pb.IaCStateBackendServer // // ResourceDriver: @@ -169,6 +171,12 @@ func registerIaCServicesOnly(s *grpc.Server, provider any) error { if v, ok := provider.(pb.IaCProviderLogCaptureServer); ok { pb.RegisterIaCProviderLogCaptureServer(s, v) } + if v, ok := provider.(pb.IaCRequirementDiscoveryServer); ok { + pb.RegisterIaCRequirementDiscoveryServer(s, v) + } + if v, ok := provider.(pb.IaCProviderRequirementMapperServer); ok { + pb.RegisterIaCProviderRequirementMapperServer(s, v) + } // IaCProviderFinalizer is the workflow#695 Phase 2.5 optional service // for plugins needing a post-apply-loop finalizer hook under v2 // dispatch. Per ADR 0024 the absence of this registration IS the diff --git a/plugin/external/sdk/iacserver_test.go b/plugin/external/sdk/iacserver_test.go index cd5203b1..ed13c676 100644 --- a/plugin/external/sdk/iacserver_test.go +++ b/plugin/external/sdk/iacserver_test.go @@ -156,6 +156,30 @@ func TestRegisterAll_RegistersIaCProviderFinalizer(t *testing.T) { } } +func TestRegisterAll_RegistersIaCRequirementDiscovery(t *testing.T) { + grpcSrv := grpc.NewServer() + provider := &requirementDiscoveryProviderStub{} + if err := sdk.RegisterAllIaCProviderServices(grpcSrv, provider); err != nil { + t.Fatalf("unexpected error: %v", err) + } + info := grpcSrv.GetServiceInfo() + if _, ok := info[pb.IaCRequirementDiscovery_ServiceDesc.ServiceName]; !ok { + t.Fatalf("IaCRequirementDiscovery service NOT registered despite provider satisfying interface; have: %v", serviceNames(info)) + } +} + +func TestRegisterAll_RegistersIaCProviderRequirementMapper(t *testing.T) { + grpcSrv := grpc.NewServer() + provider := &requirementMapperProviderStub{} + if err := sdk.RegisterAllIaCProviderServices(grpcSrv, provider); err != nil { + t.Fatalf("unexpected error: %v", err) + } + info := grpcSrv.GetServiceInfo() + if _, ok := info[pb.IaCProviderRequirementMapper_ServiceDesc.ServiceName]; !ok { + t.Fatalf("IaCProviderRequirementMapper service NOT registered despite provider satisfying interface; have: %v", serviceNames(info)) + } +} + // TestRegisterAll_SkipsIaCProviderFinalizerWhenNotImplemented locks the // negative signal contract: a provider that does NOT satisfy // pb.IaCProviderFinalizerServer MUST NOT have the service registered. @@ -202,6 +226,16 @@ type finalizerProviderStub struct { pb.UnimplementedIaCProviderFinalizerServer } +type requirementDiscoveryProviderStub struct { + pb.UnimplementedIaCProviderRequiredServer + pb.UnimplementedIaCRequirementDiscoveryServer +} + +type requirementMapperProviderStub struct { + pb.UnimplementedIaCProviderRequiredServer + pb.UnimplementedIaCProviderRequirementMapperServer +} + // allCapabilitiesStub satisfies every required + optional IaC service plus // ResourceDriver — used to assert auto-registration covers the full surface. type allCapabilitiesStub struct { @@ -213,6 +247,8 @@ type allCapabilitiesStub struct { pb.UnimplementedIaCProviderValidatorServer pb.UnimplementedIaCProviderDriftConfigDetectorServer pb.UnimplementedIaCProviderFinalizerServer + pb.UnimplementedIaCRequirementDiscoveryServer + pb.UnimplementedIaCProviderRequirementMapperServer pb.UnimplementedResourceDriverServer } From c8e82a42f90aa8479fba9e5ecbc1b9fea170e917 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 00:23:36 -0400 Subject: [PATCH 12/15] feat: model iac requirements in config --- config/config.go | 1 + config/config_test.go | 29 +++++ config/plugin_manifest.go | 39 ++++++- config/plugin_manifest_test.go | 63 +++++++++++ iac/requirements/types.go | 200 +++++++++++++++++++++++++++++++++ iac/requirements/types_test.go | 72 ++++++++++++ 6 files changed, 399 insertions(+), 5 deletions(-) create mode 100644 iac/requirements/types.go create mode 100644 iac/requirements/types_test.go diff --git a/config/config.go b/config/config.go index 5d749f89..8457cbc5 100644 --- a/config/config.go +++ b/config/config.go @@ -73,6 +73,7 @@ func IsApplicationConfig(data []byte) bool { type ModuleConfig struct { Name string `json:"name" yaml:"name"` Type string `json:"type" yaml:"type"` + Satisfies []string `json:"satisfies,omitempty" yaml:"satisfies,omitempty"` Config map[string]any `json:"config,omitempty" yaml:"config,omitempty"` DependsOn []string `json:"dependsOn,omitempty" yaml:"dependsOn,omitempty"` Branches map[string]string `json:"branches,omitempty" yaml:"branches,omitempty"` diff --git a/config/config_test.go b/config/config_test.go index 125ae887..aa4ce827 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -136,6 +136,35 @@ modules: } } +func TestLoadFromFile_ModuleSatisfies(t *testing.T) { + content := ` +modules: + - name: otel-collector + type: infra.container_service + satisfies: + - observability.telemetry.default + config: + image: otel/opentelemetry-collector-contrib:latest +` + dir := t.TempDir() + fp := filepath.Join(dir, "modules.yaml") + if err := os.WriteFile(fp, []byte(content), 0644); err != nil { + t.Fatalf("failed to write test file: %v", err) + } + + cfg, err := LoadFromFile(fp) + if err != nil { + t.Fatalf("LoadFromFile failed: %v", err) + } + if len(cfg.Modules) != 1 { + t.Fatalf("modules len = %d, want 1", len(cfg.Modules)) + } + got := cfg.Modules[0].Satisfies + if len(got) != 1 || got[0] != "observability.telemetry.default" { + t.Fatalf("Satisfies = %v, want [observability.telemetry.default]", got) + } +} + func TestExternalPluginDeclParsing(t *testing.T) { yaml := ` modules: [] diff --git a/config/plugin_manifest.go b/config/plugin_manifest.go index 8dbea6f9..741b51c9 100644 --- a/config/plugin_manifest.go +++ b/config/plugin_manifest.go @@ -3,11 +3,21 @@ package config // PluginInfraRequirements maps module types to their infrastructure needs. type PluginInfraRequirements map[string]*ModuleInfraSpec +// PluginInfraRequirementsV2 maps module types to provider-neutral IaC +// requirements. The values intentionally use manifest-friendly strings; the +// iac/requirements package owns typed enum validation and protobuf conversion. +type PluginInfraRequirementsV2 map[string]*ModuleInfraSpecV2 + // ModuleInfraSpec declares what a module type requires. type ModuleInfraSpec struct { Requires []InfraRequirement `json:"requires" yaml:"requires"` } +// ModuleInfraSpecV2 declares typed requirement metadata for a module type. +type ModuleInfraSpecV2 struct { + Requires []ModuleInfraRequirementV2 `json:"requires" yaml:"requires"` +} + // InfraRequirement is a single infrastructure dependency. type InfraRequirement struct { Type string `json:"type" yaml:"type"` @@ -20,13 +30,32 @@ type InfraRequirement struct { Optional bool `json:"optional,omitempty" yaml:"optional,omitempty"` } +// ModuleInfraRequirementV2 is the plugin.json authoring shape for derived-IaC +// requirements. It mirrors the portable fields in plugin/external/proto/iac.proto +// using strings so manifests stay easy to read and preserve unknown future +// provider details under Parameters. +type ModuleInfraRequirementV2 struct { + Key string `json:"key" yaml:"key"` + Kind string `json:"kind" yaml:"kind"` + Source string `json:"source,omitempty" yaml:"source,omitempty"` + ResourceTypeHint string `json:"resourceTypeHint,omitempty" yaml:"resourceTypeHint,omitempty"` + Environment string `json:"environment,omitempty" yaml:"environment,omitempty"` + Runtimes []string `json:"runtimes,omitempty" yaml:"runtimes,omitempty"` + TelemetrySignals []string `json:"telemetrySignals,omitempty" yaml:"telemetrySignals,omitempty"` + ObservabilityBackends []string `json:"observabilityBackends,omitempty" yaml:"observabilityBackends,omitempty"` + DeploymentModes []string `json:"deploymentModes,omitempty" yaml:"deploymentModes,omitempty"` + VendorFeatures []string `json:"vendorFeatures,omitempty" yaml:"vendorFeatures,omitempty"` + Parameters map[string]any `json:"parameters,omitempty" yaml:"parameters,omitempty"` +} + // PluginManifestFile represents the full plugin.json manifest. type PluginManifestFile struct { - Name string `json:"name" yaml:"name"` - Version string `json:"version" yaml:"version"` - Description string `json:"description" yaml:"description"` - Capabilities PluginCapabilities `json:"capabilities" yaml:"capabilities"` - ModuleInfraRequirements PluginInfraRequirements `json:"moduleInfraRequirements,omitempty" yaml:"moduleInfraRequirements,omitempty"` + Name string `json:"name" yaml:"name"` + Version string `json:"version" yaml:"version"` + Description string `json:"description" yaml:"description"` + Capabilities PluginCapabilities `json:"capabilities" yaml:"capabilities"` + ModuleInfraRequirements PluginInfraRequirements `json:"moduleInfraRequirements,omitempty" yaml:"moduleInfraRequirements,omitempty"` + ModuleInfraRequirementsV2 PluginInfraRequirementsV2 `json:"moduleInfraRequirementsV2,omitempty" yaml:"moduleInfraRequirementsV2,omitempty"` } // PluginCapabilities describes what module, step, trigger types, build hooks, diff --git a/config/plugin_manifest_test.go b/config/plugin_manifest_test.go index 86929fe4..19e1dadd 100644 --- a/config/plugin_manifest_test.go +++ b/config/plugin_manifest_test.go @@ -159,3 +159,66 @@ func TestPluginManifestNoInfraRequirements(t *testing.T) { t.Errorf("expected nil ModuleInfraRequirements, got %v", manifest.ModuleInfraRequirements) } } + +func TestPluginManifestRequirementV2YAML(t *testing.T) { + raw := ` +name: workflow-plugin-observability +version: "0.1.2" +description: Observability plugin +capabilities: + moduleTypes: + - observability.telemetry + stepTypes: [] + triggerTypes: [] +moduleInfraRequirementsV2: + observability.telemetry: + requires: + - key: observability.telemetry.default + kind: observability + source: observability.telemetry + resourceTypeHint: infra.container_service + environment: production + runtimes: + - kubernetes + - digitalocean_app_platform + telemetrySignals: + - traces + - metrics + - logs + observabilityBackends: + - otel + - datadog + deploymentModes: + - sidecar + - sibling_service + vendorFeatures: + - datadog.apm + parameters: + collector: otel +` + + var manifest PluginManifestFile + if err := yaml.Unmarshal([]byte(raw), &manifest); err != nil { + t.Fatalf("unmarshal YAML: %v", err) + } + spec := manifest.ModuleInfraRequirementsV2["observability.telemetry"] + if spec == nil { + t.Fatal("expected observability.telemetry v2 infra requirements") + } + if len(spec.Requires) != 1 { + t.Fatalf("Requires len = %d, want 1", len(spec.Requires)) + } + req := spec.Requires[0] + if req.Key != "observability.telemetry.default" { + t.Fatalf("Key = %q", req.Key) + } + if req.Kind != "observability" { + t.Fatalf("Kind = %q", req.Kind) + } + if len(req.TelemetrySignals) != 3 { + t.Fatalf("TelemetrySignals = %v", req.TelemetrySignals) + } + if req.Parameters["collector"] != "otel" { + t.Fatalf("Parameters = %v", req.Parameters) + } +} diff --git a/iac/requirements/types.go b/iac/requirements/types.go new file mode 100644 index 00000000..cfaea808 --- /dev/null +++ b/iac/requirements/types.go @@ -0,0 +1,200 @@ +package requirements + +import ( + "encoding/json" + "fmt" + "regexp" + + pb "github.com/GoCodeAlone/workflow/plugin/external/proto" +) + +type Kind string +type Runtime string +type TelemetrySignal string +type ObservabilityBackend string +type DeploymentMode string + +const ( + KindObservability Kind = "observability" + KindWebAPI Kind = "web_api" + KindMessageBroker Kind = "message_broker" + KindDatabase Kind = "database" + KindCache Kind = "cache" + KindStorage Kind = "storage" + + RuntimeKubernetes Runtime = "kubernetes" + RuntimeECS Runtime = "ecs" + RuntimeCloudRun Runtime = "cloud_run" + RuntimeAzureContainerApps Runtime = "azure_container_apps" + RuntimeDigitalOceanAppPlatform Runtime = "digitalocean_app_platform" + TelemetrySignalTraces TelemetrySignal = "traces" + TelemetrySignalMetrics TelemetrySignal = "metrics" + TelemetrySignalLogs TelemetrySignal = "logs" + ObservabilityBackendOTel ObservabilityBackend = "otel" + ObservabilityBackendDatadog ObservabilityBackend = "datadog" + ObservabilityBackendPrometheus ObservabilityBackend = "prometheus" + ObservabilityBackendLoki ObservabilityBackend = "loki" + ObservabilityBackendGrafana ObservabilityBackend = "grafana" + DeploymentModeSidecar DeploymentMode = "sidecar" + DeploymentModeDaemonSet DeploymentMode = "daemonset" + DeploymentModeSiblingService DeploymentMode = "sibling_service" + DeploymentModeManaged DeploymentMode = "managed" +) + +var requirementKeyPattern = regexp.MustCompile(`^[a-z][a-z0-9]*(?:[._-][a-z0-9]+)*$`) + +var kindToProto = map[Kind]pb.RequirementKind{ + KindObservability: pb.RequirementKind_REQUIREMENT_KIND_OBSERVABILITY, + KindWebAPI: pb.RequirementKind_REQUIREMENT_KIND_WEB_API, + KindMessageBroker: pb.RequirementKind_REQUIREMENT_KIND_MESSAGE_BROKER, + KindDatabase: pb.RequirementKind_REQUIREMENT_KIND_DATABASE, + KindCache: pb.RequirementKind_REQUIREMENT_KIND_CACHE, + KindStorage: pb.RequirementKind_REQUIREMENT_KIND_STORAGE, +} + +var runtimeToProto = map[Runtime]pb.RequirementRuntime{ + RuntimeKubernetes: pb.RequirementRuntime_REQUIREMENT_RUNTIME_KUBERNETES, + RuntimeECS: pb.RequirementRuntime_REQUIREMENT_RUNTIME_ECS, + RuntimeCloudRun: pb.RequirementRuntime_REQUIREMENT_RUNTIME_CLOUD_RUN, + RuntimeAzureContainerApps: pb.RequirementRuntime_REQUIREMENT_RUNTIME_AZURE_CONTAINER_APPS, + RuntimeDigitalOceanAppPlatform: pb.RequirementRuntime_REQUIREMENT_RUNTIME_DIGITALOCEAN_APP_PLATFORM, +} + +var signalToProto = map[TelemetrySignal]pb.TelemetrySignal{ + TelemetrySignalTraces: pb.TelemetrySignal_TELEMETRY_SIGNAL_TRACES, + TelemetrySignalMetrics: pb.TelemetrySignal_TELEMETRY_SIGNAL_METRICS, + TelemetrySignalLogs: pb.TelemetrySignal_TELEMETRY_SIGNAL_LOGS, +} + +var backendToProto = map[ObservabilityBackend]pb.ObservabilityBackend{ + ObservabilityBackendOTel: pb.ObservabilityBackend_OBSERVABILITY_BACKEND_OTEL, + ObservabilityBackendDatadog: pb.ObservabilityBackend_OBSERVABILITY_BACKEND_DATADOG, + ObservabilityBackendPrometheus: pb.ObservabilityBackend_OBSERVABILITY_BACKEND_PROMETHEUS, + ObservabilityBackendLoki: pb.ObservabilityBackend_OBSERVABILITY_BACKEND_LOKI, + ObservabilityBackendGrafana: pb.ObservabilityBackend_OBSERVABILITY_BACKEND_GRAFANA, +} + +var deploymentModeToProto = map[DeploymentMode]pb.DeploymentMode{ + DeploymentModeSidecar: pb.DeploymentMode_DEPLOYMENT_MODE_SIDECAR, + DeploymentModeDaemonSet: pb.DeploymentMode_DEPLOYMENT_MODE_DAEMONSET, + DeploymentModeSiblingService: pb.DeploymentMode_DEPLOYMENT_MODE_SIBLING_SERVICE, + DeploymentModeManaged: pb.DeploymentMode_DEPLOYMENT_MODE_MANAGED, +} + +// Requirement is Workflow's provider-neutral IaC requirement model. It mirrors +// the strict protobuf contract while staying pleasant to author in Go tests and +// plugin manifest adapters. +type Requirement struct { + Key string + Kind Kind + Source string + ResourceTypeHint string + Environment string + Runtimes []Runtime + TelemetrySignals []TelemetrySignal + ObservabilityBackends []ObservabilityBackend + DeploymentModes []DeploymentMode + VendorFeatures []string + ParametersJSON []byte +} + +func (r Requirement) Validate() error { + if !requirementKeyPattern.MatchString(r.Key) { + return fmt.Errorf("invalid requirement key %q", r.Key) + } + if _, ok := kindToProto[r.Kind]; !ok { + return fmt.Errorf("invalid requirement kind %q", r.Kind) + } + for _, runtime := range r.Runtimes { + if _, ok := runtimeToProto[runtime]; !ok { + return fmt.Errorf("invalid requirement runtime %q", runtime) + } + } + for _, signal := range r.TelemetrySignals { + if _, ok := signalToProto[signal]; !ok { + return fmt.Errorf("invalid telemetry signal %q", signal) + } + } + for _, backend := range r.ObservabilityBackends { + if _, ok := backendToProto[backend]; !ok { + return fmt.Errorf("invalid observability backend %q", backend) + } + } + for _, mode := range r.DeploymentModes { + if _, ok := deploymentModeToProto[mode]; !ok { + return fmt.Errorf("invalid deployment mode %q", mode) + } + } + if len(r.ParametersJSON) > 0 && !json.Valid(r.ParametersJSON) { + return fmt.Errorf("parameters_json is not valid JSON") + } + return nil +} + +func (r Requirement) ToProto() (*pb.IaCRequirement, error) { + if err := r.Validate(); err != nil { + return nil, err + } + return &pb.IaCRequirement{ + Key: r.Key, + Kind: kindToProto[r.Kind], + Source: r.Source, + ResourceTypeHint: r.ResourceTypeHint, + Environment: r.Environment, + Runtimes: mapSlice(r.Runtimes, runtimeToProto), + TelemetrySignals: mapSlice(r.TelemetrySignals, signalToProto), + ObservabilityBackends: mapSlice(r.ObservabilityBackends, backendToProto), + DeploymentModes: mapSlice(r.DeploymentModes, deploymentModeToProto), + VendorFeatures: append([]string(nil), r.VendorFeatures...), + ParametersJson: append([]byte(nil), r.ParametersJSON...), + }, nil +} + +func FromProto(in *pb.IaCRequirement) (Requirement, error) { + if in == nil { + return Requirement{}, fmt.Errorf("iac requirement proto is nil") + } + out := Requirement{ + Key: in.GetKey(), + Kind: reverse(kindToProto, in.GetKind()), + Source: in.GetSource(), + ResourceTypeHint: in.GetResourceTypeHint(), + Environment: in.GetEnvironment(), + Runtimes: reverseSlice(runtimeToProto, in.GetRuntimes()), + TelemetrySignals: reverseSlice(signalToProto, in.GetTelemetrySignals()), + ObservabilityBackends: reverseSlice(backendToProto, in.GetObservabilityBackends()), + DeploymentModes: reverseSlice(deploymentModeToProto, in.GetDeploymentModes()), + VendorFeatures: append([]string(nil), in.GetVendorFeatures()...), + ParametersJSON: append([]byte(nil), in.GetParametersJson()...), + } + if err := out.Validate(); err != nil { + return Requirement{}, err + } + return out, nil +} + +func mapSlice[K comparable, V any](in []K, table map[K]V) []V { + out := make([]V, 0, len(in)) + for _, item := range in { + out = append(out, table[item]) + } + return out +} + +func reverse[K comparable, V comparable](table map[K]V, value V) K { + for k, v := range table { + if v == value { + return k + } + } + var zero K + return zero +} + +func reverseSlice[K comparable, V comparable](table map[K]V, in []V) []K { + out := make([]K, 0, len(in)) + for _, item := range in { + out = append(out, reverse(table, item)) + } + return out +} diff --git a/iac/requirements/types_test.go b/iac/requirements/types_test.go new file mode 100644 index 00000000..571a8446 --- /dev/null +++ b/iac/requirements/types_test.go @@ -0,0 +1,72 @@ +package requirements + +import ( + "testing" + + pb "github.com/GoCodeAlone/workflow/plugin/external/proto" +) + +func TestRequirementValidation(t *testing.T) { + req := Requirement{ + Key: "observability.telemetry.default", + Kind: KindObservability, + Runtimes: []Runtime{RuntimeKubernetes, RuntimeDigitalOceanAppPlatform}, + TelemetrySignals: []TelemetrySignal{TelemetrySignalTraces, TelemetrySignalMetrics, TelemetrySignalLogs}, + ObservabilityBackends: []ObservabilityBackend{ObservabilityBackendOTel, ObservabilityBackendDatadog}, + DeploymentModes: []DeploymentMode{DeploymentModeSidecar, DeploymentModeSiblingService}, + VendorFeatures: []string{"datadog.apm"}, + ResourceTypeHint: "infra.container_service", + ParametersJSON: []byte(`{"collector":"otel"}`), + } + if err := req.Validate(); err != nil { + t.Fatalf("Validate: %v", err) + } +} + +func TestRequirementValidationRejectsInvalidKey(t *testing.T) { + req := Requirement{Key: "CMS telemetry", Kind: KindObservability} + if err := req.Validate(); err == nil { + t.Fatal("expected invalid key error") + } +} + +func TestRequirementValidationRejectsUnknownEnum(t *testing.T) { + req := Requirement{Key: "observability.telemetry.default", Kind: Kind("telemetryish")} + err := req.Validate() + if err == nil { + t.Fatal("expected invalid kind error") + } + if got := err.Error(); got != `invalid requirement kind "telemetryish"` { + t.Fatalf("error = %q", got) + } +} + +func TestRequirementProtoRoundTrip(t *testing.T) { + req := Requirement{ + Key: "observability.telemetry.default", + Kind: KindObservability, + Source: "observability.telemetry", + ResourceTypeHint: "infra.container_service", + Environment: "production", + Runtimes: []Runtime{RuntimeECS}, + TelemetrySignals: []TelemetrySignal{TelemetrySignalTraces}, + ObservabilityBackends: []ObservabilityBackend{ObservabilityBackendOTel}, + DeploymentModes: []DeploymentMode{DeploymentModeSidecar}, + VendorFeatures: []string{"datadog.apm"}, + ParametersJSON: []byte(`{"sample":true}`), + } + proto, err := req.ToProto() + if err != nil { + t.Fatalf("ToProto: %v", err) + } + if proto.Kind != pb.RequirementKind_REQUIREMENT_KIND_OBSERVABILITY { + t.Fatalf("proto kind = %v", proto.Kind) + } + round, err := FromProto(proto) + if err != nil { + t.Fatalf("FromProto: %v", err) + } + if round.Key != req.Key || round.Kind != req.Kind || round.Runtimes[0] != RuntimeECS { + t.Fatalf("round trip = %+v, want %+v", round, req) + } +} From 79ce6d4523c05b4f3340ed4d1671b4c0f0778e17 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 00:28:57 -0400 Subject: [PATCH 13/15] feat: discover iac requirements --- cmd/wfctl/plugin_infra.go | 7 + cmd/wfctl/plugin_infra_test.go | 40 +++++ iac/requirements/discovery.go | 256 +++++++++++++++++++++++++++++ iac/requirements/discovery_test.go | 123 ++++++++++++++ iac/requirements/external.go | 63 +++++++ iac/requirements/external_test.go | 48 ++++++ 6 files changed, 537 insertions(+) create mode 100644 iac/requirements/discovery.go create mode 100644 iac/requirements/discovery_test.go create mode 100644 iac/requirements/external.go create mode 100644 iac/requirements/external_test.go diff --git a/cmd/wfctl/plugin_infra.go b/cmd/wfctl/plugin_infra.go index 52580f9b..01cdfc8b 100644 --- a/cmd/wfctl/plugin_infra.go +++ b/cmd/wfctl/plugin_infra.go @@ -6,6 +6,7 @@ import ( "path/filepath" "github.com/GoCodeAlone/workflow/config" + "github.com/GoCodeAlone/workflow/iac/requirements" ) // LoadPluginManifests loads all plugin.json files from the given plugins directory. @@ -96,3 +97,9 @@ func DetectPluginInfraNeeds(cfg *config.WorkflowConfig, manifests map[string]*co return needs } + +// DetectPluginRequirementsV2 exposes provider-neutral moduleInfraRequirementsV2 +// declarations without changing the legacy DetectPluginInfraNeeds return type. +func DetectPluginRequirementsV2(cfg *config.WorkflowConfig, manifests map[string]*config.PluginManifestFile) ([]requirements.Requirement, error) { + return requirements.DiscoverManifestRequirements(cfg, manifests) +} diff --git a/cmd/wfctl/plugin_infra_test.go b/cmd/wfctl/plugin_infra_test.go index 2931e56b..59205657 100644 --- a/cmd/wfctl/plugin_infra_test.go +++ b/cmd/wfctl/plugin_infra_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/GoCodeAlone/workflow/config" + "github.com/GoCodeAlone/workflow/iac/requirements" ) func TestLoadPluginManifests_EmptyDir(t *testing.T) { @@ -215,3 +216,42 @@ func TestDetectPluginInfraNeeds_ServiceModules(t *testing.T) { t.Errorf("type: got %q", needs[0].Type) } } + +func TestDetectPluginRequirementsV2(t *testing.T) { + cfg := &config.WorkflowConfig{ + Modules: []config.ModuleConfig{{Name: "telemetry", Type: "observability.telemetry"}}, + Services: map[string]*config.ServiceConfig{ + "api": { + Binary: "./cmd/api", + Expose: []config.ExposeConfig{{Port: 8080, Protocol: "http"}}, + }, + }, + } + manifests := map[string]*config.PluginManifestFile{ + "workflow-plugin-observability": { + Name: "workflow-plugin-observability", + ModuleInfraRequirementsV2: config.PluginInfraRequirementsV2{ + "observability.telemetry": { + Requires: []config.ModuleInfraRequirementV2{{ + Key: "observability.telemetry.default", + Kind: "observability", + TelemetrySignals: []string{"traces"}, + ObservabilityBackends: []string{"otel"}, + DeploymentModes: []string{"sidecar"}, + }}, + }, + }, + }, + } + + reqs, err := DetectPluginRequirementsV2(cfg, manifests) + if err != nil { + t.Fatalf("DetectPluginRequirementsV2: %v", err) + } + if len(reqs) != 1 { + t.Fatalf("requirements len = %d, want 1", len(reqs)) + } + if reqs[0].Key != "observability.telemetry.default" || reqs[0].Kind != requirements.KindObservability { + t.Fatalf("requirement = %+v", reqs[0]) + } +} diff --git a/iac/requirements/discovery.go b/iac/requirements/discovery.go new file mode 100644 index 00000000..3f535d1c --- /dev/null +++ b/iac/requirements/discovery.go @@ -0,0 +1,256 @@ +package requirements + +import ( + "context" + "encoding/json" + "fmt" + "sort" + + "github.com/GoCodeAlone/workflow/config" +) + +type Input struct { + Config *config.WorkflowConfig + Manifests map[string]*config.PluginManifestFile + Providers []Provider + Environment string +} + +type Provider interface { + IaCRequirements(context.Context, Input) ([]Requirement, error) +} + +type ProviderFunc func(context.Context, Input) ([]Requirement, error) + +func (f ProviderFunc) IaCRequirements(ctx context.Context, input Input) ([]Requirement, error) { + return f(ctx, input) +} + +func Discover(ctx context.Context, input Input) ([]Requirement, error) { + var out []Requirement + seen := make(map[string]struct{}) + + add := func(req Requirement) error { + if req.Environment == "" { + req.Environment = input.Environment + } + if err := req.Validate(); err != nil { + return err + } + if _, ok := seen[req.Key]; ok { + return nil + } + seen[req.Key] = struct{}{} + out = append(out, req) + return nil + } + + for _, req := range discoverBuiltIns(input.Config) { + if err := add(req); err != nil { + return nil, err + } + } + manifestReqs, err := discoverManifestRequirements(input.Config, input.Manifests) + if err != nil { + return nil, err + } + for _, req := range manifestReqs { + if err := add(req); err != nil { + return nil, err + } + } + for _, provider := range input.Providers { + reqs, err := provider.IaCRequirements(ctx, input) + if err != nil { + return nil, err + } + for _, req := range reqs { + if err := add(req); err != nil { + return nil, err + } + } + } + + satisfied := satisfiedKeys(input.Config) + if len(satisfied) == 0 { + return out, nil + } + filtered := out[:0] + for _, req := range out { + if _, ok := satisfied[req.Key]; ok { + continue + } + filtered = append(filtered, req) + } + return filtered, nil +} + +func DiscoverManifestRequirements(cfg *config.WorkflowConfig, manifests map[string]*config.PluginManifestFile) ([]Requirement, error) { + reqs, err := discoverManifestRequirements(cfg, manifests) + if err != nil { + return nil, err + } + seen := make(map[string]struct{}) + out := make([]Requirement, 0, len(reqs)) + for _, req := range reqs { + if err := req.Validate(); err != nil { + return nil, err + } + if _, ok := seen[req.Key]; ok { + continue + } + seen[req.Key] = struct{}{} + out = append(out, req) + } + satisfied := satisfiedKeys(cfg) + if len(satisfied) == 0 { + return out, nil + } + filtered := out[:0] + for _, req := range out { + if _, ok := satisfied[req.Key]; ok { + continue + } + filtered = append(filtered, req) + } + return filtered, nil +} + +func discoverBuiltIns(cfg *config.WorkflowConfig) []Requirement { + if cfg == nil { + return nil + } + var out []Requirement + for _, name := range sortedServiceNames(cfg.Services) { + svc := cfg.Services[name] + if svc == nil { + continue + } + if svc.Binary != "" || len(svc.Expose) > 0 { + out = append(out, Requirement{ + Key: "web.api." + name, + Kind: KindWebAPI, + Source: "services." + name, + ResourceTypeHint: "infra.container_service", + }) + } + } + if cfg.Mesh != nil && (cfg.Mesh.Transport == "nats" || cfg.Mesh.NATS != nil) { + out = append(out, Requirement{ + Key: "messaging.nats.default", + Kind: KindMessageBroker, + Source: "mesh", + ResourceTypeHint: "infra.message_broker", + VendorFeatures: []string{"nats"}, + }) + } + return out +} + +func discoverManifestRequirements(cfg *config.WorkflowConfig, manifests map[string]*config.PluginManifestFile) ([]Requirement, error) { + if cfg == nil || len(manifests) == 0 { + return nil, nil + } + var out []Requirement + for _, mod := range allModules(cfg) { + for _, manifestName := range sortedManifestNames(manifests) { + manifest := manifests[manifestName] + if manifest == nil || manifest.ModuleInfraRequirementsV2 == nil { + continue + } + spec := manifest.ModuleInfraRequirementsV2[mod.Type] + if spec == nil { + continue + } + for _, raw := range spec.Requires { + req, err := FromManifestRequirement(raw) + if err != nil { + return nil, fmt.Errorf("module %q requirement %q: %w", mod.Type, raw.Key, err) + } + if req.Source == "" { + req.Source = mod.Type + } + out = append(out, req) + } + } + } + return out, nil +} + +func FromManifestRequirement(raw config.ModuleInfraRequirementV2) (Requirement, error) { + var params []byte + if len(raw.Parameters) > 0 { + encoded, err := json.Marshal(raw.Parameters) + if err != nil { + return Requirement{}, fmt.Errorf("marshal requirement parameters: %w", err) + } + params = encoded + } + req := Requirement{ + Key: raw.Key, + Kind: Kind(raw.Kind), + Source: raw.Source, + ResourceTypeHint: raw.ResourceTypeHint, + Environment: raw.Environment, + Runtimes: castSlice[Runtime](raw.Runtimes), + TelemetrySignals: castSlice[TelemetrySignal](raw.TelemetrySignals), + ObservabilityBackends: castSlice[ObservabilityBackend](raw.ObservabilityBackends), + DeploymentModes: castSlice[DeploymentMode](raw.DeploymentModes), + VendorFeatures: append([]string(nil), raw.VendorFeatures...), + ParametersJSON: params, + } + if err := req.Validate(); err != nil { + return Requirement{}, err + } + return req, nil +} + +func allModules(cfg *config.WorkflowConfig) []config.ModuleConfig { + if cfg == nil { + return nil + } + out := append([]config.ModuleConfig(nil), cfg.Modules...) + for _, name := range sortedServiceNames(cfg.Services) { + svc := cfg.Services[name] + if svc != nil { + out = append(out, svc.Modules...) + } + } + return out +} + +func satisfiedKeys(cfg *config.WorkflowConfig) map[string]struct{} { + out := make(map[string]struct{}) + for _, mod := range allModules(cfg) { + for _, key := range mod.Satisfies { + out[key] = struct{}{} + } + } + return out +} + +func castSlice[T ~string](in []string) []T { + out := make([]T, 0, len(in)) + for _, item := range in { + out = append(out, T(item)) + } + return out +} + +func sortedServiceNames(services map[string]*config.ServiceConfig) []string { + names := make([]string, 0, len(services)) + for name := range services { + names = append(names, name) + } + sort.Strings(names) + return names +} + +func sortedManifestNames(manifests map[string]*config.PluginManifestFile) []string { + names := make([]string, 0, len(manifests)) + for name := range manifests { + names = append(names, name) + } + sort.Strings(names) + return names +} diff --git a/iac/requirements/discovery_test.go b/iac/requirements/discovery_test.go new file mode 100644 index 00000000..7a20650c --- /dev/null +++ b/iac/requirements/discovery_test.go @@ -0,0 +1,123 @@ +package requirements + +import ( + "context" + "testing" + + "github.com/GoCodeAlone/workflow/config" +) + +func TestDiscoverRequirementsFromConfigShape(t *testing.T) { + cfg := &config.WorkflowConfig{ + Services: map[string]*config.ServiceConfig{ + "api": { + Binary: "./cmd/api", + Expose: []config.ExposeConfig{{ + Port: 8080, + Protocol: "http", + }}, + }, + }, + Mesh: &config.MeshConfig{ + Transport: "nats", + }, + } + + reqs, err := Discover(context.Background(), Input{Config: cfg}) + if err != nil { + t.Fatalf("Discover: %v", err) + } + assertHasRequirement(t, reqs, "web.api.api", KindWebAPI) + assertHasRequirement(t, reqs, "messaging.nats.default", KindMessageBroker) +} + +func TestDiscoverRequirementsFromManifestV2(t *testing.T) { + cfg := &config.WorkflowConfig{ + Modules: []config.ModuleConfig{{Name: "telemetry", Type: "observability.telemetry"}}, + } + manifests := map[string]*config.PluginManifestFile{ + "workflow-plugin-observability": { + ModuleInfraRequirementsV2: config.PluginInfraRequirementsV2{ + "observability.telemetry": { + Requires: []config.ModuleInfraRequirementV2{{ + Key: "observability.telemetry.default", + Kind: "observability", + Source: "observability.telemetry", + ResourceTypeHint: "infra.container_service", + Runtimes: []string{"kubernetes"}, + TelemetrySignals: []string{"traces", "metrics", "logs"}, + ObservabilityBackends: []string{"otel"}, + DeploymentModes: []string{"sidecar"}, + }}, + }, + }, + }, + } + + reqs, err := Discover(context.Background(), Input{Config: cfg, Manifests: manifests}) + if err != nil { + t.Fatalf("Discover: %v", err) + } + req := assertHasRequirement(t, reqs, "observability.telemetry.default", KindObservability) + if req.ResourceTypeHint != "infra.container_service" { + t.Fatalf("ResourceTypeHint = %q", req.ResourceTypeHint) + } + if len(req.TelemetrySignals) != 3 { + t.Fatalf("TelemetrySignals = %v", req.TelemetrySignals) + } +} + +func TestDiscoverRequirementsFiltersSatisfiedKeys(t *testing.T) { + cfg := &config.WorkflowConfig{ + Modules: []config.ModuleConfig{ + {Name: "telemetry", Type: "observability.telemetry"}, + {Name: "otel", Type: "infra.container_service", Satisfies: []string{"observability.telemetry.default"}}, + }, + } + manifests := map[string]*config.PluginManifestFile{ + "workflow-plugin-observability": { + ModuleInfraRequirementsV2: config.PluginInfraRequirementsV2{ + "observability.telemetry": { + Requires: []config.ModuleInfraRequirementV2{{ + Key: "observability.telemetry.default", + Kind: "observability", + }}, + }, + }, + }, + } + + reqs, err := Discover(context.Background(), Input{Config: cfg, Manifests: manifests}) + if err != nil { + t.Fatalf("Discover: %v", err) + } + if len(reqs) != 0 { + t.Fatalf("expected satisfied requirement to be filtered; got %+v", reqs) + } +} + +func TestDiscoverRequirementsFromInProcessProvider(t *testing.T) { + provider := ProviderFunc(func(context.Context, Input) ([]Requirement, error) { + return []Requirement{{Key: "cache.redis.default", Kind: KindCache}}, nil + }) + + reqs, err := Discover(context.Background(), Input{Providers: []Provider{provider}}) + if err != nil { + t.Fatalf("Discover: %v", err) + } + assertHasRequirement(t, reqs, "cache.redis.default", KindCache) +} + +func assertHasRequirement(t *testing.T, reqs []Requirement, key string, kind Kind) Requirement { + t.Helper() + for _, req := range reqs { + if req.Key == key { + if req.Kind != kind { + t.Fatalf("requirement %q kind = %q, want %q", key, req.Kind, kind) + } + return req + } + } + t.Fatalf("requirement %q not found in %+v", key, reqs) + return Requirement{} +} diff --git a/iac/requirements/external.go b/iac/requirements/external.go new file mode 100644 index 00000000..ae0e1022 --- /dev/null +++ b/iac/requirements/external.go @@ -0,0 +1,63 @@ +package requirements + +import ( + "context" + "fmt" + + "github.com/GoCodeAlone/workflow/config" + pb "github.com/GoCodeAlone/workflow/plugin/external/proto" +) + +type ExternalDiscoveryProvider struct { + Client pb.IaCRequirementDiscoveryClient + Context *pb.RequirementContext + ModuleConfigJSON []byte +} + +func (p ExternalDiscoveryProvider) IaCRequirements(ctx context.Context, input Input) ([]Requirement, error) { + if p.Client == nil { + return nil, fmt.Errorf("iac requirement discovery client is nil") + } + req := &pb.DiscoverRequirementsRequest{ + Context: p.Context, + ModuleConfigJson: append([]byte(nil), p.ModuleConfigJSON...), + } + if req.Context == nil { + req.Context = RequirementContextFromConfig(input.Config, input.Environment) + } + resp, err := p.Client.DiscoverRequirements(ctx, req) + if err != nil { + return nil, err + } + out := make([]Requirement, 0, len(resp.GetRequirements())) + for _, protoReq := range resp.GetRequirements() { + req, err := FromProto(protoReq) + if err != nil { + return nil, err + } + out = append(out, req) + } + return out, nil +} + +func RequirementContextFromConfig(cfg *config.WorkflowConfig, environment string) *pb.RequirementContext { + ctx := &pb.RequirementContext{Environment: environment} + if cfg == nil { + return ctx + } + refs := allModules(cfg) + ctx.Modules = make([]*pb.ModuleRef, 0, len(refs)) + for _, mod := range refs { + ctx.Modules = append(ctx.Modules, &pb.ModuleRef{ + Name: mod.Name, + Type: mod.Type, + Satisfies: append([]string(nil), mod.Satisfies...), + }) + } + if cfg.Plugins != nil { + for _, plugin := range cfg.Plugins.External { + ctx.PluginIds = append(ctx.PluginIds, plugin.Name) + } + } + return ctx +} diff --git a/iac/requirements/external_test.go b/iac/requirements/external_test.go new file mode 100644 index 00000000..18afe843 --- /dev/null +++ b/iac/requirements/external_test.go @@ -0,0 +1,48 @@ +package requirements + +import ( + "context" + "testing" + + pb "github.com/GoCodeAlone/workflow/plugin/external/proto" + "google.golang.org/grpc" +) + +func TestExternalRequirementDiscovery(t *testing.T) { + client := &fakeRequirementDiscoveryClient{ + resp: &pb.DiscoverRequirementsResponse{ + Requirements: []*pb.IaCRequirement{{ + Key: "observability.telemetry.default", + Kind: pb.RequirementKind_REQUIREMENT_KIND_OBSERVABILITY, + }}, + }, + } + provider := ExternalDiscoveryProvider{ + Client: client, + ModuleConfigJSON: []byte(`{"backends":["otel"]}`), + } + + reqs, err := provider.IaCRequirements(context.Background(), Input{Environment: "production"}) + if err != nil { + t.Fatalf("IaCRequirements: %v", err) + } + if string(client.last.GetModuleConfigJson()) != `{"backends":["otel"]}` { + t.Fatalf("module config json = %s", string(client.last.GetModuleConfigJson())) + } + if client.last.GetContext().GetEnvironment() != "production" { + t.Fatalf("context environment = %q", client.last.GetContext().GetEnvironment()) + } + assertHasRequirement(t, reqs, "observability.telemetry.default", KindObservability) +} + +type fakeRequirementDiscoveryClient struct { + pb.IaCRequirementDiscoveryClient + last *pb.DiscoverRequirementsRequest + resp *pb.DiscoverRequirementsResponse + err error +} + +func (f *fakeRequirementDiscoveryClient) DiscoverRequirements(_ context.Context, req *pb.DiscoverRequirementsRequest, _ ...grpc.CallOption) (*pb.DiscoverRequirementsResponse, error) { + f.last = req + return f.resp, f.err +} From d38202e6d2f575b07483396045ce433e14cce130 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 00:45:45 -0400 Subject: [PATCH 14/15] fix: avoid requirement range copies --- iac/requirements/discovery.go | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/iac/requirements/discovery.go b/iac/requirements/discovery.go index 3f535d1c..7e5edb6d 100644 --- a/iac/requirements/discovery.go +++ b/iac/requirements/discovery.go @@ -45,7 +45,9 @@ func Discover(ctx context.Context, input Input) ([]Requirement, error) { return nil } - for _, req := range discoverBuiltIns(input.Config) { + builtIns := discoverBuiltIns(input.Config) + for i := range builtIns { + req := builtIns[i] if err := add(req); err != nil { return nil, err } @@ -54,7 +56,8 @@ func Discover(ctx context.Context, input Input) ([]Requirement, error) { if err != nil { return nil, err } - for _, req := range manifestReqs { + for i := range manifestReqs { + req := manifestReqs[i] if err := add(req); err != nil { return nil, err } @@ -64,7 +67,8 @@ func Discover(ctx context.Context, input Input) ([]Requirement, error) { if err != nil { return nil, err } - for _, req := range reqs { + for i := range reqs { + req := reqs[i] if err := add(req); err != nil { return nil, err } @@ -76,7 +80,8 @@ func Discover(ctx context.Context, input Input) ([]Requirement, error) { return out, nil } filtered := out[:0] - for _, req := range out { + for i := range out { + req := out[i] if _, ok := satisfied[req.Key]; ok { continue } @@ -92,7 +97,8 @@ func DiscoverManifestRequirements(cfg *config.WorkflowConfig, manifests map[stri } seen := make(map[string]struct{}) out := make([]Requirement, 0, len(reqs)) - for _, req := range reqs { + for i := range reqs { + req := reqs[i] if err := req.Validate(); err != nil { return nil, err } @@ -107,7 +113,8 @@ func DiscoverManifestRequirements(cfg *config.WorkflowConfig, manifests map[stri return out, nil } filtered := out[:0] - for _, req := range out { + for i := range out { + req := out[i] if _, ok := satisfied[req.Key]; ok { continue } @@ -162,7 +169,8 @@ func discoverManifestRequirements(cfg *config.WorkflowConfig, manifests map[stri if spec == nil { continue } - for _, raw := range spec.Requires { + for i := range spec.Requires { + raw := spec.Requires[i] req, err := FromManifestRequirement(raw) if err != nil { return nil, fmt.Errorf("module %q requirement %q: %w", mod.Type, raw.Key, err) From df783beccb4a6f765f9dceff3c773d9b3ef304d7 Mon Sep 17 00:00:00 2001 From: Jon Langevin Date: Mon, 25 May 2026 01:03:04 -0400 Subject: [PATCH 15/15] fix: cover iac requirement services --- wftest/bdd/strict_iac.go | 8 ++++++++ wftest/bdd/strict_iac_test.go | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/wftest/bdd/strict_iac.go b/wftest/bdd/strict_iac.go index 03098076..62eb4fa1 100644 --- a/wftest/bdd/strict_iac.go +++ b/wftest/bdd/strict_iac.go @@ -81,6 +81,14 @@ var iacServiceChecks = []iacServiceCheck{ _, ok := p.(pb.IaCStateBackendServer) return ok }}, + {"workflow.plugin.external.iac.IaCRequirementDiscovery", func(p any) bool { + _, ok := p.(pb.IaCRequirementDiscoveryServer) + return ok + }}, + {"workflow.plugin.external.iac.IaCProviderRequirementMapper", func(p any) bool { + _, ok := p.(pb.IaCProviderRequirementMapperServer) + return ok + }}, } // AssertProviderCapabilitiesMatchRegistration asserts that every typed diff --git a/wftest/bdd/strict_iac_test.go b/wftest/bdd/strict_iac_test.go index ca87d352..d8eced94 100644 --- a/wftest/bdd/strict_iac_test.go +++ b/wftest/bdd/strict_iac_test.go @@ -62,6 +62,8 @@ func TestAssertProviderCapabilitiesMatchRegistration_ManuallyRegisteredMissingOp "IaCProviderValidator", "IaCProviderDriftConfigDetector", "ResourceDriver", + "IaCRequirementDiscovery", + "IaCProviderRequirementMapper", } joined := strings.Join(rec.errors, "\n") for _, name := range wantContains { @@ -149,6 +151,8 @@ type allCapabilitiesStub struct { pb.UnimplementedIaCProviderValidatorServer pb.UnimplementedIaCProviderDriftConfigDetectorServer pb.UnimplementedResourceDriverServer + pb.UnimplementedIaCRequirementDiscoveryServer + pb.UnimplementedIaCProviderRequirementMapperServer } // requiredOnlyStub satisfies Required ONLY.