When both pattern matching and domain matching fail to identify a
tracker, an opt-in LLM agent can now attempt identification using
internal database searches and optional web search. The agent returns
structured output (third party name, category, description, confidence)
and the worker auto-creates CommonThirdParty records when needed.
The feature is gated behind the `llm.tracker-mapping.provider` config
field; when unset the worker behaves exactly as before.
Signed-off-by: Émile Ré <emile@probo.com>
The pattern analysis worker creates glob patterns (e.g. prism_*) by
merging exact patterns but never set MappingRequestedAt, so the tracker
mapping worker never picked them up to match against common tracker
patterns.
Signed-off-by: Émile Ré <emile@probo.com>
When neither pattern nor domain matching finds an existing common
tracker pattern, upsert one with no third party association and a
lower confidence (0.5) so every seen pattern is cataloged.
Also fix table name in LoadByOrganizationIDAndCommonThirdPartyID
(vendors -> third_parties).
Signed-off-by: Émile Ré <emile@probo.com>
Move tracker_mapping_worker.go from pkg/probo to pkg/cookiebanner and
rename worker.go to pattern_analysis_worker.go to reflect the worker
name.
Signed-off-by: Émile Ré <emile@probo.com>
Previously, resolveThirdParty silently swallowed all errors from
LoadByOrganizationIDAndCommonThirdPartyID, making real database
errors indistinguishable from a missing third party. Now it returns
an error for non-not-found failures, wrapped for clarity, and
callers log and degrade gracefully.
Signed-off-by: Émile Ré <emile@probo.com>
Remove redundant resolveThirdParty fallback that re-attempted
resolution with the same inputs, and rename
LoadCommonThirdPartyIDByTrackerPatternID to
LoadCommonThirdPartyIDByDomainMatch to reflect that it joins on
initiator_domain.
Signed-off-by: Émile Ré <emile@probo.com>
Change the unique constraint on common_third_party_domains from (domain)
to (common_third_party_id, domain) so a domain like google.com can be
associated with Google, Google Analytics, Google AdSense, etc.
Also fix Beamer domain (was hotjar.com, now getbeamer.com) and preserve
the original url.Parse error in pgconn DSN parsing.
Signed-off-by: Émile Ré <emile@probo.com>
Replace the --data flag with go:embed so the dataset is baked into the
proboctl binary and the seed command needs no external file argument.
Signed-off-by: Émile Ré <emile@probo.com>
Introduce a new proboctl Cobra CLI for Probo instance management
that connects directly to PostgreSQL. Move the standalone
common-third-parties-import and common-tracker-patterns-import
commands into proboctl as `proboctl seed common-third-parties`
and `proboctl seed common-tracker-patterns`, replacing flag-based
PG connection with a shared factory pattern.
Signed-off-by: Émile Ré <emile@probo.com>
Add a slug column to common_third_parties for stable cross-source
deduplication. The OCD tracker patterns importer now resolves third
parties via a three-step cascade (slug lookup, domain fallback,
auto-create) instead of silently dropping unmatched links.
Signed-off-by: Émile Ré <emile@probo.com>
- Replace copy-pasted New Relic URLs in Resend third-party entry
with correct resend.com URLs and drop inapplicable fields
- Escape single '%' instead of '%%' in LIKE pattern conversion so
literal percent signs are not treated as wildcards
- Return actual row ID from CommonTrackerPattern.Upsert via
RETURNING id so conflict-path callers get the existing ID
- Add ORDER BY id ASC to vendor-by-common-third-party query for
deterministic LIMIT 1 selection
Signed-off-by: Émile Ré <emile@getprobo.com>
Signed-off-by: Émile Ré <emile@probo.com>
Replace the local data.json source with a live clone of the
Open Cookie Database repository. The importer now reads
open-cookie-database.json, maps OCD entries to tracker pattern
rows, and resolves third-party links via case-insensitive
platform name lookup.
Signed-off-by: Émile Ré <emile@getprobo.com>
Signed-off-by: Émile Ré <emile@probo.com>
LoadByID and LoadByIDs used 4-space indentation and were missed
by the bulk column addition. The struct field existed but the
SELECT did not return it, causing pgx scan failures.
Signed-off-by: Émile Ré <emile@getprobo.com>
Signed-off-by: Émile Ré <emile@probo.com>
Poll-based worker that maps org-scoped tracker patterns to the
common knowledge base via pattern matching and domain-based
attribution. Populates initiator_domain on detected trackers
at report time. Resolves org-scoped vendors through the common
third party link.
Signed-off-by: Émile Ré <emile@getprobo.com>
Signed-off-by: Émile Ré <emile@probo.com>
Seed common_tracker_patterns from Open Cookie Database (2300
patterns with max_age_seconds where available). Add domain
aliases to all 92 vendors in data.json. Extend third-parties
import to upsert domain aliases. Add dedicated import command
for tracker patterns with third-party name cache.
Signed-off-by: Émile Ré <emile@getprobo.com>
Signed-off-by: Émile Ré <emile@probo.com>
Uses golang.org/x/net/publicsuffix to extract the effective
top-level domain plus one label from a URL. Used to populate
detected_trackers.initiator_domain for domain-based tracker
attribution.
Signed-off-by: Émile Ré <emile@getprobo.com>
Signed-off-by: Émile Ré <emile@probo.com>
CommonThirdPartyDomain maps eTLD+1 domains to third parties for
fast domain-based attribution. CommonTrackerPattern stores the
global tracker knowledge base with glob/exact matching support.
Signed-off-by: Émile Ré <emile@getprobo.com>
Signed-off-by: Émile Ré <emile@probo.com>
Introduces common_third_party_domains (CITEXT domain aliases per
third party), common_tracker_patterns (global tracker knowledge
base), and new FK columns on tracker_patterns (third_party_id,
common_tracker_pattern_id), vendors (common_third_party_id), and
detected_trackers (initiator_domain) to support automated
tracker-to-vendor attribution.
Signed-off-by: Émile Ré <emile@getprobo.com>
Signed-off-by: Émile Ré <emile@probo.com>
Users are created with state=INACTIVE and only become ACTIVE on
first login. The server-side state check incorrectly rejected
newly-created users who hadn't yet activated their accounts.
The frontend filter (state: ACTIVE) is the correct layer to hide
deactivated people from the recipient picker. The existing contract
end date validation remains as server-side defense in depth.
Co-authored-by: Émile Ré <nemile.re@gmail.com>
Signed-off-by: Émile Ré <emile@getprobo.com>
Signed-off-by: Émile Ré <emile@probo.com>
The signature request recipient lists (both the multi-select dialog
and the document signatures page) included people who were inactive
via SCIM deactivation. The existing filter only excluded people with
ended contracts but not those with an INACTIVE state.
This adds state: ACTIVE to the ProfileFilter in both frontend queries
and introduces a server-side ErrProfileInactive validation in the
RequestSignature and BulkRequestSignatures service methods to reject
inactive profiles even if called directly via API.
Co-authored-by: Émile Ré <nemile.re@gmail.com>
Signed-off-by: Émile Ré <emile@getprobo.com>
Signed-off-by: Émile Ré <emile@probo.com>
- Drop Helm wiring for the 9 new access-review connectors
- Drop e2e TODO about access-review connector coverage gap
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
- Require CLIENT_SECRET for new access-review connectors
- Use Heroku account UUID as ExternalID
- Bump GitHub orgs picker to per_page=100
- Drop Snyk, Ramp, Lever, Deel access-review providers
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
- Inline Vercel driver URL with url.URL
- Escape URL path segments in connector name resolvers
- Dedup Vercel /v2/user fallback in name resolver
- Drop allowedHosts:true from vite dev server
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
- Rename access-review migration with random time
- Move PagerDuty token-response handling to its own file
- Strip OAuth error_description from log and redirect
- Validate PagerDuty subdomain on OAuth callback
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
- Stop leaking customer email domain in cassette guard
- Deep-copy ExtraAuthParams in ApplyProviderDefaults
- Drop raw monday graphql error from returned errors
- Add PKCE coverage tests for entropy and replay
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
- Strip email local-part from cassette guard failure
- Drop dead src/components/connectors vite include
- Cover all 13 access-review providers in builder test
- Wire 13 access-review connectors in Helm chart
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
- Wire post-OAuth pickers and 2-auto callback handling
- Add 13 vendor logo components for new connectors
- Wire access-review connectors into bootstrap config
- Track e2e gap for new access-review connectors
Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
The register/document model has fully replaced the snapshot system.
Delete every snapshot-scoped row and strip the application code that
referenced them: SnapshotID/SourceID struct fields, snapshot_id IS NULL
filters, snapshot columns from SELECT/INSERT statements and named args,
and the eight migrate-*-snapshots-to-documents one-shot tools.
The remaining snapshot_id / source_id columns, the snapshots and
controls_snapshots tables, the snapshots_type enum, and the
snapshot-scoped indexes are now unused; they are dropped in a follow-up
schema migration so this change can roll back cleanly without leaving
orphaned data.
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>