Skip to content

Legal pages: eight promises pinned to the code, seven of them corrected - #372

Merged
Apolloccrypt merged 10 commits into
mainfrom
fix/legal-texts-match-practice
Sep 3, 2026
Merged

Legal pages: eight promises pinned to the code, seven of them corrected#372
Apolloccrypt merged 10 commits into
mainfrom
fix/legal-texts-match-practice

Conversation

@Apolloccrypt

@Apolloccrypt Apolloccrypt commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Read the legal pages against the code: /privacy, /dpa, /terms, /license, and the retention and sub-processor claims on /security and /parasend. Sources: relay/relay.js, relay/lib/tiers.js, relay/envelope.js, relay/lib/ct-hash.js, relay/lib/mollie.js, relay/lib/billing-recurring.js, admin/server.js, docker-compose.yml, deploy/nginx-*.conf, LICENSE, SECURITY.md.

Fourteen rows in docs/site-claims.md (23 to 36), all pinned in tests/site-claims.test.mjs, each one verified by sabotaging both the source and the page and watching the block go red.

What was wrong

Page Said The code says Source
license, terms Converts to MIT on 1 January 2030 Apache License 2.0 on 2029-01-01 LICENSE:5-6, deploy/LICENSE:5-6
license, terms The licence permits non-commercial use only It grants production use, commercial included, up to 5 active API keys and one self-hosted deployment LICENSE:8-18
deploy/LICENSE No Additional Use Grant at all, while its Terms refer to one "above" The grant is the operative sentence a self-hoster relies on LICENSE:8-18 vs deploy/LICENSE:6-8 before this
license (four head copies) "Free for personal use" in the description, og, twitter and JSON-LD The grant gives production use, commercial included; seo-contract pins the four to each other, so they understated it together LICENSE:8-18
privacy (a row this PR wrote) "The audit log and the edge access log are capped by volume, not by time" The audit trail is trimmed by age as well as by count, 400 days by default, and it stores a /16-masked address, not a client IP admin/lib/audit.js:10,14-20,35-42
pricing "NEN 7510, eIDAS, and IEC 62443 mappings ship with Pro and Enterprise" Two of the three mappings are written and served publicly; the false half is the paid-tier framing, not the existence. eIDAS is the one with no mapping docs/ot-guide.md:221, docs/dicom-guide.md:11-17,190-198
press "Blobs are destroyed on download, not on a timer" Every tier carries a view_ttl_ms: 1 hour, 24 hours, 7 days, 7 days relay/lib/tiers.js:49,58,67,77
parasend Signed DPA listed as an Enterprise feature POST /v2/sign-dpa asks nobody for a plan. Found by the sweep #382 prompted, in a list three rounds had missed relay/relay.js:3585-3620
license The box did not reproduce LICENSE; nothing kept it honest deploy/LICENSE and the box are now the file word for word, em-dashes included LICENSE:8-18
license Licensor "Mick Beer", Licensed Work "Ghost Pipe Protocol, Relay and Dashboard" "PARAMANT / Mick Beer" and "PARAMANT Ghost Pipe" LICENSE:3-4
privacy Every chunk is destroyed after the first download Community 1 read, Pro 10, Business 25, Enterprise 100 relay/lib/tiers.js max_views
privacy, terms 1 hour / 24 hours / 7 days for Community, Pro, Enterprise Business exists and shares the 7 day ceiling relay/lib/tiers.js view_ttl_ms
dpa Two sub-processors: Hetzner and Resend The server also calls api.mollie.com relay/lib/mollie.js:12
dpa Mollie receives an email address and the plan bought Amount, description, and metadata{accountId, product, plan, interval}. No email while the recurring layer is off relay/relay.js:5439-5445, relay/lib/billing-recurring.js:123
dpa ParaSign capsules "may persist until envelope expiry" 30 days by default, 365 at most relay/envelope.js:30-31
privacy, terms Billing is not yet live, plans are arranged by hand, by e-mail Checkout runs through Mollie today, as a one-off payment; subscriptions stay off while BILLING_MODE is unset relay/relay.js:5406,5439, relay/lib/mollie.js:45-55
privacy, pricing, audit-log-export The DPA is for Pro and Enterprise, or for paid tiers, or an Enterprise line item POST /v2/sign-dpa is public and checks a name, an organisation, an email and a rate limit relay/relay.js:187,195,3585-3620
audit-log-export "Relay does not process personal data (holds only ciphertext)" The opposite of the position the whole of /dpa takes frontend/dpa.html throughout
press, architecture "No US entity in the chain" Resend Inc. is US, under SCCs, and the signed DPA table says so frontend/dpa.html:264,271
sign, co-sign "Not eIDAS-qualified", and nothing about the level it does reach /about and /parasign name a Simple Electronic Signature frontend/about.html:254, frontend/parasign.html:212
privacy An IP is "processed only transiently" The edge writes an access log full of client addresses, and a script in this repository reads it. The nginx config here logs nothing, which is why the sentence survived every review scripts/access-log-visitors.mjs
privacy Capsule kept "until its expiry" 30 days by default, 365 at most relay/envelope.js:30-31
privacy Nothing about delivery receipts Held 15 minutes in Redis relay/relay.js:1727
privacy CT log hashed with SHA-256 SHA3-256 throughout, as /dpa already said relay/lib/ct-hash.js
privacy Browser storage: ps_free_uses for a "10/day limit", pm_docs_key Neither string exists in the repository. The limit is 10 a month. Five keys the frontend does write were unlisted frontend/js/parashare.page.js, js/status.inline1.js, sign-flow.js, js/dashboard.js
privacy "Last updated: July 21, 2026", on a page this PR rewrites Bumped to 3 September 2026
security "Access logging is switched off" True for the hosted config, false for the self-host config, whose log_format starts with $remote_addr deploy/nginx-selfhost.conf:37,45,102
dpa, SECURITY.md The same audit quoted in two files with nothing keeping them equal 114 checks, 49 auditd rules, AIDE daily, AppArmor enforcing SECURITY.md:42,44,50,54,55
README Hetzner Frankfurt The DPA and /privacy say Nuremberg NBG1 frontend/dpa.html:225,263,270

One code comment as well: deploy/nginx-paramant-live.conf called Bunny.net "the edge". The A record points straight at this machine, so it is DNS and nothing else.

Tests

Blocks 23 to 35 in tests/site-claims.test.mjs, in function scope, node builtins only, in the root integration job. Block 5 was extended to cover Business and /terms. Block 23 now compares the Additional Use Grant, the Licensor and the Licensed Work word for word across LICENSE, deploy/LICENSE and the box on /license, not only the Change Date and the Change License. Block 25 also forbids the "No US entity" denial while the DPA table names a US row. Block 26 now pins the envelope retention on /dpa as well.

Block 31 calls mollie.billingStance() rather than pattern-matching it, so the stance the pages describe is asserted against the function that decides it.

Sabotage matrix, every mutation applied and reverted, source side and page side for each new pin:

Sabotage Result
LICENSE Change Date 2029 to 2028 block 23 red
LICENSE grant: 5 API keys to 6 block 23 red
deploy/LICENSE Licensed Work renamed block 23 red
license.html box: "a single self-hosted deployment" to "two" block 23 red
terms.html back to "non-commercial" block 23 red
tiers.js community max_views 1 to 2 block 24 red
delete the Mollie row from the /dpa table block 25 red
press.html back to "No US entity in the chain" block 25 red
/dpa Resend row from US to EU block 25 red
envelope.js DEFAULT_TTL_DAYS 30 to 31 blocks 26 red (privacy and dpa)
/dpa capsule row back to "may persist until envelope expiry" block 26 red
relay.js RECEIPT_TTL_MS 15 to 20 minutes block 26 red
ct-hash.js sha3-256 to sha256 block 27 red
remove one <code> key from the /privacy list block 28 red
bump a storage key in js/dashboard.js block 28 red
drop $remote_addr from the self-host log format block 29 red
README back to Frankfurt block 30 red
relay.js metadata key plan to tier block 31 red
relay.js adds an email field to the checkout payload block 31 red
mollie.js recurring true by default block 31 red
/dpa Mollie column back to the email claim block 31 red
/terms back to "billing is not yet live" block 31 red
/v2/sign-dpa handler gated on !keyData block 32 red
/privacy back to "For Pro and Enterprise customers" block 32 red
/audit-log-export back to "relay does not process personal data" block 32 red
SECURITY.md auditd 49 to 48 block 33 red
/dpa 114 checks to 113 block 33 red
sign.html drops the SES sentence block 34 red
a fifth page gains the eIDAS disclaimer without naming the level block 34 red
/privacy drops the log section block 35 red
/privacy back to "processed only transiently" block 35 red
the access-log reader points at another file block 35 red
maskIpForLog renamed in admin/lib/log-redact.js block 35 red
/privacy claims raw admin log lines again block 35 red
audit retention 400 to 200 days block 35 red
the audit age trim removed block 35 red
the audit /16 mask returns a full address block 35 red
/privacy back to volume-only for the audit log block 35 red
the IEC 62443 mapping section removed block 36 red
the NEN 7510 rows removed block 36 red
an eIDAS mapping appears in docs/ block 36 red
/pricing gates the mappings again block 36 red
/press denies the timer again block 24 red
/press keeps a stale ceiling block 24 red
pro view_ttl_ms changed blocks 5 and 24 red
the licence box drops the MariaDB clause block 23 red
the licence box drops the Covenants section block 23 red
the licence box gains a line LICENSE lacks block 23 red
a shared paragraph reworded in LICENSE block 23 red
the DPA bullet back on /index block 32 red
the DPA bullet back on /pricing or /parasend block 32 red
the homepage "applies to every plan" sentence deleted block 32 red

Full battery on this branch, rebased on origin/main at #369: tests/static-sanity.sh eleven checks pass, scripts/check-test-declarations.sh 114 suites clean, root integration suites 194 of 197 with 2 skips, relay/test/pricing-page.test.js green, eslint clean, cache-bust and csp-inline clean. The one failure is tests/heartbeat-lib.test.mjs, which cannot resolve @noble/post-quantum in this environment; it fails the same way on origin/main before any change here.

Round three, what the reviewer caught

Four of the five were pages this pull request had already touched, which is the uncomfortable part: a row it wrote itself said the audit log was capped by volume and not by time, and admin/lib/audit.js trims by age too. Understating a retention is not carefulness, it is being wrong in the flattering direction. All five are corrected and pinned, and one of the pins found a fifth page nobody had looked at.

Left alone on purpose: /parasend lists "IEC 62443 / NIS2 / NEN 7510 documentation as input for your own compliance process, not third-party certification" in its Enterprise card. That sentence is true, carries its own caveat, and is pinned verbatim by relay/test/pricing-page.test.js:704, so it stays as it is. The fifteen pages calling burn-on-read universal are still a batch of their own; only the outright denial of the timer on /press is fixed here, because a denial can be swept in one line and a rewrite of fifteen pages cannot.

One block that changed under us

Block 35 originally had two halves: the edge access log, and three lines in admin/server.js that wrote a full client IP with one of them carrying the account email. #374 landed while this branch was open and masked all three at the call site, so on the merge commit the admin count was zero and CI was right to go red: /privacy was describing a system that no longer exists.

The page now says what the code does. An address is truncated to its network before it is written and an email keeps one character and its domain, so the container log holds neither in full. The admin entry stays on the page as contrast, not as the finding.

The block keeps only what this pull request adds: the edge access log, pinned to scripts/access-log-visitors.mjs. The admin claim belongs to row 9 and admin/test/log-redact.test.js, which pin it at the source; a second, weaker copy here would only rot again. What is left of that half is a guard, that /privacy may not go back to describing raw lines and that the masking it describes still exists.

One note on the style guard

LICENSE is unchanged from main, down to the two em-dashes in the Additional Use Grant. It decides what anyone may do with this software, so rewriting it to satisfy a punctuation rule is a decision for the licensor and not for a script in scripts/. An earlier commit on this branch did exactly that and has been reverted.

scripts/check-commit-style.sh carries the exception instead, and only for rule 1. LICENSE and deploy/LICENSE are exempt on path. On /license the exempt region is the block between LICENCE-VERBATIM-START and LICENCE-VERBATIM-END, applied per line number, so a dash added anywhere else on that page still fails. Emoji and AI attribution stay forbidden everywhere including the licence text, and a commit message with a dash is still refused even when it edits the licence. All three of those were checked by trying them.

The exemption buys freedom from the punctuation rule and none at all from the test: block 23 still compares the Additional Use Grant, the Licensor and the Licensed Work word for word across LICENSE, deploy/LICENSE and the box.

Out of scope, next batch

Fifteen pages state burn-on-read as a universal property of the service: index, parasend, parashare, ontvang, press, docs, architecture, security, pricing, privacy, vs, audit-log-export and the three help pages. tiers.js gives Pro 10 reads per link, Business 25 and Enterprise 100, and /pricing sells exactly that. Row 24 settles the paragraph on /privacy; the rest still say it flat. That is one sweep over fifteen pages rather than a legal-text correction, so it gets its own pull request. /press:266 "not on a timer" belongs to that batch too.

Decisions for you, not for a test

The first version of this list had twenty items and nine of them were not decisions at all: they were facts the code already settled, or contradictions inside this repository. Those are fixed above and pinned. Twelve remain, and each one carries the text that is live today as its default. Nothing waits on you; if you never answer, the default stands.

Processor agreement template

  1. Governing law is split. /dpa says German law and the German courts, /terms says Dutch law and the Dutch courts, same company. Default in force: both texts as written.
  2. Dates and versions do not line up. /dpa is "effective 1 January 2025" and the signature record writes version: '2025-01-01' (frontend/js/dpa.inline1.js:28); /terms is version 1 of 25 August 2026. Default in force: both as written, and the signature record keeps stamping 2025-01-01.
  3. Deletion within 30 days versus a CT log with no delete path. /dpa promises deletion of all personal data within 30 days after termination and adds that the CT log may be retained. Pruning is FIFO at 10,000 entries (relay/lib/ct-window.js:55) and file rotation at 100 MB keeping one generation (relay/relay.js:341). Default in force: the sentence as written, with the CT log carve-out.
  4. Bunny.net in the signed table, or not. It hosts DNS and answers the lookup; no page or file passes through it. Default in force: named on /privacy, absent from the /dpa table.
  5. The 14 day notice. /dpa promises 14 days notice before a sub-processor change. Adding the Mollie row is a change to that list on paper, even though the code has called Mollie all along. Default in force: the row is added and no notice was sent.
  6. The article 32 host row. auditd with 49 CIS L2 rules, AIDE, AppArmor and a 114 check CIS benchmark describe the host. Block 33 now makes /dpa and SECURITY.md quote the same figures, and that is all it does: nothing in this repository verifies the host is in that state. Default in force: the row stays, equal to SECURITY.md.

Cookie text

  1. Is a separate cookie statement required. There is no cookie banner and no cookie page. /privacy and /rules say one strictly necessary session cookie and no trackers, and that matches the code: admin/server.js sets paramant_user_session and nothing else. Default in force: no cookie page.
  2. Which section owns the storage list. The browser-storage list is complete and correct, but localStorage is not a cookie and the page keeps them in separate sections. Default in force: the list stays where it is. Relevant only if a cookie statement lands.

eIDAS beyond SES

  1. QES via a QTSP partner. /pricing:559 says "QES is coming via an EU QTSP partner". No QTSP is named anywhere in the repository. Default in force: the sentence stays, undated.
  2. The norm mappings, settled and no longer a decision. The first version of this list said the mappings ship with Pro and Enterprise and the second said nothing in the tree backs them. Both were wrong. docs/ot-guide.md:221 is an IEC 62443 requirement table and docs/dicom-guide.md:11-17,190-198 a NEN 7510 table, and both are served from frontend/docs/ where a Community account reads them for nothing. What was false is the paid-tier framing. eIDAS is the one with no mapping document. Now row 36 and pinned in three directions, so there is nothing here left for you to decide.

Operator calls, not legal ones

  1. The :8090 block. Overtaken by Admin logs: no full client IP, no plaintext address, and the :8090 gateway written down #374, which gave it access_log off in the repo conf and wrote the open question up in full in docs/site-claims.md: location /dicom/ reaches a fly.dev host through it, with resolver 8.8.8.8, and neither party is on a sub-processor list. Read that row, not this line. Default in force: the route stays.
  2. Stripe in deploy/paramant-admin.py. SECURITY.md calls it an operator-configured legacy path. It is on no sub-processor list. Default in force: the client stays and the list stays as it is.

Coordination

Rebased twice more, on #375 and then on #374, #376, #377 and #378. #374 is the one that mattered: it changed the code half of block 35 out from under it, which is written up above. Nothing else on this branch overlapped.

Coordination (earlier)

Rebased on origin/main after #369 merged. The two files both branches touched are resolved: the "Burned on read" row in docs/site-claims.md keeps this PR's note with #369's page name rules, and the Jurisdiction table in frontend/security.html keeps #369's "exact 5 MB for the ParaSend web app" next to this PR's self-host access-log sentence.

Apolloccrypt and others added 9 commits September 3, 2026 03:18
The pass covered /privacy, /dpa, /terms, /license and the retention and
sub-processor claims on /security, read against relay.js, tiers.js,
envelope.js, ct-hash.js, the deploy configuration and LICENSE.

What was wrong:

LICENSE grants a conversion to the Apache License 2.0 on 2029-01-01.
/license said MIT on 1 January 2030 in its prose, in its licence box and
in all four head copies, and /terms repeated it. Corrected to the file.

tiers.js gives Pro 10 reads per link, Business 25 and Enterprise 100.
/privacy stated burn-on-read as a property of every plan, and left
Business out of the expiry list. So did /terms.

The relay and the admin call two external hosts. /dpa, which customers
sign, listed one of them: Mollie was missing from the sub-processor
table while /privacy named it. Added, and Bunny.net (DNS, Slovenia) put
on the /privacy list the rest of the site already names.

A signing envelope is kept 30 days by default and 365 at most, and a
delivery receipt for 15 minutes. /privacy said "until its expiry" for
the first and nothing for the second.

ct-hash.js is SHA3-256 throughout. /dpa said so, /privacy said SHA-256.

The browser-storage list named ps_free_uses and pm_docs_key, neither of
which exists anywhere in the repository, and described a 10 a day limit
that is 10 a month. It did not name the five keys the frontend writes.

The IP-logging row on /security described the hosted configuration only.
The self-host configuration in this repository logs the client address.

README named Frankfurt in the table that claims EU jurisdiction; the DPA
and /privacy name Nuremberg.

Also: the real_ip comment in nginx-paramant-live.conf called Bunny the
edge. The A record points at this machine, so it is DNS only.

Rows 23 to 30 in docs/site-claims.md, all pinned in
tests/site-claims.test.mjs and each verified by sabotaging its source.
… DPA scope

Four things the reviewer caught, and the tests that hold each of them.

LICENSE grants production use up to five active API keys and one self-hosted
deployment, commercial use included. Nothing said so. deploy/LICENSE shipped no
Additional Use Grant at all while its Terms referred to one "above"; the box on
/license granted non-commercial use only, under a different Licensor and a
different Licensed Work; /terms repeated the narrow version twice. Block 23 now
compares the Additional Use Grant, the Licensor and the Licensed Work word for
word across LICENSE, deploy/LICENSE and the box, and forbids any page from
selling the licence as non-commercial only.

Mollie is a real sub-processor: both billing routes are wired and createPayment
is unconditional, so the DPA row stays. What the row claimed it sends was wrong
both ways. The payload is the amount, a description and metadata of accountId,
product, plan and interval, and no e-mail: the only path that would send one is
ensureCustomer, skipped while BILLING_MODE is unset. /privacy and /terms still
said billing was not live and plans were arranged by hand, two versions behind
the code. Block 31 reads the payload, calls billingStance() for the stance, and
pins all three pages to both.

POST /v2/sign-dpa is public and checks a name, an organisation, an e-mail and a
rate limit. Four pages described four different gates; "applies to all plans"
was the one that matched. Block 32 pins the endpoint's lack of a gate to that
sentence, and /audit-log-export no longer claims the relay processes no personal
data, which was the opposite of the position the whole of /dpa takes.

Three smaller ones. Block 33 makes the auditd and CIS figures on /dpa equal to
the ones SECURITY.md records, without claiming either proves the host is in that
state. Block 34 requires every page carrying the "Not eIDAS-qualified"
disclaimer to name the level the signature does reach; /sign and /co-sign only
said what it is not. Block 35 replaces "processed only transiently" on /privacy
with the two logs that really hold an address: three admin lines, one of them
with the account e-mail, in a container log rotated on volume, and the edge
access log that scripts/access-log-visitors.mjs reads. Block 26 now pins the
envelope retention on /dpa as well, in days rather than "until expiry".

Every new assertion was sabotaged in both directions, source and page.
/press and /architecture both said "No US entity in the chain" while the signed
/dpa table names Resend Inc. in the US under Standard Contractual Clauses, and
/dpa section 6 spells the transfer out. That is the site contradicting the
document a controller signs, on the one point where the answer is a jurisdiction
and not a nuance. Both sentences now say what is true: no US entity holds
ciphertext or a key, and the one American sub-processor sends transactional
email under SCCs.

Block 25 reads the US row out of the /dpa table and forbids the denial on any
public page while that row stands. Sabotaged in both directions: putting the
sentence back turns it red, and so does moving the Resend row to the EU.
All four copies on /license (description, og, twitter, JSON-LD) sold the licence
as free for personal use. The Additional Use Grant gives more than that: five
active API keys and one self-hosted deployment in production, commercial use
included. seo-contract pins the four to each other, so they were consistently
understating the same thing. Rewritten to name the grant, inside the 165
character budget seo-contract enforces.
The previous commit took two em-dashes out of the Additional Use Grant in
LICENSE so the style guard would pass. That is the wrong way round. LICENSE
decides what anyone may do with this software, and rewriting it to satisfy a
punctuation rule is a decision for the licensor, not for a shell script in
scripts/. Both dashes are back, exactly as origin/main has them, deploy/LICENSE
is byte identical to the root again, and the box on /license reproduces the
grant with them.

The guard gets the exception instead, and only for rule 1. LICENSE and
deploy/LICENSE are exempt on path. On /license the exemption is the region
between LICENCE-VERBATIM-START and LICENCE-VERBATIM-END, applied per line
number: a dash added anywhere else on that page still fails. Emoji and AI
attribution stay forbidden everywhere, the licence text included, and a commit
message with a dash is still refused even when it edits the licence.

Block 23 is untouched and still compares the Additional Use Grant, the Licensor
and the Licensed Work word for word across the three copies, so the exemption
buys freedom from the punctuation rule and no freedom at all from the test.
This commit is its own proof: it adds both dashes and the guard passes.
The first version matched a whole template literal with a backtick character
class. It found three lines on this machine and none on the runner, so the
suite went red in CI with "admin/server.js now writes 0 log lines with a full
client IP" against a file that plainly writes three. A pin that is green where
it is cheap and red where it counts is worse than no pin.

A log call is one line in that file, so it now reads one line at a time: skip a
commented-out line, require the call, require the interpolation. No backtick
class and no brace escapes, so nothing is left for a regex engine to disagree
about. The two markers are built by concatenation for the same reason: the test
file must be able to name them without a template literal reading them as its
own.

Same two assertions, three lines and one of them carrying the account email,
and both sabotages still turn it red: a fourth line with the client IP, and the
pending-signup line losing the address.
… open

CI was red on this branch for a reason that had nothing to do with the runner.
The block asserted that admin/server.js writes three log lines with a full
client IP. It did when the block was written. #374 landed first and routed all
three through admin/lib/log-redact.js, so on the merge commit the count is zero
and the assertion was right to fail: /privacy was describing a system that no
longer exists.

The page now says what the code does. An address is truncated to its network
before it is written and an email keeps one character and its domain, so the
container log holds neither in full. The section is renamed accordingly and the
admin entry stands as contrast rather than as the finding.

The block keeps only what this pull request actually adds: the edge access log,
which no page described, pinned to scripts/access-log-visitors.mjs. The claim
about the admin lines belongs to row 9 and admin/test/log-redact.test.js, which
pin it at the source, and a second weaker copy here would only rot again. What
remains of that half is a guard: /privacy may not go back to describing raw
lines, and the masking it does describe has to still exist.

Five sabotages red in both directions: dropping the section, restoring "only
transiently", pointing the reader at another file, renaming maskIpForLog, and
putting the raw-lines sentence back.
Leftovers from the version of that section that had an admin half. The core
principle paragraph, the client-IP row in the processing table and the "what we
never do" bullet each pointed at "the logs named below" in the plural. One log
holds a full address now, the edge access log, and the page says one.
The audit trail. The row this branch wrote said the audit log was "capped by
volume, not by time". Both halves were wrong. admin/lib/audit.js sets a 400 day
default retention and trims by score as well as by rank, so there is an age
bound; and what it stores is not a client IP but its network part, 1.2.x.x for
IPv4 and the first two groups for IPv6. Understating a retention is not being
careful, it is being wrong in the direction that flatters us. Both figures and
the mask are now read off the file.

The norm mappings. /pricing said the three ship with Pro and Enterprise, and the
last round called the claim unbacked. Both were wrong. docs/ot-guide.md carries
an IEC 62443 requirement table and docs/dicom-guide.md a NEN 7510 table, both
served from frontend/docs/ where a Community account reads them for nothing. The
false half was never "these exist"; it was the paid-tier framing. eIDAS is the
one with no mapping document, and the page says so. Block 36 requires the
sections in both copies, forbids a plan in front of them, and goes red if an
eIDAS mapping appears so the sentence changes with it.

The timer. /press said blobs are "destroyed on download, not on a timer" while
every tier in tiers.js carries a view_ttl_ms. Saying a thing exists where it
does not is one mistake; denying a thing that does is another, and this one fits
in a sweep. No page may make the denial, and the ceilings /press names are read
off tiers.js so a changed TTL moves the page too.

The licence box. It called itself a word for word copy while missing the MariaDB
trademark clause and the whole Covenants section and carrying a copyright line
LICENSE does not have. The field pins could not see any of that: gutting a
shared paragraph stayed green. The box is the whole file now, and block 23
compares the whole box to it with whitespace normalised, on top of the field
pins.

Eleven sabotages, source side and page side for each new assertion.
@Apolloccrypt
Apolloccrypt force-pushed the fix/legal-texts-match-practice branch from 749bc39 to 0a1d8ae Compare September 3, 2026 01:18
…ooked at

#382 took the signed DPA out of the Enterprise item on the homepage. This is
what stops it coming back, and it reads both shapes a tier list takes here: the
one-line form on /index, and the tier-name heading with its own list on /pricing
and /parasend. The first version scanned list items only and walked straight
past the card, which the sabotage caught: putting the bullet back on /pricing
stayed green.

Reading the card found /parasend saying the same untrue thing, in a list nobody
had looked at during three rounds on this branch. Same fix as /pricing: custom
terms are what Enterprise negotiates, the standard agreement is public and asks
nobody for a plan. The homepage sentence itself is pinned too, so the fix cannot
be deleted quietly.

The Enterprise card on /pricing also listed the norm documentation flat, one
screen above the paragraph in this same pull request saying a Community account
reads it for nothing. The bullet says which it is now. The equivalent line on
/parasend already carries its caveat and is pinned verbatim by
relay/test/pricing-page.test.js, so it stays as it is.

Sabotages: the DPA bullet back on /index, /pricing and /parasend, the homepage
sentence deleted, and the tier headings renamed to check the sweep is not
counting nothing.
@Apolloccrypt
Apolloccrypt merged commit 84167ab into main Sep 3, 2026
13 checks passed
@Apolloccrypt
Apolloccrypt deleted the fix/legal-texts-match-practice branch September 5, 2026 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants