Add first-party verdict and guards to tracker mapping
The tracker-pattern catalog was binary (linked to a vendor or not), so generic and first-party artifacts (loglevel keys, wallet-extension keys, an org's own trackers) were retried forever and, once one row was wrongly attributed, re-propagated to every organization with no re-check. Give catalog rows a terminal attribution verdict (UNDETERMINED, THIRD_PARTY, FIRST_PARTY): FIRST_PARTY short-circuits the whole mapping pipeline so the artifact is never attributed again. Gate deterministic vendor adoption behind a trust bar so only curated/operator rows auto-propagate; lower-confidence agent/heuristic rows are reused as hints and re-resolved, and an independent agent re-confirmation corroborates and promotes them. Make the mapping agent emit an evidence source and reject any attribution that lacks concrete evidence, and let it declare a first-party verdict. Skip the speculative agent for PRE_EXISTING-source patterns, whose low signal invites invented vendors. Add proboctl "ctp mark-first-party" and an --attribution list filter to audit and remediate existing wrong links, and a cursor rule documenting migration naming so the timestamp is taken from date -u, not invented. Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
@@ -62,17 +62,59 @@ const (
|
||||
// rather than the pattern, so the stored row confidence is a
|
||||
// constant like the other heuristic signals (domain, sibling).
|
||||
agentSourceConfidence = 0.8
|
||||
|
||||
// trustedAttributionConfidence is the bar a catalog row must meet for
|
||||
// its third party to be adopted deterministically by another pattern
|
||||
// (the existing-link and matchByPattern paths). Only curated/seed rows
|
||||
// and operator links (confidence 1.0) clear it; agent (0.8) and
|
||||
// domain/sibling (0.7) attributions do not, so a single low-confidence
|
||||
// guess never becomes an authoritative precedent that auto-propagates
|
||||
// across organizations. Such rows are reused as hints only: the
|
||||
// pattern falls through to the evidence-guarded agent, which can
|
||||
// corroborate the guess (promoting the row to this tier) or override
|
||||
// it.
|
||||
trustedAttributionConfidence float32 = 0.9
|
||||
)
|
||||
|
||||
//go:embed prompts/tracker_identification.txt.tmpl
|
||||
var trackerIdentificationPrompt string
|
||||
|
||||
// Tracker-mapping evidence kinds. The agent must report which concrete
|
||||
// evidence backs a vendor attribution; an attribution without one of the
|
||||
// substantive kinds (i.e. "none" or empty) is discarded so the agent
|
||||
// never attributes a vendor from general knowledge or vague similarity.
|
||||
const (
|
||||
evidenceSourceDatabaseMatch = "database_match"
|
||||
evidenceSourceNamingConvention = "naming_convention"
|
||||
evidenceSourceWebSearch = "web_search"
|
||||
evidenceSourceBrowserPage = "browser_page"
|
||||
evidenceSourceNone = "none"
|
||||
)
|
||||
|
||||
// TrackerMappingAgentResult is the structured output the tracker-mapping
|
||||
// agent returns.
|
||||
type TrackerMappingAgentResult struct {
|
||||
ThirdPartyName string `json:"third_party_name" jsonschema:"Name of the company or service that sets this tracker (e.g. 'Google Analytics', 'Meta Pixel'). Empty string if truly unknown."`
|
||||
Category coredata.ThirdPartyCategory `json:"category" jsonschema:"Third party category"`
|
||||
ThirdPartyConfidence float64 `json:"third_party_confidence" jsonschema:"Confidence (0.0 to 1.0) in which company or service set this tracker, independent of whether the artifact is a classic web tracker. Set below 0.5 if unsure who set it."`
|
||||
EvidenceSource string `json:"evidence_source" jsonschema:"The concrete evidence that backs the attribution: 'database_match' (exact pattern in the database), 'naming_convention' (the tracker's meaningful prefix or an embedded vendor name), 'web_search' (a web result naming the setter), 'browser_page' (a page you opened that names the setter), or 'none' when there is no concrete evidence. Must be 'none' whenever third_party_name is empty."`
|
||||
IsFirstParty bool `json:"is_first_party" jsonschema:"True when the artifact has no third party at all: it is the scanned site's own tracker, a generic library or log key (e.g. 'loglevel'), a browser-extension key that embeds the scanned site's origin, or otherwise not attributable to any external vendor. Leave false when a vendor is or might be responsible."`
|
||||
}
|
||||
|
||||
// evidenceSupportsAttribution reports whether the agent supplied a
|
||||
// concrete evidence kind for a vendor attribution. An empty value or
|
||||
// "none" (or any unrecognized value) does not support an attribution.
|
||||
func evidenceSupportsAttribution(evidenceSource string) bool {
|
||||
switch evidenceSource {
|
||||
case
|
||||
evidenceSourceDatabaseMatch,
|
||||
evidenceSourceNamingConvention,
|
||||
evidenceSourceWebSearch,
|
||||
evidenceSourceBrowserPage:
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// buildTrackerMappingAgent builds the tracker-mapping agent. extraTools
|
||||
|
||||
Reference in New Issue
Block a user