0070. A has-many names the inverse it follows with via=
0070. A has-many names the inverse it follows with via=
Status
Accepted
Date
2026-10-10
Deciders
operator (Saulo Vallory), accepting roadmap revision 5 on 2026-10-10 at 09:05, decision D7 with its recommended option.
Context
A has-many :memberships entity=Membership follows the key that Membership holds back to this entity. Hyper’s Membership has three belongs-to to Collaborator (collaborator, grantedBy, revokedBy) and its Dependency two to Task; the compiler accepts the has-many without saying which key it follows, and the model records no key (gap G28). The entities page reserves &name for a member of this entity, so via=&collaborator would name a member of the other entity with a spelling that means something else everywhere (ADR-0067).
Decision
has-many takes an optional via=, an atom naming the other entity’s belongs-to:
has-many :memberships entity=Membership via=:collaborator
- With exactly one
belongs-tofrom the other entity back to this one,viamay be left out and that key is followed. - With more than one,
viais required; omitting it is a build error that lists the candidates. - A
viathat names nobelongs-toof the other entity, or one that points at a different entity, is a build error at the attribute, with a did-you-mean. has-oneis unchanged.
Options considered
via=:collaborator, an atom (chosen). An atom names a declaration or a fixed-set value (ADR-0066); here it names a declaration in another entity.via=&collaborator. Reads as a member of this entity, which it is not.- Infer from the name (
:membershipsfollowsmembershipsId): breaks as soon as names differ from the keys.
Trade-off analysis
An atom is the only spelling in the file that names something without referring to this entity’s members. The build cannot check an atom against this entity’s members, so the check is a cross-file one (the other entity’s relationships), which the build already makes for entity=. The cost is one more option on has-many.
Consequences
- The model records the key a
has-manyfollows, which relationship loading (M7) needs. - Entities documents the option.
Action items
- M7: the contract attribute, the cross-file check and the loader.