Filter banner trackers by linked third party

The trackers list page on the cookie-banner configuration screen needs
to filter rows by the third party that the pattern resolves to. The
tricky part is that "third party" comes from two unrelated tables:
ThirdParty (org-scoped, linked through tracker_patterns.third_party_id)
and CommonThirdParty (global catalog, reached indirectly through
common_tracker_patterns.common_third_party_id). The filter must accept
either flavour of GID and resolve transparently.

Add a single thirdPartyId field to TrackerPatternFilter and dispatch
on the GID's entity-type prefix at the resolver:

  ThirdPartyEntityType       -> WithThirdPartyID
  CommonThirdPartyEntityType -> resolve common_tracker_pattern_id list
                                via the cookiebanner service, then
                                WithCommonTrackerPatternIDs

Any other entity type returns an Invalid error rather than silently
matching everything; an unknown caller-supplied GID is a contract bug.
The empty-but-non-nil ID slice produced when a CommonThirdParty has no
patterns yet correctly yields zero rows because the SQL fragment uses
ANY(...).

To populate the filter combobox, add a new CookieBanner.linkedThirdParties
field returning [TrackerPatternThirdPartyLink!]!, a union of ThirdParty
and CommonThirdParty. The resolver collects DISTINCT third_party_id and
common_tracker_pattern_id from the banner's tracker patterns (no joins,
per coredata convention), then chains the catalog lookup through
CommonTrackerPatterns -> CommonThirdParties. Authorization scopes
follow the existing trackerPattern resolvers: ActionTrackerPatternList
gates the aggregation, ActionThirdPartyGet and ActionCommonThirdPartyGet
each gate their respective fan-out only when that branch has work.

The org-scoped fan-out uses dataloadgen.LoadAll so it batches in a
single round-trip; per-key NotFound errors are dropped (a deleted
third party doesn't fail the whole list), other errors bubble up.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-05-28 08:49:25 +02:00
parent d93ff7ba25
commit 66ffcf3411
4 changed files with 143 additions and 0 deletions

View File

@@ -167,6 +167,15 @@ type CookieBanner implements Node {
filter: TrackerPatternFilter
): TrackerPatternConnection @goField(forceResolver: true)
"""
The deduped union of third parties referenced by the banner's
tracker patterns, both org-scoped (ThirdParty) and global
(CommonThirdParty). Powers the third-party filter combobox on the
trackers list page.
"""
linkedThirdParties: [TrackerPatternThirdPartyLink!]!
@goField(forceResolver: true)
uncategorisedTrackerResources(
first: Int
after: CursorKey
@@ -318,6 +327,14 @@ type TrackerPatternConnection
pageInfo: PageInfo!
}
"""
A third party associated with a banner's tracker patterns. Either the
tenant-managed ThirdParty (when a pattern was promoted to the org
catalog) or the global CommonThirdParty linked through a common
tracker pattern.
"""
union TrackerPatternThirdPartyLink = ThirdParty | CommonThirdParty
type TrackerPatternEdge {
cursor: CursorKey!
node: TrackerPattern!
@@ -339,6 +356,14 @@ input TrackerPatternFilter
source: CookieSource
trackerType: TrackerType
cookieCategoryId: ID
"""
Filter to tracker patterns linked to a single third party. Accepts
either an org-scoped ThirdParty GID (matched against third_party_id)
or a global CommonThirdParty GID (matched against the indirect link
through common_tracker_patterns). The dispatch happens at the
resolver based on the GID entity-type prefix.
"""
thirdPartyId: ID
}
type DetectedTracker implements Node {