Skip to content

docs(concepts): provider-defined functions + caveats - #29

Draft
so0k wants to merge 1 commit into
mainfrom
docs/provider-defined-functions
Draft

docs(concepts): provider-defined functions + caveats#29
so0k wants to merge 1 commit into
mainfrom
docs/provider-defined-functions

Conversation

@so0k

@so0k so0k commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator

Documents the provider-defined function bindings from open-constructs/cdk-terrain#296 (provider.functions.* API) and the three review-round caveats (OpenTofu 1.7/1.8 generation-vs-usage skew, provider-config self-reference cycle, ephemeral outputs needing ephemeralasnull + sensitive), and fixes the now-stale 'out of scope' Limitations bullet.

Draft until cdk-terrain#296 merges — the functions getter API documented here ships with it.

Adds a Provider-Defined Functions section to the functions concept page,
covering the generated `provider.functions.*` bindings from
open-constructs/cdk-terrain#296, the unconditional targetVersions
validation, and three caveats surfaced during that PR's review rounds:

- the OpenTofu 1.7 language-support vs 1.8 schema-emission skew
  (generating bindings needs a newer binary than using them),
- the provider-configuration self-reference cycle (warning moved here
  from the generated per-method JSDoc per review consensus),
- ephemeral-derived outputs needing Fn.ephemeralasnull + sensitive.

Also updates the stale Limitations bullet that declared provider-defined
functions out of validation scope - they are now validated as a family.
@mintlify

mintlify Bot commented Jul 18, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
cdkterrain 🟢 Ready View Preview Jul 18, 2026, 9:06 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

so0k added a commit to open-constructs/cdk-terrain that referenced this pull request Jul 23, 2026
…ons (RFC-04) (#296)

Implements RFC-04 — **provider feature availability**: support the newer
provider plugin-protocol capability families with `targetVersions`-aware
codegen and synth-time validation. Proposal, dataset, sweep tooling and
interactive report live in **open-constructs/cdktn-planning** →
`RFCS/04-provider-feature-availability/` (only the merged matrix is
vendored here, matching the function-availability split).

Builds directly on the #269 foundation (`targetVersions` +
`ValidateFeatureTargetSupport`) and the #268 usage-registry pattern.

## Guiding decision

**Generate the full surface the schema offers; narrow per project at
synth time via `targetVersions`.** Generation-time filtering would fork
the generated API by project configuration — impossible for prebuilt
providers and hostile to caching. Constraints baked into the validations
are the per-product `>=` ranges from the sweep dataset.

## Review guide (one commit per RFC rollout item)

1. **`chore: vendor provider-feature availability matrix`** — dataset
digest + README only, no behavior change.
2. **`feat(lib): TerraformEphemeralResource`** — new public base class
synthesizing to the top-level `ephemeral` key (JSON + HCL renderer),
refs as `ephemeral.<type>.<id>.<attr>`, no
provisioners/connection/import/move. Constructor registers the
target-version validation unconditionally (new API surface — only fires
on use, no feature flag per RFC). Internal `providerFeatureConstraints`
map sourced from the vendored matrix.
3. **`feat(provider-generator): acquire newer provider-protocol schema
sections`** (Phase 0, a bugfix on its own) — commons types for
`functions` / `ephemeral_resource_schemas` / `resource_identity_schemas`
/ `write_only`; sanitizer walks ephemeral schemas; fetched schemas
stamped with the fetching CLI; **cache key now includes CLI
product+minor** (a schema fetched once with an old CLI no longer poisons
every later generation); fetch-time warning when the fetching binary
structurally cannot emit sections the targets admit.
4. **`feat(provider-generator): generate ephemeral resource bindings`**
— third schema family mirroring the `data_` pipeline
(`EphemeralRandomPassword` in `ephemeral-random-password/`), config
extends `TerraformEphemeralMetaArguments`, no `generateConfigForImport`.
Zero churn in existing snapshots (ephemeral models append after
resources/data sources; class-name dedup is order-dependent).
5. **`feat(provider-generator): generate provider-defined function
bindings`** — `TimeProviderFunctions.rfc3339Parse(ts)` →
`${provider::time::rfc3339_parse(...)}`; namespace defaults to the
registry short name with a `providerLocalName` override (local names
change the namespace, aliases don't). Runtime flows through one public
jsii chokepoint (`TerraformProviderFunction.invoke`) feeding a usage
registry; `TerraformStack` validates usage against `terraform >=1.8.0` /
`opentofu >=1.7.0` — note the deliberate asymmetry: OpenTofu *language*
support (1.7.0) predates its schema *emission* (1.8.0), so generation
and validation use different boundaries.
6. **`feat(provider-generator): deprecate write-only attribute getters,
validate usage`** — providers never persist write-only values (every
read is `null` by protocol contract), so the state-backed getter is a
trap: emitted `@deprecated` now, removal rides the next prebuilt major
(JSII-breaking otherwise). Setting one (setter or constructor config)
registers usage via a new protected
`TerraformResource.registerProviderFeatureUsage` hook — generated code
reaches the validation machinery only by extending base classes.
7. **`feat(cli): thread targetVersions into cdktn get`** —
`GetOptions.targetVersions` → `ConstructsMaker` → `readSchema`, driving
the Phase 0 fetch-time warning; `constraints.json` gains diagnostic
stamps (`targetVersions`, fetching `cli`) without affecting the
`filterAlreadyGenerated` staleness logic (targets don't change codegen
output, so they must not force regeneration).

## Test coverage

- Generator: snapshot tests against **real `terraform providers schema
-json` fragments** from the sweep (random ephemeral, time functions
incl. object returns, vault `*_wo`), plus a synthetic fixture for
variadic/reserved-name mapping branches. Zero churn in pre-existing
snapshots.
- Core: validation matrices mirroring `validations.test.ts`
(admit/exclude per product, hint text, the OpenTofu 1.7.0 asymmetry,
registry resets).
- Schema: emission-gap logic matrix, cache-key suffix behavior,
sanitizer walk over ephemeral schemas; CLI stamps in network snapshots
are stubbed (environment-dependent).

## Known/deferred

- `matchers.test.ts › toPlanSuccessfully` fails in this environment
before and after these changes (downloads the real docker provider;
verified pre-existing via stash on the unmodified tree).
- Deferred per RFC Phase 4: resource identity consumption (schema
plumbing already carried), list resources / actions / state stores
(Terraform-only today; re-evaluate on opentofu/opentofu#3787).
- **Follow-ups tracked as issues**: #308 (nested write-only
registration), #309 (matrix drift check / in-repo tooling), #310
(`hcl2cdk` ephemeral conversion), #311 (edge-provider schema
cross-language coverage), #312 (ephemeral integration test gated on TF
>= 1.10), #313 (pre-existing HCL renderer defects), #304 (first-class
`provider_meta`; #314 closed as its duplicate), #316 (remove the
deprecated write-only getters at the next prebuilt-provider major — the
Phase 3 end state). New this round: #336 (structural typing for
object-shaped function params/returns), #337 (runtime CI thin slice on
terraform 1.15.x + opentofu 1.12.x — CI's Terraform ceiling is 1.6.5, so
the new schema sections are covered by fixture unit tests, the
edge-provider compile slice below, and the external demo harness until
#337 lands).

## Review findings addressed (from the demo-harness verification
comment)

- **Fixed — `targetVersions` validation bypass**:
`CdktfConfig.targetVersions` (the `runGetInDir` path) now validates via
commons `validateTargetVersions` (warn + ignore), and the emission-gap
check treats invalid ranges as not-wanted instead of throwing — a
malformed range previously crashed `cdktn get` via `semver.intersects`.
- **Fixed — ephemeral lifecycle narrowed**: new
`TerraformEphemeralResourceLifecycle` (`precondition`/`postcondition`
only) replaces the full managed-resource lifecycle on the ephemeral API,
before it ships as jsii surface.
- **Fixed (docs) — provider-fn self-reference cycle**: generated
provider-function JSDoc and `TerraformProviderFunction.invoke` now warn
against calling a provider's functions inside that same provider's
configuration block.
- **Documented — ephemeral × write-only**: registration deliberately
skips ephemeral resources — write-only is a state concept, ephemeral
resources have no state, and no schema in the sweep (incl. vault's 16
ephemeral resources) combines the two.
- **Follow-up — nested write-only registration** (#308): `write_only`
inside nested blocks gets the deprecated getter but skips usage
registration; deep config scanning deserves its own PR (a miss degrades
to the plan-time error, not silent breakage).
- **Pre-existing / by design**: the AWS barrel-import OOM predates this
PR (lazy-index is the existing mitigation); `Fn.ephemeralasnull` +
`sensitive` on outputs is Terraform semantics (docs candidate); list
resources / actions / resource identity codegen is the RFC Phase 4
deferral noted above.

## Second review round addressed

- **Fixed — cross-App usage-registry leak**: `App` construction now
resets both usage registries (a new App = a new synthesis session).
Within an App the process-global registry is by design — every stack
resolves the same `targetVersions` from App context — but usage no
longer leaks into later, unrelated Apps in the same process (the
reviewer's jest scenario). Regression tests cover the exact sequence;
the flag-gated `Fn` registry had the same latent leak and is reset too.
- **Fixed — emission-gap warning on cache hits**: the warning moved from
`readProviderSchema` into `readSchema`, running for cached *and* fresh
schemas using the `cli_name`/`cli_version` stamps the schema carries.
Regression test: two `readSchema` calls against a cache dir → one
producer call, two warnings.
- **Docs — matrix as source of truth**: both hand-maintained maps now
name `features-matrix.json` as their source and cross-reference each
other; automated drift check tracked in #309.

## Third review round addressed (cfncompat/awscc demo findings)

- **Fixed — dynamic-typed provider-function returns coerced to string**:
generated wrappers for `dynamic`/`object`/`map` return types no longer
wrap in `Token.asString(...)`; they return the raw `invoke()`
`IResolvable`, which `Tokenization.isResolvable()` recognizes —
struct-typed attribute assignments (`OutputReference.internalValue`) no
longer vanish silently from synth output.
- **Fixed — `invoke()` dropped literal `null` positional arguments**:
arguments are now validated per position (variadic flattening stays in
the generated wrappers where the signature is known), and a latent third
bug this exposed was fixed too: `FunctionCall` rendered args via
`Array.prototype.join`, which collapses `null` entries to empty strings
— resolved `null`/`undefined` now render as the Terraform `null`
keyword. Regression tests pin the exact
`provider::cfncompat::condition_if(true, null, {"a" = 1})` rendering.


## Fourth review round addressed (jsteinich's CHANGES_REQUESTED)

Seven commits on top of the reviewed head, one per finding group (inline
replies on each thread carry the details):

1. **Schema fidelity** — `FunctionParameter` gains `is_nullable`,
`FunctionSignature` gains `deprecation_message`, and both drop
`description_kind` (verified against
`internal/command/jsonfunction/{function,parameter}.go` and the OpenTofu
equivalent: that field does not exist on function JSON;
`allow_null_value`/`allow_unknown_values` are protocol-only names — the
old comment was wrong). OpenTofu emits no `deprecation_message` at all
(divergence, documented).
2. **Recursive, honest type mapping** — collections recurse
(`list(number)` → `number[]` via `Token.asNumberList`, `set(bool)` param
→ `Array<boolean | IResolvable>`, nested compose); object/map/dynamic
returns are declared `IResolvable` instead of `any` (property access on
a token is now a compile error); `is_nullable` consumed (trailing →
jsii-optional, mid-position → `any`, variadic → `any[]`, docstrings say
`T | null`); `deprecation_message` → `@deprecated`; name collisions
hard-fail generation with an actionable error. Structural helpers for
object shapes: #336.
3. **App-owned usage registries** — recording moved to token-resolve
time keyed by the resolving stack's `node.root` (WeakMaps); the
App-constructor resets and the "pathological" disclaimer are gone; the
interleaved-App false negative is structurally impossible and pinned by
regression tests for both registries.
4. **Functions move onto the provider class** —
`time.functions.rfc3339Parse(ts)` via a memoized getter fed by
`this.terraformResourceType` (the exact `required_providers` key, so the
namespace is correct by construction); the static class and
`providerLocalName` parameter are gone, mooting the `providerAlias`
naming question. Per-method self-reference JSDoc dropped (kept once on
`invoke`; docs PR: open-constructs/cdk-terrain-docs#29).
5. **Cleanups** — `registerProviderFeatureUsage` moved to
`TerraformElement` (ephemeral resources reuse it); enum casts replaced
by a membership guard + direct `ProviderFeature` indexing; hints get
their own map instead of runtime label-mangling (messages
byte-identical); write-only registration treats explicit `null` as
omission (`!= null`, both constructor and setter paths, four pinned
tests).
6. **Demo-validation fixes** — exercising the generated bindings in a
real app ([demo
PR](sakul-learning/cdktn-provider-features-demo#5))
caught three bugs snapshots couldn't: the sibling import needed `/index`
under `nodenext`; the wrapper constructor's TS parameter property is
rejected by Node's native type-stripping (jsii accepts it — Node is the
stricter consumer); variadic rest params need `Array<T>` for union
element types.
7. **Edge-provider compile coverage** (closes #311) — the edge schema
now carries nine functions (one per generator branch, incl. all three
nullability shapes and deprecation), an ephemeral resource, and a
`write_only` attribute; its bindings ride the existing postbuild jsii +
pacmak flow for all five languages and the `test/<lang>/edge`
native-compile suites, independent of CI's Terraform version.

**External validation** (full matrix in the [demo
PR](sakul-learning/cdktn-provider-features-demo#5)):
terraform 1.15.7 and opentofu 1.12.3 generate byte-identical bindings
modulo registry-host doc links; schema cache keys per CLI product+minor;
omitted/explicit/mid-position nullable args all render the bare `null`
keyword in position; generated bindings pass tsc + jsii + pacmak; the
targetVersions validation error was demonstrated live through the
resolve-time registry.

## Resolves Terraform CDK issues

- hashicorp/terraform-cdk#3886
- hashicorp/terraform-cdk#3686

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
X-Guardian pushed a commit to X-Guardian/cdk-terrain that referenced this pull request Aug 10, 2026
…ons (RFC-04) (open-constructs#296)

Implements RFC-04 — **provider feature availability**: support the newer
provider plugin-protocol capability families with `targetVersions`-aware
codegen and synth-time validation. Proposal, dataset, sweep tooling and
interactive report live in **open-constructs/cdktn-planning** →
`RFCS/04-provider-feature-availability/` (only the merged matrix is
vendored here, matching the function-availability split).

Builds directly on the open-constructs#269 foundation (`targetVersions` +
`ValidateFeatureTargetSupport`) and the open-constructs#268 usage-registry pattern.

## Guiding decision

**Generate the full surface the schema offers; narrow per project at
synth time via `targetVersions`.** Generation-time filtering would fork
the generated API by project configuration — impossible for prebuilt
providers and hostile to caching. Constraints baked into the validations
are the per-product `>=` ranges from the sweep dataset.

## Review guide (one commit per RFC rollout item)

1. **`chore: vendor provider-feature availability matrix`** — dataset
digest + README only, no behavior change.
2. **`feat(lib): TerraformEphemeralResource`** — new public base class
synthesizing to the top-level `ephemeral` key (JSON + HCL renderer),
refs as `ephemeral.<type>.<id>.<attr>`, no
provisioners/connection/import/move. Constructor registers the
target-version validation unconditionally (new API surface — only fires
on use, no feature flag per RFC). Internal `providerFeatureConstraints`
map sourced from the vendored matrix.
3. **`feat(provider-generator): acquire newer provider-protocol schema
sections`** (Phase 0, a bugfix on its own) — commons types for
`functions` / `ephemeral_resource_schemas` / `resource_identity_schemas`
/ `write_only`; sanitizer walks ephemeral schemas; fetched schemas
stamped with the fetching CLI; **cache key now includes CLI
product+minor** (a schema fetched once with an old CLI no longer poisons
every later generation); fetch-time warning when the fetching binary
structurally cannot emit sections the targets admit.
4. **`feat(provider-generator): generate ephemeral resource bindings`**
— third schema family mirroring the `data_` pipeline
(`EphemeralRandomPassword` in `ephemeral-random-password/`), config
extends `TerraformEphemeralMetaArguments`, no `generateConfigForImport`.
Zero churn in existing snapshots (ephemeral models append after
resources/data sources; class-name dedup is order-dependent).
5. **`feat(provider-generator): generate provider-defined function
bindings`** — `TimeProviderFunctions.rfc3339Parse(ts)` →
`${provider::time::rfc3339_parse(...)}`; namespace defaults to the
registry short name with a `providerLocalName` override (local names
change the namespace, aliases don't). Runtime flows through one public
jsii chokepoint (`TerraformProviderFunction.invoke`) feeding a usage
registry; `TerraformStack` validates usage against `terraform >=1.8.0` /
`opentofu >=1.7.0` — note the deliberate asymmetry: OpenTofu *language*
support (1.7.0) predates its schema *emission* (1.8.0), so generation
and validation use different boundaries.
6. **`feat(provider-generator): deprecate write-only attribute getters,
validate usage`** — providers never persist write-only values (every
read is `null` by protocol contract), so the state-backed getter is a
trap: emitted `@deprecated` now, removal rides the next prebuilt major
(JSII-breaking otherwise). Setting one (setter or constructor config)
registers usage via a new protected
`TerraformResource.registerProviderFeatureUsage` hook — generated code
reaches the validation machinery only by extending base classes.
7. **`feat(cli): thread targetVersions into cdktn get`** —
`GetOptions.targetVersions` → `ConstructsMaker` → `readSchema`, driving
the Phase 0 fetch-time warning; `constraints.json` gains diagnostic
stamps (`targetVersions`, fetching `cli`) without affecting the
`filterAlreadyGenerated` staleness logic (targets don't change codegen
output, so they must not force regeneration).

## Test coverage

- Generator: snapshot tests against **real `terraform providers schema
-json` fragments** from the sweep (random ephemeral, time functions
incl. object returns, vault `*_wo`), plus a synthetic fixture for
variadic/reserved-name mapping branches. Zero churn in pre-existing
snapshots.
- Core: validation matrices mirroring `validations.test.ts`
(admit/exclude per product, hint text, the OpenTofu 1.7.0 asymmetry,
registry resets).
- Schema: emission-gap logic matrix, cache-key suffix behavior,
sanitizer walk over ephemeral schemas; CLI stamps in network snapshots
are stubbed (environment-dependent).

## Known/deferred

- `matchers.test.ts › toPlanSuccessfully` fails in this environment
before and after these changes (downloads the real docker provider;
verified pre-existing via stash on the unmodified tree).
- Deferred per RFC Phase 4: resource identity consumption (schema
plumbing already carried), list resources / actions / state stores
(Terraform-only today; re-evaluate on opentofu/opentofu#3787).
- **Follow-ups tracked as issues**: open-constructs#308 (nested write-only
registration), open-constructs#309 (matrix drift check / in-repo tooling), open-constructs#310
(`hcl2cdk` ephemeral conversion), open-constructs#311 (edge-provider schema
cross-language coverage), open-constructs#312 (ephemeral integration test gated on TF
>= 1.10), open-constructs#313 (pre-existing HCL renderer defects), open-constructs#304 (first-class
`provider_meta`; open-constructs#314 closed as its duplicate), open-constructs#316 (remove the
deprecated write-only getters at the next prebuilt-provider major — the
Phase 3 end state). New this round: open-constructs#336 (structural typing for
object-shaped function params/returns), open-constructs#337 (runtime CI thin slice on
terraform 1.15.x + opentofu 1.12.x — CI's Terraform ceiling is 1.6.5, so
the new schema sections are covered by fixture unit tests, the
edge-provider compile slice below, and the external demo harness until
open-constructs#337 lands).

## Review findings addressed (from the demo-harness verification
comment)

- **Fixed — `targetVersions` validation bypass**:
`CdktfConfig.targetVersions` (the `runGetInDir` path) now validates via
commons `validateTargetVersions` (warn + ignore), and the emission-gap
check treats invalid ranges as not-wanted instead of throwing — a
malformed range previously crashed `cdktn get` via `semver.intersects`.
- **Fixed — ephemeral lifecycle narrowed**: new
`TerraformEphemeralResourceLifecycle` (`precondition`/`postcondition`
only) replaces the full managed-resource lifecycle on the ephemeral API,
before it ships as jsii surface.
- **Fixed (docs) — provider-fn self-reference cycle**: generated
provider-function JSDoc and `TerraformProviderFunction.invoke` now warn
against calling a provider's functions inside that same provider's
configuration block.
- **Documented — ephemeral × write-only**: registration deliberately
skips ephemeral resources — write-only is a state concept, ephemeral
resources have no state, and no schema in the sweep (incl. vault's 16
ephemeral resources) combines the two.
- **Follow-up — nested write-only registration** (open-constructs#308): `write_only`
inside nested blocks gets the deprecated getter but skips usage
registration; deep config scanning deserves its own PR (a miss degrades
to the plan-time error, not silent breakage).
- **Pre-existing / by design**: the AWS barrel-import OOM predates this
PR (lazy-index is the existing mitigation); `Fn.ephemeralasnull` +
`sensitive` on outputs is Terraform semantics (docs candidate); list
resources / actions / resource identity codegen is the RFC Phase 4
deferral noted above.

## Second review round addressed

- **Fixed — cross-App usage-registry leak**: `App` construction now
resets both usage registries (a new App = a new synthesis session).
Within an App the process-global registry is by design — every stack
resolves the same `targetVersions` from App context — but usage no
longer leaks into later, unrelated Apps in the same process (the
reviewer's jest scenario). Regression tests cover the exact sequence;
the flag-gated `Fn` registry had the same latent leak and is reset too.
- **Fixed — emission-gap warning on cache hits**: the warning moved from
`readProviderSchema` into `readSchema`, running for cached *and* fresh
schemas using the `cli_name`/`cli_version` stamps the schema carries.
Regression test: two `readSchema` calls against a cache dir → one
producer call, two warnings.
- **Docs — matrix as source of truth**: both hand-maintained maps now
name `features-matrix.json` as their source and cross-reference each
other; automated drift check tracked in open-constructs#309.

## Third review round addressed (cfncompat/awscc demo findings)

- **Fixed — dynamic-typed provider-function returns coerced to string**:
generated wrappers for `dynamic`/`object`/`map` return types no longer
wrap in `Token.asString(...)`; they return the raw `invoke()`
`IResolvable`, which `Tokenization.isResolvable()` recognizes —
struct-typed attribute assignments (`OutputReference.internalValue`) no
longer vanish silently from synth output.
- **Fixed — `invoke()` dropped literal `null` positional arguments**:
arguments are now validated per position (variadic flattening stays in
the generated wrappers where the signature is known), and a latent third
bug this exposed was fixed too: `FunctionCall` rendered args via
`Array.prototype.join`, which collapses `null` entries to empty strings
— resolved `null`/`undefined` now render as the Terraform `null`
keyword. Regression tests pin the exact
`provider::cfncompat::condition_if(true, null, {"a" = 1})` rendering.


## Fourth review round addressed (jsteinich's CHANGES_REQUESTED)

Seven commits on top of the reviewed head, one per finding group (inline
replies on each thread carry the details):

1. **Schema fidelity** — `FunctionParameter` gains `is_nullable`,
`FunctionSignature` gains `deprecation_message`, and both drop
`description_kind` (verified against
`internal/command/jsonfunction/{function,parameter}.go` and the OpenTofu
equivalent: that field does not exist on function JSON;
`allow_null_value`/`allow_unknown_values` are protocol-only names — the
old comment was wrong). OpenTofu emits no `deprecation_message` at all
(divergence, documented).
2. **Recursive, honest type mapping** — collections recurse
(`list(number)` → `number[]` via `Token.asNumberList`, `set(bool)` param
→ `Array<boolean | IResolvable>`, nested compose); object/map/dynamic
returns are declared `IResolvable` instead of `any` (property access on
a token is now a compile error); `is_nullable` consumed (trailing →
jsii-optional, mid-position → `any`, variadic → `any[]`, docstrings say
`T | null`); `deprecation_message` → `@deprecated`; name collisions
hard-fail generation with an actionable error. Structural helpers for
object shapes: open-constructs#336.
3. **App-owned usage registries** — recording moved to token-resolve
time keyed by the resolving stack's `node.root` (WeakMaps); the
App-constructor resets and the "pathological" disclaimer are gone; the
interleaved-App false negative is structurally impossible and pinned by
regression tests for both registries.
4. **Functions move onto the provider class** —
`time.functions.rfc3339Parse(ts)` via a memoized getter fed by
`this.terraformResourceType` (the exact `required_providers` key, so the
namespace is correct by construction); the static class and
`providerLocalName` parameter are gone, mooting the `providerAlias`
naming question. Per-method self-reference JSDoc dropped (kept once on
`invoke`; docs PR: open-constructs/cdk-terrain-docs#29).
5. **Cleanups** — `registerProviderFeatureUsage` moved to
`TerraformElement` (ephemeral resources reuse it); enum casts replaced
by a membership guard + direct `ProviderFeature` indexing; hints get
their own map instead of runtime label-mangling (messages
byte-identical); write-only registration treats explicit `null` as
omission (`!= null`, both constructor and setter paths, four pinned
tests).
6. **Demo-validation fixes** — exercising the generated bindings in a
real app ([demo
PR](sakul-learning/cdktn-provider-features-demo#5))
caught three bugs snapshots couldn't: the sibling import needed `/index`
under `nodenext`; the wrapper constructor's TS parameter property is
rejected by Node's native type-stripping (jsii accepts it — Node is the
stricter consumer); variadic rest params need `Array<T>` for union
element types.
7. **Edge-provider compile coverage** (closes open-constructs#311) — the edge schema
now carries nine functions (one per generator branch, incl. all three
nullability shapes and deprecation), an ephemeral resource, and a
`write_only` attribute; its bindings ride the existing postbuild jsii +
pacmak flow for all five languages and the `test/<lang>/edge`
native-compile suites, independent of CI's Terraform version.

**External validation** (full matrix in the [demo
PR](sakul-learning/cdktn-provider-features-demo#5)):
terraform 1.15.7 and opentofu 1.12.3 generate byte-identical bindings
modulo registry-host doc links; schema cache keys per CLI product+minor;
omitted/explicit/mid-position nullable args all render the bare `null`
keyword in position; generated bindings pass tsc + jsii + pacmak; the
targetVersions validation error was demonstrated live through the
resolve-time registry.

## Resolves Terraform CDK issues

- hashicorp/terraform-cdk#3886
- hashicorp/terraform-cdk#3686

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant