Skip to content

fix: a list result names the object by the key the resource is addressed by - #108

Merged
ShocOne merged 1 commit into
mainfrom
fix/list-identity-from-item-key
Aug 15, 2026
Merged

fix: a list result names the object by the key the resource is addressed by#108
ShocOne merged 1 commit into
mainfrom
fix/list-identity-from-item-key

Conversation

@ShocOne

@ShocOne ShocOne commented Aug 15, 2026

Copy link
Copy Markdown
Member

ThousandEyes emitted 35 resources and 11 list resources. The count was accurate;
the gap was a defect.

The rule, and where it was lost

A collection GET with no id in its path is a list resource wherever a resource
of the same kind exists. classify.go implements exactly that
(listOK := resourceOK && e.list != nil && e.list.SuccessSchema() != nil) and
derives 34 for ThousandEyes. Emission served 11 and refused 23, narrowing a
classification rule from a stage that was never meant to decide it.

Defect one: the element had no id to publish

A list result is an identity, and an identity is the resource's id. The resource
takes its id from the item path key wherever the object declares no property of
that name — ensureID has always done this, so /tests/{testId} gives the
resource an id reading testId. derive.listResource never called it, so the
element kept only the document's own spelling as test_id, and
findIdentityNode looked for a literal id and refused the entity.

The split was exact, which is what confirmed it: 11 of 34 ThousandEyes
elements declared a literal id, and 11 emitted. Every one of the other 23
carried the key — as testId, ruleId, dashboardId, snapshotId.

Fixed by calling ensureID on the element with the same key the resource uses.
Not a new rule; the rule the resource already follows, applied to the entity
that needs the same answer. ensureID returns early when an id exists, so the
entities that worked are untouched by construction.

Defect two, which the first was hiding

With the element publishing an identity, entities got one refusal further and
hit a second: "the list block cannot supply rule_id, which the resource's
identity names"
.

An identity is the parents that scope an object plus its id, and the item path
key is the id. addressingNames collected every path parameter including
that one, so wherever a document also declared the key as a property —
/alerts/rules/{ruleId} beside a ruleId field — the identity required the
same value under two names, of every import and of every list result. Only
resourceIdentity changes; the joinTree callers still want the full set.

Measured

All three trees regenerate, pass postcheck and report no drift under
provider verify:

Document List resources before After Emission refusals before After
ThousandEyes 11 30 23 4
GitHub 23 29 21 15
Jamf Pro 39 39 17 17
Total 73 98 61 36

docs/emittance_tracker.md is re-measured.

What still refuses, and why it is data

Eleven entities across the three documents are one shape: the path spells the
key generically while the element names it specifically — /roles/{id} beside
roleId, /users/{id} beside uid, aid, groupId. No rule derives those.
Taking the element's only id-shaped scalar would resolve some and silently pick
wrong on dashboard, which carries four; a wrong identity lists the wrong
objects and says nothing.

So the refusal now names what it looked for and what the element does carry:

entity "role" :: the element publishes no identity: it carries no readable
  scalar "id", though it carries roleId
entity "orgs_campaign" :: the element publishes no identity: it carries no
  readable scalar "id", and no readable scalar it carries is spelled like a key

Naming the field as data — an x-tfpfgen-* key on the list operation — is the
follow-up, and gated on the naming decision.

Verification

make check passes at 91.3%. New derivation tests cover an element keyed the
API's way and one that declares its own id; new emission tests cover the
identity being published from the element's own key, the refusal naming its
candidates, and the item key not doubling as addressing. derive_test.go passed
the 800-line ceiling, so the list-resource cases moved to
derive_list_resource_test.go.

Both defects were found by regenerating the three documents, not by a test.

🤖 Generated with Claude Code

…sed by

A collection GET with no id in its path is a list resource wherever a
resource of the same kind exists. Classification says so and derives 34 of
them from ThousandEyes; emission served 11, and narrowed the rule for a
difference in wording.

A list result is an identity and an identity is the resource's id. The
resource takes its id from the item path key where the object declares no
property of that name — ensureID has always done this — but the list
element did not, so an API spelling its key testId rather than id
published no identity and lost the entity outright.

Deriving the element's id the same way exposed a second refusal behind the
first. An identity is the parents that scope an object plus its id, and
the item path key is the id; counting it as addressing too required the
same value under two names, of every import and of every list result,
wherever the document also declared that key as a property.

List resources go 73 to 98: ThousandEyes 11 to 30, GitHub 23 to 29, Jamf
Pro unchanged. What still refuses names the key it looked for and the
fields the element does carry, so the eleven that need the field named as
data can be found without reading the toolkit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ShocOne
ShocOne merged commit d4b7519 into main Aug 15, 2026
2 checks passed
@ShocOne
ShocOne deleted the fix/list-identity-from-item-key branch August 15, 2026 19:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant