Specifies AND and OR filter composition, missing-value behavior, facet counts, and authorization-before-count rules so filtered navigation remains correct under ACLs and incomplete indexes.
Package status: AI-assisted reference package. Static package validation has passed; implementation scenarios remain not run and human domain review is required before stable adoption.
Decision
Faceted search exposes a filter grammar with explicit composition rules rather than leaving AND/OR behavior implicit. Filters across facets combine with AND by default; values within a facet combine with OR unless a facet declares otherwise. Missing or unindexed field values land in a named bucket and do not silently match unrelated filters. Facet counts are computed only after the same authorization predicate used for results is applied, so inaccessible documents never inflate or deflate counts visible to the user. Counts exclude the facet currently being edited from self-filter distortion where the profile requires conjunctive navigation behavior.
Scope
- Filter operator grammar, cross-facet and within-facet composition, and validation errors.
- Missing, null, and unindexed field behavior in filters and facet buckets.
- Facet count computation order relative to authorization and active filters.
- Multi-tenant denial of cross-tenant aggregation signals.
Outside this block
- Zero-result recovery UX and suggestion panels.
- Hybrid lexical-vector retrieval and ranking weights.
- Index mapping design for every catalog field.
Contract
- Cross-facet filters compose with AND; within-facet multi-select composes with OR unless a facet override declares AND, and the API documents which facets use which rule.
- Documents with unindexed or null facet fields are excluded from positive matches for that facet unless the client explicitly selects the not-set missing-value bucket key.
- Facet counts are calculated after authorization filtering and before returning buckets; inaccessible documents are removed from all denominators and never appear as non-zero buckets for forbidden values.
- The facet being adjusted excludes its own active filter from count calculations when self-filter exclusion is enabled in the profile.
- Zero-count buckets for values the principal cannot access are omitted entirely rather than shown as zero, preventing existence leaks.
- Unknown facets, unsupported operators, or excessive filter depth produce a validation error with no partial result payload.
Implementation guidance
- Represent filters as a normalized abstract syntax tree so UI, API, and index layers share one grammar from
filter-grammar.yaml. - Apply authorization as a mandatory query clause shared by result retrieval and aggregation paths; do not compute global counts and trim in the UI.
- Name the missing-value bucket consistently and localize display labels separately from internal bucket keys.
Failure handling and safeguards
- When aggregation exceeds latency budget, degrade by returning results with stale facet counts only if counts are labeled with as-of metadata; default profile should fail closed on count timeout for admin interfaces.
- Reject filter payloads that attempt to encode raw index expressions not in the grammar to prevent injection-style query escape.
- Log filter validation failures without echoing full malicious payloads into unsecured logs.
Verification and operations
- Measure count latency, authorization mismatch incidents, and invalid-filter rate.
- Test principals with partial catalog access and verify forbidden facet values never appear with non-zero counts.
- Prove cross-facet AND and within-facet OR with tagged override using fixed fixtures.
The executable-looking examples in this package are fixtures and acceptance contracts. Run static validation on the package structure and metadata, then implement and execute the scenarios in the target repository.
Adoption assumptions
- Names and numeric values in
example.yamlare an adoption profile, not universal defaults. - Elasticsearch aggregation documentation informs count semantics but no search engine is mandatory.
- The adopting team maps facet names, operators, and authorization predicates to its index and policy model.