Skip to content

feat: add write-only attributes for secret fields (Terraform >= 1.11) [ON HOLD]#329

Draft
Aaron ("AJ") Steers (aaronsteers) wants to merge 3 commits intomainfrom
devin/1771368165-write-only-secrets
Draft

feat: add write-only attributes for secret fields (Terraform >= 1.11) [ON HOLD]#329
Aaron ("AJ") Steers (aaronsteers) wants to merge 3 commits intomainfrom
devin/1771368165-write-only-secrets

Conversation

@aaronsteers
Copy link
Copy Markdown
Member

@aaronsteers Aaron ("AJ") Steers (aaronsteers) commented Feb 17, 2026

⚠️ ON HOLD: Typed source/destination resources are being deprecated in favor of the generic airbyte_source and airbyte_destination resources (plus the airbyte_connector_configuration validation helper). With typed resources targeting removal in 1.1, the write-only annotation for those resources has no long-term value. This PR is paused pending a decision on how/if to apply write-only support to the generic resources instead (see #330).

Summary

Adds x-speakeasy-terraform-write-only: true to the Speakeasy overlay for all connector fields marked with airbyte_secret: true. After regeneration, this will generate WriteOnly: true in the Terraform schema, preventing secrets from being persisted to plan or state files entirely.

Also adds README documentation covering write-only attributes and ephemeral variable usage for Terraform >= 1.11 / OpenTofu >= 1.11.

This is an overlay + docs + generation-script change. The generated provider code will not reflect write-only attributes until the next Speakeasy regeneration run (poe generate-full).

Closes #328
See also: #330 (follow-on for generic airbyte_source / airbyte_destination resources)

Changes

  1. Overlay (overlays/terraform_speakeasy.yaml): Adds x-speakeasy-terraform-write-only: true to all airbyte_secret fields via the same JSONPath used for x-speakeasy-param-sensitive.

  2. Entity version bump (scripts/generate_terraform_spec.py): Adds DEFAULT_ENTITY_VERSION = 1 (bumped from implicit 0) and x-speakeasy-entity-version to all typed resource schema templates. This causes Speakeasy to set Version: 1 on each resource and bootstrap boilerplate state upgrader files at internal/stateupgraders/. Individual resources can override the default via ENTITY_VERSION_OVERRIDES. This is required to prevent a breaking upgrade path — see details below.

  3. README docs: Section on write-only attributes and ephemeral variable usage.

  4. Test project (test-projects/v1-tf-latest-test/main.tf): Added "Approach 4" demonstrating ephemeral variables with write-only secret fields.

Breaking change mitigation (upgrade path)

During manual testing, we discovered that adding WriteOnly: true to fields that previously stored values in state is a breaking change without a schema version bump. When Terraform reads existing state (schema v0) with non-null secret values and the new provider declares those fields as write-only (still schema v0), the framework's same-version passthrough does not nullify write-only values, and Terraform core rejects the state:

Error: Invalid resource state upgrade
the provider returned a value for the write-only attribute ...

The fix: bumping the schema version to 1 triggers the explicit state upgrader code path, where the framework does nullify write-only attributes after the upgrader runs. This was validated with a proof-of-concept (apply with RC6 binary → plan with patched v1 binary → no error).

Important: After the next poe generate-full, Speakeasy will bootstrap boilerplate state upgrader files. These upgraders need to be implemented to pass through the prior state correctly (the framework handles write-only nullification automatically after the upgrader runs, so the upgraders primarily just need to forward state as-is).

Manual test results (prior to entity version changes)

Tested with Terraform 1.12.1 + CI binary:

  • terraform validate — passed
  • terraform plan — shows token = (sensitive, write-only attribute)
  • terraform apply — source created successfully
  • Raw state file — "token": null (secret not persisted)
  • terraform plan (post-apply) — "No changes" (no false drift)
  • terraform destroy — clean teardown

Review & Testing Checklist for Human

This PR is on hold. If/when it is revisited (likely for generic resources per #330), the following should be verified:

  • Scope reassessment: Determine whether write-only support should target generic airbyte_source/airbyte_destination resources instead of (or in addition to) typed resources, given the deprecation plan.
  • State upgrader implementation: The Speakeasy-generated boilerplate stubs (642 files in internal/stateupgraders/) return empty state and need implementation. A post-generate script approach was proposed but not yet built.
  • Upgrade path validation: Test the RC6 → regenerated provider upgrade path with a real statefile containing secrets.

Notes

Add x-speakeasy-terraform-write-only: true to the Speakeasy overlay for
all airbyte_secret fields. This generates WriteOnly: true in the Terraform
schema, preventing secrets from being persisted to plan or state artifacts.

Also add documentation for ephemeral variable usage with Terraform >= 1.11
and OpenTofu >= 1.11.

Closes #328

Co-Authored-By: AJ Steers <[email protected]>
Copilot AI review requested due to automatic review settings February 17, 2026 22:45
@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@github-actions
Copy link
Copy Markdown
Contributor

Thanks for opening this pull request!

Your contribution is appreciated. Here are some helpful tips and resources.

💡 Show Tips and Tricks

Terraform Example Commands

  • /tf-examples project=pre-1.0 action=plan - Run terraform plan on the pre-1.0 example project
  • /tf-examples project=1.0 action=plan - Run terraform plan on the 1.0 example project
  • /tf-examples project=all action=plan - Run terraform plan on all example projects
  • /tf-examples project=pre-1.0 action=apply - Apply terraform changes to the pre-1.0 example project
  • /tf-examples project=pre-1.0 action=destroy - Destroy terraform resources in the pre-1.0 example project
📚 Show Repo Guidance

About This Repository

This repository uses Speakeasy to generate the Terraform provider from the Airbyte OpenAPI specification. The CI will automatically build the provider, validate code generation, and run acceptance tests across Terraform versions 1.0-1.4.

Note: This is a generated codebase. Direct modifications to generated files are not accepted - changes must be made to the upstream OpenAPI spec.

📝 Edit this welcome message.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 3 additional findings.

Open in Devin Review

This comment was marked as resolved.

devin-ai-integration Bot and others added 2 commits February 17, 2026 23:38
Add a global DEFAULT_ENTITY_VERSION constant (set to 1) and per-resource
ENTITY_VERSION_OVERRIDES dict to the spec generation script. This sets
x-speakeasy-entity-version on all typed connector resource schemas, which
causes Speakeasy to:
  - Set Version: 1 on each resource's Terraform schema
  - Bootstrap boilerplate state upgrader files at internal/stateupgraders/

This is required to support the v0 -> v1 state migration when adding
write-only attributes to secret fields. Without a version bump, the
Terraform framework's same-version passthrough does not nullify write-only
values in existing state, causing upgrade failures for users with secrets
already stored in state from prior provider versions.

Refs: #328
Co-Authored-By: AJ Steers <[email protected]>
@aaronsteers
Copy link
Copy Markdown
Member Author

Note: We have decided to deprecate the typed source and destination resources, in favor of the generic airbyte_source and airbyte_destination resources - along with the validation helper airbyte_connector_configuration.

With typed resources phasing out (target removal in 1.1), the write-only annotation for those resources has no long-term value.

Putting this PR on hold for now. (Devin, please update the PR description with a header to this affect.)

@devin-ai-integration devin-ai-integration Bot changed the title feat: add write-only attributes for secret fields (Terraform >= 1.11) [ON HOLD] feat: add write-only attributes for secret fields (Terraform >= 1.11) Feb 18, 2026
@devin-ai-integration devin-ai-integration Bot changed the title [ON HOLD] feat: add write-only attributes for secret fields (Terraform >= 1.11) feat: add write-only attributes for secret fields (Terraform >= 1.11) [ON HOLD] Feb 18, 2026
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.

Support Write-Only Attributes + Ephemeral Guidance for Secret Fields (Terraform ≥1.12 / OpenTofu ≥1.11)

2 participants