[superlog] Skip unsupported filter fields per query type instead of throwing#477
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
|
The latest updates on your projects. Learn more about Unkey Deploy
|
Greptile SummaryThis PR changes
Confidence Score: 3/5The fix is conceptually right but the implementation is broken — every query carrying any filter will throw a TypeError instead of running. The only changed code path — packages/ai/src/query/simple-builder.ts — the new guard block at lines 1055-1064 Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[buildWhereClauseFromFilters called] --> B{filter.target or filter.having?}
B -- yes --> C[continue / skip]
B -- no --> D{isGloballyAllowed?\n⚠️ calls Set.includes — TypeError}
D -- TypeError --> E[💥 Crashes — regression]
D -- allowed --> F{config.allowedFilters includes field?}
F -- no --> C
F -- yes --> G[buildFilter]
G -- allowed --> H[append WHERE clause]
G -- not allowed --> I[throw 'not permitted']
H --> J[return whereClause]
style E fill:#ff4444,color:#fff
style D fill:#ffaaaa
Reviews (1): Last reviewed commit: "[superlog] Skip unsupported filter field..." | Re-trigger Greptile |
| const isGloballyAllowed = GLOBAL_ALLOWED_FILTERS.includes( | ||
| filter.field as (typeof GLOBAL_ALLOWED_FILTERS)[number] | ||
| ); | ||
| if ( | ||
| !( | ||
| isGloballyAllowed || | ||
| this.config.allowedFilters?.includes(filter.field) | ||
| ) | ||
| ) { | ||
| continue; |
There was a problem hiding this comment.
Set.prototype.includes does not exist — TypeError on every request with filters
GLOBAL_ALLOWED_FILTERS is declared as new Set([...]) (line 44). Set has .has(), not .includes(). Calling .includes() on a Set throws TypeError: GLOBAL_ALLOWED_FILTERS.includes is not a function at runtime, which would crash every query that carries filters — a regression worse than the original throw. The pre-existing isFilterFieldAllowed helper (line 61-68) already performs this exact check correctly using .has(). The entire new block should be replaced with a single call to that helper:
if (!isFilterFieldAllowed(this.config, filter.field)) {
continue;
}The type assertion as (typeof GLOBAL_ALLOWED_FILTERS)[number] is also unsound for a Set — Set<string>[number] resolves to undefined — but it is superseded by the runtime crash anyway.
izadoesdev
left a comment
There was a problem hiding this comment.
Parking this one for a functional blocker before staging merge. In packages/ai/src/query/simple-builder.ts the new filtered-query path calls GLOBAL_ALLOWED_FILTERS.includes(...), but GLOBAL_ALLOWED_FILTERS is a Set, not an array. That breaks filtered query compilation with TypeError/TS2339; the existing isFilterFieldAllowed(this.config, filter.field) helper, or GLOBAL_ALLOWED_FILTERS.has(...), is the likely fix. The mixed-batch regression test is directionally useful, but the implementation needs this fix and the red Check Types/Test checks cleared before approval.
izadoesdev
left a comment
There was a problem hiding this comment.
Fixed the remaining helper mismatch in the batch filter path: buildWhereClauseFromFilters now uses isFilterFieldAllowed(...) instead of duplicating allow-list logic and calling .includes on the global Set. Verification: cd packages/ai && bun run check-types, cd packages/ai && bun test src/query/simple-builder.test.ts, bun run lint, bun run check-types, and the pre-push full bun run test hook all pass. Approving for staging merge.
Summary
When a user applies an
hreffilter on the outbound links or outbound domains view, the batch query endpoint sends all 6 dashboard queries — includingcountry,top_pages,browsers, etc. — with that same filter. Standard analytics queries don't declarehrefin theirallowedFilters, sobuildFilterthrows insidebuildWhereClauseFromFilters. This crashes the entire union batch group, logs a noisy ERROR, and leaves those widgets empty.The
outbound_linksandoutbound_domainsbuilders correctly declareallowedFilters: ["client_id", "anonymous_id", "session_id", "href", "text"], so they succeed individually after the fallback. But other query types (likecountry) have noallowedFiltersand rejecthrefwith an error.The fix changes
buildWhereClauseFromFiltersto silently skip filters whose field is not permitted by the current query config, rather than throwing. This is the correct semantic: a dimension-specific filter (href,id) that doesn't apply to a given query type should simply be omitted from that query's WHERE clause. The security behavior is unchanged — unknown/injection field names are still never emitted into SQL, they're just silently skipped.An alternative approach would be to strip unsupported filters in the batch route before calling
executeBatch, but that would require per-query filter pre-processing at the API layer and duplicates theallowedFiltersknowledge that already lives in the builder config.Tests updated: the three existing tests that expected
compile()to throw on unsupported fields now assert the field is absent from the compiled SQL instead.Incident on Superlog
Was this PR helpful? Leave feedback — goes straight to the Superlog team.
Summary by cubic
Skip unsupported filter fields per query type instead of throwing, so batch queries no longer fail when a dimension-specific filter (e.g.
href) is applied. This prevents empty widgets and noisy errors; unrelated queries now compile and run.buildWhereClauseFromFiltersto ignore filters not inallowedFiltersvia the sharedisFilterFieldAllowedhelper; SQL injection safety unchanged.hreffilters (outbound links/domains) no longer break other queries likecountry,top_pages, orbrowsers.hrefin mixed batches.Written for commit 8b0c80e. Summary will update on new commits.