Methodology
The scores are the product this site sells, so the model is published rather than described: this page is rendered from methodology.json, the same file the scorer reads. The method cannot drift from the numbers, because there is only one copy of it.
Neither score is printed without the service class, which is what tells you which of the two answers the question you actually have.
Rank is not a stored value. It is a property of a list: each ranked page orders providers from the two scores and says which axis it sorted on. A privacy ranking leads on security, a streaming ranking on usability. Where the leading axis ties, the list falls back to the other score and then to the name, so the order is total and no two rows carry the same number. There is no rank field for anyone to nudge.
Eight independent risk channels, each asking one question of the published record. A channel answers with a probability between 0 and 1 — how likely it is that this particular route identifies the user — and the eight are multiplied, not added.
No channel is weighted by how important it feels. The weighting is in what each channel finds, and finding nothing leaves the score alone.
Each channel names the fields it reads, and every provider page shows the actual values it read, with sources and dates. The count below is how many of the 67 security fields feed each one; a field that answers more than one question is counted under each, which is why the counts sum to more than 67.
| Channel | The question it asks | Fields |
|---|---|---|
| Retention | Does a record exist that links traffic to a person, and who checked? | 13 |
| Jurisdiction | Can someone compel what exists, without the provider getting a say? | 5 |
| Disclosure | Has it already handed something over? | 6 |
| Integrity | Has it been caught saying one thing and doing another? | 17 |
| Architecture | Who operates the exit, and what does it do to the traffic? | 2 |
| Hygiene | What identifying material is collected in passing, and can the client be checked at all? | 12 |
| Ignorance | How much of this did nobody establish? | 6 |
| Silence | Ten years, millions of users and nothing on record? | 5 |
A channel does not read a field and produce a number by itself. Between the two sit the model's rules: 32 of them, each naming what it reads, which channel it answers to and what shape of arithmetic it uses. They are printed here in full because a rule a reader cannot see is a rule a reader has to take on trust.
Ten shapes cover all of them, and the shape is the honest summary of what a rule can do to a score:
capped_sum
Addends accumulate towards a ceiling they cannot pass.
constraint
An invariant the tables must satisfy. It prices nothing and is checked by selftest.py rather than evaluated per provider.
decay
A value scaled by the age of the evidence behind it.
derivation
Computes one field from others, so the fact is stored once.
flag
Publishes a marker for the reader and moves no score.
gate
Chooses which branch of the model applies, rather than computing a number.
max
The worst of several codings of one circumstance. They do not compound: one event written down twice is still one event.
noisy_or
Independent findings compound: 1 - product(1 - each).
product
Factors multiply, each scaling what the others established.
threshold
A test on the inputs that decides a band, or whether the rule fires.
Not all 32 price anything. Four carry the shape constraint, and three of those — R08, R22, R23 — evaluate against no provider at all: they are invariants the tables themselves must satisfy, checked when the contract is built rather than when a record is scored, which is why they name a scope instead of a field count.
The fourth, R29, does read a record, but to decide how a field may be coded rather than what the coding costs. One more, R15, is a flag: it publishes a marker for the reader and moves no number.
R01_bought_coverageintegritymaxreads 4 fields
Coverage that exists because it was paid for
max of: the (X08, X10) pair priced by params.bought_coverage, and — where M10 lists review_directory — X11 priced by params.review_directory; 0.000 when neither route fires
R02_cluster_contagionintegrityproductreads 4 fields
Risk imported from a sibling caught lying
min(params.cap, coupling x transfer x max over siblings s of R04_lie_group(s)); coupling is params.coupling read on M18_shared_infrastructure, falling back to M17_brand_role where the infrastructure is separate, unknown or names nothing in the table; transfer: 1.0 if finding date >= max(M16 of both) else 0.0; undated finding -> 0.0; siblings must be published records; never reads a sibling's own contagion
R03_owner_businessintegritymaxreads 1 field
Monetisation implied by what else the group sells
max over M10 categories; combined with X05 by max not noisy-OR (one circumstance, two codings)
R04_lie_groupintegritymaxreads 2 fields
The lie axis
max(X01, X02) — never noisy-OR: one event coded twice must not compound to CHANNEL_CAP; S19 = caught_lying if >0, unexamined if both unknown, clean otherwise
R05_exposuresilencethresholdreads 3 fields
Exposure band
pts = years operating scored by params.years_points + M08 by params.scale_points + params.stayed_logging_points when P04=stayed_logging; the band is the highest threshold in params.bands the total reaches, low otherwise; hand-written P10 is ignored
R06_ignoranceignoranceproductreads 5 fields
The band is read off the published score rather than stored beside it, so the word and the number cannot drift apart.
| Band | Score | What it means |
|---|---|---|
| Protection: high | 75–100 | The provider's key privacy claims are backed by evidence, and an independent audit has checked them. |
| Protection: medium | 55–74 | Most of what matters is confirmed and nothing on record rules the provider out, but some gaps remain. |
| Protection: below average | 35–54 | More is unconfirmed than confirmed. Nothing scandalous, but not enough to recommend. |
| Protection: low | 15–34 | What is known mostly counts against the provider, or almost nothing about it can be confirmed. |
| Not recommended | 0–14 | Ruled out: the provider was caught lying about what it does, or its app sends other people's traffic through its users' devices. |
Security is a gate, not a tradeable quantity. On a general ranking a high usability score cannot lift a provider above one with a better security score. The list sorts on security first and reaches for usability only between records security scores identically.
In the register as it stands, a provider scoring 60 on usability sits 25 places below one scoring 55 — and that is the correct order rather than a bug.
The model scores the state of the published evidence, not our opinion of a company. Three things about a value therefore matter as much as the value itself.
Every value carries its sources, and each source carries a level. The weights are the model's own:
| Level | Weight | What it is |
|---|---|---|
| A | 1.00 | The artefact itself — the policy, the report, the court record |
| B | 0.85 | The provider saying it somewhere accountable |
| C | 0.70 | A competent third party reporting it |
| D | 0.35 | Anything thinner than that |
Separately, each value records how it came to be there. document means a citation exists, and only those may be rendered as sourced claims; derived was computed from other fields by a rule on this page; asserted is a value with nothing behind it, which is how a field nobody established is stored.
There is no fourth grade: a value either stands on a document, was computed from values that do, or has nothing behind it at all.
The three curves in numbers:
| What ages | Counts in full for | Halves every | Never below |
|---|---|---|---|
| An audit or inspection | 12 months | 18 months | 5% |
| A claim about ongoing practice | 12 months | 60 months | 15% |
| A transparency figure | 12 months | 60 months | 35% |
The three curves differ because the things they describe change at different speeds. An auditor's snapshot goes stale fastest: it says what was true in one week of one year. A claim about ongoing practice and a transparency figure describe a standing state of affairs, so they hold their value far longer — and a transparency report keeps the highest floor of the three, because a company that once published its numbers has established something about itself that a quiet year does not undo.
A different shape entirely, because it answers a different kind of question: an additive weighted sum, where features add up and a missing one is a shortfall. Thirteen fields, twelve of them carrying weight, 34 points between them. The thirteenth is the yearly price: published because a reader wants it, weighted at nothing because a discount for paying twelve months in advance is a commercial term rather than a property of the service.
| Field | Weight | Re-checked |
|---|---|---|
| Works under active censorship | 5 | 30 days |
| Platforms with a client | 4 | 30 days |
| Countries with exit locations offered | 4 | 90 days |
| Monthly price USD, month-to-month plan, as charged | 3 | 30 days |
| Usable free tier | 3 | 30 days |
| Protocols offered | 3 | 30 days |
| Kill switch coverage | 3 | 30 days |
| Simultaneous connections | 2 | 30 days |
| Friction to start using it | 2 | 30 days |
| P2P allowed | 2 | 30 days |
| Major streaming services reachable | 2 | 30 days |
| Split tunneling available | 1 | 30 days |
| Yearly plan price USD, first term as charged | — | 30 days |
The result is averaged over the fields that carry a value, so a provider is not punished for a field nobody has filled in for anybody. Censorship circumvention carries the most weight because it is the one usability property that decides whether the service works at all in the places it matters most; split tunnelling carries the least because its absence is an inconvenience.
Price enters here, not on the security axis, and only the monthly rate does. Yearly rates are shown everywhere on the site but not scored: a discount for committing twelve months in advance is a commercial term, not a property of the service.
A score at 50% completeness is a different claim from the same score at 95%, so completeness ships with the score and the two are shown together. It is the share of fields that were established at all.
Alongside it, every record carries key gaps: analyst prose naming what was not established, what would settle it, and the caveats that qualify the number. It is where a reader learns that an assurance report is Type I rather than Type II, or that a fleet country was inferred from a routing note.
A high score with a long list of gaps is not a contradiction: the score says what the evidence supports, the gaps say how much evidence there was. Neither half is hidden to make the other read better.
Where a provider publishes nothing, the field stays unknown. It is never estimated, never inferred from a competitor, never quietly filled with a marketing number, and never guessed either way — the ignorance channel is where that costs the score, which is the honest place for it to cost something. In a table an unestablished value renders as — and sorts last in both directions: sorting by fleet size ascending does not reward a provider for having refused to tell us.
Two axes, two floors, and they are set at different heights on purpose. On security the model withholds a verdict when under 30% of the substantive fields were established at all, or when — below 50% established and under 35 points — the dominant risk is our own ignorance. Neither is a statement about the provider: it says the research did not get far enough to place it, and 9 of 77 records are.
On usability the floor is higher — the score has to rest on 50% of the available weight, not 30% — and it is higher because the two axes charge for a blank differently. Security prices ignorance inside the score, so a thin record already carries what it costs.
Usability has no such channel: an unestablished feature simply leaves the average, so without a floor a record with two known fields would read like a measured one. 15 of 77 records publish usability.state: no_data, and the number they carry is a lower bound rather than a measurement — it is never printed beside a known one as though the two were comparable.
Six limits, published with the model rather than discovered later. They are part of methodology.json and travel with every score it produces, which is why they are printed here word for word rather than paraphrased:
expires_at before quoting a price.key_gaps is where it has to say so.V15_assurance_strength reads unknown and every audited provider is credited at the market norm rather than at what its own report says. The field records the declared strength, not the rigour behind it — an engagement can carry a reasonable-assurance opinion and still be narrow, which is what V03_audit_subject and V04_scope_servers are for.There is no editorial adjustment. An earlier version of this method allowed an editor to move a computed score by up to two points with a published reason; it has been removed, because the breakdown on every provider page now shows the arithmetic in full, and a number that did not come out of that arithmetic would make the breakdown a lie.
Editorial judgement has one place to live, and it is not the score: a manual quality tier, kept separate and never mixed in. If an editor believes a record is wrong, the route is the same one open to any reader — change the evidence, and let the model recompute.
Scores are recalculated on every import and on demand. Because the model version applies to every record at once, a change to it moves the whole register rather than one row — which is what should happen, and why every change is logged in public. A provider's updated date moves only when something material changed; a re-import that changes nothing leaves every date alone, because stamping 77 pages with today's date would be a freshness signal we had not earned.
What it can buy is a commission when somebody subscribes through a link, and — if paid placement is ever sold — a labelled block of its own above the ranking, outside the order. Neither is switched on today — no link carries an affiliate parameter and no placement has been sold — and both are disclosed where they appear and in the affiliate disclosure. Because the ranking is computed from evidence and the evidence is published beside it, buying a better position would require changing the published record — which is exactly the thing anybody can check.
The price of what nobody established
min(params.cap, params.slope x (1 - known_share)) x (1 - params.posture_relief x posture); posture = sum of posture: entries capped at 1.0
R07_silencesilencethresholdreads 4 fields
Silence in proportion to exposure
fires only when P01 and P03 in {none_known, unknown} and P05 in {none, unknown, fresh_no_numbers}; risk = min(params.cap, params.per_year x years operating x weight), the weight taken from params.weight by exposure band. Priced by the year because silence accumulates: fifteen years with nothing on the record is not the same claim as five, and a flat band said it was. A provider whose launch year is unknown charges nothing here, per R08
R08_unknown_pricing6 channelsconstraintevery risk and floor table in the schema
Presumption of innocence as an arithmetic rule
applies to findings against the provider only, and never to an unknown written as a published channel prior (C01 = prior_0.550), which is a base rate and not a finding. Otherwise risk(unknown) <= 0.50 x risk(worst confirmed value) for that field and never equal to it; a caught lie always outranks a blank; on the lie axis and every event field risk(unknown) = 0.000 outright. The full price of a blank is paid once, in ignorance, where it is labelled as ours
R09_channel_combination8 channelsnoisy_orreads 8 fields
How the eight channels become one number
score = 100 x product(1 - min(0.90, r_c)) over the eight channels; no blanket floor or ceiling; S18 enters inside integrity, not as a ninth channel
R10_disclosure_decaydisclosuredecaymaxreads 4 fields
Adverse events age too
disclosure = max over P01, P02 and P03 of that field's own price after decay — one route taken at its worst, never compounded, because three codings of one seizure are one seizure; decay(plateau=12, half_life=60, floor=0.35) on the date of the P12_case_history entry for the same episode, matched by what the entry says happened — P01 to a seizure, P03 to a court_order, subpoena or mandate_order — and never by how it came out, since an episode that produced nothing is still the episode that dates the finding; P02 is matched on outcome because there the outcome is the fact; an adverse event with no such entry keeps its undecayed value; the practice curve shape with a higher floor, 0.35 here against 0.15 for practice evidence, because a proven disclosure stays permanently on the record
R11_evidence_voidingretentiondisclosureintegritygatereads 1 field
A change of control resets what transfers
evidence dated before M16 does not attach to the current owner: audits lose the series bonus, disclosure events drop to the R10 floor, sibling findings do not transfer at all
R12_report_plausibilityintegrityignorancethresholdreads 5 fields
A transparency report is worth its content
P06 = zero_implausible when P09 = 0 and P08 is above params.min_requests and the record establishes that a per-person record exists to disclose — retention severity at or above params.min_retention. Judging it by user scale alone punished the opposite of what it was for: a provider that publishes its numbers and reports none granted was called a liar, while one that publishes nothing paid nothing. Zero granted is only incredible against a provider whose own record says it holds something to grant; against an established no-logs finding it is the expected answer, and the model must not disbelieve in one channel what it credited in another. When it does fire, posture relief from P05 is set to 0.00 and integrity gains the route in params.route
R13_derived_jurisdictionjurisdictionnoisy_ormaxreads 6 fields
Mandate fields are derived not judged
C10 = M06 in MANDATE_COUNTRIES; C11 = M11 in MANDATE_COUNTRIES; when M11 = M06 the two are one circumstance and jurisdiction takes max(C10, C11, P11), never noisy-OR; fleet exposure enters as max(C09b, P04), which is a separate route from the company one; a hand-written override requires its own source and is published as such
R14_disclosure_ratedisclosurethresholdreads 2 fields
The share of requests that produced data
rate = P09 / P08 once P08 reaches params.min_requests; risk = params.weight x rate; published beside the rate because cross-jurisdiction comparability is low — a request means a court order in one country and a letter in another
R15_free_tier_flagno channelflagreads 2 fields
Free tiers are paid for somehow
S22 = flagged when every field named in params carries one of the values params lists for it, none otherwise; changes no score on either axis — both inputs are already priced where they belong, and pricing their conjunction would be the averaging the two axes exist to refuse
R16_opaque_at_mass_scaleintegritythresholdreads 2 fields
Opacity is worse the more people it covers
X03 = opaque and M08 = mass -> params.at_mass_scale instead of X03's own price for opaque
R17_location_noticejurisdictionderivationreads 3 fields
Where a mandate country is offered, what is actually there
C09 = U02 countries that appear in MANDATE_COUNTRIES, derived and never hand-filled. C09 alone charges nothing and stays out of the completeness denominator: offering an exit in such a country says nothing on its own, and it is published against the location a reader picks. What is charged is C09b, the one question worth asking once C09 is non-empty — whether hardware actually sits under that mandate or the location is virtual with the hardware elsewhere. C09b is n/a when C09 is empty, and combines with P04 by max: presence under a mandate is one circumstance, coded twice
R18_audit_gateretentiongatemaxreads 2 fields
Which retention branch an audit takes
V11 states retention -> stated branch at params.credence_stated; V01 = yes_* and V11 silent -> silent branch at params.credence_silent x subject_factor (params.subject_default where the subject is not established), and no branch exceeds params.credence_max; otherwise no paper evidence at all; severity on the chosen branch = max(C01_linkable_retention, V11_audit_findings), never noisy-OR — one circumstance coded twice must not compound (as R04)
R19_audit_decayretentiondecayreads 1 field
Configuration churns
decay(params.decay) — continuous in months, no knots
R20_practice_agesretentiondecaymaxreads 1 field
Every documented event carries its own date
each event in P12 with outcome = nothing_produced contributes decay(practice, its own date); the field's practice value is the max over its events, never their sum; replaces the single-date reading of P01 and P03, which collapsed several seizures into one
R21_circumvention_decayusabilitydecayreads 1 field
Blocking moves faster than evidence
U06 = proven scores as claimed once the field's own as-of date is more than 12 months old; the record already dates every field, so the age is read from there rather than written into the value; the only usability field with a decay, because it is the only one whose truth expires
R22_completenessignoranceconstraintthe completeness column of every field
What the denominator counts
substantive fields with completeness = yes; n/a leaves the denominator, unknown stays in it; identity fields, model outputs, redundant labels and usability fields are all out — usability coverage is reported separately as S16
R23_credence_defaultsretentionconstraintevery factor table in the schema
Unread evidence is not credited
the mirror of R08 and deliberately not symmetric with it. factor(unknown) <= the weakest genuine evidentiary tier in that field, and strictly above any value encoding a refusal to disclose (V06 unnamed, V02 none). Crediting an audit nobody read at face value is how a purchased report launders into a score; charging our own ignorance as if it were the provider''s refusal is the opposite error. Declining to credit unverified evidence is not an accusation — the provider falls back to prior, the market base rate, not to a finding
R24_retention_compositionretentionproductmaxreads 14 fields
How the retention sub-channels become one number
the four sub-channels do not average. credence.paper = the branch R18 chooses (stated: credence_stated; silent: credence_silent x subject_factor) x source_credence of that branch's own .conf x audit_decay (R19) x publication_factor x engagement_factor (firm x standard x assurance strength) x scope_factor on the stated branch x series_bonus when R11 leaves the series standing, capped at credence_max. credence.practice = max over dated nothing_produced events of practice_credence x practice_decay (R20). credence = min(credence_max, max(paper, practice) + secondary_weight x min(paper, practice)) — two kinds of evidence beat one, and no amount of evidence reaches certainty. severity = max(C01, V11) per R18, or prior when neither is established. retention = credence x severity + (1 - credence) x max(severity, prior): regression to the market base rate is upward-only, so an admission against interest keeps its face value. retention.floor = max(retention, C12 floor:) last, because an audit scoped to the tunnel cannot clear a fact in the app
R25_integrity_compositionintegritynoisy_orreads 14 fields
How the integrity routes become one number
integrity = 1 - product(1 - route) over the routes that fire: the lie axis (R04), owner transparency (R16 at mass scale), owner group history, monetisation combined with what the group sells (R03), incident handling, absolute claims, lifetime push, bought coverage (R01), the implausible-report route (R12), the store-declaration gap (R28), disclosure_rate_weight x rate (R14) and cluster contagion (R02, S18). Routes compound because they are separate findings; the pairs that are one circumstance coded twice were already collapsed by max inside their own rule, which is why nothing is collapsed again here
R26_hygiene_compositionhygienecapped_sumreads 12 fields
How the hygiene fields become one number
hygiene = min(params.cap, sum of the risk: price of each field routed here). The one additive channel on the security axis: these are small independent leaks accumulating, not one finding deciding an outcome, and the cap is what keeps a pile of minor collection from reading like a disclosure. A list field is worth its cheapest member — one anonymous payment method is enough — and falls back to its own unknown price when no member is priced. C13_weakest_protocol is a derived summand here (R32): a live legacy transport is one more thing collected in passing, not a finding that decides an outcome
R27_report_concealmentintegritymaxreads 2 fields
Silence about disclosure at a scale that guarantees requests
a provider at mid or mass scale certainly receives requests, so an established absence of numbers is a fact about the provider rather than a gap in our research: P05 = none charges 0.150, fresh_no_numbers 0.100 — a published report that omits the one number that matters is the sharpest form of it — and stale 0.050. Fires only on an established value; unknown charges nothing here and is priced in ignorance, where our own not having looked belongs. The mirror of R12: one prices an incredible number, this one prices the absence of any number
R28_store_declaration_gapintegritymaxreads 1 field
The store declaration against the policy the provider gave the store
the mandatory store form is the provider's own signed statement about its app, so anything the form declares must also appear in the policy the provider itself points the store to. Read in one direction only: the app is a subset of the service, so a form that declares less than the policy admits is explained by scope and charges nothing, while a category the form declares and the policy never mentions has no such excuse. Graded by what the undisclosed category reveals: an identifier or a diagnostic charges 0.150, behaviour — app activity, installed apps, location, or any advertising purpose — charges 0.300, and a declaration of the very collection a no-logs claim denies charges 0.450. The two stores define collection differently, so a difference between the Apple form and the Google form is not itself a finding. Worst gap across the stores wins
R29_session_stateretentionconstraintreads 2 fields
The connection is not a record of the connection
C01 grades what a provider can still link to a person once the session is over. State that exists only while the tunnel is up — a source IP, an account id and a connection timestamp held so the server can route packets and enforce the device limit — is the connection itself, not a record of it, and pricing it as retention charges a provider for describing how a VPN works. Worse, it charges more than saying nothing: the blank on this field is the market prior 0.550 and source_ip is 0.750, so the honest description of a fifteen-minute buffer cost more than silence. The carve-out is narrow, and has to be, or it becomes the sentence every provider writes. It applies only where the provider's own document states a deletion window tied to the end of the session and no longer than 24 hours — the shortest calendar unit, longer than any teardown a service needs and shorter than any rotation a log keeps. Undeclared duration is retention. A calendar period — 7 days, 30 days, a rotation cycle — is retention however it is worded, because it outlives the session by design. Whatever the provider keeps past the window is still worth its own tier, and the carve-out reads the provider's claim only: where an audit found the data present, R18 already puts the finding above the claim
R30_usability_foundationusabilitythresholdthe weight column of every usability field
How much of the table the usability score rests on
the usability sum divides by the weight it could read: a field nobody established leaves the denominator instead of scoring zero, because coverage is not quality. The cost is that the score cannot see its own foundation - a column whose heaviest field is unread produces the same shape of number as a filled one. S21 = weight read / weight live, where live is every weighted usability field less those that are n/a. Below usability_foundation_floor S20 = no_data: a number resting on less than half the table states which fields were filled, not what the product does. The floor is stricter than the security one because this axis has no ignorance channel - security charges for a blank inside the score and usability charges for it nowhere. The score is still published under no_data, exactly as the security score is; a number withheld cannot be checked.
R32_protocol_floorhygienederivationmaxreads 1 field
The weakest transport still on offer
C13_weakest_protocol is the worst protocol in U07_protocols by the risk order in C13's own table, derived at load time and never hand-filled — the same shape as R17 deriving C09 from U02. It enters R26_hygiene_composition as one more summand and is bound by the hygiene channel cap like every term there. On a fleet that offers only modern transports the field is not_applicable rather than a name: with no protocol pricing above 0.000 there is nothing weak on offer to point at, and picking the least-bad of the good ones by tie-break order would publish a finding nobody made. The field is carried for the cheap segment where PPTP and L2TP are still live. The proprietary price is not a charge for a vendor writing its own protocol — it is the price of not being able to tell whether that protocol is weak, which is why vendor_open costs nothing: a vendor transport whose source is published and independently reviewed can be assessed, and nothing in the assessment says it is weak. Charging it anyway would price an ignorance that has been resolved, and would make publishing the source dearer than withholding it.
R33_exit_conductarchitecturemaxreads 2 fields
What the exit does to the traffic it carries
architecture = max(price of C00_architecture, price of C14_traffic_modification). Who runs the exit and what the exit does to what passes through it are one question — whether the far end of the tunnel is on your side — and one bad answer decides it, so the channel takes the worse of the two prices and never their sum: an exit run by strangers that also rewrites your headers is not twice as bad as either, it is that bad. headers_injected (0.300) is a session identifier or any other header added to traffic passing through, which hands every destination a name for the user; content_injected (0.500) is scripts, advertising or other material placed into pages; tls_interception (0.750) is the exit opening encrypted sessions. none has to be read off a document that says so, which few do, so unknown carries the same market prior as C00 and the ignorance channel does the rest.
verdict: no_data is what says so out loud. Read completeness on both axes before reading either score.M14_inclusion_basis is the only record of why each one is here. A provider absent from the catalogue is evidence about that hand-picking before it is evidence about the provider, and nothing here estimates how much it misses.Three
This is what multiplying buys. Seven channels can be immaculate and the eighth still settles the record — which is why a provider cannot average away a disqualifying fact by being tidy everywhere else. Move the control.
Seven channels holding 0.05 each, and one — the red one — the reader moves
Nothing was added up and nothing was averaged. The seven tidy channels are still tidy at the far end of that control — and they cannot buy back what the eighth took, which is the whole reason the eight are multiplied.
Four
No channel may pass 0.9, because certainty is not available from reading documents. And one finding pins a channel from below, where no audit can reach it.
The retention channel
A flawless report empties the glass. What stays in it is the identifier the provider holds:
A report can only say what was written down. An identifier says the user is nameable whether anything was written down or not, so the two are not answers to the same question — and the model refuses to let the first one settle the second.
Five
Nothing enters this model at face value. What the report says and who says it are two separate ladders, and they multiply.
What the report saysretention credence_stated against credence_silent
Who says itthe four tiers of source_credence
The two multiply. The four levels of who says it, and what each one is:
One
They are drawn here in the proportion the register draws them in, because that proportion is the argument: one of the two decides the order, and the other describes what you get for it.
Security asks 8 questions
Every one of the 67 security fields feeds at least one of them. The eight answers are multiplied.
Decides the order
Describes what you get
Usability weighs 12 fields
Weights sum to 34, and the twelve are added as a weighted mean. A thirteenth is carried at weight zero, so it is published and priced by nothing.
Two
Nothing is added up. Each channel keeps the share of the record the one before it left standing, so the eight are a chain rather than a column of figures.
score = 100 × ∏ (1 − channel)
The shape is a noisy-OR over independent risk channels. Worked here on the record of Proton VPN, the highest score on file — the numbers below are that record's, not an example written for the occasion.
Three channels find nothing and take nothing. The other five take a small share each, and the shares compound rather than cancel: 70 is what is left of the hundred.
Nine
Every VPN here gets one integer out of a hundred, and the model cuts that scale at four floors it publishes in advance. Cross a floor and the word changes. Nothing else moves it — not a nicer logo, not a discount, not a press release.
Bands are ranges, fixed before a single record is scored and printed so you can check every crossing yourself — the number is computed, the word is read off it, and neither can be bought.
Eight
Every line in the fan is a rule naming the channel it answers to. All of them are printed in full further down this page, because a rule a reader cannot see is a rule taken on trust.
The left fan is every rule reaching for the fields it reads; the right one is every rule naming the channel it answers to. All 32 are printed further down this page in full, because a rule a reader cannot see is a rule taken on trust. The machine is not large because it is clever — it is large because the questions are, and a model small enough to summarise in a paragraph would be summarising the wrong thing.
Six
Three kinds of evidence, three curves, each holding flat for a plateau and then falling to a floor it never leaves. An audit is a thing that happened on a date, not a state a provider is in.
Up the side: the weight the evidence still carries — full at the top, its own floor at the bottom
today1 yr23456 yrs
Every curve holds flat for a plateau and then falls to a floor it never leaves — evidence goes stale, it does not become a lie. The dots are the 30 records on file that publish a dated audit, placed on the audit curve at their own age. An audit is not a state a provider is in; it is a thing that happened on a date.
Seven
The one channel that prices a blank. It is also the only thing on this site a provider can move by itself — and the way to move it is to publish, not to ask.
0.00charged to the record
min(0.6, 0.9 × (1 − established)) × (1 − 0.4 × posture)
Not knowing is not neutral. A provider nobody has established anything about carries real risk, and the model prices it rather than leaving a polite blank — which makes this the one number on the whole site a provider moves by itself. Every other channel waits for something to be found; this one waits for something to be published.