@memberjunction/search-engine 5.49.0 → 5.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generic/EntitySearchProvider.d.ts +17 -3
- package/dist/generic/EntitySearchProvider.d.ts.map +1 -1
- package/dist/generic/EntitySearchProvider.js +23 -6
- package/dist/generic/EntitySearchProvider.js.map +1 -1
- package/dist/generic/ExternalHitMapper.d.ts +48 -0
- package/dist/generic/ExternalHitMapper.d.ts.map +1 -0
- package/dist/generic/ExternalHitMapper.js +88 -0
- package/dist/generic/ExternalHitMapper.js.map +1 -0
- package/dist/generic/FullTextSearchProvider.d.ts +9 -1
- package/dist/generic/FullTextSearchProvider.d.ts.map +1 -1
- package/dist/generic/FullTextSearchProvider.js +11 -3
- package/dist/generic/FullTextSearchProvider.js.map +1 -1
- package/dist/generic/ScopeDimensionResolver.d.ts +146 -0
- package/dist/generic/ScopeDimensionResolver.d.ts.map +1 -0
- package/dist/generic/ScopeDimensionResolver.js +464 -0
- package/dist/generic/ScopeDimensionResolver.js.map +1 -0
- package/dist/generic/ScopeExplanation.d.ts +141 -0
- package/dist/generic/ScopeExplanation.d.ts.map +1 -0
- package/dist/generic/ScopeExplanation.js +72 -0
- package/dist/generic/ScopeExplanation.js.map +1 -0
- package/dist/generic/ScopeFilterGuard.d.ts +127 -0
- package/dist/generic/ScopeFilterGuard.d.ts.map +1 -0
- package/dist/generic/ScopeFilterGuard.js +290 -0
- package/dist/generic/ScopeFilterGuard.js.map +1 -0
- package/dist/generic/ScopeTemplateRenderer.d.ts +12 -2
- package/dist/generic/ScopeTemplateRenderer.d.ts.map +1 -1
- package/dist/generic/ScopeTemplateRenderer.js +25 -5
- package/dist/generic/ScopeTemplateRenderer.js.map +1 -1
- package/dist/generic/ScopeValueEscaper.d.ts +112 -0
- package/dist/generic/ScopeValueEscaper.d.ts.map +1 -0
- package/dist/generic/ScopeValueEscaper.js +152 -0
- package/dist/generic/ScopeValueEscaper.js.map +1 -0
- package/dist/generic/SearchEngine.d.ts +188 -8
- package/dist/generic/SearchEngine.d.ts.map +1 -1
- package/dist/generic/SearchEngine.js +600 -35
- package/dist/generic/SearchEngine.js.map +1 -1
- package/dist/generic/VectorSearchProvider.d.ts +2 -1
- package/dist/generic/VectorSearchProvider.d.ts.map +1 -1
- package/dist/generic/VectorSearchProvider.js +23 -26
- package/dist/generic/VectorSearchProvider.js.map +1 -1
- package/dist/generic/search.types.d.ts +160 -0
- package/dist/generic/search.types.d.ts.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/permissions/SearchScopePermissionResolver.d.ts +37 -2
- package/dist/permissions/SearchScopePermissionResolver.d.ts.map +1 -1
- package/dist/permissions/SearchScopePermissionResolver.js +74 -2
- package/dist/permissions/SearchScopePermissionResolver.js.map +1 -1
- package/dist/providers/AzureAISearchProvider.d.ts.map +1 -1
- package/dist/providers/AzureAISearchProvider.js +24 -6
- package/dist/providers/AzureAISearchProvider.js.map +1 -1
- package/dist/providers/ElasticsearchSearchProvider.d.ts.map +1 -1
- package/dist/providers/ElasticsearchSearchProvider.js +17 -5
- package/dist/providers/ElasticsearchSearchProvider.js.map +1 -1
- package/dist/providers/OpenSearchSearchProvider.d.ts.map +1 -1
- package/dist/providers/OpenSearchSearchProvider.js +16 -5
- package/dist/providers/OpenSearchSearchProvider.js.map +1 -1
- package/dist/providers/TypesenseSearchProvider.d.ts.map +1 -1
- package/dist/providers/TypesenseSearchProvider.js +17 -6
- package/dist/providers/TypesenseSearchProvider.js.map +1 -1
- package/package.json +8 -8
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Per-lane value escapers — §5.4, "the security core".
|
|
3
|
+
*
|
|
4
|
+
* A scope filter is a string template. Every dimension value that reaches it is interpolated into
|
|
5
|
+
* a syntax with its own quoting rules, and until now nothing escaped anything: an author was
|
|
6
|
+
* expected to remember. That is the wrong default in both directions — it puts the obligation on
|
|
7
|
+
* the person least likely to be thinking about injection, and it fails silently when forgotten.
|
|
8
|
+
*
|
|
9
|
+
* So escaping here is **automatic and keyed off the lane**, with an explicit, greppable opt-out.
|
|
10
|
+
* The renderer escapes every interpolated context value for the lane it is rendering into; an
|
|
11
|
+
* author who genuinely needs a raw value writes `contextRaw.…` instead of `context.…`, which shows
|
|
12
|
+
* up in a grep and in review.
|
|
13
|
+
*
|
|
14
|
+
* WHY DEFAULT-ON IS SAFE TO ADD TO AN EXISTING SYSTEM
|
|
15
|
+
*
|
|
16
|
+
* Because §5.4 also prohibits `freetext` in any filter position, a value that reaches a restricting
|
|
17
|
+
* filter is a uuid, enum, int, iso-date or bool. **None of those grammars can contain a character
|
|
18
|
+
* any of these escapers would change.** So for every legitimate value the escaper is a no-op, and
|
|
19
|
+
* existing templates keep rendering byte-for-byte what they rendered before. The escaper only alters
|
|
20
|
+
* output when a value contains a quote, a backslash or a control character — that is, when something
|
|
21
|
+
* has already gone wrong. That is what makes this deployable without touching a single template.
|
|
22
|
+
*
|
|
23
|
+
* WHY THE EXISTING `json` / `jsoninline` FILTERS CANNOT SERVE
|
|
24
|
+
*
|
|
25
|
+
* They escape `"` and `\` — they do not escape `'`, which is the quote character both the SQL and
|
|
26
|
+
* the OData lanes use. A value passed through `jsoninline` is still perfectly capable of closing a
|
|
27
|
+
* single-quoted SQL literal.
|
|
28
|
+
*
|
|
29
|
+
* @module @memberjunction/search-engine
|
|
30
|
+
*/
|
|
31
|
+
/**
|
|
32
|
+
* The filter dialect a lane consumes, which determines how a value must be escaped.
|
|
33
|
+
*
|
|
34
|
+
* `none` is for positions that are NOT filters — `UserSearchString`, query transforms — where the
|
|
35
|
+
* value becomes search text rather than syntax, and escaping would corrupt the query rather than
|
|
36
|
+
* protect it.
|
|
37
|
+
*/
|
|
38
|
+
export type ScopeLaneKind = 'sql' | 'odata' | 'json' | 'filter_by' | 'esdsl' | 'path' | 'none';
|
|
39
|
+
/**
|
|
40
|
+
* Escape a value for a single-quoted **T-SQL** literal.
|
|
41
|
+
*
|
|
42
|
+
* Doubling `'` is the whole of it — SQL Server has no backslash escape, so a backslash is data.
|
|
43
|
+
* Control characters are stripped rather than encoded: they cannot appear in any permitted value
|
|
44
|
+
* grammar, and leaving them in a predicate invites parser-level surprises.
|
|
45
|
+
*/
|
|
46
|
+
export declare function EscapeSqlLiteral(value: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* Escape a value for a single-quoted **OData** string literal (Azure AI Search `$filter`).
|
|
49
|
+
*
|
|
50
|
+
* OData v4 also escapes `'` by doubling. Azure additionally treats a backslash as an escape inside
|
|
51
|
+
* some function arguments, so it is doubled too — harmless for values that contain none, which is
|
|
52
|
+
* every legitimate value.
|
|
53
|
+
*/
|
|
54
|
+
export declare function EscapeODataLiteral(value: string): string;
|
|
55
|
+
/**
|
|
56
|
+
* Escape a value for placement inside a double-quoted **JSON** string.
|
|
57
|
+
*
|
|
58
|
+
* Deliberately escapes only what JSON requires, without adding the surrounding quotes: templates
|
|
59
|
+
* write `"{{ context.X }}"` and supply their own. Returning a quoted string here would produce
|
|
60
|
+
* `""value""` in every existing template.
|
|
61
|
+
*/
|
|
62
|
+
export declare function EscapeJsonValue(value: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Escape a value for a **Typesense `filter_by`** clause.
|
|
65
|
+
*
|
|
66
|
+
* Neutralises the value delimiter (backtick — Typesense has no documented escape for it, so it is
|
|
67
|
+
* removed) and the boolean operator sequences `&&` / `||`. Everything else is left alone.
|
|
68
|
+
*
|
|
69
|
+
* An earlier version also stripped the character class `[&|:[]()]`, which **corrupted legitimate
|
|
70
|
+
* values**: an `iso-date` dimension carrying a time (`2026-07-28T10:30:00Z`) came back as
|
|
71
|
+
* `2026-07-28T103000Z`, so the filter silently matched nothing. Found by probing the "no-op on
|
|
72
|
+
* legitimate values" claim rather than by review. The contract here mirrors the SQL escaper's:
|
|
73
|
+
* neutralise the delimiter and assume the template quoted the value, exactly as a SQL template must
|
|
74
|
+
* supply its own single quotes.
|
|
75
|
+
*/
|
|
76
|
+
export declare function EscapeFilterByLiteral(value: string): string;
|
|
77
|
+
/**
|
|
78
|
+
* Escape a value for a **storage path segment** (`FolderPath`).
|
|
79
|
+
*
|
|
80
|
+
* Path traversal is the risk, not quoting: `..` and both separators are removed so a dimension can
|
|
81
|
+
* never climb out of the folder its scope confined it to. This is the one escaper that is NOT a
|
|
82
|
+
* no-op on an otherwise-valid value — a legitimate value simply must not contain a separator.
|
|
83
|
+
*/
|
|
84
|
+
export declare function EscapePathSegment(value: string): string;
|
|
85
|
+
/**
|
|
86
|
+
* Escape one value for a lane. Non-strings are returned untouched — numbers and booleans have no
|
|
87
|
+
* syntax to break, and re-typing them to strings here would change how templates render them.
|
|
88
|
+
*/
|
|
89
|
+
export declare function EscapeScopeValue(value: unknown, kind: ScopeLaneKind): unknown;
|
|
90
|
+
/**
|
|
91
|
+
* Recursively escape every string inside a context value for a lane.
|
|
92
|
+
*
|
|
93
|
+
* Arrays are mapped element-wise, which is what makes `{{ ids | join("','") }}` safe: each member
|
|
94
|
+
* is escaped before the join, so a member cannot terminate the literal and inject a clause.
|
|
95
|
+
*/
|
|
96
|
+
export declare function EscapeScopeValueDeep(value: unknown, kind: ScopeLaneKind): unknown;
|
|
97
|
+
/**
|
|
98
|
+
* Map a lane's existing `IndexType` to the dialect its filter is written in.
|
|
99
|
+
*
|
|
100
|
+
* §5.5 proposed a new `MetadataFilterKind` column for this. It turned out to be unnecessary:
|
|
101
|
+
* `IndexType` already carries the information — every provider dispatches on it to decide whether a
|
|
102
|
+
* lane is even theirs — so a second column would be a redundant field to keep in sync, wrong on
|
|
103
|
+
* every pre-existing row until backfilled, and a new thing for authors to get wrong. Deriving is
|
|
104
|
+
* strictly better. If a deployment ever needs to override the derivation, THEN add the column as an
|
|
105
|
+
* override rather than as the source of truth.
|
|
106
|
+
*
|
|
107
|
+
* `Other` maps to `json` rather than to `none`: an unknown external index is the case we know least
|
|
108
|
+
* about, so it gets escaping rather than a pass. Choosing `none` there would mean the least-understood
|
|
109
|
+
* lane is the only unprotected one.
|
|
110
|
+
*/
|
|
111
|
+
export declare function LaneKindForIndexType(indexType: string | null | undefined): ScopeLaneKind;
|
|
112
|
+
//# sourceMappingURL=ScopeValueEscaper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScopeValueEscaper.d.ts","sourceRoot":"","sources":["../../src/generic/ScopeValueEscaper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAE/F;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD;AAeD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAG7E;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAQjF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,aAAa,CASxF"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Per-lane value escapers — §5.4, "the security core".
|
|
3
|
+
*
|
|
4
|
+
* A scope filter is a string template. Every dimension value that reaches it is interpolated into
|
|
5
|
+
* a syntax with its own quoting rules, and until now nothing escaped anything: an author was
|
|
6
|
+
* expected to remember. That is the wrong default in both directions — it puts the obligation on
|
|
7
|
+
* the person least likely to be thinking about injection, and it fails silently when forgotten.
|
|
8
|
+
*
|
|
9
|
+
* So escaping here is **automatic and keyed off the lane**, with an explicit, greppable opt-out.
|
|
10
|
+
* The renderer escapes every interpolated context value for the lane it is rendering into; an
|
|
11
|
+
* author who genuinely needs a raw value writes `contextRaw.…` instead of `context.…`, which shows
|
|
12
|
+
* up in a grep and in review.
|
|
13
|
+
*
|
|
14
|
+
* WHY DEFAULT-ON IS SAFE TO ADD TO AN EXISTING SYSTEM
|
|
15
|
+
*
|
|
16
|
+
* Because §5.4 also prohibits `freetext` in any filter position, a value that reaches a restricting
|
|
17
|
+
* filter is a uuid, enum, int, iso-date or bool. **None of those grammars can contain a character
|
|
18
|
+
* any of these escapers would change.** So for every legitimate value the escaper is a no-op, and
|
|
19
|
+
* existing templates keep rendering byte-for-byte what they rendered before. The escaper only alters
|
|
20
|
+
* output when a value contains a quote, a backslash or a control character — that is, when something
|
|
21
|
+
* has already gone wrong. That is what makes this deployable without touching a single template.
|
|
22
|
+
*
|
|
23
|
+
* WHY THE EXISTING `json` / `jsoninline` FILTERS CANNOT SERVE
|
|
24
|
+
*
|
|
25
|
+
* They escape `"` and `\` — they do not escape `'`, which is the quote character both the SQL and
|
|
26
|
+
* the OData lanes use. A value passed through `jsoninline` is still perfectly capable of closing a
|
|
27
|
+
* single-quoted SQL literal.
|
|
28
|
+
*
|
|
29
|
+
* @module @memberjunction/search-engine
|
|
30
|
+
*/
|
|
31
|
+
/**
|
|
32
|
+
* Escape a value for a single-quoted **T-SQL** literal.
|
|
33
|
+
*
|
|
34
|
+
* Doubling `'` is the whole of it — SQL Server has no backslash escape, so a backslash is data.
|
|
35
|
+
* Control characters are stripped rather than encoded: they cannot appear in any permitted value
|
|
36
|
+
* grammar, and leaving them in a predicate invites parser-level surprises.
|
|
37
|
+
*/
|
|
38
|
+
export function EscapeSqlLiteral(value) {
|
|
39
|
+
return value.replace(/'/g, "''").replace(/[\0\b\n\r\t\x1a]/g, '');
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Escape a value for a single-quoted **OData** string literal (Azure AI Search `$filter`).
|
|
43
|
+
*
|
|
44
|
+
* OData v4 also escapes `'` by doubling. Azure additionally treats a backslash as an escape inside
|
|
45
|
+
* some function arguments, so it is doubled too — harmless for values that contain none, which is
|
|
46
|
+
* every legitimate value.
|
|
47
|
+
*/
|
|
48
|
+
export function EscapeODataLiteral(value) {
|
|
49
|
+
return value.replace(/\\/g, '\\\\').replace(/'/g, "''").replace(/[\0\b\n\r\t\x1a]/g, '');
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Escape a value for placement inside a double-quoted **JSON** string.
|
|
53
|
+
*
|
|
54
|
+
* Deliberately escapes only what JSON requires, without adding the surrounding quotes: templates
|
|
55
|
+
* write `"{{ context.X }}"` and supply their own. Returning a quoted string here would produce
|
|
56
|
+
* `""value""` in every existing template.
|
|
57
|
+
*/
|
|
58
|
+
export function EscapeJsonValue(value) {
|
|
59
|
+
// JSON.stringify handles quotes, backslashes, control chars and unicode correctly; strip the
|
|
60
|
+
// quotes it adds so the result drops into an author-supplied pair.
|
|
61
|
+
const quoted = JSON.stringify(value);
|
|
62
|
+
return quoted.slice(1, -1);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Escape a value for a **Typesense `filter_by`** clause.
|
|
66
|
+
*
|
|
67
|
+
* Neutralises the value delimiter (backtick — Typesense has no documented escape for it, so it is
|
|
68
|
+
* removed) and the boolean operator sequences `&&` / `||`. Everything else is left alone.
|
|
69
|
+
*
|
|
70
|
+
* An earlier version also stripped the character class `[&|:[]()]`, which **corrupted legitimate
|
|
71
|
+
* values**: an `iso-date` dimension carrying a time (`2026-07-28T10:30:00Z`) came back as
|
|
72
|
+
* `2026-07-28T103000Z`, so the filter silently matched nothing. Found by probing the "no-op on
|
|
73
|
+
* legitimate values" claim rather than by review. The contract here mirrors the SQL escaper's:
|
|
74
|
+
* neutralise the delimiter and assume the template quoted the value, exactly as a SQL template must
|
|
75
|
+
* supply its own single quotes.
|
|
76
|
+
*/
|
|
77
|
+
export function EscapeFilterByLiteral(value) {
|
|
78
|
+
return value.replace(/`/g, '').replace(/&&/g, '').replace(/\|\|/g, '').replace(/[\0\b\n\r\t\x1a]/g, '');
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Escape a value for a **storage path segment** (`FolderPath`).
|
|
82
|
+
*
|
|
83
|
+
* Path traversal is the risk, not quoting: `..` and both separators are removed so a dimension can
|
|
84
|
+
* never climb out of the folder its scope confined it to. This is the one escaper that is NOT a
|
|
85
|
+
* no-op on an otherwise-valid value — a legitimate value simply must not contain a separator.
|
|
86
|
+
*/
|
|
87
|
+
export function EscapePathSegment(value) {
|
|
88
|
+
return value.replace(/\.\./g, '').replace(/[/\\]/g, '').replace(/[\0\b\n\r\t\x1a]/g, '');
|
|
89
|
+
}
|
|
90
|
+
/** Escaper for each lane kind. `none`/`esdsl` pass through — see below. */
|
|
91
|
+
const ESCAPERS = {
|
|
92
|
+
sql: EscapeSqlLiteral,
|
|
93
|
+
odata: EscapeODataLiteral,
|
|
94
|
+
json: EscapeJsonValue,
|
|
95
|
+
filter_by: EscapeFilterByLiteral,
|
|
96
|
+
path: EscapePathSegment,
|
|
97
|
+
// Elasticsearch/OpenSearch DSL is JSON, so JSON escaping is the correct rule for it.
|
|
98
|
+
esdsl: EscapeJsonValue,
|
|
99
|
+
// Not a filter position: the value becomes query text, and escaping would corrupt the search.
|
|
100
|
+
none: (v) => v,
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Escape one value for a lane. Non-strings are returned untouched — numbers and booleans have no
|
|
104
|
+
* syntax to break, and re-typing them to strings here would change how templates render them.
|
|
105
|
+
*/
|
|
106
|
+
export function EscapeScopeValue(value, kind) {
|
|
107
|
+
if (typeof value !== 'string')
|
|
108
|
+
return value;
|
|
109
|
+
return ESCAPERS[kind](value);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Recursively escape every string inside a context value for a lane.
|
|
113
|
+
*
|
|
114
|
+
* Arrays are mapped element-wise, which is what makes `{{ ids | join("','") }}` safe: each member
|
|
115
|
+
* is escaped before the join, so a member cannot terminate the literal and inject a clause.
|
|
116
|
+
*/
|
|
117
|
+
export function EscapeScopeValueDeep(value, kind) {
|
|
118
|
+
if (Array.isArray(value))
|
|
119
|
+
return value.map((v) => EscapeScopeValueDeep(v, kind));
|
|
120
|
+
if (value !== null && typeof value === 'object') {
|
|
121
|
+
const out = {};
|
|
122
|
+
for (const [k, v] of Object.entries(value))
|
|
123
|
+
out[k] = EscapeScopeValueDeep(v, kind);
|
|
124
|
+
return out;
|
|
125
|
+
}
|
|
126
|
+
return EscapeScopeValue(value, kind);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Map a lane's existing `IndexType` to the dialect its filter is written in.
|
|
130
|
+
*
|
|
131
|
+
* §5.5 proposed a new `MetadataFilterKind` column for this. It turned out to be unnecessary:
|
|
132
|
+
* `IndexType` already carries the information — every provider dispatches on it to decide whether a
|
|
133
|
+
* lane is even theirs — so a second column would be a redundant field to keep in sync, wrong on
|
|
134
|
+
* every pre-existing row until backfilled, and a new thing for authors to get wrong. Deriving is
|
|
135
|
+
* strictly better. If a deployment ever needs to override the derivation, THEN add the column as an
|
|
136
|
+
* override rather than as the source of truth.
|
|
137
|
+
*
|
|
138
|
+
* `Other` maps to `json` rather than to `none`: an unknown external index is the case we know least
|
|
139
|
+
* about, so it gets escaping rather than a pass. Choosing `none` there would mean the least-understood
|
|
140
|
+
* lane is the only unprotected one.
|
|
141
|
+
*/
|
|
142
|
+
export function LaneKindForIndexType(indexType) {
|
|
143
|
+
switch (indexType) {
|
|
144
|
+
case 'AzureAISearch': return 'odata';
|
|
145
|
+
case 'Typesense': return 'filter_by';
|
|
146
|
+
case 'Elasticsearch':
|
|
147
|
+
case 'OpenSearch': return 'esdsl';
|
|
148
|
+
case 'Vector': return 'json';
|
|
149
|
+
default: return 'json';
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=ScopeValueEscaper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ScopeValueEscaper.js","sourceRoot":"","sources":["../../src/generic/ScopeValueEscaper.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,7 +22,21 @@
|
|
|
22
22
|
import { IMetadataProvider, UserInfo } from '@memberjunction/core';
|
|
23
23
|
import { SearchEngineBase } from '@memberjunction/core-entities';
|
|
24
24
|
import { BaseSingleton } from '@memberjunction/global';
|
|
25
|
-
import { SearchParams, SearchResult, SearchResultItem, SearchStreamEvent } from './search.types.js';
|
|
25
|
+
import { SearchParams, SearchResult, SearchResultItem, SearchStreamEvent, ScopePrincipals } from './search.types.js';
|
|
26
|
+
import { ScopeDimensionResolver } from './ScopeDimensionResolver.js';
|
|
27
|
+
import { ScopeExplanation, ExplainScopeInput } from './ScopeExplanation.js';
|
|
28
|
+
/**
|
|
29
|
+
* Collects lane problems keyed by the lane's **row ID** instead of throwing.
|
|
30
|
+
*
|
|
31
|
+
* Present ⇒ the caller is EXPLAINING a hypothetical search and wants every broken lane in one
|
|
32
|
+
* pass. Absent ⇒ the caller is RUNNING a real search and the first unusable restriction must
|
|
33
|
+
* abort it, because the alternative is querying that lane unfiltered.
|
|
34
|
+
*
|
|
35
|
+
* Keyed by row ID rather than by display name: two `SearchScopeEntity` rows over the SAME
|
|
36
|
+
* entity is a legitimate configuration (two different `ExtraFilter`s), and keying by the entity
|
|
37
|
+
* name made them collide — one broken lane then reported its sibling as skipped too.
|
|
38
|
+
*/
|
|
39
|
+
type LaneProblemCollector = Map<string, string>;
|
|
26
40
|
/**
|
|
27
41
|
* Configuration options for the SearchEngine.
|
|
28
42
|
*/
|
|
@@ -93,10 +107,12 @@ export declare class SearchEngine extends BaseSingleton<SearchEngine> {
|
|
|
93
107
|
private _defaultMaxResults;
|
|
94
108
|
private _defaultOverfetchFactor;
|
|
95
109
|
/**
|
|
96
|
-
* Minimum trimmed query length we accept.
|
|
97
|
-
*
|
|
110
|
+
* Minimum trimmed query length we accept. A single-character query against a
|
|
111
|
+
* `LIKE '%term%'` fan-out is essentially a full-database scan with negligible
|
|
98
112
|
* relevance — the providers also enforce this, but we short-circuit here to
|
|
99
|
-
* avoid the cache lookup and provider dispatch overhead too.
|
|
113
|
+
* avoid the cache lookup and provider dispatch overhead too. Set to 2 (was 3) so
|
|
114
|
+
* legitimate short queries aren't silently dropped (bug C3); must stay in lockstep
|
|
115
|
+
* with the providers' MIN_TERM_LENGTH.
|
|
100
116
|
*/
|
|
101
117
|
private static readonly MIN_TERM_LENGTH;
|
|
102
118
|
/**
|
|
@@ -108,6 +124,12 @@ export declare class SearchEngine extends BaseSingleton<SearchEngine> {
|
|
|
108
124
|
/** Maximum cached entries across all users. LRU-evicted on overflow. */
|
|
109
125
|
private static readonly CACHE_MAX_ENTRIES;
|
|
110
126
|
private _cache;
|
|
127
|
+
private _dimensionResolver;
|
|
128
|
+
/**
|
|
129
|
+
* Resolver for a scope's declared Search Context dimensions. Overridable so a host can
|
|
130
|
+
* supply additional derivation sources (e.g. an external signal) without forking the engine.
|
|
131
|
+
*/
|
|
132
|
+
protected get dimensionResolver(): ScopeDimensionResolver;
|
|
111
133
|
/** Access the cached provider metadata from SearchEngineBase */
|
|
112
134
|
protected get Base(): SearchEngineBase;
|
|
113
135
|
/** Resolve the metadata provider via SearchEngineBase (which extends BaseEngine and tracks ProviderToUse). */
|
|
@@ -180,11 +202,50 @@ export declare class SearchEngine extends BaseSingleton<SearchEngine> {
|
|
|
180
202
|
*/
|
|
181
203
|
streamSearch(params: SearchParams, contextUser: UserInfo): AsyncIterable<SearchStreamEvent>;
|
|
182
204
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
205
|
+
* Deterministically serialize a value with object keys sorted, so that two
|
|
206
|
+
* logically-identical inputs always produce the same string.
|
|
207
|
+
*
|
|
208
|
+
* `JSON.stringify` preserves *insertion* order, which means a caller that builds
|
|
209
|
+
* `SecondaryScopes` by spreading (a common pattern) can emit the same dimensions in
|
|
210
|
+
* different orders across calls. Left unsorted that causes avoidable cache misses;
|
|
211
|
+
* sorted, identity is stable. Array order is PRESERVED — see buildCacheKey for why
|
|
212
|
+
* `ScopeIDs` order is significant.
|
|
213
|
+
*/
|
|
214
|
+
protected stableStringify(value: unknown): string;
|
|
215
|
+
/**
|
|
216
|
+
* Build a stable cache key for a search.
|
|
217
|
+
*
|
|
218
|
+
* The key must include EVERY input that can change the result set, or the cache
|
|
219
|
+
* will serve one caller's results to another. Two of those inputs were previously
|
|
220
|
+
* missing and both are tenancy/authorization-relevant:
|
|
221
|
+
*
|
|
222
|
+
* - `SearchContext` — carries `PrimaryScopeRecordID` (the TENANT) and the
|
|
223
|
+
* `SecondaryScopes` dimensions. Omitting it meant a user with access to two
|
|
224
|
+
* tenants could be served the other tenant's results for up to the cache TTL,
|
|
225
|
+
* and that two searches differing only by dimension (channel, skill, …)
|
|
226
|
+
* collided. This is the reason for the fix.
|
|
227
|
+
* - `ScopeIDs` — determines which corpora are searched at all.
|
|
228
|
+
*
|
|
229
|
+
* Also folded in: `Mode`, `FusionWeightsOverride` and `PermissionOverfetchFactor`
|
|
230
|
+
* (all change ranking or the candidate pool, so they change results) and
|
|
231
|
+
* `AIAgentID` (conservative: agent identity participates in scope resolution and
|
|
232
|
+
* per-agent overrides upstream; including it can only cost a miss, never leak).
|
|
233
|
+
*
|
|
234
|
+
* `ScopeIDs` order is deliberately NOT sorted: it is behaviourally significant,
|
|
235
|
+
* because cross-scope reranker config and budget are taken from the first scope in
|
|
236
|
+
* the array that supplies one. Two different orderings can therefore produce
|
|
237
|
+
* different results and must not share a key.
|
|
238
|
+
*
|
|
239
|
+
* The whole projection is emitted through `stableStringify` so key-order variation
|
|
240
|
+
* in `SecondaryScopes` doesn't fragment the cache. The user ID stays as a readable
|
|
241
|
+
* prefix for debuggability.
|
|
242
|
+
*
|
|
243
|
+
* Note this runs AFTER scope resolution in `searchInternal`, so nothing here is
|
|
244
|
+
* circular. Entitlement is resolved by the CALLERS (`__Scoped_Search`, the
|
|
245
|
+
* GraphQL resolvers), which deny before reaching the engine; the engine therefore
|
|
246
|
+
* never caches across an allow/deny boundary.
|
|
186
247
|
*/
|
|
187
|
-
|
|
248
|
+
protected buildCacheKey(trimmed: string, params: SearchParams, contextUser: UserInfo): string;
|
|
188
249
|
/** Insert into the LRU cache, evicting oldest entries when over capacity. */
|
|
189
250
|
private cachePut;
|
|
190
251
|
/** Test / admin hook: clear the result cache. */
|
|
@@ -200,6 +261,92 @@ export declare class SearchEngine extends BaseSingleton<SearchEngine> {
|
|
|
200
261
|
* @returns Search result in preview mode
|
|
201
262
|
*/
|
|
202
263
|
PreviewSearch(query: string, maxResults: number, contextUser: UserInfo): Promise<SearchResult>;
|
|
264
|
+
/**
|
|
265
|
+
* Resolve the entire access chain for one or more scopes and report what a search WOULD be
|
|
266
|
+
* able to reach — **without querying any provider**.
|
|
267
|
+
*
|
|
268
|
+
* This is the answer to a question the platform previously could not answer at all: *"as
|
|
269
|
+
* this user, with this skill active, for this tenant — what is in bounds?"* Every input to
|
|
270
|
+
* that decision is transient. A grant applies because a time window is open right now; a
|
|
271
|
+
* dimension is discarded because it was caller-authored on a `ServerDerived` key; a lane is
|
|
272
|
+
* skipped because its filter lost an `{% if %}` clause. Afterwards, none of it is visible:
|
|
273
|
+
* a correctly-bounded result set and an accidentally-widened one look identical.
|
|
274
|
+
*
|
|
275
|
+
* Note the distinction from {@link PreviewSearch}, which is a real search capped at a few
|
|
276
|
+
* results. This runs **no** search — it reports the bound, not a sample of what is inside
|
|
277
|
+
* it. A sample cannot show you an over-broad bound, because the extra documents it would
|
|
278
|
+
* newly permit are exactly the ones you did not think to look for.
|
|
279
|
+
*
|
|
280
|
+
* Two properties make the output trustworthy:
|
|
281
|
+
*
|
|
282
|
+
* - It takes the **same untrusted `SearchContext` a real caller would send**, so the
|
|
283
|
+
* preview shows the anti-spoof discard actually happening. A dry run that only accepted
|
|
284
|
+
* pre-sanitized input would hide the one thing worth previewing.
|
|
285
|
+
* - It reports **every** broken lane in one pass rather than throwing on the first, so a
|
|
286
|
+
* misconfigured scope can be fixed in one sitting instead of one error per re-run.
|
|
287
|
+
*
|
|
288
|
+
* Unlike a real search this never throws for a scope-level problem; a scope that would fail
|
|
289
|
+
* closed comes back with `Reachable: false` and the reason, since "it would have failed"
|
|
290
|
+
* is precisely the finding the caller asked for.
|
|
291
|
+
*
|
|
292
|
+
* @param input scopes to explain plus the hypothetical caller context and principals
|
|
293
|
+
* @param contextUser the user to evaluate entitlement for
|
|
294
|
+
* @returns one explanation per requested scope, in the order requested
|
|
295
|
+
*/
|
|
296
|
+
ExplainScope(input: ExplainScopeInput, contextUser: UserInfo): Promise<ScopeExplanation[]>;
|
|
297
|
+
/**
|
|
298
|
+
* Build the principal set a dimension's expansion query may bind.
|
|
299
|
+
*
|
|
300
|
+
* Exists so the real search path and the `ExplainScope` dry run cannot construct principals
|
|
301
|
+
* differently. They already did once: `ExplainScope` passed the agent and the search path
|
|
302
|
+
* passed nothing, so any scope deriving its bound from `AgentID` previewed one bound and
|
|
303
|
+
* searched with another. A single conversion site makes that class of drift unrepresentable
|
|
304
|
+
* rather than merely fixed.
|
|
305
|
+
*
|
|
306
|
+
* Accepts anything carrying the two principal IDs, which both `SearchParams` and
|
|
307
|
+
* `ExplainScopeInput` do.
|
|
308
|
+
*/
|
|
309
|
+
protected principalsFrom(source: {
|
|
310
|
+
AIAgentID?: string | null;
|
|
311
|
+
AISkillID?: string | null;
|
|
312
|
+
}): ScopePrincipals;
|
|
313
|
+
/** Explain a single scope. Never throws — a failure to resolve IS the explanation. */
|
|
314
|
+
private explainOneScope;
|
|
315
|
+
/** Resolve entitlement for the dry run, including the skill and tenant principals. */
|
|
316
|
+
private explainEntitlement;
|
|
317
|
+
/** Load an agent or skill principal by ID; null when no ID was supplied. */
|
|
318
|
+
private loadPrincipal;
|
|
319
|
+
/**
|
|
320
|
+
* Render every lane and report which would run.
|
|
321
|
+
*
|
|
322
|
+
* Reuses `buildScopeConstraints` with a collector rather than duplicating the render logic.
|
|
323
|
+
* That matters more than it looks: a separate "explain" renderer would be a second
|
|
324
|
+
* implementation of the guard rules, free to drift from the enforcing one, and a preview
|
|
325
|
+
* that disagrees with what actually runs is worse than having no preview.
|
|
326
|
+
*/
|
|
327
|
+
/**
|
|
328
|
+
* Turn already-built constraints plus a problem map into per-lane explanations.
|
|
329
|
+
*
|
|
330
|
+
* Takes the constraints rather than rebuilding them. The previous version called
|
|
331
|
+
* `buildScopeConstraints` itself, which meant the SEARCH path re-rendered every Nunjucks
|
|
332
|
+
* template a second time on every scope of every query purely to produce a log record —
|
|
333
|
+
* pure waste on the hottest path in the engine.
|
|
334
|
+
*
|
|
335
|
+
* Both callers still share one rendering pass, which is what keeps the dry run honest:
|
|
336
|
+
* a separate explain-only renderer would be a second implementation of the guard rules,
|
|
337
|
+
* free to drift from the enforcing one.
|
|
338
|
+
*/
|
|
339
|
+
private buildLaneExplanations;
|
|
340
|
+
/** Render every lane for a DRY RUN, collecting problems instead of throwing on the first. */
|
|
341
|
+
private explainLanes;
|
|
342
|
+
/** Every lane, reported as skipped for one shared reason. */
|
|
343
|
+
private buildAllLanesSkipped;
|
|
344
|
+
/** Explanation for a scope that is inactive, missing, or otherwise not loadable. */
|
|
345
|
+
private buildUnresolvableExplanation;
|
|
346
|
+
/** Parse a lane's required-key contract for display; a malformed one reports as empty. */
|
|
347
|
+
private safeRequiredKeys;
|
|
348
|
+
/** Render a filter of unknown shape as a display string. */
|
|
349
|
+
private stringifyFilter;
|
|
203
350
|
/**
|
|
204
351
|
* Load `ScopeBundle`s for each requested scope ID, filtering out inactive / expired.
|
|
205
352
|
* Returns an empty array when no scope IDs are supplied (caller treats as Global).
|
|
@@ -213,6 +360,36 @@ export declare class SearchEngine extends BaseSingleton<SearchEngine> {
|
|
|
213
360
|
* Assemble a `ScopeConstraints` for a single scope: Nunjucks-render each template
|
|
214
361
|
* field against the `SearchContext`, then hand the rendered values to providers.
|
|
215
362
|
*/
|
|
363
|
+
/**
|
|
364
|
+
* Fail a search CLOSED when a scope field that RESTRICTS was authored but did not render
|
|
365
|
+
* usably (see `CheckRenderedTemplate`).
|
|
366
|
+
*
|
|
367
|
+
* Throwing rather than dropping the offending row is deliberate. Dropping it would empty
|
|
368
|
+
* the row collection, and `buildScopeConstraints` collapses an empty collection to
|
|
369
|
+
* `undefined` — which every provider reads as "unscoped", i.e. all entities / all indexes
|
|
370
|
+
* with no filter. So the surgical-looking fix is the one that widens; failing the search
|
|
371
|
+
* is the one that doesn't. A broken restricting template is a misconfiguration and should
|
|
372
|
+
* be loud and actionable, never silently degraded into a wider search.
|
|
373
|
+
*/
|
|
374
|
+
protected assertRestrictingTemplateRendered(source: string | null | undefined, rendered: unknown, fieldName: string, scopeLabel: string, rowLabel: string, laneID: string, collector?: LaneProblemCollector): void;
|
|
375
|
+
/**
|
|
376
|
+
* Enforce a lane's `RequiredMetadataKeys` contract (Phase E).
|
|
377
|
+
*
|
|
378
|
+
* The rendered filter must mention every key the author declared. This is the only guard
|
|
379
|
+
* that catches a filter which rendered *partially* — where an optional `{% if %}` clause
|
|
380
|
+
* disappeared because its dimension was absent or discarded, leaving a non-empty filter
|
|
381
|
+
* that passes every other check while restricting on strictly less than intended.
|
|
382
|
+
*/
|
|
383
|
+
protected assertRequiredMetadataKeys(declaration: string | null | undefined, laneID: string, rendered: unknown, scopeLabel: string, rowLabel: string, collector?: LaneProblemCollector): void;
|
|
384
|
+
/**
|
|
385
|
+
* Route a lane problem to the right place: throw when enforcing a real search, record when
|
|
386
|
+
* explaining a hypothetical one.
|
|
387
|
+
*
|
|
388
|
+
* A dry run must be able to report *every* broken lane in one pass. If it threw on the first
|
|
389
|
+
* one, an administrator would fix a scope one error at a time, re-running after each — and
|
|
390
|
+
* the whole point of the preview is to see the entire picture before anything runs.
|
|
391
|
+
*/
|
|
392
|
+
private reportLaneProblem;
|
|
216
393
|
private buildScopeConstraints;
|
|
217
394
|
/** Resolve the EntityID → EntityName via MJ Metadata (for passing to providers that key by name). */
|
|
218
395
|
private lookupEntityName;
|
|
@@ -289,6 +466,8 @@ export declare class SearchEngine extends BaseSingleton<SearchEngine> {
|
|
|
289
466
|
StartTime: number;
|
|
290
467
|
ContextUser: UserInfo;
|
|
291
468
|
AIAgentID?: string | null;
|
|
469
|
+
AISkillID?: string | null;
|
|
470
|
+
PrimaryScopeRecordID?: string | null;
|
|
292
471
|
}): Promise<void>;
|
|
293
472
|
/**
|
|
294
473
|
* Best-effort hook (P3.2) that writes one MJSearchExecutionLog row per
|
|
@@ -307,4 +486,5 @@ export declare class SearchEngine extends BaseSingleton<SearchEngine> {
|
|
|
307
486
|
/** Defensive JSON parse that never throws. Returns `null` on any failure. */
|
|
308
487
|
private parseJson;
|
|
309
488
|
}
|
|
489
|
+
export {};
|
|
310
490
|
//# sourceMappingURL=SearchEngine.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchEngine.d.ts","sourceRoot":"","sources":["../../src/generic/SearchEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAoC,iBAAiB,EAA0C,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC7I,OAAO,EACH,gBAAgB,
|
|
1
|
+
{"version":3,"file":"SearchEngine.d.ts","sourceRoot":"","sources":["../../src/generic/SearchEngine.ts"],"names":[],"mappings":"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"}
|