fix(search): keep the empty-qf 400 at the wire

The empty-tree grammar relaxation (create-modal episodes seed) must not
leak into the search deep-link contract: qf={"mode":"all","children":[]}
as a QUERY would silently mean "match everything". The seed's meaning —
a rules-less collection matching nothing — lives in the stored tree and
its composers; the query entry point now rejects a rule-less tree
explicitly, preserving the pinned 400 that TestFilterQFValidationAndPrecedence
guards (the test caught the leak during this round's full-suite run).
This commit is contained in:
John O'Keefe committed 2026-10-31 15:56:23 -04:00
1 parent d6619cd0e1
commit 744d33e13f
1 file changed
+7
+7
View File
@@ -2559,6 +2559,13 @@ func ParseMediaSearchParams(c searchParamSource) services.SearchParams {
tree, err := services.ParseFilterTree(qf)
if err != nil {
params.FilterParseErr = err.Error()
} else if len(tree.Children) == 0 {
// A qf with no rules is not a browse query: the deep-link
// contract answers 400 (pinned). The empty root gained
// meaning only as a STORED collection seed — where the
// composers define it as matching nothing. As a query it
// would silently mean "everything", so reject at the wire.
params.FilterParseErr = "qf tree has no rules"
} else {
params.FilterTree = tree
}