9 Commits

Author SHA1 Message Date
Sacha Al Himdani
4c57d201a4 Make license declarations consistently MIT
The source headers, LICENSE files, and license metadata had drifted
apart. Align the entire project to MIT:

- Convert every source-file header to the MIT text across all comment
  styles (Go, TS, TSX, JS, MJS, SQL, CSS, GraphQL, shell), including
  SPDX-License-Identifier tags
- Set the root and cookie-banner LICENSE files to the MIT text with a
  "MIT License" title line
- Switch the package.json license fields, Docker image label, and
  cookie-banner README to MIT
- Update docs and the genmodels header generator accordingly
- Normalize copyright lines to a single format
  (Copyright (c) <year(s)> Probo Inc <hello@probo.com>.): unify the
  hello@getprobo.com and hello@probo.inc emails to hello@probo.com and
  the comma-separated years to a hyphenated range

Genuine third-party references are intentionally left untouched: the
Lucide icon attributions (Lucide is ISC) and the trivy dependency
license allowlist.

Signed-off-by: Sacha Al Himdani <sacha@probo.com>
2026-07-13 16:21:14 +02:00
Sacha Al Himdani
9ac71f948f Update contact email to hello@probo.com
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
2026-06-09 16:45:23 +02:00
Émile Ré
9156d6a16a Add wsl linter and fix
Signed-off-by: Émile Ré <emile@probo.com>
2026-05-20 09:27:28 +04:00
Émile Ré
10adf2bd4b Refactor domain-match lookup to idiomatic Load + filter
Replace the cross-entity JOIN in
DetectedTrackers.LoadCommonThirdPartyIDByDomainMatch with two
idiomatic coredata calls: LoadInitiatorDomainsByTrackerPatternID
on DetectedTrackers, then a new CommonThirdPartyDomains.Load with
a CommonThirdPartyDomainFilter. Each entity now queries only its
own table, and the caller orchestrates the lookup.

Document the Load vs LoadAll naming convention and the no
cross-entity JOINs rule in contrib/claude/coredata.md.

Signed-off-by: Émile Ré <emile@probo.com>
2026-05-19 11:52:57 +04:00
Émile Ré
370b593217 Replace xmax upsert trick with RETURNING full row
Upsert methods now RETURNING all struct columns and scan the result
back into the pointer receiver, keeping the caller in sync with the
actual DB state (id, created_at, etc. from the existing row on
conflict). Insert detection compares the saved original ID with the
returned ID instead of relying on the PostgreSQL-internal xmax column.

Signed-off-by: Émile Ré <emile@probo.com>
2026-05-19 11:37:26 +04:00
Émile Ré
0c89a4b241 Drop RowsAffected check from Delete methods
Deletes are idempotent — zero affected rows is not an error.

Signed-off-by: Émile Ré <emile@probo.com>
2026-05-19 11:08:01 +04:00
Émile Ré
f1357a7e20 Check constraint name in PgError unique violations
Checking only pgErr.Code == "23505" is insufficient when a
table has multiple unique constraints. Always verify
pgErr.ConstraintName as well to avoid mapping unrelated
violations to the wrong sentinel error.

Signed-off-by: Émile Ré <emile@probo.com>
2026-05-19 11:03:37 +04:00
Émile Ré
ed41b354b0 Allow domains to belong to multiple third parties
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>
2026-05-18 19:05:11 +04:00
Émile Ré
8aa82104e0 Add coredata models for tracker mapping
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>
2026-05-18 19:05:06 +04:00