@memberjunction/search-engine 6.1.0-edge.4 → 6.1.0-edge.6
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.map +1 -1
- package/dist/generic/EntitySearchProvider.js +10 -2
- package/dist/generic/EntitySearchProvider.js.map +1 -1
- package/dist/generic/SearchEngine.d.ts +22 -6
- package/dist/generic/SearchEngine.d.ts.map +1 -1
- package/dist/generic/SearchEngine.js +128 -14
- package/dist/generic/SearchEngine.js.map +1 -1
- package/dist/generic/VectorSearchProvider.d.ts +7 -4
- package/dist/generic/VectorSearchProvider.d.ts.map +1 -1
- package/dist/generic/VectorSearchProvider.js +10 -7
- package/dist/generic/VectorSearchProvider.js.map +1 -1
- package/dist/permissions/SearchScopePermissionResolver.d.ts +80 -6
- package/dist/permissions/SearchScopePermissionResolver.d.ts.map +1 -1
- package/dist/permissions/SearchScopePermissionResolver.js +186 -12
- package/dist/permissions/SearchScopePermissionResolver.js.map +1 -1
- package/package.json +8 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntitySearchProvider.d.ts","sourceRoot":"","sources":["../../src/generic/EntitySearchProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"EntitySearchProvider.d.ts","sourceRoot":"","sources":["../../src/generic/EntitySearchProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAiE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAE/G,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAoB,gBAAgB,EAAyB,MAAM,gBAAgB,CAAC;AAG1I;;;;GAIG;AACH,qBACa,oBAAqB,SAAQ,kBAAkB;IACxD,SAAgB,UAAU,EAAE,YAAY,CAAY;IAEpD;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAK;IAE5C;;;;;;;;;;;OAWG;IACH,OAAc,mBAAmB,SAA0D;IAE3F;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAc,kBAAkB,SAA2D;IAE3F;;;;;;;;OAQG;IACU,MAAM,CACf,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,aAAa,GAAG,SAAS,EAClC,WAAW,EAAE,QAAQ,EACrB,gBAAgB,CAAC,EAAE,gBAAgB,GACpC,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAmF9B;;;;;;;OAOG;IACH,OAAO,CAAC,qBAAqB;IAoB7B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAc7B;;;;;;;;;OASG;YACW,eAAe;YAsBf,kBAAkB;IA8BhC;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAgEtB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAmCpB;;OAEG;IACH,OAAO,CAAC,cAAc;IAetB;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,wBAAwB;CAGnC"}
|
|
@@ -14,7 +14,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
14
14
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
15
15
|
};
|
|
16
16
|
var EntitySearchProvider_1;
|
|
17
|
-
import { LogError, LogStatus, RunView } from '@memberjunction/core';
|
|
17
|
+
import { CompositeKey, LogError, LogStatus, RunView } from '@memberjunction/core';
|
|
18
18
|
import { RegisterClass } from '@memberjunction/global';
|
|
19
19
|
import { BaseSearchProvider } from './ISearchProvider.js';
|
|
20
20
|
import { envIntOverride } from './env-config.js';
|
|
@@ -240,7 +240,15 @@ let EntitySearchProvider = class EntitySearchProvider extends BaseSearchProvider
|
|
|
240
240
|
const nameFields = searchFields.filter(f => f.IsNameField);
|
|
241
241
|
const totalSearchableFields = Math.max(searchFields.length, 1);
|
|
242
242
|
return records.map((record) => {
|
|
243
|
-
|
|
243
|
+
// Build the key from the entity's actual primary-key column(s) and emit it in compact
|
|
244
|
+
// CompositeKey form: the bare value for a single-column key (whatever it is called),
|
|
245
|
+
// "F1|v1||F2|v2" for a composite one. Reading `record.ID` yielded '' for any entity whose
|
|
246
|
+
// key isn't named ID, and SearchFusion drops empty RecordIDs — so this lane silently
|
|
247
|
+
// contributed nothing for those entities. RunView always returns the PK columns, even
|
|
248
|
+
// with an explicit Fields list, so the values are guaranteed present on the row.
|
|
249
|
+
const recordID = entityInfo
|
|
250
|
+
? CompositeKey.FromEntityRecord(entityInfo, record).ToCompactURLSegment()
|
|
251
|
+
: String(record.ID ?? '');
|
|
244
252
|
const title = this.extractTitle(record, entityInfo);
|
|
245
253
|
const snippet = this.extractSnippet(record, entityInfo);
|
|
246
254
|
// Calculate relevance: check how many fields match the query
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntitySearchProvider.js","sourceRoot":"","sources":["../../src/generic/EntitySearchProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;;;;;;;;AAEH,OAAO,EAAqB,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAY,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"EntitySearchProvider.js","sourceRoot":"","sources":["../../src/generic/EntitySearchProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
* @module @memberjunction/search-engine
|
|
21
21
|
*/
|
|
22
22
|
import { IMetadataProvider, UserInfo } from '@memberjunction/core';
|
|
23
|
-
import { SearchEngineBase } from '@memberjunction/core-entities';
|
|
23
|
+
import { SearchEngineBase, MJAIAgentEntity, MJAISkillEntity } from '@memberjunction/core-entities';
|
|
24
24
|
import { BaseSingleton } from '@memberjunction/global';
|
|
25
25
|
import { SearchParams, SearchResult, SearchResultItem, SearchStreamEvent, ScopePrincipals } from './search.types.js';
|
|
26
26
|
import { ScopeDimensionResolver } from './ScopeDimensionResolver.js';
|
|
27
|
-
import { ScopeExplanation, ExplainScopeInput } from './ScopeExplanation.js';
|
|
27
|
+
import { ScopeExplanation, ExplainScopeInput, EntitlementExplanation } from './ScopeExplanation.js';
|
|
28
28
|
/**
|
|
29
29
|
* Collects lane problems keyed by the lane's **row ID** instead of throwing.
|
|
30
30
|
*
|
|
@@ -312,10 +312,14 @@ export declare class SearchEngine extends BaseSingleton<SearchEngine> {
|
|
|
312
312
|
}): ScopePrincipals;
|
|
313
313
|
/** Explain a single scope. Never throws — a failure to resolve IS the explanation. */
|
|
314
314
|
private explainOneScope;
|
|
315
|
-
/** Resolve entitlement for the dry run, including the skill and tenant principals.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
315
|
+
/** Resolve entitlement for the dry run, including the skill and tenant principals.
|
|
316
|
+
* `protected`, like {@link principalsFrom}, so a test can drive it without weak-typed casts.
|
|
317
|
+
*/
|
|
318
|
+
protected explainEntitlement(scopeID: string, input: ExplainScopeInput, contextUser: UserInfo): Promise<EntitlementExplanation>;
|
|
319
|
+
/** Load an agent or skill principal by ID; null when no ID was supplied.
|
|
320
|
+
* `protected` so a test can substitute principal loading; see {@link explainEntitlement}.
|
|
321
|
+
*/
|
|
322
|
+
protected loadPrincipal<T extends MJAIAgentEntity | MJAISkillEntity>(entityName: string, id: string | null | undefined, contextUser: UserInfo): Promise<T | null>;
|
|
319
323
|
/**
|
|
320
324
|
* Render every lane and report which would run.
|
|
321
325
|
*
|
|
@@ -463,6 +467,18 @@ export declare class SearchEngine extends BaseSingleton<SearchEngine> {
|
|
|
463
467
|
* record of this entity is dropped whether or not a row filter exists.
|
|
464
468
|
*/
|
|
465
469
|
private verifyOwnershipAndRowFilters;
|
|
470
|
+
/** `PK IN ('a','b',...)` — the fast path for the overwhelmingly common single-column key. */
|
|
471
|
+
private buildSingleKeyMembership;
|
|
472
|
+
/** `(F1='v1' AND F2='v2') OR (...)` — one term per composite-key result. */
|
|
473
|
+
private buildCompositeKeyMembership;
|
|
474
|
+
/**
|
|
475
|
+
* Key values in primary-key metadata order, UUID-normalized and joined — the comparison form for
|
|
476
|
+
* matching a result's RecordID against the rows the database returned. Field-name lookup is
|
|
477
|
+
* case-insensitive and values are normalized so a segment written by an external index (lowercase
|
|
478
|
+
* UUIDs, differently-cased column names) still matches. For a single-column key this is exactly
|
|
479
|
+
* `NormalizeUUID(value)`.
|
|
480
|
+
*/
|
|
481
|
+
private canonicalKeyValues;
|
|
466
482
|
/** Build an error SearchResult */
|
|
467
483
|
/**
|
|
468
484
|
* Public hook for callers (e.g. the GraphQL resolver) to emit a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchEngine.d.ts","sourceRoot":"","sources":["../../src/generic/SearchEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"SearchEngine.d.ts","sourceRoot":"","sources":["../../src/generic/SearchEngine.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
*
|
|
20
20
|
* @module @memberjunction/search-engine
|
|
21
21
|
*/
|
|
22
|
-
import { EntityPermissionType, LogError, LogStatus, RunView } from '@memberjunction/core';
|
|
22
|
+
import { CompositeKey, EntityPermissionType, LogError, LogStatus, RunView } from '@memberjunction/core';
|
|
23
23
|
import { SearchEngineBase } from '@memberjunction/core-entities';
|
|
24
|
-
import { BaseSingleton, MJGlobal, NormalizeUUID, UUIDsEqual } from '@memberjunction/global';
|
|
24
|
+
import { BaseSingleton, EscapeSQLString, MJGlobal, NormalizeUUID, UUIDsEqual } from '@memberjunction/global';
|
|
25
25
|
import { BaseSearchProvider } from './ISearchProvider.js';
|
|
26
26
|
import { SearchFusion } from './SearchFusion.js';
|
|
27
27
|
import { SearchEnricher } from './SearchEnricher.js';
|
|
@@ -704,11 +704,60 @@ export class SearchEngine extends BaseSingleton {
|
|
|
704
704
|
let effectiveContext;
|
|
705
705
|
let dimensionFailure = null;
|
|
706
706
|
try {
|
|
707
|
+
// DO NOT BIND A PRINCIPAL THE ENTITLEMENT STEP JUST REFUSED. `deriveServerValue` binds
|
|
708
|
+
// `Principals.SkillID` (and AgentID) into a dimension's expansion query, so resolving
|
|
709
|
+
// with the caller's principals after `explainEntitlement` denied them would run
|
|
710
|
+
// server-authored SQL parameterised by an ID that failed its gate — the exact thing the
|
|
711
|
+
// action refuses with INVALID_PARAM rather than "continuing with a null skill". The
|
|
712
|
+
// dimension explanation is still produced, just for an unprincipled search, and the
|
|
713
|
+
// diagnostic says so rather than leaving the reader to assume the principals applied.
|
|
714
|
+
// Drop the principals ONLY when the principals are what was refused. Dropping them for
|
|
715
|
+
// an unrelated denial — the user simply has no per-scope grant — drives the expansion
|
|
716
|
+
// query with null ids, which returns no rows, which makes a required dimension throw and
|
|
717
|
+
// the explanation announce "dimension resolution FAILED". The admin then goes and fixes a
|
|
718
|
+
// dimension that was never broken. `PrincipalNotActivatable` is exactly the distinction
|
|
719
|
+
// needed to tell those two cases apart.
|
|
720
|
+
// EVERY principal-side refusal drops the principals, not just one of them.
|
|
721
|
+
//
|
|
722
|
+
// The rule stated above is "drop them ONLY when the principals are what was refused", and
|
|
723
|
+
// `PrincipalNotActivatable` was the only source honouring it. `AgentNone`,
|
|
724
|
+
// `AgentAssignedNotListed`, `SkillNone` and `SkillAssignedNotListed` are equally
|
|
725
|
+
// principal-side — the principal IS the reason — yet their ids were still bound into the
|
|
726
|
+
// expansion query. This is the same set the Scoped Search action classifies as
|
|
727
|
+
// ACCESS_DENIED rather than PERMISSION_DENIED, for the same reason.
|
|
728
|
+
// A TOTAL MAP, NOT A LIST: `SearchScopePermissionSource` is a closed union, so writing
|
|
729
|
+
// this as `Record<Source, boolean>` makes the compiler demand an answer for any source
|
|
730
|
+
// added later. As a `string[]` a new principal-side source would silently default to
|
|
731
|
+
// "bind it" — which is the exact defect this block exists to fix, re-openable by an
|
|
732
|
+
// unrelated edit.
|
|
733
|
+
const IS_PRINCIPAL_SIDE = {
|
|
734
|
+
PrincipalNotActivatable: true,
|
|
735
|
+
AgentNone: true,
|
|
736
|
+
AgentAssignedNotListed: true,
|
|
737
|
+
SkillNone: true,
|
|
738
|
+
SkillAssignedNotListed: true,
|
|
739
|
+
// Grant-only sources: unreachable while `Allowed` is false, listed for totality.
|
|
740
|
+
AgentUnscopedAll: false,
|
|
741
|
+
SkillUnscopedAll: false,
|
|
742
|
+
// User-side: dropping principals here would drive the expansion query with nulls,
|
|
743
|
+
// making a required dimension throw and the explanation announce a failure that is
|
|
744
|
+
// not real. `DirectGrant` covers the explicit-None deny, which is still user-side.
|
|
745
|
+
DirectGrant: false,
|
|
746
|
+
RoleGrant: false,
|
|
747
|
+
NoGrant: false,
|
|
748
|
+
};
|
|
749
|
+
const principalsJudged = entitlement.Allowed || !IS_PRINCIPAL_SIDE[entitlement.Source];
|
|
750
|
+
if (!principalsJudged && (input.AIAgentID || input.AISkillID)) {
|
|
751
|
+
diagnostics.push('principals were NOT bound into dimension resolution: entitlement denied them, '
|
|
752
|
+
+ 'so the bound below is the one an unprincipled search would see.');
|
|
753
|
+
}
|
|
707
754
|
const resolved = await this.dimensionResolver.Resolve({
|
|
708
755
|
Scope: scope,
|
|
709
756
|
CallerContext: input.SearchContext,
|
|
710
757
|
ContextUser: contextUser,
|
|
711
|
-
Principals:
|
|
758
|
+
Principals: principalsJudged
|
|
759
|
+
? this.principalsFrom(input)
|
|
760
|
+
: { AgentID: null, SkillID: null },
|
|
712
761
|
});
|
|
713
762
|
dimensions = resolved.Provenance;
|
|
714
763
|
diagnostics.push(...resolved.Diagnostics);
|
|
@@ -745,7 +794,9 @@ export class SearchEngine extends BaseSingleton {
|
|
|
745
794
|
ResolvedContext: effectiveContext,
|
|
746
795
|
};
|
|
747
796
|
}
|
|
748
|
-
/** Resolve entitlement for the dry run, including the skill and tenant principals.
|
|
797
|
+
/** Resolve entitlement for the dry run, including the skill and tenant principals.
|
|
798
|
+
* `protected`, like {@link principalsFrom}, so a test can drive it without weak-typed casts.
|
|
799
|
+
*/
|
|
749
800
|
async explainEntitlement(scopeID, input, contextUser) {
|
|
750
801
|
const principals = {
|
|
751
802
|
UserID: contextUser.ID ?? null,
|
|
@@ -754,10 +805,37 @@ export class SearchEngine extends BaseSingleton {
|
|
|
754
805
|
PrimaryScopeRecordID: input.SearchContext?.PrimaryScopeRecordID ?? null,
|
|
755
806
|
};
|
|
756
807
|
try {
|
|
808
|
+
// No ENTITLEMENT gate here on purpose — that judgement belongs to
|
|
809
|
+
// ResolveEffectivePermission. (The loadability check just below is a different thing: it
|
|
810
|
+
// refuses an id that names nothing, which the resolver could not judge either way.)
|
|
811
|
+
// The principals are judged inside ResolveEffectivePermission,
|
|
812
|
+
// where a principal actually widens — so the preview and the search reach the same
|
|
813
|
+
// verdict because they run the same code, not because two copies agree.
|
|
757
814
|
const [agent, skill] = await Promise.all([
|
|
758
815
|
this.loadPrincipal('MJ: AI Agents', input.AIAgentID, contextUser),
|
|
759
816
|
this.loadPrincipal('MJ: AI Skills', input.AISkillID, contextUser),
|
|
760
817
|
]);
|
|
818
|
+
// A PRINCIPAL THAT WAS NAMED BUT WOULD NOT LOAD IS A REFUSAL, NOT AN ABSENCE.
|
|
819
|
+
//
|
|
820
|
+
// `loadPrincipal` returns null both when nothing was supplied and when what was supplied
|
|
821
|
+
// does not exist. Letting the second case fall through as null means the resolver never
|
|
822
|
+
// sees a principal, so its rules never fire, and a user with their own grant is reported
|
|
823
|
+
// ALLOWED — after which `principalsJudged` is true and `principalsFrom(input)` binds the
|
|
824
|
+
// caller's RAW id string into the expansion query, unjudged. That is precisely what the
|
|
825
|
+
// action refuses with INVALID_PARAM rather than "continuing with a null skill", and a
|
|
826
|
+
// preview that promises what the search refuses is worse than no preview.
|
|
827
|
+
const unloadable = (input.AIAgentID && !agent) ? `agent '${input.AIAgentID}'`
|
|
828
|
+
: (input.AISkillID && !skill) ? `skill '${input.AISkillID}'`
|
|
829
|
+
: null;
|
|
830
|
+
if (unloadable) {
|
|
831
|
+
return {
|
|
832
|
+
Allowed: false,
|
|
833
|
+
Level: 'None',
|
|
834
|
+
Source: 'PrincipalNotActivatable',
|
|
835
|
+
Reason: `${unloadable} was supplied but could not be loaded, so it cannot be judged. The Scoped Search action refuses this with INVALID_PARAM, and the SearchKnowledge resolvers refuse an unloadable agent the same way — preview and enforcement agree.`,
|
|
836
|
+
Principals: principals,
|
|
837
|
+
};
|
|
838
|
+
}
|
|
761
839
|
const permission = await GetSearchScopePermissionResolver().ResolveEffectivePermission({
|
|
762
840
|
User: contextUser,
|
|
763
841
|
SearchScopeID: scopeID,
|
|
@@ -777,6 +855,9 @@ export class SearchEngine extends BaseSingleton {
|
|
|
777
855
|
catch (e) {
|
|
778
856
|
// A resolver failure must read as "denied", never as "allowed" — an explanation that
|
|
779
857
|
// fails open would be worse than no explanation at all.
|
|
858
|
+
// NOTE: Source 'NoGrant' is user-side, so the caller's principals are still bound into
|
|
859
|
+
// dimension resolution even though nothing judged them — reaching here requires the
|
|
860
|
+
// permission store itself to be failing. Revisit if ExplainScope gains a production caller.
|
|
780
861
|
const msg = e instanceof Error ? e.message : String(e);
|
|
781
862
|
return {
|
|
782
863
|
Allowed: false,
|
|
@@ -787,7 +868,9 @@ export class SearchEngine extends BaseSingleton {
|
|
|
787
868
|
};
|
|
788
869
|
}
|
|
789
870
|
}
|
|
790
|
-
/** Load an agent or skill principal by ID; null when no ID was supplied.
|
|
871
|
+
/** Load an agent or skill principal by ID; null when no ID was supplied.
|
|
872
|
+
* `protected` so a test can substitute principal loading; see {@link explainEntitlement}.
|
|
873
|
+
*/
|
|
791
874
|
async loadPrincipal(entityName, id, contextUser) {
|
|
792
875
|
if (!id)
|
|
793
876
|
return null;
|
|
@@ -1599,23 +1682,27 @@ export class SearchEngine extends BaseSingleton {
|
|
|
1599
1682
|
* record of this entity is dropped whether or not a row filter exists.
|
|
1600
1683
|
*/
|
|
1601
1684
|
async verifyOwnershipAndRowFilters(entity, entityResults, rlsClause, contextUser, permitted) {
|
|
1602
|
-
const pkField = entity.FirstPrimaryKey;
|
|
1685
|
+
const pkField = entity.FirstPrimaryKey; // first-pk-ok: presence check; Name is only used under the PrimaryKeys.length === 1 branch
|
|
1603
1686
|
if (!pkField) {
|
|
1604
1687
|
// Cannot verify without a primary key — exclude results
|
|
1605
1688
|
LogError(`SearchEngine: Entity "${entity.Name}" has no primary key, cannot verify result ownership`);
|
|
1606
1689
|
return;
|
|
1607
1690
|
}
|
|
1608
|
-
|
|
1609
|
-
|
|
1691
|
+
// `RecordID` is a compact CompositeKey segment: the bare value for a single-column key, a
|
|
1692
|
+
// "F1|v1||F2|v2" segment for a composite one. A single-column key is verified with one IN();
|
|
1693
|
+
// a composite key needs a (F1=.. AND F2=..) term per record — an IN() on the first column
|
|
1694
|
+
// alone could never match the segment, and this check fails closed, so every composite-key
|
|
1695
|
+
// result would have been dropped as unauthorized.
|
|
1696
|
+
const membership = entity.PrimaryKeys.length === 1
|
|
1697
|
+
? this.buildSingleKeyMembership(pkField.Name, entityResults)
|
|
1698
|
+
: this.buildCompositeKeyMembership(entity, entityResults);
|
|
1610
1699
|
// Without a row filter this is a pure existence check against the entity's own view.
|
|
1611
|
-
const filter = rlsClause
|
|
1612
|
-
? `${pkFieldName} IN (${recordIDs}) AND (${rlsClause})`
|
|
1613
|
-
: `${pkFieldName} IN (${recordIDs})`;
|
|
1700
|
+
const filter = rlsClause ? `(${membership}) AND (${rlsClause})` : membership;
|
|
1614
1701
|
const rv = new RunView();
|
|
1615
1702
|
const result = await rv.RunView({
|
|
1616
1703
|
EntityName: entity.Name,
|
|
1617
1704
|
ExtraFilter: filter,
|
|
1618
|
-
Fields:
|
|
1705
|
+
Fields: entity.PrimaryKeys.map(pk => pk.Name),
|
|
1619
1706
|
ResultType: 'simple'
|
|
1620
1707
|
}, contextUser);
|
|
1621
1708
|
if (!result.Success) {
|
|
@@ -1623,13 +1710,40 @@ export class SearchEngine extends BaseSingleton {
|
|
|
1623
1710
|
LogError(`SearchEngine: ownership/RLS RunView failed for entity "${entity.Name}": ${result.ErrorMessage ?? 'unknown error'}`);
|
|
1624
1711
|
return;
|
|
1625
1712
|
}
|
|
1626
|
-
const
|
|
1713
|
+
const validKeys = new Set(result.Results.map(r => this.canonicalKeyValues(entity, CompositeKey.FromEntityRecord(entity, r))));
|
|
1627
1714
|
for (const item of entityResults) {
|
|
1628
|
-
|
|
1715
|
+
const key = CompositeKey.FromURLSegment(entity, item.RecordID);
|
|
1716
|
+
if (validKeys.has(this.canonicalKeyValues(entity, key))) {
|
|
1629
1717
|
permitted.push(item);
|
|
1630
1718
|
}
|
|
1631
1719
|
}
|
|
1632
1720
|
}
|
|
1721
|
+
/** `PK IN ('a','b',...)` — the fast path for the overwhelmingly common single-column key. */
|
|
1722
|
+
buildSingleKeyMembership(pkFieldName, results) {
|
|
1723
|
+
const ids = results.map(r => `'${EscapeSQLString(r.RecordID)}'`).join(',');
|
|
1724
|
+
return `${pkFieldName} IN (${ids})`;
|
|
1725
|
+
}
|
|
1726
|
+
/** `(F1='v1' AND F2='v2') OR (...)` — one term per composite-key result. */
|
|
1727
|
+
buildCompositeKeyMembership(entity, results) {
|
|
1728
|
+
return results
|
|
1729
|
+
.map(r => `(${CompositeKey.FromURLSegment(entity, r.RecordID).ToWhereClause()})`)
|
|
1730
|
+
.join(' OR ');
|
|
1731
|
+
}
|
|
1732
|
+
/**
|
|
1733
|
+
* Key values in primary-key metadata order, UUID-normalized and joined — the comparison form for
|
|
1734
|
+
* matching a result's RecordID against the rows the database returned. Field-name lookup is
|
|
1735
|
+
* case-insensitive and values are normalized so a segment written by an external index (lowercase
|
|
1736
|
+
* UUIDs, differently-cased column names) still matches. For a single-column key this is exactly
|
|
1737
|
+
* `NormalizeUUID(value)`.
|
|
1738
|
+
*/
|
|
1739
|
+
canonicalKeyValues(entity, key) {
|
|
1740
|
+
return entity.PrimaryKeys
|
|
1741
|
+
.map(pk => {
|
|
1742
|
+
const match = key.KeyValuePairs.find(kv => kv.FieldName.trim().toLowerCase() === pk.Name.trim().toLowerCase());
|
|
1743
|
+
return NormalizeUUID(String(match?.Value ?? ''));
|
|
1744
|
+
})
|
|
1745
|
+
.join('||');
|
|
1746
|
+
}
|
|
1633
1747
|
/** Build an error SearchResult */
|
|
1634
1748
|
/**
|
|
1635
1749
|
* Public hook for callers (e.g. the GraphQL resolver) to emit a
|