QueryEngine — Filtering, Sorting & Pagination
Granit.QueryEngine provides a declarative search engine: a strongly-typed
QueryDefinition<T> describes columns, filter groups, quick filters, and sort
options. The same definition drives the API query engine and the frontend data
grid — no duplication.
Package structure
Section titled “Package structure”DirectoryGranit.QueryEngine.Abstractions/ Contracts: QueryRequest, PagedResult, ISavedViewStore, SavedView
DirectoryGranit.QueryEngine/ QueryDefinition builder, DI wiring, null-object defaults
- Granit.QueryEngine.EntityFrameworkCore EF Core IQueryEngine implementation
- Granit.QueryEngine.AspNetCore Generic search endpoint, query binding, saved view CRUD
- Granit.QueryEngine.AI NL-to-query translation via LLM
| Package | Role | Depends on |
|---|---|---|
Granit.QueryEngine.Abstractions | QueryRequest, PagedResult<T>, ISavedViewStoreReader/Writer, SavedView | Granit |
Granit.QueryEngine | QueryDefinition<T>, IQueryEngine<T>, DI wiring, null-object defaults | Granit.QueryEngine.Abstractions |
Granit.QueryEngine.EntityFrameworkCore | EF Core query executor, EfCoreSavedViewStore | Granit.QueryEngine, Granit.Persistence |
Granit.QueryEngine.AspNetCore | MapGranitQuery<T>() generic search endpoint | Granit.QueryEngine |
Granit.QueryEngine.AI | NL-to-query translation via LLM | Granit.QueryEngine.Abstractions, Granit.AI |
Security hardening
Section titled “Security hardening”The query engine applies defense-in-depth across multiple layers:
Authentication by default
Section titled “Authentication by default”All endpoints registered via MapGranitQuery<T>() require authentication by
default. To apply a named policy use AuthorizationPolicy; to opt out
explicitly use AllowAnonymous:
endpoints.MapGranitQuery<Invoice>("/api/invoices", sp => ..., options =>{ options.AuthorizationPolicy = "Invoices.Read"; // named policy});
// Rare: anonymous access (public catalog)endpoints.MapGranitQuery<Product>("/api/products", sp => ..., options =>{ options.AllowAnonymous = true;});SavedView ownership enforcement
Section titled “SavedView ownership enforcement”Update, delete, and set-default operations verify that the authenticated user
owns the target view (or that the view is shared, for set-default). The
response DTO exposes IsOwner (boolean) instead of the raw UserId to
prevent user enumeration.
LIKE wildcard escaping
Section titled “LIKE wildcard escaping”Search terms and string filter values (Contains, StartsWith, EndsWith)
have SQL LIKE metacharacters (%, _, [) escaped before reaching EF Core,
preventing wildcard injection probing (CWE-943).
Cursor integrity (HMAC signing)
Section titled “Cursor integrity (HMAC signing)”Keyset pagination cursors can be signed with HMAC-SHA256 to prevent forgery.
Configure a 256-bit key in QueryEngineOptions.CursorHmacKey (base64):
{ "QueryEngine": { "CursorHmacKey": "BASE64_ENCODED_32_BYTE_KEY" }}When configured, tampered cursors are rejected with a silent fallback.
Resource exhaustion protection
Section titled “Resource exhaustion protection”| Control | Default | Option |
|---|---|---|
| Max page size | 100 | MaxPageSize |
| Max stream size | 100 000 | MaxStreamSize |
| Max group-by cardinality | 1 000 | MaxGroupCount |
| Max saved views per user | 100 | MaxSavedViewsPerUser |
| Max filter entries | 50 | Validator constant |
| Max filter key length | 200 chars | Validator constant |
| Max filter value length | 2 000 chars | Validator constant |
| Max JSON field length (saved views) | 10 000 chars | Validator + EF config |
Operator-type validation
Section titled “Operator-type validation”Filter operators are validated at runtime against the column’s CLR type. For
example, Contains is only accepted on string columns; Between is only
accepted on numeric and date types. Invalid operator/type combinations are
silently ignored.
PII-safe logging
Section titled “PII-safe logging”Filter values, cursor payloads, and natural language inputs are never written to log messages. Only field names, target types, and input lengths are logged.
See also
Section titled “See also”- Persistence module — EF Core interceptors, query filters
- API & Http overview — HTTP infrastructure