The wording for "you may not WRITE this field" — used only when the caller can READ it.
Naming the reason here discloses nothing. The caller can see the field and its values, so
both facts the ambiguous wording withholds — that the column exists, and that it is
restricted for them — are already theirs. All this adds is which permission is missing,
which they would learn by trying anyway.
The two justifications behind FieldSecurityDenialMessage do not reach this case:
predicate probing is a question about columns the caller cannot READ, and the
#3485 argument — that "does not exist"
becomes literally true once restricted fields stop shipping to clients — is false for a
readable field, which keeps shipping. Ambiguity there does not age into truth; it just tells
someone that a field they are looking at might not exist.
A field the caller cannot read must still use the ambiguous wording. That is not hypothetical:
SetMany deliberately skips the readability assertion (it is the hydration and resolver-apply
path), so server-side code can dirty a read-denied field and reach the update gate.
The wording for "you may not WRITE this field" — used only when the caller can READ it.
Naming the reason here discloses nothing. The caller can see the field and its values, so both facts the ambiguous wording withholds — that the column exists, and that it is restricted for them — are already theirs. All this adds is which permission is missing, which they would learn by trying anyway.
The two justifications behind FieldSecurityDenialMessage do not reach this case: predicate probing is a question about columns the caller cannot READ, and the #3485 argument — that "does not exist" becomes literally true once restricted fields stop shipping to clients — is false for a readable field, which keeps shipping. Ambiguity there does not age into truth; it just tells someone that a field they are looking at might not exist.
A field the caller cannot read must still use the ambiguous wording. That is not hypothetical:
SetManydeliberately skips the readability assertion (it is the hydration and resolver-apply path), so server-side code can dirty a read-denied field and reach the update gate.