You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 207eb98
Browse filesBrowse the repository at this point in the historyBrowse files
fix(rest)!: declare the public picker's key change as a breaking widening with one narrowing, and pin the narrowing
The changeset now grades the change minor with the breaking signal, declares
it yes with the narrowing arm, and carries one ADR-0087 disposition marker
(not-required, no migration prescription). The narrowing it names: with a
security service that cannot give the query answer, every display field
declaring a masking rule is passed over for every caller, so a picker whose
display fields all declare one is refused 403 PERMISSION_DENIED where it was
served. One pin drives that case for a caller the rule is lifted for, with
the answering service as its control, and asserts the engine is never asked.
The route is unchanged.
Claude-Session: https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H
Co-authored-by: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: .changeset/21062-picker-queryable-key.md
+16-8Lines changed: 16 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,10 +1,14 @@
1
1
---
2
-
'@objectstack/rest': patch
2
+
'@objectstack/rest': minor
3
3
---
4
4
5
-
fix(rest): a public form's lookup picker searches and sorts by the first display field the caller may query, so a picker whose first display field is masked for its caller serves its rows instead of answering 403 (#21062)
5
+
fix(rest)!: a public form's lookup picker searches and sorts by the first display field the caller may query, so a picker whose first display field is masked for its caller serves its rows instead of answering 403 (#21062)
6
6
7
-
Clause-②: no
7
+
Clause-②: yes (narrowing)
8
+
9
+
<!-- adr-0087: not-required (no-migration-prescription) a change of which display field the public lookup picker (`GET /forms/:slug/lookup/:field`) searches and sorts by: the first display field the caller may query, by the security service's answer, where it used to be the first display field. No authorable key, spelling, export or stored shape moves: `@objectstack/rest` exports nothing new and nothing less, `FormFieldPublicPickerSchema` keeps parsing every value it parsed, and no stored row is read or rewritten. A picker's `displayFields` keep their meaning as the projected fields. The other categories are closed on facts: the package publishes (not `unpublished`); no ADR-0087 id covers which field a picker keys on (not `already-registered`); and the change is route behaviour, not a declaration (not `runtime-interface-only` / `type-surface-only`). -->
10
+
11
+
**BREAKING**: this widens what the public lookup picker serves and narrows it in one composition. The narrowing: with a security service that lacks `ISecurityService.getQueryableFields`, or that answers no answer for the object, the picker passes over every display field whose declaration carries a `maskingRule`, for every caller, including a caller the rule is lifted for. So its search and order move to the next display field that declares no rule, and a picker whose display fields all declare a rule is refused `403 PERMISSION_DENIED` without the engine being asked, where it used to be served. The security service this repository ships implements the method, so a deployment using it is not narrowed. It ships as `minor` under the launch-window convention for accept-set narrowings. No export or published type changes.
8
12
9
13
**What changed.** The public lookup picker (`GET /forms/:slug/lookup/:field`)
10
14
matches the visitor's search and orders its rows by one key. That key used to
@@ -23,14 +27,18 @@ row, masked, as before.
23
27
running a query.
24
28
25
29
**Unchanged.** A picker with no masked display field, and a caller the masking
26
-
rule is lifted for, keep the first display field as the key. A deployment with
27
-
no security service keeps the first display field. A security service that
28
-
cannot say which fields are queryable (it predates the method, or has no answer
29
-
for the object) gets the fallback its contract prescribes: every display field
30
-
whose declaration carries a `maskingRule` is passed over, whoever the caller is.
30
+
rule is lifted for, keep the first display field as the key, with the security
31
+
service this repository ships. A deployment with no security service keeps the
32
+
first display field.
31
33
32
34
**What to do.** Nothing. To choose the field a picker searches when its first
33
35
display field is masked for some of its callers, list a field those callers may
34
36
query among `displayFields`: the first such entry is the one searched and
35
37
sorted on. A picker whose only display fields are masked for its callers is
36
38
refused, so give it one they may query.
39
+
40
+
**What to do after upgrading, if your security service predates `getQueryableFields`.**
41
+
Implement `getQueryableFields` on it: it answers which fields a caller may filter,
42
+
sort, group or aggregate by, and the picker then keys on the first display field
43
+
in that answer. Until it does, give each picker at least one display field that
44
+
declares no `maskingRule`, or the picker is refused for every caller.
Copy file name to clipboardExpand all lines: packages/rest/src/public-form-lookup-picker-queryable-key.test.ts
+26Lines changed: 26 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -394,3 +394,29 @@ describe('[#21062] a security service that cannot give the query answer passes o
394
394
});
395
395
}
396
396
});
397
+
398
+
/**
399
+
* The narrowing the changeset declares (`Clause-②: yes (narrowing)`). With a
400
+
* security service that cannot give the query answer, the fallback passes over
401
+
* every display field declaring a masking rule WHOEVER the caller is, so for a
402
+
* caller the rule is lifted for, a picker whose display fields all declare one
403
+
* goes from served to refused. Its control is the same caller and picker with
404
+
* the service that answers: served.
405
+
*/
406
+
describe('[#21062] the declared narrowing: a security service without the query answer refuses a picker whose display fields all declare a masking rule',()=>{
0 commit comments