Skip to content

content(iac): split dynamic providers into a concepts page and an authoring guide#19361

Open
jkodroff wants to merge 1 commit into
masterfrom
jkodroff/dynamic-providers-guide
Open

content(iac): split dynamic providers into a concepts page and an authoring guide#19361
jkodroff wants to merge 1 commit into
masterfrom
jkodroff/dynamic-providers-guide

Conversation

@jkodroff
Copy link
Copy Markdown
Member

Resolves #19358.

What

The dynamic providers concepts page had grown to ~730 lines and mixed two jobs: explaining what a dynamic provider is and how to author one. This PR splits it.

  • Concepts/docs/iac/concepts/providers/dynamic-providers/ is trimmed to conceptual material only: what a dynamic provider is, when to use one, the caveats (pnpm, Bun, policy packs), and how it executes (two-phase execution / function serialization).
  • New guideAuthor a Dynamic Provider at /docs/iac/guides/building-extending/providers/dynamic-providers/ covers the how-to: when to choose a dynamic provider over the alternatives (full provider, Command provider) with a decision diagram, the full resource provider interface, strongly typed inputs and outputs, credential handling, and complete TypeScript and Python examples.

Issue requirements

Testing

  • make lint passes.
  • make build succeeds; both pages render and all example-program-snippet blocks resolve.
  • ONLY_TEST="dynamic-github-labels" ./scripts/programs/test.sh passes for both the TypeScript and Python programs (preview exercises the new check method).

🤖 Generated with Claude Code

@pulumi-bot
Copy link
Copy Markdown
Collaborator

pulumi-bot commented May 22, 2026

…horing guide

Resolves #19358.

The dynamic providers concepts page mixed conceptual material with
how-to content. This splits it:

- Concepts (`/docs/iac/concepts/providers/dynamic-providers/`) keeps the
  explanation of what a dynamic provider is, when to use one, a
  consolidated Limitations section, and how it executes.
- A new guide, "Author a Dynamic Provider"
  (`/docs/iac/guides/building-extending/providers/dynamic-providers/`),
  covers when to choose a dynamic provider over the alternatives, the
  full resource provider interface, strongly typed inputs and outputs,
  credential handling, and complete TypeScript and Python examples.

Also extends the dynamic-github-labels example programs with `check`
and `diff` methods so a single example demonstrates the entire
interface (#11577), and surfaces the strongly typed
inputs/outputs patterns prominently in the guide (#12151).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jkodroff jkodroff force-pushed the jkodroff/dynamic-providers-guide branch from 3197b69 to 0b8b360 Compare May 22, 2026 21:42
@jkodroff jkodroff marked this pull request as ready for review May 22, 2026 21:43
@github-actions github-actions Bot added review:triaging Claude Triage is currently classifying the PR domain:docs PR touches technical docs domain:mixed PR touches more than one domain domain:programs PR touches static/programs/ review:in-progress Claude review is currently running and removed review:triaging Claude Triage is currently classifying the PR labels May 22, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Pre-merge Review — Last updated 2026-05-22T21:47:36Z

Tip

Summary: This PR splits the dynamic-providers concepts page into two: a trimmed concepts page (what a dynamic provider is, when to use one, a consolidated Limitations section, how it executes) and a new authoring guide under guides/building-extending/providers/ that parallels build-a-provider.md and provider-architecture.md. The example programs (dynamic-github-labels-typescript, dynamic-github-labels-python) are extended to demonstrate check and diff on top of the existing configure/create/update/delete. The kind of wrongness that would block a reader: a stale cross-link between the two new pages, an interface description that drifts from the actual TypeScript/Python SDK signatures, or an example program that can't be type-checked when copied into a real Pulumi project. The investigative passes that ran: frontmatter sweep, external claim verification (115 claims), cited-claim spot-checks, temporal-trigger sweep, code-examples checks (3 specialists), code execution against the test harness, and cross-sibling reads against the four neighbor pages.

Review confidence:

Dimension Level Notes
mechanics HIGH
facts MEDIUM 8 claims unverifiable within the per-claim turn budget; the substantive ones (Bun runtime behavior, pulumi-nodejs:dynamic:Resource type sharing, read's eventual semantics) would benefit from a citation or sample reproducer from the author.
cross-sibling consistency HIGH
code correctness HIGH
Investigation log
  • Cross-sibling reads: 4 of 4 siblings
  • External claim verification: 84 of 115 claims verified (18 unverifiable, 6 contradicted) · 4 specialists (numerical, cross-reference, capability, framing); 0 cross-specialist corroborations · routed: 0 inline, 97 Pass 1, 12 Pass 2 (verified 5, contradicted 0, unverifiable 7), 6 Pass 3 (verified 6, contradicted 0, unverifiable 0).
  • Cited-claim spot-checks: 12 of 12 cited claims fetched and compared
  • Frontmatter sweep: ran on body + meta_desc
  • Temporal-trigger sweep: ran (recency words present in diff; spot-check in-review)
  • Code execution: ran static/programs/dynamic-github-labels-python, static/programs/dynamic-github-labels-typescript (CI test harness gates parse + imports)
  • Code-examples checks: ran (3 specialists: structural, existence, body-code-coverage); 0 findings
  • Editorial-balance pass: not run (not under content/blog/)
🚨 Outstanding ⚠️ Low-confidence 💡 Pre-existing ✅ Resolved
0 15 9 0

🔍 Verification trail

115 claims extracted · 84 verified · 18 unverifiable · 6 contradicted
  • L24 in content/docs/iac/concepts/providers/dynamic-providers.md "Dynamic providers are supported only in TypeScript and Python." → ✅ verified (evidence: The file at content/docs/iac/concepts/providers/dynamic-providers.md contains exactly this text at L24 inside a notes block: "Dynamic providers are supported only in TypeScript and Python." The document's code examples and chooser blocks…; source: repo:content/docs/iac/concepts/providers/dynamic-providers.md)
  • L28 in content/docs/iac/concepts/providers/dynamic-providers.md "A decision diagram for when to use a dynamic provider exists at /docs/iac/guides/building-extending/providers/dynamic-providers/#when-to-use-a-dynamic-provider." → ✅ verified (evidence: The concepts page (content/docs/iac/concepts/providers/dynamic-providers.md) links to the decision diagram at /docs/iac/guides/building-extending/providers/dynamic-providers/#when-to-use-a-dynamic-provider, and the guide page (`content…; source: repo:content/docs/iac/concepts/providers/dynamic-providers.md and repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L36 in content/docs/iac/concepts/providers/dynamic-providers.md "The full dynamic provider interface is documented at /docs/iac/guides/building-extending/providers/dynamic-providers/." → ✅ verified (evidence: The file content/docs/iac/guides/building-extending/providers/dynamic-providers.md exists and contains the full ResourceProvider interface documentation. The concepts page at content/docs/iac/concepts/providers/dynamic-providers.md c…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L36 in content/docs/iac/concepts/providers/dynamic-providers.md "All dynamic providers must at minimum implement the create function." → ✅ verified (evidence: The file states: "You must at least implement the create function but, in practice, you will probably also want to implement the update and delete functions as well." and later "This interface supports all CRUD operations, but only t…; source: repo:content/docs/iac/concepts/providers/dynamic-providers.md)
  • L42 in content/docs/iac/concepts/providers/dynamic-providers.md "The dynamic provider chooser in this page supports only TypeScript and Python (not Go, C#, Java, or YAML)." → ✅ verified (evidence: The file at line ~42 contains {{< chooser language "typescript,python" >}}, and the page also explicitly states "Dynamic providers are supported only in TypeScript and Python." — no Go, C#, Java, or YAML options are present in any choose…; source: repo:content/docs/iac/concepts/providers/dynamic-providers.md)
  • L71 in content/docs/iac/concepts/providers/dynamic-providers.md "The dynamic provider resource base class language chooser supports only TypeScript and Python." → ✅ verified (evidence: The file at line ~71 contains {{< chooser language "typescript,python" >}} for the dynamic resource base class section, and the document also explicitly states "Dynamic providers are supported only in TypeScript and Python." Both the cho…; source: repo:content/docs/iac/concepts/providers/dynamic-providers.md)
  • L75 in content/docs/iac/concepts/providers/dynamic-providers.md "In TypeScript, pulumi.dynamic.Resource is a subclass of pulumi.CustomResource." → ✅ verified (evidence: The documentation file at L75 explicitly states "Extend pulumi.dynamic.Resource, which is a subclass of pulumi.CustomResource", and the SDK source sdk/nodejs/dynamic/index.ts in pulumi/pulumi imports from ../resource (which defines…; source: repo:content/docs/iac/concepts/providers/dynamic-providers.md; gh api repos/pulumi/pulumi/contents/sdk/nodejs/dynamic/index.ts)
  • L88 in content/docs/iac/concepts/providers/dynamic-providers.md "In Python, pulumi.dynamic.Resource is a subclass of pulumi.CustomResource." → ✅ verified (evidence: The SDK source at sdk/python/lib/pulumi/dynamic/dynamic.py imports from .. import CustomResource, ResourceOptions, confirming CustomResource is the base class. The doc file itself at the relevant line states "Subclass `pulumi.dynamic…; source: gh api repos/pulumi/pulumi/contents/sdk/python/lib/pulumi/dynamic/dynamic.py)
  • L113 in content/docs/iac/concepts/providers/dynamic-providers.md "The read method is not currently implemented for dynamic providers." → ✅ verified (evidence: The file at L113 states: "If Pulumi needs to read an existing resource without managing it directly, it will call read. (Note: read is not currently implemented for dynamic providers.)" and the Limitations section also confirms: "No `rea…; source: repo:content/docs/iac/concepts/providers/dynamic-providers.md)
  • L115 in content/docs/iac/concepts/providers/dynamic-providers.md "Details on each dynamic provider interface function are documented at /docs/iac/guides/building-extending/providers/dynamic-providers/." → ✅ verified (evidence: The file content/docs/iac/guides/building-extending/providers/dynamic-providers.md exists and contains a full "The resource provider interface" section documenting each method (configure, check, create, diff, update, delete, read). The c…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L123 in content/docs/iac/concepts/providers/dynamic-providers.md "Dynamic providers are built on top of the same function serialization used for turning callbacks into AWS Lambdas or Google Cloud Functions." → ✅ verified (evidence: The dynamic-providers.md file states: "dynamic providers are built on top of the same function serialization that is used for turning callbacks into AWS Lambdas or Google Cloud Functi…; source: repo:content/docs/iac/concepts/providers/dynamic-providers.md)
  • L129 in content/docs/iac/concepts/providers/dynamic-providers.md "A dynamic provider can only be used from programs written in the same language as the provider; for multi-language support, a bridged or native provider must b…" → ✅ verified (evidence: The file at line ~129 (Limitations section) states: "Single language. A dynamic provider can only be used from programs written in the same language as the provider. For multi-language support, build a [bridged or native provider](/doc…; source: repo:content/docs/iac/concepts/providers/dynamic-providers.md)
  • L130 in content/docs/iac/concepts/providers/dynamic-providers.md "The read method is not currently functional for dynamic providers, so pulumi import and the static get method are not supported." → ✅ verified (evidence: The dynamic-providers.md file contains exactly this text in the Limitations section: "The read method is not currently functional, so pulumi import and the static [get method](/docs/iac/concep…; source: repo:content/docs/iac/concepts/providers/dynamic-providers.md)
  • L131 in content/docs/iac/concepts/providers/dynamic-providers.md "Dynamic provider methods are serialized to run in a separate process, which limits what code they can capture." → ✅ verified (evidence: The dynamic-providers.md file states: "Because your implementation of the resource provider interface must be used by a different process, potentially at a different point in time, dynamic providers are built on top of the same function se…; source: repo:content/docs/iac/concepts/providers/dynamic-providers.md)
  • L132-134 in content/docs/iac/concepts/providers/dynamic-providers.md "Dynamic providers are not supported with the Bun runtime (runtime: bun) because they depend on function serialization, which requires Node.js v8/inspector AP…" → 🤷 unverifiable (evidence: The pre-fetched URL (Refresh fails after Pulumi upgrade if dynamic provider exists pulumi#9085) returns HTTP 200 but the body is severely truncated and only shows the issue title "Refresh fails after Pulumi upgrade if dynamic provider exists" — there is no visible con…; source: Refresh fails after Pulumi upgrade if dynamic provider exists pulumi#9085)
  • L133 in content/docs/iac/concepts/providers/dynamic-providers.md "- No Bun runtime support (TypeScript). Dynamic providers are not supported with the Bun runtime (runtime: bun), because they depend on function serializa…" → ✅ verified (framing: strengthened — the claim narrows the broader Node.js compatibility page to the specific node:inspector section; the page's existence and topic confirm the cl…; evidence: The cited URL https://bun.com/docs/runtime/nodejs-compat#nodeinspector returns HTTP 200, confirming the page exists. The body is truncated but shows "Node.js Compatibility - Bun" page, consistent with the claim that Bun does not fully impl…; source: https://bun.com/docs/runtime/nodejs-compat#nodeinspector)
  • L134 in content/docs/iac/concepts/providers/dynamic-providers.md "All dynamic resources in TypeScript share the resource type pulumi-nodejs:dynamic:Resource." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L138 in content/docs/iac/concepts/providers/dynamic-providers.md "The Author a Dynamic Provider guide at /docs/iac/guides/building-extending/providers/dynamic-providers/ covers the full resource provider interface, strongly t…" → ✅ verified (framing: strengthened — the claim adds "strongly typed inputs and outputs" which wasn't directly visible in the file content read, but the rest of the description accur…; evidence: The file at content/docs/iac/guides/building-extending/providers/dynamic-providers.md exists and its meta_desc states "when to choose one, the resource provider interface, and complete TypeScript and Python examples." The guide covers th…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L39 in content/docs/iac/guides/building-extending/providers/_index.md "The 'Any Terraform Provider' feature lets a Pulumi program consume any provider from the OpenTofu registry without writing a Pulumi provider at all." → ✅ verified (evidence: The file at content/docs/iac/guides/building-extending/providers/_index.md states: "reach for Any Terraform Provider, which lets a Pulumi program consume any provider from the OpenT…; source: repo:content/docs/iac/guides/building-extending/providers/_index.md)
  • L40 in content/docs/iac/guides/building-extending/providers/_index.md "The dynamic provider documentation is located at /docs/iac/guides/building-extending/providers/dynamic-providers/." → 🤷 unverifiable (evidence: The file content/docs/iac/guides/building-extending/providers/_index.md does link to /docs/iac/guides/building-extending/providers/dynamic-providers/ (e.g., "Author a Dynamic Provider" in the guides list), but the directory `content/do…; source: repo:content/docs/iac/guides/building-extending/providers/_index.md)
  • L55 in content/docs/iac/guides/building-extending/providers/_index.md "The Provider Architecture page is located at /docs/iac/guides/building-extending/providers/provider-architecture/ and covers the three-layer model of the provi…" → ✅ verified (evidence: The file content/docs/iac/guides/building-extending/providers/provider-architecture.md exists and renders at /docs/iac/guides/building-extending/providers/provider-architecture/. The parent _index.md at L55 states: "Provider Architec…; source: repo:content/docs/iac/guides/building-extending/providers/provider-architecture.md)
  • L55-59 in content/docs/iac/guides/building-extending/providers/_index.md "The Provider Configuration page is located at /docs/iac/guides/building-extending/providers/provider-configuration/ and covers declaring configuration keys, se…" → ✅ verified (evidence: The _index.md file at content/docs/iac/guides/building-extending/providers/_index.md lists: "- Provider Configuration — declaring configuration keys, secrets, and…; source: repo:content/docs/iac/guides/building-extending/providers/_index.md)
  • L20 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "Direct provider implementation (using gRPC bindings) is documented at /docs/iac/guides/building-extending/providers/implementers/." → ✅ verified (evidence: The file at L20 contains: "If you prefer to implement providers directly using gRPC bindings for full control, or need to use a language other than Go, see [Direct provider implementation](/docs/iac/guides/building-extending/providers/impl…; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L25 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "Dynamic providers are documented at /docs/iac/guides/building-extending/providers/dynamic-providers/." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L25 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "Pulumi providers are ideal when you need to manage resources that are not yet supported by existing Pulumi providers or when you require custom behavior for ma…" → ✅ verified (evidence: The exact claim text appears verbatim in the file content/docs/iac/guides/building-extending/providers/build-a-provider.md: "Pulumi providers are ideal when you need to manage resources that are not yet supported by existing Pulumi provi…; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L31 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The Pulumi Go Provider interface (pkg.go.dev/github.com/pulumi/pulumi-go-provider#Provider) implements the following core methods: Create, Read, Update, Delete…" → ❌ contradicted (framing: narrowed — claim presents 7 methods as "the following core methods" of the Provider interface, but the actual interface has at least 14 methods; the claim omit…; evidence: The Provider interface in pulumi-go-provider includes far more than the 7 listed methods. The integration.go Server interface (which directly wraps p.Provider) shows: GetSchema, Cancel, CheckConfig, DiffConfig, Configure, `…; source: gh api repos/pulumi/pulumi-go-provider/contents/integration/integration.go)
  • L43 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "Pulumi providers are gRPC servers that respond to commands from the Pulumi engine." → ✅ verified (evidence: The Pulumi docs page at the exact file path cited contains the verbatim text: "Pulumi providers are gRPC servers that respond to commands from the Pulumi engine." This is also corroborated by the protocol reference page which states "When…; source: https://www.pulumi.com/docs/iac/guides/building-extending/providers/build-a-provider/)
  • L43 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "When a Pulumi program runs (e.g. pulumi up), the Pulumi engine connects to the provider process and sends instructions to create, update, or delete resources…" → ➖ not-a-claim (framing: strengthened — the claim accurately describes Pulumi's gRPC-based provider architecture, which is well-established in Pulumi's own documentation and codebase,…; evidence: The text at L43 area reads: "When a Pulumi program runs (e.g. pulumi up), the engine connects to the provider process and sends instructions to create, update, or delete resources via calls to the provider interface implementation." This…; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L49 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "Provider configuration and secrets are set via Pulumi ESC environments and/or pulumi config, and encrypted secrets and configuration values are passed to the…" → ✅ verified (evidence: The file at L49 area contains: "Configuration and Secrets: Set via Pulumi ESC environments and/or pulumi config. Encrypted secrets and configuration values are passed to the provider at runtim…; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L49 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "Provider configuration is documented at /docs/iac/guides/building-extending/providers/provider-configuration/." → 🤝 matches (evidence: The file content/docs/iac/guides/building-extending/providers/provider-configuration.md exists in the repo (confirmed via GitHub API directory listing), and build-a-provider.md links to it as "See [Provider configuration](/docs/iac/gui…; source: gh api repos/pulumi/docs/contents/content/docs/iac/guides/building-extending/providers)
  • L51 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "Pulumi maintains resource state to track dependencies and detect changes." → ✅ verified (evidence: The file at content/docs/iac/guides/building-extending/providers/build-a-provider.md contains exactly this text in the "Configuration, secrets, outputs, and state" section: "State: Pulumi maintains resource state to track dependencie…; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L59 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The provider package schema enables Pulumi to generate SDKs for multiple languages and ensures consistency across them, as well as providing documentation." → ✅ verified (evidence: The file content/docs/iac/guides/building-extending/providers/build-a-provider.md contains the exact text: "This schema enables Pulumi to generate SDKs for multiple languages and ensures consistency across them, as well as providing docu…; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L59 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The provider package schema enables Pulumi to generate SDKs for multiple languages." → ✅ verified (framing: strengthened — claim narrows 'This schema enables Pulumi to generate SDKs for multiple languages and ensures consistency across them, as well as providing docu…; evidence: The file at line ~59 (in the "The provider schema" section) states: "This schema enables Pulumi to generate SDKs for multiple languages and ensures consistency across them, as well as providing documentation." The claim is a narrower subse…; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L63 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "Historically it was necessary to hand-author and maintain the schema.json file that accompanied a provider implementation; now most of this is generated auto…" → ✅ verified (framing: strengthened — claim narrows 'without hand-authoring a JSON schema' to 'schema.json file is no longer necessary'; source's broader form proves the claim as a s…; evidence: The pulumi-go-provider SDK docs page states: "The library uses Go reflection to derive the package's schema from your Go types, so multi-language SDKs can be generated without hand-authoring a JSON schema." This confirms the claim that sch…; source: content/docs/iac/guides/building-extending/packages/pulumi-go-provider-sdk.md)
  • L69 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "Python direct provider implementation is documented at /docs/iac/guides/building-extending/providers/implementers/python/." → ✅ verified (evidence: The file content/docs/iac/guides/building-extending/providers/implementers/python.md exists in the repo and documents Python direct provider implementation. The build-a-provider.md source file itself links to `/docs/iac/guides/building…; source: gh api repos/pulumi/docs/contents/content/docs/iac/guides/building-extending/providers/implementers)
  • L69 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "Pulumi providers can be written in any language that supports gRPC, and used in any Pulumi program regardless of that program's language." → ✅ verified (evidence: The file at the specified path contains the exact claim verbatim: "Pulumi providers can be written in any language that supports gRPC, and used in any Pulumi program regardless of that program's language." This appears in the "Language sup…; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L69 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "Pulumi providers can be used in any Pulumi program regardless of that program's language." → ✅ verified (evidence: The file at the specified path contains the exact statement: "Pulumi providers can be written in any language that supports gRPC, and used in any Pulumi program regardless of that program's language."; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L69 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The provider architecture has multiple layers; Layer 3 is the Pulumi Go Provider SDK, described as the most streamlined approach for Go." → ✅ verified (evidence: The file at the specified path contains the exact statement: "The provider architecture has multiple layers. Layer 3 is the Pulumi Go Provider SDK—the most streamlined approach for Go."; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L69 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "Layer 2 of the provider architecture lets you implement the gRPC interface directly in Python, Go, TypeScript, or any language with gRPC support." → ✅ verified (evidence: The file build-a-provider.md states at the relevant line: "Layer 2 lets you implement the gRPC interface directly in Python, Go, TypeScript, or any language with gRPC support." The architecture source page also confirms Layer 2 co…; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L71 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The Pulumi Go Provider SDK handles protocol complexity and generates schemas automatically." → ✅ verified (evidence: The file at the relevant section states: "We recommend using the Pulumi Go Provider SDK for Go providers, as it handles protocol complexity and generates schemas automatically." This is a verbatim match to the claim.; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L75 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "With the Pulumi Provider SDK, you define resource types and implementation using Go structs and methods, and the SDK handles RPC and auto-generated schema for…" → ✅ verified (evidence: The file states under "Some advantages of using the Pulumi Provider SDK": "Minimal Code Required: You define your resource types and implementation using Go structs and methods, and the SDK handles the rest (RPC, auto-generated schema…; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L76 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The Pulumi Provider SDK includes a built-in testing framework for testing custom providers." → ✅ verified (evidence: The file at L76 (within the "Some advantages of using the Pulumi Provider SDK" section) states: "Includes a Testing Framework: Testing custom providers is made much easier with the SDK's built-in testing framework." This directly confi…; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L77 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The Pulumi Provider SDK provides middleware support that enhances providers with layers like dispatch logic, schema generation, and cancellation propagation." → ✅ verified (evidence: The file at L77 area explicitly states under "Some advantages of using the Pulumi Provider SDK": "Middleware Support: Enhances providers with layers like dispatch logic, schema generation, and cancellation propagation." This is an exac…; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L81 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The file provider example is located at https://github.com/pulumi/pulumi-go-provider/blob/main/examples/file/main.go." → ✅ verified (evidence: The GitHub API confirms the file exists at examples/file/main.go in the pulumi/pulumi-go-provider repository, with html_url matching exactly: https://github.com/pulumi/pulumi-go-provider/blob/main/examples/file/main.go.; source: https://github.com/pulumi/pulumi-go-provider/blob/main/examples/file/main.go)
  • L112 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The go.mod file for the file-provider example requires github.com/pulumi/pulumi-go-provider and github.com/pulumi/pulumi/sdk/v3 as dependencies." → ✅ verified (evidence: The documentation at line ~112 shows a go.mod example with require ( github.com/pulumi/pulumi-go-provider v1.0.0 github.com/pulumi/pulumi/sdk/v3 v3.167.0 ), confirming both dependencies are listed. The surrounding text also states: "We…; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L119 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The example go.mod file specifies Go version 1.24." → ✅ verified (evidence: The official Pulumi "Build a Provider" docs page shows the example go.mod as: "module example.com/file-provider go 1.24 toolchain go1.24.0 require ( github.com/pulumi/pulumi-go-provider v1.0.0 ..."; source: https://www.pulumi.com/docs/iac/guides/building-extending/providers/implementers/go/)
  • L121 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The example go.mod file specifies toolchain go1.24.0." → ✅ verified (framing: strengthened — the claim asserts a specific version string in a code example; the source confirms go1.24.0 is a valid released toolchain, proving the version r…; evidence: go1.24.0 is a real, released Go toolchain version (released February 2025), confirmed by the official Go release history: "Go 1.24.0 is a major release of Go." The toolchain go1.24.0 directive is a valid go.mod entry per Go toolchain doc…; source: https://go.dev/doc/devel/release)
  • L124-125 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The example go.mod file pins github.com/pulumi/pulumi-go-provider to v1.0.0." → ❌ contradicted (evidence: The go.mod example in the file does pin github.com/pulumi/pulumi-go-provider v1.0.0, but the GitHub release list for pulumi/pulumi-go-provider shows no stable v1.0.0 release — releases go from pre-release v1.0.0-rc.2 directly to…; source: gh release list -R pulumi/pulumi-go-provider --limit 20; intuition: v1.0.0 is missing from the release list; the first stable v1 release is v1.0.1, making the pinned version in the exampl…)
  • L137 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The PulumiPlugin.yaml file tells Pulumi that the code can be loaded as a provider plugin and specifies the runtime environment to use." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L433 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The .WithNamespace method sets the namespace that the generated language-specific SDKs will use, and if not provided, the default value will be pulumi, whi…" → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L516 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The Pulumi Provider SDK provides default implementations for all provider interface functions other than Create." → ❌ contradicted (framing: narrowed — claim broadens the source by asserting defaults exist for all functions except Create; source shows CustomUpdate also has no default behavior; evidence: The pulumi-go-provider source (infer/resource.go) explicitly states "There is no default behavior for CustomUpdate." — meaning Update also lacks a default, not just Create. The claim that defaults exist for ALL functions other than…; source: gh api repos/pulumi/pulumi-go-provider/contents/infer/resource.go (decoded: "// There is no default behavior for CustomUpdate."))
  • L714 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "A provider created in Go and used in YAML 'just works' by default without generating additional SDKs." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L714 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "To use a provider from other Pulumi authoring languages (TypeScript, Python, Java, Go, C#), it is necessary to generate SDKs for each target language." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L717-719 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The command pulumi package gen-sdk <path-to-provider> generates language SDKs for all supported languages." → ✅ verified (evidence: The source code for package_gen_sdk.go shows the --language flag defaults to "all", and when language == "all", it iterates over ["dotnet", "go", "java", "nodejs", "python"] to generate SDKs for each. The flag description reads:…; source: gh api repos/pulumi/pulumi/contents/pkg/cmd/pulumi/packagecmd/package_gen_sdk.go)
  • L722 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The pulumi package gen-sdk command documentation is at /docs/iac/cli/commands/pulumi_package_gen-sdk/." → ✅ verified (evidence: The file content/docs/iac/cli/commands/pulumi_package_gen-sdk.md exists in the repo with title "pulumi package gen-sdk | CLI commands", confirming the documentation is located at the path /docs/iac/cli/commands/pulumi_package_gen-sdk/.; source: repo:content/docs/iac/cli/commands/pulumi_package_gen-sdk.md)
  • L726 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The pulumi package get-schema <path-to-provider> command can be used to generate the schema.json file, e.g. for debugging purposes, and is documented at /doc…" → ✅ verified (evidence: The file content/docs/iac/cli/commands/pulumi_package_get-schema.md exists at the referenced path and states: "Get the schema.json from a package. ... pulumi package get-schema <schema-source> [flags] [--] [provider-parameter]...", con…; source: repo:content/docs/iac/cli/commands/pulumi_package_get-schema.md)
  • L726 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "Historically, Pulumi providers required a schema.json file; this is now generated on the fly by the Pulumi Provider SDK and so you don't need to have this fi…" → ✅ verified (framing: strengthened — the source says "most of this is generated automatically" while the claim implies full generation; the claim slightly overstates completeness bu…; evidence: The file itself contains: "Historically it was necessary to hand-author and maintain the schema.json file that accompanied your provider implementation, however, now most of this is generated automatically by the [Pulumi Go Provider SDK]…; source: repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L734 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "Pulumi providers can be hosted publicly or privately in GitHub and GitLab, using a private registry within Pulumi Cloud, or published to the public Pulumi regi…" → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L736 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "The Pulumi package authoring guide is documented at /docs/iac/using-pulumi/pulumi-packages/authoring/." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L14 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "A dynamic provider lets you implement a resource's create, read, update, and delete (CRUD) logic directly inside a Pulumi program, without building and publish…" → ✅ verified (evidence: The exact sentence appears verbatim at line 14 of the file: "A dynamic provider lets you implement a resource's create, read, update, and delete (CRUD) logic directly inside a Pulumi program, without building and publishing a separate prov…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L16 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "There is a conceptual overview of dynamic providers at /docs/iac/concepts/providers/dynamic-providers/ in the Pulumi concepts documentation." → ✅ verified (evidence: The file content/docs/iac/concepts/providers/dynamic-providers.md exists in the repository, confirming that the conceptual overview of dynamic providers is located at /docs/iac/concepts/providers/dynamic-providers/ as claimed.; source: repo:content/docs/iac/concepts/providers/dynamic-providers.md)
  • L19 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "For languages other than TypeScript and Python, users should build a full provider at /docs/iac/guides/building-extending/providers/build-a-provider/." → ✅ verified (evidence: The dynamic-providers.md file at L19 contains: "Dynamic providers are supported only in TypeScript and Python. For other languages, build a full provider." The target file…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md and repo:content/docs/iac/guides/building-extending/providers/build-a-provider.md)
  • L26-28 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "Any Terraform Provider lets you consume a Terraform or OpenTofu provider directly, and is documented at /docs/iac/concepts/providers/any-terraform-provider/." → ✅ verified (evidence: The dynamic-providers.md file at L26-28 states: "If a Terraform or OpenTofu provider exists, Any Terraform Provider lets you consume it directly." The referenced doc at that path exis…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md and repo:content/docs/iac/concepts/providers/any-terraform-provider.md)
  • L27 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "- The Command provider. If you only need to run a command or script as part of provisioning — rather than model a resource with a real lifecycle — the [Com…" → ✅ verified (evidence: The URL https://www.pulumi.com/registry/packages/command/ returns HTTP 200 and confirms the existence of the Pulumi Command provider package ("Command v1.2.1, Mar 3 26 ... Publisher: Pulumi ... Repository: https://github.com/pulumi/pulumi-…; source: https://www.pulumi.com/registry/packages/command/)
  • L28 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "A full provider supports import, can be reused across languages, shared with other teams, and published to the Registry; a dynamic provider does not support…" → ✅ verified (evidence: The dynamic-providers.md file at L28 states: "If the provider should be reusable across languages, shared with other teams, published to the Registry, or needs import support, build a full provider instead." This directly confirms that a…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L42 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "A dynamic provider can only be used from programs written in the same language as the provider." → ✅ verified (evidence: The exact claim text appears verbatim in the file at the stated location: "A dynamic provider can only be used from programs written in the same language as the provider." This is listed under the "Keep these constraints in mind when choos…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L43-44 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "Because read is not currently functional, pulumi import and the static get method are not supported for dynamic providers." → ✅ verified (evidence: The dynamic-providers.md file at lines 43-44 states: "The read method is not currently functional, so pulumi import and the static get method are not suppo…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L44 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "Dynamic provider methods are serialized to run in a separate process, which limits what code they can capture." → ✅ verified (framing: strengthened — claim adds "Dynamic" qualifier to "Provider methods" which is already implied by the document context; source's form proves the claim as a subset; evidence: The dynamic-providers.md file at the relevant section states: "Provider methods are serialized to run in a separate process, which limits what code they can capture. See [function serialization](/docs/iac/concepts/functions/function-serial…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L48 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "You author a dynamic provider by implementing the pulumi.dynamic.ResourceProvider interface." → ✅ verified (evidence: The file at the specified path contains the exact sentence: "You author a dynamic provider by implementing the pulumi.dynamic.ResourceProvider interface." in the "The resource provider interface" section.; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L48 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "Each method of the pulumi.dynamic.ResourceProvider interface can be asynchronous." → ✅ verified (evidence: The file at the described location states: "Each method can be asynchronous, and most implementations perform network I/O to provision resources in a backing API." This directly confirms the claim about pulumi.dynamic.ResourceProvider in…; source: content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L52-54 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "If another deployment happens and the resource already exists, Pulumi calls diff to determine whether a change can be made in place or whether a replacement…" → ✅ verified (evidence: The file at line 52-54 states exactly: "If another deployment happens and the resource already exists, Pulumi calls diff to determine whether a change can be made in place or whether a replacement is needed." This matches the claim verba…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L54-57 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "If another deployment happens and the resource already exists, Pulumi calls diff to determine whether a change can be made in place or whether a replacement…" → ✅ verified (evidence: The file at content/docs/iac/guides/building-extending/providers/dynamic-providers.md contains the exact text: "If another deployment happens and the resource already exists, Pulumi calls diff to determine whether a change can be made in…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L57 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "read is not currently functional for dynamic providers." → ✅ verified (evidence: The file at the relevant section explicitly states: "The read method is not currently functional for dynamic providers. Attempting to invoke it — for example, by running pulumi import or using t[he static get method]..." and referenc…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md and gh issue view 16175 -R pulumi/pulumi)
  • L61 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The configure method receives a ConfigureRequest containing the current stack's configuration." → ✅ verified (evidence: The file at line ~61 contains the section "### configure(ConfigureRequest)" which states: "It receives a ConfigureRequest containing the current stack's configuration." — an exact match to the claim.; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L65 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The check method receives the old input properties stored in state after the previous update, and the new inputs from the current deployment." → ✅ verified (evidence: The file at line ~65 (in the check(olds, news) section) states verbatim: "It receives the old input properties stored in state after the previous update, and the new inputs from the current deployment."; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L70 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The inputs returned from check are the inputs Pulumi uses for all further processing of the resource, including the values passed to diff, create, and u…" → ✅ verified (evidence: The claim appears verbatim in the documentation file at the check(olds, news)section: "The inputs returned fromcheckare the inputs Pulumi uses for all further processing of the resource, including the values passed todiff, creat…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md; gh api repos/pulumi/pulumi/contents/sdk/nodejs/dynamic/index.ts)
  • L74 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The create method returns an id that uniquely identifies the resource in the backing provider and a set of outputs that are returned to the user code as…" (also L77) → ✅ verified (framing: strengthened — claim omits "for later lookups" qualifier but is otherwise an accurate subset of the source text; evidence: The file at the relevant section states: "An id that uniquely identifies the resource in the backing provider for later lookups. A set of outputs that are returned to the user code as properties on the resource and stored in state." Th…; source: content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L74 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The create method receives the checked inputs returned from check." → ✅ verified (evidence: The file at the relevant section states: "The create method is invoked when the resource's URN is not found in the existing state. The engine passes it the checked inputs returned from check."; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L76-77 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The create method returns a set of outputs that are returned to the user code as properties on the resource and stored in state." → ✅ verified (evidence: The file at the specified path contains the exact text at the create method description: "A set of outputs that are returned to the user code as properties on the resource and stored in state."; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L83 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The diff method returns four optional values: changes, replaces, stables, and deleteBeforeReplace." → ✅ verified (evidence: The Pulumi Node.js SDK source at sdk/nodejs/dynamic/index.ts defines DiffResult with exactly four optional fields: readonly changes?: boolean, readonly replaces?: string[], readonly stables?: string[], and `readonly deleteBeforeR…; source: gh api repos/pulumi/pulumi/contents/sdk/nodejs/dynamic/index.ts)
  • L83 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The diff method is invoked when the resource's URN already exists, and receives the id returned by create, the old outputs from state, and the checked in…" → ✅ verified (evidence: The file at the diff section reads: "The diff method is invoked when the resource's URN already exists. It receives the id returned by create, the old outputs from state, and the checked inputs from the current deployment." — an ex…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L83 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The diff method receives the id returned by create, the old outputs from state, and the checked inputs from the current deployment." → ✅ verified (evidence: The file at L83 area states: "The diff method is invoked when the resource's URN already exists. It receives the id returned by create, the old outputs from state, and the checked inputs from the current deployment." This is an exact…; source: content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L85 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The diff method returns four optional values: changes, replaces, stables, and deleteBeforeReplace." (also L88) → ✅ verified (evidence: The Pulumi Node.js SDK's DiffResult interface in sdk/nodejs/dynamic/index.ts defines exactly four optional fields: readonly changes?: boolean, readonly replaces?: string[], readonly stables?: string[], and `readonly deleteBeforeR…; source: gh api repos/pulumi/pulumi/contents/sdk/nodejs/dynamic/index.ts)
  • L87 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The stables field in the diff result is an array of property names known not to change between updates, and Pulumi uses this to process some apply calls…" → ✅ verified (evidence: The file at content/docs/iac/guides/building-extending/providers/dynamic-providers.md contains the exact text: "stables: an array of property names known not to change between updates. Pulumi uses this to process some [apply](/docs/iac…; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L88 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "Setting deleteBeforeReplace: true in the diff result causes Pulumi to delete the existing resource before creating the new one during a replacement." → ✅ verified (evidence: The file itself at the relevant section states: "deleteBeforeReplace: true if a replacement requires deleting the existing resource before creating the new one. By default, Pulumi creates the new resource before deleting the old one to…; source: content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L92 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The update method receives the id of the resource, the old outputs from state, and the new checked inputs." → ✅ verified (evidence: The documentation file at the update(id, olds, news) section states verbatim: "It receives the id of the resource, the old outputs from state, and the new checked inputs." This is an exact match to the claim.; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L96 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The delete method is invoked when the URN exists in the previous state but not in the new desired state, or when a replacement is needed." → ✅ verified (evidence: The file at L96 (the delete(id, props) section) reads verbatim: "The delete method is invoked when the URN exists in the previous state but not in the new desired state, or when a replacement is needed." This matches the claim exactly.; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L96 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The delete method does not need to return anything." → ✅ verified (evidence: The file's ### delete(id, props) section states: "It receives the id of the resource and the old outputs from state, and deletes the corresponding resource from the backing API. Nothing needs to be returned."; source: repo:content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L101 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "Attempting to invoke the read method on a dynamic provider — for example by running pulumi import or using the static get method — results in an unimplem…" → ✅ verified (evidence: The GitHub issue Add 'idp-best-practices' tag to deployment guardrails blog post #16175 is titled "Cannot import a Resource provided by a Dynamic Resource Provider," which directly supports the claim that invoking read (e.g., via pulumi import) on a dynamic provider results in an unimplemented exce…; source: Cannot import a Resource provided by a Dynamic Resource Provider pulumi#16175)
  • L104 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "When functional, read is intended to support the static get method, pulumi import, and pulumi refresh." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L108 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "A dynamic provider's methods are invoked with the fully resolved input values, not Input wrapped values." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L182 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "How data is passed between the core Pulumi program and a dynamic provider has nuances documented in GitHub issue Dynamic resource changes order of fields of objects in input / clobbers input type pulumi#16582." → ✅ verified (evidence: The GitHub issue Dynamic resource changes order of fields of objects in input / clobbers input type pulumi#16582 exists and returns HTTP 200. Its title "Dynamic resource changes order of fields of objects in input / clobbers input type" confirms it documents nuances in how data is passed between the core Pulumi pr…; source: Dynamic resource changes order of fields of objects in input / clobbers input type pulumi#16582)
  • L187 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "To access dynamic provider outputs with strong typing, declare each output as a class member on your pulumi.dynamic.Resource subclass, and the member name mu…" → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L219 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "Using public readonly with the definite assignment assertion (!) can cause outputs to be undefined in some TypeScript configurations for dynamic provider…" → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L219 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The declare keyword tells TypeScript the property exists without emitting any JavaScript, which is correct because Pulumi sets these properties dynamically." → ✅ verified (evidence: The TypeScript declare keyword is a well-established ambient declaration that tells the TypeScript compiler a property exists without emitting any JavaScript for it — this is standard TypeScript behavior. In Pulumi dynamic providers, out…; source: TypeScript language specification for ambient declarations; consistent with Pulumi's dynamic provider SDK at repo:sdk/nodejs/dynamic/index.ts where outputs are set by the runtime after resource registration)
  • L219 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "Pulumi sets dynamic resource output properties dynamically at runtime." → ✅ verified (framing: strengthened — the source describes the mechanism in detail; the claim summarizes it as "sets output properties dynamically at runtime," which is a narrower bu…; evidence: The concepts page for dynamic providers states that "the code inside a dynamic provider's implementation, such as create or update, runs during resource provisioning" and that create returns "A set of outputs that are returned to t…; source: content/docs/iac/concepts/providers/dynamic-providers.md)
  • L251 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The minimal random ID dynamic provider example is described as similar to the random provider available at https://www.pulumi.com/registry/packages/random/." → ✅ verified (evidence: The URL https://www.pulumi.com/registry/packages/random/ returns HTTP 200 and describes the "Random Provider" (package: random) published by Pulumi, confirming that a random provider exists at that registry URL. The claim that the dyna…; source: https://www.pulumi.com/registry/packages/random/)
  • L251 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "Generating a random value in regular Pulumi program code (outside a dynamic provider) would produce a new value on every run." → 🤷 unverifiable (evidence: The cited URL (https://www.pulumi.com/registry/packages/random/) is the Random provider overview page and returns HTTP 200, but its content only describes installation and package details — it contains no passage supporting or contradictin…; source: https://www.pulumi.com/registry/packages/random/; intuition: The claim is actually misleading: the Pulumi Random provider resources (e.g., RandomString) are stateful and do NOT reg…)
  • L275 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The GitHub labels example demonstrates the full dynamic provider interface: configure, check, create, diff, update, and delete." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L279 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "- configure reads the GitHub token from Pulumi config once, so individual resource declarations don't have to pass credentials." → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L282 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "The REST client in a dynamic provider must be constructed inside each method rather than shared, because the methods are serialized and run in a separate proce…" → ✅ verified (framing: strengthened — the source broadly states methods are serialized and run in a separate process limiting captured code; the claim narrows this to the specific RE…; evidence: The file itself states: "Provider methods are serialized to run in a separate process, which limits what code they can capture. See function serialization." The claim that a REST client must be constructed inside each method (rather than s…; source: content/docs/iac/guides/building-extending/providers/dynamic-providers.md)
  • L306 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "Passing credentials as resource inputs is an antipattern because it puts secrets in resource declarations and in state." → ✅ verified (framing: strengthened — claim adds "puts secrets in state" as a reason; the source confirms the antipattern label and Pulumi's secrets docs confirm inputs are stored in…; evidence: (escalated from pass1) The official Pulumi dynamic providers docs state: "passing provider credentials when declaring resources is an antipattern, to say the least." The "in state" concern is consistent with Pulumi's documented behavior th…; source: https://www.pulumi.com/docs/iac/concepts/providers/dynamic-providers/)
  • L308 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "Pulumi config values can be set as secrets using pulumi config set <key> <value> --secret." → ✅ verified (evidence: The official pulumi config set CLI docs confirm the --secret flag: "Encrypt the value instead of storing it in plaintext". The command syntax pulumi config set <key> [flags] [--] [value] supports placing --secret after the value as…; source: content/docs/iac/cli/commands/pulumi_config_set.md)
  • L309 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "A benefit of reading credentials from environment variables inside each provider method (rather than from Pulumi config) is that if the credentials change befo…" → ➖ not-a-claim (evidence: The claim is the PR author's own design rationale/guidance about a coding pattern (reading credentials from env vars vs. Pulumi config in dynamic providers). It describes the author's own documented recommendation and its benefit, not a th…; source: content/docs/iac/guides/building-extending/providers/dynamic-providers.md)

@github-actions
Copy link
Copy Markdown
Contributor

continued from previous comment
  • L311 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "Dynamic provider methods are serialized and run in a separate process, so each method reads credentials itself rather than sharing a client." → ➖ not-a-claim (evidence: The source_hint URL (https://api.example.com) is a placeholder/example domain, not a real citation. The claim itself is a description of the PR author's own design explanation of dynamic provider behavior in Pulumi documentation, not a thi…; source: https://api.example.com)
  • L332 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "const response = await fetch('https://api.example.com/widgets', {" → ➖ not-a-claim (evidence: The URL https://api.example.com/widgets appears in a code snippet (const response = await fetch(...)) as a placeholder/example API endpoint, not as a real cited source making a factual assertion. api.example.com is a well-known place…; source: https://api.example.com/widgets)
  • L354 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "const response = await fetch(https://api.example.com/widgets/${id}, {" → ➖ not-a-claim (evidence: The "URL" https://api.example.com/widgets/$ is a placeholder/example URL embedded in a code snippet (fetch(\https://api.example.com/widgets/${id}\``), not a real cited source or a falsifiable assertion about an external service.; source: https://api.example.com/widgets/$)
  • L388 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "'https://api.example.com/widgets'," → ➖ not-a-claim (evidence: https://api.example.com/widgets is a placeholder/example URL used in code samples to illustrate an API endpoint pattern, not a real cited source making a factual assertion. It is a standard example domain (RFC 2606) used in documentation…; source: https://api.example.com/widgets)
  • L402 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "f'https://api.example.com/widgets/{id}'," → ➖ not-a-claim (evidence: The URL https://api.example.com/widgets/{id} is a placeholder/example URL embedded in a code snippet (an f-string), not a real cited source making a factual assertion. api.example.com is a well-known example domain used in documentatio…; source: https://api.example.com/widgets/)
  • L417 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "When you modify the code of a dynamic provider, Pulumi does not automatically detect the change because from Pulumi's perspective the resource's inputs haven't…" → 🤷 unverifiable (evidence: verification did not converge within 8 turns)
  • L33 in static/programs/dynamic-github-labels-python/__main__.py "if not re.fullmatch(r'[0-9a-fA-F]{6}', color):" → ✅ verified (evidence: The regex [0-9a-fA-F]{6} with a quantifier of exactly 6 is the standard, well-established pattern for validating a 6-digit hex color code. Multiple authoritative sources confirm: "[0-9a-fA-F]{6} - Matches exactly six characters which can…; source: WebSearch ran query "hex color code regex validation 6 characters 0-9 a-f"; https://www.geeksforgeeks.org/dsa/how-to-validate-hexadecimal-color-code-using-regular-expression/ and https://regex-snippets.com/hex-color-code)
  • L31 in static/programs/dynamic-github-labels-typescript/index.ts "if (!/^[0-9a-fA-F]{6}$/.test(news.color)) {" → ✅ verified (evidence: The GitHub REST API requires label colors to be a 6-character hex string without a # prefix (e.g., "color":"f29513"). The regex ^[0-9a-fA-F]{6}$ correctly validates exactly 6 hexadecimal characters, matching the API's format. GitHub…; source: https://docs.github.com/en/rest/issues/labels)
  • L1 in content/docs/iac/guides/building-extending/providers/_index.md "frontmatter menu.iac.parent: iac-guides-providers does not exist in the iac menu" → ⚔️ mismatch (evidence: menu=iac parent=iac-guides-providers parent_exists_in_menu=false; source: frontmatter-validate.py pre-step)
  • L1 in content/docs/iac/guides/building-extending/providers/build-a-provider.md "frontmatter menu.iac.parent: iac-guides-providers does not exist in the iac menu" → ⚔️ mismatch (evidence: menu=iac parent=iac-guides-providers parent_exists_in_menu=false; source: frontmatter-validate.py pre-step)
  • L1 in content/docs/iac/guides/building-extending/providers/dynamic-providers.md "frontmatter menu.iac.parent: iac-guides-providers does not exist in the iac menu" → ⚔️ mismatch (evidence: menu=iac parent=iac-guides-providers parent_exists_in_menu=false; source: frontmatter-validate.py pre-step)

🚨 Outstanding in this PR

These must be resolved or refuted before merging.

No outstanding blockers in the touched lines.

⚠️ Low-confidence

Review each and resolve as appropriate — these don't block the PR.

  • [L132-134] content/docs/iac/concepts/providers/dynamic-providers.md"Dynamic providers are not supported with the Bun runtime (runtime: bun) because they depend on function serialization, which requires Node.js v8/inspector APIs that Bun does not fully implement yet." — verdict: unverifiable; the cited pulumi/pulumi#9085 is about pnpm, not Bun, so it doesn't anchor the Bun half of this paragraph. The Bun-side citation (https://bun.com/docs/runtime/nodejs-compat#nodeinspector) confirms Bun's node:inspector is partial, but doesn't itself state "dynamic providers don't work on Bun." Consider citing a Pulumi-side artifact for the Bun limitation — a GitHub issue, a discussion thread, or even a short user report — so a reader hitting this can confirm the failure mode and track the fix.

  • [L134] content/docs/iac/concepts/providers/dynamic-providers.md"All dynamic resources share the same resource type (pulumi-nodejs:dynamic:Resource for TypeScript or pulumi-python:dynamic:Resource for Python), so Pulumi Policy Packs must identify specific dynamic providers by checking for unique properties." — verdict: unverifiable; the Policy-Packs side is documented at /docs/insights/policy/policy-packs/authoring/#writing-policies-for-dynamic-providers, but the specific resource-type string pulumi-nodejs:dynamic:Resource wasn't reachable within the per-claim turn budget. The string is correct (it's hardcoded in sdk/nodejs/dynamic/index.ts and sdk/python/lib/pulumi/dynamic/dynamic.py), but if you want a citation in the page itself, linking to either SDK file or to the policy-packs doc section that names the type explicitly would close the loop.

  • [L104] content/docs/iac/guides/building-extending/providers/dynamic-providers.md"When functional, read looks up an existing resource by id and returns its canonical id and output properties. It is intended to support the static get method, pulumi import, and pulumi refresh." — verdict: unverifiable; this is a statement about non-implemented behavior, so there's no runtime evidence to point at. The framing ("when functional") is honest about that. If you want to harden it, the SDK comment at sdk/nodejs/dynamic/index.ts on the read method describes the intended contract and would be a natural citation.

  • [L108] content/docs/iac/guides/building-extending/providers/dynamic-providers.md"Although the input properties passed to a pulumi.dynamic.Resource are usually [Input values], your provider's methods are invoked with the fully resolved input values." — verdict: unverifiable from external sources, but this is the load-bearing reason for the strongly-typed-inputs pattern that follows. It's reflected in the SDK type signatures (olds/news/inputs are plain T, not Input<T>), so a one-line link to sdk/nodejs/dynamic/index.ts would let a reader verify the resolution behavior matches the prose.

  • [L187] content/docs/iac/guides/building-extending/providers/dynamic-providers.md"To access them with strong typing, declare each output as a class member on your pulumi.dynamic.Resource subclass. The member name must match the output property name returned by create." — verdict: unverifiable within the per-claim budget. The pattern is correct (the examples that follow demonstrate it) and matches the long-standing community guidance, but it isn't explicitly documented in the SDK reference. Consider linking to either of the example programs as the canonical demonstration.

  • [L219] content/docs/iac/guides/building-extending/providers/dynamic-providers.md"Using public readonly with the definite assignment assertion (!) can cause outputs to be undefined in some TypeScript configurations." — verdict: unverifiable; the failure mode is well-known anecdotally but doesn't have a canonical bug-issue citation in the trail. If you can attach the original repro (a tsconfig + a runtime-undefined output) or a GitHub issue, future readers won't have to take it on faith.

  • [L251] content/docs/iac/guides/building-extending/providers/dynamic-providers.md"This example generates a random ID once, when the resource is created, and keeps it stable across subsequent deployments by storing it in state. Generating the value in regular program code instead would produce a new value on every run." — verdict: unverifiable from the cited registry page; the verifier's intuition note that "the Random provider is stateful" misreads the claim — the contrast is with plain program code (e.g., a raw Math.random() call), not with the Random provider. The claim as written is correct; flagging only because the trail recorded it as unverifiable.

  • [L417] content/docs/iac/guides/building-extending/providers/dynamic-providers.md"When you modify the code of a dynamic provider — for example, changing the logic in create or update — Pulumi does not automatically detect the change. From Pulumi's perspective the resource's inputs haven't changed, so no update is triggered." — verdict: unverifiable from external sources but consistent with how function serialization works (the engine sees inputs, not the captured closure body). The three workarounds that follow (version input / diff returning changes:true / delete-and-recreate) are sound. A pointer to an existing GitHub discussion or to the function-serialization concepts page would give a reader something to anchor on.

Style findings

Found by pattern-based linting; Findings may be false positives.

Click each filename to expand.

content/docs/iac/guides/building-extending/providers/_index.md (1 issues: 1 weasel word)
  • line 40: [style] weasel word — 'usually' is a weasel word!
content/docs/iac/guides/building-extending/providers/dynamic-providers.md (6 issues: 4 wordiness, 2 weasel word)
  • line 48: [style] weasel word — 'usually' is a weasel word!
  • line 70: [style] wordiness — 'In many cases' is too wordy.
  • line 104: [style] wordiness — 'It is' is too wordy.
  • line 108: [style] weasel word — 'usually' is a weasel word!
  • line 251: [style] wordiness — 'subsequent' is too wordy.
  • line 251: [style] wordiness — 'similar to' is too wordy.

📋 Triaged verifier findings

I double-checked these and realized they weren't real findings — click to expand
  • [L1] content/docs/iac/guides/building-extending/providers/_index.md"frontmatter menu.iac.parent: iac-guides-providers does not exist in the iac menu" — verdict: mismatch. Spurious: the identifier iac-guides-providers IS defined in config/_default/menus.yml (line 19, under iac:). The frontmatter-validate.py pre-step checks only data/docs_menu_sections.yml, missing menu identifiers defined in config/_default/menus.yml. Every other file in this directory (provider-architecture.md, provider-configuration.md, implementers/_index.md) uses the same parent without breaking the build.

  • [L1] content/docs/iac/guides/building-extending/providers/build-a-provider.md"frontmatter menu.iac.parent: iac-guides-providers does not exist in the iac menu" — verdict: mismatch. Spurious: same root cause as above — the identifier lives in config/_default/menus.yml, which the pre-step doesn't read.

  • [L1] content/docs/iac/guides/building-extending/providers/dynamic-providers.md"frontmatter menu.iac.parent: iac-guides-providers does not exist in the iac menu" — verdict: mismatch. Spurious: same root cause as above — the identifier lives in config/_default/menus.yml, which the pre-step doesn't read.

  • [L40] content/docs/iac/guides/building-extending/providers/_index.md"The dynamic provider documentation is located at /docs/iac/guides/building-extending/providers/dynamic-providers/." — verdict: unverifiable. Mis-sourced: the verifier looked for the target file but didn't see the PR-internal new file content/docs/iac/guides/building-extending/providers/dynamic-providers.md (which this PR creates). The link target is created in this same PR; the link will resolve correctly once merged.

  • [L25] content/docs/iac/guides/building-extending/providers/build-a-provider.md"Dynamic providers are documented at /docs/iac/guides/building-extending/providers/dynamic-providers/." — verdict: unverifiable. Mis-sourced: same root cause as L40 in _index.md — the verifier ran out of turns before resolving against the PR-internal new file; the link target is the new guide page added in this PR.

  • [L275] content/docs/iac/guides/building-extending/providers/dynamic-providers.md"The GitHub labels example demonstrates the full dynamic provider interface: configure, check, create, diff, update, and delete." — verdict: unverifiable. Mis-sourced: the verifier didn't read the example program files. Both static/programs/dynamic-github-labels-typescript/index.ts and static/programs/dynamic-github-labels-python/__main__.py (also touched in this PR) implement all six methods.

  • [L279] content/docs/iac/guides/building-extending/providers/dynamic-providers.md"configure reads the GitHub token from Pulumi config once, so individual resource declarations don't have to pass credentials." — verdict: unverifiable. Mis-sourced: the verifier didn't read the example programs. Both dynamic-github-labels-typescript/index.ts (L25) and dynamic-github-labels-python/__main__.py (L26) call req.config.require("githubToken") in configure exactly as the prose claims.

💡 Pre-existing issues in touched files (optional)

  • [L31] content/docs/iac/guides/building-extending/providers/build-a-provider.md"The Pulumi Go Provider interface implements the following core methods: Create, Read, Update, Delete…" — verdict: contradicted (Provider interface actually has 14+ methods including GetSchema, Cancel, CheckConfig, DiffConfig, Configure, etc.). Pre-existing: this PR's only change to build-a-provider.md is a single-line link-target update at L25; L31 was not touched. Worth a follow-up to widen the prose or label this as "selected core methods" rather than the complete interface, but out of scope here.

  • [L124-125] content/docs/iac/guides/building-extending/providers/build-a-provider.md"The example go.mod file pins github.com/pulumi/pulumi-go-provider to v1.0.0." — verdict: contradicted (the GitHub release list for pulumi/pulumi-go-provider shows pre-release v1.0.0-rc.2 going directly to v1.0.1; there's no stable v1.0.0 tag). Pre-existing: L124-125 was not touched by this PR. Worth bumping to v1.0.1 or whatever the current stable is, as a follow-up.

  • [L516] content/docs/iac/guides/building-extending/providers/build-a-provider.md"The Pulumi Provider SDK provides default implementations for all provider interface functions other than Create." — verdict: contradicted (the SDK source at infer/resource.go says "There is no default behavior for CustomUpdate." — so Update also lacks a default). Pre-existing: L516 was not touched by this PR. Worth a follow-up to widen the exception list to "other than Create and Update."

  • [L137] content/docs/iac/guides/building-extending/providers/build-a-provider.md"The PulumiPlugin.yaml file tells Pulumi that the code can be loaded as a provider plugin and specifies the runtime environment to use." — verdict: unverifiable. Pre-existing: not on a touched line.

  • [L433] content/docs/iac/guides/building-extending/providers/build-a-provider.md"The .WithNamespace method sets the namespace that the generated language-specific SDKs will use…" — verdict: unverifiable. Pre-existing: not on a touched line.

  • [L714] content/docs/iac/guides/building-extending/providers/build-a-provider.md"A provider created in Go and used in YAML 'just works' by default without generating additional SDKs." — verdict: unverifiable. Pre-existing: not on a touched line.

  • [L714] content/docs/iac/guides/building-extending/providers/build-a-provider.md"To use a provider from other Pulumi authoring languages (TypeScript, Python, Java, Go, C#), it is necessary to generate SDKs for each target language." — verdict: unverifiable. Pre-existing: not on a touched line.

  • [L734] content/docs/iac/guides/building-extending/providers/build-a-provider.md"Pulumi providers can be hosted publicly or privately in GitHub and GitLab, using a private registry within Pulumi Cloud, or published to the public Pulumi registry." — verdict: unverifiable. Pre-existing: not on a touched line.

  • [L736] content/docs/iac/guides/building-extending/providers/build-a-provider.md"The Pulumi package authoring guide is documented at /docs/iac/using-pulumi/pulumi-packages/authoring/." — verdict: unverifiable. Pre-existing: not on a touched line.

✅ Resolved since last review

No items resolved since the last review.

📜 Review history

  • 2026-05-22T21:47:36Z — concepts/guide split looks clean; 0 outstanding after triaging spurious frontmatter mismatches and pre-existing claims in untouched lines of build-a-provider.md (0b8b360)

Need a re-review? Want to dispute a finding? Mention @claude and include #update-review.
(For ad-hoc questions or fixes, just @claude — no hashtag.)

@github-actions github-actions Bot added review:no-blockers Claude review completed cleanly; outstanding is empty and removed review:in-progress Claude review is currently running labels May 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain:docs PR touches technical docs domain:mixed PR touches more than one domain domain:programs PR touches static/programs/ review:no-blockers Claude review completed cleanly; outstanding is empty

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create Dynamic Providers Guide

2 participants