Skip to content

Commit 859dfa7

Browse files
committed
docs(spec): correct three statements in the cross-class D3 entry; lint header names the delegation
The entry's reason no longer says a file field has no stored column: the file family is refused by name for the ADR-0104 dual-encoding reason the spec module gives. acceptanceCriteria qualifies the 400 read with "on the SQL drivers", and the replacement's text class lists all four reference types (tree included). registry.ts regenerated by gen:migration-registry. The lint header's #20347 paragraph says driver-sql now delegates through crossFieldColumnVerdict instead of naming the retired parity test. Claude-Session: https://claude.ai/code/session_01N8TPEsoJxPsdSdNKGnNGEN Co-authored-by: Claude <noreply@anthropic.com>
1 parent 4e430ba commit 859dfa7

3 files changed

Lines changed: 22 additions & 12 deletions

File tree

‎packages/lint/src/validate-rls-predicate-enforceability.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,8 @@
246246
*
247247
* This arm refuses the comparison where it is written, by the same rule the
248248
* read applies: {@link crossFieldComparisonVerdict} (`@objectstack/spec/data`),
249-
* the classification lifted from driver-sql and held to it by a pairwise parity
250-
* test there. Only `comparable` passes; `cross-class` and `no-class` (a file
249+
* the classification lifted from driver-sql, which now delegates to it
250+
* through `crossFieldColumnVerdict`. Only `comparable` passes; `cross-class` and `no-class` (a file
251251
* field, a formula field) are refused, and `unjudged` — a declared type outside
252252
* `FieldType` — is Zod's to reject, not this arm's. A comparison either side of
253253
* which holds a list or an object stays the arm above's, so no comparison is

‎packages/spec/src/migrations/entries/semantic/18.rls-predicate-cross-class-field-comparison-refused.ts‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,20 @@ export const entry: SemanticMigration = {
2525
replacement:
2626
'a comparison between two columns of one comparison class: a number with a number (number, '
2727
+ 'currency, percent, rating, slider, progress, summary), text with text (the string types, '
28-
+ 'autonumber, a single select or radio, a single lookup, master_detail or user), a boolean with '
29-
+ 'a boolean, a date with a date, a datetime with a datetime, a time of day with a time of day. '
28+
+ 'autonumber, a single select or radio, a single lookup or user, a master_detail or a tree), a '
29+
+ 'boolean with a boolean, a date with a date, a datetime with a datetime, a time of day with a '
30+
+ 'time of day. '
3031
+ 'A file field and a formula field cannot be compared with another column at all: compare the '
3132
+ 'field with a literal or test it for null. If the two columns do hold comparable values, one '
3233
+ 'of them is declared with the wrong type, so correct that declaration rather than the '
3334
+ 'predicate. Comparisons between two columns of one class lower and evaluate exactly as before',
3435
reason:
3536
'A column-to-column comparison has one meaning only within one comparison class: across '
3637
+ 'classes SQLite orders every TEXT above every INTEGER while the in-process evaluator coerces '
37-
+ '("open" > 5 is false), and a file or formula field has no stored column value to compare. '
38+
+ '("open" > 5 is false). A formula field is virtual, with no stored column to reference. The '
39+
+ 'file family is refused by name, whatever the deployment stores: during the ADR-0104 '
40+
+ 'dual-encoding window one media column can hold a bare id and another the JSON-quoted form of '
41+
+ 'the same id, so no comparison against the family is provably one answer on every path. '
3842
+ 'driver-sql has refused such a comparison on the read since #5222, so a policy written '
3943
+ 'record.status != record.amount (text and a number), record.status != record.photo (text and '
4044
+ 'an image) or record.status != record.is_open (text and a formula field) got three answers, '
@@ -65,6 +69,7 @@ export const entry: SemanticMigration = {
6569
+ 'compares two fields of different comparison classes, with both declarations. Rewrite each as '
6670
+ 'the replacement says. A policy that never passed os validate (stored before the authoring '
6771
+ 'arm, or written by another path) is refused at request time instead: every read it scopes '
68-
+ 'answers 400, and so does every insert or update its check judges, so re-check what each such '
69-
+ 'policy is meant to admit rather than assuming the writes it admitted before were right.',
72+
+ 'answers 400 on the SQL drivers, and so does every insert or update its check judges, so '
73+
+ 're-check what each such policy is meant to admit rather than assuming the writes it admitted '
74+
+ 'before were right.',
7075
};

‎packages/spec/src/migrations/registry.ts‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14260,16 +14260,20 @@ const step18: MigrationStep = {
1426014260
replacement:
1426114261
'a comparison between two columns of one comparison class: a number with a number (number, '
1426214262
+ 'currency, percent, rating, slider, progress, summary), text with text (the string types, '
14263-
+ 'autonumber, a single select or radio, a single lookup, master_detail or user), a boolean with '
14264-
+ 'a boolean, a date with a date, a datetime with a datetime, a time of day with a time of day. '
14263+
+ 'autonumber, a single select or radio, a single lookup or user, a master_detail or a tree), a '
14264+
+ 'boolean with a boolean, a date with a date, a datetime with a datetime, a time of day with a '
14265+
+ 'time of day. '
1426514266
+ 'A file field and a formula field cannot be compared with another column at all: compare the '
1426614267
+ 'field with a literal or test it for null. If the two columns do hold comparable values, one '
1426714268
+ 'of them is declared with the wrong type, so correct that declaration rather than the '
1426814269
+ 'predicate. Comparisons between two columns of one class lower and evaluate exactly as before',
1426914270
reason:
1427014271
'A column-to-column comparison has one meaning only within one comparison class: across '
1427114272
+ 'classes SQLite orders every TEXT above every INTEGER while the in-process evaluator coerces '
14272-
+ '("open" > 5 is false), and a file or formula field has no stored column value to compare. '
14273+
+ '("open" > 5 is false). A formula field is virtual, with no stored column to reference. The '
14274+
+ 'file family is refused by name, whatever the deployment stores: during the ADR-0104 '
14275+
+ 'dual-encoding window one media column can hold a bare id and another the JSON-quoted form of '
14276+
+ 'the same id, so no comparison against the family is provably one answer on every path. '
1427314277
+ 'driver-sql has refused such a comparison on the read since #5222, so a policy written '
1427414278
+ 'record.status != record.amount (text and a number), record.status != record.photo (text and '
1427514279
+ 'an image) or record.status != record.is_open (text and a formula field) got three answers, '
@@ -14300,8 +14304,9 @@ const step18: MigrationStep = {
1430014304
+ 'compares two fields of different comparison classes, with both declarations. Rewrite each as '
1430114305
+ 'the replacement says. A policy that never passed os validate (stored before the authoring '
1430214306
+ 'arm, or written by another path) is refused at request time instead: every read it scopes '
14303-
+ 'answers 400, and so does every insert or update its check judges, so re-check what each such '
14304-
+ 'policy is meant to admit rather than assuming the writes it admitted before were right.',
14307+
+ 'answers 400 on the SQL drivers, and so does every insert or update its check judges, so '
14308+
+ 're-check what each such policy is meant to admit rather than assuming the writes it admitted '
14309+
+ 'before were right.',
1430514310
},
1430614311
// Stage 2e of #19886: the mirror of stage 2d's ordering refusal, with the list on
1430714312
// the RECORD's side. The shape is legal, a field ordered against one bound; what

0 commit comments

Comments
 (0)