update_node stamped source/owner metadata on updated attributes but not on
updated relationships, so a relationship changed by a sync carried no lineage
back to the sync source/owner. This was asymmetric with the create path, which
attributes relationships via generate_payload_create.
Assign relationships via a data dict ({"id", "source", "owner"}) instead of the
bare peer, in both the cardinality-one and cardinality-many branches, so the
same attribution the attribute path applies is stamped on relationships too.
Adds unit tests covering attribute attribution (regression), cardinality-one
and cardinality-many relationships (with and without source/owner), and a
real-SDK check that the dict serialises to _relation__source/_relation__owner.
Fixes #142
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem
update_node(infrahub_sync/adapters/infrahub.py) setssource/ownerattribution on updated attributes but not on updated relationships. A relationship changed by a sync therefore carries no lineage back to the sync's source/owner — most visible for update-only flows, where an object is matched and only its relationships/attributes are updated (never created). This is asymmetric with the create path, wheregenerate_payload_create(..., source=..., owner=..., is_protected=True)attributes attributes and relationships alike.Fixes #142.
Fix
Assign relationships via a data dict (
{"id", "source", "owner"}) instead of the bare peer, in both the cardinality-one and cardinality-many branches. The SDK'sRelatedNodereadssource/ownerfrom that dict and serialises them as_relation__source/_relation__ownerin the mutation input — the same attribution the attribute path already applies.Before → after:
source/ownerare omitted from the dict when unset, so behaviour is unchanged when no source/owner is configured.Tests
New
tests/adapters/test_infrahub_update_node_attribution.py(12 tests):idwhen unset)RelatedNodeSyncbuilt from the helper serialises to_relation__source/_relation__ownerThe relationship tests were confirmed to fail against the pre-fix code. Full unit suite: 122 passed / 2 skipped.
ruff check,ruff format --check, andty checkare all clean (no new diagnostics vsmain).Note
Scoped to
source/ownerto mirror the attribute-update path exactly. The create path additionally setsis_protected=Trueon relationships; this PR intentionally does not change protection on update (that would be a behaviour change beyond the attribution gap). Happy to add it if maintainers prefer full create/update parity.🤖 Generated with Claude Code
Summary by CodeRabbit