fix: a list resource is the list capability of a resource - #99
Merged
Conversation
Terraform matches a list resource to a managed resource by type name and refuses to load a provider whose list resource names none — refusing the whole provider, not the one entity. Every list resource emitted was unmatched: classification produced one exactly where an entity had a collection GET and no item GET, which is the shape no resource can have. So the entity that is enumerable but not addressable is a datasource, and the list capability belongs to a resource the API can enumerate. A resource the bindings or emission refuse takes its list resource with it, because the pair is what terraform requires. Terraform also reserves seven names at the root of a schema, and rejects a provider declaring one. A root attribute so named is refused with the remedy named: a correction renaming the property. Nested, the same name is an ordinary field and stands. Neither defect is visible to postcheck, which builds the tree and never loads it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 1 of making the generated providers' own tests pass. Two defects, both of
which cost the entire provider, and neither of which
postcheckcan see —it builds the tree and never loads it.
1. Every emitted list resource was unmatched
HashiCorp's documentation:
fwserver/server_listresources.go:98enforces it asresourceFuncs[typeName],and an unmatched list resource fails the provider's whole schema load:
classify.go:183made a match impossible —resourceOKneeds an item GET,listOnlyShapeneeds its absence — so the resource/list-resource overlap wasexactly zero on all three pilots. The entities concerned are read-only
collections:
GET /app,GET /v1/activation-code/history,GET /v1/api-role-privileges. None is manageable.Now: an entity that is enumerable but not addressable is a datasource.
The list capability belongs to a resource the API can enumerate, sharing its
terraform type — which
Namesalready give, being computed per entity beforethe kind dispatch.
And the other direction: a resource the bindings or emission refuse takes its
list resource with it. Six github list resources were left unmatched that way
even after reclassification —
orgs_actions_runner_groupamong them, whoseresource is refused for a path parameter the SDK types differently. The pair is
what terraform requires, so the pair goes together.
2. Terraform reserves seven root attribute names
A second, independent whole-provider failure:
fwschema.ReservedResourceAttributeNamesisconnection,count,depends_on,for_each,lifecycle,provider,provisioner— applied byresource/schema,datasource/schema,action/schemaandlist/schemaalike, at root depth only.A root attribute so named is refused, with the remedy named in the reason: a
correction renaming the property. Refused rather than renamed here, because the
name is what a practitioner writes and choosing another belongs in a correction,
not in a rule. Nested, the same name is an ordinary field and stands.
Measured effect
Zero schema-load failures on all three pilots, from 712 / 530 / 258.
440 invalid list resources → 118 valid ones. No entity was lost: they moved
kind.
provider verifyreports no drift (4390 / 3895 / 1798 files) andpostcheckpasses.Refusals: github 817 → 834 (+17: six list resources whose resource is not
served, plus reclassification), jamfpro 290 → 255 (−35), thousandeyes 343 → 361
(+18). Four
countrefusals on jamfpro and oneconnectionon thousandeyes arethe reserved names.
Naming
docs/glossary.md: list resource is redefined as "the list capability of amanaged resource", with the old meaning recorded as retired the way the v1
vocabulary is, and a resource identity schema entry added for Phase 2.
Tests
Toolkit tests were updated to the new semantics, not weakened — several asserted
the old taxonomy directly. New:
TestUnit_ListResource_GoesWithTheResourceItLists,TestUnit_Attribute_RefusesAReservedRootName,TestDerive_ListOnlyEntityIsADatasource,and two classification cases pinning that neither half of the pair fires alone.
The IR fixture's
countattribute was renamed rather than special-cased, so thetests that use it keep their meaning.
Gates
gofmt,repo_hygiene_gate.sh,golangci-lint(0 issues),go build/go vet— passgo test ./...— pass, coverage 91.5% totalprovider generate+provider verifyon all three — no driftStill to come
Phase 2 emits the resource identity schema —
NewListResultdereferences it, soreal
terraform listwould still panic. Phase 3 makes fixtures respectformat.🤖 Generated with Claude Code