@@ -113,6 +113,7 @@ function toContextValidations(validations: unknown[] | null | undefined): Contex
113113function toContextField (
114114 field : FieldWithWireEnums ,
115115 ambiguousKeys : ReadonlySet < string > ,
116+ derivedPrimaryKeys : ReadonlySet < string > ,
116117) : ContextField {
117118 const serialized : ContextField = { field : field . field , type : field . type } ;
118119
@@ -126,7 +127,10 @@ function toContextField(
126127 const polymorphicTargets = toArray ( field . polymorphicReferencedModels ) ;
127128 if ( polymorphicTargets . length > 0 ) serialized . polymorphicTargets = [ ...polymorphicTargets ] ;
128129
129- if ( field . isPrimaryKey ) serialized . isPrimaryKey = true ;
130+ // The read-model derives a key when the schema declares none, and the BFF builds record
131+ // identifiers from it. Publishing only the schema's flag would leave a client unable to name the
132+ // key the BFF is actually using.
133+ if ( field . isPrimaryKey || derivedPrimaryKeys . has ( field . field ) ) serialized . isPrimaryKey = true ;
130134 if ( field . isRequired ) serialized . isRequired = true ;
131135 if ( field . isReadOnly ) serialized . isReadOnly = true ;
132136
@@ -168,10 +172,13 @@ function toContextCollection(
168172 field => typeof field === 'object' && field !== null ,
169173 ) ;
170174 const ambiguousKeys = ambiguousRecordKeys ( fields ) ;
175+ const derivedPrimaryKeys = new Set (
176+ readModel . getPrimaryKeys ( collection . name ) . map ( key => key . name ) ,
177+ ) ;
171178
172179 return {
173180 name : collection . name ,
174- fields : fields . map ( field => toContextField ( field , ambiguousKeys ) ) ,
181+ fields : fields . map ( field => toContextField ( field , ambiguousKeys , derivedPrimaryKeys ) ) ,
175182 actions : toArray ( collection . actions )
176183 . filter ( action => {
177184 const allowed = allowedActions [ action ?. name ] ;
0 commit comments