Repository navigation
feat(sdl): offer only typed relationship endpoints that pass their subtype's attribute rules #1577
Description
Gap Claim
PR #1446 (for #1339) gives each typed relationship endpoint an eligibility purpose by declaration kind, and completion offers only declarations of the admitted kinds. The identity, topology and tenancy subtypes also check attributes of the named record, and completion does not apply those checks. So completion can offer a declaration that validation then refuses:
domain_controller_forandjoins_domainsource: the node must be a compute node (domain.relationship.source-not-vm,raes/semantics/domain_topology.py). Completion offers every node, including a switch node.placed_on_carrier: both nodes must be compute nodes and the target must carry the carrier persona, in the same deployment cell (deployment-tenancy.placement.*,raes/semantics/deployment_tenancy.py). Completion offers every node.forest_trusts: the two forests must differ (enterprise-identity.forest-trust.self). Completion offers the forest already named on the other side.
Evidence: on the #1446 branch, test_typed_endpoint_kinds_equal_what_the_owning_semantic_module_accepts in implementations/python/tests/test_issue_1339_relationship_endpoints.py lists the switch node lan of the all-kinds fixture as an attribute row. The policy admits its kind, and the owning module refuses the record with its attribute diagnostic.
Existing Surface Audit
raes/_reference_targetability.pyandraes/_relationship_endpoint_policy.py(feat!: make reference eligibility explicit per purpose and align the editor with validation #1446) decide endpoint eligibility by declaration kind. Make target eligibility explicit and align editor suggestions #1339 bullet 1 and audit F4 ask for eligibility "by purpose and declaration kind", and ADR-052 §2 places typed-subtype cross-reference resolution in the semantic validator.- The semantic modules resolve the endpoint with
resolve_section_reforservice_ownerand check the attributes on the resolved record. - Completion (
raes/language_service.py) already applies one refinement beyond kind for participant relationships (_endpoint_held), so a per-field refinement after the kind filter has a precedent.
Alternatives
- Do nothing: completion keeps offering records that validation refuses for subtype attributes. Rejected, because F5 asks completion to agree with validation.
- Move the attribute checks into the reference policy: rejected. Eligibility is by declaration kind, and the attribute rules belong to the subtype owners (ADR-052 §2); a second copy in the policy could drift.
- Let completion ask each owning module whether a resolved candidate passes its attribute checks, after the kind filter: selected.
Chosen Architecture
Each owning semantic module exposes a small predicate over a resolved candidate for its (type, side) that reuses the check it already runs: compute node, carrier persona, same cell, distinct forest. Completion applies that predicate after the purpose filter, as _endpoint_held does for participant relationships. Validation is unchanged.
Verification Plan
- For every (type, side) with an attribute rule, every candidate that completion offers in the all-kinds fixture validates when written into that endpoint.
- The switch node
lanis not offered as adomain_controller_forsource or aplaced_on_carrierendpoint, and a forest is not offered as its own trust partner. - Kind-level completion for subtypes without attribute rules is unchanged.
Related
- Make target eligibility explicit and align editor suggestions #1339, feat!: make reference eligibility explicit per purpose and align the editor with validation #1446 (kind-level endpoint purposes), Relationship scope completion ignores the selected control specification #1511 (another completion bound that validation applies)
Activity