Improve tracker source and first-party cleanup
Surface every CookieSource value in the console: the trackers page filter was missing the HTTP option and the source badge helper had no EXTENSION case, so HTTP-sourced rows could not be filtered and extension-sourced rows rendered the raw enum string. On the backend, the mark-first-party verdict now blanks the stale description on both the catalog row and its uncategorised org tracker patterns. A terminal non-third-party row keeps no vendor link, so a description naming the (now-cleared) vendor would be misleading; the mapping worker only copies descriptions into empty rows and never clears them, so clearing is done explicitly here. Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
@@ -244,6 +244,7 @@ export default function CookieBannerTrackersPage({
|
|||||||
<Option value="ALL">{__("All sources")}</Option>
|
<Option value="ALL">{__("All sources")}</Option>
|
||||||
<Option value="SCRIPT">{__("Script")}</Option>
|
<Option value="SCRIPT">{__("Script")}</Option>
|
||||||
<Option value="PRE_EXISTING">{__("Pre-existing")}</Option>
|
<Option value="PRE_EXISTING">{__("Pre-existing")}</Option>
|
||||||
|
<Option value="HTTP">{__("HTTP")}</Option>
|
||||||
<Option value="EXTENSION">{__("Extension")}</Option>
|
<Option value="EXTENSION">{__("Extension")}</Option>
|
||||||
</Select>
|
</Select>
|
||||||
<Select
|
<Select
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export function getTrackerSourceBadge(source: string, __: Translator): Badge {
|
|||||||
case "SCRIPT": return { label: __("Script"), variant: "info" };
|
case "SCRIPT": return { label: __("Script"), variant: "info" };
|
||||||
case "PRE_EXISTING": return { label: __("Pre-existing"), variant: "outline" };
|
case "PRE_EXISTING": return { label: __("Pre-existing"), variant: "outline" };
|
||||||
case "HTTP": return { label: __("HTTP"), variant: "neutral" };
|
case "HTTP": return { label: __("HTTP"), variant: "neutral" };
|
||||||
|
case "EXTENSION": return { label: __("Extension"), variant: "warning" };
|
||||||
default: return { label: source, variant: "neutral" };
|
default: return { label: source, variant: "neutral" };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1015,6 +1015,38 @@ WHERE
|
|||||||
return result.RowsAffected(), nil
|
return result.RowsAffected(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClearDescriptionByIDs blanks the researched description on the given
|
||||||
|
// catalog rows without re-arming enrichment or touching the enrichment
|
||||||
|
// payload. It backs the first-party verdict: a terminal non-third-party
|
||||||
|
// row keeps no vendor link, so a description that named the (now-cleared)
|
||||||
|
// vendor would be stale. The verdict is terminal, so rather than re-derive
|
||||||
|
// a description - which would re-run the mapping agent and re-link a
|
||||||
|
// vendor - the description simply returns to empty. Returns the number of
|
||||||
|
// rows updated.
|
||||||
|
func (ps *CommonTrackerPatterns) ClearDescriptionByIDs(
|
||||||
|
ctx context.Context,
|
||||||
|
tx pg.Tx,
|
||||||
|
ids []gid.GID,
|
||||||
|
) (int64, error) {
|
||||||
|
q := `
|
||||||
|
UPDATE common_tracker_patterns
|
||||||
|
SET
|
||||||
|
description = '',
|
||||||
|
updated_at = NOW()
|
||||||
|
WHERE
|
||||||
|
id = ANY(@ids)
|
||||||
|
`
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{"ids": ids}
|
||||||
|
|
||||||
|
result, err := tx.Exec(ctx, q, args)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("cannot clear common tracker pattern description: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.RowsAffected(), nil
|
||||||
|
}
|
||||||
|
|
||||||
// RequestEnrichmentByIDs arms enrichment on the given common tracker
|
// RequestEnrichmentByIDs arms enrichment on the given common tracker
|
||||||
// patterns by stamping enrichment_requested_at, which is the only column
|
// patterns by stamping enrichment_requested_at, which is the only column
|
||||||
// the enrichment worker claims on. It resets enrichment_attempts to 0 so
|
// the enrichment worker claims on. It resets enrichment_attempts to 0 so
|
||||||
|
|||||||
@@ -1406,6 +1406,49 @@ WHERE
|
|||||||
return result.RowsAffected(), nil
|
return result.RowsAffected(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClearDescriptionForUncategorisedByCommonTrackerPatternIDs blanks the
|
||||||
|
// description on the uncategorised org tracker patterns linked to the
|
||||||
|
// given common tracker patterns. It pairs with the first-party verdict on
|
||||||
|
// the catalog row: when the catalog description is cleared because its
|
||||||
|
// vendor attribution was wrong, the descriptions fanned out to org
|
||||||
|
// patterns named the same stale vendor and must be cleared too - the
|
||||||
|
// mapping worker only ever copies a description into an empty org row, it
|
||||||
|
// never clears one. Like the mapping re-arm it is a global catalog
|
||||||
|
// operation, so it is intentionally not tenant-scoped, and it leaves
|
||||||
|
// excluded and user-categorised patterns untouched. The cookie_categories
|
||||||
|
// subquery is used only for filtering. Returns the number of org patterns
|
||||||
|
// cleared.
|
||||||
|
func (tps *TrackerPatterns) ClearDescriptionForUncategorisedByCommonTrackerPatternIDs(
|
||||||
|
ctx context.Context,
|
||||||
|
tx pg.Tx,
|
||||||
|
commonIDs []gid.GID,
|
||||||
|
) (int64, error) {
|
||||||
|
q := `
|
||||||
|
UPDATE tracker_patterns
|
||||||
|
SET
|
||||||
|
description = '',
|
||||||
|
updated_at = NOW()
|
||||||
|
WHERE
|
||||||
|
common_tracker_pattern_id = ANY(@common_ids)
|
||||||
|
AND excluded = false
|
||||||
|
AND cookie_category_id IN (
|
||||||
|
SELECT id FROM cookie_categories WHERE kind = @uncategorised_kind
|
||||||
|
)
|
||||||
|
`
|
||||||
|
|
||||||
|
args := pgx.StrictNamedArgs{
|
||||||
|
"common_ids": commonIDs,
|
||||||
|
"uncategorised_kind": CookieCategoryKindUncategorised,
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := tx.Exec(ctx, q, args)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("cannot clear uncategorised tracker pattern descriptions: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.RowsAffected(), nil
|
||||||
|
}
|
||||||
|
|
||||||
// RequestMappingForUnmappedByInitiatorDomains re-arms mapping on the
|
// RequestMappingForUnmappedByInitiatorDomains re-arms mapping on the
|
||||||
// still-unmapped org tracker patterns whose detected trackers share one
|
// still-unmapped org tracker patterns whose detected trackers share one
|
||||||
// of the given initiator domains, so the mapping worker re-resolves them
|
// of the given initiator domains, so the mapping worker re-resolves them
|
||||||
|
|||||||
@@ -44,12 +44,14 @@ func newCmdMarkFirstParty(f *cmdutil.Factory) *cobra.Command {
|
|||||||
Long: "Record the terminal FIRST_PARTY verdict on selected common tracker " +
|
Long: "Record the terminal FIRST_PARTY verdict on selected common tracker " +
|
||||||
"patterns: the artifact has no third party (it is the scanned site's own, " +
|
"patterns: the artifact has no third party (it is the scanned site's own, " +
|
||||||
"a generic library/log key, or an extension key embedding the site origin). " +
|
"a generic library/log key, or an extension key embedding the site origin). " +
|
||||||
"Any vendor link is cleared, and the uncategorised org tracker patterns " +
|
"Any vendor link is cleared and the now-stale description - which may name " +
|
||||||
"linked to them are remapped (org third party cleared, mapping re-armed) so " +
|
"the wrong vendor - is blanked on both the catalog row and the uncategorised " +
|
||||||
"the pipeline drops the stale vendor; because the verdict is terminal the " +
|
"org tracker patterns linked to it. Those org patterns are remapped (org " +
|
||||||
"mapping worker leaves them unattributed. User-categorised and excluded org " +
|
"third party cleared, mapping re-armed) so the pipeline drops the stale " +
|
||||||
"patterns are left untouched. Selection mirrors 'reenrich'. To re-attribute " +
|
"vendor; because the verdict is terminal the mapping worker leaves them " +
|
||||||
"a row later, use 'link' (which returns it to THIRD_PARTY).",
|
"unattributed. User-categorised and excluded org patterns are left " +
|
||||||
|
"untouched. Selection mirrors 'reenrich'. To re-attribute a row later, use " +
|
||||||
|
"'link' (which returns it to THIRD_PARTY).",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,6 +111,7 @@ func newCmdMarkFirstParty(f *cmdutil.Factory) *cobra.Command {
|
|||||||
var (
|
var (
|
||||||
marked int64
|
marked int64
|
||||||
remapped int64
|
remapped int64
|
||||||
|
cleared int64
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := pgClient.WithTx(
|
if err := pgClient.WithTx(
|
||||||
@@ -121,6 +124,10 @@ func newCmdMarkFirstParty(f *cmdutil.Factory) *cobra.Command {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err = ps.ClearDescriptionByIDs(ctx, tx, ids); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
var tps coredata.TrackerPatterns
|
var tps coredata.TrackerPatterns
|
||||||
|
|
||||||
remapped, err = tps.RequestMappingForUncategorisedByCommonTrackerPatternIDs(ctx, tx, ids)
|
remapped, err = tps.RequestMappingForUncategorisedByCommonTrackerPatternIDs(ctx, tx, ids)
|
||||||
@@ -128,6 +135,11 @@ func newCmdMarkFirstParty(f *cmdutil.Factory) *cobra.Command {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cleared, err = tps.ClearDescriptionForUncategorisedByCommonTrackerPatternIDs(ctx, tx, ids)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
); err != nil {
|
); err != nil {
|
||||||
@@ -136,9 +148,10 @@ func newCmdMarkFirstParty(f *cmdutil.Factory) *cobra.Command {
|
|||||||
|
|
||||||
_, _ = fmt.Fprintf(
|
_, _ = fmt.Fprintf(
|
||||||
out,
|
out,
|
||||||
"Marked %d pattern(s) first-party, remapped %d uncategorised org tracker pattern(s).\n",
|
"Marked %d pattern(s) first-party, remapped %d uncategorised org tracker pattern(s), cleared %d stale org description(s).\n",
|
||||||
marked,
|
marked,
|
||||||
remapped,
|
remapped,
|
||||||
|
cleared,
|
||||||
)
|
)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Reference in New Issue
Block a user