Skip to content

Root cause: member/attribute enumerators don't walk the generalization chain (umbrella for #758, #703, #451) #765

Description

@dimenus

Summary

Several separate issues share one root cause: the code that enumerates an entity's members walks only the entity's own members and never the generalization (inheritance) chain. When an entity extends a parent, the inherited attributes and associations are invisible to these paths, so they are dropped, skipped, or mis-qualified.

This issue is a place to track that shared gap, so the symptoms can be fixed together rather than one at a time.

Symptoms already reported

The common gap

The member/attribute enumerators build their member set from the entity's own Attributes and own FROM-side associations only. Two examples from the security path:

  • mdl/backend/modelsdk/domainmodel_security_write.go (ReconcileMemberAccesses): the "known member" set is built from ent.AttributesItems(), own FROM-side associations, and System.owner / System.changedBy (the last only when the entity has NoGeneralization). It then removes any existing MemberAccess whose qualified name is not in that set — so System.FileDocument.Contents on an entity that extends System.FileDocument gets stripped.
  • mdl/executor/cmd_security_write.go (around line 381): builds MemberAccess entries only for entity.Attributes (own), so a GRANT ... read (InheritedAttr, ...) omits the inherited names.

Generalization is consulted only for narrow special cases (the NoGeneralization owner/changedBy branch, and a GeneralizationRef == "System.User" check). There is no general "include the parent's members" step anywhere.

Why it is not a trivial fix

A full fix has to resolve the parent entity's members, and the parent is often a System-module entity (System.FileDocument, System.Image). The System module's domain model is virtual (injected, not stored in mprcontents, immutable), so the fix needs generalization-chain traversal plus cross-module resolution plus the virtual System-module member set.

A smaller, safer step for the security reconcile specifically: own members are qualified as Module.ThisEntity.member, while inherited members are qualified under their parent (a different prefix). The reconcile could remove only entries carrying the entity's own prefix that are truly gone, and leave differently-prefixed (inherited) entries alone — which avoids resolving the System module. This would need confirming how inherited-member qualified names are actually stored.

Suggested label

architecture (shared root cause across writers), or bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions