Skip to content

Privacy Score — SQL source

One number for your privacy health: your browser fingerprint, a test password's strength and breach exposure, and a site's security headers — four checks, one score, concrete fixes. Runs in your browser; only a 5-character hash prefix ever leaves it.

This is the SQL implementation — the same logic the interactive tool runs, in a shareable, citable form.

-- privacy-score — scoring rubric + overall letter computation.
-- Source:   CosmoDev polyglot showcase port of the Privacy Score tool,
--           ported from src/lib/privacy-score.ts (canonical TypeScript).
-- License:  display source — part of CosmoDev's polyglot tool pages.
--
-- Four category checks, each scored out of 25; the overall percent is
-- renormalized over the checks that actually ran (skipping a check never
-- lowers your score). Letter bands: >=85 A, >=70 B, >=50 C, else D.

-- The rubric: how each category converts raw check output into points.
CREATE TABLE privacy_rubric (
  category   TEXT PRIMARY KEY,  -- fingerprint | password | headers | breach
  rule       TEXT NOT NULL,     -- point conversion, straight from the TS lib
  floor_bad  INTEGER NOT NULL,  -- points < floor_bad  -> 'bad'  (act now)
  floor_warn INTEGER NOT NULL   -- ... < floor_warn    -> 'warn'
);
INSERT INTO privacy_rubric (category, rule, floor_bad, floor_warn) VALUES
  ('fingerprint', '25 - high_risk*4 - medium_risk*1.5 - max(0, signals - 12)*0.5', 10, 20),
  ('password',    'clamp(score,0,4)/4 * 25, then *0.32 when breached',              10, 20),
  ('headers',     'any F -> 0; any C -> 10; any B -> 18; else 25 (0 when none)',    10, 20),
  ('breach',      'pwned -> 0, clean -> 25',                                         10, 20);

-- One row per check that ran, already converted to points by the rubric.
CREATE TABLE privacy_checks (
  run_id    INTEGER NOT NULL,
  category  TEXT NOT NULL REFERENCES privacy_rubric (category),
  points    INTEGER NOT NULL CHECK (points BETWEEN 0 AND 25)
);
INSERT INTO privacy_checks (run_id, category, points) VALUES
  (1, 'fingerprint', 8),   -- 18 signals, 2 high-risk, 4 medium
  (1, 'password',    8),   -- score 4 but breached -> 25 * 0.32 floor
  (1, 'headers',     18),  -- grades A A B
  (1, 'breach',      25);  -- not pwned

-- Per-check status against the rubric floors (ok >= 20, warn >= 10).
SELECT c.category,
       c.points,
       CASE WHEN c.points >= r.floor_warn THEN 'ok'
            WHEN c.points >= r.floor_bad  THEN 'warn'
            ELSE 'bad' END AS status
FROM privacy_checks AS c
JOIN privacy_rubric AS r ON r.category = c.category
WHERE c.run_id = 1
ORDER BY c.rowid;

-- Overall: renormalize over the checks that ran and grade the letter.
SELECT sum(points)                    AS total,
       count(*) * 25                  AS max,
       round(sum(points) * 100.0 / (count(*) * 25)) AS percent,
       CASE
         WHEN count(*) = 0 THEN '—'
         WHEN round(sum(points) * 100.0 / (count(*) * 25)) >= 85 THEN 'A'
         WHEN round(sum(points) * 100.0 / (count(*) * 25)) >= 70 THEN 'B'
         WHEN round(sum(points) * 100.0 / (count(*) * 25)) >= 50 THEN 'C'
         ELSE 'D'
       END AS letter
FROM privacy_checks
WHERE run_id = 1;

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →