Entity<ID> binds its parameter through id() (Entity.java:37); Projection<ID> (storm-foundation/src/main/java/st/orm/Projection.java:69) has an empty body, so ID is a phantom parameter, and its javadoc assigns it two meanings ("the primary key type, or Void if the projection has no primary key"). The asymmetry surfaces in the API: Ref.of(projection, id) (Ref.java:130) must take the id separately precisely because the type cannot produce it.
Decide the contract: either projections with a PK expose an accessor the type can rely on, or the marker-only role (and the Void convention) is documented as deliberate on the interface. Today a reader cannot tell which is intended.
Entity<ID>binds its parameter throughid()(Entity.java:37);Projection<ID>(storm-foundation/src/main/java/st/orm/Projection.java:69) has an empty body, soIDis a phantom parameter, and its javadoc assigns it two meanings ("the primary key type, or Void if the projection has no primary key"). The asymmetry surfaces in the API:Ref.of(projection, id)(Ref.java:130) must take the id separately precisely because the type cannot produce it.Decide the contract: either projections with a PK expose an accessor the type can rely on, or the marker-only role (and the Void convention) is documented as deliberate on the interface. Today a reader cannot tell which is intended.